From abe8b9236b8e3d0fb6886ff348c15503b82d57c5 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Thu, 4 Dec 2014 16:09:18 -0500 Subject: [PATCH] updates to match current fellow cpu code --- cpu/CpuIntegration.c | 105 +---- cpu/CpuModule.c | 4 +- cpu/CpuModule.h | 4 +- cpu/CpuModule_Disassembler.c | 88 ++-- cpu/CpuModule_EffectiveAddress.c | 2 +- cpu/CpuModule_Exceptions.c | 46 +- cpu/CpuModule_Flags.c | 2 +- cpu/CpuModule_Instructions.c | 691 +++++++++++++++---------------- cpu/CpuModule_Internal.h | 5 +- cpu/CpuModule_InternalState.c | 19 +- cpu/CpuModule_Interrupts.c | 40 +- cpu/CpuModule_Logging.c | 2 +- cpu/CpuModule_StackFrameGen.c | 2 +- cpu/defs.h | 1 + 14 files changed, 483 insertions(+), 528 deletions(-) diff --git a/cpu/CpuIntegration.c b/cpu/CpuIntegration.c index 8b24798..57590b7 100644 --- a/cpu/CpuIntegration.c +++ b/cpu/CpuIntegration.c @@ -1,4 +1,4 @@ -/* @(#) $Id: CpuIntegration.c,v 1.10 2013/01/08 19:17:33 peschau Exp $ */ +/* @(#) $Id: CpuIntegration.c,v 1.10 2013-01-08 19:17:33 peschau Exp $ */ /*=========================================================================*/ /* Fellow */ /* Initialization of 68000 core */ @@ -29,15 +29,12 @@ #include "CpuModule.h" #include "CpuIntegration.h" #include "CpuModule_Internal.h" -//#include "bus.h" -//#include "fileops.h" - +#include "bus.h" +#include "fileops.h" +#include "interrupt.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; +ULO cpu_integration_chip_interrupt_number; /* Cycles spent by chips (Blitter) as a result of an instruction */ static ULO cpu_integration_chip_cycles; @@ -75,7 +72,7 @@ static ULO cpuIntegrationGetSpeedMultiplier(void) return cpu_integration_speed_multiplier; } -static void cpuIntegrationCalculateMultiplier(void) +void cpuIntegrationCalculateMultiplier(void) { ULO multiplier = 12; @@ -144,65 +141,25 @@ ULO cpuIntegrationGetChipSlowdown(void) return cpu_integration_chip_slowdown; } -ULO cpuIntegrationGetChipIrqToIntLevel(ULO chip_irq) +void cpuIntegrationSetChipInterruptNumber(ULO chip_interrupt_number) { - return cpu_integration_int_to_level[chip_irq]; + cpu_integration_chip_interrupt_number = chip_interrupt_number; } -void cpuIntegrationSetIrqSource(ULO irq_source) +ULO cpuIntegrationGetChipInterruptNumber(void) { - cpu_integration_irq_source = irq_source; + return cpu_integration_chip_interrupt_number; } -ULO cpuIntegrationGetIrqSource(void) +// A wrapper for cpuSetIrqLevel that restarts the +// scheduling of cpu events if the cpu was stoppped +void cpuIntegrationSetIrqLevel(ULO new_interrupt_level, ULO chip_interrupt_number) { - 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) + if (cpuSetIrqLevel(new_interrupt_level)) { - 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; - } - } - } + cpuEvent.cycle = busGetCycle(); } - return FALSE; -} - -void cpuIntegrationCheckPendingInterrupts(void) -{ - cpuCheckPendingInterrupts(); + cpuIntegrationSetChipInterruptNumber(chip_interrupt_number); } /*=========================================*/ @@ -244,7 +201,7 @@ void cpuInstructionLogOpen(void) void cpuIntegrationPrintBusCycle(void) { - fprintf(CPUINSTRUCTIONLOG, "%d:%.5d ", bus.frame_no, bus.cycle); + fprintf(CPUINSTRUCTIONLOG, "%I64u:%.5u ", bus.frame_no, bus.cycle); } void cpuIntegrationInstructionLogging(void) @@ -293,37 +250,13 @@ void cpuIntegrationExceptionLogging(STR *description, ULO original_pc, UWO opcod 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())); + fprintf(CPUINSTRUCTIONLOG, "Irq %u to %.6X (%s)\n", level, vector_address, interruptGetInterruptName(cpuIntegrationGetChipInterruptNumber())); } #endif @@ -396,7 +329,7 @@ void cpuIntegrationSetDefaultConfig(void) cpuIntegrationSetChipSlowdown(1); cpuIntegrationSetSpeed(4); - cpuSetCheckPendingInterruptsFunc(cpuIntegrationCheckPendingInterruptsFunc); + cpuSetCheckPendingInterruptsFunc(interruptRaisePending); cpuSetMidInstructionExceptionFunc(cpuIntegrationMidInstructionExceptionFunc); cpuSetResetExceptionFunc(cpuIntegrationResetExceptionFunc); diff --git a/cpu/CpuModule.c b/cpu/CpuModule.c index db33e59..b2bfa06 100644 --- a/cpu/CpuModule.c +++ b/cpu/CpuModule.c @@ -1,4 +1,4 @@ -/* @(#) $Id: CpuModule.c,v 1.7 2012/08/12 16:51:02 peschau Exp $ */ +/* @(#) $Id: CpuModule.c,v 1.7 2012-08-12 16:51:02 peschau Exp $ */ /*=========================================================================*/ /* Fellow */ /* Initialization of 68000 core */ @@ -48,7 +48,7 @@ void cpuClearEverything(void) cpuSetSfc(0); cpuSetDfc(0); cpuSetIrqLevel(0); - cpuSetIrqAddress(0); + cpuSetRaiseInterrupt(FALSE); cpuSetStop(FALSE); cpuSetInstructionTime(0); cpuSetOriginalPC(0); diff --git a/cpu/CpuModule.h b/cpu/CpuModule.h index 2d3e956..52035c8 100644 --- a/cpu/CpuModule.h +++ b/cpu/CpuModule.h @@ -18,7 +18,7 @@ extern void cpuSetFLineExceptionFunc(cpuLineExceptionFunc func); typedef BOOLE (*cpuCheckPendingInterruptsFunc)(void); extern void cpuSetCheckPendingInterruptsFunc(cpuCheckPendingInterruptsFunc func); extern void cpuCheckPendingInterrupts(void); -extern void cpuSetUpInterrupt(void); +void cpuSetUpInterrupt(ULO new_interrupt_level); extern void cpuInitializeFromNewPC(ULO new_pc); @@ -77,7 +77,7 @@ extern ULO cpuGetInitialSP(void); extern ULO cpuGetInstructionTime(void); -extern void cpuSetIrqLevel(ULO irq_level); +extern BOOLE cpuSetIrqLevel(ULO new_interrupt_level); extern ULO cpuGetIrqLevel(void); extern void cpuSetIrqAddress(ULO irq_address); diff --git a/cpu/CpuModule_Disassembler.c b/cpu/CpuModule_Disassembler.c index a176802..01df00d 100644 --- a/cpu/CpuModule_Disassembler.c +++ b/cpu/CpuModule_Disassembler.c @@ -150,7 +150,7 @@ static ULO cpuDis05(ULO regno, ULO pcp, STR *sdata, STR *soperands) ULO disp = memoryReadWord(pcp); cpuDisWordAppend(disp, sdata); - sprintf(cpuDisEoS(soperands), "$%.4X(A%1d)", disp, regno); + sprintf(cpuDisEoS(soperands), "$%.4X(A%1u)", disp, regno); return pcp + 2; } @@ -168,22 +168,22 @@ static ULO cpuDis06Brief(ULO regno, ULO pcp, ULO ext, BOOLE is_pc_indirect, STR { if (!is_pc_indirect) { - sprintf(cpuDisEoS(soperands), "$%.2X(A%1d,%c%1d.%c)", offset, regno, indexregtype, indexregno, indexsize); + sprintf(cpuDisEoS(soperands), "$%.2X(A%1u,%c%1u.%c)", offset, regno, indexregtype, indexregno, indexsize); } else { - sprintf(cpuDisEoS(soperands), "$%.2X(PC,%c%1d.%c)", offset, indexregtype, indexregno, indexsize); + sprintf(cpuDisEoS(soperands), "$%.2X(PC,%c%1u.%c)", offset, indexregtype, indexregno, indexsize); } } else { if (!is_pc_indirect) { - sprintf(cpuDisEoS(soperands), "$%.2X(A%1d,%c%1d.%c%s)", offset, regno, indexregtype, indexregno, indexsize, scale[scalefactor]); + sprintf(cpuDisEoS(soperands), "$%.2X(A%1u,%c%1u.%c%s)", offset, regno, indexregtype, indexregno, indexsize, scale[scalefactor]); } else { - sprintf(cpuDisEoS(soperands), "$%.2X(PC,%c%1d.%c%s)", offset, indexregtype, indexregno, indexsize, scale[scalefactor]); + sprintf(cpuDisEoS(soperands), "$%.2X(PC,%c%1u.%c%s)", offset, indexregtype, indexregno, indexsize, scale[scalefactor]); } } return pcp; @@ -250,7 +250,7 @@ static ULO cpuDis06Extended(ULO regno, ULO pcp, ULO ext, BOOLE is_pc_indirect, S } else { - sprintf(baseregstr, "A%d", regno); + sprintf(baseregstr, "A%u", regno); } } @@ -262,7 +262,7 @@ static ULO cpuDis06Extended(ULO regno, ULO pcp, ULO ext, BOOLE is_pc_indirect, S } else { /* Index included */ - sprintf(indexstr, "%c%d.%c%s", indexregtype, indexregno, indexsize, scale[scalefactor]); + sprintf(indexstr, "%c%u.%c%s", indexregtype, indexregno, indexsize, scale[scalefactor]); } /* Base displacement */ @@ -373,11 +373,9 @@ static ULO cpuDis71(ULO pcp, STR *sdata, STR *soperands) static ULO cpuDis72(ULO pcp, STR *sdata, STR *soperands) { ULO disp = memoryReadWord(pcp); - ULO ea = pcp + disp; - if (disp & 0x8000) ea += 0xffff0000; cpuDisWordAppend(disp, sdata); - sprintf(cpuDisEoS(soperands), "$%.4X ; $%.4X(PC)", ea, disp); + sprintf(cpuDisEoS(soperands), "$%.4X(PC)", disp); return pcp + 2; } @@ -563,7 +561,7 @@ static ULO cpuDisArith4(ULO prc, UWO opc, ULO nr, STR *sdata, STR *sinstruction, imm = 8; } sprintf(sinstruction, "%sQ.%c", cpu_dis_anr[nr], cpuDisSizeChar(size)); - sprintf(soperands, "#$%.1d,", imm); + sprintf(soperands, "#$%.1u,", imm); return cpuDisAdrMode(eamode, eareg, prc + 2, size, sdata, soperands); } @@ -619,12 +617,12 @@ static ULO cpuDisShift(ULO prc, UWO opc, ULO nr, STR *sdata, STR *sinstruction, dreg = 8; } sprintf(sinstruction, "%s%c.%c", cpu_dis_shnr[nr], rl, sc); - sprintf(soperands, "#$%1X,D%1d", dreg, eareg); + sprintf(soperands, "#$%1X,D%1u", dreg, eareg); } else { sprintf(sinstruction, "%s%c.%c", cpu_dis_shnr[nr], rl, sc); - sprintf(soperands, "D%1d,D%1d", dreg, eareg); + sprintf(soperands, "D%1u,D%1u", dreg, eareg); } prc += 2; } @@ -815,7 +813,7 @@ static ULO cpuDisDBcc(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sope adr = (offset > 32767) ? (prc + offset - 65536) : (prc + offset); cpuDisWordAppend(offset, sdata); sprintf(sinstruction, "DB%s", (bratype == 0) ? "T" : ((bratype == 1) ? "F" : cpu_dis_btab[bratype])); - sprintf(soperands, "D%1d,$%6.6X", cpuDisGetSourceRegister(opc), adr); + sprintf(soperands, "D%1u,$%6.6X", cpuDisGetSourceRegister(opc), adr); return prc + 2; } @@ -851,7 +849,7 @@ static ULO cpuDisExg(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *soper static ULO cpuDisExt(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *soperands) { sprintf(sinstruction, "EXT.%c", (cpuDisGetBit(opc, 6) == 0) ? 'W' : 'L'); - sprintf(soperands, "D%d", cpuDisGetSourceRegister(opc)); + sprintf(soperands, "D%u", cpuDisGetSourceRegister(opc)); return prc + 2; } @@ -876,7 +874,7 @@ static ULO cpuDisLink(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sope cpuDisWordAppend(imm, sdata); sprintf(sinstruction, "LINK"); - sprintf(soperands, "A%1d,#$%.4X", cpuDisGetSourceRegister(opc), imm); + sprintf(soperands, "A%1u,#$%.4X", cpuDisGetSourceRegister(opc), imm); return prc + 4; } @@ -1025,11 +1023,11 @@ static ULO cpuDisMovep(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sop sprintf(sinstruction, "MOVEP.%c", sizech); if (to_mem) { - sprintf(soperands, "D%1d,$%.4X(A%d)", dataregno, disp, adrregno); + sprintf(soperands, "D%1u,$%.4X(A%1u)", dataregno, disp, adrregno); } else { - sprintf(soperands, "$%.4X(A%1d),D%1d,", disp, adrregno, dataregno); + sprintf(soperands, "$%.4X(A%1u),D%1u", disp, adrregno, dataregno); } return prc + 4; } @@ -1037,7 +1035,7 @@ static ULO cpuDisMovep(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sop static ULO cpuDisMoveq(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *soperands) { sprintf(sinstruction, "MOVEQ.L"); - sprintf(soperands, "#$%8.8X,D%d", cpuDisGetLowByteSignExtend(opc), cpuDisGetDestinationRegister(opc)); + sprintf(soperands, "#$%8.8X,D%u", cpuDisGetLowByteSignExtend(opc), cpuDisGetDestinationRegister(opc)); return prc + 2; } @@ -1224,31 +1222,31 @@ static ULO cpuDisBf(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sopera sprintf(sinstruction, "BF%s", cpu_dis_bftxt[n]); if (n == 7) { - sprintf(stmp, "D%d,", (ext >> 12) & 7); + sprintf(stmp, "D%u,", (ext >> 12) & 7); strcat(soperands, stmp); } prc = cpuDisAdrMode(eamode, eareg, prc + 4, 16, sdata, soperands); if (ext & 0x800) { - sprintf(stmp, "{D%d:", offset & 7); + sprintf(stmp, "{D%u:", offset & 7); } else { - sprintf(stmp, "{%d:", offset); + sprintf(stmp, "{%u:", offset); } strcat(soperands, stmp); if (ext & 0x20) { - sprintf(stmp, "D%d}", width & 7); + sprintf(stmp, "D%u}", width & 7); } else { - sprintf(stmp, "%d}", width); + sprintf(stmp, "%u}", width); } strcat(soperands, stmp); if ((n == 1) || (n == 3) || (n == 7)) { - sprintf(stmp, ",D%d", (ext >> 12) & 7); + sprintf(stmp, ",D%u", (ext >> 12) & 7); strcat(soperands, stmp); } return prc; @@ -1268,7 +1266,7 @@ static ULO cpuDisCas(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *soper sprintf(sinstruction, "CAS2.%c", cpuDisSizeChar(size)); sprintf(soperands, - "D%d:D%d,D%d:D%d,(%s%d):(%s%d)", + "D%u:D%u,D%u:D%u,(%s%u):(%s%u)", ext & 7, ext2 & 7, (ext >> 6) & 7, @@ -1282,7 +1280,7 @@ static ULO cpuDisCas(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *soper else { sprintf(sinstruction, "CAS.%c", cpuDisSizeChar(size)); - sprintf(soperands, "D%d,D%d,", ext & 7, (ext >> 6) & 7); + sprintf(soperands, "D%u,D%u,", ext & 7, (ext >> 6) & 7); prc = cpuDisAdrMode(cpuDisGetEaNo(cpuDisGetSourceMode(opc), eareg), eareg, prc + 4, size, sdata, soperands); } return prc; @@ -1308,7 +1306,7 @@ static ULO cpuDisChk2(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sope cpuDisWordAppend(ext, sdata); sprintf(sinstruction, "%s.%c", (ext & 0x800) ? "CHK2" : "CMP2", cpuDisSizeChar(size)); prc = cpuDisAdrMode(cpuDisGetEaNo(cpuDisGetSourceMode(opc), eareg), eareg, prc + 4, size, sdata, soperands); - sprintf(stmp, ",%s%d", (ext & 0x8000) ? "A" : "D", (ext>>12) & 7); + sprintf(stmp, ",%s%u", (ext & 0x8000) ? "A" : "D", (ext>>12) & 7); strcat(soperands, stmp); return prc; } @@ -1328,11 +1326,11 @@ static ULO cpuDisDivl(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sope prc = cpuDisAdrMode(cpuDisGetEaNo(cpuDisGetSourceMode(opc), eareg), eareg, prc + 4, 32, sdata, soperands); if (ext & 0x400) { - sprintf(stmp, ",D%d:D%d", dr, dq); + sprintf(stmp, ",D%u:D%u", dr, dq); } else { - sprintf(stmp, ",D%d", dq); + sprintf(stmp, ",D%u", dq); } strcat(soperands, stmp); return prc; @@ -1341,7 +1339,7 @@ static ULO cpuDisDivl(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sope static ULO cpuDisExtb(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *soperands) { sprintf(sinstruction, "EXTB.L"); - sprintf(soperands, "D%d", cpuDisGetSourceRegister(opc)); + sprintf(soperands, "D%u", cpuDisGetSourceRegister(opc)); return prc + 2; } @@ -1350,7 +1348,7 @@ static ULO cpuDisLinkl(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sop ULO disp = memoryReadLong(prc + 2); cpuDisLongAppend(disp, sdata); sprintf(sinstruction, "LINK.L"); - sprintf(soperands, "A%d, #$%.8X", cpuDisGetSourceRegister(opc), disp); + sprintf(soperands, "A%u, #$%.8X", cpuDisGetSourceRegister(opc), disp); return prc + 6; } @@ -1372,7 +1370,7 @@ static ULO cpuDisMovec(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sop sprintf(sinstruction, "MOVEC.L"); if (opc & 1) { /* To control register */ - sprintf(stmp, "%s%d,", (extw & 0x8000) ? "A" : "D", (extw>>12) & 7); + sprintf(stmp, "%s%u,", (extw & 0x8000) ? "A" : "D", (extw>>12) & 7); strcat(soperands, stmp); } creg = extw & 0xfff; @@ -1410,7 +1408,7 @@ static ULO cpuDisMovec(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sop } if (!(opc & 1)) { /* From control register */ - sprintf(stmp, ",%s%d", (extw & 0x8000) ? "A":"D", (extw >> 12) & 7); + sprintf(stmp, ",%s%u", (extw & 0x8000) ? "A":"D", (extw >> 12) & 7); strcat(soperands, stmp); } return prc + 4; @@ -1427,13 +1425,13 @@ static ULO cpuDisMoves(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sop sprintf(sinstruction, "MOVES.%c", cpuDisSizeChar(size)); if (ext & 0x800) { - sprintf(stmp, "%s%d,", (ext & 0x8000) ? "A" : "D", (ext >> 12) & 7); + sprintf(stmp, "%s%u,", (ext & 0x8000) ? "A" : "D", (ext >> 12) & 7); strcat(soperands, stmp); } prc = cpuDisAdrMode(cpuDisGetEaNo(cpuDisGetSourceMode(opc), eareg), eareg, prc + 4, size, sdata, soperands); if (!(ext & 0x800)) { - sprintf(stmp, ",%s%d", (ext & 0x8000) ? "A" : "D", (ext >> 12) & 7); + sprintf(stmp, ",%s%u", (ext & 0x8000) ? "A" : "D", (ext >> 12) & 7); strcat(soperands, stmp); } return prc; @@ -1454,11 +1452,11 @@ static ULO cpuDisMull(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sope prc = cpuDisAdrMode(cpuDisGetEaNo(cpuDisGetSourceMode(opc), eareg), eareg, prc + 4, 32, sdata, soperands); if (ext & 0x400) { - sprintf(stmp, ",D%d:D%d", dh, dl); + sprintf(stmp, ",D%u:D%u", dh, dl); } else { - sprintf(stmp, ",D%d", dl); + sprintf(stmp, ",D%u", dl); } strcat(soperands, stmp); return prc; @@ -1491,12 +1489,12 @@ static void cpuDisPflush030PrintFc(STR *soperands, ULO fcode) else if (fcode == 1) strcat(soperands, "DFC,"); else if ((fcode & 0x18) == 8) { - sprintf(stmp, "D%d,", fcode & 7); + sprintf(stmp, "D%u,", fcode & 7); strcat(soperands, stmp); } else if ((fcode & 0x18) == 0x10) { - sprintf(stmp, "#%d,", fcode & 7); + sprintf(stmp, "#%u,", fcode & 7); strcat(soperands, stmp); } } @@ -1566,11 +1564,11 @@ static ULO cpuDisPflush040(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR { case 0: sprintf(sinstruction, "PFLUSHN"); - sprintf(soperands, "(A%d)", reg); + sprintf(soperands, "(A%u)", reg); break; case 1: sprintf(sinstruction, "PFLUSH"); - sprintf(soperands, "(A%d)", reg); + sprintf(soperands, "(A%u)", reg); break; case 2: sprintf(sinstruction, "PFLUSHAN"); @@ -1590,7 +1588,7 @@ static ULO cpuDisPtest040(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR * ULO rw = cpuDisGetBit(opc, 5); sprintf(sinstruction, "PTEST%c", (rw) ? 'R' : 'W'); - sprintf(soperands, "(A%d)", reg); + sprintf(soperands, "(A%u)", reg); return prc + 2; } @@ -1652,14 +1650,14 @@ static ULO cpuDisCallm(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *sop ULO eareg = cpuDisGetSourceRegister(opc); ULO ext = memoryReadWord(prc + 2); cpuDisWordAppend(ext, sdata); - sprintf(soperands, "#%d,", ext & 0xff); + sprintf(soperands, "#%u,", ext & 0xff); return cpuDisAdrMode(cpuDisGetEaNo(cpuDisGetSourceMode(opc), eareg), eareg, prc + 4, 16, sdata, soperands); } static ULO cpuDisRtm(ULO prc, UWO opc, STR *sdata, STR *sinstruction, STR *soperands) { sprintf(sinstruction, "RTM"); - sprintf(soperands, "%c%d", (opc & 8) ? 'A':'D', cpuDisGetSourceRegister(opc)); + sprintf(soperands, "%c%u", (opc & 8) ? 'A':'D', cpuDisGetSourceRegister(opc)); return prc + 2; } diff --git a/cpu/CpuModule_EffectiveAddress.c b/cpu/CpuModule_EffectiveAddress.c index 2f4ae64..e40331f 100644 --- a/cpu/CpuModule_EffectiveAddress.c +++ b/cpu/CpuModule_EffectiveAddress.c @@ -1,4 +1,4 @@ -/* @(#) $Id: CpuModule_EffectiveAddress.c,v 1.3 2012/07/15 22:20:35 peschau Exp $ */ +/* @(#) $Id: CpuModule_EffectiveAddress.c,v 1.3 2012-07-15 22:20:35 peschau Exp $ */ /*=========================================================================*/ /* Fellow */ /* CPU 68k effective address calculation functions */ diff --git a/cpu/CpuModule_Exceptions.c b/cpu/CpuModule_Exceptions.c index b2d803d..eda203e 100644 --- a/cpu/CpuModule_Exceptions.c +++ b/cpu/CpuModule_Exceptions.c @@ -1,4 +1,4 @@ -/* @(#) $Id: CpuModule_Exceptions.c,v 1.5 2012/08/12 16:51:02 peschau Exp $ */ +/* @(#) $Id: CpuModule_Exceptions.c,v 1.5 2012-08-12 16:51:02 peschau Exp $ */ /*=========================================================================*/ /* Fellow */ /* CPU 68k exception handling functions */ @@ -94,26 +94,54 @@ static STR *cpuGetExceptionName(ULO vector_offset) Sets up an exception ===============================================*/ +void cpuExceptionFail(BOOLE executejmp) +{ + // Avoid endless loop that will crash the emulator. + // The (odd) address error exception vector contained an odd address. + cpuCallResetExceptionFunc(); + cpuHardReset(); + cpuSetInstructionTime(132); + if (executejmp) + { + cpuCallMidInstructionExceptionFunc(); // Supposed to be doing setjmp/longjmp back to machine emulator code + } +} + void cpuThrowException(ULO vector_offset, ULO pc, BOOLE executejmp) { ULO vector_address; + BOOLE is_address_error_on_sub_020 = (cpuGetModelMajor() < 2 && vector_offset == 0xc); + BOOLE stack_is_even = !(cpuGetAReg(7) & 1); + BOOLE vbr_is_even = !(cpuGetVbr() & 1); + + if ((is_address_error_on_sub_020 && !stack_is_even) || !vbr_is_even) + { + cpuExceptionFail(executejmp); + return; + } #ifdef CPU_INSTRUCTION_LOGGING cpuCallExceptionLoggingFunc(cpuGetExceptionName(vector_offset), cpuGetOriginalPC(), cpuGetCurrentOpcode()); #endif - cpuActivateSSP(); + cpuActivateSSP(); + + stack_is_even = !(cpuGetAReg(7) & 1); + + if (is_address_error_on_sub_020 && !stack_is_even) + { + cpuExceptionFail(executejmp); + return; + } + cpuStackFrameGenerate((UWO) vector_offset, pc); // read a memory position vector_address = memoryReadLong(cpuGetVbr() + vector_offset); - if (cpuGetModelMajor() < 2 && vector_address & 0x1 && vector_offset == 0xc) + if (is_address_error_on_sub_020 && vector_address & 1) { - // Avoid endless loop that will crash the emulator. - // The (odd) address error exception vector contained an odd address. - cpuCallResetExceptionFunc(); - cpuHardReset(); - cpuSetInstructionTime(132); + cpuExceptionFail(executejmp); + return; } else { @@ -192,7 +220,7 @@ void cpuThrowTraceException(void) void cpuThrowAddressErrorException(void) { - cpuThrowException(0xc, cpuGetPC(), TRUE); + cpuThrowException(0xc, cpuGetPC() - 2, TRUE); } /*=================*/ diff --git a/cpu/CpuModule_Flags.c b/cpu/CpuModule_Flags.c index f1859e2..aaca6b9 100644 --- a/cpu/CpuModule_Flags.c +++ b/cpu/CpuModule_Flags.c @@ -1,4 +1,4 @@ -/* @(#) $Id: CpuModule_Flags.c,v 1.3 2011/07/18 17:22:55 peschau Exp $ */ +/* @(#) $Id: CpuModule_Flags.c,v 1.3 2011-07-18 17:22:55 peschau Exp $ */ /*=========================================================================*/ /* Fellow */ /* 68000 flag and condition code handling */ diff --git a/cpu/CpuModule_Instructions.c b/cpu/CpuModule_Instructions.c index 2d4101b..0a9e178 100644 --- a/cpu/CpuModule_Instructions.c +++ b/cpu/CpuModule_Instructions.c @@ -1,4 +1,4 @@ -/* @(#) $Id: CpuModule_Instructions.c,v 1.12 2013/01/08 18:55:48 peschau Exp $ */ +/* @(#) $Id: CpuModule_Instructions.c,v 1.12 2013-01-08 18:55:48 peschau Exp $ */ /*=========================================================================*/ /* Fellow */ /* CPU 68k functions */ @@ -105,40 +105,55 @@ static __inline void cpuTscAfter(LLO* a, LLO* b, ULO* c) /* Maintains the integrity of the super/user state */ -void cpuUpdateSr(ULO new_sr) { - BOOLE supermode_was_set = cpuGetFlagSupervisor(); - BOOLE master_was_set = (cpuGetModelMajor() >= 2) && cpuGetFlagMaster(); +void cpuUpdateSr(ULO new_sr) +{ + BOOLE supermode_was_set = cpuGetFlagSupervisor(); + BOOLE master_was_set = (cpuGetModelMajor() >= 2) && cpuGetFlagMaster(); - BOOLE supermode_is_set = !!(new_sr & 0x2000); - BOOLE master_is_set = (cpuGetModelMajor() >= 2) && !!(new_sr & 0x1000); + BOOLE supermode_is_set = !!(new_sr & 0x2000); + BOOLE master_is_set = (cpuGetModelMajor() >= 2) && !!(new_sr & 0x1000); - ULO runlevel_old = (cpuGetSR() >> 8) & 7; - ULO runlevel_new = (new_sr >> 8) & 7; + ULO runlevel_old = (cpuGetSR() >> 8) & 7; + ULO runlevel_new = (new_sr >> 8) & 7; - if (!supermode_was_set) - cpuSetUspDirect(cpuGetAReg(7)); - else if (master_was_set) - cpuSetMspDirect(cpuGetAReg(7)); - else - cpuSetSspDirect(cpuGetAReg(7)); + if (!supermode_was_set) + { + cpuSetUspDirect(cpuGetAReg(7)); + } + else if (master_was_set) + { + cpuSetMspDirect(cpuGetAReg(7)); + } + else + { + cpuSetSspDirect(cpuGetAReg(7)); + } - if (!supermode_is_set) - cpuSetAReg(7, cpuGetUspDirect()); - else if (master_is_set) - cpuSetAReg(7, cpuGetMspDirect()); - else - cpuSetAReg(7, cpuGetSspDirect()); + if (!supermode_is_set) + { + cpuSetAReg(7, cpuGetUspDirect()); + } + else if (master_is_set) + { + cpuSetAReg(7, cpuGetMspDirect()); + } + else + { + cpuSetAReg(7, cpuGetSspDirect()); + } - cpuSetSR(new_sr); + cpuSetSR(new_sr); - if (runlevel_old != runlevel_new) { - cpuCallCheckPendingInterruptsFunc(); - } + if (runlevel_old != runlevel_new) + { + cpuCheckPendingInterrupts(); + } } -static void cpuIllegal(void) { - UWO opcode = memoryReadWord(cpuGetPC() - 2); - if ((opcode & 0xf000) == 0xf000) +static void cpuIllegal(void) +{ + UWO opcode = memoryReadWord(cpuGetPC() - 2); + if ((opcode & 0xf000) == 0xf000) { if (cpu_f_line_exception_func) { @@ -148,8 +163,8 @@ static void cpuIllegal(void) { } else { - cpuThrowFLineException(); - } + cpuThrowFLineException(); + } } else if ((opcode & 0xa000) == 0xa000) { @@ -1059,9 +1074,9 @@ static void cpuMulL(ULO src1, UWO extension) { BOOLE o; if (result >= 0) - o = (result & 0xffffffff00000000) != 0; + o = (result & 0xffffffff00000000) != 0; else - o = (result & 0xffffffff00000000) != 0xffffffff00000000; + o = (result & 0xffffffff00000000) != 0xffffffff00000000; cpuSetDReg(dl, (ULO)result); cpuSetFlagsNZVC(result == 0, result < 0, o, FALSE); } @@ -1079,7 +1094,7 @@ static void cpuMulL(ULO src1, UWO extension) else // 32bx32b=32b { cpuSetDReg(dl, (ULO)result); - cpuSetFlagsNZVC(result == 0, !!(result & 0x8000000000000000), (result >> 32) != 0, FALSE); + cpuSetFlagsNZVC(result == 0, !!(result & 0x80000000), (result >> 32) != 0, FALSE); } } cpuSetInstructionTime(4); @@ -1097,7 +1112,7 @@ void cpuCreateMuluTimeTable(void) j = 0; for (k = 0; k < 8; k++) if (((i>>k) & 1) == 1) - j++; + j++; cpuMuluTime[i] = (UBY) j*2; } } @@ -1111,7 +1126,7 @@ void cpuCreateMulsTimeTable(void) j = 0; for (k = 0; k < 9; k++) if ((((i>>k) & 3) == 1) || (((i>>k) & 3) == 2)) - j++; + j++; cpuMulsTime[i] = (UBY) j*2; } } @@ -1229,15 +1244,15 @@ static void cpuDivL(ULO divisor, ULO ext) if (y_signed < 0) { - y = (ULL) -y_signed; - resultsigned = !resultsigned; + y = (ULL) -y_signed; + resultsigned = !resultsigned; } else y = y_signed; if (x_signed < 0) { - x = (ULL) -x_signed; - resultsigned = !resultsigned; - restsigned = TRUE; + x = (ULL) -x_signed; + resultsigned = !resultsigned; + restsigned = TRUE; } else x = (ULL) x_signed; } @@ -1255,30 +1270,30 @@ static void cpuDivL(ULO divisor, ULO ext) { if ((resultsigned && result > 0x80000000) || (!resultsigned && result > 0x7fffffff)) { - /* Overflow */ - cpuSetFlagsVC(TRUE, FALSE); + /* Overflow */ + cpuSetFlagsVC(TRUE, FALSE); } else { - LLO result_signed = (resultsigned) ? (-(LLO)result) : ((LLO)result); - LLO rest_signed = (restsigned) ? (-(LLO)rest) : ((LLO)rest); - cpuSetDReg(dr_reg, (ULO) rest_signed); - cpuSetDReg(dq_reg, (ULO) result_signed); - cpuSetFlagsNZ00NewL((ULO) result_signed); + LLO result_signed = (resultsigned) ? (-(LLO)result) : ((LLO)result); + LLO rest_signed = (restsigned) ? (-(LLO)rest) : ((LLO)rest); + cpuSetDReg(dr_reg, (ULO) rest_signed); + cpuSetDReg(dq_reg, (ULO) result_signed); + cpuSetFlagsNZ00NewL((ULO) result_signed); } } else { if (result > 0xffffffff) { - /* Overflow */ - cpuSetFlagsVC(TRUE, FALSE); + /* Overflow */ + cpuSetFlagsVC(TRUE, FALSE); } else { - cpuSetDReg(dr_reg, (ULO) rest); - cpuSetDReg(dq_reg, (ULO) result); - cpuSetFlagsNZ00NewL((ULO) result); + cpuSetDReg(dr_reg, (ULO) rest); + cpuSetDReg(dq_reg, (ULO) result); + cpuSetFlagsNZ00NewL((ULO) result); } } } @@ -1465,10 +1480,16 @@ static UBY cpuAslB(UBY dst, ULO sh, ULO cycles) { UBY mask = 0xff << (7-sh); UBY out = dst & mask; - BOOLE n; res = ((BYT)dst) << sh; - n = cpuMsbB(res); - cpuSetFlagsShift(cpuIsZeroB(res), n, dst & (0x80>>(sh-1)), (cpuMsbB(dst)) ? (out != mask) : (out != 0)); + + // Overflow calculation: + // 1. The msb of the result and original are different + // 2. Or the bits shifted out were not all the same as the msb of the original + BOOLE n_result = cpuMsbB(res); + BOOLE n_original = cpuMsbB(dst); + BOOLE msb_changed = (n_result != n_original) || ((n_original) ? (out != mask) : (out != 0)); + + cpuSetFlagsShift(cpuIsZeroB(res), n_result, dst & (0x80>>(sh-1)), msb_changed); } cpuSetInstructionTime(cycles + sh*2); return (UBY) res; @@ -1495,10 +1516,16 @@ static UWO cpuAslW(UWO dst, ULO sh, ULO cycles) { UWO mask = 0xffff << (15-sh); UWO out = dst & mask; - BOOLE n; res = ((WOR)dst) << sh; - n = cpuMsbW(res); - cpuSetFlagsShift(cpuIsZeroW(res), n, dst & (0x8000>>(sh-1)), (cpuMsbW(dst)) ? (out != mask) : (out != 0)); + + // Overflow calculation: + // 1. The msb of the result and original are different + // 2. Or the bits shifted out were not all the same as the msb of the original + BOOLE n_result = cpuMsbW(res); + BOOLE n_original = cpuMsbW(dst); + BOOLE msb_changed = (n_result != n_original) || ((n_original) ? (out != mask) : (out != 0)); + + cpuSetFlagsShift(cpuIsZeroW(res), n_result, dst & (0x8000>>(sh-1)), msb_changed); } cpuSetInstructionTime(cycles + sh*2); return (UWO) res; @@ -1525,10 +1552,16 @@ static ULO cpuAslL(ULO dst, ULO sh, ULO cycles) { ULO mask = 0xffffffff << (31-sh); ULO out = dst & mask; - BOOLE n; res = ((LON)dst) << sh; - n = cpuMsbL(res); - cpuSetFlagsShift(cpuIsZeroL(res), n, dst & (0x80000000>>(sh-1)), (cpuMsbL(dst)) ? (out != mask) : (out != 0)); + + // Overflow calculation: + // 1. The msb of the result and original are different + // 2. Or the bits shifted out were not all the same as the msb of the original + BOOLE n_result = cpuMsbL(res); + BOOLE n_original = cpuMsbL(dst); + BOOLE msb_changed = (n_result != n_original) || ((n_original) ? (out != mask) : (out != 0)); + + cpuSetFlagsShift(cpuIsZeroL(res), n_result, dst & (0x80000000>>(sh-1)), msb_changed); } cpuSetInstructionTime(cycles + sh*2); return (ULO) res; @@ -1909,9 +1942,7 @@ static void cpuReset() static void cpuRtd() { ULO displacement = cpuGetNextWordSignExt(); - - cpuInitializeFromNewPC(memoryReadLong(cpuGetAReg(7))); - + cpuInitializeFromNewPC(memoryReadLong(cpuGetAReg(7))); cpuSetAReg(7, cpuGetAReg(7) + 4 + displacement); cpuSetInstructionTime(4); } @@ -1937,10 +1968,10 @@ static void cpuRte() if (cpuGetModelMajor() > 0) { - ULO frame_type = (memoryReadWord(cpuGetAReg(7)) >> 12) & 0xf; - cpuSetAReg(7, cpuGetAReg(7) + 2); - cpuSetAReg(7, cpuGetAReg(7) + cpuRteStackInc[frame_type]); - redo = (frame_type == 1 && cpuGetModelMajor() >= 2 && cpuGetModelMajor() < 6); + ULO frame_type = (memoryReadWord(cpuGetAReg(7)) >> 12) & 0xf; + cpuSetAReg(7, cpuGetAReg(7) + 2); + cpuSetAReg(7, cpuGetAReg(7) + cpuRteStackInc[frame_type]); + redo = (frame_type == 1 && cpuGetModelMajor() >= 2 && cpuGetModelMajor() < 6); } else redo = FALSE; @@ -2093,12 +2124,12 @@ static void cpuMovemwPre(UWO regs, ULO reg) dstea -= 2; if (cpuGetModelMajor() >= 2 && j == reg) { - ea_reg_seen = TRUE; - ea_reg_ea = dstea; + ea_reg_seen = TRUE; + ea_reg_ea = dstea; } else { - memoryWriteWord(cpuGetRegWord(i, j), dstea); + memoryWriteWord(cpuGetRegWord(i, j), dstea); } cycles += 4; } @@ -2145,12 +2176,12 @@ static void cpuMovemlPre(UWO regs, ULO reg) dstea -= 4; if (cpuGetModelMajor() >= 2 && j == reg) { - ea_reg_seen = TRUE; - ea_reg_ea = dstea; + ea_reg_seen = TRUE; + ea_reg_ea = dstea; } else { - memoryWriteLong(cpuGetReg(i, j), dstea); + memoryWriteLong(cpuGetReg(i, j), dstea); } cycles += 8; } @@ -2194,10 +2225,10 @@ static void cpuMovemwPost(UWO regs, ULO reg) { if (regs & index) { - // Each word, for both data and address registers, is sign-extended before stored. - cpuSetReg(i, j, (ULO)(LON)(WOR) memoryReadWord(dstea)); - dstea += 2; - cycles += 4; + // Each word, for both data and address registers, is sign-extended before stored. + cpuSetReg(i, j, (ULO)(LON)(WOR) memoryReadWord(dstea)); + dstea += 2; + cycles += 4; } index = index << 1; } @@ -2223,9 +2254,9 @@ static void cpuMovemlPost(UWO regs, ULO reg) { if (regs & index) { - cpuSetReg(i, j, memoryReadLong(dstea)); - dstea += 4; - cycles += 8; + cpuSetReg(i, j, memoryReadLong(dstea)); + dstea += 4; + cycles += 8; } index = index << 1; } @@ -2251,10 +2282,10 @@ static void cpuMovemwEa2R(UWO regs, ULO ea, ULO eacycles) { if (regs & index) { - // Each word, for both data and address registers, is sign-extended before stored. - cpuSetReg(i, j, (ULO)(LON)(WOR) memoryReadWord(dstea)); - dstea += 2; - cycles += 4; + // Each word, for both data and address registers, is sign-extended before stored. + cpuSetReg(i, j, (ULO)(LON)(WOR) memoryReadWord(dstea)); + dstea += 2; + cycles += 4; } index = index << 1; } @@ -2279,9 +2310,9 @@ static void cpuMovemlEa2R(UWO regs, ULO ea, ULO eacycles) { if (regs & index) { - cpuSetReg(i, j, memoryReadLong(dstea)); - dstea += 4; - cycles += 8; + cpuSetReg(i, j, memoryReadLong(dstea)); + dstea += 4; + cycles += 8; } index = index << 1; } @@ -2306,9 +2337,9 @@ static void cpuMovemwR2Ea(UWO regs, ULO ea, ULO eacycles) { if (regs & index) { - memoryWriteWord(cpuGetRegWord(i, j), dstea); - dstea += 2; - cycles += 4; + memoryWriteWord(cpuGetRegWord(i, j), dstea); + dstea += 2; + cycles += 4; } index = index << 1; } @@ -2333,9 +2364,9 @@ static void cpuMovemlR2Ea(UWO regs, ULO ea, ULO eacycles) { if (regs & index) { - memoryWriteLong(cpuGetReg(i, j), dstea); - dstea += 4; - cycles += 8; + memoryWriteLong(cpuGetReg(i, j), dstea); + dstea += 4; + cycles += 8; } index = index << 1; } @@ -2622,53 +2653,38 @@ static UBY cpuNbcdB(UBY dst) } // Bit field functions -static void cpuGetBfRegBytes(UBY *bytes, ULO regno) +struct cpuBfData { - bytes[0] = (UBY)(cpuGetDReg(regno) >> 24); - bytes[1] = (UBY)(cpuGetDReg(regno) >> 16); - bytes[2] = (UBY)(cpuGetDReg(regno) >> 8); - bytes[3] = (UBY)cpuGetDReg(regno); -} + LON offset; + ULO width; + ULO normalized_offset; -static void cpuGetBfEaBytes(UBY *bytes, ULO address, ULO count) -{ - ULO i; - for (i = 0; i < count; ++i) - { - bytes[i] = memoryReadByte(address + i); - } -} + ULO base_address; + LON base_address_byte_offset; + ULO base_address_byte_count; -static void cpuSetBfRegBytes(UBY *bytes, ULO regno) -{ - cpuSetDReg(regno, cpuJoinByteToLong(bytes[0], bytes[1], bytes[2], bytes[3])); -} + ULO field; + ULL field_mask; + ULO dn; + ULL field_memory; +}; -static void cpuSetBfEaBytes(UBY *bytes, ULO address, ULO count) -{ - ULO i; - for (i = 0; i < count; ++i) - { - memoryWriteByte(bytes[i], address + i); - } -} - -static LON cpuGetBfOffset(UWO ext, BOOLE offsetIsDr) +static LON cpuGetBfOffset(UWO ext, bool offsetIsDataRegister) { LON offset = (ext >> 6) & 0x1f; - if (offsetIsDr) + if (offsetIsDataRegister) { offset = (LON) cpuGetDReg(offset & 7); } return offset; } -static ULO cpuGetBfWidth(UWO ext, BOOLE widthIsDr) +static ULO cpuGetBfWidth(UWO ext, bool widthIsDataRegister) { ULO width = (ext & 0x1f); - if (widthIsDr) + if (widthIsDataRegister) { - width = (cpuGetDReg(width & 7) & 0x1f); + width = cpuGetDReg(width & 7) & 0x1f; } if (width == 0) { @@ -2677,105 +2693,90 @@ static ULO cpuGetBfWidth(UWO ext, BOOLE widthIsDr) return width; } -static ULO cpuGetBfField(UBY *bytes, ULO end_offset, ULO byte_count, ULO field_mask) +static void cpuSetBfField(struct cpuBfData *bf_data, ULO ea_or_reg, bool has_ea) { - ULO i; - ULO field = ((ULO)bytes[byte_count - 1]) >> end_offset; - - for (i = 1; i < byte_count; i++) - { - field |= ((ULO)bytes[byte_count - i - 1]) << (8*i - end_offset); - } - return field & field_mask; -} - -static void cpuSetBfField(UBY *bytes, ULO end_offset, ULO byte_count, ULO field, ULO field_mask) -{ - ULO i; - - bytes[byte_count - 1] = (UBY)((field << end_offset) | (bytes[byte_count - 1] & (UBY)~(field_mask << end_offset))); - for (i = 1; i < byte_count - 1; ++i) - { - bytes[byte_count - i - 1] = (UBY)(field >> (end_offset + 8*i)); - } - if (i < byte_count) - { - // clang warning... - //bytes[0] = (bytes[0] & (UBY)~(field_mask >> (end_offset + 8*i)) | (UBY)(field >> (end_offset + 8*i))); - bytes[0] = ((bytes[0] & (UBY)~(field_mask >> (end_offset + 8*i))) | (UBY)(field >> (end_offset + 8*i))); - } -} - -struct cpuBfData -{ - UWO ext; - BOOLE offsetIsDr; - BOOLE widthIsDr; - LON offset; - ULO width; - ULO base_address; - ULO bit_offset; - ULO end_offset; - ULO byte_count; - ULO field; - ULO field_mask; - ULO dn; - UBY b[5]; -}; - -void cpuBfExtWord(struct cpuBfData *bf_data, ULO val, BOOLE has_dn, BOOLE has_ea, UWO ext) -{ - bf_data->ext = ext; - bf_data->offsetIsDr = (bf_data->ext & 0x0800); - bf_data->widthIsDr = (bf_data->ext & 0x20); - bf_data->offset = cpuGetBfOffset(bf_data->ext, bf_data->offsetIsDr); - bf_data->width = cpuGetBfWidth(bf_data->ext, bf_data->widthIsDr); - bf_data->bit_offset = bf_data->offset & 7; - bf_data->byte_count = ((bf_data->bit_offset + bf_data->width + 7) >> 3); - bf_data->end_offset = (bf_data->byte_count*8 - (bf_data->offset + bf_data->width)) & 7; - bf_data->field = 0; - bf_data->field_mask = 0xffffffff >> (32 - bf_data->width); - if (has_dn) - { - bf_data->dn = (bf_data->ext & 0x7000) >> 12; - } if (has_ea) { - bf_data->base_address = val + (bf_data->offset >> 3); - cpuGetBfEaBytes(&bf_data->b[0], bf_data->base_address, bf_data->byte_count); + ULO shift = bf_data->base_address_byte_count*8 - bf_data->normalized_offset - bf_data->width; + ULL field_value = (bf_data->field_memory & ~(bf_data->field_mask << shift)) | (bf_data->field << shift); + ULO address = bf_data->base_address + bf_data->base_address_byte_offset; + + for (int i = bf_data->base_address_byte_count - 1; i >= 0; --i) + { + UBY field_byte = (field_value >> (i*8)) & 0xff; + memoryWriteByte(field_byte, address); + ++address; + } } else { - cpuGetBfRegBytes(&bf_data->b[0], val); + ULO reg_shift = (32 - bf_data->offset - bf_data->width); + ULO reg_value = (cpuGetDReg(ea_or_reg) & ~(bf_data->field_mask << reg_shift)) | (bf_data->field << reg_shift); + cpuSetDReg(ea_or_reg, reg_value); } } +void cpuBfDecodeExtWordAndGetField(struct cpuBfData *bf_data, ULO ea_or_reg, bool has_dn, bool has_ea, UWO ext) +{ + bool offsetIsDataRegister = ((ext & 0x0800) == 0x0800); + bool widthIsDataRegister = ((ext & 0x0020) == 0x0020); + + bf_data->offset = cpuGetBfOffset(ext, offsetIsDataRegister); + bf_data->width = cpuGetBfWidth(ext, widthIsDataRegister); + bf_data->field_mask = 0xffffffff >> (32 - bf_data->width); + + if (has_dn) + { + bf_data->dn = (ext & 0x7000) >> 12; + } + + if (has_ea) + { + bf_data->base_address = ea_or_reg; // Base address of the field, before offset is applied + bf_data->base_address_byte_offset = (bf_data->offset >> 3); // The first byte in the field + bf_data->normalized_offset = bf_data->offset - (bf_data->base_address_byte_offset)*8; // Offset relative to the first byte in the field + bf_data->base_address_byte_count = (bf_data->normalized_offset + bf_data->width + 7) / 8; + + ULO field = 0; + ULL field_memory = 0; + ULO address = bf_data->base_address + bf_data->base_address_byte_offset; + ULO shift = (8 - bf_data->normalized_offset - bf_data->width) & 7; + for (int i = bf_data->base_address_byte_count - 1; i >= 0; --i) + { + ULL value = (ULL) memoryReadByte(address); + field_memory |= (value << (8*i)); + field |= ((value >> shift) << (8*i)); + ++address; + } + + bf_data->field_memory = field_memory; + bf_data->field = field; + } + else + { + bf_data->field = cpuGetDReg(ea_or_reg) >> (32 - bf_data->offset - bf_data->width); + } + bf_data->field &= bf_data->field_mask; +} + /// /// bfchg common logic /// -static void cpuBfChgCommon(ULO val, BOOLE has_ea, UWO ext) +static void cpuBfChgCommon(ULO ea_or_reg, bool has_ea, UWO ext) { struct cpuBfData bf_data; - cpuBfExtWord(&bf_data, val, FALSE, has_ea, ext); - bf_data.field = cpuGetBfField(&bf_data.b[0], bf_data.end_offset, bf_data.byte_count, bf_data.field_mask); + cpuBfDecodeExtWordAndGetField(&bf_data, ea_or_reg, false, has_ea, ext); cpuSetFlagsNZVC(bf_data.field == 0, bf_data.field & (1 << (bf_data.width - 1)), FALSE, FALSE); - cpuSetBfField(&bf_data.b[0], bf_data.end_offset, bf_data.byte_count, (~bf_data.field) & bf_data.field_mask, bf_data.field_mask); - if (has_ea) - { - cpuSetBfEaBytes(&bf_data.b[0], bf_data.base_address, bf_data.byte_count); - } - else - { - cpuSetBfRegBytes(&bf_data.b[0], val); - } + + bf_data.field = (~bf_data.field) & bf_data.field_mask; + + cpuSetBfField(&bf_data, ea_or_reg, has_ea); } -/// -/// bfchg dx {offset:width} -/// +// bfchg dx {offset:width} static void cpuBfChgReg(ULO regno, UWO ext) { - cpuBfChgCommon(regno, FALSE, ext); + cpuBfChgCommon(regno, false, ext); } /// @@ -2783,27 +2784,22 @@ static void cpuBfChgReg(ULO regno, UWO ext) /// static void cpuBfChgEa(ULO ea, UWO ext) { - cpuBfChgCommon(ea, TRUE, ext); + cpuBfChgCommon(ea, true, ext); } /// /// bfclr common logic /// -static void cpuBfClrCommon(ULO val, BOOLE has_ea, UWO ext) +static void cpuBfClrCommon(ULO ea_or_reg, bool has_ea, UWO ext) { struct cpuBfData bf_data; - cpuBfExtWord(&bf_data, val, FALSE, has_ea, ext); - bf_data.field = cpuGetBfField(&bf_data.b[0], bf_data.end_offset, bf_data.byte_count, bf_data.field_mask); + cpuBfDecodeExtWordAndGetField(&bf_data, ea_or_reg, false, has_ea, ext); + cpuSetFlagsNZVC(bf_data.field == 0, bf_data.field & (1 << (bf_data.width - 1)), FALSE, FALSE); - cpuSetBfField(&bf_data.b[0], bf_data.end_offset, bf_data.byte_count, 0, bf_data.field_mask); - if (has_ea) - { - cpuSetBfEaBytes(&bf_data.b[0], bf_data.base_address, bf_data.byte_count); - } - else - { - cpuSetBfRegBytes(&bf_data.b[0], val); - } + + bf_data.field = 0; + + cpuSetBfField(&bf_data, ea_or_reg, has_ea); } /// @@ -2811,7 +2807,7 @@ static void cpuBfClrCommon(ULO val, BOOLE has_ea, UWO ext) /// static void cpuBfClrReg(ULO regno, UWO ext) { - cpuBfClrCommon(regno, FALSE, ext); + cpuBfClrCommon(regno, false, ext); } /// @@ -2819,24 +2815,27 @@ static void cpuBfClrReg(ULO regno, UWO ext) /// static void cpuBfClrEa(ULO ea, UWO ext) { - cpuBfClrCommon(ea, TRUE, ext); + cpuBfClrCommon(ea, true, ext); } /// /// bfexts common logic /// -static void cpuBfExtsCommon(ULO val, BOOLE has_ea, UWO ext) +static void cpuBfExtsCommon(ULO ea_or_reg, bool has_ea, UWO ext) { struct cpuBfData bf_data; BOOLE n_flag; - cpuBfExtWord(&bf_data, val, TRUE, has_ea, ext); - bf_data.field = cpuGetBfField(&bf_data.b[0], bf_data.end_offset, bf_data.byte_count, bf_data.field_mask); + cpuBfDecodeExtWordAndGetField(&bf_data, ea_or_reg, true, has_ea, ext); + n_flag = bf_data.field & (1 << (bf_data.width - 1)); + cpuSetFlagsNZVC(bf_data.field == 0, n_flag, FALSE, FALSE); + if (n_flag) { - bf_data.field = ~bf_data.field_mask | bf_data.field; + bf_data.field = (ULO)((~bf_data.field_mask) | bf_data.field); } + // Destination is always Dn cpuSetDReg(bf_data.dn, bf_data.field); } @@ -2845,7 +2844,7 @@ static void cpuBfExtsCommon(ULO val, BOOLE has_ea, UWO ext) /// static void cpuBfExtsReg(ULO regno, UWO ext) { - cpuBfExtsCommon(regno, FALSE, ext); + cpuBfExtsCommon(regno, false, ext); } /// @@ -2853,18 +2852,18 @@ static void cpuBfExtsReg(ULO regno, UWO ext) /// static void cpuBfExtsEa(ULO ea, UWO ext) { - cpuBfExtsCommon(ea, TRUE, ext); + cpuBfExtsCommon(ea, true, ext); } /// /// bfextu ea {offset:width}, Dn /// -static void cpuBfExtuCommon(ULO val, BOOLE has_ea, UWO ext) +static void cpuBfExtuCommon(ULO ea_or_reg, bool has_ea, UWO ext) { struct cpuBfData bf_data; - cpuBfExtWord(&bf_data, val, TRUE, has_ea, ext); - bf_data.field = cpuGetBfField(&bf_data.b[0], bf_data.end_offset, bf_data.byte_count, bf_data.field_mask); + cpuBfDecodeExtWordAndGetField(&bf_data, ea_or_reg, true, has_ea, ext); cpuSetFlagsNZVC(bf_data.field == 0, bf_data.field & (1 << (bf_data.width - 1)), FALSE, FALSE); + // Destination is always Dn cpuSetDReg(bf_data.dn, bf_data.field); } @@ -2873,7 +2872,7 @@ static void cpuBfExtuCommon(ULO val, BOOLE has_ea, UWO ext) /// static void cpuBfExtuReg(ULO regno, UWO ext) { - cpuBfExtuCommon(regno, FALSE, ext); + cpuBfExtuCommon(regno, false, ext); } /// @@ -2881,22 +2880,22 @@ static void cpuBfExtuReg(ULO regno, UWO ext) /// static void cpuBfExtuEa(ULO ea, UWO ext) { - cpuBfExtuCommon(ea, TRUE, ext); + cpuBfExtuCommon(ea, true, ext); } /// /// bfffo common logic /// -static void cpuBfFfoCommon(ULO val, BOOLE has_ea, UWO ext) +static void cpuBfFfoCommon(ULO val, bool has_ea, UWO ext) { struct cpuBfData bf_data; ULO i; - cpuBfExtWord(&bf_data, val, TRUE, has_ea, ext); - bf_data.field = cpuGetBfField(&bf_data.b[0], bf_data.end_offset, bf_data.byte_count, bf_data.field_mask); + cpuBfDecodeExtWordAndGetField(&bf_data, val, true, has_ea, ext); cpuSetFlagsNZVC(bf_data.field == 0, bf_data.field & (1 << (bf_data.width - 1)), FALSE, FALSE); + for (i = 0; i < bf_data.width; ++i) { - if (bf_data.field & (0x1 << (bf_data.width - i - 1))) + if (bf_data.field & (1 << (bf_data.width - i - 1))) break; } cpuSetDReg(bf_data.dn, bf_data.offset + i); @@ -2907,7 +2906,7 @@ static void cpuBfFfoCommon(ULO val, BOOLE has_ea, UWO ext) /// static void cpuBfFfoReg(ULO regno, UWO ext) { - cpuBfFfoCommon(regno, FALSE, ext); + cpuBfFfoCommon(regno, false, ext); } /// @@ -2915,28 +2914,23 @@ static void cpuBfFfoReg(ULO regno, UWO ext) /// static void cpuBfFfoEa(ULO ea, UWO ext) { - cpuBfFfoCommon(ea, TRUE, ext); + cpuBfFfoCommon(ea, true, ext); } /// /// bfins common logic /// -static void cpuBfInsCommon(ULO val, BOOLE has_ea, UWO ext) +static void cpuBfInsCommon(ULO ea_or_reg, bool has_ea, UWO ext) { struct cpuBfData bf_data; - cpuBfExtWord(&bf_data, val, TRUE, has_ea, ext); - bf_data.field = cpuGetBfField(&bf_data.b[0], bf_data.end_offset, bf_data.byte_count, bf_data.field_mask); - cpuSetFlagsNZVC(bf_data.field == 0, bf_data.field & (1 << (bf_data.width - 1)), FALSE, FALSE); + cpuBfDecodeExtWordAndGetField(&bf_data, ea_or_reg, true, has_ea, ext); + bf_data.field = cpuGetDReg(bf_data.dn) & bf_data.field_mask; - cpuSetBfField(&bf_data.b[0], bf_data.end_offset, bf_data.byte_count, bf_data.field, bf_data.field_mask); - if (has_ea) - { - cpuSetBfEaBytes(&bf_data.b[0], bf_data.base_address, bf_data.byte_count); - } - else - { - cpuSetBfRegBytes(&bf_data.b[0], val); - } + + // Flags are set according to the inserted value + cpuSetFlagsNZVC(bf_data.field == 0, bf_data.field & (1 << (bf_data.width - 1)), FALSE, FALSE); + + cpuSetBfField(&bf_data, ea_or_reg, has_ea); } /// @@ -2944,7 +2938,7 @@ static void cpuBfInsCommon(ULO val, BOOLE has_ea, UWO ext) /// static void cpuBfInsReg(ULO regno, UWO ext) { - cpuBfInsCommon(regno, FALSE, ext); + cpuBfInsCommon(regno, false, ext); } /// @@ -2952,28 +2946,21 @@ static void cpuBfInsReg(ULO regno, UWO ext) /// static void cpuBfInsEa(ULO ea, UWO ext) { - cpuBfInsCommon(ea, TRUE, ext); + cpuBfInsCommon(ea, true, ext); } /// /// bfset common logic /// -static void cpuBfSetCommon(ULO val, BOOLE has_ea, UWO ext) +static void cpuBfSetCommon(ULO ea_or_reg, bool has_ea, UWO ext) { struct cpuBfData bf_data; - cpuBfExtWord(&bf_data, val, FALSE, has_ea, ext); - bf_data.field = cpuGetBfField(&bf_data.b[0], bf_data.end_offset, bf_data.byte_count, bf_data.field_mask); + cpuBfDecodeExtWordAndGetField(&bf_data, ea_or_reg, false, has_ea, ext); cpuSetFlagsNZVC(bf_data.field == 0, bf_data.field & (1 << (bf_data.width - 1)), FALSE, FALSE); - bf_data.field = bf_data.field_mask; - cpuSetBfField(&bf_data.b[0], bf_data.end_offset, bf_data.byte_count, bf_data.field, bf_data.field_mask); - if (has_ea) - { - cpuSetBfEaBytes(&bf_data.b[0], bf_data.base_address, bf_data.byte_count); - } - else - { - cpuSetBfRegBytes(&bf_data.b[0], val); - } + + bf_data.field = (ULO)bf_data.field_mask; + + cpuSetBfField(&bf_data, ea_or_reg, has_ea); } /// @@ -2981,7 +2968,7 @@ static void cpuBfSetCommon(ULO val, BOOLE has_ea, UWO ext) /// static void cpuBfSetReg(ULO regno, UWO ext) { - cpuBfSetCommon(regno, FALSE, ext); + cpuBfSetCommon(regno, false, ext); } /// @@ -2989,17 +2976,16 @@ static void cpuBfSetReg(ULO regno, UWO ext) /// static void cpuBfSetEa(ULO ea, UWO ext) { - cpuBfSetCommon(ea, TRUE, ext); + cpuBfSetCommon(ea, true, ext); } /// /// bftst common logic /// -static void cpuBfTstCommon(ULO val, BOOLE has_ea, UWO ext) +static void cpuBfTstCommon(ULO ea_or_reg, bool has_ea, UWO ext) { struct cpuBfData bf_data; - cpuBfExtWord(&bf_data, val, FALSE, has_ea, ext); - bf_data.field = cpuGetBfField(&bf_data.b[0], bf_data.end_offset, bf_data.byte_count, bf_data.field_mask); + cpuBfDecodeExtWordAndGetField(&bf_data, ea_or_reg, false, has_ea, ext); cpuSetFlagsNZVC(bf_data.field == 0, bf_data.field & (1 << (bf_data.width - 1)), FALSE, FALSE); } @@ -3008,7 +2994,7 @@ static void cpuBfTstCommon(ULO val, BOOLE has_ea, UWO ext) /// static void cpuBfTstReg(ULO regno, UWO ext) { - cpuBfTstCommon(regno, FALSE, ext); + cpuBfTstCommon(regno, false, ext); } /// @@ -3016,7 +3002,7 @@ static void cpuBfTstReg(ULO regno, UWO ext) /// static void cpuBfTstEa(ULO ea, UWO ext) { - cpuBfTstCommon(ea, TRUE, ext); + cpuBfTstCommon(ea, true, ext); } /// @@ -3025,8 +3011,7 @@ static void cpuBfTstEa(ULO ea, UWO ext) static void cpuMovepWReg(ULO areg, ULO dreg) { ULO ea = cpuGetAReg(areg) + cpuGetNextWordSignExt(); - memoryWriteByte((UBY) (cpuGetDReg(dreg) >> 8), ea); - memoryWriteByte(cpuGetDRegByte(dreg), ea + 2); + cpuSetDRegWord(dreg, cpuJoinByteToWord(memoryReadByte(ea), memoryReadByte(ea + 2))); cpuSetInstructionTime(16); } @@ -3036,10 +3021,7 @@ static void cpuMovepWReg(ULO areg, ULO dreg) static void cpuMovepLReg(ULO areg, ULO dreg) { ULO ea = cpuGetAReg(areg) + cpuGetNextWordSignExt(); - memoryWriteByte((UBY)(cpuGetDReg(dreg) >> 24), ea); - memoryWriteByte((UBY)(cpuGetDReg(dreg) >> 16), ea + 2); - memoryWriteByte((UBY)(cpuGetDReg(dreg) >> 8), ea + 4); - memoryWriteByte(cpuGetDRegByte(dreg), ea + 6); + cpuSetDReg(dreg, cpuJoinByteToLong(memoryReadByte(ea), memoryReadByte(ea + 2), memoryReadByte(ea + 4), memoryReadByte(ea + 6))); cpuSetInstructionTime(24); } @@ -3049,7 +3031,8 @@ static void cpuMovepLReg(ULO areg, ULO dreg) static void cpuMovepWEa(ULO areg, ULO dreg) { ULO ea = cpuGetAReg(areg) + cpuGetNextWordSignExt(); - cpuSetDRegWord(dreg, cpuJoinByteToWord(memoryReadByte(ea), memoryReadByte(ea + 2))); + memoryWriteByte((UBY) (cpuGetDReg(dreg) >> 8), ea); + memoryWriteByte(cpuGetDRegByte(dreg), ea + 2); cpuSetInstructionTime(16); } @@ -3059,7 +3042,10 @@ static void cpuMovepWEa(ULO areg, ULO dreg) static void cpuMovepLEa(ULO areg, ULO dreg) { ULO ea = cpuGetAReg(areg) + cpuGetNextWordSignExt(); - cpuSetDReg(dreg, cpuJoinByteToLong(memoryReadByte(ea), memoryReadByte(ea + 2), memoryReadByte(ea + 4), memoryReadByte(ea + 6))); + memoryWriteByte((UBY)(cpuGetDReg(dreg) >> 24), ea); + memoryWriteByte((UBY)(cpuGetDReg(dreg) >> 16), ea + 2); + memoryWriteByte((UBY)(cpuGetDReg(dreg) >> 8), ea + 4); + memoryWriteByte(cpuGetDRegByte(dreg), ea + 6); cpuSetInstructionTime(24); } @@ -3127,41 +3113,41 @@ static void cpuMoveCFrom() { switch (ctrl_regno) { - case 0x000: cpuSetReg(da, regno, cpuGetSfc()); break; - case 0x001: cpuSetReg(da, regno, cpuGetDfc()); break; - case 0x800: cpuSetReg(da, regno, cpuGetUspDirect()); break; // In supervisor mode, usp is up to date. - case 0x801: cpuSetReg(da, regno, cpuGetVbr()); break; - default: cpuThrowIllegalInstructionException(FALSE); return; // Illegal instruction + case 0x000: cpuSetReg(da, regno, cpuGetSfc()); break; + case 0x001: cpuSetReg(da, regno, cpuGetDfc()); break; + case 0x800: cpuSetReg(da, regno, cpuGetUspDirect()); break; // In supervisor mode, usp is up to date. + case 0x801: cpuSetReg(da, regno, cpuGetVbr()); break; + default: cpuThrowIllegalInstructionException(FALSE); return; // Illegal instruction } } else if (cpuGetModelMajor() == 2) { switch (ctrl_regno) { - case 0x000: cpuSetReg(da, regno, cpuGetSfc()); break; - case 0x001: cpuSetReg(da, regno, cpuGetDfc()); break; - case 0x002: cpuSetReg(da, regno, cpuGetCacr() & 3); break; - case 0x800: cpuSetReg(da, regno, cpuGetUspDirect()); break; // In supervisor mode, usp is up to date. - case 0x801: cpuSetReg(da, regno, cpuGetVbr()); break; - case 0x802: cpuSetReg(da, regno, cpuGetCaar() & 0xfc); break; - case 0x803: cpuSetReg(da, regno, cpuGetMspAutoMap()); break; - case 0x804: cpuSetReg(da, regno, cpuGetIspAutoMap()); break; - default: cpuThrowIllegalInstructionException(FALSE); return; // Illegal instruction + case 0x000: cpuSetReg(da, regno, cpuGetSfc()); break; + case 0x001: cpuSetReg(da, regno, cpuGetDfc()); break; + case 0x002: cpuSetReg(da, regno, cpuGetCacr() & 3); break; + case 0x800: cpuSetReg(da, regno, cpuGetUspDirect()); break; // In supervisor mode, usp is up to date. + case 0x801: cpuSetReg(da, regno, cpuGetVbr()); break; + case 0x802: cpuSetReg(da, regno, cpuGetCaar() & 0xfc); break; + case 0x803: cpuSetReg(da, regno, cpuGetMspAutoMap()); break; + case 0x804: cpuSetReg(da, regno, cpuGetIspAutoMap()); break; + default: cpuThrowIllegalInstructionException(FALSE); return; // Illegal instruction } } else if (cpuGetModelMajor() == 3) { switch (ctrl_regno) { - case 0x000: cpuSetReg(da, regno, cpuGetSfc()); break; - case 0x001: cpuSetReg(da, regno, cpuGetDfc()); break; - case 0x002: cpuSetReg(da, regno, cpuGetCacr()); break; - case 0x800: cpuSetReg(da, regno, cpuGetUspDirect()); break; // In supervisor mode, usp is up to date. - case 0x801: cpuSetReg(da, regno, cpuGetVbr()); break; - case 0x802: cpuSetReg(da, regno, cpuGetCaar() & 0xfc); break; - case 0x803: cpuSetReg(da, regno, cpuGetMspAutoMap()); break; - case 0x804: cpuSetReg(da, regno, cpuGetIspAutoMap()); break; - default: cpuThrowIllegalInstructionException(FALSE); return; // Illegal instruction + case 0x000: cpuSetReg(da, regno, cpuGetSfc()); break; + case 0x001: cpuSetReg(da, regno, cpuGetDfc()); break; + case 0x002: cpuSetReg(da, regno, cpuGetCacr()); break; + case 0x800: cpuSetReg(da, regno, cpuGetUspDirect()); break; // In supervisor mode, usp is up to date. + case 0x801: cpuSetReg(da, regno, cpuGetVbr()); break; + case 0x802: cpuSetReg(da, regno, cpuGetCaar() & 0xfc); break; + case 0x803: cpuSetReg(da, regno, cpuGetMspAutoMap()); break; + case 0x804: cpuSetReg(da, regno, cpuGetIspAutoMap()); break; + default: cpuThrowIllegalInstructionException(FALSE); return; // Illegal instruction } } } @@ -3188,41 +3174,41 @@ static void cpuMoveCTo() { switch (ctrl_regno) { - case 0x000: cpuSetSfc(cpuGetReg(da, regno) & 7); break; - case 0x001: cpuSetDfc(cpuGetReg(da, regno) & 7); break; - case 0x800: cpuSetUspDirect(cpuGetReg(da, regno)); break; - case 0x801: cpuSetVbr(cpuGetReg(da, regno)); break; - default: cpuThrowIllegalInstructionException(FALSE); return; // Illegal instruction + case 0x000: cpuSetSfc(cpuGetReg(da, regno) & 7); break; + case 0x001: cpuSetDfc(cpuGetReg(da, regno) & 7); break; + case 0x800: cpuSetUspDirect(cpuGetReg(da, regno)); break; + case 0x801: cpuSetVbr(cpuGetReg(da, regno)); break; + default: cpuThrowIllegalInstructionException(FALSE); return; // Illegal instruction } } else if (cpuGetModelMajor() == 2) { switch (ctrl_regno) { - case 0x000: cpuSetSfc(cpuGetReg(da, regno) & 7); break; - case 0x001: cpuSetDfc(cpuGetReg(da, regno) & 7); break; - case 0x002: cpuSetCacr(cpuGetReg(da, regno) & 0x3); break; - case 0x800: cpuSetUspDirect(cpuGetReg(da, regno)); break; - case 0x801: cpuSetVbr(cpuGetReg(da, regno)); break; - case 0x802: cpuSetCaar(cpuGetReg(da, regno) & 0x00fc); break; - case 0x803: cpuSetMspAutoMap(cpuGetReg(da, regno)); break; - case 0x804: cpuSetIspAutoMap(cpuGetReg(da, regno)); break; - default: cpuThrowIllegalInstructionException(FALSE); return; // Illegal instruction + case 0x000: cpuSetSfc(cpuGetReg(da, regno) & 7); break; + case 0x001: cpuSetDfc(cpuGetReg(da, regno) & 7); break; + case 0x002: cpuSetCacr(cpuGetReg(da, regno) & 0x3); break; + case 0x800: cpuSetUspDirect(cpuGetReg(da, regno)); break; + case 0x801: cpuSetVbr(cpuGetReg(da, regno)); break; + case 0x802: cpuSetCaar(cpuGetReg(da, regno) & 0x00fc); break; + case 0x803: cpuSetMspAutoMap(cpuGetReg(da, regno)); break; + case 0x804: cpuSetIspAutoMap(cpuGetReg(da, regno)); break; + default: cpuThrowIllegalInstructionException(FALSE); return; // Illegal instruction } } else if (cpuGetModelMajor() == 3) { switch (ctrl_regno) { - case 0x000: cpuSetSfc(cpuGetReg(da, regno) & 7); break; - case 0x001: cpuSetDfc(cpuGetReg(da, regno) & 7); break; - case 0x002: cpuSetCacr(cpuGetReg(da, regno) & 0x3313); break; - case 0x800: cpuSetUspDirect(cpuGetReg(da, regno)); break; - case 0x801: cpuSetVbr(cpuGetReg(da, regno)); break; - case 0x802: cpuSetCaar(cpuGetReg(da, regno) & 0x00fc); break; - case 0x803: cpuSetMspAutoMap(cpuGetReg(da, regno)); break; - case 0x804: cpuSetIspAutoMap(cpuGetReg(da, regno)); break; - default: cpuThrowIllegalInstructionException(FALSE); return; // Illegal instruction + case 0x000: cpuSetSfc(cpuGetReg(da, regno) & 7); break; + case 0x001: cpuSetDfc(cpuGetReg(da, regno) & 7); break; + case 0x002: cpuSetCacr(cpuGetReg(da, regno) & 0x3313); break; + case 0x800: cpuSetUspDirect(cpuGetReg(da, regno)); break; + case 0x801: cpuSetVbr(cpuGetReg(da, regno)); break; + case 0x802: cpuSetCaar(cpuGetReg(da, regno) & 0x00fc); break; + case 0x803: cpuSetMspAutoMap(cpuGetReg(da, regno)); break; + case 0x804: cpuSetIspAutoMap(cpuGetReg(da, regno)); break; + default: cpuThrowIllegalInstructionException(FALSE); return; // Illegal instruction } } } @@ -3252,11 +3238,11 @@ static void cpuMoveSB(ULO ea, UWO extension) UBY data = memoryReadByte(ea); if (da == 0) { - cpuSetDRegByte(regno, data); + cpuSetDRegByte(regno, data); } else { - cpuSetAReg(regno, (ULO)(LON)(BYT) data); + cpuSetAReg(regno, (ULO)(LON)(BYT) data); } } } @@ -3265,7 +3251,7 @@ static void cpuMoveSB(ULO ea, UWO extension) cpuThrowPrivilegeViolationException(); return; } - cpuSetInstructionTime(4); + cpuSetInstructionTime(4); } /// @@ -3286,11 +3272,11 @@ static void cpuMoveSW(ULO ea, UWO extension) UWO data = memoryReadWord(ea); if (da == 0) { - cpuSetDRegWord(regno, data); + cpuSetDRegWord(regno, data); } else { - cpuSetAReg(regno, (ULO)(LON)(WOR) data); + cpuSetAReg(regno, (ULO)(LON)(WOR) data); } } } @@ -3299,7 +3285,7 @@ static void cpuMoveSW(ULO ea, UWO extension) cpuThrowPrivilegeViolationException(); return; } - cpuSetInstructionTime(4); + cpuSetInstructionTime(4); } /// @@ -3325,7 +3311,7 @@ static void cpuMoveSL(ULO ea, UWO extension) cpuThrowPrivilegeViolationException(); return; } - cpuSetInstructionTime(4); + cpuSetInstructionTime(4); } /// @@ -3338,7 +3324,7 @@ static void cpuTrapcc(ULO cc) cpuThrowTrapVException(); // TrapV and Trapcc share the exception vector return; } - cpuSetInstructionTime(4); + cpuSetInstructionTime(4); } /// @@ -3352,7 +3338,7 @@ static void cpuTrapccW(ULO cc) cpuThrowTrapVException(); // TrapV and Trapcc share the exception vector return; } - cpuSetInstructionTime(4); + cpuSetInstructionTime(4); } /// @@ -3366,7 +3352,7 @@ static void cpuTrapccL(ULO cc) cpuThrowTrapVException(); // TrapV and Trapcc share the exception vector return; } - cpuSetInstructionTime(4); + cpuSetInstructionTime(4); } /// @@ -3658,18 +3644,18 @@ static void cpuPflush040(ULO opmode, ULO regno) { if (cpuGetFlagSupervisor()) { - if (cpuGetModelMajor() != 2) // This is NOP on 68EC040 + if (cpuGetModelMajor() != 2) // This is NOP on 68EC040 { switch (opmode) { - case 0: //PFLUSHN (An) - break; - case 1: //PFLUSH (An) - break; - case 2: //PFLUSHAN - break; - case 3: //PFLUSHA - break; + case 0: //PFLUSHN (An) + break; + case 1: //PFLUSH (An) + break; + case 2: //PFLUSHAN + break; + case 3: //PFLUSHA + break; } } } @@ -3693,15 +3679,15 @@ static void cpuPtest040(ULO rw, ULO regno) { if (cpuGetFlagSupervisor()) { - if (cpuGetModelMajor() != 2) // This is NOP on 68EC040 + if (cpuGetModelMajor() != 2) // This is NOP on 68EC040 { if (rw == 0) { - // ptestr + // ptestr } else { - // ptestw + // ptestw } } } @@ -3739,11 +3725,14 @@ void cpuMakeOpcodeTableForModel(void) } } +ULO irq_arrival_time = -1; +extern ULO busGetCycle(); + ULO cpuExecuteInstruction(void) { if (cpuGetRaiseInterrupt()) { - cpuSetUpInterrupt(); + cpuSetUpInterrupt(cpuGetRaiseInterruptLevel()); cpuCheckPendingInterrupts(); return 44; } @@ -3765,8 +3754,8 @@ ULO cpuExecuteInstruction(void) cpuSetInstructionTime(0); - cpu_opcode_data_current[opcode].instruction_func( - cpu_opcode_data_current[opcode].data); + cpu_opcode_data_current[opcode].instruction_func( + cpu_opcode_data_current[opcode].data); if (oldSr & 0xc000) { // This instruction was traced diff --git a/cpu/CpuModule_Internal.h b/cpu/CpuModule_Internal.h index b7bf858..9f68069 100644 --- a/cpu/CpuModule_Internal.h +++ b/cpu/CpuModule_Internal.h @@ -51,7 +51,7 @@ 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 BOOLE cpuSetIrqLevel(ULO new_interrupt_level); extern ULO cpuGetIrqLevel(void); extern void cpuSetIrqAddress(ULO irq_address); extern ULO cpuGetIrqAddress(void); @@ -167,10 +167,11 @@ 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); +extern void cpuSetRaiseInterruptLevel(ULO raise_irq_level); +extern ULO cpuGetRaiseInterruptLevel(void); // Exceptions extern void cpuThrowPrivilegeViolationException(void); diff --git a/cpu/CpuModule_InternalState.c b/cpu/CpuModule_InternalState.c index 2fba027..db93bba 100644 --- a/cpu/CpuModule_InternalState.c +++ b/cpu/CpuModule_InternalState.c @@ -1,4 +1,4 @@ -/* @(#) $Id: CpuModule_InternalState.c,v 1.9 2012/08/12 16:51:02 peschau Exp $ */ +/* @(#) $Id: CpuModule_InternalState.c,v 1.9 2012-08-12 16:51:02 peschau Exp $ */ /*=========================================================================*/ /* Fellow */ /* 68000 internal state */ @@ -43,8 +43,7 @@ static ULO cpu_caar; /* Irq management */ static BOOLE cpu_raise_irq; -static ULO cpu_irq_level; -static ULO cpu_irq_address; +static ULO cpu_raise_irq_level; /* Reset values */ static ULO cpu_initial_pc; @@ -186,12 +185,6 @@ 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;} @@ -207,6 +200,10 @@ UWO cpuGetCurrentOpcode(void) {return cpu_current_opcode;} void cpuSetRaiseInterrupt(BOOLE raise_irq) {cpu_raise_irq = raise_irq;} BOOLE cpuGetRaiseInterrupt(void) {return cpu_raise_irq;} +void cpuSetRaiseInterruptLevel(ULO raise_irq_level) {cpu_raise_irq_level = raise_irq_level;} +ULO cpuGetRaiseInterruptLevel(void) {return cpu_raise_irq_level;} + +ULO cpuGetIrqLevel(void) {return (cpu_sr & 0x0700) >> 8;} void cpuSetInitialPC(ULO pc) {cpu_initial_pc = pc;} ULO cpuGetInitialPC(void) {return cpu_initial_pc;} @@ -352,8 +349,6 @@ void cpuSaveState(FILE *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); } @@ -382,8 +377,6 @@ void cpuLoadState(FILE *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. diff --git a/cpu/CpuModule_Interrupts.c b/cpu/CpuModule_Interrupts.c index 8558bd1..0dab357 100644 --- a/cpu/CpuModule_Interrupts.c +++ b/cpu/CpuModule_Interrupts.c @@ -1,4 +1,4 @@ -/* @(#) $Id: CpuModule_Interrupts.c,v 1.5 2012/08/12 16:51:02 peschau Exp $ */ +/* @(#) $Id: CpuModule_Interrupts.c,v 1.5 2012-08-12 16:51:02 peschau Exp $ */ /*=========================================================================*/ /* Fellow */ /* 68000 interrupt handling */ @@ -31,15 +31,10 @@ /* 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(); + if (cpuGetRaiseInterrupt()) return; + if (cpu_check_pending_interrupts_func) cpu_check_pending_interrupts_func(); } void cpuSetCheckPendingInterruptsFunc(cpuCheckPendingInterruptsFunc func) @@ -70,24 +65,41 @@ ULO cpuActivateSSP(void) return currentSP; } +// Retrns TRUE if the CPU is in the stopped state, +// this allows our scheduling queue to start +// scheduling CPU events again. +BOOLE cpuSetIrqLevel(ULO new_interrupt_level) +{ + cpuSetRaiseInterrupt(TRUE); + cpuSetRaiseInterruptLevel(new_interrupt_level); + + if (cpuGetStop()) + { + cpuSetStop(FALSE); + return TRUE; + } + return FALSE; +} + /*============================================================ Transfers control to an interrupt routine ============================================================*/ -// Returns TRUE if the cpu was stopped -void cpuSetUpInterrupt(void) +void cpuSetUpInterrupt(ULO new_interrupt_level) { - UWO vector_offset = (UWO) (0x60 + cpuGetIrqLevel()*4); + UWO vector_offset = (UWO) (0x60 + new_interrupt_level*4); + ULO vector_address = memoryReadLong(cpuGetVbr() + vector_offset); + 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 + cpuSetSR(cpuGetSR() | (UWO)(new_interrupt_level << 8)); // Set interrupt level #ifdef CPU_INSTRUCTION_LOGGING - cpuCallInterruptLoggingFunc(cpuGetIrqLevel(), cpuGetIrqAddress()); + cpuCallInterruptLoggingFunc(new_interrupt_level, vector_address); #endif if (cpuGetModelMajor() >= 2 && cpuGetModelMajor() < 6) @@ -101,7 +113,7 @@ void cpuSetUpInterrupt(void) cpuSetSR(cpuGetSR() & 0xefff); // Clear master bit } } - cpuInitializeFromNewPC(cpuGetIrqAddress()); + cpuInitializeFromNewPC(vector_address); cpuSetStop(FALSE); cpuSetRaiseInterrupt(FALSE); } diff --git a/cpu/CpuModule_Logging.c b/cpu/CpuModule_Logging.c index 1336e06..fde361f 100644 --- a/cpu/CpuModule_Logging.c +++ b/cpu/CpuModule_Logging.c @@ -1,4 +1,4 @@ -/* @(#) $Id: CpuModule_Logging.c,v 1.3 2012/08/12 16:51:02 peschau Exp $ */ +/* @(#) $Id: CpuModule_Logging.c,v 1.3 2012-08-12 16:51:02 peschau Exp $ */ /*=========================================================================*/ /* Fellow */ /* CPU 68k logging functions */ diff --git a/cpu/CpuModule_StackFrameGen.c b/cpu/CpuModule_StackFrameGen.c index d68583c..178c0d0 100644 --- a/cpu/CpuModule_StackFrameGen.c +++ b/cpu/CpuModule_StackFrameGen.c @@ -1,4 +1,4 @@ -/* @(#) $Id: CpuModule_StackFrameGen.c,v 1.3 2011/07/18 17:22:55 peschau Exp $ */ +/* @(#) $Id: CpuModule_StackFrameGen.c,v 1.3 2011-07-18 17:22:55 peschau Exp $ */ /*=========================================================================*/ /* Fellow */ /* 68000 stack frame generation */ diff --git a/cpu/defs.h b/cpu/defs.h index 3c55584..33226dc 100644 --- a/cpu/defs.h +++ b/cpu/defs.h @@ -4,6 +4,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" {