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 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 __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); }
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 JitBlockCache::FinalizeBlock(int block_num, bool block_link) { JitBlock &b = blocks_[block_num]; b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress); MIPSOpcode opcode = GetEmuHackOpForBlock(block_num); Memory::Write_Opcode_JIT(b.originalAddress, opcode); AddBlockMap(block_num); u32 latestExit = 0; if (block_link) { for (int i = 0; i < MAX_JIT_BLOCK_EXITS; i++) { if (b.exitAddress[i] != INVALID_EXIT) { links_to_.insert(std::make_pair(b.exitAddress[i], block_num)); latestExit = std::max(latestExit, b.exitAddress[i]); } } LinkBlock(block_num); LinkBlockExits(block_num); } if (Memory::IsScratchpadAddress(b.originalAddress)) { ExpandRange(blockMemRanges_[JITBLOCK_RANGE_SCRATCH], b.originalAddress, latestExit); } const u32 halfUserMemory = (PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase()) / 2; if (b.originalAddress < PSP_GetUserMemoryBase() + halfUserMemory) { ExpandRange(blockMemRanges_[JITBLOCK_RANGE_RAMBOTTOM], b.originalAddress, latestExit); } if (latestExit > PSP_GetUserMemoryBase() + halfUserMemory) { ExpandRange(blockMemRanges_[JITBLOCK_RANGE_RAMTOP], b.originalAddress, latestExit); } #if defined USE_OPROFILE && USE_OPROFILE char buf[100]; sprintf(buf, "EmuCode%x", b.originalAddress); const u8* blockStart = blocks_[block_num].checkedEntry; op_write_native_code(agent, buf, (uint64_t)blockStart, blockStart, b.normalEntry + b.codeSize - b.checkedEntry); #endif #ifdef USE_VTUNE sprintf(b.blockName, "EmuCode_0x%08x", b.originalAddress); iJIT_Method_Load jmethod = {0}; jmethod.method_id = iJIT_GetNewMethodID(); jmethod.class_file_name = ""; jmethod.source_file_name = __FILE__; jmethod.method_load_address = (void*)blocks_[block_num].checkedEntry; jmethod.method_size = b.normalEntry + b.codeSize - b.checkedEntry; jmethod.line_number_size = 0; jmethod.method_name = b.blockName; iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod); #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); }
void DumpMemoryWindow::changeMode(HWND hwnd, Mode newMode) { char buffer[128]; selectedMode = newMode; SendMessage(GetDlgItem(hwnd,IDC_DUMP_USERMEMORY),BM_SETCHECK,selectedMode == MODE_RAM ? BST_CHECKED : BST_UNCHECKED,0); SendMessage(GetDlgItem(hwnd,IDC_DUMP_VRAM),BM_SETCHECK,selectedMode == MODE_VRAM ? BST_CHECKED : BST_UNCHECKED,0); SendMessage(GetDlgItem(hwnd,IDC_DUMP_SCRATCHPAD),BM_SETCHECK,selectedMode == MODE_SCRATCHPAD ? BST_CHECKED : BST_UNCHECKED,0); SendMessage(GetDlgItem(hwnd,IDC_DUMP_CUSTOMRANGE),BM_SETCHECK,selectedMode == MODE_CUSTOM ? BST_CHECKED : BST_UNCHECKED,0); if (selectedMode == MODE_CUSTOM) { EnableWindow(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),TRUE); EnableWindow(GetDlgItem(hwnd,IDC_DUMP_SIZE),TRUE); if (filenameChosen == false) SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_FILENAME),"Custom.dump"); } else { u32 start, size; const char* defaultFileName; switch (selectedMode) { case MODE_RAM: start = PSP_GetUserMemoryBase(); size = PSP_GetUserMemoryEnd()-start; defaultFileName = "RAM.dump"; break; case MODE_VRAM: start = PSP_GetVidMemBase(); size = PSP_GetVidMemEnd()-start; defaultFileName = "VRAM.dump"; break; case MODE_SCRATCHPAD: start = PSP_GetScratchpadMemoryBase(); size = PSP_GetScratchpadMemoryEnd()-start; defaultFileName = "Scratchpad.dump"; break; } sprintf(buffer,"0x%08X",start); SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),buffer); EnableWindow(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),FALSE); sprintf(buffer,"0x%08X",size); SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_SIZE),buffer); EnableWindow(GetDlgItem(hwnd,IDC_DUMP_SIZE),FALSE); if (filenameChosen == false) SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_FILENAME),defaultFileName); } }
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)); }
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 }
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; }