From 07b4aa53a8d515e2e4e0322d3cd80b441c83d013 Mon Sep 17 00:00:00 2001 From: meepingsnesroms Date: Mon, 22 Jul 2019 15:00:20 -0700 Subject: [PATCH] Clean up sandbox to prepare for adding ARMv5 tools to it --- bugs/unimplementedHardware.txt | 1 + src/debug/sandbox.c | 503 ++++++--------------------------- src/debug/sandbox.h | 6 +- src/emulator.c | 2 + 4 files changed, 85 insertions(+), 427 deletions(-) diff --git a/bugs/unimplementedHardware.txt b/bugs/unimplementedHardware.txt index a3f585c..9a8e1ef 100644 --- a/bugs/unimplementedHardware.txt +++ b/bugs/unimplementedHardware.txt @@ -49,6 +49,7 @@ This thing: case SEND_STATUS://HACK, need to add real write protection, this com Debug tools: ADS7846 channels can't be read in single reference mode in hwTestSuite +Mu sandbox dosent have memory and opcode hooks setup when in ARMv5 mode MakePalmBitmap: diff --git a/src/debug/sandbox.c b/src/debug/sandbox.c index 210a328..639d51b 100644 --- a/src/debug/sandbox.c +++ b/src/debug/sandbox.c @@ -20,6 +20,15 @@ #include "sandbox.h" #include "trapNames.h" +#if defined(EMU_SUPPORT_PALM_OS5) +#include "../armv5te/cpu.h" +#endif + + +#if !defined(EMU_SUPPORT_PALM_OS5) +//fake functions for ARMv5 CPU accesses +#define reg_pc(x) 0 +#endif #define SANDBOX_MAX_UNLOGGED_JUMP_SIZE 0xFFFFFFFF #define SANDBOX_MAX_WATCH_REGIONS 1000 @@ -39,7 +48,7 @@ typedef struct{ uint16_t sr; uint32_t a0; uint32_t d0; -}local_cpu_state_t; +}m68k_local_cpu_state_t; typedef struct{ uint32_t address; @@ -48,16 +57,16 @@ typedef struct{ }mem_region_t; -static bool sandboxActive;//used to "log out" of the emulator once a test has finished -static bool sandboxControlHandoff;//used for functions that depend on timing, hands full control to the m68k -static uint8_t sandboxCurrentCpuArch; -static local_cpu_state_t sandboxOldFunctionCpuState; -static uint64_t sandboxFramesRan; -static mem_region_t sandboxWatchRegions[SANDBOX_MAX_WATCH_REGIONS];//code locations in 68k address space to be sandboxed -static uint16_t sandboxWatchRegionsActive;//number of used sandboxWatchRegions entrys +static bool sandboxActive;//used to "log out" of the emulator once a test has finished +static bool sandboxControlHandoff;//used for functions that depend on timing, hands full control to the m68k +static uint8_t sandboxCurrentCpuArch; +static m68k_local_cpu_state_t sandboxOldFunctionM68kCpuState; +static uint64_t sandboxFramesRan; +static mem_region_t sandboxWatchRegions[SANDBOX_MAX_WATCH_REGIONS];//code locations in 68k address space to be sandboxed +static uint16_t sandboxWatchRegionsActive;//number of used sandboxWatchRegions entrys -static uint32_t sandboxCallGuestFunction(bool fallthrough, uint32_t address, uint16_t trap, const char* prototype, ...); +static uint32_t m515CallGuestFunction(bool fallthrough, uint32_t address, uint16_t trap, const char* prototype, ...); #include "sandboxTrapNumToName.c.h" @@ -104,7 +113,7 @@ static void patchOsRom(uint32_t address, char* patch){ swap16BufferIfLittle(&palmRom[swapBegin], swapSize); } -static const char* getLowMemGlobalName(uint32_t address){ +static const char* m515GetLowMemGlobalName(uint32_t address){ switch(address){ case 0x00000100: return "MemTotalCards"; @@ -147,7 +156,7 @@ static const char* getLowMemGlobalName(uint32_t address){ } } -static bool ignoreTrap(uint16_t trap){ +static bool m515IgnoreTrap(uint16_t trap){ switch(trap){ case HwrDisableDataWrites: case HwrEnableDataWrites: @@ -160,11 +169,11 @@ static bool ignoreTrap(uint16_t trap){ return false; } -static void printTrapInfo(uint16_t trap){ +static void m515PrintTrapInfo(uint16_t trap){ debugLog("name:%s, API:0x%04X, location:0x%08X\n", lookupTrap(trap), trap, m68k_read_memory_32(0x000008CC + (trap & 0x0FFF) * 4)); } -bool validExecutionAddress(uint32_t address){ +bool m515ValidExecutionAddress(uint32_t address){ if(dbvzChipSelects[DBVZ_CHIP_A0_ROM].inBootMode || address >= dbvzChipSelects[DBVZ_CHIP_A0_ROM].start && address < dbvzChipSelects[DBVZ_CHIP_A0_ROM].start + dbvzChipSelects[DBVZ_CHIP_A0_ROM].lineSize) return true; if(address >= dbvzChipSelects[DBVZ_CHIP_DX_RAM].start && address < dbvzChipSelects[DBVZ_CHIP_DX_RAM].start + dbvzChipSelects[DBVZ_CHIP_DX_RAM].lineSize) @@ -174,26 +183,26 @@ bool validExecutionAddress(uint32_t address){ return false; } -void log68kJumps(void){ +void logM68kJumps(void){ uint32_t opcodeStartPc = m68k_get_reg(NULL, M68K_REG_PPC); uint32_t opcodeEndPc = m68k_get_reg(NULL, M68K_REG_PC); uint32_t difference = llabs((int64_t)opcodeStartPc - (int64_t)opcodeEndPc); //if invalid always log, otherwise only log if big jump - if(!validExecutionAddress(opcodeEndPc)) + if(!m515ValidExecutionAddress(opcodeEndPc)) debugLog("m68k jumped 0x%08X bytes to invalid address, from 0x%08X to 0x%08X\n", difference, opcodeStartPc, opcodeEndPc); else if(difference > SANDBOX_MAX_UNLOGGED_JUMP_SIZE) debugLog("m68k jumped 0x%08X bytes, from 0x%08X to 0x%08X\n", difference, opcodeStartPc, opcodeEndPc); } -static void logApiCalls(void){ +static void m515LogApiCalls(void){ uint32_t programCounter = m68k_get_reg(NULL, M68K_REG_PPC); uint16_t instruction = m68k_read_memory_16(programCounter); if(instruction == 0x4E4F/*Trap F/API call opcode*/){ uint16_t trap = m68k_read_memory_16(programCounter + 2); - if(!ignoreTrap(trap)) + if(!m515IgnoreTrap(trap)) debugLog("Trap F API:%s, API number:0x%04X, PC:0x%08X\n", lookupTrap(trap), trap, programCounter); } } @@ -212,7 +221,7 @@ static bool readable6CharsBack(uint32_t address){ return true; } -static uint32_t find68kString(const char* str, uint32_t rangeStart, uint32_t rangeEnd){ +static uint32_t findM68kString(const char* str, uint32_t rangeStart, uint32_t rangeEnd){ uint32_t strLength = strlen(str) + 1;//include null terminator uint32_t scanAddress; @@ -240,7 +249,7 @@ static uint32_t find68kString(const char* str, uint32_t rangeStart, uint32_t ran return rangeEnd; } -static uint32_t skip68kString(uint32_t address){ +static uint32_t skipM68kString(uint32_t address){ while(m68k_read_memory_8(address) != '\0') address++; address++;//skip null terminator too @@ -248,18 +257,18 @@ static uint32_t skip68kString(uint32_t address){ } //THIS FUNCTION DOES NOT WORK IF A WORD ALIGNED 0x0000 IS FOUND IN THE FUNCTION BEING SEARCHED FOR, THIS IS A BUG -static uint32_t scanForPrivateFunctionAddress(const char* name){ +static uint32_t m515ScanForPrivateFunctionAddress(const char* name){ //function name format [0x**(unknown), string(with null terminator), 0x00, 0x00(if last 0x00 was on an even address, protects opcode alignemnt)] //this is not 100% accurate, it scans memory for a function address based on a string //if a duplicate set of stings is found but not encasing a function a fatal error will occur on execution uint32_t rangeEnd = dbvzChipSelects[DBVZ_CHIP_A0_ROM].start + dbvzChipSelects[DBVZ_CHIP_A0_ROM].lineSize - 1; - uint32_t address = find68kString(name, dbvzChipSelects[DBVZ_CHIP_A0_ROM].start, rangeEnd); + uint32_t address = findM68kString(name, dbvzChipSelects[DBVZ_CHIP_A0_ROM].start, rangeEnd); while(address < rangeEnd){ uint32_t signatureBegining = address - 3;//last opcode of function being looked for if the string is correct //skip string to test the null terminators - address = skip68kString(address); + address = skipM68kString(address); //after a function string there are 2 null terminators(the one all strings have and 1 extra) or 3(2 extra) if the previous one was on an even address if(m68k_read_memory_8(address) == '\0' && (address & 0x00000001 || m68k_read_memory_8(address + 1) == '\0')){ @@ -284,14 +293,14 @@ static uint32_t scanForPrivateFunctionAddress(const char* name){ } //string matched but structure was invalid, get next string - address = find68kString(name, address, rangeEnd); + address = findM68kString(name, address, rangeEnd); } return 0x00000000; } //call anywhere in a function to get its name, used to determine the location of a crash, must free the pointer after reading the string -static char* getFunctionName68k(uint32_t address){ +static char* getFunctionNameM68k(uint32_t address){ char* data; uint32_t offset; @@ -324,9 +333,9 @@ static char* getFunctionName68k(uint32_t address){ return data; } -static uint32_t makePalmString(const char* str){ +static uint32_t m515MakePalmString(const char* str){ uint32_t strLength = strlen(str) + 1; - uint32_t strData = sandboxCallGuestFunction(false, 0x00000000, MemPtrNew, "p(l)", strLength); + uint32_t strData = m515CallGuestFunction(false, 0x00000000, MemPtrNew, "p(l)", strLength); if(strData){ uint32_t count; @@ -338,9 +347,9 @@ static uint32_t makePalmString(const char* str){ return strData; } -static char* makeNativeString(uint32_t address){ +static char* m515MakeNativeString(uint32_t address){ if(address){ - int16_t strLength = sandboxCallGuestFunction(false, 0x00000000, StrLen, "w(p)", address) + 1; + int16_t strLength = m515CallGuestFunction(false, 0x00000000, StrLen, "w(p)", address) + 1; char* nativeStr = malloc(strLength); int16_t count; @@ -351,11 +360,11 @@ static char* makeNativeString(uint32_t address){ return NULL; } -static void freePalmString(uint32_t address){ - sandboxCallGuestFunction(false, 0x00000000, MemChunkFree, "w(p)", address); +static void m515FreePalmString(uint32_t address){ + m515CallGuestFunction(false, 0x00000000, MemChunkFree, "w(p)", address); } -static bool installResourceToDevice(uint8_t* data, uint32_t size){ +static bool m515InstallResourceToDevice(uint8_t* data, uint32_t size){ /* #define memNewChunkFlagNonMovable 0x0200 #define memNewChunkFlagAllowLarge 0x1000 // this is not in the sdk *g* @@ -375,7 +384,7 @@ static bool installResourceToDevice(uint8_t* data, uint32_t size){ } */ - uint32_t palmSideResourceData = sandboxCallGuestFunction(false, 0x00000000, MemChunkNew, "p(wlw)", 1/*heapID, storage RAM*/, size, 0x1200/*attr, seems to work without memOwnerID*/); + uint32_t palmSideResourceData = m515CallGuestFunction(false, 0x00000000, MemChunkNew, "p(wlw)", 1/*heapID, storage RAM*/, size, 0x1200/*attr, seems to work without memOwnerID*/); bool storageRamReadOnly = dbvzChipSelects[DBVZ_CHIP_DX_RAM].readOnlyForProtectedMemory; uint16_t error; uint32_t count; @@ -388,8 +397,8 @@ static bool installResourceToDevice(uint8_t* data, uint32_t size){ for(count = 0; count < size; count++) m68k_write_memory_8(palmSideResourceData + count, data[count]); dbvzChipSelects[DBVZ_CHIP_DX_RAM].readOnlyForProtectedMemory = storageRamReadOnly;//restore old protection state - error = sandboxCallGuestFunction(false, 0x00000000, DmCreateDatabaseFromImage, "w(p)", palmSideResourceData);//Err DmCreateDatabaseFromImage(MemPtr bufferP);//this looks best - sandboxCallGuestFunction(false, 0x00000000, MemChunkFree, "w(p)", palmSideResourceData); + error = m515CallGuestFunction(false, 0x00000000, DmCreateDatabaseFromImage, "w(p)", palmSideResourceData);//Err DmCreateDatabaseFromImage(MemPtr bufferP);//this looks best + m515CallGuestFunction(false, 0x00000000, MemChunkFree, "w(p)", palmSideResourceData); //didnt install if(error != 0) @@ -398,187 +407,7 @@ static bool installResourceToDevice(uint8_t* data, uint32_t size){ return true; } -static void printChunkHeader(uint32_t pointer){ - uint32_t address = pointer - 8; - uint32_t headerLong1 = m68k_read_memory_32(address); - uint32_t totalSize = headerLong1 & 0x00FFFFFF; - uint8_t extraBytes = headerLong1 >> 24 & 0x0F; - uint32_t userRequestedSize = totalSize - 8 - extraBytes; - - debugLog("Chunk header: address:0x%08X, totalSize:%d(0x%08X), userSize:%d(0x%08X), extraBytes:%d(0x%02X)\n", address, totalSize, totalSize, userRequestedSize, userRequestedSize, extraBytes, extraBytes); -} - -static void checkMemoryAlignmentPointer(uint16_t heap){ - uint32_t memPtrs[100]; - uint8_t index; - uint16_t error; - - memset(memPtrs, 0x00, sizeof(memPtrs)); - - //get randomly sized memory regions - for(index = 0; index < 100; index++){ - memPtrs[index] = sandboxCallGuestFunction(false, 0x00000000, MemChunkNew, "p(wlw)", heap, getRandomRange(1, 100), 0x0200/*memNewChunkFlagNonMovable*/); - if(!memPtrs[index]){ - debugLog("Memory test: Failed to allocate memory\n"); - goto failed; - } - } - - //check alignment - for(index = 0; index < 100; index++){ - if(memPtrs[index] & 0x00000003){ - debugLog("Memory test: Memory allocations are not 32 bit aligned:0x%08X\n", memPtrs[index]); - printChunkHeader(memPtrs[index]); - goto failed; - } - } - - //non moveable memory wont resize - - //shuffle memory - error = sandboxCallGuestFunction(false, 0x00000000, MemHeapCompact, "w(w)", heap); - if(error != 0x0000/*errNone*/){ - debugLog("Memory test: Unable to scramble heap:0x%04X\n", error); - goto failed; - } - - //check alignment again - for(index = 0; index < 100; index++){ - if(memPtrs[index] & 0x00000003){ - debugLog("Memory test: Memory misaligned by defragment:0x%08X\n", memPtrs[index]); - printChunkHeader(memPtrs[index]); - goto failed; - } - } - - debugLog("Memory test: Memory aligned correctly\n"); - - failed: - - //free pointers - for(index = 0; index < 100; index++) - if(memPtrs[index]) - sandboxCallGuestFunction(false, 0x00000000, MemChunkFree, "w(p)", memPtrs[index]); -} - -static void checkMemoryAlignmentHandle(uint16_t heap){ - uint32_t memHandles[100]; - uint32_t memPtrs[100]; - uint8_t index; - uint16_t error; - - //a handle is just a pointer with bit 31 set, when the pointer is moved a look up table entry is set to the new address and used for future operations - - memset(memHandles, 0x00, sizeof(memHandles)); - memset(memPtrs, 0x00, sizeof(memPtrs)); - - //get randomly sized memory regions - for(index = 0; index < 100; index++){ - memHandles[index] = sandboxCallGuestFunction(false, 0x00000000, MemChunkNew, "p(wlw)", heap, getRandomRange(1, 100), 0x0000); - if(!memHandles[index]){ - debugLog("Memory test: Failed to allocate memory\n"); - goto failed; - } - memHandles[index] |= 0x80000000;//tell the OS this is a handle, this is all MemHandleNew does is allocate memory normally and set that bit - } - - //update pointer list - for(index = 0; index < 100; index++){ - memPtrs[index] = sandboxCallGuestFunction(false, 0x00000000, MemHandleLock, "p(l)", memHandles[index]); - if(!memPtrs[index]){ - debugLog("Memory test: Failed to lock handle\n"); - goto failed; - } - error = sandboxCallGuestFunction(false, 0x00000000, MemHandleUnlock, "w(l)", memHandles[index]); - if(error != 0x0000/*errNone*/){ - debugLog("Memory test: Failed to unlock handle\n"); - goto failed; - } - } - - //check alignment - for(index = 0; index < 100; index++){ - if(memPtrs[index] & 0x00000003){ - debugLog("Memory test: Memory allocations are not 32 bit aligned:0x%08X\n", memPtrs[index]); - printChunkHeader(memPtrs[index]); - goto failed; - } - } - - //resize memory - for(index = 0; index < 100; index++){ - error = sandboxCallGuestFunction(false, 0x00000000, MemHandleResize, "w(ll)", memHandles[index], getRandomRange(1, 100)); - if(error != 0x0000/*errNone*/){ - debugLog("Memory test: Failed to resize memory:0x%04X\n", error); - goto failed; - } - } - - //update pointer list - for(index = 0; index < 100; index++){ - memPtrs[index] = sandboxCallGuestFunction(false, 0x00000000, MemHandleLock, "p(l)", memHandles[index]); - if(!memPtrs[index]){ - debugLog("Memory test: Failed to lock handle\n"); - goto failed; - } - error = sandboxCallGuestFunction(false, 0x00000000, MemHandleUnlock, "w(l)", memHandles[index]); - if(error != 0x0000/*errNone*/){ - debugLog("Memory test: Failed to unlock handle\n"); - goto failed; - } - } - - //check alignment again - for(index = 0; index < 100; index++){ - if(memPtrs[index] & 0x00000003){ - debugLog("Memory test: Memory misaligned by resize:0x%08X\n", memPtrs[index]); - printChunkHeader(memPtrs[index]); - goto failed; - } - } - - //shuffle memory - error = sandboxCallGuestFunction(false, 0x00000000, MemHeapCompact, "w(w)", heap); - if(error != 0x0000/*errNone*/){ - debugLog("Memory test: Unable to scramble heap:0x%04X\n", error); - goto failed; - } - - //update pointer list - for(index = 0; index < 100; index++){ - memPtrs[index] = sandboxCallGuestFunction(false, 0x00000000, MemHandleLock, "p(l)", memHandles[index]); - if(!memPtrs[index]){ - debugLog("Memory test: Failed to lock handle\n"); - goto failed; - } - error = sandboxCallGuestFunction(false, 0x00000000, MemHandleUnlock, "w(l)", memHandles[index]); - if(error != 0x0000/*errNone*/){ - debugLog("Memory test: Failed to unlock handle\n"); - goto failed; - } - } - - //check alignment again - for(index = 0; index < 100; index++){ - if(memPtrs[index] & 0x00000003){ - debugLog("Memory test: Memory misaligned by defragment:0x%08X\n", memPtrs[index]); - printChunkHeader(memPtrs[index]); - goto failed; - } - } - - debugLog("Memory test: Memory aligned correctly\n"); - - failed: - - //free handles - for(index = 0; index < 100; index++) - if(memHandles[index]) - sandboxCallGuestFunction(false, 0x00000000, MemHandleFree, "w(l)", memHandles[index]); -} - - -static uint32_t sandboxGetStackFrameSize(const char* prototype){ +static uint32_t m515GetStackFrameSize(const char* prototype){ const char* params = prototype + 2; uint32_t size = 0; @@ -611,23 +440,23 @@ static uint32_t sandboxGetStackFrameSize(const char* prototype){ return size; } -static void sandboxBackupCpuState(void){ - sandboxOldFunctionCpuState.sp = m68k_get_reg(NULL, M68K_REG_SP); - sandboxOldFunctionCpuState.pc = m68k_get_reg(NULL, M68K_REG_PC); - sandboxOldFunctionCpuState.sr = m68k_get_reg(NULL, M68K_REG_SR); - sandboxOldFunctionCpuState.a0 = m68k_get_reg(NULL, M68K_REG_A0); - sandboxOldFunctionCpuState.d0 = m68k_get_reg(NULL, M68K_REG_D0); +static void m515BackupCpuState(void){ + sandboxOldFunctionM68kCpuState.sp = m68k_get_reg(NULL, M68K_REG_SP); + sandboxOldFunctionM68kCpuState.pc = m68k_get_reg(NULL, M68K_REG_PC); + sandboxOldFunctionM68kCpuState.sr = m68k_get_reg(NULL, M68K_REG_SR); + sandboxOldFunctionM68kCpuState.a0 = m68k_get_reg(NULL, M68K_REG_A0); + sandboxOldFunctionM68kCpuState.d0 = m68k_get_reg(NULL, M68K_REG_D0); } -static void sandboxRestoreCpuState(void){ - m68k_set_reg(M68K_REG_SP, sandboxOldFunctionCpuState.sp); - m68k_set_reg(M68K_REG_PC, sandboxOldFunctionCpuState.pc); - m68k_set_reg(M68K_REG_SR, sandboxOldFunctionCpuState.sr & 0xF0FF | m68k_get_reg(NULL, M68K_REG_SR) & 0x0700);//dont restore intMask - m68k_set_reg(M68K_REG_A0, sandboxOldFunctionCpuState.a0); - m68k_set_reg(M68K_REG_D0, sandboxOldFunctionCpuState.d0); +static void m515RestoreCpuState(void){ + m68k_set_reg(M68K_REG_SP, sandboxOldFunctionM68kCpuState.sp); + m68k_set_reg(M68K_REG_PC, sandboxOldFunctionM68kCpuState.pc); + m68k_set_reg(M68K_REG_SR, sandboxOldFunctionM68kCpuState.sr & 0xF0FF | m68k_get_reg(NULL, M68K_REG_SR) & 0x0700);//dont restore intMask + m68k_set_reg(M68K_REG_A0, sandboxOldFunctionM68kCpuState.a0); + m68k_set_reg(M68K_REG_D0, sandboxOldFunctionM68kCpuState.d0); } -static uint32_t sandboxCallGuestFunction(bool fallthrough, uint32_t address, uint16_t trap, const char* prototype, ...){ +static uint32_t m515CallGuestFunction(bool fallthrough, uint32_t address, uint16_t trap, const char* prototype, ...){ //prototype is a Java style function signature describing values passed and returned "v(wllp)" //is return void and pass a uint16_t(word), 2 uint32_t(long) and 1 pointer //valid types are b(yte), w(ord), l(ong), p(ointer) and v(oid), a capital letter means its a return pointer @@ -636,7 +465,7 @@ static uint32_t sandboxCallGuestFunction(bool fallthrough, uint32_t address, uin va_list args; const char* params = prototype + 2; uint32_t stackFrameStart = m68k_get_reg(NULL, M68K_REG_SP); - uint32_t newStackFrameSize = sandboxGetStackFrameSize(prototype); + uint32_t newStackFrameSize = m515GetStackFrameSize(prototype); uint32_t stackWriteAddr = stackFrameStart - newStackFrameSize; uint32_t oldStopped = m68ki_cpu.stopped; uint32_t functionReturn = 0x00000000; @@ -646,7 +475,7 @@ static uint32_t sandboxCallGuestFunction(bool fallthrough, uint32_t address, uin uint32_t callStart; uint8_t count; - sandboxBackupCpuState(); + m515BackupCpuState(); va_start(args, prototype); while(*params != ')'){ @@ -751,7 +580,7 @@ static uint32_t sandboxCallGuestFunction(bool fallthrough, uint32_t address, uin else if(prototype[0] == 'b' || prototype[0] == 'w' || prototype[0] == 'l') functionReturn = m68k_get_reg(NULL, M68K_REG_D0); m68ki_cpu.stopped = oldStopped; - sandboxRestoreCpuState(); + m515RestoreCpuState(); //remap all argument pointers for(count = 0; count < functionReturnPointerIndex; count++){ @@ -783,6 +612,7 @@ void sandboxInit(void){ void sandboxReset(void){ sandboxActive = false; sandboxControlHandoff = false; + sandboxCurrentCpuArch = SANDBOX_CPU_ARCH_M68K; sandboxFramesRan = 0; memset(sandboxWatchRegions, 0x00, sizeof(sandboxWatchRegions)); @@ -802,8 +632,8 @@ uint32_t sandboxStateSize(void){ uint32_t size = 0; size += sizeof(uint8_t) * 3;//sandboxActive / sandboxControlHandoff / sandboxCurrentCpuArch - size += sizeof(uint32_t) * 4;//sandboxOldFunctionCpuState.(sp/pc/a0/d0) - size += sizeof(uint16_t);//sandboxOldFunctionCpuState.sr + size += sizeof(uint32_t) * 4;//sandboxOldFunctionM68kCpuState.(sp/pc/a0/d0) + size += sizeof(uint16_t);//sandboxOldFunctionM68kCpuState.sr size += sizeof(uint64_t);//sandboxFramesRan size += sizeof(uint32_t) * 2 * SANDBOX_MAX_WATCH_REGIONS;//sandboxWatchRegions.(address/size) size += sizeof(uint8_t) * SANDBOX_MAX_WATCH_REGIONS;//sandboxWatchRegions.type @@ -822,15 +652,15 @@ void sandboxSaveState(uint8_t* data){ offset += sizeof(uint8_t); writeStateValue8(data + offset, sandboxCurrentCpuArch);//currently cant be ARMv5 during a frame boundry but that may change offset += sizeof(uint8_t); - writeStateValue32(data + offset, sandboxOldFunctionCpuState.sp); + writeStateValue32(data + offset, sandboxOldFunctionM68kCpuState.sp); offset += sizeof(uint32_t); - writeStateValue32(data + offset, sandboxOldFunctionCpuState.pc); + writeStateValue32(data + offset, sandboxOldFunctionM68kCpuState.pc); offset += sizeof(uint32_t); - writeStateValue16(data + offset, sandboxOldFunctionCpuState.sr); + writeStateValue16(data + offset, sandboxOldFunctionM68kCpuState.sr); offset += sizeof(uint16_t); - writeStateValue32(data + offset, sandboxOldFunctionCpuState.a0); + writeStateValue32(data + offset, sandboxOldFunctionM68kCpuState.a0); offset += sizeof(uint32_t); - writeStateValue32(data + offset, sandboxOldFunctionCpuState.d0); + writeStateValue32(data + offset, sandboxOldFunctionM68kCpuState.d0); offset += sizeof(uint32_t); writeStateValue64(data + offset, sandboxFramesRan); offset += sizeof(uint64_t); @@ -856,15 +686,15 @@ void sandboxLoadState(uint8_t* data){ offset += sizeof(uint8_t); sandboxCurrentCpuArch = readStateValue8(data + offset);//currently cant be ARMv5 during a frame boundry but that may change offset += sizeof(uint8_t); - sandboxOldFunctionCpuState.sp = readStateValue32(data + offset); + sandboxOldFunctionM68kCpuState.sp = readStateValue32(data + offset); offset += sizeof(uint32_t); - sandboxOldFunctionCpuState.pc = readStateValue32(data + offset); + sandboxOldFunctionM68kCpuState.pc = readStateValue32(data + offset); offset += sizeof(uint32_t); - sandboxOldFunctionCpuState.sr = readStateValue16(data + offset); + sandboxOldFunctionM68kCpuState.sr = readStateValue16(data + offset); offset += sizeof(uint16_t); - sandboxOldFunctionCpuState.a0 = readStateValue32(data + offset); + sandboxOldFunctionM68kCpuState.a0 = readStateValue32(data + offset); offset += sizeof(uint32_t); - sandboxOldFunctionCpuState.d0 = readStateValue32(data + offset); + sandboxOldFunctionM68kCpuState.d0 = readStateValue32(data + offset); offset += sizeof(uint32_t); sandboxFramesRan = readStateValue64(data + offset); offset += sizeof(uint64_t); @@ -898,173 +728,12 @@ uint32_t sandboxCommand(uint32_t command, void* data){ //patchOsRom(0x83B0A, "203C000800004E75");//move.l 0x80000, d0; rts //patchOsRom(0x5CC6, "203C001000004E75");//move.l 0x100000, d0; rts //patchOsRom(0x83B0A, "203C001000004E75");//move.l 0x100000, d0; rts - - //patch PrvChunkNew to only allocate in 4 byte intervals - //PrvChunkNew_10020CBC: - //TODO - - //set RAM to 32MB - //patchOsRom(0x2C5E, "203C020000004E75");//move.l 0x2000000, d0; rts - //patchOsRom(0x8442E, "203C020000004E75");//move.l 0x2000000, d0; rts - - //set RAM to 128MB - //PrvGetRAMSize_10002C5E, small ROM - //PrvGetRAMSize_1008442E, big ROM - //patchOsRom(0x2C5E, "203C080000004E75");//move.l 0x8000000, d0; rts - //patchOsRom(0x8442E, "203C080000004E75");//move.l 0x8000000, d0; rts - //ROM:100219D0 move.l #unk_FFFFFF,d0 - //patchOsRom(0x219D0, "203C01FFFFFF4E75");//move.l 0x1FFFFFF, d0; rts - //bus error at 0x1001DEDA when 128MB is present - //0x55 memory filler, 32 bit, at PC:0x1001FFDC, and of course, its MemSet, need a stack trace now - //PrvInitHeapPtr_10021908 sets up the 0x55 stuff in RAM - /* - ROM:100219C2 move.l d0,6(a4) ; Move Data from Source to Destination - ROM:100219C6 tst.b arg_A(a6) ; Test an Operand - ROM:100219CA beq.s loc_100219EA ; Branch if Equal - ROM:100219CC move.b #$55,-(sp) ; 'U' ; Move Data from Source to Destination - ROM:100219D0 move.l #unk_FFFFFF,d0 ; Move Data from Source to Destination - ROM:100219D6 and.l (a3),d0 ; AND Logical - ROM:100219D8 subq.l #8,d0 ; Subtract Quick - ROM:100219DA move.l d0,-(sp) ; Move Data from Source to Destination - ROM:100219DC movea.l a3,a0 ; Move Address - ROM:100219DE pea 8(a0) ; Push Effective Address - ROM:100219E2 trap #$F ; Trap sysTrapMemSet - ROM:100219E2 dc.w $A027 - ROM:100219E6 lea $A(sp),sp ; Load Effective Address - */ - //D0 is 0x3E1CC(254412) at PC:0x10021988 - - // Add the heap, as long as it's not the dynamic heap. During - // bootup, the memory initialization sequence goes like: - // - // if hard reset required: - // MemCardFormat - // lay out the card - // MemStoreInit - // for each heap - // MemHeapInit - // MemInit - // for each card: - // MemInitHeapTable - // for each dynamic heap: - // MemHeapInit - // for each RAM heap: - // Unlock all chunks - // Compact - // - // Which means that if there's no hard reset, MemHeapInit - // has not been called on the dynamic heap at the time - // MemInitHeapTable is called. And since the dynamic heap - // is currently in a corrupted state (because the boot stack - // and initial LCD buffer have been whapped over it), we - // can't perform the heap walk we'd normally do when adding - // a heap object. - - //need to investigate what these vars are - /* - ROM:100148EE move.l #$3BE,(dword_15C).w ; Move Data from Source to Destination - ROM:100148F6 move.l #$422,(dword_112).w ; Move Data from Source to Destination - ROM:100148FE move.l #$890,(dword_11A).w ; Move Data from Source to Destination - ROM:10014906 move.l #$8CC,(TrapTablePointer).w ; Move Data from Source to Destination - ROM:1001490E move.w #$45A,(word_13E).w ; Move Data from Source to Destination - ROM:10014914 move.w #$1000,(word_28E).w ; Move Data from Source to Destination - */ - - //another road block surfaces - /* - When a Palm Powered handheld is presented with multiple dynamic heaps, - the first heap (heap 0) on card 0 is the active dynamic heap. - All other potential dynamic heaps are ignored. For example, it - is possible that a future Palm Powered handheld supporting multiple - cards might be presented with two cards, each having its own dynamic heap; - if so, only the dynamic heap residing on card 0 would be active—the system - would not treat any heaps on other cards as dynamic heaps, nor would heap - IDs be assigned to these heaps. Subsequent storage heaps would be assigned - IDs in sequential order, as always beginning with RAM heaps, followed by ROM heaps. - */ - - //PrvChunkNew alignment code - /* - ROM:10020D04 moveq #1,d0 ; Move Quick - ROM:10020D06 and.l size(a6),d0 ; Check if size is a multiple of 2 - ROM:10020D0A addq.w #2,sp ; Add Quick - ROM:10020D0C beq.s loc_10020D16 ; Skip adding extra byte if already aligned - ROM:10020D0E moveq #9,d0 ; Size is not 16 bit aligned, align and add 8 bytes - ROM:10020D10 add.l size(a6),d0 ; Add requested size - ROM:10020D14 bra.s loc_10020D1C ; Branch Always - ROM:10020D16 ; --------------------------------------------------------------------------- - ROM:10020D16 - ROM:10020D16 loc_10020D16: ; CODE XREF: PrvChunkNew_10020CBC+50↑j - ROM:10020D16 move.l size(a6),d0 ; Set requested size - ROM:10020D1A addq.l #8,d0 ; Add 8 bytes(currently dont know what there for) - ROM:10020D1C - */ - - //PrvPtrResize alignment code - /* - ROM:1002123C moveq #1,d0 ; Move Quick - ROM:1002123E and.l arg_4(a6),d0 ; AND Logical - ROM:10021242 addq.w #8,sp ; Add Quick - ROM:10021244 beq.s loc_1002124E ; Branch if Equal - ROM:10021246 moveq #9,d0 ; Move Quick - ROM:10021248 add.l arg_4(a6),d0 ; Add - ROM:1002124C bra.s loc_10021254 ; Branch Always - ROM:1002124E ; --------------------------------------------------------------------------- - ROM:1002124E - ROM:1002124E loc_1002124E: ; CODE XREF: PrvPtrResize_100211F6+4E↑j - ROM:1002124E move.l arg_4(a6),d0 ; Move Data from Source to Destination - ROM:10021252 addq.l #8,d0 ; Add Quick - ROM:10021254 - */ - - //PrvMoveChunk alignment code???(not sure yet) - /* - ROM:10021C82 sub.l d0,d7 ; Subtract - ROM:10021C84 move.l d7,d5 ; Move Data from Source to Destination - ROM:10021C86 moveq #1,d0 ; Set bitmask - ROM:10021C88 and.l d7,d0 ; Check if bit 0 of d7 is set - ROM:10021C8A beq.s loc_10021C8E ; If bit 0 of d7 is set add 1 to d5 - ROM:10021C8C addq.l #1,d5 ; 16 bit align ??? - */ - - //size extra bits are not being set when chunks are allocated - - //PrvChunkNew derives size extra from total size - requested size, so its already safe, PrvPtrResize does the same - /* - ROM:10020FFA setSizeExtra: ; CODE XREF: PrvChunkNew_10020CBC+312↑j - ROM:10020FFA move.l d3,d0 ; Move Data from Source to Destination - ROM:10020FFC sub.l size(a6),d0 ; Subtract - ROM:10021000 subq.l #8,d0 ; Subtract Quick - ROM:10021002 andi.b #$F,d0 ; AND Immediate - ROM:10021006 andi.b #$F0,(a2) ; AND Immediate - ROM:1002100A or.b d0,(a2) ; Inclusive-OR Logical - */ - - //current suspect functions are PrvCreateFreeChunk and PrvUseFreeChunk - //also merging chunks may cause some kind of issue - - //PrvPtrResize is likely moving the chunk in front forwards if its small enough and leaving the data in place to save the opcodes needed to copy the data elsewhere - //if this is true then a resize of existing size + 2 will push the next chunk forward by 2 misaligning it - //could also be moving the header backwards by 2 if its willing to shift all the data manualy or corrupt the data - - //patch PrvChunkNew to 32 bit alignment, this alone does not fix 32 bit alignment issues - patchOsRom(0x20D04, "202E000AC0BCFFFFFFFCB0AE000A6700000458805080544F");//adds an extra 4 bytes if & 0x00000003 is true - //when moving memory around some 16 bit aligned pointers still show up - - //patch PrvPtrResize to 32 bit alignment, this alone does not fix 32 bit alignment issues - patchOsRom(0x2123C, "202E000CC0BCFFFFFFFCB0AE000C6700000458805080504F");//adds an extra 4 bytes if & 0x00000003 is true - - //may need to patch 0x7FFFFFFE's to 0x7FFFFFFC's - - //other functions that may need to be patched are: - //PrvCompactHeap_10021A12 - //PrvMoveChunk_10021C3E } break; case SANDBOX_CMD_DEBUG_INSTALL_APP:{ uintptr_t* values = data; - bool success = installResourceToDevice(values[0], values[1]); + bool success = m515InstallResourceToDevice(values[0], values[1]); if(!success) result = EMU_ERROR_OUT_OF_MEMORY; @@ -1077,14 +746,6 @@ uint32_t sandboxCommand(uint32_t command, void* data){ } break; - case SANDBOX_CMD_TEST_MEMORY_ALIGNMENT:{ - checkMemoryAlignmentPointer(0);//RAM heap - checkMemoryAlignmentPointer(1);//storage heap - checkMemoryAlignmentHandle(0);//RAM heap - checkMemoryAlignmentHandle(1);//storage heap - } - break; - default: break; } @@ -1098,11 +759,7 @@ void sandboxOnFrameRun(void){ //run at the end of every frame sandboxFramesRan++; - /* - if(sandboxFramesRan == SANDBOX_SECONDS_TO_FRAMES(10)){ - sandboxCommand(SANDBOX_CMD_TEST_MEMORY_ALIGNMENT, NULL); - } - */ + //add tests here } void sandboxOnOpcodeRun(void){ @@ -1193,7 +850,7 @@ void sandboxOnMemoryAccess(uint32_t address, uint8_t size, bool write, uint32_t if(sandboxedMemory || sandboxRunning()){ uint32_t pc = m68k_get_reg(NULL, M68K_REG_PPC); - char* function = getFunctionName68k(pc); + char* function = getFunctionNameM68k(pc); bool functionValid = !!function; if(!functionValid) @@ -1204,9 +861,9 @@ void sandboxOnMemoryAccess(uint32_t address, uint8_t size, bool write, uint32_t address &= 0xFFFF; if(write) - debugLog("Writing low mem global: name:%s/global:0x%08X, size:%d, value:0x%08X, function:%s/PC:0x%08X\n", getLowMemGlobalName(address), address, size, value, function, pc); + debugLog("Writing low mem global: name:%s/global:0x%08X, size:%d, value:0x%08X, function:%s/PC:0x%08X\n", m515GetLowMemGlobalName(address), address, size, value, function, pc); else - debugLog("Reading low mem global: name:%s/global:0x%08X, size:%d, function:%s/PC:0x%08X\n", getLowMemGlobalName(address), address, size, function, pc); + debugLog("Reading low mem global: name:%s/global:0x%08X, size:%d, function:%s/PC:0x%08X\n", m515GetLowMemGlobalName(address), address, size, function, pc); } else if(address >= 0xFFFFF000){ //hardware registers @@ -1268,7 +925,7 @@ void sandboxOnMemoryAccess(uint32_t address, uint8_t size, bool write, uint32_t } bool sandboxRunning(void){ - uint32_t pc = m68k_get_reg(NULL, M68K_REG_PC); + uint32_t pc = sandboxCurrentCpuArch == SANDBOX_CPU_ARCH_M68K ? m68k_get_reg(NULL, M68K_REG_PC) : reg_pc(15); uint16_t memRegion; //this is used to capture full logs when running from specific locations @@ -1285,7 +942,7 @@ void sandboxReturn(void){ if(sandboxControlHandoff){ //control was just handed back to the host sandboxControlHandoff = false; - sandboxRestoreCpuState(); + m515RestoreCpuState(); debugLog("Sandbox: Control returned to host\n"); } } diff --git a/src/debug/sandbox.h b/src/debug/sandbox.h index 606cf48..09453be 100644 --- a/src/debug/sandbox.h +++ b/src/debug/sandbox.h @@ -7,8 +7,7 @@ enum{ SANDBOX_CMD_PATCH_OS = 0, SANDBOX_CMD_DEBUG_INSTALL_APP, - SANDBOX_CMD_REGISTER_WATCH_ENABLE, - SANDBOX_CMD_TEST_MEMORY_ALIGNMENT + SANDBOX_CMD_REGISTER_WATCH_ENABLE }; enum{ @@ -20,8 +19,7 @@ enum{ enum{ SANDBOX_CPU_ARCH_M68K = 0, - SANDBOX_CPU_ARCH_ARMV5, - SANDBOX_CPU_ARCH_THUMB + SANDBOX_CPU_ARCH_ARMV5 }; void sandboxInit(void); diff --git a/src/emulator.c b/src/emulator.c index b89ca77..d611c9b 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -139,6 +139,7 @@ uint32_t emulatorInit(uint8_t* palmRomData, uint32_t palmRomSize, uint8_t* palmB pxa260Framebuffer = palmFramebuffer; blip_set_rates(palmAudioResampler, DBVZ_AUDIO_MAX_CLOCK_RATE, AUDIO_SAMPLE_RATE); sandboxInit(); + sandboxSetCpuArch(SANDBOX_CPU_ARCH_ARMV5); //reset everything emulatorSoftReset(); @@ -185,6 +186,7 @@ uint32_t emulatorInit(uint8_t* palmRomData, uint32_t palmRomSize, uint8_t* palmB //initialize components blip_set_rates(palmAudioResampler, DBVZ_AUDIO_MAX_CLOCK_RATE, AUDIO_SAMPLE_RATE); sandboxInit(); + sandboxSetCpuArch(SANDBOX_CPU_ARCH_M68K); //reset everything emulatorSoftReset();