//
-// Virtual 6809 v1.4.1
+// Virtual 6809 v1.4.2
//
-// by James L. Hammons
-// (C) 1997, 2009, 2014 Underground Software
+// by James Hammons
+// (C) 1997, 2009, 2014, 2023 Underground Software
//
-// JLH = James L. Hammons <jlhamm@acm.org>
+// JLH = James Hammons <jlhamm@acm.org>
//
// WHO WHEN WHAT
// --- ---------- -----------------------------------------------------------
// JLH 11/11/2006 Removed all SignedX() references
// JLH 09/29/2009 Converted V6809 to macro implementation!
// JLH 04/17/2014 Misc. cleanups, fixes to missing instructions
+// JLH 01/03/2023 Added missing clock cycles to indexed memory accesses
//
-#define __DEBUG__
-
#include "v6809.h"
-#ifdef __DEBUG__
-#include "dis6809.h" // Temporary...
-#include "log.h" // Temporary...
-bool disasm = false;//so we can extern this shit
-#endif
-
#define TEST_DONT_BRANCH_OPTIMIZATION
// Various macros
#define SET_V(a,b,r) (flagV = (((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x80) >> 7)
#define SET_V16(a,b,r) (flagV = (((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x8000) >> 15)
#define SET_H(a,b,r) (flagH = (((a) ^ (b) ^ (r)) & 0x10) >> 4)
-
-//Not sure that this code is computing the carry correctly... Investigate! [Seems to be]
-//#define SET_C_ADD(a,b) (flagC = ((uint8_t)(b) > (uint8_t)(~(a)) ? 1 : 0))
-//#define SET_C_SUB(a,b) (regs.cc = ((uint8_t)(b) >= (uint8_t)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))
-//#define SET_C_CMP(a,b) (flagC = ((uint8_t)(b) >= (uint8_t)(a) ? 1 : 0))
#define SET_ZN(r) SET_N(r); SET_Z(r)
#define SET_ZN16(r) SET_N16(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)
#define EA_IMM regs.pc++
#define EA_DP (regs.dp << 8) | regs.RdMem(regs.pc++)
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // $Fx
};
+// Cycle counts for PUL/PSHx instructions
+static uint8_t bitCount[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+
// Private function prototypes
static uint16_t RdMemW(uint16_t addr);
static uint16_t DecodeReg(uint8_t); // Decode register data
static uint16_t DecodeIDX(uint8_t); // Decode IDX data
-
//
// Read word from memory function
//
return (uint16_t)(regs.RdMem(addr) << 8) | regs.RdMem(addr + 1);
}
-
//
// Fetch a word from memory function. Increments PC
//
return (uint16_t)(regs.RdMem(addr) << 8) | regs.RdMem(addr + 1);
}
-
//
// Write word to memory function
//
regs.WrMem(addr + 1, w & 0xFF);
}
-
//
// Function to read TFR/EXG post byte
//
return retval;
}
-
//
// Function to set TFR/EXG data
//
}
}
-
//
// Function to decode register data
//
return retval;
}
-
//
// Function to decode IDX data
//
static uint16_t DecodeIDX(uint8_t code)
{
+/*
+Cycle counts are now taken into account here...
+
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+90 5 6 5 6 3 4 4 0 4 7 0 7 4 8 0 5
+B0 5 6 5 6 3 4 4 0 4 7 0 7 4 8 0 5
+D0 5 6 5 6 3 4 4 0 4 7 0 7 4 8 0 5
+F0 5 6 5 6 3 4 4 0 4 7 0 7 4 8 0 5
+
+80 2 3 2 3 0 1 1 0 1 4 0 4 1 5 0 5
+A0 2 3 2 3 0 1 1 0 1 4 0 4 1 5 0 5
+C0 2 3 2 3 0 1 1 0 1 4 0 4 1 5 0 5
+E0 2 3 2 3 0 1 1 0 1 4 0 4 1 5 0 5
+*/
uint16_t addr, woff;
+ int16_t offset;
uint8_t reg = (code & 0x60) >> 5, idxind = (code & 0x10) >> 4, lo_nyb = code & 0x0F;
if (!(code & 0x80)) // Hi bit unset? Then decode 4 bit offset
+ {
addr = DecodeReg(reg) + (idxind ? lo_nyb - 16 : lo_nyb);
+ regs.clock++;
+ }
else
{
if (idxind)
case 2: regs.u += 2; break;
case 3: regs.s += 2; break;
}
+ regs.clock += 6;
break;
case 3:
switch (reg)
}
woff = DecodeReg(reg);
addr = RdMemW(woff);
+ regs.clock += 6;
break;
case 4:
woff = DecodeReg(reg);
addr = RdMemW(woff);
+ regs.clock += 3;
break;
case 5:
woff = DecodeReg(reg) + (int16_t)(int8_t)regs.b;
addr = RdMemW(woff);
+ regs.clock += 4;
break;
case 6:
woff = DecodeReg(reg) + (int16_t)(int8_t)regs.a;
addr = RdMemW(woff);
+ regs.clock += 4;
break;
case 8:
woff = DecodeReg(reg) + (int16_t)(int8_t)regs.RdMem(regs.pc++);
addr = RdMemW(woff);
+ regs.clock += 4;
break;
case 9:
woff = DecodeReg(reg) + FetchMemW(regs.pc);
addr = RdMemW(woff);
+ regs.clock += 7;
break;
case 11:
woff = DecodeReg(reg) + ((regs.a << 8) | regs.b);
addr = RdMemW(woff);
+ regs.clock += 7;
break;
case 12:
// woff = regs.pc + (int16_t)(int8_t)regs.RdMem(regs.pc++);
+#if 1
+ // I believe this is the correct interpretation
+ offset = (int16_t)(int8_t)regs.RdMem(regs.pc++);
+ woff = regs.pc + offset;
+#else
woff = regs.pc + (int16_t)(int8_t)regs.RdMem(regs.pc);
regs.pc++;
+#endif
addr = RdMemW(woff);
+ regs.clock += 4;
break;
case 13:
woff = regs.pc + FetchMemW(regs.pc);
addr = RdMemW(woff);
+ regs.clock += 8;
break;
case 15:
woff = FetchMemW(regs.pc);
addr = RdMemW(woff);
+ regs.clock += 5;
break;
+ default:
+ addr = 0;
}
}
else
case 2: regs.u++; break;
case 3: regs.s++; break;
}
+ regs.clock += 2;
break;
case 1:
addr = DecodeReg(reg);
case 2: regs.u += 2; break;
case 3: regs.s += 2; break;
}
+ regs.clock += 3;
+ break;
+ case 2:
+ switch(reg)
+ {
+ case 0: regs.x--; break;
+ case 1: regs.y--; break;
+ case 2: regs.u--; break;
+ case 3: regs.s--; break;
+ }
+ addr = DecodeReg(reg);
+ regs.clock += 2;
+ break;
+ case 3:
+ switch(reg)
+ {
+ case 0: regs.x -= 2; break;
+ case 1: regs.y -= 2; break;
+ case 2: regs.u -= 2; break;
+ case 3: regs.s -= 2; break;
+ }
+ addr = DecodeReg(reg);
+ regs.clock += 3;
+ break;
+ case 4:
+ addr = DecodeReg(reg);
+ break;
+ case 5:
+ addr = DecodeReg(reg) + (int16_t)(int8_t)regs.b;
+ regs.clock++;
+ break;
+ case 6:
+ addr = DecodeReg(reg) + (int16_t)(int8_t)regs.a;
+ regs.clock++;
break;
- case 2: { switch(reg)
- {
- case 0: regs.x--; break;
- case 1: regs.y--; break;
- case 2: regs.u--; break;
- case 3: regs.s--; break;
- }
- addr = DecodeReg(reg); break; }
- case 3: { switch(reg)
- {
- case 0: regs.x--; regs.x--; break;
- case 1: regs.y--; regs.y--; break;
- case 2: regs.u--; regs.u--; break;
- case 3: regs.s--; regs.s--; break;
- }
- addr = DecodeReg(reg); break; }
- case 4: { addr = DecodeReg(reg); break; }
- case 5: { addr = DecodeReg(reg) + (int16_t)(int8_t)regs.b; break; }
- case 6: { addr = DecodeReg(reg) + (int16_t)(int8_t)regs.a; break; }
- case 8: { addr = DecodeReg(reg) + (int16_t)(int8_t)regs.RdMem(regs.pc++); break; }
- case 9: { addr = DecodeReg(reg) + FetchMemW(regs.pc); break; }
- case 11: { addr = DecodeReg(reg) + ((regs.a << 8) | regs.b); break; }
-// case 12: { addr = regs.pc + (int16_t)(int8_t)regs.RdMem(regs.pc++); break; }
- case 12: { addr = regs.pc + (int16_t)(int8_t)regs.RdMem(regs.pc); regs.pc++; break; }
- case 13: { addr = regs.pc + FetchMemW(regs.pc); break; }
+ case 8:
+ addr = DecodeReg(reg) + (int16_t)(int8_t)regs.RdMem(regs.pc++);
+ regs.clock++;
+ break;
+ case 9:
+ addr = DecodeReg(reg) + FetchMemW(regs.pc);
+ regs.clock += 4;
+ break;
+ case 11:
+ addr = DecodeReg(reg) + ((regs.a << 8) | regs.b);
+ regs.clock += 4;
+ break;
+ case 12:
+// addr = regs.pc + (int16_t)(int8_t)regs.RdMem(regs.pc++);
+#if 1
+ // I believe this is the correct interpretation of the above
+ offset = (int16_t)(int8_t)regs.RdMem(regs.pc++);
+ addr = regs.pc + offset;
+#else
+ addr = regs.pc + (int16_t)(int8_t)regs.RdMem(regs.pc);
+ regs.pc++;
+#endif
+ regs.clock++;
+ break;
+ case 13:
+ addr = regs.pc + FetchMemW(regs.pc);
+ regs.clock += 5;
+ break;
+ default:
+ addr = 0;
}
}
}
acc = sum & 0xFF; \
SET_ZN(acc)
-/*
-Old flag handling code:
- (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Adjust Carry
- ((regs.a^tmp^addr)&0x10 ? regs.cc |= 0x20 : regs.cc &= 0xDF); // Set Half carry
- ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
- regs.a = addr & 0xFF; // Set accumulator
- (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Adjust Zero
- (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative
-*/
-
static void Op89(void) // ADCA #
{
uint16_t m = READ_IMM;
OP_ADC_HANDLER(m, regs.a);
}
-
static void Op99(void) // ADCA DP
{
uint16_t m = READ_DP;
OP_ADC_HANDLER(m, regs.a);
}
-
static void OpA9(void) // ADCA IDX
{
uint16_t m = READ_IDX;
OP_ADC_HANDLER(m, regs.a);
}
-
static void OpB9(void) // ADCA ABS
{
uint16_t m = READ_ABS;
OP_ADC_HANDLER(m, regs.a);
}
-
static void OpC9(void) // ADCB #
{
uint16_t m = READ_IMM;
OP_ADC_HANDLER(m, regs.b);
}
-
static void OpD9(void) // ADCB DP
{
uint16_t m = READ_DP;
OP_ADC_HANDLER(m, regs.b);
}
-
static void OpE9(void) // ADCB IDX
{
uint16_t m = READ_IDX;
OP_ADC_HANDLER(m, regs.b);
}
-
static void OpF9(void) // ADCB ABS
{
uint16_t m = READ_ABS;
OP_ADC_HANDLER(m, regs.b);
}
-
/*
+-----------------------------------------------------------------+
| Opcode | | Addressing | | |
loreg = acc & 0xFF; \
SET_ZN16(acc)
-/*
-Old flags:
- (addr > 0xFF ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Set Carry flag
- ((regs.a^tmp^addr)&0x10 ? regs.cc |= 0x20 : regs.cc &= 0xDF); // Set Half carry
- ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
- regs.a = addr & 0xFF; // Set accumulator
- (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Set Zero flag
- (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Set Negative flag
-
- dr += addr;
- (dr > 0xFFFF ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Adjust Carry flag
- dr &= 0xFFFF;
- (dr == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Adjust Zero flag
- (dr&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative flag
- ((ds^addr^dr^(regs.cc<<15))&0x8000 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerfl
- regs.a = dr>>8; regs.b = dr&0xFF;
- regs.clock += 4;
-*/
-
static void Op3A(void) // ABX
{
regs.x += (uint16_t)regs.b;
}
-
static void Op8B(void) // ADDA #
{
uint16_t m = READ_IMM;
OP_ADD_HANDLER(m, regs.a);
}
-
static void Op9B(void) // ADDA DP
{
uint16_t m = READ_DP;
OP_ADD_HANDLER(m, regs.a);
}
-
static void OpAB(void) // ADDA IDX
{
uint16_t m = READ_IDX;
OP_ADD_HANDLER(m, regs.a);
}
-
static void OpBB(void) // ADDA ABS
{
uint16_t m = READ_ABS;
OP_ADD_HANDLER(m, regs.a);
}
-
static void OpC3(void) // ADDD #
{
uint32_t m = READ_IMM16;
OP_ADD_HANDLER16(m, regs.a, regs.b);
}
-
static void OpCB(void) // ADDB #
{
uint16_t m = READ_IMM;
OP_ADD_HANDLER(m, regs.b);
}
-
static void OpD3(void) // ADDD DP
{
uint32_t m = READ_DP16;
OP_ADD_HANDLER16(m, regs.a, regs.b);
}
-
static void OpDB(void) // ADDB DP
{
uint16_t m = READ_DP;
OP_ADD_HANDLER(m, regs.b);
}
-
static void OpE3(void) // ADDD IDX
{
uint32_t m = READ_IDX16;
OP_ADD_HANDLER16(m, regs.a, regs.b);
}
-
static void OpEB(void) // ADDB IDX
{
uint16_t m = READ_IDX;
OP_ADD_HANDLER(m, regs.b);
}
-
static void OpF3(void) // ADDD ABS
{
uint32_t m = READ_ABS16;
OP_ADD_HANDLER16(m, regs.a, regs.b);
}
-
static void OpFB(void) // ADDB ABS
{
uint16_t m = READ_ABS;
OP_ADD_HANDLER(m, regs.b);
}
-
/*
+-----------------------------------------------------------------+
| Opcode | | Addressing | | |
{
// C
int16_t offset = (int16_t)(int8_t)READ_IMM;
-//if (disasm)
-// WriteLog("[offset=%04X,flagC=%08X]", offset, flagC);
#ifdef TEST_DONT_BRANCH_OPTIMIZATION
regs.pc += offset * flagC;
static void Op3E(void) // RESET
{
- regs.cpuFlags |= V6809_ASSERT_LINE_RESET;
+ regs.cpuFlags |= V6809_LINE_RESET;
}
static void Op3F(void) // SWI
{
}
-/*
-D3F8: A6 47 LDA (7),U CC=--H----- A=30 B=00 DP=9C X=3C72 Y=CE5C S=BFFF U=BAF0 PC=D3FA
-D3FA: 8B 01 ADDA #$01 CC=--H----- A=31 B=00 DP=9C X=3C72 Y=CE5C S=BFFF U=BAF0 PC=D3FC
-D3FC: 19 DAA CC=--H----- A=37 B=00 DP=9C X=3C72 Y=CE5C S=BFFF U=BAF0 PC=D3FD
-*/
-
static void Op19() // DAA
{
uint16_t result = (uint16_t)regs.a;
-// if ((regs.a & 0x0F) > 0x09 || (regs.cc & FLAG_H))
if ((regs.a & 0x0F) > 0x09 || flagH)
result += 0x06;
-// if ((regs.a & 0xF0) > 0x90 || (regs.cc & FLAG_C) || ((regs.a & 0xF0) > 0x80 && (regs.a & 0x0F) > 0x09))
if ((regs.a & 0xF0) > 0x90 || flagC || ((regs.a & 0xF0) > 0x80 && (regs.a & 0x0F) > 0x09))
result += 0x60;
WRITE_BACK(m);
}
-
static void Op4C(void) // INCA
{
OP_INC_HANDLER(regs.a);
}
-
static void Op5C(void) // INCB
{
OP_INC_HANDLER(regs.b);
}
-
static void Op6C(void) // INC IDX
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op7C(void) // INC ABS
{
uint8_t m;
WRITE_BACK(m);
}
-
/*
+-----------------------------------------------------------------+
| Opcode | | Addressing | | |
regs.pc = m;
}
-
static void Op17(void) // LBSR
{
uint16_t word = FetchMemW(regs.pc);
regs.pc += word;
}
-
static void Op39(void) // RTS
{
PULLS16(regs.pc);
}
-
static void Op3B(void) // RTI
{
PULLS(regs.cc);
PULLS16(regs.pc);
}
-
static void Op6E(void) // JMP IDX
{
regs.pc = EA_IDX;
}
-
static void Op7E(void) // JMP ABS
{
regs.pc = EA_ABS;
}
-
static void Op8D(void) // BSR
{
uint16_t word = (int16_t)(int8_t)READ_IMM;
regs.pc += word;
}
-
static void Op9D(void) // JSR DP
{
uint16_t word = EA_DP;
regs.pc = word;
}
-
static void OpAD(void) // JSR IDX
{
uint16_t word = EA_IDX;
regs.pc = word;
}
-
static void OpBD(void) // JSR ABS
{
uint16_t word = EA_ABS;
regs.pc = word;
}
-
/*
+-----------------------------------------------------------------+
| Opcode | | Addressing | | |
flagC = (res >= 0x80 ? 1 : 0); \
m = res
-/*
- UINT16 r,t;
- DIRBYTE(t);
- r = -t;
- CLR_NZVC;
- SET_FLAGS8(0,t,r);
- WM(EAD,r);
-#define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);}
-#define SET_C8(a) CC|=((a&0x100)>>8)
-*/
static void Op00(void) // NEG DP
{
uint8_t m;
}
// Count bits in each nybble to come up with correct cycle counts...
- uint8_t bitCount[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
regs.clock += (1 * bitCount[m & 0x0F]) + (2 * bitCount[m >> 4]);
}
PULLS16(regs.pc);
// Count bits in each nybble to come up with correct cycle counts...
- uint8_t bitCount[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
regs.clock += (1 * bitCount[m & 0x0F]) + (2 * bitCount[m >> 4]);
}
}
// Count bits in each nybble to come up with correct cycle counts...
- uint8_t bitCount[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
regs.clock += (1 * bitCount[m & 0x0F]) + (2 * bitCount[m >> 4]);
}
PULLU16(regs.pc);
// Count bits in each nybble to come up with correct cycle counts...
- uint8_t bitCount[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
regs.clock += (1 * bitCount[m & 0x0F]) + (2 * bitCount[m >> 4]);
}
flagC = (m >> 7) & 0x01; \
m = res
-/*
- UINT16 t,r;
- DIRBYTE(t);
- r = (CC & CC_C) | (t << 1);
- CLR_NZVC;
- SET_FLAGS8(t,t,r);
- WM(EAD,r);
-*/
static void Op09(void) // ROL DP
{
uint8_t m;
OP_TST_HANDLER(m);
}
-
static void Op4D(void) // TSTA
{
OP_TST_HANDLER(regs.a);
}
-
static void Op5D(void) // TSTB
{
OP_TST_HANDLER(regs.b);
}
-
static void Op6D(void) // TST IDX
{
uint8_t m = READ_IDX;
OP_TST_HANDLER(m);
}
-
static void Op7D(void) // TST ABS
{
uint8_t m = READ_ABS;
OP_TST_HANDLER(m);
}
-
//
// Undocumented Opcodes
//
Op00(); // NEG DP
}
-
-//temp, for testing...
-#ifdef __DEBUG__
-static uint8_t backTrace[256];
-static uint16_t 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++)
-{
- Decode6809(btPC[(btPtr + i) & 0xFF]);
- WriteLog("\n");
-}//*/
-#endif
}
//
Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__
};
-
// These are here to save typing a ton of forward declarations...
-
// Page 1 opcode
static void Op10(void)
{
-// exec_op1[regs.RdMem(regs.pc++)]();
uint8_t opcode = regs.RdMem(regs.pc++);
exec_op1[opcode]();
regs.clock += page1Cycles[opcode];
}
-
// Page 2 opcode
static void Op11(void)
{
-// exec_op2[regs.RdMem(regs.pc++)]();
uint8_t opcode = regs.RdMem(regs.pc++);
exec_op2[opcode]();
regs.clock += page2Cycles[opcode];
}
-
//
// Internal "memcpy" (so we don't have to link with any external libraries!)
//
d[i] = s[i];
}
-
//
// Function to execute 6809 instructions
//
-//#define DEBUG_ILLEGAL
-#ifdef DEBUG_ILLEGAL
-#include "log.h"
-#include "dis6809.h"
-uint8_t btPtr = 0;
-uint8_t backTrace[256];
-V6809REGS btRegs[256];
-bool tripped = false;
-#endif
void Execute6809(V6809REGS * context, uint32_t cycles)
{
// If this is not in place, the clockOverrun calculations can cause the
// V6809 to get stuck in an infinite loop.
- if (cycles == 0)
+ if (cycles == 0) // Nothing to do, so bail!
return;
myMemcpy(®s, context, sizeof(V6809REGS));
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_t 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__
-if (disasm)
-{
- Decode6809(regs);
-// WriteLog("[e=%02X,f=%02X,h=%02X,i=%02X,n=%02X,z=%02X,v=%02X,c=%02X]", flagE, flagF, flagH, flagI, flagN, flagZ, flagV, flagC);
-}
-#if 0 //we solved this...
-if ((flagE | flagF | flagH | flagI | flagN | flagZ | flagV | flagC) > 1)
- WriteLog("\n\n!!! FLAG OUT OF BOUNDS !!!\n\n");
-#endif
-//static bool disasm = false;
-/*//if (regs.pc == 0x15BA) disasm = true;
-//if (regs.pc == 0xFE76) disasm = true;
-if (regs.x == 0xFED4) disasm = true;
-if (disasm) Decode6809(regs.pc);
-//if (regs.pc == 0x164A) disasm = false;//*/
-
-//temp, for testing...
-/*backTrace[btPtr] = regs.RdMem(regs.pc);
-btPC[btPtr] = regs.pc;
-btPtr = (btPtr + 1) & 0xFF;//*/
-#endif
-// exec_op0[regs.RdMem(regs.pc++)]();
uint8_t opcode = regs.RdMem(regs.pc++);
exec_op0[opcode]();
regs.clock += page0Cycles[opcode];
// uint32_t flags = context->cpuFlags;
uint32_t flags = regs.cpuFlags;
- if (flags & V6809_ASSERT_LINE_RESET) // *** RESET handler ***
+ // *** RESET handler ***
+ if (flags & V6809_LINE_RESET)
{
-#ifdef __DEBUG__
-if (disasm) WriteLog("\nV6809: RESET line asserted!\n");
-#endif
flagF = flagI = 1; // Set F, I
regs.dp = 0; // Reset direct page register
regs.pc = RdMemW(0xFFFE); // And load PC with the RESET vector
- context->cpuFlags &= ~V6809_ASSERT_LINE_RESET;
- regs.cpuFlags &= ~V6809_ASSERT_LINE_RESET;
+ context->cpuFlags &= ~V6809_LINE_RESET;
+ regs.cpuFlags &= ~V6809_LINE_RESET;
}
- else if (flags & V6809_ASSERT_LINE_NMI) // *** NMI handler ***
+ // *** NMI handler ***
+ else if (flags & V6809_LINE_NMI)
{
-#ifdef __DEBUG__
-if (disasm) WriteLog("\nV6809: NMI line asserted!\n");
-#endif
flagE = 1; // Set Entire flag
regs.cc = PACK_FLAGS; // Mash flags back into the CC register
flagI = flagF = 1; // 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)...
}
- else if (flags & V6809_ASSERT_LINE_FIRQ) // *** FIRQ handler ***
+ // *** FIRQ handler ***
+ else if (flags & V6809_LINE_FIRQ)
{
-#ifdef __DEBUG__
-if (disasm) WriteLog("\nV6809: FIRQ line asserted!\n");
-#endif
if (!flagF) // Is the FIRQ masked (F == 1)?
{
-#ifdef __DEBUG__
-if (disasm) WriteLog(" FIRQ taken...\n");
-#endif
flagE = 0; // Clear Entire flag
regs.cc = PACK_FLAGS; // Mash flags back into the CC register
flagI = flagF = 1; // 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)...
}
}
- else if (flags & V6809_ASSERT_LINE_IRQ) // *** IRQ handler ***
+ // *** IRQ handler ***
+ else if (flags & V6809_LINE_IRQ)
{
-#ifdef __DEBUG__
-if (disasm) WriteLog("\nV6809: IRQ line asserted!\n");
-#endif
if (!flagI) // Is the IRQ masked (I == 1)?
{
-#ifdef __DEBUG__
-if (disasm) WriteLog(" IRQ taken...\n");
-#endif
flagE = 1; // Set the Entire flag
regs.cc = PACK_FLAGS; // Mash flags back into the CC register
flagI = 1; // 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!
-// context->cpuFlags &= ~V6809_ASSERT_LINE_IRQ; // Reset the asserted line (IRQ)...
-// regs.cpuFlags &= ~V6809_ASSERT_LINE_IRQ; // Reset the asserted line (IRQ)...
}
}
-#ifdef __DEBUG__
-if (disasm) WriteLog("CC=%s%s%s%s%s%s%s%s A=%02X B=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X\n",
- (flagE ? "E" : "-"), (flagF ? "F" : "-"), (flagH ? "H" : "-"), (flagI ? "I" : "-"),
- (flagN ? "N" : "-"), (flagZ ? "Z" : "-"), (flagV ? "V" : "-"), (flagC ? "C" : "-"),
- regs.a, regs.b, 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
}
// Keep track of how much we overran so we can adjust on the next run...
myMemcpy(context, ®s, sizeof(V6809REGS));
}
-
//
// Get the clock of the currently executing CPU
//
return regs.clock;
}
-
//
// Get the PC of the currently executing CPU
//
return regs.pc;
}
-
// Set a line of the currently executing CPU
void SetLineOfCurrentV6809(uint32_t line)
{
regs.cpuFlags |= line;
}
-
// Clear a line of the currently executing CPU
void ClearLineOfCurrentV6809(uint32_t line)
{
-#ifdef __DEBUG__
-if (disasm)
- WriteLog("V6809: Clearing line %s...", (line == V6809_ASSERT_LINE_IRQ ? "IRQ" : "OTHER"));
-#endif
regs.cpuFlags &= ~line;
}
-
-#if 0
-FE54: 27 6A BEQ $FEC0 CC=EF-I-Z-- A=39 B=01 DP=00 X=FEE2 Y=F51
-E S=BFFF U=0000 PC=FEC0
-FEC0: 6E A4 JMP ,Y CC=EF-I-Z-- A=39 B=01 DP=00 X=FEE2 Y=F51E S=BFFF
- U=0000 PC=F51E
-F51E: 86 34 LDA #$34 CC=EF-I---- A=34 B=01 DP=00 X=FEE2 Y=F51E S=BFFF
- U=0000 PC=F520
-F520: B7 C8 0D STA $C80D CC=EF-I---- A=34 B=01 DP=00 X=FEE2 Y=F51E S=BFFF U=0000 PC=F523
-F523: B7 C8 0F STA $C80F CC=EF-I---- A=34 B=01 DP=00 X=FEE2 Y=F51E S=BFFF U=0000 PC=F526
-F526: 7F C8 0E CLR $C80EV6809: Clearing line IRQ... CC=EF-I-Z-- A=34 B=01 DP=00 X=FEE2 Y=F51E S=BFFF U=0000 PC=F529
-F529: 86 9C LDA #$9C CC=EF-IN--- A=9C B=01 DP=00 X=FEE2 Y=F51E S=BFFF U=0000 PC=F52B
-F52B: 1F 8B TFR A,DP CC=EF-IN--- A=9C B=01 DP=9C X=FEE2 Y=F51E S=BFFF U=0000 PC=F52D
-F52D: 10 CE BF FF LDS #$BFFF CC=EF-IN--- A=9C B=01 DP=9C X=FEE2 Y=F51E S=BFFF U=0000 PC=F531
-F531: BD 13 BD JSR $13BD CC=EF-IN--- A=9C B=01 DP=9C X=FEE2 Y=F51E S=BFFD U=0000 PC=13BD
-13BD: 34 76 PSHS A B X Y U CC=EF-IN--- A=9C B=01 DP=9C X=FEE2 Y=F51E S=BFF5 U=0000 PC=13BF
-13BF: CE 9C 00 LDU #$9C00 CC=EF-IN--- A=9C B=01 DP=9C X=FEE2 Y=F51E S=BFF5 U=9C00 PC=13C2
-13C2: 8E 00 00 LDX #$0000 CC=EF-I-Z-- A=9C B=01 DP=9C X=0000 Y=F51E S=BFF5 U=9C00 PC=13C5
-13C5: 1F 12 TFR X,Y CC=EF-I-Z-- A=9C B=01 DP=9C X=0000 Y=0000 S=BFF5 U=9C00 PC=13C7
-13C7: 1F 10 TFR X,D CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFF5 U=9C00 PC=13C9
-13C9: 36 36 PSHU A B X Y CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFEF U=9C00 PC=13CB
-13CB: 36 36 PSHU A B X Y CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFE9 U=9C00 PC=13CD
-13CD: 36 36 PSHU A B X Y CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFE3 U=9C00 PC=13CF
-13CF: 36 36 PSHU A B X Y CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFDD U=9C00 PC=13D1
-13D1: 36 36 PSHU A B X Y CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFD7 U=9C00 PC=13D3
-13D3: 36 10 PSHU X CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFD5 U=9C00 PC=13D5
-13D5: 11 83 00 00 CMPU #$0000 CC=EF-IN--- A=00 B=00 DP=9C X=0000 Y=000
-#endif