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 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 __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 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); } }
jint Java_com_ruin_psp_PSP_readRAMU32(JNIEnv *env, jclass clazz, jint address) { u32 start = PSP_GetUserMemoryBase() + (u32)address; u32 size = 32; auto memLock = Memory::Lock(); if (!PSP_IsInited()) return 0; if (!checkStart(start, size)) return 0; return (jint) Memory::Read_U32(start); }
static inline u32 SampleNearest(int level, unsigned int u, unsigned int v) { GETextureFormat texfmt = gstate.getTextureFormat(); u32 texaddr = (gstate.texaddr[level] & 0xFFFFF0) | ((gstate.texbufwidth[level] << 8) & 0x0F000000); u8* srcptr = (u8*)Memory::GetPointer(texaddr); // TODO: not sure if this is the right place to load from...? // Special rules for kernel textures (PPGe), TODO: Verify! int texbufwidth = (texaddr < PSP_GetUserMemoryBase()) ? gstate.texbufwidth[level] & 0x1FFF : gstate.texbufwidth[level] & 0x7FF; // TODO: Should probably check if textures are aligned properly... if (texfmt == GE_TFMT_4444) { srcptr += GetPixelDataOffset(16, texbufwidth*8, u, v); return DecodeRGBA4444(*(u16*)srcptr); } else if (texfmt == GE_TFMT_5551) { srcptr += GetPixelDataOffset(16, texbufwidth*8, u, v); return DecodeRGBA5551(*(u16*)srcptr); } else if (texfmt == GE_TFMT_5650) { srcptr += GetPixelDataOffset(16, texbufwidth*8, u, v); return DecodeRGB565(*(u16*)srcptr); } else if (texfmt == GE_TFMT_8888) { srcptr += GetPixelDataOffset(32, texbufwidth*8, u, v); return DecodeRGBA8888(*(u32*)srcptr); } else if (texfmt == GE_TFMT_CLUT32) { srcptr += GetPixelDataOffset(32, texbufwidth*8, u, v); u32 val = srcptr[0] + (srcptr[1] << 8) + (srcptr[2] << 16) + (srcptr[3] << 24); return LookupColor(GetClutIndex(val), level); } else if (texfmt == GE_TFMT_CLUT16) { srcptr += GetPixelDataOffset(16, texbufwidth*8, u, v); u16 val = srcptr[0] + (srcptr[1] << 8); return LookupColor(GetClutIndex(val), level); } else if (texfmt == GE_TFMT_CLUT8) { srcptr += GetPixelDataOffset(8, texbufwidth*8, u, v); u8 val = *srcptr; return LookupColor(GetClutIndex(val), level); } else if (texfmt == GE_TFMT_CLUT4) { srcptr += GetPixelDataOffset(4, texbufwidth*8, u, v); u8 val = (u & 1) ? (srcptr[0] >> 4) : (srcptr[0] & 0xF); return LookupColor(GetClutIndex(val), level); } else {
jfloat Java_com_ruin_psp_PSP_readRAMU32Float (JNIEnv *env, jclass clazz, jint address) { u32 start = PSP_GetUserMemoryBase() + (u32)address; u32 size = 32; auto memLock = Memory::Lock(); if (!PSP_IsInited()) return 0; if (!checkStart(start, size)) return 0; u32 dat = Memory::Read_U32(start); float f; memcpy(&f, &dat, sizeof(f)); return (jfloat) f; }
double ExecCPUTest() { int blockTicks = 1000000; int total = 0; double st = real_time_now(); do { for (int j = 0; j < 1000; ++j) { currentMIPS->pc = PSP_GetUserMemoryBase(); coreState = CORE_RUNNING; while (coreState == CORE_RUNNING) { mipsr4k.RunLoopUntil(blockTicks); } ++total; } } while (real_time_now() - st < 0.5); double elapsed = real_time_now() - st; return total / elapsed; }
jbyteArray Java_com_ruin_psp_PSP_readRam(JNIEnv *env, jclass clazz, jint address, jint size) { u32 start = PSP_GetUserMemoryBase() + (u32)address; auto memLock = Memory::Lock(); if (!PSP_IsInited()) return 0; if (!checkStart(start, size)) return 0; u8 *ptr = Memory::GetPointer(start); jbyte arr[size]; memcpy(&arr, ptr, sizeof(arr)); jbyteArray ret = env->NewByteArray(size); env->SetByteArrayRegion(ret, 0, size, arr); return ret; }
bool TestJit() { SetupJitHarness(); currentMIPS->pc = PSP_GetUserMemoryBase(); u32 *p = (u32 *)Memory::GetPointer(currentMIPS->pc); // TODO: Smarter way of seeding in the code sequence. static const char *lines[] = { //"vcrsp.t C000, C100, C200", //"vdot.q C000, C100, C200", //"vmmul.q M000, M100, M200", "lui r1, 0x8910", "vmmul.q M000, M100, M200", "sv.q C000, 0(r1)", "sv.q C000, 16(r1)", "sv.q C000, 32(r1)", "sv.q C000, 48(r1)", /* "abs.s f1, f1", "cvt.w.s f1, f1", "cvt.w.s f3, f1", "cvt.w.s f0, f2", "cvt.w.s f5, f1", "cvt.w.s f6, f5", */ }; bool compileSuccess = true; u32 addr = currentMIPS->pc; DebugInterface *dbg = currentDebugMIPS; for (int i = 0; i < 100; ++i) { /* // VFPU ops aren't supported by MIPSAsm yet. *p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8); *p++ = 0xD03C0000 | (1 << 7) | (1 << 15); *p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8); *p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8); *p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8); *p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8); *p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8); */ for (size_t j = 0; j < ARRAY_SIZE(lines); ++j) { p++; if (!MIPSAsm::MipsAssembleOpcode(lines[j], currentDebugMIPS, addr)) { printf("ERROR: %ls\n", MIPSAsm::GetAssembleError().c_str()); compileSuccess = false; } addr += 4; } } *p++ = MIPS_MAKE_SYSCALL("UnitTestFakeSyscalls", "UnitTestTerminator"); *p++ = MIPS_MAKE_BREAK(1); // Dogfood. addr = currentMIPS->pc; for (size_t j = 0; j < ARRAY_SIZE(lines); ++j) { char line[512]; MIPSDisAsm(Memory::Read_Instruction(addr), addr, line, true); addr += 4; printf("%s\n", line); } printf("\n"); double jit_speed = 0.0, interp_speed = 0.0; if (compileSuccess) { interp_speed = ExecCPUTest(); mipsr4k.UpdateCore(CPUCore::JIT); jit_speed = ExecCPUTest(); // Disassemble JitBlockCache *cache = MIPSComp::jit->GetBlockCache(); JitBlock *block = cache->GetBlock(0); // Should only be one block. #if defined(ARM) std::vector<std::string> lines = DisassembleArm2(block->normalEntry, block->codeSize); #elif defined(ARM64) std::vector<std::string> lines = DisassembleArm64(block->normalEntry, block->codeSize); #else std::vector<std::string> lines = DisassembleX86(block->normalEntry, block->codeSize); #endif // Cut off at 25 due to the repetition above. Might need tweaking for large instructions. const int cutoff = 25; for (int i = 0; i < std::min((int)lines.size(), cutoff); i++) { printf("%s\n", lines[i].c_str()); } if (lines.size() > cutoff) printf("...\n"); printf("Jit was %fx faster than interp.\n\n", jit_speed / interp_speed); } printf("\n"); DestroyJitHarness(); return jit_speed >= interp_speed; }