// 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 void Op6E(void) // JMP ZP, X
{
- regs.pc = EA_ZP_X;
+ uint16_t m = EA_ZP_X;
+ regs.pc = m;
}
// 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!
//
-void (* exec_op[256])() = {
+static void (* exec_op[256])() = {
Op__, Op01, Op__, Op__, Op04, Op05, Op06, Op07, Op08, Op09, Op0A, Op0B, Op0C, Op0D, Op0E, Op0F,
Op10, Op11, OpUN, OpUN, Op__, Op__, Op16, Op17, Op18, Op19, Op1A, Op1B, Op__, Op__, Op__, Op__,
Op20, Op21, Op22, Op23, Op24, Op25, Op26, Op27, Op28, Op29, Op2A, Op2B, Op2C, Op2D, Op2E, Op2F,
#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);
}
}
#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)
{
#ifdef __DEBUG__
-WriteLog("*** RESET LINE ASSERTED ***\n");
+if (V63701LogGo)
+ WriteLog("*** RESET LINE ASSERTED ***\n");
#endif
regs.tcsr.byte = 0;
regs.tcsrWasRead = false;
else if (regs.cpuFlags & V63701_ASSERT_LINE_NMI)
{
#ifdef __DEBUG__
-WriteLog("*** NMI LINE ASSERTED ***\n");
+if (V63701LogGo)
+ WriteLog("*** NMI LINE ASSERTED ***\n");
#endif
HandleInterrupt(0xFFFC, V63701_ASSERT_LINE_NMI);
}
else if (regs.cpuFlags & V63701_ASSERT_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);
}
else if (regs.cpuFlags & V63701_ASSERT_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);
}
else if (regs.cpuFlags & V63701_ASSERT_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);
}
else if (regs.cpuFlags & V63701_ASSERT_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);
}
{
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;
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