From 209827b67c45f5718b236f9a7b69c04abf7f2d97 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Thu, 18 Feb 2021 01:45:32 +1000 Subject: [PATCH] PGXP: Compute PSX values on demand for CPU instructions Generates shorter code for the recompiler. --- src/core/cpu_core.cpp | 46 ++++---- src/core/cpu_recompiler_code_generator.cpp | 123 ++++++++++----------- src/core/pgxp.cpp | 81 +++++++++----- src/core/pgxp.h | 40 +++---- 4 files changed, 151 insertions(+), 139 deletions(-) diff --git a/src/core/cpu_core.cpp b/src/core/cpu_core.cpp index c67e7191a..890c1f282 100644 --- a/src/core/cpu_core.cpp +++ b/src/core/cpu_core.cpp @@ -585,7 +585,7 @@ restart_instruction: { const u32 new_value = ReadReg(inst.r.rt) << inst.r.shamt; if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_SLL(inst.bits, new_value, ReadReg(inst.r.rt)); + PGXP::CPU_SLL(inst.bits, ReadReg(inst.r.rt)); WriteReg(inst.r.rd, new_value); } @@ -595,7 +595,7 @@ restart_instruction: { const u32 new_value = ReadReg(inst.r.rt) >> inst.r.shamt; if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_SRL(inst.bits, new_value, ReadReg(inst.r.rt)); + PGXP::CPU_SRL(inst.bits, ReadReg(inst.r.rt)); WriteReg(inst.r.rd, new_value); } @@ -605,7 +605,7 @@ restart_instruction: { const u32 new_value = static_cast(static_cast(ReadReg(inst.r.rt)) >> inst.r.shamt); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_SRA(inst.bits, new_value, ReadReg(inst.r.rt)); + PGXP::CPU_SRA(inst.bits, ReadReg(inst.r.rt)); WriteReg(inst.r.rd, new_value); } @@ -616,7 +616,7 @@ restart_instruction: const u32 shift_amount = ReadReg(inst.r.rs) & UINT32_C(0x1F); const u32 new_value = ReadReg(inst.r.rt) << shift_amount; if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_SLLV(inst.bits, new_value, ReadReg(inst.r.rt), shift_amount); + PGXP::CPU_SLLV(inst.bits, ReadReg(inst.r.rt), shift_amount); WriteReg(inst.r.rd, new_value); } @@ -627,7 +627,7 @@ restart_instruction: const u32 shift_amount = ReadReg(inst.r.rs) & UINT32_C(0x1F); const u32 new_value = ReadReg(inst.r.rt) >> shift_amount; if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_SRLV(inst.bits, new_value, ReadReg(inst.r.rt), shift_amount); + PGXP::CPU_SRLV(inst.bits, ReadReg(inst.r.rt), shift_amount); WriteReg(inst.r.rd, new_value); } @@ -638,7 +638,7 @@ restart_instruction: const u32 shift_amount = ReadReg(inst.r.rs) & UINT32_C(0x1F); const u32 new_value = static_cast(static_cast(ReadReg(inst.r.rt)) >> shift_amount); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_SRAV(inst.bits, new_value, ReadReg(inst.r.rt), shift_amount); + PGXP::CPU_SRAV(inst.bits, ReadReg(inst.r.rt), shift_amount); WriteReg(inst.r.rd, new_value); } @@ -648,7 +648,7 @@ restart_instruction: { const u32 new_value = ReadReg(inst.r.rs) & ReadReg(inst.r.rt); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_AND_(inst.bits, new_value, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); + PGXP::CPU_AND_(inst.bits, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); WriteReg(inst.r.rd, new_value); } @@ -658,7 +658,7 @@ restart_instruction: { const u32 new_value = ReadReg(inst.r.rs) | ReadReg(inst.r.rt); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_OR_(inst.bits, new_value, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); + PGXP::CPU_OR_(inst.bits, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); WriteReg(inst.r.rd, new_value); } @@ -668,7 +668,7 @@ restart_instruction: { const u32 new_value = ReadReg(inst.r.rs) ^ ReadReg(inst.r.rt); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_XOR_(inst.bits, new_value, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); + PGXP::CPU_XOR_(inst.bits, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); WriteReg(inst.r.rd, new_value); } @@ -678,7 +678,7 @@ restart_instruction: { const u32 new_value = ~(ReadReg(inst.r.rs) | ReadReg(inst.r.rt)); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_NOR(inst.bits, new_value, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); + PGXP::CPU_NOR(inst.bits, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); WriteReg(inst.r.rd, new_value); } @@ -696,7 +696,7 @@ restart_instruction: } if constexpr (pgxp_mode == PGXPMode::CPU) - PGXP::CPU_ADD(inst.bits, new_value, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); + PGXP::CPU_ADD(inst.bits, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); else if constexpr (pgxp_mode >= PGXPMode::Memory) { if (add_value == 0) @@ -716,7 +716,7 @@ restart_instruction: const u32 add_value = ReadReg(inst.r.rt); const u32 new_value = old_value + add_value; if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_ADD(inst.bits, new_value, old_value, add_value); + PGXP::CPU_ADD(inst.bits, old_value, add_value); else if constexpr (pgxp_mode >= PGXPMode::Memory) { if (add_value == 0) @@ -742,7 +742,7 @@ restart_instruction: } if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_SUB(inst.bits, new_value, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); + PGXP::CPU_SUB(inst.bits, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); WriteReg(inst.r.rd, new_value); } @@ -752,7 +752,7 @@ restart_instruction: { const u32 new_value = ReadReg(inst.r.rs) - ReadReg(inst.r.rt); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_SUB(inst.bits, new_value, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); + PGXP::CPU_SUB(inst.bits, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); WriteReg(inst.r.rd, new_value); } @@ -762,7 +762,7 @@ restart_instruction: { const u32 result = BoolToUInt32(static_cast(ReadReg(inst.r.rs)) < static_cast(ReadReg(inst.r.rt))); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_SLT(inst.bits, result, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); + PGXP::CPU_SLT(inst.bits, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); WriteReg(inst.r.rd, result); } @@ -772,7 +772,7 @@ restart_instruction: { const u32 result = BoolToUInt32(ReadReg(inst.r.rs) < ReadReg(inst.r.rt)); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_SLTU(inst.bits, result, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); + PGXP::CPU_SLTU(inst.bits, ReadReg(inst.r.rs), ReadReg(inst.r.rt)); WriteReg(inst.r.rd, result); } @@ -948,7 +948,7 @@ restart_instruction: const u32 new_value = ReadReg(inst.i.rs) & inst.i.imm_zext32(); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_ANDI(inst.bits, new_value, ReadReg(inst.i.rs)); + PGXP::CPU_ANDI(inst.bits, ReadReg(inst.i.rs)); WriteReg(inst.i.rt, new_value); } @@ -959,7 +959,7 @@ restart_instruction: const u32 new_value = ReadReg(inst.i.rs) | inst.i.imm_zext32(); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_ORI(inst.bits, new_value, ReadReg(inst.i.rs)); + PGXP::CPU_ORI(inst.bits, ReadReg(inst.i.rs)); WriteReg(inst.i.rt, new_value); } @@ -970,7 +970,7 @@ restart_instruction: const u32 new_value = ReadReg(inst.i.rs) ^ inst.i.imm_zext32(); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_XORI(inst.bits, new_value, ReadReg(inst.i.rs)); + PGXP::CPU_XORI(inst.bits, ReadReg(inst.i.rs)); WriteReg(inst.i.rt, new_value); } @@ -988,7 +988,7 @@ restart_instruction: } if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_ADDI(inst.bits, new_value, ReadReg(inst.i.rs)); + PGXP::CPU_ADDI(inst.bits, ReadReg(inst.i.rs)); else if constexpr (pgxp_mode >= PGXPMode::Memory) { if (add_value == 0) @@ -1009,7 +1009,7 @@ restart_instruction: const u32 new_value = old_value + add_value; if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_ADDI(inst.bits, new_value, ReadReg(inst.i.rs)); + PGXP::CPU_ADDI(inst.bits, ReadReg(inst.i.rs)); else if constexpr (pgxp_mode >= PGXPMode::Memory) { if (add_value == 0) @@ -1028,7 +1028,7 @@ restart_instruction: const u32 result = BoolToUInt32(static_cast(ReadReg(inst.i.rs)) < static_cast(inst.i.imm_sext32())); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_SLTI(inst.bits, result, ReadReg(inst.i.rs)); + PGXP::CPU_SLTI(inst.bits, ReadReg(inst.i.rs)); WriteReg(inst.i.rt, result); } @@ -1039,7 +1039,7 @@ restart_instruction: const u32 result = BoolToUInt32(ReadReg(inst.i.rs) < inst.i.imm_sext32()); if constexpr (pgxp_mode >= PGXPMode::CPU) - PGXP::CPU_SLTIU(inst.bits, result, ReadReg(inst.i.rs)); + PGXP::CPU_SLTIU(inst.bits, ReadReg(inst.i.rs)); WriteReg(inst.i.rt, result); } diff --git a/src/core/cpu_recompiler_code_generator.cpp b/src/core/cpu_recompiler_code_generator.cpp index 12a2eed94..b569cd52e 100644 --- a/src/core/cpu_recompiler_code_generator.cpp +++ b/src/core/cpu_recompiler_code_generator.cpp @@ -1137,34 +1137,34 @@ bool CodeGenerator::Compile_Bitwise(const CodeBlockInstruction& cbi) { case InstructionOp::ori: { + if (g_settings.UsingPGXPCPUMode()) + EmitFunctionCall(nullptr, &PGXP::CPU_ORI, Value::FromConstantU32(cbi.instruction.bits), lhs); + result = OrValues(lhs, rhs); if (spec_lhs && spec_rhs) spec_value = *spec_lhs | *spec_rhs; - - if (g_settings.UsingPGXPCPUMode()) - EmitFunctionCall(nullptr, &PGXP::CPU_ORI, Value::FromConstantU32(cbi.instruction.bits), result, lhs); } break; case InstructionOp::andi: { + if (g_settings.UsingPGXPCPUMode()) + EmitFunctionCall(nullptr, &PGXP::CPU_ANDI, Value::FromConstantU32(cbi.instruction.bits), lhs); + result = AndValues(lhs, rhs); if (spec_lhs && spec_rhs) spec_value = *spec_lhs & *spec_rhs; - - if (g_settings.UsingPGXPCPUMode()) - EmitFunctionCall(nullptr, &PGXP::CPU_ANDI, Value::FromConstantU32(cbi.instruction.bits), result, lhs); } break; case InstructionOp::xori: { + if (g_settings.UsingPGXPCPUMode()) + EmitFunctionCall(nullptr, &PGXP::CPU_XORI, Value::FromConstantU32(cbi.instruction.bits), lhs); + result = XorValues(lhs, rhs); if (spec_lhs && spec_rhs) spec_value = *spec_lhs ^ *spec_rhs; - - if (g_settings.UsingPGXPCPUMode()) - EmitFunctionCall(nullptr, &PGXP::CPU_XORI, Value::FromConstantU32(cbi.instruction.bits), result, lhs); } break; @@ -1174,45 +1174,45 @@ bool CodeGenerator::Compile_Bitwise(const CodeBlockInstruction& cbi) { case InstructionFunct::or_: { + if (g_settings.UsingPGXPCPUMode()) + EmitFunctionCall(nullptr, &PGXP::CPU_OR_, Value::FromConstantU32(cbi.instruction.bits), lhs, rhs); + result = OrValues(lhs, rhs); if (spec_lhs && spec_rhs) spec_value = *spec_lhs | *spec_rhs; - - if (g_settings.UsingPGXPCPUMode()) - EmitFunctionCall(nullptr, &PGXP::CPU_OR_, Value::FromConstantU32(cbi.instruction.bits), result, lhs, rhs); } break; case InstructionFunct::and_: { + if (g_settings.UsingPGXPCPUMode()) + EmitFunctionCall(nullptr, &PGXP::CPU_AND_, Value::FromConstantU32(cbi.instruction.bits), lhs, rhs); + result = AndValues(lhs, rhs); if (spec_lhs && spec_rhs) spec_value = *spec_lhs & *spec_rhs; - - if (g_settings.UsingPGXPCPUMode()) - EmitFunctionCall(nullptr, &PGXP::CPU_AND_, Value::FromConstantU32(cbi.instruction.bits), result, lhs, rhs); } break; case InstructionFunct::xor_: { + if (g_settings.UsingPGXPCPUMode()) + EmitFunctionCall(nullptr, &PGXP::CPU_XOR_, Value::FromConstantU32(cbi.instruction.bits), lhs, rhs); + result = XorValues(lhs, rhs); if (spec_lhs && spec_rhs) spec_value = *spec_lhs ^ *spec_rhs; - - if (g_settings.UsingPGXPCPUMode()) - EmitFunctionCall(nullptr, &PGXP::CPU_XOR_, Value::FromConstantU32(cbi.instruction.bits), result, lhs, rhs); } break; case InstructionFunct::nor: { + if (g_settings.UsingPGXPCPUMode()) + EmitFunctionCall(nullptr, &PGXP::CPU_NOR, Value::FromConstantU32(cbi.instruction.bits), lhs, rhs); + result = NotValue(OrValues(lhs, rhs)); if (spec_lhs && spec_rhs) spec_value = ~(*spec_lhs | *spec_rhs); - - if (g_settings.UsingPGXPCPUMode()) - EmitFunctionCall(nullptr, &PGXP::CPU_NOR, Value::FromConstantU32(cbi.instruction.bits), result, lhs, rhs); } break; @@ -1264,51 +1264,51 @@ bool CodeGenerator::Compile_Shift(const CodeBlockInstruction& cbi) case InstructionFunct::sll: case InstructionFunct::sllv: { - result = ShlValues(rt, shamt, false); - if (rt_spec && shamt_spec) - result_spec = *rt_spec << *shamt_spec; - if (g_settings.UsingPGXPCPUMode()) { if (cbi.instruction.r.funct == InstructionFunct::sll) - EmitFunctionCall(nullptr, &PGXP::CPU_SLL, Value::FromConstantU32(cbi.instruction.bits), result, rt); + EmitFunctionCall(nullptr, &PGXP::CPU_SLL, Value::FromConstantU32(cbi.instruction.bits), rt); else // if (cbi.instruction.r.funct == InstructionFunct::sllv) - EmitFunctionCall(nullptr, &PGXP::CPU_SLLV, Value::FromConstantU32(cbi.instruction.bits), result, rt, shamt); + EmitFunctionCall(nullptr, &PGXP::CPU_SLLV, Value::FromConstantU32(cbi.instruction.bits), rt, shamt); } + + result = ShlValues(rt, shamt, false); + if (rt_spec && shamt_spec) + result_spec = *rt_spec << *shamt_spec; } break; case InstructionFunct::srl: case InstructionFunct::srlv: { - result = ShrValues(rt, shamt, false); - if (rt_spec && shamt_spec) - result_spec = *rt_spec >> *shamt_spec; - if (g_settings.UsingPGXPCPUMode()) { if (cbi.instruction.r.funct == InstructionFunct::srl) - EmitFunctionCall(nullptr, &PGXP::CPU_SRL, Value::FromConstantU32(cbi.instruction.bits), result, rt); + EmitFunctionCall(nullptr, &PGXP::CPU_SRL, Value::FromConstantU32(cbi.instruction.bits), rt); else // if (cbi.instruction.r.funct == InstructionFunct::srlv) - EmitFunctionCall(nullptr, &PGXP::CPU_SRLV, Value::FromConstantU32(cbi.instruction.bits), result, rt, shamt); + EmitFunctionCall(nullptr, &PGXP::CPU_SRLV, Value::FromConstantU32(cbi.instruction.bits), rt, shamt); } + + result = ShrValues(rt, shamt, false); + if (rt_spec && shamt_spec) + result_spec = *rt_spec >> *shamt_spec; } break; case InstructionFunct::sra: case InstructionFunct::srav: { - result = SarValues(rt, shamt, false); - if (rt_spec && shamt_spec) - result_spec = static_cast(static_cast(*rt_spec) << *shamt_spec); - if (g_settings.UsingPGXPCPUMode()) { if (cbi.instruction.r.funct == InstructionFunct::sra) - EmitFunctionCall(nullptr, &PGXP::CPU_SRA, Value::FromConstantU32(cbi.instruction.bits), result, rt); + EmitFunctionCall(nullptr, &PGXP::CPU_SRA, Value::FromConstantU32(cbi.instruction.bits), rt); else // if (cbi.instruction.r.funct == InstructionFunct::srav) - EmitFunctionCall(nullptr, &PGXP::CPU_SRAV, Value::FromConstantU32(cbi.instruction.bits), result, rt, shamt); + EmitFunctionCall(nullptr, &PGXP::CPU_SRAV, Value::FromConstantU32(cbi.instruction.bits), rt, shamt); } + + result = SarValues(rt, shamt, false); + if (rt_spec && shamt_spec) + result_spec = static_cast(static_cast(*rt_spec) << *shamt_spec); } break; @@ -1721,32 +1721,23 @@ bool CodeGenerator::Compile_Add(const CodeBlockInstruction& cbi) } // detect register moves and handle them for pgxp - bool do_pgxp_cpu = g_settings.UsingPGXPCPUMode(); if (g_settings.gpu_pgxp_enable && rhs.HasConstantValue(0)) { EmitFunctionCall(nullptr, &PGXP::CPU_MOVE, Value::FromConstantU32((static_cast(dest) << 8) | (static_cast(lhs_src))), lhs); - do_pgxp_cpu = false; + } + else if (g_settings.UsingPGXPCPUMode()) + { + if (cbi.instruction.op != InstructionOp::funct) + EmitFunctionCall(nullptr, &PGXP::CPU_ADDI, Value::FromConstantU32(cbi.instruction.bits), lhs); + else + EmitFunctionCall(nullptr, &PGXP::CPU_ADD, Value::FromConstantU32(cbi.instruction.bits), lhs, rhs); } Value result = AddValues(lhs, rhs, check_overflow); if (check_overflow) GenerateExceptionExit(cbi, Exception::Ov, Condition::Overflow); - if (do_pgxp_cpu) - { - if (cbi.instruction.op != InstructionOp::funct) - { - // addiu/addiu - EmitFunctionCall(nullptr, &PGXP::CPU_ADDI, Value::FromConstantU32(cbi.instruction.bits), result, lhs); - } - else - { - // add/addu - EmitFunctionCall(nullptr, &PGXP::CPU_ADD, Value::FromConstantU32(cbi.instruction.bits), result, lhs, rhs); - } - } - m_register_cache.WriteGuestRegister(dest, std::move(result)); SpeculativeValue value_spec; @@ -1771,13 +1762,13 @@ bool CodeGenerator::Compile_Subtract(const CodeBlockInstruction& cbi) SpeculativeValue lhs_spec = SpeculativeReadReg(cbi.instruction.r.rs); SpeculativeValue rhs_spec = SpeculativeReadReg(cbi.instruction.r.rt); + if (g_settings.UsingPGXPCPUMode()) + EmitFunctionCall(nullptr, &PGXP::CPU_SUB, Value::FromConstantU32(cbi.instruction.bits), lhs, rhs); + Value result = SubValues(lhs, rhs, check_overflow); if (check_overflow) GenerateExceptionExit(cbi, Exception::Ov, Condition::Overflow); - if (g_settings.UsingPGXPCPUMode()) - EmitFunctionCall(nullptr, &PGXP::CPU_SUB, Value::FromConstantU32(cbi.instruction.bits), result, lhs, rhs); - m_register_cache.WriteGuestRegister(cbi.instruction.r.rd, std::move(result)); SpeculativeValue value_spec; @@ -2037,22 +2028,22 @@ bool CodeGenerator::Compile_SetLess(const CodeBlockInstruction& cbi) m_register_cache.InvalidateGuestRegister(dest); } - Value result = m_register_cache.AllocateScratch(RegSize_32); - EmitCmp(lhs.host_reg, rhs); - EmitSetConditionResult(result.host_reg, result.size, signed_comparison ? Condition::Less : Condition::Below); - if (g_settings.UsingPGXPCPUMode()) { if (cbi.instruction.op == InstructionOp::slti) - EmitFunctionCall(nullptr, &PGXP::CPU_SLTI, Value::FromConstantU32(cbi.instruction.bits), result, lhs); + EmitFunctionCall(nullptr, &PGXP::CPU_SLTI, Value::FromConstantU32(cbi.instruction.bits), lhs); else if (cbi.instruction.op == InstructionOp::sltiu) - EmitFunctionCall(nullptr, &PGXP::CPU_SLTIU, Value::FromConstantU32(cbi.instruction.bits), result, lhs); + EmitFunctionCall(nullptr, &PGXP::CPU_SLTIU, Value::FromConstantU32(cbi.instruction.bits), lhs); else if (cbi.instruction.r.funct == InstructionFunct::slt) - EmitFunctionCall(nullptr, &PGXP::CPU_SLT, Value::FromConstantU32(cbi.instruction.bits), result, lhs, rhs); + EmitFunctionCall(nullptr, &PGXP::CPU_SLT, Value::FromConstantU32(cbi.instruction.bits), lhs, rhs); else // if (cbi.instruction.r.funct == InstructionFunct::sltu) - EmitFunctionCall(nullptr, &PGXP::CPU_SLTU, Value::FromConstantU32(cbi.instruction.bits), result, lhs, rhs); + EmitFunctionCall(nullptr, &PGXP::CPU_SLTU, Value::FromConstantU32(cbi.instruction.bits), lhs, rhs); } + Value result = m_register_cache.AllocateScratch(RegSize_32); + EmitCmp(lhs.host_reg, rhs); + EmitSetConditionResult(result.host_reg, result.size, signed_comparison ? Condition::Less : Condition::Below); + m_register_cache.WriteGuestRegister(dest, std::move(result)); SpeculativeValue value_spec; diff --git a/src/core/pgxp.cpp b/src/core/pgxp.cpp index 02df16c9c..a86a6a942 100644 --- a/src/core/pgxp.cpp +++ b/src/core/pgxp.cpp @@ -784,6 +784,8 @@ bool GetPreciseVertex(u32 addr, u32 value, int x, int y, int xOffs, int yOffs, f #define rt(_instr) ((_instr >> 16) & 0x1F) // The rt part of the instruction register #define rs(_instr) ((_instr >> 21) & 0x1F) // The rs part of the instruction register #define imm(_instr) (_instr & 0xFFFF) // The immediate part of the instruction register +#define imm_sext(_instr) \ + static_cast(static_cast(_instr & 0xFFFF)) // The immediate part of the instruction register void PGXP_InitCPU() { @@ -884,7 +886,7 @@ void CPU_MOVE(u32 rd_and_rs, u32 rsVal) CPU_reg[(rd_and_rs >> 8)] = CPU_reg[Rs]; } -void CPU_ADDI(u32 instr, u32 rtVal, u32 rsVal) +void CPU_ADDI(u32 instr, u32 rsVal) { // Rt = Rs + Imm (signed) psx_value tempImm; @@ -911,12 +913,13 @@ void CPU_ADDI(u32 instr, u32 rtVal, u32 rsVal) } CPU_reg[rt(instr)] = ret; - CPU_reg[rt(instr)].value = rtVal; + CPU_reg[rt(instr)].value = rsVal + imm_sext(instr); } -void CPU_ANDI(u32 instr, u32 rtVal, u32 rsVal) +void CPU_ANDI(u32 instr, u32 rsVal) { // Rt = Rs & Imm + const u32 rtVal = rsVal & imm(instr); psx_value vRt; PGXP_value ret; @@ -948,9 +951,10 @@ void CPU_ANDI(u32 instr, u32 rtVal, u32 rsVal) CPU_reg[rt(instr)].value = rtVal; } -void CPU_ORI(u32 instr, u32 rtVal, u32 rsVal) +void CPU_ORI(u32 instr, u32 rsVal) { // Rt = Rs | Imm + const u32 rtVal = rsVal | imm(instr); psx_value vRt; PGXP_value ret; @@ -974,9 +978,10 @@ void CPU_ORI(u32 instr, u32 rtVal, u32 rsVal) CPU_reg[rt(instr)] = ret; } -void CPU_XORI(u32 instr, u32 rtVal, u32 rsVal) +void CPU_XORI(u32 instr, u32 rsVal) { // Rt = Rs ^ Imm + const u32 rtVal = rsVal ^ imm(instr); psx_value vRt; PGXP_value ret; @@ -1000,7 +1005,7 @@ void CPU_XORI(u32 instr, u32 rtVal, u32 rsVal) CPU_reg[rt(instr)] = ret; } -void CPU_SLTI(u32 instr, u32 rtVal, u32 rsVal) +void CPU_SLTI(u32 instr, u32 rsVal) { // Rt = Rs < Imm (signed) psx_value tempImm; @@ -1013,12 +1018,12 @@ void CPU_SLTI(u32 instr, u32 rtVal, u32 rsVal) ret.y = 0.f; ret.x = (CPU_reg[rs(instr)].x < tempImm.sw.h) ? 1.f : 0.f; ret.flags |= VALID_1; - ret.value = rtVal; + ret.value = BoolToUInt32(static_cast(rsVal) < imm_sext(instr)); CPU_reg[rt(instr)] = ret; } -void CPU_SLTIU(u32 instr, u32 rtVal, u32 rsVal) +void CPU_SLTIU(u32 instr, u32 rsVal) { // Rt = Rs < Imm (Unsigned) psx_value tempImm; @@ -1031,7 +1036,7 @@ void CPU_SLTIU(u32 instr, u32 rtVal, u32 rsVal) ret.y = 0.f; ret.x = (f16Unsign(CPU_reg[rs(instr)].x) < tempImm.w.h) ? 1.f : 0.f; ret.flags |= VALID_1; - ret.value = rtVal; + ret.value = BoolToUInt32(rsVal < imm(instr)); CPU_reg[rt(instr)] = ret; } @@ -1053,7 +1058,7 @@ void CPU_LUI(u32 instr) // Register Arithmetic //////////////////////////////////// -void CPU_ADD(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +void CPU_ADD(u32 instr, u32 rsVal, u32 rtVal) { // Rd = Rs + Rt (signed) PGXP_value ret; @@ -1095,12 +1100,12 @@ void CPU_ADD(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) ret = CPU_reg[rs(instr)]; } - ret.value = rdVal; + ret.value = rsVal + rtVal; CPU_reg[rd(instr)] = ret; } -void CPU_SUB(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +void CPU_SUB(u32 instr, u32 rsVal, u32 rtVal) { // Rd = Rs - Rt (signed) PGXP_value ret; @@ -1133,12 +1138,12 @@ void CPU_SUB(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) ret.lFlags |= CPU_reg[rt(instr)].lFlags; ret.hFlags |= CPU_reg[rt(instr)].hFlags; - ret.value = rdVal; + ret.value = rsVal - rtVal; CPU_reg[rd(instr)] = ret; } -void CPU_AND_(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +static void CPU_BITWISE(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) { // Rd = Rs & Rt psx_value vald, vals, valt; @@ -1230,25 +1235,35 @@ void CPU_AND_(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) CPU_reg[rd(instr)] = ret; } -void CPU_OR_(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +void CPU_AND_(u32 instr, u32 rsVal, u32 rtVal) +{ + // Rd = Rs & Rt + const u32 rdVal = rsVal & rtVal; + CPU_BITWISE(instr, rdVal, rsVal, rtVal); +} + +void CPU_OR_(u32 instr, u32 rsVal, u32 rtVal) { // Rd = Rs | Rt - CPU_AND_(instr, rdVal, rsVal, rtVal); + const u32 rdVal = rsVal | rtVal; + CPU_BITWISE(instr, rdVal, rsVal, rtVal); } -void CPU_XOR_(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +void CPU_XOR_(u32 instr, u32 rsVal, u32 rtVal) { // Rd = Rs ^ Rt - CPU_AND_(instr, rdVal, rsVal, rtVal); + const u32 rdVal = rsVal ^ rtVal; + CPU_BITWISE(instr, rdVal, rsVal, rtVal); } -void CPU_NOR(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +void CPU_NOR(u32 instr, u32 rsVal, u32 rtVal) { // Rd = Rs NOR Rt - CPU_AND_(instr, rdVal, rsVal, rtVal); + const u32 rdVal = ~(rsVal | rtVal); + CPU_BITWISE(instr, rdVal, rsVal, rtVal); } -void CPU_SLT(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +void CPU_SLT(u32 instr, u32 rsVal, u32 rtVal) { // Rd = Rs < Rt (signed) PGXP_value ret; @@ -1270,11 +1285,11 @@ void CPU_SLT(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) 1.f : (f16Unsign(CPU_reg[rs(instr)].x) < f16Unsign(CPU_reg[rt(instr)].x)) ? 1.f : 0.f; - ret.value = rdVal; + ret.value = BoolToUInt32(static_cast(rsVal) < static_cast(rtVal)); CPU_reg[rd(instr)] = ret; } -void CPU_SLTU(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +void CPU_SLTU(u32 instr, u32 rsVal, u32 rtVal) { // Rd = Rs < Rt (unsigned) PGXP_value ret; @@ -1296,7 +1311,7 @@ void CPU_SLTU(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) 1.f : (f16Unsign(CPU_reg[rs(instr)].x) < f16Unsign(CPU_reg[rt(instr)].x)) ? 1.f : 0.f; - ret.value = rdVal; + ret.value = BoolToUInt32(rsVal < rtVal); CPU_reg[rd(instr)] = ret; } @@ -1494,9 +1509,10 @@ void CPU_DIVU(u32 instr, u32 rsVal, u32 rtVal) //////////////////////////////////// // Shift operations (sa) //////////////////////////////////// -void CPU_SLL(u32 instr, u32 rdVal, u32 rtVal) +void CPU_SLL(u32 instr, u32 rtVal) { // Rd = Rt << Sa + const u32 rdVal = rtVal << sa(instr); PGXP_value ret; u32 sh = sa(instr); Validate(&CPU_reg[rt(instr)], rtVal); @@ -1538,9 +1554,10 @@ void CPU_SLL(u32 instr, u32 rdVal, u32 rtVal) CPU_reg[rd(instr)] = ret; } -void CPU_SRL(u32 instr, u32 rdVal, u32 rtVal) +void CPU_SRL(u32 instr, u32 rtVal) { // Rd = Rt >> Sa + const u32 rdVal = rtVal >> sa(instr); PGXP_value ret; u32 sh = sa(instr); Validate(&CPU_reg[rt(instr)], rtVal); @@ -1601,9 +1618,10 @@ void CPU_SRL(u32 instr, u32 rdVal, u32 rtVal) CPU_reg[rd(instr)] = ret; } -void CPU_SRA(u32 instr, u32 rdVal, u32 rtVal) +void CPU_SRA(u32 instr, u32 rtVal) { // Rd = Rt >> Sa + const u32 rdVal = static_cast(static_cast(rtVal) >> sa(instr)); PGXP_value ret; u32 sh = sa(instr); Validate(&CPU_reg[rt(instr)], rtVal); @@ -1666,9 +1684,10 @@ void CPU_SRA(u32 instr, u32 rdVal, u32 rtVal) //////////////////////////////////// // Shift operations variable //////////////////////////////////// -void CPU_SLLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal) +void CPU_SLLV(u32 instr, u32 rtVal, u32 rsVal) { // Rd = Rt << Rs + const u32 rdVal = rtVal << rsVal; PGXP_value ret; u32 sh = rsVal & 0x1F; Validate(&CPU_reg[rt(instr)], rtVal); @@ -1710,9 +1729,10 @@ void CPU_SLLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal) CPU_reg[rd(instr)] = ret; } -void CPU_SRLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal) +void CPU_SRLV(u32 instr, u32 rtVal, u32 rsVal) { // Rd = Rt >> Sa + const u32 rdVal = rtVal >> rsVal; PGXP_value ret; u32 sh = rsVal & 0x1F; Validate(&CPU_reg[rt(instr)], rtVal); @@ -1774,9 +1794,10 @@ void CPU_SRLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal) CPU_reg[rd(instr)] = ret; } -void CPU_SRAV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal) +void CPU_SRAV(u32 instr, u32 rtVal, u32 rsVal) { // Rd = Rt >> Sa + const u32 rdVal = static_cast(static_cast(rtVal) >> rsVal); PGXP_value ret; u32 sh = rsVal & 0x1F; Validate(&CPU_reg[rt(instr)], rtVal); diff --git a/src/core/pgxp.h b/src/core/pgxp.h index 04399bfb6..912d57619 100644 --- a/src/core/pgxp.h +++ b/src/core/pgxp.h @@ -55,25 +55,25 @@ void CPU_SW(u32 instr, u32 rtVal, u32 addr); void CPU_MOVE(u32 rd_and_rs, u32 rsVal); // Arithmetic with immediate value -void CPU_ADDI(u32 instr, u32 rtVal, u32 rsVal); -void CPU_ANDI(u32 instr, u32 rtVal, u32 rsVal); -void CPU_ORI(u32 instr, u32 rtVal, u32 rsVal); -void CPU_XORI(u32 instr, u32 rtVal, u32 rsVal); -void CPU_SLTI(u32 instr, u32 rtVal, u32 rsVal); -void CPU_SLTIU(u32 instr, u32 rtVal, u32 rsVal); +void CPU_ADDI(u32 instr, u32 rsVal); +void CPU_ANDI(u32 instr, u32 rsVal); +void CPU_ORI(u32 instr, u32 rsVal); +void CPU_XORI(u32 instr, u32 rsVal); +void CPU_SLTI(u32 instr, u32 rsVal); +void CPU_SLTIU(u32 instr, u32 rsVal); // Load Upper void CPU_LUI(u32 instr); // Register Arithmetic -void CPU_ADD(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); -void CPU_SUB(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); -void CPU_AND_(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); -void CPU_OR_(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); -void CPU_XOR_(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); -void CPU_NOR(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); -void CPU_SLT(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); -void CPU_SLTU(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); +void CPU_ADD(u32 instr, u32 rsVal, u32 rtVal); +void CPU_SUB(u32 instr, u32 rsVal, u32 rtVal); +void CPU_AND_(u32 instr, u32 rsVal, u32 rtVal); +void CPU_OR_(u32 instr, u32 rsVal, u32 rtVal); +void CPU_XOR_(u32 instr, u32 rsVal, u32 rtVal); +void CPU_NOR(u32 instr, u32 rsVal, u32 rtVal); +void CPU_SLT(u32 instr, u32 rsVal, u32 rtVal); +void CPU_SLTU(u32 instr, u32 rsVal, u32 rtVal); // Register mult/div void CPU_MULT(u32 instr, u32 rsVal, u32 rtVal); @@ -82,14 +82,14 @@ void CPU_DIV(u32 instr, u32 rsVal, u32 rtVal); void CPU_DIVU(u32 instr, u32 rsVal, u32 rtVal); // Shift operations (sa) -void CPU_SLL(u32 instr, u32 rdVal, u32 rtVal); -void CPU_SRL(u32 instr, u32 rdVal, u32 rtVal); -void CPU_SRA(u32 instr, u32 rdVal, u32 rtVal); +void CPU_SLL(u32 instr, u32 rtVal); +void CPU_SRL(u32 instr, u32 rtVal); +void CPU_SRA(u32 instr, u32 rtVal); // Shift operations variable -void CPU_SLLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal); -void CPU_SRLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal); -void CPU_SRAV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal); +void CPU_SLLV(u32 instr, u32 rtVal, u32 rsVal); +void CPU_SRLV(u32 instr, u32 rtVal, u32 rsVal); +void CPU_SRAV(u32 instr, u32 rtVal, u32 rsVal); // Move registers void CPU_MFHI(u32 instr, u32 hiVal);