PGXP: Compute PSX values on demand for CPU instructions

Generates shorter code for the recompiler.
This commit is contained in:
Connor McLaughlin 2021-02-18 01:45:32 +10:00
parent 54f5c737ce
commit 209827b67c
4 changed files with 151 additions and 139 deletions

View file

@ -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<u32>(static_cast<s32>(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<u32>(static_cast<s32>(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<s32>(ReadReg(inst.r.rs)) < static_cast<s32>(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<s32>(ReadReg(inst.i.rs)) < static_cast<s32>(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);
}

View file

@ -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<u32>(static_cast<s32>(*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<u32>(static_cast<s32>(*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<u32>(dest) << 8) | (static_cast<u32>(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;

View file

@ -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<s32>(static_cast<s16>(_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<s32>(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<s32>(rsVal) < static_cast<s32>(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<u32>(static_cast<s32>(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<u32>(static_cast<s32>(rtVal) >> rsVal);
PGXP_value ret;
u32 sh = rsVal & 0x1F;
Validate(&CPU_reg[rt(instr)], rtVal);

View file

@ -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);