X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fv63701.cpp;h=ea225bd0c6c7642bdfe3ec8df4d013322762ca1e;hb=1c26b00fe4ae49984de2d33f7d13c20760664dd9;hp=3f01921f74819789e9da73063c702c220ef9ccc1;hpb=756fbabdd25117272164fd2d31810e6018a5990e;p=thunder diff --git a/src/v63701.cpp b/src/v63701.cpp index 3f01921..ea225bd 100644 --- a/src/v63701.cpp +++ b/src/v63701.cpp @@ -37,7 +37,7 @@ // 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" @@ -46,6 +46,7 @@ #ifdef __DEBUG__ #include "dis63701.h" //#include "log.h" +#include // for printf() #define WriteLog printf #endif @@ -94,10 +95,12 @@ #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; \ @@ -110,7 +113,9 @@ // 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] = { @@ -2285,7 +2290,8 @@ static void Op8D(void) // BSR static void Op6E(void) // JMP ZP, X { - regs.pc = EA_ZP_X; + uint16_t m = EA_ZP_X; + regs.pc = m; } @@ -2556,7 +2562,7 @@ static void Op__(void) // 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, @@ -2590,10 +2596,11 @@ static void myMemcpy(void * dst, void * src, uint32_t size) #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 @@ -2617,8 +2624,14 @@ void Execute63701(V63701REGS * context, uint32_t 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); @@ -2673,7 +2686,7 @@ if (logGo) } } #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 @@ -2682,7 +2695,8 @@ if (logGo) 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; @@ -2696,21 +2710,24 @@ WriteLog("*** RESET LINE ASSERTED ***\n"); 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); } @@ -2718,14 +2735,16 @@ logGo = true; 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); } @@ -2733,14 +2752,16 @@ logGo = true; 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); } @@ -2748,14 +2769,16 @@ logGo = true; 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); } @@ -2812,8 +2835,15 @@ uint8_t InternalRegisterRead(uint16_t address) { 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; @@ -2854,6 +2884,8 @@ uint8_t InternalRegisterRead(uint16_t address) void InternalRegisterWrite(uint16_t address, uint8_t data) { + uint8_t writeData; + switch (address & 0x1F) { case 0x00: @@ -2863,10 +2895,13 @@ void InternalRegisterWrite(uint16_t address, uint8_t data) 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