From f76a576fe270d4bd78eb4070eb9604115a096c2d Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Thu, 30 Jul 2009 21:26:57 +0000 Subject: [PATCH] Replaced old v6809 core with new updated one. :-) --- makefile | 3 + src/thunder.cpp | 70 +++-- src/v6809.cpp | 711 ++++++++++++++++++++++++++++++++++-------------- src/v6809.h | 19 +- 4 files changed, 553 insertions(+), 250 deletions(-) diff --git a/makefile b/makefile index d0f50c7..e9dc6f1 100755 --- a/makefile +++ b/makefile @@ -56,10 +56,13 @@ LIBS = -L/usr/local/lib `sdl-config $(SDLLIBTYPE)` -lstdc++ -lz $(GLLIB) -lcurse INCS = -I. -Isrc -I/usr/local/include OBJS = \ + obj/dis6808.o \ + obj/dis6809.o \ obj/gui.o \ obj/log.o \ obj/resource.o \ obj/screen.o \ + obj/v6808.o \ obj/v6809.o \ obj/thunder.o \ $(ICON) diff --git a/src/thunder.cpp b/src/thunder.cpp index 3a9d8ae..ffbfed9 100755 --- a/src/thunder.cpp +++ b/src/thunder.cpp @@ -99,18 +99,6 @@ uint8 * gram, * grom; // Allocate RAM & ROM pointers uint8 gram1[0x10000], gram2[0x10000], grom1[0x10000], grom2[0x10000]; // Actual memory uint8 grom3[0x8000], grom4[0x8000], data_rom[0x40000], spr_rom[0x80000], voice_rom[0x20000]; uint8 chr_rom[0x60000]; // Character ROM pointer -/* - gram1 = new uint8[0x10000]; - grom1 = new uint8[0x10000]; - gram2 = new uint8[0x10000]; - grom2 = new uint8[0x10000]; - chr_rom = new uint8[0x60000]; - grom3 = new uint8[0x8000]; - grom4 = new uint8[0x8000]; - data_rom = new uint8[0x40000]; - spr_rom = new uint8[0x80000]; - voice_rom = new uint8[0x20000]; -*/ V6809REGS cpu1, cpu2; @@ -451,25 +439,25 @@ void DisplayBytes(uint16 src, unsigned long dst) uint8 cnt; unsigned long i; - printf("%04X: ", src); + WriteLog("%04X: ", src); cnt = 0; // Init counter... if (src > dst) dst += 0x10000; // That should fix the FFFF bug... for(i=src; i CPU clock #1: %u\n", cpu1.clock); - // Will *this* help video sync? + // Will *this* help video sync? NO while (cpu1.clock < 8000) // was 17000, 20000, 5000 { Execute6809(&cpu1, 1); Execute6809(&cpu2, 1); } +#endif } WriteLog("About to set up screen...\n"); @@ -1270,7 +1262,7 @@ WriteLog("About to set up screen...\n"); } SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256); -#if 1 +#if 0 // This confirms that we're getting video to the screen... SDL_LockSurface(screen); @@ -1497,6 +1489,12 @@ WriteLog("About to enter main loop...\n"); Execute6809(&cpu2, 10); } // } +//F12 is used above, but the values are ignored. So we'll do it here too. + if (keys[SDLK_F12]) + { + cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET; + cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET; + } // if (enable_cpu) if (true) @@ -1525,8 +1523,8 @@ WriteLog("About to enter main loop...\n"); Execute6809(&cpu2, 100); } - cpu1.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed) - cpu2.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)//*/ +// cpu1.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed) +// cpu2.clock -= 25000; // Remove 25K ticks from clock (in case it overflowed)//*/ #endif } // END: enable_cpu diff --git a/src/v6809.cpp b/src/v6809.cpp index 894476f..9c2160f 100755 --- a/src/v6809.cpp +++ b/src/v6809.cpp @@ -1,41 +1,112 @@ // -// Virtual 6809 v1.2 (Last build: 2/27/2004) +// Virtual 6809 v1.3 // // by James L. Hammons +// (c) 1997, 2006 Underground Software // -// (c) 1997,2004 Underground Software +// JLH = James L. Hammons +// +// WHO WHEN WHAT +// --- ---------- ------------------------------------------------------------ +// JLH 06/15/2006 Added changelog ;-) +// JLH 06/15/2006 Scrubbed all BYTE, WORD & DWORD references from the code +// JLH 11/11/2006 Removed all SignedX() references +// + +// Mebbe someday I'll get around to fixing the core to be more like V65C02... +// We have a start... ;-) // #include "v6809.h" +//#define __DEBUG__ #ifdef __DEBUG__ #include "dis6809.h" // Temporary... #include "log.h" // Temporary... #endif +// Various macros + +#define CLR_Z (regs.cc &= ~FLAG_Z) +#define CLR_ZN (regs.cc &= ~(FLAG_Z | FLAG_N)) +#define CLR_ZNC (regs.cc &= ~(FLAG_Z | FLAG_N | FLAG_C)) +#define CLR_V (regs.cc &= ~FLAG_V) +#define CLR_N (regs.cc &= ~FLAG_N) +#define SET_Z(r) (regs.cc = ((r) == 0 ? regs.cc | FLAG_Z : regs.cc & ~FLAG_Z)) +#define SET_N(r) (regs.cc = ((r) & 0x80 ? regs.cc | FLAG_N : regs.cc & ~FLAG_N)) + +//Not sure that this code is computing the carry correctly... Investigate! [Seems to be] +#define SET_C_ADD(a,b) (regs.cc = ((uint8)(b) > (uint8)(~(a)) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C)) +//#define SET_C_SUB(a,b) (regs.cc = ((uint8)(b) >= (uint8)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C)) +#define SET_C_CMP(a,b) (regs.cc = ((uint8)(b) >= (uint8)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C)) +#define SET_ZN(r) SET_N(r); SET_Z(r) +#define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b) +//#define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b) +#define SET_ZNC_CMP(a,b,r) SET_N(r); SET_Z(r); SET_C_CMP(a,b) + +//Small problem with the EA_ macros: ABS macros don't increment the PC!!! !!! FIX !!! +//Hmm, why not do like we did for READ_ABS*??? +//Because the EA_* macros are usually used as an argument to a function call, that's why. +#define EA_IMM regs.pc++ +#define EA_ZP regs.RdMem(regs.pc++) +#define EA_ZP_X (regs.RdMem(regs.pc++) + regs.x) & 0xFF +#define EA_ZP_Y (regs.RdMem(regs.pc++) + regs.y) & 0xFF +#define EA_ABS RdMemW(regs.pc) +#define EA_ABS_X RdMemW(regs.pc) + regs.x +#define EA_ABS_Y RdMemW(regs.pc) + regs.y +#define EA_IND_ZP_X RdMemW((regs.RdMem(regs.pc++) + regs.x) & 0xFF) +#define EA_IND_ZP_Y RdMemW(regs.RdMem(regs.pc++)) + regs.y +#define EA_IND_ZP RdMemW(regs.RdMem(regs.pc++)) + +#define READ_IMM regs.RdMem(EA_IMM) +#define READ_ZP regs.RdMem(EA_ZP) +#define READ_ZP_X regs.RdMem(EA_ZP_X) +#define READ_ZP_Y regs.RdMem(EA_ZP_Y) +#define READ_ABS regs.RdMem(EA_ABS); regs.pc += 2 +#define READ_ABS_X regs.RdMem(EA_ABS_X); regs.pc += 2 +#define READ_ABS_Y regs.RdMem(EA_ABS_Y); regs.pc += 2 +#define READ_IND_ZP_X regs.RdMem(EA_IND_ZP_X) +#define READ_IND_ZP_Y regs.RdMem(EA_IND_ZP_Y) +#define READ_IND_ZP regs.RdMem(EA_IND_ZP) + +#define READ_IMM_WB(v) uint16 addr = EA_IMM; v = regs.RdMem(addr) +#define READ_ZP_WB(v) uint16 addr = EA_ZP; v = regs.RdMem(addr) +#define READ_ZP_X_WB(v) uint16 addr = EA_ZP_X; v = regs.RdMem(addr) +#define READ_ABS_WB(v) uint16 addr = EA_ABS; v = regs.RdMem(addr); regs.pc += 2 +#define READ_ABS_X_WB(v) uint16 addr = EA_ABS_X; v = regs.RdMem(addr); regs.pc += 2 +#define READ_ABS_Y_WB(v) uint16 addr = EA_ABS_Y; v = regs.RdMem(addr); regs.pc += 2 +#define READ_IND_ZP_X_WB(v) uint16 addr = EA_IND_ZP_X; v = regs.RdMem(addr) +#define READ_IND_ZP_Y_WB(v) uint16 addr = EA_IND_ZP_Y; v = regs.RdMem(addr) +#define READ_IND_ZP_WB(v) uint16 addr = EA_IND_ZP; v = regs.RdMem(addr) + +#define WRITE_BACK(d) regs.WrMem(addr, (d)) + // Private global variables static V6809REGS regs; -static uint16 addr; // Temporary variables common to all funcs... +//Let's see if we can nuke this shit. +static uint16 addr; // Temporary variables common to all funcs... static uint8 tmp; // Private function prototypes -static int SignedB(uint8); // Return signed byte from unsigned -static int SignedW(uint16); // Return signed word from unsigned static uint16 FetchW(void); static uint16 RdMemW(uint16 addr); static void WrMemW(uint16 addr, uint16 w); -static uint16 ReadEXG(uint8); // Read TFR/EXG post byte -static void WriteEXG(uint8, uint16); // Set TFR/EXG data -static uint16 DecodeReg(uint8); // Decode register data -static uint16 DecodeIDX(uint8); // Decode IDX data +static uint16 ReadEXG(uint8); // Read TFR/EXG post byte +static void WriteEXG(uint8, uint16); // Set TFR/EXG data +static uint16 DecodeReg(uint8); // Decode register data +static uint16 DecodeIDX(uint8); // Decode IDX data + +//static void (* exec_op1[256])(); +//static void (* exec_op2[256])(); +#if 1 // This is here because of the stupid forward declaration rule that C++ forces (the C++ compiler // isn't smart enough to know that the identifiers in the arrays are declared later, it doesn't // even *try* to see if they're there). -#define FD(x) static void Op##x(); // FD -> "Forward Declaration" +#define FD(x) static void Op##x(); // FD -> "Forward Declaration" #define FE(x) static void Op10##x(); #define FF(x) static void Op11##x(); @@ -67,6 +138,12 @@ FF(3F) FF(83) FF(8C) FF(93) FF(9C) FF(A3) FF(AC) FF(B3) FF(BC) #undef FE #undef FF +#endif + +// We can move these down and do away with the forward declarations... !!! FIX !!! +// Actually, we can't because these are used in a couple of the opcode functions. +// Have to think about how to fix that... + // // Function arrays // @@ -142,13 +219,6 @@ static uint16 FetchW() regs.pc += 2; return w; } -// -// Fetch word function -// -/*uint16 FetchW(void) -{ - return (uint16)(regs.RdMem(regs.pc++) << 8) | regs.RdMem(regs.pc++); -}*/ // // Read word from memory function @@ -167,22 +237,6 @@ void WrMemW(uint16 addr, uint16 w) regs.WrMem(addr + 1, w & 0xFF); } -// -// return signed byte from unsigned -// -int SignedB(uint8 b) -{ - return (b & 0x80 ? b - 256 : b); -} - -// -// return signed word from unsigned -// -int SignedW(uint16 w) -{ - return (w & 0x8000 ? w - 65536 : w); -} - // // Function to read TFR/EXG post byte // @@ -289,7 +343,7 @@ uint16 DecodeIDX(uint8 code) uint16 addr, woff; uint8 reg = (code & 0x60) >> 5, idxind = (code & 0x10) >> 4, lo_nyb = code & 0x0F; - if (!(code & 0x80)) // Hi bit unset? Then decode 4 bit offset + if (!(code & 0x80)) // Hi bit unset? Then decode 4 bit offset addr = DecodeReg(reg) + (idxind ? lo_nyb - 16 : lo_nyb); else { @@ -324,31 +378,31 @@ uint16 DecodeIDX(uint8 code) addr = RdMemW(woff); break; case 5: - woff = DecodeReg(reg) + SignedB(regs.b); + woff = DecodeReg(reg) + (int16)(int8)regs.b; addr = RdMemW(woff); break; case 6: - woff = DecodeReg(reg) + SignedB(regs.a); + woff = DecodeReg(reg) + (int16)(int8)regs.a; addr = RdMemW(woff); break; case 8: - woff = DecodeReg(reg) + SignedB(regs.RdMem(regs.pc++)); + woff = DecodeReg(reg) + (int16)(int8)regs.RdMem(regs.pc++); addr = RdMemW(woff); break; case 9: - woff = DecodeReg(reg) + SignedW(FetchW()); + woff = DecodeReg(reg) + FetchW(); addr = RdMemW(woff); break; case 11: - woff = DecodeReg(reg) + SignedW((regs.a << 8) | regs.b); + woff = DecodeReg(reg) + ((regs.a << 8) | regs.b); addr = RdMemW(woff); break; case 12: - woff = regs.pc + SignedB(regs.RdMem(regs.pc++)); + woff = regs.pc + (int16)(int8)regs.RdMem(regs.pc++); addr = RdMemW(woff); break; case 13: - woff = regs.pc + SignedW(FetchW()); + woff = regs.pc + FetchW(); addr = RdMemW(woff); break; case 15: @@ -398,13 +452,13 @@ uint16 DecodeIDX(uint8 code) } addr = DecodeReg(reg); break; } case 4: { addr = DecodeReg(reg); break; } - case 5: { addr = DecodeReg(reg) + SignedB(regs.b); break; } - case 6: { addr = DecodeReg(reg) + SignedB(regs.a); break; } - case 8: { addr = DecodeReg(reg) + SignedB(regs.RdMem(regs.pc++)); break; } - case 9: { addr = DecodeReg(reg) + SignedW(FetchW()); break; } - case 11: { addr = DecodeReg(reg) + SignedW((regs.a << 8) | regs.b); break; } - case 12: { addr = regs.pc + SignedB(regs.RdMem(regs.pc++)); break; } - case 13: { addr = regs.pc + SignedW(FetchW()); break; } + case 5: { addr = DecodeReg(reg) + (int16)(int8)regs.b; break; } + case 6: { addr = DecodeReg(reg) + (int16)(int8)regs.a; break; } + case 8: { addr = DecodeReg(reg) + (int16)(int8)regs.RdMem(regs.pc++); break; } + case 9: { addr = DecodeReg(reg) + FetchW(); break; } + case 11: { addr = DecodeReg(reg) + ((regs.a << 8) | regs.b); break; } + case 12: { addr = regs.pc + (int16)(int8)regs.RdMem(regs.pc++); break; } + case 13: { addr = regs.pc + FetchW(); break; } } } } @@ -546,32 +600,41 @@ static void Op10(void) // Page 1 opcode exec_op1[regs.RdMem(regs.pc++)](); } -static void Op11(void) // Page 2 opcode +static void Op11(void) // Page 2 opcode { exec_op2[regs.RdMem(regs.pc++)](); } -static void Op12(void) // NOP +static void Op12(void) // NOP { regs.clock += 2; } -static void Op13(void) // SYNC +static void Op13(void) // SYNC { - regs.clock += 2; + // Fix this so it does the right thing (software interrupt!) + regs.clock += 2; } -static void Op16(void) // LBRA + +static void Op16(void) // LBRA { - regs.pc += SignedW(FetchW()); - regs.clock += 5; +// regs.pc += SignedW(FetchW()); + regs.pc += FetchW(); // No need to make signed, both are 16 bit quantities + + regs.clock += 5; } -static void Op17(void) // LBSR + +static void Op17(void) // LBSR { - addr = FetchW(); - regs.WrMem(--regs.s, regs.pc&0xFF); regs.WrMem(--regs.s, regs.pc>>8); - regs.pc += SignedW(addr); - regs.clock += 9; + uint16 word = FetchW(); + regs.WrMem(--regs.s, regs.pc & 0xFF); + regs.WrMem(--regs.s, regs.pc >> 8); +// regs.pc += SignedW(addr); + regs.pc += word; // No need to make signed, both are 16 bit + + regs.clock += 9; } + static void Op19(void) // DAA { if ((regs.cc&0x20) || ((regs.a&0x0F) > 0x09)) // H set or lo nyb too big? @@ -602,7 +665,7 @@ static void Op1C(void) // ANDCC # regs.clock += 3; } -static void Op1D(void) // SEX +static void Op1D(void) // SEX { (regs.b & 0x80 ? regs.a = 0xFF : regs.a = 0x00); @@ -612,7 +675,7 @@ static void Op1D(void) // SEX regs.clock += 2; } -static void Op1E(void) // EXG +static void Op1E(void) // EXG { tmp = regs.RdMem(regs.pc++); addr = ReadEXG(tmp >> 4); @@ -628,100 +691,162 @@ static void Op1F(void) // TFR WriteEXG(tmp&0xF, ReadEXG(tmp>>4)); regs.clock += 7; } -static void Op20(void) // BRA + +static void Op20(void) // BRA { - regs.pc += SignedB(regs.RdMem(regs.pc++)); // Branch always - regs.clock += 3; +// regs.pc += SignedB(regs.RdMem(regs.pc++)); // Branch always + regs.pc += (int16)(int8)regs.RdMem(regs.pc) + 1; // Branch always + + regs.clock += 3; } -static void Op21(void) // BRN + +static void Op21(void) // BRN { - regs.RdMem(regs.pc++); - regs.clock += 3; + regs.RdMem(regs.pc++); + + regs.clock += 3; } -static void Op22(void) // BHI + +static void Op22(void) // BHI { - tmp = regs.RdMem(regs.pc++); - if (!(regs.cc&0x05)) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (!(regs.cc & 0x05)) + regs.pc += word; + + regs.clock += 3; } -static void Op23(void) // BLS + +static void Op23(void) // BLS { - tmp = regs.RdMem(regs.pc++); - if (regs.cc&0x05) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (regs.cc & 0x05) + regs.pc += word; + + regs.clock += 3; } -static void Op24(void) // BCC (BHS) + +static void Op24(void) // BCC (BHS) { - tmp = regs.RdMem(regs.pc++); - if (!(regs.cc&0x01)) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (!(regs.cc & 0x01)) + regs.pc += word; + + regs.clock += 3; } -static void Op25(void) // BCS (BLO) + +static void Op25(void) // BCS (BLO) { - tmp = regs.RdMem(regs.pc++); - if (regs.cc&0x01) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (regs.cc & 0x01) + regs.pc += word; + + regs.clock += 3; } -static void Op26(void) // BNE + +static void Op26(void) // BNE { - tmp = regs.RdMem(regs.pc++); - if (!(regs.cc&0x04)) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (!(regs.cc & 0x04)) + regs.pc += word; + + regs.clock += 3; } -static void Op27(void) // BEQ + +static void Op27(void) // BEQ { - tmp = regs.RdMem(regs.pc++); - if (regs.cc&0x04) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (regs.cc & 0x04) + regs.pc += word; + + regs.clock += 3; } -static void Op28(void) // BVC + +static void Op28(void) // BVC { - tmp = regs.RdMem(regs.pc++); - if (!(regs.cc&0x02)) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (!(regs.cc & 0x02)) + regs.pc += word; + + regs.clock += 3; } -static void Op29(void) // BVS + +static void Op29(void) // BVS { - tmp = regs.RdMem(regs.pc++); - if (regs.cc&0x02) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (regs.cc & 0x02) + regs.pc += word; + + regs.clock += 3; } -static void Op2A(void) // BPL + +static void Op2A(void) // BPL { - tmp = regs.RdMem(regs.pc++); - if (!(regs.cc&0x08)) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (!(regs.cc & 0x08)) + regs.pc += word; + + regs.clock += 3; } -static void Op2B(void) // BMI + +static void Op2B(void) // BMI { - tmp = regs.RdMem(regs.pc++); - if (regs.cc&0x08) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (regs.cc & 0x08) + regs.pc += word; + + regs.clock += 3; } -static void Op2C(void) // BGE + +static void Op2C(void) // BGE { - tmp = regs.RdMem(regs.pc++); - if (!(((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (!(((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02))) + regs.pc += word; + + regs.clock += 3; } -static void Op2D(void) // BLT + +static void Op2D(void) // BLT { - tmp = regs.RdMem(regs.pc++); - if (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02)) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02)) + regs.pc += word; + + regs.clock += 3; } -static void Op2E(void) // BGT + +static void Op2E(void) // BGT { - tmp = regs.RdMem(regs.pc++); - if (!((regs.cc&0x04) | (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02)))) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if (!((regs.cc & 0x04) | (((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02)))) + regs.pc += word; + + regs.clock += 3; } -static void Op2F(void) // BLE + +static void Op2F(void) // BLE { - tmp = regs.RdMem(regs.pc++); - if ((regs.cc&0x04) | (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))) regs.pc += SignedB(tmp); - regs.clock += 3; + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + + if ((regs.cc & 0x04) | (((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02))) + regs.pc += word; + + regs.clock += 3; } + static void Op30(void) // LEAX { regs.x = DecodeIDX(regs.RdMem(regs.pc++)); @@ -1375,13 +1500,17 @@ static void Op8C(void) // CMPX # (dw&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative flag regs.clock += 4; } -static void Op8D(void) // Bregs.s - { - tmp = regs.RdMem(regs.pc++); - regs.WrMem(--regs.s, regs.pc&0xFF); regs.WrMem(--regs.s, regs.pc>>8); - regs.pc += SignedB(tmp); - regs.clock += 7; - } + +static void Op8D(void) // Bregs.s +{ + uint16 word = (int16)(int8)regs.RdMem(regs.pc++); + regs.WrMem(--regs.s, regs.pc & 0xFF); + regs.WrMem(--regs.s, regs.pc >> 8); + regs.pc += word; + + regs.clock += 7; +} + static void Op8E(void) // LDX # { regs.x = FetchW(); @@ -2426,95 +2555,153 @@ static void OpFF(void) // STU ABS // Page one opcodes' execute code // -static void Op1021(void) // LBRN +static void Op1021(void) // LBRN { - addr = FetchW(); - regs.clock += 5; + addr = FetchW(); + + regs.clock += 5; } -static void Op1022(void) // LBHI + +static void Op1022(void) // LBHI { - addr = FetchW(); - if (!((regs.cc&0x01)|(regs.cc&0x04))) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if (!((regs.cc & 0x01) | (regs.cc & 0x04))) + regs.pc += word; + + regs.clock += 5; } -static void Op1023(void) // LBLS + +static void Op1023(void) // LBLS { - addr = FetchW(); - if ((regs.cc&0x01)|(regs.cc&0x04)) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if ((regs.cc & 0x01) | (regs.cc & 0x04)) + regs.pc += word; + + regs.clock += 5; } -static void Op1024(void) // LBCC (LBHS) + +static void Op1024(void) // LBCC (LBHS) { - addr = FetchW(); - if (!(regs.cc&0x01)) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if (!(regs.cc & 0x01)) + regs.pc += word; + + regs.clock += 5; } -static void Op1025(void) // LBCS (LBLO) + +static void Op1025(void) // LBCS (LBLO) { - addr = FetchW(); - if (regs.cc&0x01) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if (regs.cc & 0x01) + regs.pc += word; + + regs.clock += 5; } -static void Op1026(void) // LBNE + +static void Op1026(void) // LBNE { - addr = FetchW(); - if (!(regs.cc&0x04)) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if (!(regs.cc & 0x04)) + regs.pc += word; + + regs.clock += 5; } -static void Op1027(void) // LBEQ + +static void Op1027(void) // LBEQ { - addr = FetchW(); - if (regs.cc&0x04) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if (regs.cc & 0x04) + regs.pc += word; + + regs.clock += 5; } -static void Op1028(void) // LBVC + +static void Op1028(void) // LBVC { - addr = FetchW(); - if (!(regs.cc&0x02)) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if (!(regs.cc & 0x02)) + regs.pc += word; + + regs.clock += 5; } -static void Op1029(void) // LBVS + +static void Op1029(void) // LBVS { - addr = FetchW(); - if (regs.cc&0x02) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if (regs.cc & 0x02) + regs.pc += word; + + regs.clock += 5; } -static void Op102A(void) // LBPL + +static void Op102A(void) // LBPL { - addr = FetchW(); - if (!(regs.cc&0x08)) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if (!(regs.cc & 0x08)) + regs.pc += word; + + regs.clock += 5; } -static void Op102B(void) // LBMI + +static void Op102B(void) // LBMI { - addr = FetchW(); - if (regs.cc&0x08) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if (regs.cc & 0x08) + regs.pc += word; + + regs.clock += 5; } -static void Op102C(void) // LBGE + +static void Op102C(void) // LBGE { - addr = FetchW(); - if (!(((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if (!(((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02))) + regs.pc += word; + + regs.clock += 5; } -static void Op102D(void) // LBLT + +static void Op102D(void) // LBLT { - addr = FetchW(); - if (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02)) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if (((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02)) + regs.pc += word; + + regs.clock += 5; } -static void Op102E(void) // LBGT + +static void Op102E(void) // LBGT { - addr = FetchW(); - if (!((regs.cc&0x04) | (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02)))) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if (!((regs.cc & 0x04) | (((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02)))) + regs.pc += word; + + regs.clock += 5; } -static void Op102F(void) // LBLE + +static void Op102F(void) // LBLE { - addr = FetchW(); - if ((regs.cc&0x04) | (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))) regs.pc += SignedW(addr); - regs.clock += 5; + uint16 word = FetchW(); + + if ((regs.cc & 0x04) | (((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02))) + regs.pc += word; + + regs.clock += 5; } + static void Op103F(void) // SWI2 (Not yet implemented) { regs.clock += 20; @@ -2827,20 +3014,24 @@ static void Op11BC(void) // CMPS ABS } //temp, for testing... -/*static uint8 backTrace[256]; +#ifdef __DEBUG__ +static uint8 backTrace[256]; static uint16 btPC[256]; static int btPtr = 0;//*/ +#endif static void Op__(void) // Illegal opcode { regs.clock++; // illegal = true; regs.cpuFlags |= V6809_STATE_ILLEGAL_INST; +#ifdef __DEBUG__ /*WriteLog("V6809: Executed illegal opcode %02X at PC=%04X...\n\nBacktrace:\n\n", regs.RdMem(regs.pc - 1), regs.pc - 1); for(int i=0; i<256; i++) { - dpc = btPC[(btPtr+i)&0xFF]; - Decode_6809(); + Decode6809(btPC[(btPtr + i) & 0xFF]); + WriteLog("\n"); }//*/ +#endif } @@ -2858,24 +3049,76 @@ static void myMemcpy(void * dst, void * src, uint32 size) // // Function to execute 6809 instructions // +//#define DEBUG_ILLEGAL +#ifdef DEBUG_ILLEGAL +#include "log.h" +#include "dis6809.h" +uint8 btPtr = 0; +uint8 backTrace[256]; +V6809REGS btRegs[256]; +bool tripped = false; +#endif void Execute6809(V6809REGS * context, uint32 cycles) { + // If this is not in place, the clockOverrun calculations can cause the V6809 to get + // stuck in an infinite loop. + if (cycles == 0) // Nothing to do, so bail! + return; + myMemcpy(®s, context, sizeof(V6809REGS)); // Execute here... -uint32 clockSave = regs.clock; -regs.clock = 0; - while (regs.clock < cycles) + + // Since we can't guarantee that we'll execute the number of cycles passed in + // exactly, we have to keep track of how much we overran the number of cycles + // the last time we executed. Since we already executed those cycles, this time + // through we remove them from the cycles passed in in order to come out + // approximately even. Over the long run, this unevenness in execution times + // evens out. + uint64 endCycles = regs.clock + (uint64)(cycles - regs.clockOverrun); + + while (regs.clock < endCycles) { -/*static bool disasm = false; -if (regs.pc == 0x15BA) disasm = true; -if (disasm) { dpc = regs.pc; Decode_6809(); } -if (regs.pc == 0x164A) disasm = false;//*/ +#ifdef DEBUG_ILLEGAL +if (!tripped) +{ + backTrace[btPtr] = regs.RdMem(regs.pc); + btRegs[btPtr] = regs; + btPtr = (btPtr + 1) & 0xFF; + + if (regs.cpuFlags & V6809_STATE_ILLEGAL_INST) + { + WriteLog("V6809: Executed illegal instruction!!!!\n\nBacktrace:\n\n"); + regs.cpuFlags &= ~V6809_STATE_ILLEGAL_INST; + + for(uint16 i=btPtr; icpuFlags &= ~V6809_ASSERT_LINE_NMI;// Reset the asserted line (NMI)... - regs.cpuFlags &= ~V6809_ASSERT_LINE_NMI; // Reset the asserted line (NMI)... +// context->cpuFlags &= ~V6809_ASSERT_LINE_NMI;// Reset the asserted line (NMI)... +// regs.cpuFlags &= ~V6809_ASSERT_LINE_NMI; // Reset the asserted line (NMI)... } else if (flags & V6809_ASSERT_LINE_FIRQ) // *** FIRQ handler *** { +#ifdef __DEBUG__ +if (disasm) WriteLog("\nV6809: FIRQ line asserted!\n"); +#endif if (!(regs.cc & FLAG_F)) // Is the FIRQ masked (F == 1)? { +#ifdef __DEBUG__ +if (disasm) WriteLog(" FIRQ taken...\n"); +#endif regs.cc &= ~FLAG_E; // Clear the Entire flag regs.WrMem(--regs.s, regs.pc & 0xFF); // Save PC, CC regs... @@ -2926,14 +3181,20 @@ btPtr = (btPtr++) & 0xFF;//*/ regs.cc |= (FLAG_I | FLAG_F); // Set IRQ/FIRQ suppress flags regs.pc = RdMemW(0xFFF6); // And load PC with the IRQ vector regs.clock += 10; - context->cpuFlags &= ~V6809_ASSERT_LINE_FIRQ; // Reset the asserted line (FIRQ)... - regs.cpuFlags &= ~V6809_ASSERT_LINE_FIRQ; // Reset the asserted line (FIRQ)... +// context->cpuFlags &= ~V6809_ASSERT_LINE_FIRQ; // Reset the asserted line (FIRQ)... +// regs.cpuFlags &= ~V6809_ASSERT_LINE_FIRQ; // Reset the asserted line (FIRQ)... } } else if (flags & V6809_ASSERT_LINE_IRQ) // *** IRQ handler *** { +#ifdef __DEBUG__ +if (disasm) WriteLog("\nV6809: IRQ line asserted!\n"); +#endif if (!(regs.cc & FLAG_I)) // Is the IRQ masked (I == 1)? { +#ifdef __DEBUG__ +if (disasm) WriteLog(" IRQ taken...\n"); +#endif regs.cc |= FLAG_E; // Set the Entire flag regs.WrMem(--regs.s, regs.pc & 0xFF); // Save all regs... @@ -2952,14 +3213,50 @@ btPtr = (btPtr++) & 0xFF;//*/ regs.cc |= FLAG_I; // Specs say that it doesn't affect FIRQ... or FLAG_F [WAS: Set IRQ/FIRQ suppress flags] regs.pc = RdMemW(0xFFF8); // And load PC with the IRQ vector regs.clock += 19; +// Apparently, not done here! +// Need to put IRQ handling in somewhere... It shouldn't be cleared here! context->cpuFlags &= ~V6809_ASSERT_LINE_IRQ; // Reset the asserted line (IRQ)... regs.cpuFlags &= ~V6809_ASSERT_LINE_IRQ; // Reset the asserted line (IRQ)... } } -/*if (disasm) WriteLog("\tA=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X\n", +#ifdef __DEBUG__ +if (disasm) WriteLog("\tA=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X\n", + regs.a, regs.b, regs.cc, regs.dp, regs.x, regs.y, regs.s, regs.u, regs.pc);//*/ +/*WriteLog("\tA=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X\n", regs.a, regs.b, regs.cc, regs.dp, regs.x, regs.y, regs.s, regs.u, regs.pc);//*/ +#endif } -regs.clock += clockSave; + + // Keep track of how much we overran so we can adjust on the next run... + regs.clockOverrun = (uint32)(regs.clock - endCycles); myMemcpy(context, ®s, sizeof(V6809REGS)); } + +// +// Get the clock of the currently executing CPU +// +uint64 GetCurrentV6809Clock(void) +{ + return regs.clock; +} + +// +// Get the PC of the currently executing CPU +// +uint16 GetCurrentV6809PC(void) +{ + return regs.pc; +} + +// Set a line of the currently executing CPU +void SetLine(uint32 line) +{ + regs.cpuFlags |= line; +} + +// Clear a line of the currently executing CPU +void ClearLine(uint32 line) +{ + regs.cpuFlags &= ~line; +} diff --git a/src/v6809.h b/src/v6809.h index 6ad4424..9511654 100755 --- a/src/v6809.h +++ b/src/v6809.h @@ -3,7 +3,7 @@ // // by James L. Hammons // -// (c) 1997, 2004 Underground Software +// (C) 1997, 2004 Underground Software // #ifndef __V6809_H__ @@ -35,24 +35,29 @@ struct V6809REGS { - uint16 pc; // 6809 PC register + uint16 pc; // 6809 PC register uint16 x; // 6809 X index register uint16 y; // 6809 Y index register uint16 s; // 6809 System stack pointer uint16 u; // 6809 User stack pointer - uint8 cc; // 6809 Condition Code register + uint8 cc; // 6809 Condition Code register uint8 a; // 6809 A register uint8 b; // 6809 B register - uint8 dp; // 6809 Direct Page register - uint32 clock; // 6809 clock -//uint32 _reserved;// uint8 (* Fetch)(uint16&); // Address of uint8 fetch routine + uint8 dp; // 6809 Direct Page register +// uint32 clock; // 6809 clock (@ 1 MHz, wraps at 71.5 minutes) + uint64 clock; // 6809 clock (@ 1 MHz, wraps at 570842 years) uint8 (* RdMem)(uint16); // Address of uint8 read routine void (* WrMem)(uint16, uint8); // Address of uint8 write routine uint32 cpuFlags; // v6809 IRQ/RESET flags + uint32 clockOverrun; }; // Function prototypes -void Execute6809(V6809REGS *, uint32); // Function to execute 6809 instructions +void Execute6809(V6809REGS *, uint32); // Function to execute 6809 instructions +uint64 GetCurrentV6809Clock(void); // Get the clock of the currently executing CPU +uint16 GetCurrentV6809PC(void); // Get the PC of the currently executing CPU +void SetLine(uint32 line); // Set a line of the currently executing CPU +void ClearLine(uint32 line); // Clear a line of the currently executing CPU #endif // __V6809_H__ -- 2.37.2