From 3577016ba87fdf3b544ac70f4cf0f4fbd189574c Mon Sep 17 00:00:00 2001 From: meepingsnesroms Date: Wed, 18 Apr 2018 16:44:44 -0700 Subject: [PATCH] The dragonball uses a 68000 not 68020, more boot chip fixes --- qtBuildSystem/Mu/Mu.pro | 8 +-- src/{cpu32Opcodes.c => 68328Functions.c} | 22 ++++++--- src/{cpu32Opcodes.h => 68328Functions.h} | 2 +- src/emulator.c | 63 ++++++++++++++++++++---- src/hardwareRegisters.c | 18 ++++--- src/hardwareRegisters.h | 1 + src/m68k/m68kconf.h | 2 +- src/makefile.all | 2 +- src/memoryAccess.c | 4 +- unimplementedFeatures.txt | 1 + 10 files changed, 90 insertions(+), 33 deletions(-) rename src/{cpu32Opcodes.c => 68328Functions.c} (75%) rename src/{cpu32Opcodes.h => 68328Functions.h} (63%) diff --git a/qtBuildSystem/Mu/Mu.pro b/qtBuildSystem/Mu/Mu.pro index d1fb7bc..a9e9020 100644 --- a/qtBuildSystem/Mu/Mu.pro +++ b/qtBuildSystem/Mu/Mu.pro @@ -40,13 +40,13 @@ SOURCES += \ src/m68k/m68kopdm.c \ src/m68k/m68kopnz.c \ src/m68k/m68kops.c \ - src/cpu32Opcodes.c \ src/emulator.c \ src/hardwareRegisters.c \ src/memoryAccess.c \ src/sdcard.c \ src/sed1376.c \ - src/silkscreen.c + src/silkscreen.c \ + src/68328Functions.c HEADERS += \ mainwindow.h \ @@ -61,7 +61,6 @@ HEADERS += \ src/m68k/m68kconf.h \ src/m68k/m68kcpu.h \ src/m68k/m68kops.h \ - src/cpu32Opcodes.h \ src/emuFeatureRegistersSpec.h \ src/emulator.h \ src/hardwareRegisterNames.h \ @@ -70,7 +69,8 @@ HEADERS += \ src/portability.h \ src/sdcard.h \ src/sed1376.h \ - src/silkscreen.h + src/silkscreen.h \ + src/68328Functions.h FORMS += \ mainwindow.ui diff --git a/src/cpu32Opcodes.c b/src/68328Functions.c similarity index 75% rename from src/cpu32Opcodes.c rename to src/68328Functions.c index a7953d5..78d39cb 100755 --- a/src/cpu32Opcodes.c +++ b/src/68328Functions.c @@ -17,7 +17,9 @@ bool lowPowerStopActive; static inline void patchOpcode(uint16_t opcode, void (*handler)(void), unsigned char cycles){ m68ki_instruction_jump_table[opcode] = handler; - m68ki_cycles[2][opcode] = cycles;//set how many cycles for 68020 + m68ki_cycles[0][opcode] = cycles; + m68ki_cycles[1][opcode] = cycles; + m68ki_cycles[2][opcode] = cycles; } @@ -32,28 +34,28 @@ void cpu32OpLpstop(void){ //program lacks authority m68ki_exception_privilege_violation(); } - debugLog("LowPowerStop set, CPU is off, PC 0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC)); + debugLog("LowPowerStop set, CPU is off, PC:0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC)); } void cpu32OpTbls(void){ - debugLog("TBLS opcode not implemented, PC 0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC)); + debugLog("TBLS opcode not implemented, PC:0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC)); } void cpu32OpTblsn(void){ - debugLog("TBLSN opcode not implemented, PC 0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC)); + debugLog("TBLSN opcode not implemented, PC:0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC)); } void cpu32OpTblu(void){ - debugLog("TBLU opcode not implemented, PC 0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC)); + debugLog("TBLU opcode not implemented, PC:0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC)); } void cpu32OpTblun(void){ - debugLog("TBLUN opcode not implemented, PC 0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC)); + debugLog("TBLUN opcode not implemented, PC:0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC)); } void m68k_op_bgnd(void){ - debugLog("Opcode BGND not implemented, PC 0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC)); + debugLog("Opcode BGND not implemented, PC:0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC)); } void m68k_op_cpu32_dispatch(void){ @@ -89,9 +91,13 @@ void m68k_op_cpu32_dispatch(void){ } -void patchMusashiOpcodeHandlerCpu32(){ +void patchTo68328(){ + CPU_ADDRESS_MASK = 0xFFFFFFFF; + patchOpcode(OPCODE_BGND, m68k_op_bgnd, 16/*dont know how many cycles, average opcode*/); for(uint32_t currentOpcode = OPCODE_CPU32_START; currentOpcode <= OPCODE_CPU32_END; currentOpcode++) patchOpcode(currentOpcode, m68k_op_cpu32_dispatch, 91/*dont know how many cycles, most expensive opcode*/); + + //68328 may actually use some 68020 opcodes, those will be patched in if and when Palm OS attempts to call one } diff --git a/src/cpu32Opcodes.h b/src/68328Functions.h similarity index 63% rename from src/cpu32Opcodes.h rename to src/68328Functions.h index a02eba5..b0222f6 100755 --- a/src/cpu32Opcodes.h +++ b/src/68328Functions.h @@ -4,4 +4,4 @@ extern bool lowPowerStopActive; -void patchMusashiOpcodeHandlerCpu32(); +void patchTo68328(); diff --git a/src/emulator.c b/src/emulator.c index 316a32d..d1a7720 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -4,7 +4,7 @@ #include #include "m68k/m68k.h" -#include "cpu32Opcodes.h" +#include "68328Functions.h" #include "emulator.h" #include "hardwareRegisters.h" #include "memoryAccess.h" @@ -54,20 +54,42 @@ static inline bool allSdCardCallbacksPresent(){ //debug #ifdef EMU_OPCODE_LEVEL_DEBUG -#define LOGGED_OPCODES 10 +#define LOGGED_OPCODES 100 static bool invalidBehaviorAbort; static char disassemblyBuffer[LOGGED_OPCODES][100];//store the opcode and program counter for the last 10 opcodes +static char* takeStackDump(uint32_t bytes){ + char* textBytes = malloc(bytes * 2); + uint32_t textBytesOffset = 0; + uint32_t stackAddress = m68k_get_reg(NULL, M68K_REG_SP); + + textBytes[0] = '\0'; + + for(uint32_t count = 0; count < bytes; count++){ + sprintf(textBytes + textBytesOffset, "%02X", m68k_read_memory_8(stackAddress + count)); + textBytesOffset = strlen(textBytes); + } + + return textBytes; +} + static void invalidBehaviorCheck(){ char opcodeName[100]; uint32_t lastProgramCounter = m68k_get_reg(NULL, M68K_REG_PPC); uint32_t programCounter = m68k_get_reg(NULL, M68K_REG_PC); uint16_t instruction = m68k_get_reg(NULL, M68K_REG_IR); - bool invalidInstruction = !m68k_is_valid_instruction(instruction, M68K_CPU_TYPE_68020); + bool invalidInstruction = !m68k_is_valid_instruction(instruction, M68K_CPU_TYPE_68000); bool invalidBank = (bankType[START_BANK(programCounter)] == CHIP_NONE); //get current opcode - m68k_disassemble(opcodeName, programCounter, M68K_CPU_TYPE_68020); + if(!invalidBank){ + //must dissasemble as 68020 to prevent address masking, is also more descriptive for invalid opcodes + m68k_disassemble(opcodeName, programCounter, M68K_CPU_TYPE_68020); + } + else{ + strcpy(opcodeName, "Invalid bank, cant read"); + } + sprintf(opcodeName + strlen(opcodeName), " at PC:0x%08X", programCounter); //shift opcode buffer for(uint32_t i = 0; i < LOGGED_OPCODES - 1; i++) @@ -85,7 +107,25 @@ static void invalidBehaviorCheck(){ for(uint32_t i = 0; i < LOGGED_OPCODES; i++) debugLog("%s\n", disassemblyBuffer[i]); //currently CPU32 opcodes will be listed as "unknown", I cant change that properly unless I directly edit musashi source, something I want to avoid doing - debugLog("Instruction:\"%s\", instruction value:0x%04X, bank type:%d, program counter:0x%08X\n", invalidInstruction ? "unknown" : opcodeName, instruction, START_BANK(programCounter), programCounter); + debugLog("Instruction:\"%s\", instruction value:0x%04X, bank type:%d\n", invalidInstruction ? "unknown" : opcodeName, instruction, bankType[START_BANK(programCounter)]); + } + + //custom debug operations + switch(programCounter){ + /* + //case 0x10000566: + case 0x100003F8: + { + //failing on executing first trap "HwrPreDebugInit" + char* data = takeStackDump(32); + debugLog("Stack dump:%s\n", data); + free(data); + } + break; + */ + + default: + break; } } #endif @@ -94,7 +134,8 @@ static void invalidBehaviorCheck(){ void emulatorInit(uint8_t* palmRomDump, uint8_t* palmBootDump, uint32_t specialFeatures){ //CPU m68k_init(); - m68k_set_cpu_type(M68K_CPU_TYPE_68020); + m68k_set_cpu_type(M68K_CPU_TYPE_68000); + patchTo68328(); m68k_set_reset_instr_callback(emulatorReset); m68k_set_int_ack_callback(interruptAcknowledge); #ifdef EMU_OPCODE_LEVEL_DEBUG @@ -102,7 +143,6 @@ void emulatorInit(uint8_t* palmRomDump, uint8_t* palmBootDump, uint32_t specialF strcpy(disassemblyBuffer[i], "Not an opcode.\n"); m68k_set_instr_hook_callback(invalidBehaviorCheck); #endif - patchMusashiOpcodeHandlerCpu32(); resetHwRegisters(); lowPowerStopActive = false; palmCrystalCycles = 2.0 * (14.0 * (71.0/*p*/ + 1.0) + 3.0/*q*/ + 1.0) / 2.0/*prescaler1*/; @@ -166,8 +206,6 @@ void emulatorInit(uint8_t* palmRomDump, uint8_t* palmBootDump, uint32_t specialF debugLog("Fixed 32.32:0x%08lX\n", fixed3232); debugLog("Rebuilt double:%f\n", rebuilt); */ - - //debugLog("0x01000014 bank type:%d\n", bankType[0x0100]); } void emulatorExit(){ @@ -176,6 +214,7 @@ void emulatorExit(){ void emulatorReset(){ //reset doesnt clear RAM or sdcard, all programs are stored in RAM or on sdcard + debugLog("Reset triggered, PC:0x%08X\n", m68k_get_reg(NULL, M68K_REG_PC)); resetHwRegisters(); resetAddressSpace();//address space must be reset after hardware registers because it is dependant on them sed1376Reset(); @@ -208,7 +247,7 @@ uint32_t emulatorGetStateSize(){ size += REG_SIZE;//hardware registers size += TOTAL_MEMORY_BANKS;//bank handlers size += sizeof(uint32_t) * 4 * CHIP_END;//chip select states - size += sizeof(uint8_t) * 4 * CHIP_END;//chip select states + size += sizeof(uint8_t) * 5 * CHIP_END;//chip select states size += sizeof(uint64_t) * 3;//palmSdCard size += sizeof(uint8_t) * 2;//palmSdCard size += sizeof(uint64_t) * 4;//32.32 fixed point double, timerXCycleCounter and CPU cycle timers @@ -254,6 +293,8 @@ void emulatorSaveState(uint8_t* data){ offset += sizeof(uint32_t); writeStateValueUint32(data + offset, chips[chip].mask); offset += sizeof(uint32_t); + writeStateValueBool(data + offset, chips[chip].inBootMode); + offset += sizeof(uint8_t); writeStateValueBool(data + offset, chips[chip].readOnly); offset += sizeof(uint8_t); writeStateValueBool(data + offset, chips[chip].readOnlyForProtectedMemory); @@ -338,6 +379,8 @@ void emulatorLoadState(uint8_t* data){ offset += sizeof(uint32_t); chips[chip].mask = readStateValueUint32(data + offset); offset += sizeof(uint32_t); + chips[chip].inBootMode = readStateValueBool(data + offset); + offset += sizeof(uint8_t); chips[chip].readOnly = readStateValueBool(data + offset); offset += sizeof(uint8_t); chips[chip].readOnlyForProtectedMemory = readStateValueBool(data + offset); diff --git a/src/hardwareRegisters.c b/src/hardwareRegisters.c index 85b9129..bfc8e9f 100644 --- a/src/hardwareRegisters.c +++ b/src/hardwareRegisters.c @@ -6,7 +6,7 @@ #include "hardwareRegisterNames.h" #include "hardwareRegisters.h" #include "memoryAccess.h" -#include "cpu32Opcodes.h" +#include "68328Functions.h" #include "portability.h" #include "m68k/m68k.h" @@ -70,6 +70,10 @@ static inline void setCsa(uint16_t value){ chips[CHIP_A_ROM].readOnly = CAST_TO_BOOL(value & 0x8000); chips[CHIP_A_ROM].size = 0x20000/*128kb*/ << ((value >> 1) & 0x0007); + //CSA is now just a normal chipselect + if(chips[CHIP_A_ROM].enable && chips[CHIP_A_ROM].inBootMode) + chips[CHIP_A_ROM].inBootMode = false; + registerArrayWrite16(CSA, value & 0x81FF); } @@ -818,6 +822,7 @@ void refreshButtonState(){ void setBusErrorTimeOut(){ uint8_t scr = registerArrayRead8(SCR); + debugLog("Bus error timeout, PC:0x%08X\n", m68k_get_reg(NULL, M68K_REG_PC)); if(scr & 0x10){ //trigger bus error interrupt } @@ -826,6 +831,7 @@ void setBusErrorTimeOut(){ void setWriteProtectViolation(){ uint8_t scr = registerArrayRead8(SCR); + debugLog("Write protect violation, PC:0x%08X\n", m68k_get_reg(NULL, M68K_REG_PC)); if(scr & 0x10){ //trigger bus error interrupt } @@ -834,6 +840,7 @@ void setWriteProtectViolation(){ void setPrivilegeViolation(){ uint8_t scr = registerArrayRead8(SCR); + debugLog("Privilege violation, PC:0x%08X\n", m68k_get_reg(NULL, M68K_REG_PC)); if(scr & 0x10){ //trigger bus error interrupt } @@ -920,7 +927,7 @@ unsigned int getHwRegister16(unsigned int address){ } address &= 0x00000FFF; - printUnknownHwAccess(address, 0, 16, false); + //printUnknownHwAccess(address, 0, 16, false); switch(address){ //32 bit registers accessed as 16 bit @@ -940,7 +947,7 @@ unsigned int getHwRegister16(unsigned int address){ return registerArrayRead16(address); default: - //printUnknownHwAccess(address, 0, 16, false); + printUnknownHwAccess(address, 0, 16, false); return 0x0000; } @@ -1305,15 +1312,14 @@ void resetHwRegisters(){ chips[chip].size = 0x00000000; chips[chip].mask = 0x00000000; + chips[chip].inBootMode = false; chips[chip].readOnly = false; chips[chip].readOnlyForProtectedMemory = false; chips[chip].supervisorOnlyProtectedMemory = false; chips[chip].unprotectedSize = 0x00000000; } //all chipselects are disabled at boot and CSA is mapped to 0x00000000 and covers the entire address range until CSGBA set otherwise - chips[CHIP_A_ROM].enable = true; - chips[CHIP_A_ROM].start = 0x00000000; - chips[CHIP_A_ROM].size = 0xFFFF0000;//0xFFFFFFFF will block hw registers and emu registers + chips[CHIP_A_ROM].inBootMode = true; //masks for reading and writing chips[CHIP_A_ROM].mask = 0x003FFFFF; diff --git a/src/hardwareRegisters.h b/src/hardwareRegisters.h index 4c41937..c8c0167 100644 --- a/src/hardwareRegisters.h +++ b/src/hardwareRegisters.h @@ -48,6 +48,7 @@ typedef struct{ uint32_t mask;//the address lines the chip responds to, so 0x10000 on an chip with 16 address lines will return the value at 0x0000 //attributes + bool inBootMode; bool readOnly; bool readOnlyForProtectedMemory; bool supervisorOnlyProtectedMemory; diff --git a/src/m68k/m68kconf.h b/src/m68k/m68kconf.h index 22e7ecb..865ac2e 100755 --- a/src/m68k/m68kconf.h +++ b/src/m68k/m68kconf.h @@ -65,7 +65,7 @@ /* Turn ON if you want to use the following M68K variants */ #define M68K_EMULATE_010 OPT_OFF #define M68K_EMULATE_EC020 OPT_OFF -#define M68K_EMULATE_020 OPT_ON +#define M68K_EMULATE_020 OPT_OFF /* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing diff --git a/src/makefile.all b/src/makefile.all index 49d4b48..579293a 100644 --- a/src/makefile.all +++ b/src/makefile.all @@ -4,7 +4,7 @@ EMU_SOURCES_C := $(EMU_PATH)/emulator.c \ $(EMU_PATH)/sed1376.c \ $(EMU_PATH)/sdcard.c \ $(EMU_PATH)/silkscreen.c \ - $(EMU_PATH)/cpu32Opcodes.c \ + $(EMU_PATH)/68328Functions.c \ $(EMU_PATH)/m68k/m68kops.c \ $(EMU_PATH)/m68k/m68kopnz.c \ $(EMU_PATH)/m68k/m68kopdm.c \ diff --git a/src/memoryAccess.c b/src/memoryAccess.c index af9feff..1377a56 100644 --- a/src/memoryAccess.c +++ b/src/memoryAccess.c @@ -335,10 +335,10 @@ static uint8_t getProperBankType(uint32_t bank){ //normal banks if(BANK_IN_RANGE(bank, REG_START_ADDRESS, REG_SIZE)){ - //registers have first priority, they cover 0xFFFFF000 even if a chipselect overlaps this area + //registers have first priority, they cover 0xFFFFF000 even if a chipselect overlaps this area or CHIP_A_ROM is in boot mode return CHIP_REGISTERS; } - else if(chips[CHIP_A_ROM].enable && BANK_IN_RANGE(bank, chips[CHIP_A_ROM].start, chips[CHIP_A_ROM].size)){ + else if(chips[CHIP_A_ROM].inBootMode || (chips[CHIP_A_ROM].enable && BANK_IN_RANGE(bank, chips[CHIP_A_ROM].start, chips[CHIP_A_ROM].size))){ return CHIP_A_ROM; } else if(chips[CHIP_B_SED].enable && BANK_IN_RANGE(bank, chips[CHIP_B_SED].start, chips[CHIP_B_SED].size) && sed1376ClockConnected()){ diff --git a/unimplementedFeatures.txt b/unimplementedFeatures.txt index 8bf5d19..42d3497 100644 --- a/unimplementedFeatures.txt +++ b/unimplementedFeatures.txt @@ -17,6 +17,7 @@ interrupt control register (ICR), POL5 and edge trigger selects storage RAM protect(likely already done from fixing chip select bits) Fixed: +Palm OS usage of the "rte" instruction is incompatible with the 68020, switch to 68000 core System Control Register, 0xXXFFF000 all upper banks are registers mode Port D keyboard enable register (HW verified)PDPOL inverts interrupts by inverting PDDATA bits, the data register is affected by PDPOL