]> Shamusworld >> Repos - stargem2/blobdiff - src/v6809.cpp
Change V6808 clock to 64-bit, added possible "don't branch" optimization
[stargem2] / src / v6809.cpp
index 45e072d1363bff8b92d294049695534eb699b148..a8b24fadfb6266463606eaf21619d1fe733d1335 100755 (executable)
@@ -17,7 +17,7 @@
 // We have a start... ;-)
 //
 
-#define __DEBUG__
+//#define __DEBUG__
 
 #include "v6809.h"
 
@@ -46,6 +46,8 @@
 #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
@@ -218,13 +220,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
@@ -384,37 +379,30 @@ 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;
@@ -465,19 +453,12 @@ uint16 DecodeIDX(uint8 code)
                    }
                    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; }
                        }
                }
@@ -3069,13 +3050,60 @@ 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(&regs, 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;
@@ -3130,8 +3158,8 @@ if (disasm) WriteLog("\nV6809: NMI line asserted!\n");
                        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 ***
                {
@@ -3152,8 +3180,8 @@ if (disasm) WriteLog("       FIRQ taken...\n");
                                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 ***
@@ -3197,13 +3225,16 @@ if (disasm) WriteLog("\tA=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04
 #endif
        }
 
+       // Keep track of how much we overran so we can adjust on the next run...
+       regs.clockOverrun = (uint32)(regs.clock - endCycles);
+
        myMemcpy(context, &regs, sizeof(V6809REGS));
 }
 
 //
 // Get the clock of the currently executing CPU
 //
-uint32 GetCurrentV6809Clock(void)
+uint64 GetCurrentV6809Clock(void)
 {
        return regs.clock;
 }