mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-22 22:05:38 +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);
|
result = Compile_Add(cbi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case InstructionFunct::sub:
|
||||||
|
case InstructionFunct::subu:
|
||||||
|
result = Compile_Subtract(cbi);
|
||||||
|
break;
|
||||||
|
|
||||||
case InstructionFunct::mult:
|
case InstructionFunct::mult:
|
||||||
case InstructionFunct::multu:
|
case InstructionFunct::multu:
|
||||||
result = Compile_Multiply(cbi);
|
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)
|
std::pair<Value, Value> CodeGenerator::MulValues(const Value& lhs, const Value& rhs, bool signed_multiply)
|
||||||
{
|
{
|
||||||
DebugAssert(lhs.size == rhs.size);
|
DebugAssert(lhs.size == rhs.size);
|
||||||
|
@ -1051,6 +1096,26 @@ bool CodeGenerator::Compile_Add(const CodeBlockInstruction& cbi)
|
||||||
return true;
|
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)
|
bool CodeGenerator::Compile_Multiply(const CodeBlockInstruction& cbi)
|
||||||
{
|
{
|
||||||
InstructionPrologue(cbi, 1);
|
InstructionPrologue(cbi, 1);
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
void EmitZeroExtend(HostReg to_reg, RegSize to_size, HostReg from_reg, RegSize from_size);
|
void EmitZeroExtend(HostReg to_reg, RegSize to_size, HostReg from_reg, RegSize from_size);
|
||||||
void EmitCopyValue(HostReg to_reg, const Value& value);
|
void EmitCopyValue(HostReg to_reg, const Value& value);
|
||||||
void EmitAdd(HostReg to_reg, const Value& value, bool set_flags);
|
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 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 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);
|
void EmitInc(HostReg to_reg, RegSize size);
|
||||||
|
@ -134,6 +134,7 @@ public:
|
||||||
|
|
||||||
// Value ops
|
// Value ops
|
||||||
Value AddValues(const Value& lhs, const Value& rhs, bool set_flags);
|
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);
|
std::pair<Value, Value> MulValues(const Value& lhs, const Value& rhs, bool signed_multiply);
|
||||||
Value ShlValues(const Value& lhs, const Value& rhs);
|
Value ShlValues(const Value& lhs, const Value& rhs);
|
||||||
Value ShrValues(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_Store(const CodeBlockInstruction& cbi);
|
||||||
bool Compile_MoveHiLo(const CodeBlockInstruction& cbi);
|
bool Compile_MoveHiLo(const CodeBlockInstruction& cbi);
|
||||||
bool Compile_Add(const CodeBlockInstruction& cbi);
|
bool Compile_Add(const CodeBlockInstruction& cbi);
|
||||||
|
bool Compile_Subtract(const CodeBlockInstruction& cbi);
|
||||||
bool Compile_Multiply(const CodeBlockInstruction& cbi);
|
bool Compile_Multiply(const CodeBlockInstruction& cbi);
|
||||||
bool Compile_Branch(const CodeBlockInstruction& cbi);
|
bool Compile_Branch(const CodeBlockInstruction& cbi);
|
||||||
bool Compile_lui(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());
|
DebugAssert(value.IsConstant() || value.IsInHostRegister());
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue