// work well. It's a fair sight better than the one that's in MAME,
// that's for sure. :-D
-// Some random thoughts: Could there be a performance gain by breaking
-// out the flags in regs.cc into separate uint8_t variables (or bools)?
-// You'd have to convert on entering and exiting the emulation loop, but I
-// think the perfomance hit would be negligible compared to the gain in not
-// having to mask and shift flags all the time. Investigate after the
-// conversion to macro style opcodes is completed. :-)
-// [DONE--remain to be seen if there is any performance increase]
-
-//#define __DEBUG__
+#define __DEBUG__
#define TEST_DONT_BRANCH_OPTIMIZATION
#include "v63701.h"
#ifdef __DEBUG__
#include "dis63701.h"
//#include "log.h"
+#include <stdio.h> // for printf()
#define WriteLog printf
#endif
#define WRITE_BACK(d) regs.WrMem(addr, (d))
-#define PULL regs.RdMem(regs.s++)
-#define PUSH(r) regs.WrMem(--regs.s, (r))
-#define PULL16 RdMemW(regs.s); regs.s += 2
-#define PUSH16(r) regs.WrMem(--regs.s, (r) & 0xFF); regs.WrMem(--regs.s, (r) >> 8)
+// This is correct; PUSH writes the location *then* decrements the stack
+// pointer, and PULL does the opposite. Verified from the data sheet.
+#define PULL regs.RdMem(++regs.s)
+#define PUSH(r) regs.WrMem(regs.s--, (r))
+#define PULL16 RdMemW(++regs.s); ++regs.s;
+#define PUSH16(r) regs.WrMem(regs.s--, (r) & 0xFF); regs.WrMem(regs.s--, (r) >> 8)
#define PACK_FLAGS ((regs.cc & 0xC0) | (flagH << 5) | (flagI << 4) | (flagN << 3) | (flagZ << 2) | (flagV << 1) | flagC)
#define UNPACK_FLAGS flagH = (regs.cc & FLAG_H) >> 5; \
// Private global variables
static V63701REGS regs;
+//V63701REGS regs;
static V63701REGS * regsPointer;
+//V63701REGS * regsPointer;
static uint8_t flagH, flagI, flagN, flagZ, flagV, flagC;
static uint8_t CPUCycles[256] = {
static uint16_t FetchMemW(uint16_t);
static inline void HandleInterrupt(uint16_t, uint16_t flag = 0);
-
//
// Read a word out of 63701 memory (little endian format)
//
return (uint16_t)(regs.RdMem(address) << 8) | regs.RdMem(address + 1);
}
-
//
// Fetch a word out of 63701 memory (little endian format). Increments PC
//
return (uint16_t)(regs.RdMem(address) << 8) | regs.RdMem(address + 1);
}
-
//
// 63701 OPCODE IMPLEMENTATION
//
OP_ADD_HANDLER(m, regs.d.acc.a);
}
-
static void Op9B(void) // ADDA ZP
{
uint16_t m = READ_ZP;
OP_ADD_HANDLER(m, regs.d.acc.a);
}
-
static void OpAB(void) // ADDA ZP, X
{
uint16_t m = READ_ZP_X;
OP_ADD_HANDLER(m, regs.d.acc.a);
}
-
static void OpBB(void) // ADDA ABS
{
uint16_t m = READ_ABS;
OP_ADD_HANDLER(m, regs.d.acc.a);
}
-
static void OpCB(void) // ADDB #
{
uint16_t m = READ_IMM;
OP_ADD_HANDLER(m, regs.d.acc.b);
}
-
static void OpDB(void) // ADDB ZP
{
uint16_t m = READ_ZP;
OP_ADD_HANDLER(m, regs.d.acc.b);
}
-
static void OpEB(void) // ADDB ZP, X
{
uint16_t m = READ_ZP_X;
OP_ADD_HANDLER(m, regs.d.acc.b);
}
-
static void OpFB(void) // ADDB ABS
{
uint16_t m = READ_ABS;
OP_ADD_HANDLER(m, regs.d.acc.b);
}
-
static void Op1B(void) // ABA
{
OP_ADD_HANDLER(regs.d.acc.b, regs.d.acc.a);
}
-
static void Op3A(void) // ABX
{
// Seems this one does *not* affect any flags...
regs.x += (uint16_t)regs.d.acc.b;
}
-
static void OpC3(void) // ADDD #
{
uint16_t m = READ_IMM16;
OP_ADD_HANDLER16(m, regs.d.word);
}
-
static void OpD3(void) // ADDD ZP
{
uint16_t m = READ_ZP16;
OP_ADD_HANDLER16(m, regs.d.word);
}
-
static void OpE3(void) // ADDD ZP, X
{
uint16_t m = READ_ZP_X16;
OP_ADD_HANDLER16(m, regs.d.word);
}
-
static void OpF3(void) // ADDD ABS
{
uint16_t m = READ_ABS16;
OP_ADD_HANDLER16(m, regs.d.word);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
OP_ADC_HANDLER(m, regs.d.acc.a);
}
-
static void Op99(void) // ADCA ZP
{
uint16_t m = READ_ZP;
OP_ADC_HANDLER(m, regs.d.acc.a);
}
-
static void OpA9(void) // ADCA ZP, X
{
uint16_t m = READ_ZP_X;
OP_ADC_HANDLER(m, regs.d.acc.a);
}
-
static void OpB9(void) // ADCA ABS
{
uint16_t m = READ_ABS;
OP_ADC_HANDLER(m, regs.d.acc.a);
}
-
static void OpC9(void) // ADCB #
{
uint16_t m = READ_IMM;
OP_ADC_HANDLER(m, regs.d.acc.b);
}
-
static void OpD9(void) // ADCB ZP
{
uint16_t m = READ_ZP;
OP_ADC_HANDLER(m, regs.d.acc.b);
}
-
static void OpE9(void) // ADCB ZP, X
{
uint16_t m = READ_ZP_X;
OP_ADC_HANDLER(m, regs.d.acc.b);
}
-
static void OpF9(void) // ADCB ABS
{
uint16_t m = READ_ABS;
OP_ADC_HANDLER(m, regs.d.acc.b);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
OP_AND_HANDLER(m, regs.d.acc.a);
}
-
static void Op94(void) // ANDA ZP
{
uint8_t m = READ_ZP;
OP_AND_HANDLER(m, regs.d.acc.a);
}
-
static void OpA4(void) // ANDA ZP, X
{
uint16_t m = READ_ZP_X;
OP_AND_HANDLER(m, regs.d.acc.a);
}
-
static void OpB4(void) // ANDA ABS
{
uint16_t m = READ_ABS;
OP_AND_HANDLER(m, regs.d.acc.a);
}
-
static void OpC4(void) // ANDB #
{
uint8_t m = READ_IMM;
OP_AND_HANDLER(m, regs.d.acc.b);
}
-
static void OpD4(void) // ANDB ZP
{
uint8_t m = READ_ZP;
OP_AND_HANDLER(m, regs.d.acc.b);
}
-
static void OpE4(void) // ANDB ZP, X
{
uint16_t m = READ_ZP_X;
OP_AND_HANDLER(m, regs.d.acc.b);
}
-
static void OpF4(void) // ANDB ABS
{
uint16_t m = READ_ABS;
OP_AND_HANDLER(m, regs.d.acc.b);
}
-
static void Op61(void) // AIM ZP, X (AND immediate with index)
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op71(void) // AIM ZP (AND immediate with zero page)
{
uint8_t m;
WRITE_BACK(m);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
OP_BIT_HANDLER(m, regs.d.acc.a);
}
-
static void Op95(void) // BITA ZP
{
uint8_t m = READ_ZP;
OP_BIT_HANDLER(m, regs.d.acc.a);
}
-
static void OpA5(void) // BITA ZP, X
{
uint8_t m = READ_ZP_X;
OP_BIT_HANDLER(m, regs.d.acc.a);
}
-
static void OpB5(void) // BITA ABS
{
uint8_t m = READ_ABS;
OP_BIT_HANDLER(m, regs.d.acc.a);
}
-
static void OpC5(void) // BITB #
{
uint8_t m = READ_IMM;
OP_BIT_HANDLER(m, regs.d.acc.b);
}
-
static void OpD5(void) // BITB ZP
{
uint8_t m = READ_ZP;
OP_BIT_HANDLER(m, regs.d.acc.b);
}
-
static void OpE5(void) // BITB ZP, X
{
uint8_t m = READ_ZP_X;
OP_BIT_HANDLER(m, regs.d.acc.b);
}
-
static void OpF5(void) // BITB ABS
{
uint8_t m = READ_ABS;
SET_Z(0);
}
-
static void Op7F(void) // CLR ABS
{
regs.WrMem(EA_ABS, 0);
SET_Z(0);
}
-
static void Op4F(void) // CLRA
{
regs.d.acc.a = 0;
SET_Z(0);
}
-
static void Op5F(void) // CLRB
{
regs.d.acc.b = 0;
OP_CMP_HANDLER(m, regs.d.acc.a);
}
-
static void Op91(void) // CMPA ZP
{
uint8_t m = READ_ZP;
OP_CMP_HANDLER(m, regs.d.acc.a);
}
-
static void OpA1(void) // CMPA ZP, X
{
uint8_t m = READ_ZP_X;
OP_CMP_HANDLER(m, regs.d.acc.a);
}
-
static void OpB1(void) // CMPA ABS
{
uint8_t m = READ_ABS;
OP_CMP_HANDLER(m, regs.d.acc.a);
}
-
static void OpC1(void) // CMPB #
{
uint8_t m = READ_IMM;
OP_CMP_HANDLER(m, regs.d.acc.b);
}
-
static void OpD1(void) // CMPB ZP
{
uint8_t m = READ_ZP;
OP_CMP_HANDLER(m, regs.d.acc.b);
}
-
static void OpE1(void) // CMPB ZP, X
{
uint8_t m = READ_ZP_X;
OP_CMP_HANDLER(m, regs.d.acc.b);
}
-
static void OpF1(void) // CMPB ABS
{
uint8_t m = READ_ABS;
OP_CMP_HANDLER(m, regs.d.acc.b);
}
-
static void Op11(void) // CBA
{
OP_CMP_HANDLER(regs.d.acc.b, regs.d.acc.a);
WRITE_BACK(m);
}
-
static void Op73(void) // COM ABS
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op43(void) // COMA
{
OP_COM_HANDLER(regs.d.acc.a);
}
-
static void Op53(void) // COMB
{
OP_COM_HANDLER(regs.d.acc.b);
WRITE_BACK(m);
}
-
static void Op70(void) // NEG ABS
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op40(void) // NEGA
{
OP_NEG_HANDLER(regs.d.acc.a);
}
-
static void Op50(void) // NEGB
{
OP_NEG_HANDLER(regs.d.acc.b);
WRITE_BACK(m);
}
-
static void Op7A(void) // DEC ABS
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op4A(void) // DECA
{
OP_DEC_HANDLER(regs.d.acc.a);
}
-
static void Op5A(void) // DECB
{
OP_DEC_HANDLER(regs.d.acc.b);
OP_EOR_HANDLER(m, regs.d.acc.a);
}
-
static void Op98(void) // EORA ZP
{
uint8_t m = READ_ZP;
OP_EOR_HANDLER(m, regs.d.acc.a);
}
-
static void OpA8(void) // EORA ZP, X
{
uint8_t m = READ_ZP_X;
OP_EOR_HANDLER(m, regs.d.acc.a);
}
-
static void OpB8(void) // EORA ABS
{
uint8_t m = READ_ABS;
OP_EOR_HANDLER(m, regs.d.acc.a);
}
-
static void OpC8(void) // EORB #
{
uint8_t m = READ_IMM;
OP_EOR_HANDLER(m, regs.d.acc.b);
}
-
static void OpD8(void) // EORB ZP
{
uint8_t m = READ_ZP;
OP_EOR_HANDLER(m, regs.d.acc.b);
}
-
static void OpE8(void) // EORB ZP, X
{
uint8_t m = READ_ZP_X;
OP_EOR_HANDLER(m, regs.d.acc.b);
}
-
static void OpF8(void) // EORB ABS
{
uint8_t m = READ_ABS;
OP_EOR_HANDLER(m, regs.d.acc.b);
}
-
static void Op65(void) // EIM ZP, X (EOR immediate with index)
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op75(void) // EIM ZP (EOR immediate with zero page)
{
uint8_t m;
WRITE_BACK(m);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
WRITE_BACK(m);
}
-
static void Op7C(void) // INC ABS
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op4C(void) // INCA
{
OP_INC_HANDLER(regs.d.acc.a);
}
-
static void Op5C(void) // INCB
{
OP_INC_HANDLER(regs.d.acc.b);
OP_LDA_HANDLER(m, regs.d.acc.a);
}
-
static void Op96(void) // LDAA ZP
{
uint8_t m = READ_ZP;
OP_LDA_HANDLER(m, regs.d.acc.a);
}
-
static void OpA6(void) // LDAA ZP, X
{
uint8_t m = READ_ZP_X;
OP_LDA_HANDLER(m, regs.d.acc.a);
}
-
static void OpB6(void) // LDAA ABS
{
uint8_t m = READ_ABS;
OP_LDA_HANDLER(m, regs.d.acc.a);
}
-
static void OpC6(void) // LDAB #
{
uint8_t m = READ_IMM;
OP_LDA_HANDLER(m, regs.d.acc.b);
}
-
static void OpD6(void) // LDAB ZP
{
uint8_t m = READ_ZP;
OP_LDA_HANDLER(m, regs.d.acc.b);
}
-
static void OpE6(void) // LDAB ZP, X
{
uint8_t m = READ_ZP_X;
OP_LDA_HANDLER(m, regs.d.acc.b);
}
-
static void OpF6(void) // LDAB ABS
{
uint8_t m = READ_ABS;
OP_LDA_HANDLER(m, regs.d.acc.b);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
OP_ORA_HANDLER(m, regs.d.acc.a);
}
-
static void Op9A(void) // ORAA ZP
{
uint8_t m = READ_ZP;
OP_ORA_HANDLER(m, regs.d.acc.a);
}
-
static void OpAA(void) // ORAA ZP, X
{
uint8_t m = READ_ZP_X;
OP_ORA_HANDLER(m, regs.d.acc.a);
}
-
static void OpBA(void) // ORAA ABS
{
uint8_t m = READ_ABS;
OP_ORA_HANDLER(m, regs.d.acc.a);
}
-
static void OpCA(void) // ORAB #
{
uint8_t m = READ_IMM;
OP_ORA_HANDLER(m, regs.d.acc.b);
}
-
static void OpDA(void) // ORAB ZP
{
uint8_t m = READ_ZP;
OP_ORA_HANDLER(m, regs.d.acc.b);
}
-
static void OpEA(void) // ORAB ZP, X
{
uint8_t m = READ_ZP_X;
OP_ORA_HANDLER(m, regs.d.acc.b);
}
-
static void OpFA(void) // ORAB ABS
{
uint8_t m = READ_ABS;
OP_ORA_HANDLER(m, regs.d.acc.b);
}
-
static void Op62(void) // OIM ZP, X (ORA immediate with index)
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op72(void) // OIM ZP (ORA immediate with zero page)
{
uint8_t m;
WRITE_BACK(m);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
PUSH(regs.d.acc.a);
}
-
static void Op37(void) // PSHB
{
PUSH(regs.d.acc.b);
}
-
static void Op32(void) // PULA
{
regs.d.acc.a = PULL;
}
-
static void Op33(void) // PULB
{
regs.d.acc.b = PULL;
}
-
static void Op38(void) // PULX
{
regs.x = PULL16;
}
-
static void Op3C(void) // PSHX
{
PUSH16(regs.x);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
WRITE_BACK(m);
}
-
static void Op79(void) // ROL ABS
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op49(void) // ROLA
{
OP_ROL_HANDLER(regs.d.acc.a);
}
-
static void Op59(void) // ROLB
{
OP_ROL_HANDLER(regs.d.acc.b);
WRITE_BACK(m);
}
-
static void Op76(void) // ROR ABS
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op46(void) // RORA
{
OP_ROR_HANDLER(regs.d.acc.a);
}
-
static void Op56(void) // RORB
{
OP_ROR_HANDLER(regs.d.acc.b);
WRITE_BACK(m);
}
-
static void Op78(void) // ASL ABS
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op48(void) // ASLA
{
OP_ASL_HANDLER(regs.d.acc.a);
}
-
static void Op58(void) // ASLB
{
OP_ASL_HANDLER(regs.d.acc.b);
}
-
static void Op05(void) // ASLD
{
uint8_t newCarry = (regs.d.word & 0x8000) >> 15;
flagV = flagN ^ flagC;
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
WRITE_BACK(m);
}
-
static void Op77(void) // ASR ABS
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op47(void) // ASRA
{
OP_ASR_HANDLER(regs.d.acc.a);
}
-
static void Op57(void) // ASRB
{
OP_ASR_HANDLER(regs.d.acc.b);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
WRITE_BACK(m);
}
-
static void Op74(void) // LSR ABS
{
uint8_t m;
WRITE_BACK(m);
}
-
static void Op44(void) // LSRA
{
OP_LSR_HANDLER(regs.d.acc.a);
}
-
static void Op54(void) // LSRB
{
OP_LSR_HANDLER(regs.d.acc.b);
}
-
static void Op04(void) // LSRD
{
uint8_t newCarry = regs.d.word & 0x01;
flagV = flagN ^ flagC;
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
regs.WrMem(EA_ZP, regs.d.acc.a);
}
-
static void OpA7(void) // STAA ZP, X
{
regs.WrMem(EA_ZP_X, regs.d.acc.a);
}
-
static void OpB7(void) // STAA ABS
{
regs.WrMem(EA_ABS, regs.d.acc.a);
}
-
static void OpD7(void) // STAB ZP
{
regs.WrMem(EA_ZP, regs.d.acc.b);
}
-
static void OpE7(void) // STAB ZP, X
{
regs.WrMem(EA_ZP_X, regs.d.acc.b);
}
-
static void OpF7(void) // STAB ABS
{
regs.WrMem(EA_ABS, regs.d.acc.b);
}
-
// These are illegal instructions!
#if 0
static void Op87(void) // STA #
}
#endif
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
OP_SUB_HANDLER(m, regs.d.acc.a);
}
-
static void Op90(void) // SUBA ZP
{
uint16_t m = READ_ZP;
OP_SUB_HANDLER(m, regs.d.acc.a);
}
-
static void OpA0(void) // SUBA ZP, X
{
uint16_t m = READ_ZP_X;
OP_SUB_HANDLER(m, regs.d.acc.a);
}
-
static void OpB0(void) // SUBA ABS
{
uint16_t m = READ_ABS;
OP_SUB_HANDLER(m, regs.d.acc.a);
}
-
static void OpC0(void) // SUBB #
{
uint16_t m = READ_IMM;
OP_SUB_HANDLER(m, regs.d.acc.b);
}
-
static void OpD0(void) // SUBB ZP
{
uint16_t m = READ_ZP;
OP_SUB_HANDLER(m, regs.d.acc.b);
}
-
static void OpE0(void) // SUBB ZP, X
{
uint16_t m = READ_ZP_X;
OP_SUB_HANDLER(m, regs.d.acc.b);
}
-
static void OpF0(void) // SUBB ABS
{
uint16_t m = READ_ABS;
OP_SUB_HANDLER(m, regs.d.acc.b);
}
-
static void Op10(void) // SBA
{
OP_SUB_HANDLER(regs.d.acc.b, regs.d.acc.a);
}
-
static void Op83(void) // SUBD #
{
uint16_t m = READ_IMM16;
OP_SUB_HANDLER16(m, regs.d.word);
}
-
static void Op93(void) // SUBD ZP
{
uint16_t m = READ_ZP16;
OP_SUB_HANDLER16(m, regs.d.word);
}
-
static void OpA3(void) // SUBD ZP, X
{
uint16_t m = READ_ZP_X16;
OP_SUB_HANDLER16(m, regs.d.word);
}
-
static void OpB3(void) // SUBD ABS
{
uint16_t m = READ_ABS16;
OP_SUB_HANDLER16(m, regs.d.word);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
OP_SBC_HANDLER(m, regs.d.acc.a);
}
-
static void Op92(void) // SBCA ZP
{
uint16_t m = READ_ZP;
OP_SBC_HANDLER(m, regs.d.acc.a);
}
-
static void OpA2(void) // SBCA ZP, X
{
uint16_t m = READ_ZP_X;
OP_SBC_HANDLER(m, regs.d.acc.a);
}
-
static void OpB2(void) // SBCA ABS
{
uint16_t m = READ_ABS;
OP_SBC_HANDLER(m, regs.d.acc.a);
}
-
static void OpC2(void) // SBCB #
{
uint16_t m = READ_IMM;
OP_SBC_HANDLER(m, regs.d.acc.b);
}
-
static void OpD2(void) // SBCB ZP
{
uint16_t m = READ_ZP;
OP_SBC_HANDLER(m, regs.d.acc.b);
}
-
static void OpE2(void) // SBCB ZP, X
{
uint16_t m = READ_ZP_X;
OP_SBC_HANDLER(m, regs.d.acc.b);
}
-
static void OpF2(void) // SBCB ABS
{
uint16_t m = READ_ABS;
CLR_V;
}
-
static void Op17(void) // TBA
{
regs.d.acc.a = regs.d.acc.b;
#endif
}
-
static void Op7D(void) // TST ABS
{
#if 0
#endif
}
-
static void Op4D(void) // TSTA
{
OP_TST_HANDLER(regs.d.acc.a);
}
-
static void Op5D(void) // TSTB
{
OP_TST_HANDLER(regs.d.acc.b);
}
-
static void Op6B(void) // TIM ZP, X (TST immediate with index)
{
// uint8_t m;
// WRITE_BACK(m);
}
-
static void Op7B(void) // TIM ZP (TST immediate with zero page)
{
// uint8_t m;
// WRITE_BACK(m);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
OP_CPX_HANDLER(m);
}
-
static void Op9C(void) // CPX ZP
{
uint16_t m = READ_ZP16;
OP_CPX_HANDLER(m);
}
-
static void OpAC(void) // CPX ZP, X
{
uint16_t m = READ_ZP_X16;
OP_CPX_HANDLER(m);
}
-
static void OpBC(void) // CPX ABS
{
uint16_t m = READ_ABS16;
SET_Z(regs.x);
}
-
static void Op34(void) // DES
{
regs.s--;
}
-
static void Op08(void) // INX
{
regs.x++;
SET_Z(regs.x);
}
-
static void Op31(void) // INS
{
regs.s++;
OP_LD_HANDLER(regs.x);
}
-
static void OpDE(void) // LDX ZP
{
regs.x = READ_ZP16;
OP_LD_HANDLER(regs.x);
}
-
static void OpEE(void) // LDX ZP, X
{
regs.x = READ_ZP_X16;
OP_LD_HANDLER(regs.x);
}
-
static void OpFE(void) // LDX ABS
{
regs.x = READ_ABS16;
OP_LD_HANDLER(regs.x);
}
-
static void Op8E(void) // LDS #
{
regs.s = READ_IMM16;
OP_LD_HANDLER(regs.s);
}
-
static void Op9E(void) // LDS ZP
{
regs.s = READ_ZP16;
OP_LD_HANDLER(regs.s);
}
-
static void OpAE(void) // LDS ZP, X
{
regs.s = READ_ZP_X16;
OP_LD_HANDLER(regs.s);
}
-
static void OpBE(void) // LDS ABS
{
regs.s = READ_ABS16;
OP_LD_HANDLER(regs.s);
}
-
static void OpCC(void) // LDD #
{
regs.d.word = READ_IMM16;
OP_LD_HANDLER(regs.d.word);
}
-
static void OpDC(void) // LDD ZP
{
regs.d.word = READ_ZP16;
OP_LD_HANDLER(regs.d.word);
}
-
static void OpEC(void) // LDD ZP, X
{
regs.d.word = READ_ZP_X16;
OP_LD_HANDLER(regs.d.word);
}
-
static void OpFC(void) // LDD ABS
{
regs.d.word = READ_ABS16;
OP_LD_HANDLER(regs.d.word);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
OP_ST_HANDLER(m, regs.x);
}
-
static void OpEF(void) // STX ZP, X
{
uint16_t m = EA_ZP_X;
OP_ST_HANDLER(m, regs.x);
}
-
static void OpFF(void) // STX ABS
{
uint16_t m = EA_ABS;
OP_ST_HANDLER(m, regs.x);
}
-
static void Op9F(void) // STS ZP
{
uint16_t m = EA_ZP;
OP_ST_HANDLER(m, regs.s);
}
-
static void OpAF(void) // STS ZP, X
{
uint16_t m = EA_ZP_X;
OP_ST_HANDLER(m, regs.s);
}
-
static void OpBF(void) // STS ABS
{
uint16_t m = EA_ABS;
OP_ST_HANDLER(m, regs.s);
}
-
// These are illegal instructions!
#if 0
// Store immediate--nonsensical opcodes :-P
OP_ST_HANDLER(effectiveAddress, regs.s);
}
-
static void OpCF(void) // STX #
{
uint16_t effectiveAddress = regs.pc;
OP_ST_HANDLER(effectiveAddress, regs.x);
}
-
static void OpCD(void) // STD #
{
uint16_t effectiveAddress = regs.pc;
}
#endif
-
static void OpDD(void) // STD ZP
{
uint16_t m = EA_ZP;
OP_ST_HANDLER(m, regs.d.word);
}
-
static void OpED(void) // STD ZP, X
{
uint16_t m = EA_ZP_X;
OP_ST_HANDLER(m, regs.d.word);
}
-
static void OpFD(void) // STD ABS
{
uint16_t m = EA_ABS;
OP_ST_HANDLER(m, regs.d.word);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
regs.s = regs.x - 1;
}
-
static void Op30(void) // TSX
{
regs.x = regs.s + 1;
regs.pc += m;
}
-
static void Op21(void) // BRN
{
int16_t m = (int16_t)(int8_t)READ_IMM;
// regs.pc += m;
}
-
static void Op24(void) // BCC
{
// NOTE: We can optimize this by following the maxim: "Don't branch!" by
#endif
}
-
static void Op25(void) // BCS
{
int16_t m = (int16_t)(int8_t)READ_IMM;
#endif
}
-
static void Op27(void) // BEQ
{
int16_t m = (int16_t)(int8_t)READ_IMM;
#endif
}
-
static void Op2C(void) // BGE
{
int16_t m = (int16_t)(int8_t)READ_IMM;
#endif
}
-
static void Op2E(void) // BGT
{
int16_t m = (int16_t)(int8_t)READ_IMM;
#endif
}
-
static void Op22(void) // BHI
{
int16_t m = (int16_t)(int8_t)READ_IMM;
#endif
}
-
static void Op2F(void) // BLE
{
int16_t m = (int16_t)(int8_t)READ_IMM;
#endif
}
-
static void Op23(void) // BLS
{
int16_t m = (int16_t)(int8_t)READ_IMM;
#endif
}
-
static void Op2D(void) // BLT
{
int16_t m = (int16_t)(int8_t)READ_IMM;
#endif
}
-
static void Op2B(void) // BMI
{
int16_t m = (int16_t)(int8_t)READ_IMM;
#endif
}
-
static void Op26(void) // BNE
{
int16_t m = (int16_t)(int8_t)READ_IMM;
#endif
}
-
static void Op28(void) // BVC
{
int16_t m = (int16_t)(int8_t)READ_IMM;
#endif
}
-
static void Op29(void) // BVS
{
int16_t m = (int16_t)(int8_t)READ_IMM;
#endif
}
-
static void Op2A(void) // BPL
{
int16_t m = (int16_t)(int8_t)READ_IMM;
regs.pc += m;
}
-
static void Op6E(void) // JMP ZP, X
{
uint16_t m = EA_ZP_X;
regs.pc = m;
}
-
static void Op7E(void) // JMP ABS
{
regs.pc = EA_ABS;
}
-
static void Op9D(void) // JSR ZP
{
uint16_t m = (uint16_t)EA_ZP;
regs.pc = m;
}
-
static void OpAD(void) // JSR ZP, X
{
uint16_t m = EA_ZP_X;
regs.pc = m;
}
-
static void OpBD(void) // JSR ABS
{
uint16_t m = EA_ABS;
regs.pc = m;
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
{
}
-
static void Op3B(void) // RTI
{
regs.cc = PULL;
UNPACK_FLAGS;
}
-
static void Op39(void) // RTS
{
regs.pc = PULL16;
}
-
static void Op3F(void) // SWI
{
// It seems that the SWI is non-maskable, unlike the IRQ...
HandleInterrupt(0xFFFA);
}
-
static void Op3E(void) // WAI
{
#ifdef __DEBUG__
regs.cpuFlags |= V63701_STATE_WAI; // And signal that we're in WAI mode
}
-
// Multiply opcode
static void Op3D(void) // MUL
flagC = regs.d.acc.b >> 7; // bug? No, this is how it really does it
}
-
// Exchange X and D opcode
static void Op18(void) // XGDX
regs.d.word = temp;
}
-
// Sleep opcode (similar to WAI)
static void Op1A(void) // SLP
regs.cpuFlags |= V63701_STATE_WAI;
}
-
// Undocumented opcode ($12 & $13)
static void OpUN(void) // Undocumented
regs.x += regs.RdMem(regs.s + 1);
}
-
/*
Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
| |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC|
flagC = 0;
}
-
static void Op0E(void) // CLI
{
flagI = 0;
}
-
static void Op0A(void) // CLV
{
flagV = 0;
}
-
static void Op0D(void) // SEC
{
flagC = 1;
}
-
static void Op0F(void) // SEI
{
flagI = 1;
}
-
static void Op0B(void) // SEV
{
flagV = 1;
}
-
static void Op06(void) // TAP
{
regs.cc = regs.d.acc.a;
UNPACK_FLAGS;
}
-
static void Op07(void) // TPA
{
regs.d.acc.a = PACK_FLAGS;
}
-
/*
OP Operation Code, in Hexadecimal
~ Number of MPU cycles required
4: M=Xh, M+1=Xl
*/
-
static void Op__(void)
{
// TRAP is non-maskable, unlike the IRQ... Also, highest priority after
// regs.cpuFlags |= V63701_STATE_ILLEGAL_INST;
}
-
//
// Ok, the exec_op[] array is globally defined here basically to save
// a LOT of unnecessary typing. Sure it's ugly, but hey, it works!
OpF0, OpF1, OpF2, OpF3, OpF4, OpF5, OpF6, OpF7, OpF8, OpF9, OpFA, OpFB, OpFC, OpFD, OpFE, OpFF
};
-
//
// Internal "memcpy" (so we don't have to link with any external libraries!)
//
d[i] = s[i];
}
-
#ifdef __DEBUG__
//int instCount[256];
-//static bool logGo = false;
-static bool logGo = true;
+bool V63701LogGo = false;
+//static bool V63701LogGo = true;
char instBuf[256];
-extern uint8_t memory[];
+extern uint8_t mcuMem[];
+uint8_t * memory = mcuMem;
#endif
//
// Function to execute 63701 for "cycles" cycles
while (regs.clock < endCycles)
#endif
{
+#if 0
+if (regs.pc == 0x8236)
+{
+ printf("V63701: $8236 called by $%04X...\n", RdMemW(regs.s));
+}
+#endif
#ifdef __DEBUG__
-if (logGo)
+if (V63701LogGo)
{
Decode63701(memory, regs.pc, instBuf);
WriteLog("%s\n", instBuf);
if (regs.cpuFlags & V63701_STATE_WAI)
{
// Only bail out if no interrupts/resets are pending
- if (!(regs.cpuFlags & (V63701_ASSERT_LINE_IRQ | V63701_ASSERT_LINE_NMI | V63701_ASSERT_LINE_RESET | V63701_ASSERT_TIMER_OVERFLOW | V63701_ASSERT_OUTPUT_COMPARE | V63701_ASSERT_INPUT_CAPTURE)))
+ if (!(regs.cpuFlags & (V63701_LINE_IRQ | V63701_LINE_NMI | V63701_LINE_RESET | V63701_TIMER_OVERFLOW | V63701_OUTPUT_COMPARE | V63701_INPUT_CAPTURE)))
// Burn any remaining cycles...
regs.clock = endCycles;
}
if (regs.tcsr.bit.eoci)
{
- regs.cpuFlags |= V63701_ASSERT_OUTPUT_COMPARE;
- regsPointer->cpuFlags |= V63701_ASSERT_OUTPUT_COMPARE;
+ regs.cpuFlags |= V63701_OUTPUT_COMPARE;
+ regsPointer->cpuFlags |= V63701_OUTPUT_COMPARE;
}
}
if (regs.tcsr.bit.etoi)
{
- regs.cpuFlags |= V63701_ASSERT_TIMER_OVERFLOW;
- regsPointer->cpuFlags |= V63701_ASSERT_TIMER_OVERFLOW;
+ regs.cpuFlags |= V63701_TIMER_OVERFLOW;
+ regsPointer->cpuFlags |= V63701_TIMER_OVERFLOW;
}
}
#ifdef __DEBUG__
-if (logGo)
+if (V63701LogGo)
// WriteLog(" [PC=%04X, S=%04X, X=%04X, A=%02X, B=%02X, CC=%s%s%s%s%s%s%s%s]\n", regs.pc, regs.s, regs.x, regs.d.acc.a, regs.d.acc.b, (regs.cc & FLAG_E ? "E" : " "), (regs.cc & FLAG_F ? "F" : " "), (regs.cc & FLAG_H ? "H" : " "), (regs.cc & FLAG_I ? "I" : " "), (regs.cc & FLAG_N ? "N" : " "), (regs.cc & FLAG_Z ? "Z" : " "), (regs.cc & FLAG_V ? "V" : " "), (regs.cc & FLAG_C ? "C" : " "));
WriteLog(" [PC=%04X S=%04X X=%04X A=%02X B=%02X CC=%s%s%s%s%s%s TCSR=%s%s%s%s%s%s%s%s CT=%04X OC=%04X]\n", regs.pc, regs.s, regs.x, regs.d.acc.a, regs.d.acc.b, (flagH ? "H" : "."), (flagI ? "I" : "."), (flagN ? "N" : "."), (flagZ ? "Z" : "."), (flagV ? "V" : "."), (flagC ? "C" : "."), (regs.tcsr.bit.icf ? "I" :"."), (regs.tcsr.bit.ocf ? "O" :"."), (regs.tcsr.bit.tof ? "T" :"."), (regs.tcsr.bit.eici ? "i" :"."), (regs.tcsr.bit.eoci ? "o" :"."), (regs.tcsr.bit.etoi ? "t" :"."), (regs.tcsr.bit.iedg ? "E" :"."), (regs.tcsr.bit.olvl ? "O" :"."), regs.counter.word, regs.outputCompare.word);
#endif
}
- if (regs.cpuFlags & V63701_ASSERT_LINE_RESET)
+ if (regs.cpuFlags & V63701_LINE_RESET)
{
#ifdef __DEBUG__
-WriteLog("*** RESET LINE ASSERTED ***\n");
+if (V63701LogGo)
+ WriteLog("*** RESET LINE ASSERTED ***\n");
#endif
regs.tcsr.byte = 0;
regs.tcsrWasRead = false;
context->cpuFlags = 0; // Clear all lingering flags...
regs.cpuFlags = 0;
}
- else if (regs.cpuFlags & V63701_ASSERT_LINE_NMI)
+ else if (regs.cpuFlags & V63701_LINE_NMI)
{
#ifdef __DEBUG__
-WriteLog("*** NMI LINE ASSERTED ***\n");
+if (V63701LogGo)
+ WriteLog("*** NMI LINE ASSERTED ***\n");
#endif
- HandleInterrupt(0xFFFC, V63701_ASSERT_LINE_NMI);
+ HandleInterrupt(0xFFFC, V63701_LINE_NMI);
}
- else if (regs.cpuFlags & V63701_ASSERT_LINE_IRQ)
+ else if (regs.cpuFlags & V63701_LINE_IRQ)
{
#ifdef __DEBUG__
-WriteLog("*** IRQ LINE ASSERTED ***\n");
+if (V63701LogGo)
+ WriteLog("*** IRQ LINE ASSERTED ***\n");
#endif
// if (!(regs.cc & FLAG_I)) // Process an interrupt (I=0)?
if (!flagI) // Process an interrupt (I=0)?
{
#ifdef __DEBUG__
-WriteLog(" IRQ TAKEN!\n");
-logGo = true;
+if (V63701LogGo)
+ WriteLog(" IRQ TAKEN!\n");
+//V63701LogGo = true;
#endif
- HandleInterrupt(0xFFF8, V63701_ASSERT_LINE_IRQ);
+ HandleInterrupt(0xFFF8, V63701_LINE_IRQ);
}
}
- else if (regs.cpuFlags & V63701_ASSERT_INPUT_CAPTURE)
+ else if (regs.cpuFlags & V63701_INPUT_CAPTURE)
{
#ifdef __DEBUG__
-WriteLog("*** INPUT CAPTURE ASSERTED ***\n");
+if (V63701LogGo)
+ WriteLog("*** INPUT CAPTURE ASSERTED ***\n");
#endif
// Process interrupt if no I inhibit set, & enable in TCSR is set
if (!flagI && regs.tcsr.bit.eici)
{
#ifdef __DEBUG__
-WriteLog(" IC TAKEN!\n");
-logGo = true;
+if (V63701LogGo)
+ WriteLog(" IC TAKEN!\n");
+//V63701LogGo = true;
#endif
- HandleInterrupt(0xFFF6, V63701_ASSERT_INPUT_CAPTURE);
+ HandleInterrupt(0xFFF6, V63701_INPUT_CAPTURE);
}
}
- else if (regs.cpuFlags & V63701_ASSERT_OUTPUT_COMPARE)
+ else if (regs.cpuFlags & V63701_OUTPUT_COMPARE)
{
#ifdef __DEBUG__
-WriteLog("*** OUTPUT COMPARE ASSERTED ***\n");
+if (V63701LogGo)
+ WriteLog("*** OUTPUT COMPARE ASSERTED ***\n");
#endif
// Process interrupt if no I inhibit set, & enable in TCSR is set
if (!flagI && regs.tcsr.bit.eoci)
{
#ifdef __DEBUG__
-WriteLog(" OC TAKEN!\n");
-logGo = true;
+if (V63701LogGo)
+ WriteLog(" OC TAKEN!\n");
+//V63701LogGo = true;
#endif
- HandleInterrupt(0xFFF4, V63701_ASSERT_OUTPUT_COMPARE);
+ HandleInterrupt(0xFFF4, V63701_OUTPUT_COMPARE);
}
}
- else if (regs.cpuFlags & V63701_ASSERT_TIMER_OVERFLOW)
+ else if (regs.cpuFlags & V63701_TIMER_OVERFLOW)
{
#ifdef __DEBUG__
-WriteLog("*** TIMER OVER ASSERTED ***\n");
+if (V63701LogGo)
+ WriteLog("*** TIMER OVER ASSERTED ***\n");
#endif
// Process interrupt if no I inhibit set, & enable in TCSR is set
if (!flagI && regs.tcsr.bit.etoi)
{
#ifdef __DEBUG__
-WriteLog(" TO TAKEN!\n");
-logGo = true;
+if (V63701LogGo)
+ WriteLog(" TO TAKEN!\n");
+//V63701LogGo = true;
#endif
- HandleInterrupt(0xFFF2, V63701_ASSERT_TIMER_OVERFLOW);
+ HandleInterrupt(0xFFF2, V63701_TIMER_OVERFLOW);
}
}
}
myMemcpy(context, ®s, sizeof(V63701REGS));
}
-
//
// Get the clock of the currently executing CPU
//
return regs.clock;
}
-
static inline void HandleInterrupt(uint16_t vector, uint16_t flag/*= 0*/)
{
if (regs.cpuFlags & V63701_STATE_WAI)
regsPointer->cpuFlags &= ~(flag | V63701_STATE_WAI);
}
-
uint8_t InternalRegisterRead(uint16_t address)
{
switch (address & 0x1F)
{
case 0x00:
return regs.ddr1;
+ case 0x01:
+ return regs.ddr2;
case 0x02:
- return /*(regs.port1read & ~regs.ddr1) |*/ (regs.port1 & regs.ddr1);
+ return (V63701ReadPort1() & ~regs.ddr1) | (regs.port1data & regs.ddr1);
+// return /*(regs.port1read & ~regs.ddr1) |*/ (regs.port1r & ~regs.ddr1);
+ case 0x03:
+ // Top 3 bits are MCU mode bits.
+ return (V63701ReadPort2() & ~regs.ddr2) | (regs.port2data & regs.ddr2);
+// return /*(regs.port1read & ~regs.ddr1) |*/ (regs.port2r & ~regs.ddr2 & 0x1F);
// Timer Control and Status Register
case 0x08:
regs.tcsrWasRead = true;
return 0x00;
}
-
void InternalRegisterWrite(uint16_t address, uint8_t data)
{
+ uint8_t writeData;
+
switch (address & 0x1F)
{
case 0x00:
regs.ddr2 = data;
break;
case 0x02:
- regs.port1 = data;
+ regs.port1data = data;
+ writeData = (V63701ReadPort1() & ~regs.ddr1) | (data & regs.ddr1);
+ V63701WritePort1(writeData);
break;
case 0x03:
- regs.port2 = data;
+ // Port 2 only has 5 bits of output, top 3 are the MCU mode bits
+ regs.port2data = ((regs.port2data & ~regs.ddr2) | (data & regs.ddr2)) & 0x1F;
break;
// case 0x05:
// Timer Control and Status Register
#endif
}
}
-