fellow cpu code

This commit is contained in:
Kelvin Sherlock 2013-02-05 23:11:41 -05:00
parent f97b6eae24
commit ea246894be
23 changed files with 98331 additions and 0 deletions

458
cpu/CpuIntegration.c Normal file
View File

@ -0,0 +1,458 @@
/* @(#) $Id: CpuIntegration.c,v 1.10 2013/01/08 19:17:33 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* Initialization of 68000 core */
/* Integrates the 68k emulation with custom chips */
/* */
/* Author: Petter Schau */
/* */
/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software Foundation, */
/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*=========================================================================*/
#include "defs.h"
#include "fellow.h"
#include "fmem.h"
#include "CpuModule.h"
#include "CpuIntegration.h"
#include "CpuModule_Internal.h"
#include "bus.h"
#include "fileops.h"
jmp_buf cpu_integration_exception_buffer;
/* custom chip intreq bit-number to irq-level */
static ULO cpu_integration_int_to_level[16] = {1,1,1,2, 3,3,3,4, 4,4,4,5, 5,6,6,7};
static ULO cpu_integration_irq_source;
/* Cycles spent by chips (Blitter) as a result of an instruction */
static ULO cpu_integration_chip_cycles;
static ULO cpu_integration_chip_slowdown;
/*===========================================================================*/
/* CPU properties */
/*===========================================================================*/
ULO cpu_integration_speed; // The speed as expressed in the fellow configuration settings
ULO cpu_integration_speed_multiplier; // The cycle multiplier used to adjust the cpu-speed, calculated from cpu_integration_speed
cpu_integration_models cpu_integration_model; // The cpu model as expressed in the fellow configuration settings
/*===========================================================================*/
/* CPU properties */
/*===========================================================================*/
void cpuIntegrationSetSpeed(ULO speed)
{
cpu_integration_speed = speed;
}
ULO cpuIntegrationGetSpeed(void)
{
return cpu_integration_speed;
}
static void cpuIntegrationSetSpeedMultiplier(ULO multiplier)
{
cpu_integration_speed_multiplier = multiplier;
}
static ULO cpuIntegrationGetSpeedMultiplier(void)
{
return cpu_integration_speed_multiplier;
}
static void cpuIntegrationCalculateMultiplier(void)
{
ULO multiplier = 12;
switch (cpuGetModelMajor())
{
case 0:
multiplier = 12;
break;
case 1:
multiplier = 12;
break;
case 2:
multiplier = 11;
break;
case 3:
multiplier = 11;
break;
}
if (cpuIntegrationGetSpeed() >= 8) cpuIntegrationSetSpeedMultiplier(multiplier);
else if (cpuIntegrationGetSpeed() >= 4) cpuIntegrationSetSpeedMultiplier(multiplier - 1);
else if (cpuIntegrationGetSpeed() >= 2) cpuIntegrationSetSpeedMultiplier(multiplier - 2);
else if (cpuIntegrationGetSpeed() >= 1) cpuIntegrationSetSpeedMultiplier(multiplier - 3);
else cpuIntegrationSetSpeedMultiplier(multiplier - 4);
}
BOOLE cpuIntegrationSetModel(cpu_integration_models model)
{
BOOLE needreset = (cpu_integration_model != model);
cpu_integration_model = model;
switch (cpu_integration_model)
{
case M68000: cpuSetModel(0, 0); break;
case M68010: cpuSetModel(1, 0); break;
case M68020: cpuSetModel(2, 0); break;
case M68030: cpuSetModel(3, 0); break;
case M68EC20: cpuSetModel(2, 1); break;
case M68EC30: cpuSetModel(3, 1); break;
}
return needreset;
}
cpu_integration_models cpuIntegrationGetModel(void)
{
return cpu_integration_model;
}
void cpuIntegrationSetChipCycles(ULO chip_cycles)
{
cpu_integration_chip_cycles = chip_cycles;
}
ULO cpuIntegrationGetChipCycles(void)
{
return cpu_integration_chip_cycles;
}
void cpuIntegrationSetChipSlowdown(ULO chip_slowdown)
{
cpu_integration_chip_slowdown = chip_slowdown;
}
ULO cpuIntegrationGetChipSlowdown(void)
{
return cpu_integration_chip_slowdown;
}
ULO cpuIntegrationGetChipIrqToIntLevel(ULO chip_irq)
{
return cpu_integration_int_to_level[chip_irq];
}
void cpuIntegrationSetIrqSource(ULO irq_source)
{
cpu_integration_irq_source = irq_source;
}
ULO cpuIntegrationGetIrqSource(void)
{
return cpu_integration_irq_source;
}
/*=====================================================
Checking for waiting interrupts
=====================================================*/
static BOOLE cpuIntegrationCheckPendingInterruptsFunc(void)
{
ULO current_cpu_level = (cpuGetSR() >> 8) & 7;
BOOLE chip_irqs_enabled = !!(intena & 0x4000);
if (chip_irqs_enabled)
{
LON highest_chip_irq;
ULO chip_irqs = intreq & intena;
if (chip_irqs == 0) return FALSE;
for (highest_chip_irq = 13; highest_chip_irq >= 0; highest_chip_irq--)
{
if (chip_irqs & (1 << highest_chip_irq))
{
// Found a chip-irq that is both flagged and enabled.
ULO highest_chip_level = cpuIntegrationGetChipIrqToIntLevel(highest_chip_irq);
if (highest_chip_level > current_cpu_level)
{
cpuSetIrqLevel(highest_chip_level);
cpuSetIrqAddress(memoryReadLong(cpuGetVbr() + 0x60 + highest_chip_level*4));
cpuIntegrationSetIrqSource(highest_chip_irq);
if (cpuGetStop())
{
cpuSetStop(FALSE);
cpuEvent.cycle = bus.cycle;
}
return TRUE;
}
}
}
}
return FALSE;
}
void cpuIntegrationCheckPendingInterrupts(void)
{
cpuCheckPendingInterrupts();
}
/*=========================================*/
/* Exception mid-instruction exit function */
/*=========================================*/
void cpuIntegrationMidInstructionExceptionFunc(void)
{
longjmp(cpu_integration_exception_buffer, -1);
}
/*===================================================*/
/* Handles reset exception event from the cpu-module */
/*===================================================*/
void cpuIntegrationResetExceptionFunc(void)
{
fellowSoftReset();
}
/*=========*/
/* Logging */
/*=========*/
#ifdef CPU_INSTRUCTION_LOGGING
FILE *CPUINSTRUCTIONLOG;
int cpu_disable_instruction_log = TRUE;
void cpuInstructionLogOpen(void)
{
if (CPUINSTRUCTIONLOG == NULL)
{
char filename[MAX_PATH];
fileopsGetGenericFileName(filename, "WinFellow", "cpuinstructions.log");
CPUINSTRUCTIONLOG = fopen(filename, "w");
}
}
void cpuIntegrationPrintBusCycle(void)
{
fprintf(CPUINSTRUCTIONLOG, "%d:%.5d ", bus.frame_no, bus.cycle);
}
void cpuIntegrationInstructionLogging(void)
{
char saddress[256], sdata[256], sinstruction[256], soperands[256];
if (cpu_disable_instruction_log) return;
cpuInstructionLogOpen();
/*
fprintf(CPUINSTRUCTIONLOG,
"D0:%.8X D1:%.8X D2:%.8X D3:%.8X D4:%.8X D5:%.8X D6:%.8X D7:%.8X\n",
cpuGetDReg(0),
cpuGetDReg(1),
cpuGetDReg(2),
cpuGetDReg(3),
cpuGetDReg(4),
cpuGetDReg(5),
cpuGetDReg(6),
cpuGetDReg(7));
fprintf(CPUINSTRUCTIONLOG,
"A0:%.8X A1:%.8X A2:%.8X A3:%.8X A4:%.8X A5:%.8X A6:%.8X A7:%.8X\n",
cpuGetAReg(0),
cpuGetAReg(1),
cpuGetAReg(2),
cpuGetAReg(3),
cpuGetAReg(4),
cpuGetAReg(5),
cpuGetAReg(6),
cpuGetAReg(7));
*/
saddress[0] = '\0';
sdata[0] = '\0';
sinstruction[0] = '\0';
soperands[0] = '\0';
cpuDisOpcode(cpuGetPC(), saddress, sdata, sinstruction, soperands);
fprintf(CPUINSTRUCTIONLOG, "SSP:%.6X USP:%.6X SP:%.4X %s %s\t%s\t%s\n", cpuGetSspDirect(), cpuGetUspDirect(), cpuGetSR(), saddress, sdata, sinstruction, soperands);
}
void cpuIntegrationExceptionLogging(STR *description, ULO original_pc, UWO opcode)
{
if (cpu_disable_instruction_log) return;
cpuInstructionLogOpen();
cpuIntegrationPrintBusCycle();
fprintf(CPUINSTRUCTIONLOG, "%s for opcode %.4X at PC %.8X from PC %.8X\n", description, opcode, original_pc, cpuGetPC());
}
STR *cpuIntegrationGetInterruptName(ULO chip_irq_no)
{
switch (chip_irq_no)
{
case 0: return "TBE: Output buffer of the serial port is empty.";
case 1: return "DSKBLK: Disk DMA transfer ended.";
case 2: return "SOFT: Software interrupt.";
case 3: return "PORTS: From CIA-A or expansion port.";
case 4: return "COPER: Copper interrupt.";
case 5: return "VERTB: Start of vertical blank.";
case 6: return "BLIT: Blitter done.";
case 7: return "AUD0: Audio data on channel 0.";
case 8: return "AUD1: Audio data on channel 1.";
case 9: return "AUD2: Audio data on channel 2.";
case 10: return "AUD3: Audio data on channel 3.";
case 11: return "RBF: Input buffer of the serial port full.";
case 12: return "DSKSYN: Disk sync value recognized.";
case 13: return "EXTER: From CIA-B or expansion port.";
case 14: return "INTEN: BUG! Not an interrupt.";
case 15: return "NMI: BUG! Not an interrupt.";
}
return "Illegal interrupt source!";
}
void cpuIntegrationInterruptLogging(ULO level, ULO vector_address)
{
if (cpu_disable_instruction_log) return;
cpuInstructionLogOpen();
cpuIntegrationPrintBusCycle();
fprintf(CPUINSTRUCTIONLOG, "Irq %d to %.6X (%s)\n", level, vector_address, cpuIntegrationGetInterruptName(cpuIntegrationGetIrqSource()));
}
#endif
void cpuIntegrationExecuteInstructionEventHandler68000Fast(void)
{
ULO cycles;
cycles = cpuExecuteInstruction();
if (cpuGetStop())
{
cpuEvent.cycle = BUS_CYCLE_DISABLE;
}
else
{
cpuEvent.cycle += ((cycles*cpuIntegrationGetChipSlowdown())>>1) + cpuIntegrationGetChipCycles();
}
cpuIntegrationSetChipCycles(0);
}
void cpuIntegrationExecuteInstructionEventHandler68000General(void)
{
ULO cycles = 0;
ULO time_used = 0;
do
{
cycles = cpuExecuteInstruction();
cycles = cycles*cpuIntegrationGetChipSlowdown(); // Compensate for blitter time
time_used += (cpuIntegrationGetChipCycles()<<12) + (cycles<<cpuIntegrationGetSpeedMultiplier());
}
while (time_used < 8192 && !cpuGetStop());
if (cpuGetStop())
{
cpuEvent.cycle = BUS_CYCLE_DISABLE;
}
else
{
cpuEvent.cycle += (time_used>>12);
}
cpuIntegrationSetChipCycles(0);
}
void cpuIntegrationExecuteInstructionEventHandler68020(void)
{
ULO time_used = 0;
do
{
cpuExecuteInstruction();
time_used += (cpuIntegrationGetChipCycles()<<12) + (4<<cpuIntegrationGetSpeedMultiplier());
}
while (time_used < 8192 && !cpuGetStop());
if (cpuGetStop())
{
cpuEvent.cycle = BUS_CYCLE_DISABLE;
}
else
{
cpuEvent.cycle += (time_used>>12);
}
cpuIntegrationSetChipCycles(0);
}
void cpuIntegrationSetDefaultConfig(void)
{
cpuIntegrationSetModel(M68000);
cpuIntegrationSetChipCycles(0);
cpuIntegrationSetChipSlowdown(1);
cpuIntegrationSetSpeed(4);
cpuSetCheckPendingInterruptsFunc(cpuIntegrationCheckPendingInterruptsFunc);
cpuSetMidInstructionExceptionFunc(cpuIntegrationMidInstructionExceptionFunc);
cpuSetResetExceptionFunc(cpuIntegrationResetExceptionFunc);
#ifdef CPU_INSTRUCTION_LOGGING
cpuSetInstructionLoggingFunc(cpuIntegrationInstructionLogging);
cpuSetExceptionLoggingFunc(cpuIntegrationExceptionLogging);
cpuSetInterruptLoggingFunc(cpuIntegrationInterruptLogging);
#endif
}
/*=========================*/
/* Fellow lifecycle events */
/*=========================*/
void cpuIntegrationSaveState(FILE *F)
{
cpuSaveState(F);
fwrite(&cpu_integration_chip_slowdown, sizeof(cpu_integration_chip_slowdown), 1, F);
// Everything else is configuration options which will be set when the associated config-file is loaded.
}
void cpuIntegrationLoadState(FILE *F)
{
cpuLoadState(F);
fread(&cpu_integration_chip_slowdown, sizeof(cpu_integration_chip_slowdown), 1, F);
// Everything else is configuration options which will be set when the associated config-file is loaded.
}
void cpuIntegrationEmulationStart(void)
{
cpuIntegrationCalculateMultiplier();
}
void cpuIntegrationEmulationStop(void)
{
}
void cpuIntegrationHardReset(void)
{
cpuIntegrationSetChipCycles(0);
cpuIntegrationSetChipSlowdown(1);
cpuSetInitialPC(memoryInitialPC());
cpuSetInitialSP(memoryInitialSP());
cpuHardReset();
}
void cpuIntegrationStartup(void)
{
cpuStartup();
cpuIntegrationSetDefaultConfig();
cpuCreateMulTimeTables();
}
void cpuIntegrationShutdown(void)
{
cpuProfileWrite();
}

44
cpu/CpuIntegration.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef CpuIntegration_H
#define CpuIntegration_H
typedef enum {
M68000 = 0,
M68010 = 1,
M68020 = 2,
M68030 = 3,
M68EC30 = 4,
M68EC20 = 9
} cpu_integration_models;
extern void cpuIntegrationSetUpInterruptEventHandler(void);
extern void cpuIntegrationExecuteInstructionEventHandler68000Fast(void);
extern void cpuIntegrationExecuteInstructionEventHandler68000General(void);
extern void cpuIntegrationExecuteInstructionEventHandler68020(void);
extern void cpuIntegrationCheckPendingInterrupts(void);
extern ULO cpuIntegrationDisOpcode(ULO disasm_pc, STR *saddress, STR *sdata, STR *sinstruction, STR *soperands);
extern BOOLE cpuIntegrationSetModel(cpu_integration_models model);
extern cpu_integration_models cpuIntegrationGetModel(void);
extern ULO cpuIntegrationGetModelMajor(void);
extern ULO cpuIntegrationGetPC(void);
extern ULO cpuIntegrationGetInstructionTime(void);
extern void cpuIntegrationSetSpeed(ULO speed);
extern ULO cpuIntegrationGetSpeed(void);
extern void cpuIntegrationSetChipCycles(ULO chip_cycles);
extern ULO cpuIntegrationGetChipCycles(void);
extern void cpuIntegrationSetChipSlowdown(ULO chip_slowdown);
extern ULO cpuIntegrationGetChipSlowdown(void);
extern jmp_buf cpu_integration_exception_buffer;
// Fellow limecycle events
extern void cpuIntegrationSaveState(FILE *F);
extern void cpuIntegrationLoadState(FILE *F);
extern void cpuIntegrationEmulationStart(void);
extern void cpuIntegrationEmulationStop(void);
extern void cpuIntegrationHardReset(void);
extern void cpuIntegrationStartup(void);
extern void cpuIntegrationShutdown(void);
#endif

80
cpu/CpuModule.c Normal file
View File

@ -0,0 +1,80 @@
/* @(#) $Id: CpuModule.c,v 1.7 2012/08/12 16:51:02 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* Initialization of 68000 core */
/* */
/* Author: Petter Schau */
/* */
/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software Foundation, */
/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*=========================================================================*/
#include "defs.h"
#include "CpuModule.h"
#include "fellow.h"
#include "fmem.h"
#include "CpuModule_Internal.h"
void cpuClearEverything(void)
{
ULO i,j;
for (j = 0; j < 2; j++)
for (i = 0; i < 8; i++)
cpuSetReg(j, i, 0);
cpuSetUspDirect(0);
cpuSetSspDirect(0);
cpuSetMspDirect(0);
cpuSetPC(0);
cpuClearPrefetch();
cpuSetVbr(0);
cpuSetSR(0);
cpuSetCacr(0);
cpuSetCaar(0);
cpuSetSfc(0);
cpuSetDfc(0);
cpuSetIrqLevel(0);
cpuSetIrqAddress(0);
cpuSetStop(FALSE);
cpuSetInstructionTime(0);
cpuSetOriginalPC(0);
cpuSetInitialPC(0);
cpuSetInitialSP(0);
cpuSetModel(0, 0); // Also sets model-mask
cpuSetCheckPendingInterruptsFunc(NULL);
#ifdef CPU_INSTRUCTION_LOGGING
cpuSetCurrentOpcode(0);
cpuSetInstructionLoggingFunc(NULL);
cpuSetExceptionLoggingFunc(NULL);
cpuSetInterruptLoggingFunc(NULL);
#endif
cpuSetMidInstructionExceptionFunc(NULL);
cpuSetResetExceptionFunc(NULL);
}
void cpuHardReset(void)
{
cpuThrowResetException();
cpuSetRaiseInterrupt(FALSE);
}
void cpuStartup(void)
{
cpuClearEverything();
}

93
cpu/CpuModule.h Normal file
View File

@ -0,0 +1,93 @@
#ifndef CpuModule_H
#define CpuModule_H
// This header file defines the internal interfaces of the CPU module.
#define CPU_INSTRUCTION_LOGGING
// Function to check if there are any external interrupt sources wanting to issue interrupts
typedef BOOLE (*cpuCheckPendingInterruptsFunc)(void);
extern void cpuSetCheckPendingInterruptsFunc(cpuCheckPendingInterruptsFunc func);
extern void cpuCheckPendingInterrupts(void);
extern void cpuSetUpInterrupt(void);
extern void cpuInitializeFromNewPC(ULO new_pc);
// Logging interface
#ifdef CPU_INSTRUCTION_LOGGING
typedef void (*cpuInstructionLoggingFunc)(void);
extern void cpuSetInstructionLoggingFunc(cpuInstructionLoggingFunc func);
typedef void (*cpuExceptionLoggingFunc)(STR *description, ULO original_pc, UWO opcode);
extern void cpuSetExceptionLoggingFunc(cpuExceptionLoggingFunc func);
typedef void (*cpuInterruptLoggingFunc)(ULO level, ULO vector_address);
extern void cpuSetInterruptLoggingFunc(cpuInterruptLoggingFunc func);
#endif
// CPU register and control properties
extern void cpuSetPC(ULO pc);
extern ULO cpuGetPC(void);
extern void cpuSetReg(ULO da, ULO i, ULO value);
extern ULO cpuGetReg(ULO da, ULO i);
extern void cpuSetDReg(ULO i, ULO value);
extern ULO cpuGetDReg(ULO i);
extern void cpuSetAReg(ULO i, ULO value);
extern ULO cpuGetAReg(ULO i);
extern void cpuSetSR(ULO sr);
extern ULO cpuGetSR(void);
extern void cpuSetUspDirect(ULO usp);
extern ULO cpuGetUspDirect(void);
extern ULO cpuGetUspAutoMap(void);
extern void cpuSetMspDirect(ULO msp);
extern ULO cpuGetMspDirect(void);
extern void cpuSetSspDirect(ULO ssp);
extern ULO cpuGetSspDirect(void);
extern ULO cpuGetSspAutoMap(void);
extern ULO cpuGetVbr(void);
extern void cpuSetStop(BOOLE stop);
extern BOOLE cpuGetStop(void);
extern void cpuSetInitialPC(ULO pc);
extern ULO cpuGetInitialPC(void);
extern void cpuSetInitialSP(ULO sp);
extern ULO cpuGetInitialSP(void);
extern ULO cpuGetInstructionTime(void);
extern void cpuSetIrqLevel(ULO irq_level);
extern ULO cpuGetIrqLevel(void);
extern void cpuSetIrqAddress(ULO irq_address);
extern ULO cpuGetIrqAddress(void);
extern ULO cpuExecuteInstruction(void);
extern ULO cpuDisOpcode(ULO disasm_pc, STR *saddress, STR *sdata, STR *sinstruction, STR *soperands);
extern void cpuSaveState(FILE *F);
extern void cpuLoadState(FILE *F);
extern void cpuHardReset(void);
extern void cpuStartup(void);
typedef void (*cpuMidInstructionExceptionFunc)(void);
extern void cpuSetMidInstructionExceptionFunc(cpuMidInstructionExceptionFunc func);
extern void cpuThrowAddressErrorException(void);
typedef void (*cpuResetExceptionFunc)(void);
extern void cpuSetResetExceptionFunc(cpuResetExceptionFunc func);
// Configuration settings
extern void cpuSetModel(ULO major, ULO minor);
extern ULO cpuGetModelMajor(void);
extern ULO cpuGetModelMinor(void);
#endif

12233
cpu/CpuModule_Code.h Normal file

File diff suppressed because it is too large Load Diff

69648
cpu/CpuModule_Data.h Normal file

File diff suppressed because it is too large Load Diff

1685
cpu/CpuModule_Decl.h Normal file

File diff suppressed because it is too large Load Diff

1764
cpu/CpuModule_Disassembler.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,97 @@
#ifndef CPUMODULE_DISASSEMBLER_H
#define CPUMODULE_DISASSEMBLER_H
extern ULO cpuDisOpcode(ULO disasm_pc, STR *saddress, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisIllegal(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAbcd(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAdd(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAdda(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAddi(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAddq(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAddx(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAnd(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAndi(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisAsx(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisBcc(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisBt(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisChk(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisClr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisCmp(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisCmpa(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisCmpi(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisCmpm(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisDBcc(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisDivs(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisDivu(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisEor(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisEori(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisExg(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisExt(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisJmp(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisJsr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisLea(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisLink(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisLsx(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMove(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoveToCcr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoveToSr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoveFromSr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoveUsp(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMovea(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMovem(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMovep(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoveq(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMuls(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMulu(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisNbcd(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisNeg(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisNegx(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisNop(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisNot(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisOr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisOri(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisPea(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisReset(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRox(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRoxx(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRte(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRtr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRts(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSbcd(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisScc(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisStop(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSub(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSuba(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSubi(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSubq(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSubx(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisSwap(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisTas(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisTrap(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisTrapv(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisTst(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisUnlk(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisBkpt(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisBf(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisCas(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisChkl(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisChk2(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisDivl(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisExtb(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisLinkl(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoveFromCcr(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMovec(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMoves(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisMull(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisPack(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisPflush030(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisPflush040(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisPtest040(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRtd(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisTrapcc(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisUnpk(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisCallm(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
extern ULO cpuDisRtm(ULO prc, ULO opc, STR *sdata, STR *sinstruction, STR *soperands);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,194 @@
/* @(#) $Id: CpuModule_EffectiveAddress.c,v 1.3 2012/07/15 22:20:35 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* CPU 68k effective address calculation functions */
/* */
/* Author: Petter Schau */
/* */
/* */
/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software Foundation, */
/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*=========================================================================*/
#include "defs.h"
#include "fellow.h"
#include "fmem.h"
#include "CpuModule.h"
#include "CpuModule_Internal.h"
/* Calculates EA for (Ax). */
ULO cpuEA02(ULO regno)
{
return cpuGetAReg(regno);
}
/* Calculates EA for (Ax)+ */
ULO cpuEA03(ULO regno, ULO size)
{
ULO tmp = cpuGetAReg(regno);
if (regno == 7 && size == 1) size++;
cpuSetAReg(regno, tmp + size);
return tmp;
}
/* Calculates EA for -(Ax) */
ULO cpuEA04(ULO regno, ULO size)
{
if (regno == 7 && size == 1) size++;
cpuSetAReg(regno, cpuGetAReg(regno) - size);
return cpuGetAReg(regno);
}
/* Calculates EA for disp16(Ax) */
ULO cpuEA05(ULO regno)
{
return cpuGetAReg(regno) + cpuGetNextWordSignExt();
}
/* Calculates EA for disp8(Ax,Ri.size) with 68020 extended modes. */
static ULO cpuEA06Ext(UWO ext, ULO base_reg_value, ULO index_value)
{
ULO base_displacement;
ULO outer_displacement;
BOOLE index_register_suppressed = (ext & 0x0040);
BOOLE base_register_suppressed = (ext & 0x0080);
ULO base_displacement_size = (ext >> 4) & 3;
ULO memory_indirect_action = (ext & 7);
if (memory_indirect_action == 4
|| (memory_indirect_action > 4 && index_register_suppressed))
{
cpuThrowIllegalInstructionException(TRUE); /* Illegal instruction */
// Never returns
}
if (index_register_suppressed)
{
index_value = 0;
}
if (base_register_suppressed)
{
base_reg_value = 0;
}
switch (base_displacement_size)
{
case 0: /* Reserved */
cpuThrowIllegalInstructionException(TRUE); /* Illegal instruction */
break;
case 1: /* Null base displacement */
base_displacement = 0;
break;
case 2: /* Word base displacement */
base_displacement = cpuGetNextWordSignExt();
break;
case 3: /* Long base displacement */
base_displacement = cpuGetNextLong();
break;
}
switch (memory_indirect_action)
{
case 0: /* No memory indirect action */
return base_reg_value + base_displacement + index_value;
case 1: /* Indirect preindexed with null outer displacement */
return memoryReadLong(base_reg_value + base_displacement + index_value);
case 2: /* Indirect preindexed with word outer displacement */
outer_displacement = cpuGetNextWordSignExt();
return memoryReadLong(base_reg_value + base_displacement + index_value) + outer_displacement;
case 3: /* Indirect preindexed with long outer displacement */
outer_displacement = cpuGetNextLong();
return memoryReadLong(base_reg_value + base_displacement + index_value) + outer_displacement;
case 5: /* Indirect postindexed with null outer displacement, reserved for index register suppressed */
return memoryReadLong(base_reg_value + base_displacement) + index_value;
case 6: /* Indirect postindexed with word outer displacement, reserved for index register suppressed */
outer_displacement = cpuGetNextWordSignExt();
return memoryReadLong(base_reg_value + base_displacement) + index_value + outer_displacement;
case 7: /* Indirect postindexed with long outer displacement, reserved for index register suppressed */
outer_displacement = cpuGetNextLong();
return memoryReadLong(base_reg_value + base_displacement) + index_value + outer_displacement;
}
return 0; /* Should never come here. */
}
/* Calculates EA for disp8(Ax,Ri.size), calls cpuEA06Ext() for 68020 extended modes. */
ULO cpuEA06(ULO regno)
{
ULO reg_value = cpuGetAReg(regno);
UWO ext = cpuGetNextWord();
ULO index_value = cpuGetReg(ext >> 15, (ext >> 12) & 7);
if (!(ext & 0x0800))
{
index_value = cpuSignExtWordToLong((UWO)index_value);
}
if (cpuGetModelMajor() >= 2)
{
index_value = index_value << ((ext >> 9) & 3); /* Scaling index value */
if (ext & 0x0100) /* Full extension word */
{
return cpuEA06Ext(ext, reg_value, index_value);
}
}
return reg_value + index_value + cpuSignExtByteToLong((UBY)ext);
}
/* Calculates EA for xxxx.W */
ULO cpuEA70(void)
{
return cpuGetNextWordSignExt();
}
/* Calculates EA for xxxxxxxx.L */
ULO cpuEA71(void)
{
return cpuGetNextLong();
}
/// <summary>
/// Calculates EA for disp16(PC)
/// </summary>
/// <returns>Address</returns>
ULO cpuEA72(void)
{
ULO pc_tmp = cpuGetPC();
return pc_tmp + cpuGetNextWordSignExt();
}
/// <summary>
/// Calculates EA for disp8(PC,Ri.size). Calls cpuEA06Ext() to calculate extended 68020 modes.
/// </summary>
/// <returns>Address</returns>
ULO cpuEA73(void)
{
ULO reg_value = cpuGetPC();
UWO ext = cpuGetNextWord();
ULO index_value = cpuGetReg(ext >> 15, (ext >> 12) & 0x7);
if (!(ext & 0x0800))
{
index_value = cpuSignExtWordToLong((UWO)index_value);
}
if (cpuGetModelMajor() >= 2)
{
index_value = index_value << ((ext >> 9) & 0x3); // Scaling index value
if (ext & 0x0100) // Full extension word
{
return cpuEA06Ext(ext, reg_value, index_value);
}
}
return reg_value + index_value + cpuSignExtByteToLong((UBY)ext);
}

266
cpu/CpuModule_Exceptions.c Normal file
View File

@ -0,0 +1,266 @@
/* @(#) $Id: CpuModule_Exceptions.c,v 1.5 2012/08/12 16:51:02 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* CPU 68k exception handling functions */
/* */
/* Author: Petter Schau */
/* */
/* */
/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software Foundation, */
/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*=========================================================================*/
#include "defs.h"
#include "fellow.h"
#include "fmem.h"
#include "CpuModule.h"
#include "CpuModule_Internal.h"
/* Function for exiting from mid-instruction exceptions */
static cpuMidInstructionExceptionFunc cpu_mid_instruction_exception_func;
static void cpuCallMidInstructionExceptionFunc(void)
{
cpu_mid_instruction_exception_func();
}
void cpuSetMidInstructionExceptionFunc(cpuMidInstructionExceptionFunc func)
{
cpu_mid_instruction_exception_func = func;
}
/* Function for notifying the emulator about a reset */
static cpuResetExceptionFunc cpu_reset_exception_func;
void cpuCallResetExceptionFunc(void)
{
cpu_reset_exception_func();
}
void cpuSetResetExceptionFunc(cpuResetExceptionFunc func)
{
cpu_reset_exception_func = func;
}
static STR *cpuGetExceptionName(ULO vector_offset)
{
char *name;
if (vector_offset == 0x8)
name = "Exception: 2 - Access fault";
else if (vector_offset == 0xc)
name = "Exception: 3 - Address error";
else if (vector_offset == 0x10)
name = "Exception: 4 - Illegal Instruction";
else if (vector_offset == 0x14)
name = "Exception: 5 - Integer division by zero";
else if (vector_offset == 0x18)
name = "Exception: 6 - CHK, CHK2";
else if (vector_offset == 0x1c)
name = "Exception: 7 - FTRAPcc, TRAPcc, TRAPV";
else if (vector_offset == 0x20)
name = "Exception: 8 - Privilege Violation";
else if (vector_offset == 0x24)
name = "Exception: 9 - Trace";
else if (vector_offset == 0x28)
name = "Exception: 10 - A-Line";
else if (vector_offset == 0x2c)
name = "Exception: 11 - F-Line";
else if (vector_offset == 0x38)
name = "Exception: 14 - Format error";
else if (vector_offset >= 0x80 && vector_offset <= 0xbc)
name = "Exception: TRAP";
else
name = "Exception: Unknown";
return name;
}
/*===============================================
Sets up an exception
===============================================*/
void cpuThrowException(ULO vector_offset, ULO pc, BOOLE executejmp)
{
ULO vector_address;
#ifdef CPU_INSTRUCTION_LOGGING
cpuCallExceptionLoggingFunc(cpuGetExceptionName(vector_offset), cpuGetOriginalPC(), cpuGetCurrentOpcode());
#endif
cpuActivateSSP();
cpuStackFrameGenerate((UWO) vector_offset, pc);
// read a memory position
vector_address = memoryReadLong(cpuGetVbr() + vector_offset);
if (cpuGetModelMajor() < 2 && vector_address & 0x1 && vector_offset == 0xc)
{
// Avoid endless loop that will crash the emulator.
// The (odd) address error exception vector contained an odd address.
cpuCallResetExceptionFunc();
cpuHardReset();
cpuSetInstructionTime(132);
}
else
{
// set supervisor modus
cpuSetSR(cpuGetSR() | 0x2000);
cpuSetSR(cpuGetSR() & 0x3fff);
// restart cpu, if needed
cpuSetStop(FALSE);
cpuInitializeFromNewPC(vector_address);
cpuSetInstructionTime(40);
}
// If the exception happened mid-instruction...
if (executejmp)
{
cpuCallMidInstructionExceptionFunc(); // Supposed to be doing setjmp/longjmp back to machine emulator code
}
}
void cpuThrowPrivilegeViolationException(void)
{
// The saved pc points to the instruction causing the violation
// (And the kickstart excpects pc in the stack frame to be the opcode PC.)
cpuThrowException(0x20, cpuGetOriginalPC(), FALSE);
}
void cpuThrowIllegalInstructionException(BOOLE executejmp)
{
// The saved pc points to the illegal instruction
cpuThrowException(0x10, cpuGetOriginalPC(), executejmp);
}
void cpuThrowALineException(void)
{
// The saved pc points to the a-line instruction
cpuThrowException(0x28, cpuGetOriginalPC(), FALSE);
}
void cpuThrowFLineException(void)
{
// The saved pc points to the f-line instruction
cpuThrowException(0x2c, cpuGetOriginalPC(), FALSE);
}
void cpuThrowTrapVException(void)
{
// The saved pc points to the next instruction, which is now in pc
cpuThrowException(0x1c, cpuGetPC(), FALSE);
}
void cpuThrowDivisionByZeroException(BOOLE executejmp)
{
// The saved pc points to the next instruction, which is now in pc
cpuThrowException(0x14, cpuGetPC(), executejmp);
}
void cpuThrowTrapException(ULO vector_no)
{
// The saved pc points to the next instruction, which is now in pc
cpuThrowException(0x80 + vector_no*4, cpuGetPC(), FALSE);
}
void cpuThrowChkException(void)
{
// The saved pc points to the next instruction, which is now in pc
cpuThrowException(0x18, cpuGetPC(), FALSE);
}
void cpuThrowTraceException(void)
{
// The saved pc points to the next instruction, which is now in pc
cpuThrowException(0x24, cpuGetPC(), FALSE);
}
void cpuThrowAddressErrorException(void)
{
cpuThrowException(0xc, cpuGetPC(), TRUE);
}
/*=================*/
/* Reset exception */
/*=================*/
static void cpuThrowResetException000(void)
{
cpuSetSR(cpuGetSR() & 0x271f); /* T = 0 */
cpuSetSR(cpuGetSR() | 0x2700); /* S = 1, ilvl = 7 */
cpuSetVbr(0);
cpuSetSspDirect(cpuGetInitialSP()); /* ssp = fake vector 0 */
cpuInitializeFromNewPC(cpuGetInitialPC()); /* pc = fake vector 1 */
}
static void cpuThrowResetException010(void)
{
cpuSetSR(cpuGetSR() & 0x271f); /* T = 0 */
cpuSetSR(cpuGetSR() | 0x2700); /* S = 1, ilvl = 7 */
cpuSetVbr(0);
cpuSetSspDirect(cpuGetInitialSP()); /* ssp = fake vector 0 */
cpuInitializeFromNewPC(cpuGetInitialPC()); /* pc = fake vector 1 */
}
static void cpuThrowResetException020(void)
{
cpuSetSR(cpuGetSR() & 0x271f); /* T1T0 = 0, M = 0 */
cpuSetSR(cpuGetSR() | 0x2700); /* S = 1, ilvl = 7 */
cpuSetVbr(0);
cpuSetCacr(0); /* E = 0, F = 0 */
cpuSetCaar(0);
/* Invalidate cache, we don't have one */
cpuSetSspDirect(cpuGetInitialSP()); /* ssp = fake vector 0 */
cpuInitializeFromNewPC(cpuGetInitialPC()); /* pc = fake vector 1 */
}
static void cpuThrowResetException030(void)
{
cpuSetSR(cpuGetSR() & 0x271f); /* T1T0 = 0, M = 0 */
cpuSetSR(cpuGetSR() | 0x2700); /* S = 1, ilvl = 7 */
cpuSetVbr(0);
cpuSetCacr(0); /* E = 0, F = 0 */
cpuSetCaar(0);
/* Invalidate cache, we don't have one */
cpuSetSspDirect(cpuGetInitialSP()); /* ssp = fake vector 0 */
cpuInitializeFromNewPC(cpuGetInitialPC()); /* pc = fake vector 1 */
}
/*============================*/
/* Performs a Reset exception */
/*============================*/
void cpuThrowResetException(void)
{
cpuSetStop(FALSE);
switch (cpuGetModelMajor())
{
case 0:
cpuThrowResetException000();
break;
case 1:
cpuThrowResetException010();
break;
case 2:
cpuThrowResetException020();
break;
case 3:
cpuThrowResetException030();
break;
}
}

578
cpu/CpuModule_Flags.c Normal file
View File

@ -0,0 +1,578 @@
/* @(#) $Id: CpuModule_Flags.c,v 1.3 2011/07/18 17:22:55 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* 68000 flag and condition code handling */
/* */
/* Author: Petter Schau */
/* */
/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software Foundation, */
/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*=========================================================================*/
#include "defs.h"
#include "fellow.h"
#include "CpuModule.h"
#include "CpuModule_Internal.h"
/// Sets the Z flag for bit operations
void cpuSetZFlagBitOpsB(UBY res)
{
ULO flags = cpu_sr & 0xfffb;
if (res == 0) flags |= 4;
cpu_sr = flags;
}
/// Sets the Z flag for bit operations
void cpuSetZFlagBitOpsL(ULO res)
{
ULO flags = cpu_sr & 0xfffb;
if (res == 0) flags |= 4;
cpu_sr = flags;
}
// rm,dm,sm
ULO cpu_xnvc_flag_add_table[2][2][2] = { 0,0x11,0x11,0x13,0xa,8,8,0x19};
/// <summary>
/// Calculate XNVC flags of an add operation.
/// </summary>
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
static ULO cpuMakeFlagXNVCAdd(BOOLE rm, BOOLE dm, BOOLE sm)
{
return cpu_xnvc_flag_add_table[rm][dm][sm];
}
// rm,dm,sm
ULO cpu_nvc_flag_add_table[2][2][2] = { 0,1,1,3,0xa,8,8,9};
/// <summary>
/// Calculate NVC flags of an add operation for instructions not setting X.
/// </summary>
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
static ULO cpuMakeFlagNVCAdd(BOOLE rm, BOOLE dm, BOOLE sm)
{
return cpu_nvc_flag_add_table[rm][dm][sm];
}
// rm,dm,sm
ULO cpu_xnvc_flag_sub_table[2][2][2] = { 0,0x11,2,0,0x19,0x1b,8,0x19};
/// <summary>
/// Calculate XNVC flags of a sub operation.
/// </summary>
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
static ULO cpuMakeFlagXNVCSub(BOOLE rm, BOOLE dm, BOOLE sm)
{
return cpu_xnvc_flag_sub_table[rm][dm][sm];
}
// rm,dm,sm
ULO cpu_nvc_flag_sub_table[2][2][2] = { 0,1,2,0,9,0xb,8,9};
/// <summary>
/// Calculate NVC flags of a sub operation for instructions not setting X.
/// </summary>
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
static ULO cpuMakeFlagNVCSub(BOOLE rm, BOOLE dm, BOOLE sm)
{
return cpu_nvc_flag_sub_table[rm][dm][sm];
}
/// <summary>
/// Set the X and C flags to the value f.
/// </summary>
/// <param name="f">The new state of the flags.</param>
void cpuSetFlagXC(BOOLE f)
{
cpu_sr = (cpu_sr & 0xffee) | ((f) ? 0x11 : 0);
}
/// <summary>
/// Set the C flag to the value f.
/// </summary>
/// <param name="f">The new state of the flag.</param>
void cpuSetFlagC(BOOLE f)
{
cpu_sr = (cpu_sr & 0xfffe) | ((f) ? 1 : 0);
}
/// <summary>
/// Set the V flag.
/// </summary>
/// <param name="f">The new state of the flag.</param>
void cpuSetFlagV(BOOLE f)
{
cpu_sr = (cpu_sr & 0xfffd) | ((f) ? 2 : 0);
}
/// <summary>
/// Clear the V flag.
/// </summary>
static void cpuClearFlagV(void)
{
cpu_sr = cpu_sr & 0xfffd;
}
/// <summary>
/// Get the V flag.
/// </summary>
BOOLE cpuGetFlagV(void)
{
return cpu_sr & 0x2;
}
/// <summary>
/// Set the N flag.
/// </summary>
/// <param name="f">The new state of the flag.</param>
void cpuSetFlagN(BOOLE f)
{
cpu_sr = (cpu_sr & 0xfff7) | ((f) ? 8 : 0);
}
/// <summary>
/// Set the Z flag.
/// </summary>
/// <param name="f">The new state of the flag.</param>
void cpuSetFlagZ(BOOLE f)
{
cpu_sr = (cpu_sr & 0xfffb) | ((f) ? 4 : 0);
}
/// <summary>
/// Clear the Z flag.
/// </summary>
static void cpuClearFlagZ(void)
{
cpu_sr = cpu_sr & 0xfffb;
}
/// <summary>
/// Get the Z flag.
/// </summary>
static BOOLE cpuGetFlagZ(void)
{
return cpu_sr & 0x4;
}
/// <summary>
/// Get the X flag.
/// </summary>
BOOLE cpuGetFlagX(void)
{
return cpu_sr & 0x10;
}
/// <summary>
/// Set the flags.
/// </summary>
void cpuSetFlags0100(void)
{
cpu_sr = (cpu_sr & 0xfff0) | 4;
}
/// <summary>
/// Clear V and C.
/// </summary>
static void cpuClearFlagsVC(void)
{
cpu_sr = cpu_sr & 0xfffc;
}
UWO cpuGetZFlagB(UBY res) {return (UWO)((res) ? 0 : 4);}
UWO cpuGetZFlagW(UWO res) {return (UWO)((res) ? 0 : 4);}
UWO cpuGetZFlagL(ULO res) {return (UWO)((res) ? 0 : 4);}
UWO cpuGetNFlagB(UBY res) {return (UWO)((res & 0x80) >> 4);}
UWO cpuGetNFlagW(UWO res) {return (UWO)((res & 0x8000) >> 12);}
UWO cpuGetNFlagL(ULO res) {return (UWO)((res & 0x80000000) >> 28);}
/// <summary>
/// Set the flags NZVC.
/// </summary>
/// <param name="z">The Z flag.</param>
/// <param name="n">The N flag.</param>
/// <param name="v">The V flag.</param>
/// <param name="c">The C flag.</param>
void cpuSetFlagsNZVC(BOOLE z, BOOLE n, BOOLE v, BOOLE c)
{
ULO flags = cpu_sr & 0xfff0;
if (n) flags |= 8;
else if (z) flags |= 4;
if (v) flags |= 2;
if (c) flags |= 1;
cpu_sr = flags;
}
/// <summary>
/// Set the flags VC.
/// </summary>
/// <param name="v">The V flag.</param>
/// <param name="c">The C flag.</param>
void cpuSetFlagsVC(BOOLE v, BOOLE c)
{
ULO flags = cpu_sr & 0xfffc;
if (v) flags |= 2;
if (c) flags |= 1;
cpu_sr = flags;
}
/// <summary>
/// Set the flags (all) of an add operation.
/// </summary>
/// <param name="z">The Z flag.</param>
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
void cpuSetFlagsAdd(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
{
ULO flags = cpu_sr & 0xffe0;
if (z) flags |= 4;
flags |= cpuMakeFlagXNVCAdd(rm, dm, sm);
cpu_sr = flags;
}
/// <summary>
/// Set the flags (all) of a sub operation.
/// </summary>
/// <param name="z">The Z flag.</param>
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
void cpuSetFlagsSub(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
{
ULO flags = cpu_sr & 0xffe0;
if (z) flags |= 4;
flags |= cpuMakeFlagXNVCSub(rm, dm, sm);
cpu_sr = flags;
}
/// <summary>
/// Set the flags (all) of an addx operation.
/// </summary>
/// <param name="z">The Z flag.</param>
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
void cpuSetFlagsAddX(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
{
ULO flags = cpu_sr & ((z) ? 0xffe4 : 0xffe0); // Clear z if result is non-zero
flags |= cpuMakeFlagXNVCAdd(rm, dm, sm);
cpu_sr = flags;
}
/// <summary>
/// Set the flags (all) of a subx operation.
/// </summary>
/// <param name="z">The Z flag.</param>
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
void cpuSetFlagsSubX(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
{
ULO flags = cpu_sr & ((z) ? 0xffe4 : 0xffe0); // Clear z if result is non-zero
flags |= cpuMakeFlagXNVCSub(rm, dm, sm);
cpu_sr = flags;
}
/// <summary>
/// Set the flags (all) of a neg operation.
/// </summary>
/// <param name="z">The Z flag.</param>
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
void cpuSetFlagsNeg(BOOLE z, BOOLE rm, BOOLE dm)
{
ULO flags = cpu_sr & 0xffe0;
if (z) flags |= 4;
else
{
flags |= 0x11; // set XC if result is non-zero
if (rm)
{
flags |= 8;
if (dm) flags |= 2; // V
}
}
cpu_sr = flags;
}
/// <summary>
/// Set the flags (all) of a negx operation.
/// </summary>
/// <param name="z">The Z flag.</param>
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
void cpuSetFlagsNegx(BOOLE z, BOOLE rm, BOOLE dm)
{
ULO flags = cpu_sr & ((z) ? 0xffe4 : 0xffe0); // Clear z if result is non-zero
if (dm || rm)
{
flags |= 0x11; // XC
if (rm)
{
flags |= 8;
if (dm) flags |= 2; // V
}
}
cpu_sr = flags;
}
/// <summary>
/// Set the flags (all) of a cmp operation. (Same as sub, but no X.)
/// </summary>
/// <param name="z">The Z flag.</param>
/// <param name="rm">The MSB of the result.</param>
/// <param name="dm">The MSB of the destination source.</param>
/// <param name="sm">The MSB of the source.</param>
void cpuSetFlagsCmp(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm)
{
ULO flags = cpu_sr & 0xfff0;
if (z) flags |= 4;
flags |= cpuMakeFlagNVCSub(rm, dm, sm);
cpu_sr = flags;
}
/// <summary>
/// Set the flags of a 0 shift count operation.
/// </summary>
/// <param name="z">The Z flag.</param>
/// <param name="rm">The MSB of the result.</param>
void cpuSetFlagsShiftZero(BOOLE z, BOOLE rm)
{
ULO flags = cpu_sr & 0xfff0; // Always clearing the VC flag
if (rm) flags |= 8;
else if (z) flags |= 4;
cpu_sr = flags;
}
/// <summary>
/// Set the flags of a shift operation.
/// </summary>
/// <param name="z">The Z flag.</param>
/// <param name="rm">The MSB of the result.</param>
/// <param name="c">The carry of the result.</param>
/// <param name="c">The overflow of the result.</param>
void cpuSetFlagsShift(BOOLE z, BOOLE rm, BOOLE c, BOOLE v)
{
ULO flags = cpu_sr & 0xffe0;
if (rm) flags |= 8;
else if (z) flags |= 4;
if (v) flags |= 2;
if (c) flags |= 0x11;
cpu_sr = flags;
}
/// <summary>
/// Set the flags of a rotate operation.
/// </summary>
/// <param name="z">The Z flag.</param>
/// <param name="rm">The MSB of the result.</param>
/// <param name="c">The carry of the result.</param>
void cpuSetFlagsRotate(BOOLE z, BOOLE rm, BOOLE c)
{
ULO flags = cpu_sr & 0xfff0; // Always clearing the V flag
if (rm) flags |= 8;
else if (z) flags |= 4;
if (c) flags |= 1;
cpu_sr = flags;
}
/// <summary>
/// Set the flags of a rotate with x operation.
/// </summary>
/// <param name="z">The Z flag.</param>
/// <param name="rm">The MSB of the result.</param>
/// <param name="c">The extend bit and carry of the result.</param>
void cpuSetFlagsRotateX(UWO z, UWO rm, UWO x)
{
cpu_sr = (cpu_sr & 0xffe0) | z | rm | x;
}
/// <summary>
/// Set the flags (ZN00).
/// </summary>
void cpuSetFlagsNZ00NewB(UBY res)
{
ULO flag = cpu_sr & 0xfff0;
if (res & 0x80) flag |= 0x8;
else if (res == 0) flag |= 0x4;
cpu_sr = flag;
}
/// <summary>
/// Set the flags (ZN00).
/// </summary>
void cpuSetFlagsNZ00NewW(UWO res)
{
ULO flag = cpu_sr & 0xfff0;
if (res & 0x8000) flag |= 0x8;
else if (res == 0) flag |= 0x4;
cpu_sr = flag;
}
/// <summary>
/// Set the flags (ZN00).
/// </summary>
void cpuSetFlagsNZ00NewL(ULO res)
{
ULO flag = cpu_sr & 0xfff0;
if (res & 0x80000000) flag |= 0x8;
else if (res == 0) flag |= 0x4;
cpu_sr = flag;
}
/// <summary>
/// Set the flags (ZN00).
/// </summary>
void cpuSetFlagsNZ00New64(LLO res)
{
ULO flag = cpu_sr & 0xfff0;
if (res < 0) flag |= 0x8;
else if (res == 0) flag |= 0x4;
cpu_sr = flag;
}
/// <summary>
/// Set the 4 flags absolute.
/// </summary>
/// <param name="f">flags</param>
void cpuSetFlagsAbs(UWO f)
{
cpu_sr = (cpu_sr & 0xfff0) | f;
}
/// <summary>
/// Calculates the values for the condition codes.
/// </summary>
/// <returns>TRUE or FALSE</returns>
BOOLE cpuCalculateConditionCode0(void)
{
return TRUE;
}
BOOLE cpuCalculateConditionCode1(void)
{
return FALSE;
}
BOOLE cpuCalculateConditionCode2(void)
{
return !(cpu_sr & 5); // HI - !C && !Z
}
BOOLE cpuCalculateConditionCode3(void)
{
return cpu_sr & 5; // LS - C || Z
}
BOOLE cpuCalculateConditionCode4(void)
{
return (~cpu_sr) & 1; // CC - !C
}
BOOLE cpuCalculateConditionCode5(void)
{
return cpu_sr & 1; // CS - C
}
BOOLE cpuCalculateConditionCode6(void)
{
return (~cpu_sr) & 4; // NE - !Z
}
BOOLE cpuCalculateConditionCode7(void)
{
return cpu_sr & 4; // EQ - Z
}
BOOLE cpuCalculateConditionCode8(void)
{
return (~cpu_sr) & 2; // VC - !V
}
BOOLE cpuCalculateConditionCode9(void)
{
return cpu_sr & 2; // VS - V
}
BOOLE cpuCalculateConditionCode10(void)
{
return (~cpu_sr) & 8; // PL - !N
}
BOOLE cpuCalculateConditionCode11(void)
{
return cpu_sr & 8; // MI - N
}
BOOLE cpuCalculateConditionCode12(void)
{
ULO tmp = cpu_sr & 0xa;
return (tmp == 0xa) || (tmp == 0); // GE - (N && V) || (!N && !V)
}
BOOLE cpuCalculateConditionCode13(void)
{
ULO tmp = cpu_sr & 0xa;
return (tmp == 0x8) || (tmp == 0x2); // LT - (N && !V) || (!N && V)
}
BOOLE cpuCalculateConditionCode14(void)
{
ULO tmp = cpu_sr & 0xa;
return (!(cpu_sr & 0x4)) && ((tmp == 0xa) || (tmp == 0)); // GT - (N && V && !Z) || (!N && !V && !Z)
}
BOOLE cpuCalculateConditionCode15(void)
{
ULO tmp = cpu_sr & 0xa;
return (cpu_sr & 0x4) || (tmp == 0x8) || (tmp == 2);// LE - Z || (N && !V) || (!N && V)
}
BOOLE cpuCalculateConditionCode(ULO cc)
{
switch (cc & 0xf)
{
case 0: return cpuCalculateConditionCode0();
case 1: return cpuCalculateConditionCode1();
case 2: return cpuCalculateConditionCode2();
case 3: return cpuCalculateConditionCode3();
case 4: return cpuCalculateConditionCode4();
case 5: return cpuCalculateConditionCode5();
case 6: return cpuCalculateConditionCode6();
case 7: return cpuCalculateConditionCode7();
case 8: return cpuCalculateConditionCode8();
case 9: return cpuCalculateConditionCode9();
case 10: return cpuCalculateConditionCode10();
case 11: return cpuCalculateConditionCode11();
case 12: return cpuCalculateConditionCode12();
case 13: return cpuCalculateConditionCode13();
case 14: return cpuCalculateConditionCode14();
case 15: return cpuCalculateConditionCode15();
}
return FALSE;
}

3735
cpu/CpuModule_Instructions.c Normal file

File diff suppressed because it is too large Load Diff

200
cpu/CpuModule_Internal.h Normal file
View File

@ -0,0 +1,200 @@
#ifndef CpuModule_Internal_H
#define CpuModule_Internal_H
// This header file defines the internal interfaces of the CPU module.
extern void cpuMakeOpcodeTableForModel(void);
extern void cpuCreateMulTimeTables(void);
// StackFrameGen
extern void cpuStackFrameGenerate(UWO vector_no, ULO pc);
extern void cpuStackFrameInit(void);
// Registers
extern ULO cpu_sr; // Not static because the flags calculation uses it extensively
extern BOOLE cpuGetFlagSupervisor(void);
extern BOOLE cpuGetFlagMaster(void);
extern void cpuSetUspDirect(ULO usp);
extern ULO cpuGetUspDirect(void);
extern ULO cpuGetUspAutoMap(void);
extern void cpuSetSspDirect(ULO ssp);
extern ULO cpuGetSspDirect(void);
extern ULO cpuGetSspAutoMap(void);
extern void cpuSetMspDirect(ULO msp);
extern ULO cpuGetMspDirect(void);
extern ULO cpuGetMspAutoMap(void);
extern void cpuSetMspAutoMap(ULO new_msp);
extern ULO cpuGetIspAutoMap(void);
extern void cpuSetIspAutoMap(ULO new_isp);
extern void cpuSetDReg(ULO i, ULO value);
extern ULO cpuGetDReg(ULO i);
extern void cpuSetAReg(ULO i, ULO value);
extern ULO cpuGetAReg(ULO i);
extern void cpuSetReg(ULO da, ULO i, ULO value);
extern ULO cpuGetReg(ULO da, ULO i);
extern void cpuSetPC(ULO address);
extern ULO cpuGetPC(void);
extern void cpuSetStop(BOOLE stop);
extern BOOLE cpuGetStop(void);
extern void cpuSetVbr(ULO vbr);
extern ULO cpuGetVbr(void);
extern void cpuSetSfc(ULO sfc);
extern ULO cpuGetSfc(void);
extern void cpuSetDfc(ULO dfc);
extern ULO cpuGetDfc(void);
extern void cpuSetCacr(ULO cacr);
extern ULO cpuGetCacr(void);
extern void cpuSetCaar(ULO caar);
extern ULO cpuGetCaar(void);
extern void cpuSetSR(ULO sr);
extern ULO cpuGetSR(void);
extern void cpuSetIrqLevel(ULO irq_level);
extern ULO cpuGetIrqLevel(void);
extern void cpuSetIrqAddress(ULO irq_address);
extern ULO cpuGetIrqAddress(void);
extern void cpuSetInstructionTime(ULO cycles);
extern ULO cpuGetInstructionTime(void);
extern void cpuSetOriginalPC(ULO pc);
extern ULO cpuGetOriginalPC(void);
#ifdef CPU_INSTRUCTION_LOGGING
extern void cpuSetCurrentOpcode(UWO opcode);
extern UWO cpuGetCurrentOpcode(void);
#endif
extern void cpuProfileWrite(void);
extern void cpuSetModelMask(UBY model_mask);
extern UBY cpuGetModelMask(void);
extern void cpuSetDRegWord(ULO regno, UWO val);
extern void cpuSetDRegByte(ULO regno, UBY val);
extern UWO cpuGetRegWord(ULO i, ULO regno);
extern UWO cpuGetDRegWord(ULO regno);
extern UBY cpuGetDRegByte(ULO regno);
extern ULO cpuGetDRegWordSignExtLong(ULO regno);
extern UWO cpuGetDRegByteSignExtWord(ULO regno);
extern ULO cpuGetDRegByteSignExtLong(ULO regno);
extern UWO cpuGetARegWord(ULO regno);
extern UBY cpuGetARegByte(ULO regno);
extern UWO cpuGetNextWord(void);
extern ULO cpuGetNextWordSignExt(void);
extern ULO cpuGetNextLong(void);
extern void cpuSkipNextWord(void);
extern void cpuSkipNextLong(void);
extern void cpuClearPrefetch(void);
extern void cpuValidateReadPointer(void);
extern void cpuInitializeFromNewPC(ULO new_pc);
// Effective address
extern ULO cpuEA02(ULO regno);
extern ULO cpuEA03(ULO regno, ULO size);
extern ULO cpuEA04(ULO regno, ULO size);
extern ULO cpuEA05(ULO regno);
extern ULO cpuEA06(ULO regno);
extern ULO cpuEA70(void);
extern ULO cpuEA71(void);
extern ULO cpuEA72(void);
extern ULO cpuEA73(void);
// Flags
extern void cpuSetFlagsAdd(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm);
extern void cpuSetFlagsSub(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm);
extern void cpuSetFlagsCmp(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm);
extern void cpuSetZFlagBitOpsB(UBY res);
extern void cpuSetZFlagBitOpsL(ULO res);
extern void cpuSetFlagsNZ00NewB(UBY res);
extern void cpuSetFlagsNZ00NewW(UWO res);
extern void cpuSetFlagsNZ00NewL(ULO res);
extern void cpuSetFlagsNZ00New64(LLO res);
extern void cpuSetFlagZ(BOOLE f);
extern void cpuSetFlagN(BOOLE f);
extern void cpuSetFlagV(BOOLE f);
extern void cpuSetFlagC(BOOLE f);
extern void cpuSetFlagXC(BOOLE f);
extern void cpuSetFlags0100(void);
extern void cpuSetFlagsNeg(BOOLE z, BOOLE rm, BOOLE dm);
extern BOOLE cpuGetFlagX(void);
extern void cpuSetFlagsNegx(BOOLE z, BOOLE rm, BOOLE dm);
extern BOOLE cpuGetFlagV(void);
extern void cpuSetFlagsNZVC(BOOLE z, BOOLE n, BOOLE v, BOOLE c);
extern void cpuSetFlagsVC(BOOLE v, BOOLE c);
extern void cpuSetFlagsShiftZero(BOOLE z, BOOLE rm);
extern void cpuSetFlagsShift(BOOLE z, BOOLE rm, BOOLE c, BOOLE v);
extern void cpuSetFlagsRotate(BOOLE z, BOOLE rm, BOOLE c);
extern void cpuSetFlagsRotateX(UWO z, UWO rm, UWO x);
extern void cpuSetFlagsAddX(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm);
extern void cpuSetFlagsSubX(BOOLE z, BOOLE rm, BOOLE dm, BOOLE sm);
extern void cpuSetFlagsAbs(UWO f);
extern UWO cpuGetZFlagB(UBY res);
extern UWO cpuGetZFlagW(UWO res);
extern UWO cpuGetZFlagL(ULO res);
extern UWO cpuGetNFlagB(UBY res);
extern UWO cpuGetNFlagW(UWO res);
extern UWO cpuGetNFlagL(ULO res);
extern BOOLE cpuCalculateConditionCode0(void);
extern BOOLE cpuCalculateConditionCode1(void);
extern BOOLE cpuCalculateConditionCode2(void);
extern BOOLE cpuCalculateConditionCode3(void);
extern BOOLE cpuCalculateConditionCode4(void);
extern BOOLE cpuCalculateConditionCode5(void);
extern BOOLE cpuCalculateConditionCode6(void);
extern BOOLE cpuCalculateConditionCode7(void);
extern BOOLE cpuCalculateConditionCode8(void);
extern BOOLE cpuCalculateConditionCode9(void);
extern BOOLE cpuCalculateConditionCode10(void);
extern BOOLE cpuCalculateConditionCode11(void);
extern BOOLE cpuCalculateConditionCode12(void);
extern BOOLE cpuCalculateConditionCode13(void);
extern BOOLE cpuCalculateConditionCode14(void);
extern BOOLE cpuCalculateConditionCode15(void);
extern BOOLE cpuCalculateConditionCode(ULO cc);
// Logging
#ifdef CPU_INSTRUCTION_LOGGING
extern void cpuCallInstructionLoggingFunc(void);
extern void cpuCallExceptionLoggingFunc(STR *description, ULO original_pc, UWO opcode);
extern void cpuCallInterruptLoggingFunc(ULO level, ULO vector_address);
#endif
// Interrupt
extern void cpuCallCheckPendingInterruptsFunc(void);
extern ULO cpuActivateSSP(void);
extern void cpuSetRaiseInterrupt(BOOLE raise_irq);
extern BOOLE cpuGetRaiseInterrupt(void);
// Exceptions
extern void cpuThrowPrivilegeViolationException(void);
extern void cpuThrowIllegalInstructionException(BOOLE executejmp);
extern void cpuThrowFLineException(void);
extern void cpuThrowALineException(void);
extern void cpuThrowTrapVException(void);
extern void cpuThrowTrapException(ULO vector_no);
extern void cpuThrowDivisionByZeroException(BOOLE executejmp);
extern void cpuThrowChkException(void);
extern void cpuThrowTraceException(void);
extern void cpuThrowResetException(void);
extern void cpuCallResetExceptionFunc(void);
extern void cpuFrame1(UWO vector_offset, ULO pc);
// Private help functions
static ULO cpuSignExtByteToLong(UBY v) {return (ULO)(LON)(BYT) v;}
static UWO cpuSignExtByteToWord(UBY v) {return (UWO)(WOR)(BYT) v;}
static ULO cpuSignExtWordToLong(UWO v) {return (ULO)(LON)(WOR) v;}
static ULO cpuJoinWordToLong(UWO upper, UWO lower) {return (((ULO)upper) << 16) | ((ULO)lower);}
static ULO cpuJoinByteToLong(UBY upper, UBY midh, UBY midl, UBY lower) {return (((ULO)upper) << 24) | (((ULO)midh) << 16) | (((ULO)midl) << 8) | ((ULO)lower);}
static UWO cpuJoinByteToWord(UBY upper, UBY lower) {return (((UWO)upper) << 8) | ((UWO)lower);}
static BOOLE cpuMsbB(UBY v) {return v>>7;}
static BOOLE cpuMsbW(UWO v) {return v>>15;}
static BOOLE cpuMsbL(ULO v) {return v>>31;}
static BOOLE cpuIsZeroB(UBY v) {return v == 0;}
static BOOLE cpuIsZeroW(UWO v) {return v == 0;}
static BOOLE cpuIsZeroL(ULO v) {return v == 0;}
#endif

View File

@ -0,0 +1,390 @@
/* @(#) $Id: CpuModule_InternalState.c,v 1.9 2012/08/12 16:51:02 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* 68000 internal state */
/* */
/* Author: Petter Schau */
/* */
/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software Foundation, */
/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*=========================================================================*/
#include "defs.h"
#include "CpuModule.h"
#include "fellow.h"
#include "fmem.h"
#include "CpuModule_Internal.h"
/* M68k registers */
static ULO cpu_regs[2][8]; /* 0 - data, 1 - address */
static ULO cpu_pc;
static ULO cpu_usp;
static ULO cpu_ssp;
static ULO cpu_msp;
static ULO cpu_sfc;
static ULO cpu_dfc;
ULO cpu_sr; // Not static because flags calculation use it extensively
static ULO cpu_vbr;
static UWO cpu_prefetch_word;
static ULO cpu_cacr;
static ULO cpu_caar;
/* Irq management */
static BOOLE cpu_raise_irq;
static ULO cpu_irq_level;
static ULO cpu_irq_address;
/* Reset values */
static ULO cpu_initial_pc;
static ULO cpu_initial_sp;
/* Flag set if CPU is stopped */
static BOOLE cpu_stop;
/* The current CPU model */
static ULO cpu_model_major = -1;
static ULO cpu_model_minor;
static UBY cpu_model_mask;
/* For exception handling */
#ifdef CPU_INSTRUCTION_LOGGING
static UWO cpu_current_opcode;
#endif
static ULO cpu_original_pc;
/* Number of cycles taken by the last intstruction */
static ULO cpu_instruction_time;
/* Getters and setters */
void cpuSetDReg(ULO i, ULO value) {cpu_regs[0][i] = value;}
ULO cpuGetDReg(ULO i) {return cpu_regs[0][i];}
void cpuSetAReg(ULO i, ULO value) {cpu_regs[1][i] = value;}
ULO cpuGetAReg(ULO i) {return cpu_regs[1][i];}
void cpuSetReg(ULO da, ULO i, ULO value) {cpu_regs[da][i] = value;}
ULO cpuGetReg(ULO da, ULO i) {return cpu_regs[da][i];}
/// <summary>
/// Get the supervisor bit from sr.
/// </summary>
BOOLE cpuGetFlagSupervisor(void)
{
return cpu_sr & 0x2000;
}
/// <summary>
/// Get the master/irq state bit from sr.
/// </summary>
BOOLE cpuGetFlagMaster(void)
{
return cpu_sr & 0x1000;
}
void cpuSetUspDirect(ULO usp) {cpu_usp = usp;}
ULO cpuGetUspDirect(void) {return cpu_usp;}
ULO cpuGetUspAutoMap(void) {return (cpuGetFlagSupervisor()) ? cpuGetUspDirect() : cpuGetAReg(7);}
void cpuSetSspDirect(ULO ssp) {cpu_ssp = ssp;}
ULO cpuGetSspDirect(void) {return cpu_ssp;}
ULO cpuGetSspAutoMap(void) {return (cpuGetFlagSupervisor()) ? cpuGetAReg(7) : cpuGetSspDirect();}
void cpuSetMspDirect(ULO msp) {cpu_msp = msp;}
ULO cpuGetMspDirect(void) {return cpu_msp;}
/// <summary>
/// Returns the master stack pointer.
/// </summary>
ULO cpuGetMspAutoMap(void)
{
if (cpuGetFlagSupervisor() && cpuGetFlagMaster())
{
return cpuGetAReg(7);
}
return cpuGetMspDirect();
}
/// <summary>
/// Sets the master stack pointer.
/// </summary>
void cpuSetMspAutoMap(ULO new_msp)
{
if (cpuGetFlagSupervisor() && cpuGetFlagMaster())
{
cpuSetAReg(7, new_msp);
}
else
{
cpuSetMspDirect(new_msp);
}
}
/// <summary>
/// Returns the interrupt stack pointer. ssp is used as isp.
/// </summary>
ULO cpuGetIspAutoMap(void)
{
if (cpuGetFlagSupervisor() && !cpuGetFlagMaster())
{
return cpuGetAReg(7);
}
return cpuGetSspDirect();
}
/// <summary>
/// Sets the interrupt stack pointer. ssp is used as isp.
/// </summary>
void cpuSetIspAutoMap(ULO new_isp)
{
if (cpuGetFlagSupervisor() && !cpuGetFlagMaster())
{
cpuSetAReg(7, new_isp);
}
else
{
cpuSetSspDirect(new_isp);
}
}
void cpuSetPC(ULO address) {cpu_pc = address;}
ULO cpuGetPC(void) {return cpu_pc;}
void cpuSetStop(BOOLE stop) {cpu_stop = stop;}
BOOLE cpuGetStop(void) {return cpu_stop;}
void cpuSetVbr(ULO vbr) {cpu_vbr = vbr;}
ULO cpuGetVbr(void) {return cpu_vbr;}
void cpuSetSfc(ULO sfc) {cpu_sfc = sfc;}
ULO cpuGetSfc(void) {return cpu_sfc;}
void cpuSetDfc(ULO dfc) {cpu_dfc = dfc;}
ULO cpuGetDfc(void) {return cpu_dfc;}
void cpuSetCacr(ULO cacr) {cpu_cacr = cacr;}
ULO cpuGetCacr(void) {return cpu_cacr;}
void cpuSetCaar(ULO caar) {cpu_caar = caar;}
ULO cpuGetCaar(void) {return cpu_caar;}
void cpuSetSR(ULO sr) {cpu_sr = sr;}
ULO cpuGetSR(void) {return cpu_sr;}
void cpuSetIrqLevel(ULO irq_level) {cpu_irq_level = irq_level;}
ULO cpuGetIrqLevel(void) {return cpu_irq_level;}
void cpuSetIrqAddress(ULO irq_address) {cpu_irq_address = irq_address;}
ULO cpuGetIrqAddress(void) {return cpu_irq_address;}
void cpuSetInstructionTime(ULO cycles) {cpu_instruction_time = cycles;}
ULO cpuGetInstructionTime(void) {return cpu_instruction_time;}
void cpuSetOriginalPC(ULO pc) {cpu_original_pc = pc;}
ULO cpuGetOriginalPC(void) {return cpu_original_pc;}
#ifdef CPU_INSTRUCTION_LOGGING
void cpuSetCurrentOpcode(UWO opcode) {cpu_current_opcode = opcode;}
UWO cpuGetCurrentOpcode(void) {return cpu_current_opcode;}
#endif
void cpuSetRaiseInterrupt(BOOLE raise_irq) {cpu_raise_irq = raise_irq;}
BOOLE cpuGetRaiseInterrupt(void) {return cpu_raise_irq;}
void cpuSetInitialPC(ULO pc) {cpu_initial_pc = pc;}
ULO cpuGetInitialPC(void) {return cpu_initial_pc;}
void cpuSetInitialSP(ULO sp) {cpu_initial_sp = sp;}
ULO cpuGetInitialSP(void) {return cpu_initial_sp;}
void cpuSetModelMask(UBY model_mask) {cpu_model_mask = model_mask;}
UBY cpuGetModelMask(void) {return cpu_model_mask;}
ULO cpuGetModelMajor(void) {return cpu_model_major;}
ULO cpuGetModelMinor(void) {return cpu_model_minor;}
static void cpuCalculateModelMask(void)
{
switch (cpuGetModelMajor())
{
case 0:
cpuSetModelMask(0x01);
break;
case 1:
cpuSetModelMask(0x02);
break;
case 2:
cpuSetModelMask(0x04);
break;
case 3:
cpuSetModelMask(0x08);
break;
}
}
void cpuSetModel(ULO major, ULO minor)
{
BOOLE makeOpcodeTable = (cpu_model_major != major);
cpu_model_major = major;
cpu_model_minor = minor;
cpuCalculateModelMask();
cpuStackFrameInit();
if (makeOpcodeTable) cpuMakeOpcodeTableForModel();
}
void cpuSetDRegWord(ULO regno, UWO val) {*((WOR*)&cpu_regs[0][regno]) = val;}
void cpuSetDRegByte(ULO regno, UBY val) {*((UBY*)&cpu_regs[0][regno]) = val;}
UWO cpuGetRegWord(ULO i, ULO regno) {return (UWO)cpu_regs[i][regno];}
UWO cpuGetDRegWord(ULO regno) {return (UWO)cpu_regs[0][regno];}
UBY cpuGetDRegByte(ULO regno) {return (UBY)cpu_regs[0][regno];}
ULO cpuGetDRegWordSignExtLong(ULO regno) {return cpuSignExtWordToLong(cpuGetDRegWord(regno));}
UWO cpuGetDRegByteSignExtWord(ULO regno) {return cpuSignExtByteToWord(cpuGetDRegByte(regno));}
ULO cpuGetDRegByteSignExtLong(ULO regno) {return cpuSignExtByteToLong(cpuGetDRegByte(regno));}
UWO cpuGetARegWord(ULO regno) {return (UWO)cpu_regs[1][regno];}
UBY cpuGetARegByte(ULO regno) {return (UBY)cpu_regs[1][regno];}
typedef UWO (*cpuGetWordFunc)(void);
typedef ULO (*cpuGetLongFunc)(void);
static UWO cpuGetNextWordInternal(void)
{
UWO data = memoryReadWord(cpuGetPC() + 2);
return data;
}
static ULO cpuGetNextLongInternal(void)
{
ULO data = memoryReadLong(cpuGetPC() + 2);
return data;
}
UWO cpuGetNextWord(void)
{
UWO tmp = cpu_prefetch_word;
cpu_prefetch_word = cpuGetNextWordInternal();
cpuSetPC(cpuGetPC() + 2);
return tmp;
}
ULO cpuGetNextWordSignExt(void)
{
return cpuSignExtWordToLong(cpuGetNextWord());
}
ULO cpuGetNextLong(void)
{
ULO tmp = cpu_prefetch_word << 16;
ULO data = cpuGetNextLongInternal();
cpu_prefetch_word = (UWO) data;
cpuSetPC(cpuGetPC() + 4);
return tmp | (data >> 16);
}
void cpuInitializePrefetch(void)
{
cpu_prefetch_word = memoryReadWord(cpuGetPC());
}
void cpuClearPrefetch(void)
{
cpu_prefetch_word = 0;
}
void cpuSkipNextWord(void)
{
cpuSetPC(cpuGetPC() + 2);
cpuInitializePrefetch();
}
void cpuSkipNextLong(void)
{
cpuSetPC(cpuGetPC() + 4);
cpuInitializePrefetch();
}
void cpuInitializeFromNewPC(ULO new_pc)
{
cpuSetPC(new_pc);
cpuInitializePrefetch();
}
void cpuSaveState(FILE *F)
{
ULO i, j;
fwrite(&cpu_model_major, sizeof(cpu_model_major), 1, F);
fwrite(&cpu_model_minor, sizeof(cpu_model_minor), 1, F);
for (i = 0; i < 2; i++)
{
for (j = 0; j < 7; j++)
{
fwrite(&cpu_regs[i][j], sizeof(cpu_regs[i][j]), 1, F);
}
}
fwrite(&cpu_pc, sizeof(cpu_pc), 1, F);
fwrite(&cpu_usp, sizeof(cpu_usp), 1, F);
fwrite(&cpu_ssp, sizeof(cpu_ssp), 1, F);
fwrite(&cpu_msp, sizeof(cpu_msp), 1, F);
fwrite(&cpu_sfc, sizeof(cpu_sfc), 1, F);
fwrite(&cpu_dfc, sizeof(cpu_dfc), 1, F);
fwrite(&cpu_sr, sizeof(cpu_sr), 1, F);
fwrite(&cpu_prefetch_word, sizeof(cpu_prefetch_word), 1, F);
fwrite(&cpu_vbr, sizeof(cpu_vbr), 1, F);
fwrite(&cpu_cacr, sizeof(cpu_cacr), 1, F);
fwrite(&cpu_caar, sizeof(cpu_caar), 1, F);
fwrite(&cpu_irq_level, sizeof(cpu_irq_level), 1, F);
fwrite(&cpu_irq_address, sizeof(cpu_irq_address), 1, F);
fwrite(&cpu_initial_pc, sizeof(cpu_initial_pc), 1, F);
fwrite(&cpu_initial_sp, sizeof(cpu_initial_sp), 1, F);
}
void cpuLoadState(FILE *F)
{
ULO i, j;
fread(&cpu_model_major, sizeof(cpu_model_major), 1, F);
fread(&cpu_model_minor, sizeof(cpu_model_minor), 1, F);
for (i = 0; i < 2; i++)
{
for (j = 0; j < 7; j++)
{
fread(&cpu_regs[i][j], sizeof(cpu_regs[i][j]), 1, F);
}
}
fread(&cpu_pc, sizeof(cpu_pc), 1, F);
fread(&cpu_usp, sizeof(cpu_usp), 1, F);
fread(&cpu_ssp, sizeof(cpu_ssp), 1, F);
fread(&cpu_msp, sizeof(cpu_msp), 1, F);
fread(&cpu_sfc, sizeof(cpu_sfc), 1, F);
fread(&cpu_dfc, sizeof(cpu_dfc), 1, F);
fread(&cpu_sr, sizeof(cpu_sr), 1, F);
fread(&cpu_prefetch_word, sizeof(cpu_prefetch_word), 1, F);
fread(&cpu_vbr, sizeof(cpu_vbr), 1, F);
fread(&cpu_cacr, sizeof(cpu_cacr), 1, F);
fread(&cpu_caar, sizeof(cpu_caar), 1, F);
fread(&cpu_irq_level, sizeof(cpu_irq_level), 1, F);
fread(&cpu_irq_address, sizeof(cpu_irq_address), 1, F);
fread(&cpu_initial_pc, sizeof(cpu_initial_pc), 1, F);
fread(&cpu_initial_sp, sizeof(cpu_initial_sp), 1, F);
cpuSetModel(cpu_model_major, cpu_model_minor); // Recalculates stack frames etc.
}

107
cpu/CpuModule_Interrupts.c Normal file
View File

@ -0,0 +1,107 @@
/* @(#) $Id: CpuModule_Interrupts.c,v 1.5 2012/08/12 16:51:02 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* 68000 interrupt handling */
/* */
/* Author: Petter Schau */
/* */
/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software Foundation, */
/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*=========================================================================*/
#include "defs.h"
#include "fellow.h"
#include "fmem.h"
#include "CpuModule.h"
#include "CpuModule_Internal.h"
/* Function for checking pending interrupts */
cpuCheckPendingInterruptsFunc cpu_check_pending_interrupts_func;
void cpuCallCheckPendingInterruptsFunc(void)
{
if (cpuGetRaiseInterrupt()) return;
cpuSetRaiseInterrupt(cpu_check_pending_interrupts_func());
}
void cpuCheckPendingInterrupts(void)
{
cpuCallCheckPendingInterruptsFunc();
}
void cpuSetCheckPendingInterruptsFunc(cpuCheckPendingInterruptsFunc func)
{
cpu_check_pending_interrupts_func = func;
}
ULO cpuActivateSSP(void)
{
ULO currentSP = cpuGetAReg(7);
// check supervisor bit number (bit 13) within the system byte of the status register
if (!cpuGetFlagSupervisor())
{
// we are in user mode, thus save user stack pointer (USP)
cpuSetUspDirect(currentSP);
currentSP = cpuGetSspDirect();
if (cpuGetModelMajor() >= 2)
{
if (cpuGetFlagMaster())
{
currentSP = cpuGetMspDirect();
}
}
cpuSetAReg(7, currentSP);
}
return currentSP;
}
/*============================================================
Transfers control to an interrupt routine
============================================================*/
// Returns TRUE if the cpu was stopped
void cpuSetUpInterrupt(void)
{
UWO vector_offset = (UWO) (0x60 + cpuGetIrqLevel()*4);
cpuActivateSSP(); // Switch to using ssp or msp. Loads a7 and preserves usp if we came from user-mode.
cpuStackFrameGenerate(vector_offset, cpuGetPC()); // This will end up on msp if master is enabled, or on the ssp/isp if not.
cpuSetSR(cpuGetSR() & 0x38ff); // Clear interrupt level
cpuSetSR(cpuGetSR() | 0x2000); // Set supervisor mode
cpuSetSR(cpuGetSR() | (UWO)(cpuGetIrqLevel() << 8)); // Set interrupt level
#ifdef CPU_INSTRUCTION_LOGGING
cpuCallInterruptLoggingFunc(cpuGetIrqLevel(), cpuGetIrqAddress());
#endif
if (cpuGetModelMajor() >= 2 && cpuGetModelMajor() < 6)
{
if (cpuGetFlagMaster())
{ // If the cpu was in master mode, preserve msp, and switch to using ssp (isp) in a7.
ULO oldA7 = cpuGetAReg(7);
cpuSetMspDirect(oldA7);
cpuSetAReg(7, cpuGetSspDirect());
cpuFrame1(vector_offset, cpuGetPC()); // Make the throwaway frame on ssp/isp
cpuSetSR(cpuGetSR() & 0xefff); // Clear master bit
}
}
cpuInitializeFromNewPC(cpuGetIrqAddress());
cpuSetStop(FALSE);
cpuSetRaiseInterrupt(FALSE);
}

71
cpu/CpuModule_Logging.c Normal file
View File

@ -0,0 +1,71 @@
/* @(#) $Id: CpuModule_Logging.c,v 1.3 2012/08/12 16:51:02 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* CPU 68k logging functions */
/* */
/* Author: Petter Schau */
/* */
/* */
/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software Foundation, */
/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*=========================================================================*/
#include "defs.h"
#include "fellow.h"
#include "CpuModule.h"
#ifdef CPU_INSTRUCTION_LOGGING
/* Function for logging the intruction execution */
static cpuInstructionLoggingFunc cpu_instruction_logging_func;
static cpuExceptionLoggingFunc cpu_exception_logging_func;
static cpuInterruptLoggingFunc cpu_interrupt_logging_func;
void cpuSetInstructionLoggingFunc(cpuInstructionLoggingFunc func)
{
cpu_instruction_logging_func = func;
}
void cpuCallInstructionLoggingFunc(void)
{
if (cpu_instruction_logging_func != NULL)
cpu_instruction_logging_func();
}
void cpuSetExceptionLoggingFunc(cpuExceptionLoggingFunc func)
{
cpu_exception_logging_func = func;
}
void cpuCallExceptionLoggingFunc(STR *description, ULO original_pc, UWO opcode)
{
if (cpu_exception_logging_func != NULL)
cpu_exception_logging_func(description, original_pc, opcode);
}
void cpuSetInterruptLoggingFunc(cpuInterruptLoggingFunc func)
{
cpu_interrupt_logging_func = func;
}
void cpuCallInterruptLoggingFunc(ULO level, ULO vector_address)
{
if (cpu_interrupt_logging_func != NULL)
cpu_interrupt_logging_func(level, vector_address);
}
#endif

8
cpu/CpuModule_Profile.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef CPUMODULE_PROFILE_H
#define CPUMODULE_PROFILE_H
#include "fileops.h"
void cpuProfileWrite(void)
{
}
#endif

View File

@ -0,0 +1,259 @@
/* @(#) $Id: CpuModule_StackFrameGen.c,v 1.3 2011/07/18 17:22:55 peschau Exp $ */
/*=========================================================================*/
/* Fellow */
/* 68000 stack frame generation */
/* */
/* Author: Petter Schau */
/* */
/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software Foundation, */
/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*=========================================================================*/
#include "defs.h"
#include "fellow.h"
#include "fmem.h"
#include "CpuModule.h"
#include "CpuModule_Internal.h"
/* Exception stack frame jmptables */
typedef void(*cpuStackFrameGenFunc)(UWO, ULO);
static cpuStackFrameGenFunc cpu_stack_frame_gen_func[64];
static void cpuSetStackFrameGenFunc(ULO vector_no, cpuStackFrameGenFunc func)
{
cpu_stack_frame_gen_func[vector_no] = func;
}
/*========================================================================
Group 1 Frame format
000: All, except bus and address error
========================================================================*/
static void cpuFrameGroup1(UWO vector_offset, ULO pcPtr)
{
// save PC
cpuSetAReg(7, cpuGetAReg(7) - 4);
memoryWriteLong(pcPtr, cpuGetAReg(7));
// save SR
cpuSetAReg(7, cpuGetAReg(7) - 2);
memoryWriteWord((UWO)cpuGetSR(), cpuGetAReg(7));
}
/*========================================================================
Group 2 Frame format
000: Bus and address error
memory_fault_address contains the violating address
memory_fault_read is TRUE if the access was a read
========================================================================*/
static void cpuFrameGroup2(UWO vector_offset, ULO pcPtr)
{
// save PC
cpuSetAReg(7, cpuGetAReg(7) - 4);
memoryWriteLong(pcPtr, cpuGetAReg(7));
// save SR
cpuSetAReg(7, cpuGetAReg(7) - 2);
memoryWriteWord((UWO)cpuGetSR(), cpuGetAReg(7));
// fault address, skip ireg
cpuSetAReg(7, cpuGetAReg(7) - 6);
memoryWriteLong(memory_fault_address, cpuGetAReg(7));
cpuSetAReg(7, cpuGetAReg(7) - 2);
memoryWriteLong(memory_fault_read << 4, cpuGetAReg(7));
}
static void cpuFrame4Words(UWO frame_code, UWO vector_offset, ULO pc)
{
// save vector_offset word
cpuSetAReg(7, cpuGetAReg(7) - 2);
memoryWriteWord(frame_code | vector_offset, cpuGetAReg(7));
// save PC
cpuSetAReg(7, cpuGetAReg(7) - 4);
memoryWriteLong(pc, cpuGetAReg(7));
// save SR
cpuSetAReg(7, cpuGetAReg(7) - 2);
memoryWriteWord((UWO)cpuGetSR(), cpuGetAReg(7));
}
/*========================================================================
Frame format $0, four word frame
Stack words:
------------
SR
PCHI
PCLO
0000 Vector offset (4 upper bits are frame no., rest is vector offset)
010: All, except bus and address errors
020: Irq, Format error, Trap #N, Illegal inst., A-line, F-line,
Priv. violation, copr preinst
030: Same as for 020
========================================================================*/
static void cpuFrame0(UWO vector_offset, ULO pc)
{
cpuFrame4Words(0x0000, vector_offset, pc);
}
/*========================================================================
Frame format $1, 4 word throwaway frame
Stack words:
------------
SR
PCHI
PCLO
0000 Vector offset (4 upper bits are frame no., rest is Vvctor offset)
020: Irq, second frame created
030: Same as for 020
040: Same as for 020
========================================================================*/
void cpuFrame1(UWO vector_offset, ULO pc)
{
cpuFrame4Words(0x1000, vector_offset, pc);
}
/*========================================================================
Frame format $2
020: chk, chk2, cpTrapcc, trapcc, trapv, trace, zero divide, MMU config,
copr postinst
030: Same as for 020
040: chk, chk2, FTrapcc, trapcc, trapv, trace, zero divide, address error,
Unimplemented FPU inst.
060: Same as for 040
========================================================================*/
static void cpuFrame2(UWO vector_offset, ULO pc)
{
// save inst address
cpuSetAReg(7, cpuGetAReg(7) - 4);
memoryWriteLong(cpuGetOriginalPC(), cpuGetAReg(7));
cpuFrame4Words(0x2000, vector_offset, pc);
}
/*========================================================================
Frame format $8
010: Bus and address error
========================================================================*/
static void cpuFrame8(UWO vector_offset, ULO pc)
{
cpuSetAReg(7, cpuGetAReg(7) - 50);
cpuFrame4Words(0x8000, vector_offset, pc);
}
/*========================================================================
Frame format $A
020: Address or bus-error on instruction boundrary
030: Same as for 020
Will not set any values beyond the format/offset word
Fellow will always generate this frame for bus/address errors
========================================================================*/
static void cpuFrameA(UWO vector_offset, ULO pc)
{
// save vector_offset offset
cpuSetAReg(7, cpuGetAReg(7) - 24);
cpuFrame4Words(0xa000, vector_offset, pc);
}
void cpuStackFrameGenerate(UWO vector_offset, ULO pc)
{
cpu_stack_frame_gen_func[vector_offset>>2](vector_offset, pc);
}
/*==================================*/
/* Initialize stack frame jmptables */
/*==================================*/
static void cpuStackFrameInitSetDefaultFunc(cpuStackFrameGenFunc default_func)
{
ULO i;
for (i = 0; i < 64; i++)
cpuSetStackFrameGenFunc(i, default_func);
}
static void cpuStackFrameInit000(void)
{
cpuStackFrameInitSetDefaultFunc(cpuFrameGroup1);
cpuSetStackFrameGenFunc(2, cpuFrameGroup2); /* 2 - Bus error */
cpuSetStackFrameGenFunc(3, cpuFrameGroup2); /* 3 - Address error */
}
static void cpuStackFrameInit010(void)
{
cpuStackFrameInitSetDefaultFunc(cpuFrame0);
cpuSetStackFrameGenFunc(2, cpuFrame8); /* 2 - Bus error */
cpuSetStackFrameGenFunc(3, cpuFrame8); /* 3 - Address error */
}
static void cpuStackFrameInit020(void)
{
cpuStackFrameInitSetDefaultFunc(cpuFrame0);
cpuSetStackFrameGenFunc(2, cpuFrameA); /* 2 - Bus Error */
cpuSetStackFrameGenFunc(3, cpuFrameA); /* 3 - Addrss Error */
cpuSetStackFrameGenFunc(5, cpuFrame2); /* 5 - Zero Divide */
cpuSetStackFrameGenFunc(6, cpuFrame2); /* 6 - CHK, CHK2 */
cpuSetStackFrameGenFunc(7, cpuFrame2); /* 7 - TRAPV, TRAPcc, cpTRAPcc */
cpuSetStackFrameGenFunc(9, cpuFrame2); /* 9 - Trace */
}
static void cpuStackFrameInit030(void)
{
cpuStackFrameInitSetDefaultFunc(cpuFrame0);
cpuSetStackFrameGenFunc(2, cpuFrameA); /* 2 - Bus Error */
cpuSetStackFrameGenFunc(3, cpuFrameA); /* 3 - Addrss Error */
cpuSetStackFrameGenFunc(5, cpuFrame2); /* 5 - Zero Divide */
cpuSetStackFrameGenFunc(6, cpuFrame2); /* 6 - CHK, CHK2 */
cpuSetStackFrameGenFunc(7, cpuFrame2); /* 7 - TRAPV, TRAPcc, cpTRAPcc */
cpuSetStackFrameGenFunc(9, cpuFrame2); /* 9 - Trace */
}
void cpuStackFrameInit(void)
{
switch (cpuGetModelMajor())
{
case 0:
cpuStackFrameInit000();
break;
case 1:
cpuStackFrameInit010();
break;
case 2:
cpuStackFrameInit020();
break;
case 3:
cpuStackFrameInit030();
break;
}
}

72
cpu/defs.h Normal file
View File

@ -0,0 +1,72 @@
#ifndef DEFS_H
#define DEFS_H
#include <stdint.h>
#include <stdio.h>
#include <string.h>
/* Maximum values for memory, don't change */
#define CHIPMEM 0x200000
#define FASTMEM 0x800000
#define BOGOMEM 0x1c0000
#define KICKMEM 0x080000
/* Fellow types to ensure correct sizes */
typedef uint8_t UBY;
typedef uint16_t UWO;
typedef uint32_t ULO;
typedef uint64_t ULL;
typedef int8_t BYT;
typedef int16_t WOR;
typedef int32_t LON;
typedef int64_t LLO;
typedef int BOOLE;
#define FALSE 0
#define TRUE 1
typedef char STR;
/*
#ifndef X64
#define PTR_TO_INT(i) ((ULO)i)
#endif
#ifdef X64
#define PTR_TO_INT(i) ((ULL)i)
#endif
*/
/* Filename length used throughout the code */
#define CFG_FILENAME_LENGTH 256
/*------------------------------------*/
/* The decode routines have this type */
/*------------------------------------*/
typedef void (*decoderoutinetype)(ULO,ULO);
extern UBY configromname[];
typedef union {
ULO *lptr;
UWO *wptr;
UBY *bptr;
ULO lval;
UWO wval[2];
UBY bval[4];
} ptunion;
typedef void (*planar2chunkyroutine)(void);
typedef void (*playbuffer_routine)(void);
typedef void (*sound_before_emu_routine)(void);
typedef void (*sound_after_emu_routine)(void);
typedef void (*buseventfunc)(void);
#define FELLOWVERSION "WinFellow alpha v0.5.0 build 0 (CVS)"
#define FELLOWLONGVERSION "WinFellow Amiga Emulator alpha v0.5.0 - CVS"
#define FELLOWNUMERICVERSION "0.5.0.0"
#endif

2094
cpu/fmem.c Normal file

File diff suppressed because it is too large Load Diff

152
cpu/fmem.h Normal file
View File

@ -0,0 +1,152 @@
#ifndef FMEM_H
#define FMEM_H
/* Memory access functions */
extern UBY memoryReadByte(ULO address);
extern UWO memoryReadWord(ULO address);
extern ULO memoryReadLong(ULO address);
extern void memoryWriteByte(UBY data, ULO address);
extern void memoryWriteWord(UWO data, ULO address);
extern void memoryWriteLong(ULO data, ULO address);
extern UWO memoryChipReadWord(ULO address);
extern void memoryChipWriteWord(UWO data, ULO address);
#define memoryReadByteFromPointer(address) (address[0])
#define memoryReadWordFromPointer(address) ((address[0] << 8) | address[1])
#define memoryReadLongFromPointer(address) ((address[0] << 24) | (address[1] << 16) | (address[2] << 8) | address[3])
/* IO Bank functions */
typedef UWO (*memoryIoReadFunc)(ULO address);
typedef void (*memoryIoWriteFunc)(UWO data, ULO address);
extern void memorySetIoReadStub(ULO index, memoryIoReadFunc ioreadfunction);
extern void memorySetIoWriteStub(ULO index, memoryIoWriteFunc iowritefunction);
/* For the copper */
extern memoryIoWriteFunc memory_iobank_write[257];
/* Expansion card functions */
typedef void (*memoryEmemCardInitFunc)(void);
typedef void (*memoryEmemCardMapFunc)(ULO);
extern void memoryEmemClear(void);
extern void memoryEmemCardAdd(memoryEmemCardInitFunc cardinit,
memoryEmemCardMapFunc cardmap);
extern void memoryEmemSet(ULO index, ULO data);
extern void memoryEmemMirror(ULO emem_offset, UBY *src, ULO size);
/* Device memory functions. fhfile is using these. */
extern void memoryDmemSetByte(UBY data);
extern void memoryDmemSetWord(UWO data);
extern void memoryDmemSetLong(ULO data);
extern void memoryDmemSetLongNoCounter(ULO data, ULO offset);
extern void memoryDmemSetString(STR *data);
extern void memoryDmemSetCounter(ULO val);
extern ULO memoryDmemGetCounter(void);
extern void memoryDmemClear(void);
/* Module management functions */
extern void memorySaveState(FILE *F);
extern void memoryLoadState(FILE *F);
extern void memorySoftReset(void);
extern void memoryHardReset(void);
extern void memoryHardResetPost(void);
extern void memoryEmulationStart(void);
extern void memoryEmulationStop(void);
extern void memoryStartup(void);
extern void memoryShutdown(void);
/* Memory bank functions */
typedef UBY (*memoryReadByteFunc)(ULO address);
typedef UWO (*memoryReadWordFunc)(ULO address);
typedef ULO (*memoryReadLongFunc)(ULO address);
typedef void (*memoryWriteByteFunc)(UBY data, ULO address);
typedef void (*memoryWriteWordFunc)(UWO data, ULO address);
typedef void (*memoryWriteLongFunc)(ULO data, ULO address);
extern memoryReadByteFunc memory_bank_readbyte[65536];
extern memoryReadWordFunc memory_bank_readword[65536];
extern memoryReadLongFunc memory_bank_readlong[65536];
extern memoryWriteByteFunc memory_bank_writebyte[65536];
extern memoryWriteWordFunc memory_bank_writeword[65536];
extern memoryWriteLongFunc memory_bank_writelong[65536];
extern UBY *memory_bank_pointer[65536];
extern UBY *memory_bank_datapointer[65536];
extern void memoryBankSet(memoryReadByteFunc rb,
memoryReadWordFunc rw,
memoryReadLongFunc rl,
memoryWriteByteFunc wb,
memoryWriteWordFunc ww,
memoryWriteLongFunc wl,
UBY *basep,
ULO bank,
ULO basebank,
BOOLE pointer_can_write);
extern UBY *memoryAddressToPtr(ULO address);
extern void memoryChipMap(BOOLE overlay);
/* Memory configuration properties */
extern BOOLE memorySetChipSize(ULO chipsize);
extern ULO memoryGetChipSize(void);
extern BOOLE memorySetFastSize(ULO fastsize);
extern ULO memoryGetFastSize(void);
extern void memorySetFastAllocatedSize(ULO fastallocatedsize);
extern ULO memoryGetFastAllocatedSize(void);
extern BOOLE memorySetSlowSize(ULO bogosize);
extern ULO memoryGetSlowSize(void);
extern BOOLE memorySetUseAutoconfig(BOOLE useautoconfig);
extern BOOLE memoryGetUseAutoconfig(void);
extern BOOLE memorySetAddress32Bit(BOOLE address32bit);
extern BOOLE memoryGetAddress32Bit(void);
extern BOOLE memorySetKickImage(STR *kickimage);
extern STR *memoryGetKickImage(void);
extern void memorySetKey(STR *key);
extern STR *memoryGetKey(void);
extern BOOLE memoryGetKickImageOK(void);
/* Derived from memory configuration */
extern ULO memoryGetKickImageBaseBank(void);
extern ULO memoryGetKickImageVersion(void);
extern ULO memoryInitialPC(void);
extern ULO memoryInitialSP(void);
/* Kickstart load error handling */
#define MEMORY_ROM_ERROR_SIZE 0
#define MEMORY_ROM_ERROR_AMIROM_VERSION 1
#define MEMORY_ROM_ERROR_AMIROM_READ 2
#define MEMORY_ROM_ERROR_KEYFILE 3
#define MEMORY_ROM_ERROR_EXISTS_NOT 4
#define MEMORY_ROM_ERROR_FILE 5
#define MEMORY_ROM_ERROR_KICKDISK_NOT 6
#define MEMORY_ROM_ERROR_CHECKSUM 7
#define MEMORY_ROM_ERROR_KICKDISK_SUPER 8
#define MEMORY_ROM_ERROR_BAD_BANK 9
/* Global variables */
extern UBY memory_chip[];
extern UBY *memory_fast;
extern UBY memory_slow[];
extern UBY memory_kick[];
extern ULO memory_chipsize;
extern UBY memory_emem[];
extern ULO intenar,intena,intreq;
extern ULO potgor;
extern ULO memory_fault_address;
extern BOOLE memory_fault_read;
#endif