static bool checkStart(u32 start, u32 size) { bool invalidSize = false; bool invalidAddress = false; if (isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start)) { invalidSize = !isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start+size-1); } else if (isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start)) { invalidSize = !isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start+size-1); } else if (isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start)) { invalidSize = !isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start+size-1); } else { invalidAddress = true; } if (invalidAddress) { printf("Invalid address 0x%08X.\n",start); return false; } else if (invalidSize) { printf("Invalid end address 0x%08X.\n",start+size); return false; } return true; }
void __KernelMemoryInit() { kernelMemory.Init(PSP_GetKernelMemoryBase(), PSP_GetKernelMemoryEnd()-PSP_GetKernelMemoryBase()); userMemory.Init(PSP_GetUserMemoryBase(), PSP_GetUserMemoryEnd()-PSP_GetUserMemoryBase()); INFO_LOG(HLE, "Kernel and user memory pools initialized"); vplWaitTimer = CoreTiming::RegisterEvent("VplTimeout", __KernelVplTimeout); }
void __KernelMemoryInit() { kernelMemory.Init(PSP_GetKernelMemoryBase(), PSP_GetKernelMemoryEnd()-PSP_GetKernelMemoryBase()); userMemory.Init(PSP_GetUserMemoryBase(), PSP_GetUserMemoryEnd()-PSP_GetUserMemoryBase()); INFO_LOG(HLE, "Kernel and user memory pools initialized"); vplWaitTimer = CoreTiming::RegisterEvent("VplTimeout", __KernelVplTimeout); flags_ = 0; sdkVersion_ = 0; compilerVersion_ = 0; memset(tlsUsedIndexes, 0, sizeof(tlsUsedIndexes)); }
void Jit::SetCCAndR0ForSafeAddress(MIPSGPReg rs, s16 offset, ARMReg tempReg, bool reverse) { SetR0ToEffectiveAddress(rs, offset); // There are three valid ranges. Each one gets a bit. const u32 BIT_SCRATCH = 1, BIT_RAM = 2, BIT_VRAM = 4; MOVI2R(tempReg, BIT_SCRATCH | BIT_RAM | BIT_VRAM); CMP(R0, AssumeMakeOperand2(PSP_GetScratchpadMemoryBase())); SetCC(CC_LO); BIC(tempReg, tempReg, BIT_SCRATCH); SetCC(CC_HS); CMP(R0, AssumeMakeOperand2(PSP_GetScratchpadMemoryEnd())); BIC(tempReg, tempReg, BIT_SCRATCH); // If it was in that range, later compares don't matter. CMP(R0, AssumeMakeOperand2(PSP_GetVidMemBase())); SetCC(CC_LO); BIC(tempReg, tempReg, BIT_VRAM); SetCC(CC_HS); CMP(R0, AssumeMakeOperand2(PSP_GetVidMemEnd())); BIC(tempReg, tempReg, BIT_VRAM); CMP(R0, AssumeMakeOperand2(PSP_GetKernelMemoryBase())); SetCC(CC_LO); BIC(tempReg, tempReg, BIT_RAM); SetCC(CC_HS); CMP(R0, AssumeMakeOperand2(PSP_GetUserMemoryEnd())); BIC(tempReg, tempReg, BIT_RAM); // If we left any bit set, the address is OK. SetCC(CC_AL); CMP(tempReg, 0); SetCC(reverse ? CC_EQ : CC_GT); }
void Jit::WriteExitDestInEAX() { // TODO: Some wasted potential, dispatcher will always read this back into EAX. MOV(32, M(&mips_->pc), R(EAX)); WriteDowncount(); // Validate the jump to avoid a crash? if (!g_Config.bFastMemory) { CMP(32, R(EAX), Imm32(PSP_GetKernelMemoryBase())); FixupBranch tooLow = J_CC(CC_L); CMP(32, R(EAX), Imm32(PSP_GetUserMemoryEnd())); FixupBranch tooHigh = J_CC(CC_GE); JMP(asm_.dispatcher, true); SetJumpTarget(tooLow); SetJumpTarget(tooHigh); ABI_CallFunctionA(thunks.ProtectFunction((void *) Memory::GetPointer, 1), R(EAX)); CMP(32, R(EAX), Imm32(0)); J_CC(CC_NE, asm_.dispatcher, true); // TODO: "Ignore" this so other threads can continue? if (g_Config.bIgnoreBadMemAccess) MOV(32, M((void*)&coreState), Imm32(CORE_ERROR)); JMP(asm_.dispatcherCheckCoreState, true); } else JMP(asm_.dispatcher, true); }
void DoState(PointerWrap &p) { auto s = p.Section("Memory", 1, 2); if (!s) return; if (s < 2) { if (!g_RemasterMode) g_MemorySize = RAM_NORMAL_SIZE; g_PSPModel = PSP_MODEL_FAT; } else { u32 oldMemorySize = g_MemorySize; p.Do(g_PSPModel); p.DoMarker("PSPModel"); if (!g_RemasterMode) { g_MemorySize = g_PSPModel == PSP_MODEL_FAT ? RAM_NORMAL_SIZE : RAM_DOUBLE_SIZE; if (oldMemorySize < g_MemorySize) { Shutdown(); Init(); } } } p.DoArray(GetPointer(PSP_GetKernelMemoryBase()), g_MemorySize); p.DoMarker("RAM"); p.DoArray(m_pVRAM, VRAM_SIZE); p.DoMarker("VRAM"); p.DoArray(m_pScratchPad, SCRATCHPAD_SIZE); p.DoMarker("ScratchPad"); }
void Clear() { if (m_pPhysicalRAM) memset(GetPointerUnchecked(PSP_GetKernelMemoryBase()), 0, g_MemorySize); if (m_pPhysicalScratchPad) memset(m_pPhysicalScratchPad, 0, SCRATCHPAD_SIZE); if (m_pPhysicalVRAM1) memset(m_pPhysicalVRAM1, 0, VRAM_SIZE); }
OpArg Jit::JitSafeMem::PrepareMemoryOpArg(ReadType type) { // We may not even need to move into EAX as a temporary. bool needTemp = alignMask_ != 0xFFFFFFFF; #ifdef _M_IX86 // We always mask on 32 bit in fast memory mode. needTemp = needTemp || fast_; #endif if (jit_->gpr.R(raddr_).IsSimpleReg() && !needTemp) { jit_->gpr.MapReg(raddr_, true, false); xaddr_ = jit_->gpr.RX(raddr_); } else { jit_->MOV(32, R(EAX), jit_->gpr.R(raddr_)); xaddr_ = EAX; } MemCheckAsm(type); if (!fast_) { // Is it in physical ram? jit_->CMP(32, R(xaddr_), Imm32(PSP_GetKernelMemoryBase() - offset_)); tooLow_ = jit_->J_CC(CC_B); jit_->CMP(32, R(xaddr_), Imm32(PSP_GetUserMemoryEnd() - offset_ - (size_ - 1))); tooHigh_ = jit_->J_CC(CC_AE); // We may need to jump back up here. safe_ = jit_->GetCodePtr(); } else { #ifdef _M_IX86 jit_->AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); #endif } // TODO: This could be more optimal, but the common case is that we want xaddr_ not to include offset_. // Since we need to align them after add, we add and subtract. if (alignMask_ != 0xFFFFFFFF) { jit_->ADD(32, R(xaddr_), Imm32(offset_)); jit_->AND(32, R(xaddr_), Imm32(alignMask_)); jit_->SUB(32, R(xaddr_), Imm32(offset_)); } #ifdef _M_IX86 return MDisp(xaddr_, (u32) Memory::base + offset_); #else return MComplex(RBX, xaddr_, SCALE_1, offset_); #endif }
void Jit::WriteExitDestInEAX() { // TODO: Some wasted potential, dispatcher will always read this back into EAX. MOV(32, M(&mips_->pc), R(EAX)); // If we need to verify coreState and rewind, we may not jump yet. if (js.afterOp & (JitState::AFTER_CORE_STATE | JitState::AFTER_REWIND_PC_BAD_STATE)) { // CORE_RUNNING is <= CORE_NEXTFRAME. CMP(32, M((void*)&coreState), Imm32(CORE_NEXTFRAME)); FixupBranch skipCheck = J_CC(CC_LE); MOV(32, M(&mips_->pc), Imm32(js.compilerPC)); WriteSyscallExit(); SetJumpTarget(skipCheck); js.afterOp = JitState::AFTER_NONE; } WriteDowncount(); // Validate the jump to avoid a crash? if (!g_Config.bFastMemory) { CMP(32, R(EAX), Imm32(PSP_GetKernelMemoryBase())); FixupBranch tooLow = J_CC(CC_B); CMP(32, R(EAX), Imm32(PSP_GetUserMemoryEnd())); FixupBranch tooHigh = J_CC(CC_AE); // Need to set neg flag again if necessary. SUB(32, M(¤tMIPS->downcount), Imm32(0)); JMP(asm_.dispatcher, true); SetJumpTarget(tooLow); SetJumpTarget(tooHigh); CallProtectedFunction((void *) Memory::GetPointer, R(EAX)); CMP(32, R(EAX), Imm32(0)); FixupBranch skip = J_CC(CC_NE); // TODO: "Ignore" this so other threads can continue? if (g_Config.bIgnoreBadMemAccess) CallProtectedFunction((void *) Core_UpdateState, Imm32(CORE_ERROR)); SUB(32, M(¤tMIPS->downcount), Imm32(0)); JMP(asm_.dispatcherCheckCoreState, true); SetJumpTarget(skip); SUB(32, M(¤tMIPS->downcount), Imm32(0)); J_CC(CC_NE, asm_.dispatcher, true); } else JMP(asm_.dispatcher, true); }
OpArg Jit::JitSafeMem::PrepareMemoryOpArg() { // We may not even need to move into EAX as a temporary. // TODO: Except on x86 in fastmem mode. if (jit_->gpr.R(raddr_).IsSimpleReg()) { jit_->gpr.BindToRegister(raddr_, true, false); xaddr_ = jit_->gpr.RX(raddr_); } else { jit_->MOV(32, R(EAX), jit_->gpr.R(raddr_)); xaddr_ = EAX; } if (!g_Config.bFastMemory) { // Is it in physical ram? jit_->CMP(32, R(xaddr_), Imm32(PSP_GetKernelMemoryBase() - offset_)); tooLow_ = jit_->J_CC(CC_L); jit_->CMP(32, R(xaddr_), Imm32(PSP_GetUserMemoryEnd() - offset_)); tooHigh_ = jit_->J_CC(CC_GE); // We may need to jump back up here. safe_ = jit_->GetCodePtr(); } else { #ifdef _M_IX86 // Need to modify it, too bad. if (xaddr_ != EAX) jit_->MOV(32, R(EAX), R(xaddr_)); jit_->AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); xaddr_ = EAX; #endif } #ifdef _M_IX86 return MDisp(xaddr_, (u32) Memory::base + offset_); #else return MComplex(RBX, xaddr_, SCALE_1, offset_); #endif }
void DoState(PointerWrap &p) { auto s = p.Section("Memory", 1, 3); if (!s) return; if (s < 2) { if (!g_RemasterMode) g_MemorySize = RAM_NORMAL_SIZE; g_PSPModel = PSP_MODEL_FAT; } else if (s == 2) { // In version 2, we determine memory size based on PSP model. u32 oldMemorySize = g_MemorySize; p.Do(g_PSPModel); p.DoMarker("PSPModel"); if (!g_RemasterMode) { g_MemorySize = g_PSPModel == PSP_MODEL_FAT ? RAM_NORMAL_SIZE : RAM_DOUBLE_SIZE; if (oldMemorySize < g_MemorySize) { Shutdown(); Init(); } } } else { // In version 3, we started just saving the memory size directly. // It's no longer based strictly on the PSP model. u32 oldMemorySize = g_MemorySize; p.Do(g_PSPModel); p.DoMarker("PSPModel"); p.Do(g_MemorySize); if (oldMemorySize != g_MemorySize) { Shutdown(); Init(); } } p.DoArray(GetPointer(PSP_GetKernelMemoryBase()), g_MemorySize); p.DoMarker("RAM"); p.DoArray(m_pPhysicalVRAM1, VRAM_SIZE); p.DoMarker("VRAM"); p.DoArray(m_pPhysicalScratchPad, SCRATCHPAD_SIZE); p.DoMarker("ScratchPad"); }
bool DumpMemoryWindow::fetchDialogData(HWND hwnd) { char str[256],errorMessage[256]; PostfixExpression exp; // parse start address GetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),str,256); if (cpu->initExpression(str,exp) == false || cpu->parseExpression(exp,start) == false) { sprintf(errorMessage,"Invalid address expression \"%s\".",str); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } // parse size GetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_SIZE),str,256); if (cpu->initExpression(str,exp) == false || cpu->parseExpression(exp,size) == false) { sprintf(errorMessage,"Invalid size expression \"%s\".",str); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } if (size == 0) { MessageBoxA(hwnd,"Invalid size 0.","Error",MB_OK); return false; } // get filename GetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_FILENAME),fileName,MAX_PATH); if (strlen(fileName) == 0) return false; // now check if data makes sense... bool invalidSize = false; bool invalidAddress = false; if (isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start)) { invalidSize = !isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start+size-1); } else if (isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start)) { invalidSize = !isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start+size-1); } else if (isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start)) { invalidSize = !isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start+size-1); } else { invalidAddress = true; } if (invalidAddress) { sprintf(errorMessage,"Invalid address 0x%08X.",start); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } else if (invalidSize) { sprintf(errorMessage,"Invalid end address 0x%08X.",start+size); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } return true; }