// We have a start... ;-)
//
-#define __DEBUG__
+//#define __DEBUG__
#include "v6809.h"
#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*???
#define EA_IMM regs.pc++
#define EA_ZP regs.RdMem(regs.pc++)
#define EA_ZP_X (regs.RdMem(regs.pc++) + regs.x) & 0xFF
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
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;
}
addr = DecodeReg(reg); break; }
case 4: { addr = DecodeReg(reg); break; }
-// case 5: { addr = DecodeReg(reg) + SignedB(regs.b); break; }
case 5: { addr = DecodeReg(reg) + (int16)(int8)regs.b; break; }
-// case 6: { addr = DecodeReg(reg) + SignedB(regs.a); break; }
case 6: { addr = DecodeReg(reg) + (int16)(int8)regs.a; break; }
-// case 8: { addr = DecodeReg(reg) + SignedB(regs.RdMem(regs.pc++)); break; }
case 8: { addr = DecodeReg(reg) + (int16)(int8)regs.RdMem(regs.pc++); break; }
-// case 9: { addr = DecodeReg(reg) + SignedW(FetchW()); break; }
case 9: { addr = DecodeReg(reg) + FetchW(); break; }
-// case 11: { addr = DecodeReg(reg) + SignedW((regs.a << 8) | regs.b); break; }
case 11: { addr = DecodeReg(reg) + ((regs.a << 8) | regs.b); break; }
-// case 12: { addr = regs.pc + SignedB(regs.RdMem(regs.pc++)); break; }
case 12: { addr = regs.pc + (int16)(int8)regs.RdMem(regs.pc++); break; }
-// case 13: { addr = regs.pc + SignedW(FetchW()); break; }
case 13: { addr = regs.pc + FetchW(); break; }
}
}
//
// 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...
- 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)
+ {
+#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; i<btPtr+256; i++)
+ {
+ Decode6809(btRegs[i & 0xFF].pc);
+// Note that these values are *before* execution, so stale...
+ WriteLog("\n\tA=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X\n",
+ btRegs[i & 0xFF].a, btRegs[i & 0xFF].b, btRegs[i & 0xFF].cc, btRegs[i & 0xFF].dp, btRegs[i & 0xFF].x, btRegs[i & 0xFF].y, btRegs[i & 0xFF].s, btRegs[i & 0xFF].u, btRegs[i & 0xFF].pc);//*/
+ }
+
+ tripped = true;
+ }
+}
+#endif
#ifdef __DEBUG__
//Decode6809(regs.pc);
static bool disasm = false;
regs.cc |= (FLAG_I | FLAG_F); // Set IRQ/FIRQ suppress flags
regs.pc = RdMemW(0xFFFC); // And load PC with the NMI vector
regs.clock += 19;
- context->cpuFlags &= ~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 ***
{
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 ***
#endif
}
+ // 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
//
-uint32 GetCurrentV6809Clock(void)
+uint64 GetCurrentV6809Clock(void)
{
return regs.clock;
}