void CRegTable::SetValue(int row, int col, const wxString& strNewVal) { if (row < 32) { if (col == 1) { u32 new_val = 0; if (TryParseGPR(strNewVal, m_formatRegs[row], &new_val)) GPR(row) = new_val; } else if (col == 3) { unsigned long long new_val = 0; if (TryParseFPR(strNewVal, m_formatFRegs[row][0], &new_val)) riPS0(row) = new_val; } else if (col == 4) { unsigned long long new_val = 0; if (TryParseFPR(strNewVal, m_formatFRegs[row][1], &new_val)) riPS1(row) = new_val; } } else { if ((static_cast<size_t>(row - 32) < NUM_SPECIALS) && col == 1) { u32 new_val = 0; if (TryParse("0x" + WxStrToStr(strNewVal), &new_val)) SetSpecialRegValue(row - 32, new_val); } } }
wxString CRegTable::GetValue(int row, int col) { if (row < 32) { switch (col) { case 0: return StrToWxStr(GetGPRName(row)); case 1: return wxString::Format("%08x", GPR(row)); case 2: return StrToWxStr(GetFPRName(row)); case 3: return wxString::Format("%016llx", riPS0(row)); case 4: return wxString::Format("%016llx", riPS1(row)); default: return wxEmptyString; } } else { if (row - 32 < NUM_SPECIALS) { switch (col) { case 0: return StrToWxStr(special_reg_names[row - 32]); case 1: return wxString::Format("%08x", GetSpecialRegValue(row - 32)); default: return wxEmptyString; } } } return wxEmptyString; }
void CRegTable::UpdateCachedRegs() { for (int i = 0; i < 32; ++i) { m_CachedRegHasChanged[i] = (m_CachedRegs[i] != GPR(i)); m_CachedRegs[i] = GPR(i); m_CachedFRegHasChanged[i][0] = (m_CachedFRegs[i][0] != riPS0(i)); m_CachedFRegs[i][0] = riPS0(i); m_CachedFRegHasChanged[i][1] = (m_CachedFRegs[i][1] != riPS1(i)); m_CachedFRegs[i][1] = riPS1(i); } for (int i = 0; i < NUM_SPECIALS; ++i) { m_CachedSpecialRegHasChanged[i] = (m_CachedSpecialRegs[i] != GetSpecialRegValue(i)); m_CachedSpecialRegs[i] = GetSpecialRegValue(i); } }
void Interpreter::lfs(UGeckoInstruction _inst) { u32 uTemp = PowerPC::Read_U32(Helper_Get_EA(_inst)); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { u64 value = ConvertToDouble(uTemp); riPS0(_inst.FD) = value; riPS1(_inst.FD) = value; } }
wxString CRegTable::FormatFPR(int reg_index, int reg_part) { if (m_formatFRegs[reg_index][reg_part] == FormatSpecifier::Double) { double reg = (reg_part == 0) ? rPS0(reg_index) : rPS1(reg_index); return wxString::Format(GetFormatString(m_formatFRegs[reg_index][reg_part]), reg); } u64 reg = (reg_part == 0) ? riPS0(reg_index) : riPS1(reg_index); return wxString::Format(GetFormatString(m_formatFRegs[reg_index][reg_part]), reg); }
void Interpreter::lfsux(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_UX(_inst); u32 uTemp = PowerPC::Read_U32(uAddress); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { u64 value = ConvertToDouble(uTemp); riPS0(_inst.FD) = value; riPS1(_inst.FD) = value; rGPR[_inst.RA] = uAddress; } }
void RunCodeHandler() { if (!SConfig::GetInstance().bEnableCheats) return; // NOTE: Need to release the lock because of GUI deadlocks with PanicAlert in HostWrite_* { std::lock_guard<std::mutex> codes_lock(s_active_codes_lock); if (s_code_handler_installed != Installation::Installed) { // Don't spam retry if the install failed. The corrupt / missing disk file is not likely to be // fixed within 1 frame of the last error. if (s_active_codes.empty() || s_code_handler_installed == Installation::Failed) return; s_code_handler_installed = InstallCodeHandlerLocked(); // A warning was already issued for the install failing if (s_code_handler_installed != Installation::Installed) return; } } // We always do this to avoid problems with the stack since we're branching in random locations. // Even with function call return hooks (PC == LR), hand coded assembler won't necessarily // follow the ABI. [Volatile FPR, GPR, CR may not be volatile] // The codehandler will STMW all of the GPR registers, but we need to fix the Stack's Red // Zone, the LR, PC (return address) and the volatile floating point registers. // Build a function call stack frame. u32 SFP = GPR(1); // Stack Frame Pointer GPR(1) -= 256; // Stack's Red Zone GPR(1) -= 16 + 2 * 14 * sizeof(u64); // Our stack frame (HLE_Misc::GeckoReturnTrampoline) GPR(1) -= 8; // Fake stack frame for codehandler GPR(1) &= 0xFFFFFFF0; // Align stack to 16bytes u32 SP = GPR(1); // Stack Pointer PowerPC::HostWrite_U32(SP + 8, SP); // SP + 4 is reserved for the codehandler to save LR to the stack. PowerPC::HostWrite_U32(SFP, SP + 8); // Real stack frame PowerPC::HostWrite_U32(PC, SP + 12); PowerPC::HostWrite_U32(LR, SP + 16); PowerPC::HostWrite_U32(PowerPC::CompactCR(), SP + 20); // Registers FPR0->13 are volatile for (int i = 0; i < 14; ++i) { PowerPC::HostWrite_U64(riPS0(i), SP + 24 + 2 * i * sizeof(u64)); PowerPC::HostWrite_U64(riPS1(i), SP + 24 + (2 * i + 1) * sizeof(u64)); } DEBUG_LOG(ACTIONREPLAY, "GeckoCodes: Initiating phantom branch-and-link. " "PC = 0x%08X, SP = 0x%08X, SFP = 0x%08X", PC, SP, SFP); LR = HLE_TRAMPOLINE_ADDRESS; PC = NPC = ENTRY_POINT; }
void CRegTable::SetValue(int row, int col, const wxString& strNewVal) { u32 newVal = 0; if (TryParse(std::string(strNewVal.mb_str()), &newVal)) { if (row < 32) { if (col == 1) GPR(row) = newVal; else if (col == 3) riPS0(row) = newVal; else if (col == 4) riPS1(row) = newVal; } else { if ((row - 32 < NUM_SPECIALS) && (col == 1)) { SetSpecialRegValue(row - 32, newVal); } } } }
void Interpreter::lfsx(UGeckoInstruction inst) { const u32 address = Helper_Get_EA_X(inst); if ((address & 0b11) != 0) { GenerateAlignmentException(address); return; } const u32 temp = PowerPC::Read_U32(address); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { const u64 value = ConvertToDouble(temp); riPS0(inst.FD) = value; riPS1(inst.FD) = value; } }
static wxString GetValueByRowCol(int row, int col) { if (row < 32) { switch (col) { case 0: return StrToWxStr(GekkoDisassembler::GetGPRName(row)); case 1: return wxString::Format("%08x", GPR(row)); case 2: return StrToWxStr(GekkoDisassembler::GetFPRName(row)); case 3: return wxString::Format("%016llx", riPS0(row)); case 4: return wxString::Format("%016llx", riPS1(row)); case 5: { if (row < 4) return wxString::Format("DBAT%01d", row); if (row < 8) return wxString::Format("IBAT%01d", row - 4); if (row < 12) return wxString::Format("DBAT%01d", row - 4); if (row < 16) return wxString::Format("IBAT%01d", row - 8); break; } case 6: { if (row < 4) return wxString::Format("%016llx", (u64)PowerPC::ppcState.spr[SPR_DBAT0U + row * 2] << 32 | PowerPC::ppcState.spr[SPR_DBAT0L + row * 2]); if (row < 8) return wxString::Format("%016llx", (u64)PowerPC::ppcState.spr[SPR_IBAT0U + (row - 4) * 2] << 32 | PowerPC::ppcState.spr[SPR_IBAT0L + (row - 4) * 2]); if (row < 12) return wxString::Format("%016llx", (u64)PowerPC::ppcState.spr[SPR_DBAT4U + (row - 12) * 2] << 32 | PowerPC::ppcState.spr[SPR_DBAT4L + (row - 12) * 2]); if (row < 16) return wxString::Format("%016llx", (u64)PowerPC::ppcState.spr[SPR_IBAT4U + (row - 16) * 2] << 32 | PowerPC::ppcState.spr[SPR_IBAT4L + (row - 16) * 2]); break; } case 7: { if (row < 16) return wxString::Format("SR%02d", row); break; } case 8: { if (row < 16) return wxString::Format("%08x", PowerPC::ppcState.sr[row]); break; } default: return wxEmptyString; } } else { if (row - 32 < NUM_SPECIALS) { switch (col) { case 0: return StrToWxStr(special_reg_names[row - 32]); case 1: return wxString::Format("%08x", GetSpecialRegValue(row - 32)); default: return wxEmptyString; } } } return wxEmptyString; }
void RegisterWidget::PopulateTable() { for (int i = 0; i < 32; i++) { // General purpose registers (int) AddRegister(i, 0, RegisterType::gpr, "r" + std::to_string(i), [i] { return GPR(i); }, [i](u64 value) { GPR(i) = value; }); // Floating point registers (double) AddRegister(i, 2, RegisterType::fpr, "f" + std::to_string(i), [i] { return riPS0(i); }, [i](u64 value) { riPS0(i) = value; }); AddRegister(i, 4, RegisterType::fpr, "", [i] { return riPS1(i); }, [i](u64 value) { riPS1(i) = value; }); } for (int i = 0; i < 8; i++) { // IBAT registers AddRegister(i, 5, RegisterType::ibat, "IBAT" + std::to_string(i), [i] { return (static_cast<u64>(PowerPC::ppcState.spr[SPR_IBAT0U + i * 2]) << 32) + PowerPC::ppcState.spr[SPR_IBAT0L + i * 2]; }, nullptr); // DBAT registers AddRegister(i + 8, 5, RegisterType::dbat, "DBAT" + std::to_string(i), [i] { return (static_cast<u64>(PowerPC::ppcState.spr[SPR_DBAT0U + i * 2]) << 32) + PowerPC::ppcState.spr[SPR_DBAT0L + i * 2]; }, nullptr); // Graphics quantization registers AddRegister(i + 16, 7, RegisterType::gqr, "GQR" + std::to_string(i), [i] { return PowerPC::ppcState.spr[SPR_GQR0 + i]; }, nullptr); } for (int i = 0; i < 16; i++) { // SR registers AddRegister(i, 7, RegisterType::sr, "SR" + std::to_string(i), [i] { return PowerPC::ppcState.sr[i]; }, [i](u64 value) { PowerPC::ppcState.sr[i] = value; }); } // Special registers // TB AddRegister(16, 5, RegisterType::tb, "TB", [] { return static_cast<u64>(PowerPC::ppcState.spr[SPR_TU]) << 32 | PowerPC::ppcState.spr[SPR_TL]; }, nullptr); // PC AddRegister(17, 5, RegisterType::pc, "PC", [] { return PowerPC::ppcState.pc; }, [](u64 value) { PowerPC::ppcState.pc = value; }); // LR AddRegister(18, 5, RegisterType::lr, "LR", [] { return PowerPC::ppcState.spr[SPR_LR]; }, [](u64 value) { PowerPC::ppcState.spr[SPR_LR] = value; }); // CTR AddRegister(19, 5, RegisterType::ctr, "CTR", [] { return PowerPC::ppcState.spr[SPR_CTR]; }, [](u64 value) { PowerPC::ppcState.spr[SPR_CTR] = value; }); // CR AddRegister(20, 5, RegisterType::cr, "CR", [] { return GetCR(); }, [](u64 value) { SetCR(value); }); // XER AddRegister(21, 5, RegisterType::xer, "XER", [] { return GetXER().Hex; }, [](u64 value) { SetXER(UReg_XER(value)); }); // FPSCR AddRegister(22, 5, RegisterType::fpscr, "FPSCR", [] { return PowerPC::ppcState.fpscr; }, [](u64 value) { PowerPC::ppcState.fpscr = value; }); // MSR AddRegister(23, 5, RegisterType::msr, "MSR", [] { return PowerPC::ppcState.msr; }, [](u64 value) { PowerPC::ppcState.msr = value; }); // SRR 0-1 AddRegister(24, 5, RegisterType::srr, "SRR0", [] { return PowerPC::ppcState.spr[SPR_SRR0]; }, [](u64 value) { PowerPC::ppcState.spr[SPR_SRR0] = value; }); AddRegister(25, 5, RegisterType::srr, "SRR1", [] { return PowerPC::ppcState.spr[SPR_SRR1]; }, [](u64 value) { PowerPC::ppcState.spr[SPR_SRR1] = value; }); // Exceptions AddRegister(26, 5, RegisterType::exceptions, "Exceptions", [] { return PowerPC::ppcState.Exceptions; }, [](u64 value) { PowerPC::ppcState.Exceptions = value; }); // Int Mask AddRegister(27, 5, RegisterType::int_mask, "Int Mask", [] { return ProcessorInterface::GetMask(); }, nullptr); // Int Cause AddRegister(28, 5, RegisterType::int_cause, "Int Cause", [] { return ProcessorInterface::GetCause(); }, nullptr); // DSISR AddRegister(29, 5, RegisterType::dsisr, "DSISR", [] { return PowerPC::ppcState.spr[SPR_DSISR]; }, [](u64 value) { PowerPC::ppcState.spr[SPR_DSISR] = value; }); // DAR AddRegister(30, 5, RegisterType::dar, "DAR", [] { return PowerPC::ppcState.spr[SPR_DAR]; }, [](u64 value) { PowerPC::ppcState.spr[SPR_DAR] = value; }); // Hash Mask AddRegister( 31, 5, RegisterType::pt_hashmask, "Hash Mask", [] { return (PowerPC::ppcState.pagetable_hashmask << 6) | PowerPC::ppcState.pagetable_base; }, nullptr); emit RequestTableUpdate(); m_table->resizeColumnsToContents(); }