mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 15:45:42 +00:00
CPU/Recompiler: Implement sub/subu
This commit is contained in:
parent
f14ad1d3c4
commit
5b745864e3
|
@ -138,6 +138,11 @@ bool CodeGenerator::CompileInstruction(const CodeBlockInstruction& cbi)
|
|||
result = Compile_Add(cbi);
|
||||
break;
|
||||
|
||||
case InstructionFunct::sub:
|
||||
case InstructionFunct::subu:
|
||||
result = Compile_Subtract(cbi);
|
||||
break;
|
||||
|
||||
case InstructionFunct::mult:
|
||||
case InstructionFunct::multu:
|
||||
result = Compile_Multiply(cbi);
|
||||
|
@ -312,6 +317,46 @@ Value CodeGenerator::AddValues(const Value& lhs, const Value& rhs, bool set_flag
|
|||
}
|
||||
}
|
||||
|
||||
Value CodeGenerator::SubValues(const Value& lhs, const Value& rhs, bool set_flags)
|
||||
{
|
||||
DebugAssert(lhs.size == rhs.size);
|
||||
if (lhs.IsConstant() && rhs.IsConstant() && !set_flags)
|
||||
{
|
||||
// compile-time
|
||||
u64 new_cv = lhs.constant_value - rhs.constant_value;
|
||||
switch (lhs.size)
|
||||
{
|
||||
case RegSize_8:
|
||||
return Value::FromConstantU8(Truncate8(new_cv));
|
||||
|
||||
case RegSize_16:
|
||||
return Value::FromConstantU16(Truncate16(new_cv));
|
||||
|
||||
case RegSize_32:
|
||||
return Value::FromConstantU32(Truncate32(new_cv));
|
||||
|
||||
case RegSize_64:
|
||||
return Value::FromConstantU64(new_cv);
|
||||
|
||||
default:
|
||||
return Value();
|
||||
}
|
||||
}
|
||||
|
||||
Value res = m_register_cache.AllocateScratch(lhs.size);
|
||||
if (rhs.HasConstantValue(0) && !set_flags)
|
||||
{
|
||||
EmitCopyValue(res.host_reg, lhs);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCopyValue(res.host_reg, lhs);
|
||||
EmitSub(res.host_reg, rhs, set_flags);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<Value, Value> CodeGenerator::MulValues(const Value& lhs, const Value& rhs, bool signed_multiply)
|
||||
{
|
||||
DebugAssert(lhs.size == rhs.size);
|
||||
|
@ -1051,6 +1096,26 @@ bool CodeGenerator::Compile_Add(const CodeBlockInstruction& cbi)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CodeGenerator::Compile_Subtract(const CodeBlockInstruction& cbi)
|
||||
{
|
||||
InstructionPrologue(cbi, 1);
|
||||
|
||||
Assert(cbi.instruction.op == InstructionOp::funct);
|
||||
const bool check_overflow = (cbi.instruction.r.funct == InstructionFunct::sub);
|
||||
|
||||
Value lhs = m_register_cache.ReadGuestRegister(cbi.instruction.r.rs);
|
||||
Value rhs = m_register_cache.ReadGuestRegister(cbi.instruction.r.rt);
|
||||
|
||||
Value result = SubValues(lhs, rhs, check_overflow);
|
||||
if (check_overflow)
|
||||
EmitRaiseException(Exception::Ov, Condition::Overflow);
|
||||
|
||||
m_register_cache.WriteGuestRegister(cbi.instruction.r.rd, std::move(result));
|
||||
|
||||
InstructionEpilogue(cbi);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodeGenerator::Compile_Multiply(const CodeBlockInstruction& cbi)
|
||||
{
|
||||
InstructionPrologue(cbi, 1);
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
void EmitZeroExtend(HostReg to_reg, RegSize to_size, HostReg from_reg, RegSize from_size);
|
||||
void EmitCopyValue(HostReg to_reg, const Value& value);
|
||||
void EmitAdd(HostReg to_reg, const Value& value, bool set_flags);
|
||||
void EmitSub(HostReg to_reg, const Value& value);
|
||||
void EmitSub(HostReg to_reg, const Value& value, bool set_flags);
|
||||
void EmitCmp(HostReg to_reg, const Value& value);
|
||||
void EmitMul(HostReg to_reg_hi, HostReg to_reg_lo, const Value& lhs, const Value& rhs, bool signed_multiply);
|
||||
void EmitInc(HostReg to_reg, RegSize size);
|
||||
|
@ -134,6 +134,7 @@ public:
|
|||
|
||||
// Value ops
|
||||
Value AddValues(const Value& lhs, const Value& rhs, bool set_flags);
|
||||
Value SubValues(const Value& lhs, const Value& rhs, bool set_flags);
|
||||
std::pair<Value, Value> MulValues(const Value& lhs, const Value& rhs, bool signed_multiply);
|
||||
Value ShlValues(const Value& lhs, const Value& rhs);
|
||||
Value ShrValues(const Value& lhs, const Value& rhs);
|
||||
|
@ -179,6 +180,7 @@ private:
|
|||
bool Compile_Store(const CodeBlockInstruction& cbi);
|
||||
bool Compile_MoveHiLo(const CodeBlockInstruction& cbi);
|
||||
bool Compile_Add(const CodeBlockInstruction& cbi);
|
||||
bool Compile_Subtract(const CodeBlockInstruction& cbi);
|
||||
bool Compile_Multiply(const CodeBlockInstruction& cbi);
|
||||
bool Compile_Branch(const CodeBlockInstruction& cbi);
|
||||
bool Compile_lui(const CodeBlockInstruction& cbi);
|
||||
|
|
|
@ -396,7 +396,7 @@ void CodeGenerator::EmitAdd(HostReg to_reg, const Value& value, bool set_flags)
|
|||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::EmitSub(HostReg to_reg, const Value& value)
|
||||
void CodeGenerator::EmitSub(HostReg to_reg, const Value& value, bool set_flags)
|
||||
{
|
||||
DebugAssert(value.IsConstant() || value.IsInHostRegister());
|
||||
|
||||
|
|
Loading…
Reference in a new issue