CPU/Recompiler: Implement sub/subu

This commit is contained in:
Connor McLaughlin 2019-11-23 00:30:47 +10:00
parent f14ad1d3c4
commit 5b745864e3
3 changed files with 69 additions and 2 deletions

View file

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

View file

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

View file

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