CPU/Recompiler: Support targets where shifts aren't implicitly masked

This commit is contained in:
Connor McLaughlin 2020-11-21 02:02:05 +10:00
parent 053d7fdc4b
commit 6df5824616
5 changed files with 42 additions and 44 deletions

View file

@ -493,7 +493,7 @@ std::pair<Value, Value> CodeGenerator::MulValues(const Value& lhs, const Value&
return std::make_pair(std::move(hi), std::move(lo));
}
Value CodeGenerator::ShlValues(const Value& lhs, const Value& rhs)
Value CodeGenerator::ShlValues(const Value& lhs, const Value& rhs, bool assume_amount_masked /* = true */)
{
DebugAssert(lhs.size == rhs.size);
if (lhs.IsConstant() && rhs.IsConstant())
@ -528,18 +528,18 @@ Value CodeGenerator::ShlValues(const Value& lhs, const Value& rhs)
{
if (lhs.IsInHostRegister())
{
EmitShl(res.host_reg, lhs.host_reg, res.size, rhs);
EmitShl(res.host_reg, lhs.host_reg, res.size, rhs, assume_amount_masked);
}
else
{
EmitCopyValue(res.host_reg, lhs);
EmitShl(res.host_reg, res.host_reg, res.size, rhs);
EmitShl(res.host_reg, res.host_reg, res.size, rhs, assume_amount_masked);
}
}
return res;
}
Value CodeGenerator::ShrValues(const Value& lhs, const Value& rhs)
Value CodeGenerator::ShrValues(const Value& lhs, const Value& rhs, bool assume_amount_masked /* = true */)
{
DebugAssert(lhs.size == rhs.size);
if (lhs.IsConstant() && rhs.IsConstant())
@ -574,18 +574,18 @@ Value CodeGenerator::ShrValues(const Value& lhs, const Value& rhs)
{
if (lhs.IsInHostRegister())
{
EmitShr(res.host_reg, lhs.host_reg, res.size, rhs);
EmitShr(res.host_reg, lhs.host_reg, res.size, rhs, assume_amount_masked);
}
else
{
EmitCopyValue(res.host_reg, lhs);
EmitShr(res.host_reg, res.host_reg, res.size, rhs);
EmitShr(res.host_reg, res.host_reg, res.size, rhs, assume_amount_masked);
}
}
return res;
}
Value CodeGenerator::SarValues(const Value& lhs, const Value& rhs)
Value CodeGenerator::SarValues(const Value& lhs, const Value& rhs, bool assume_amount_masked /* = true */)
{
DebugAssert(lhs.size == rhs.size);
if (lhs.IsConstant() && rhs.IsConstant())
@ -623,12 +623,12 @@ Value CodeGenerator::SarValues(const Value& lhs, const Value& rhs)
{
if (lhs.IsInHostRegister())
{
EmitSar(res.host_reg, lhs.host_reg, res.size, rhs);
EmitSar(res.host_reg, lhs.host_reg, res.size, rhs, assume_amount_masked);
}
else
{
EmitCopyValue(res.host_reg, lhs);
EmitSar(res.host_reg, res.host_reg, res.size, rhs);
EmitSar(res.host_reg, res.host_reg, res.size, rhs, assume_amount_masked);
}
}
return res;
@ -1183,8 +1183,6 @@ bool CodeGenerator::Compile_Shift(const CodeBlockInstruction& cbi)
// rd <- rt op (rs & 0x1F)
shamt = m_register_cache.ReadGuestRegister(cbi.instruction.r.rs);
shamt_spec = SpeculativeReadReg(cbi.instruction.r.rs);
if constexpr (!SHIFTS_ARE_IMPLICITLY_MASKED)
EmitAnd(shamt.host_reg, shamt.host_reg, Value::FromConstantU32(0x1F));
}
Value result;
@ -1194,7 +1192,7 @@ bool CodeGenerator::Compile_Shift(const CodeBlockInstruction& cbi)
case InstructionFunct::sll:
case InstructionFunct::sllv:
{
result = ShlValues(rt, shamt);
result = ShlValues(rt, shamt, false);
if (rt_spec && shamt_spec)
result_spec = *rt_spec << *shamt_spec;
}
@ -1203,7 +1201,7 @@ bool CodeGenerator::Compile_Shift(const CodeBlockInstruction& cbi)
case InstructionFunct::srl:
case InstructionFunct::srlv:
{
result = ShrValues(rt, shamt);
result = ShrValues(rt, shamt, false);
if (rt_spec && shamt_spec)
result_spec = *rt_spec >> *shamt_spec;
}
@ -1212,7 +1210,7 @@ bool CodeGenerator::Compile_Shift(const CodeBlockInstruction& cbi)
case InstructionFunct::sra:
case InstructionFunct::srav:
{
result = SarValues(rt, shamt);
result = SarValues(rt, shamt, false);
if (rt_spec && shamt_spec)
result_spec = static_cast<u32>(static_cast<s32>(*rt_spec) << *shamt_spec);
}

View file

@ -52,9 +52,9 @@ public:
bool signed_divide);
void EmitInc(HostReg to_reg, RegSize size);
void EmitDec(HostReg to_reg, RegSize size);
void EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value);
void EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value);
void EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value);
void EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value, bool assume_amount_masked = true);
void EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value, bool assume_amount_masked = true);
void EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value, bool assume_amount_masked = true);
void EmitAnd(HostReg to_reg, HostReg from_reg, const Value& value);
void EmitOr(HostReg to_reg, HostReg from_reg, const Value& value);
void EmitXor(HostReg to_reg, HostReg from_reg, const Value& value);
@ -158,9 +158,9 @@ public:
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);
Value SarValues(const Value& lhs, const Value& rhs);
Value ShlValues(const Value& lhs, const Value& rhs, bool assume_amount_masked = true);
Value ShrValues(const Value& lhs, const Value& rhs, bool assume_amount_masked = true);
Value SarValues(const Value& lhs, const Value& rhs, bool assume_amount_masked = true);
Value OrValues(const Value& lhs, const Value& rhs);
Value AndValues(const Value& lhs, const Value& rhs);
Value XorValues(const Value& lhs, const Value& rhs);

View file

@ -632,7 +632,8 @@ void CodeGenerator::EmitDec(HostReg to_reg, RegSize size)
#endif
}
void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value)
void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value,
bool assume_amount_masked /* = true */)
{
switch (size)
{
@ -663,7 +664,8 @@ void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, cons
}
}
void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value)
void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value,
bool assume_amount_masked /* = true */)
{
switch (size)
{
@ -694,7 +696,8 @@ void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, cons
}
}
void CodeGenerator::EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value)
void CodeGenerator::EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value,
bool assume_amount_masked /* = true */)
{
switch (size)
{
@ -1295,21 +1298,21 @@ void CodeGenerator::EmitLoadGuestRAMFastmem(const Value& address, RegSize size,
switch (size)
{
case RegSize_8:
m_emit->Ldrb(GetHostReg32(result.host_reg), actual_address);
break;
case RegSize_8:
m_emit->Ldrb(GetHostReg32(result.host_reg), actual_address);
break;
case RegSize_16:
m_emit->Ldrh(GetHostReg32(result.host_reg), actual_address);
break;
case RegSize_16:
m_emit->Ldrh(GetHostReg32(result.host_reg), actual_address);
break;
case RegSize_32:
m_emit->Ldr(GetHostReg32(result.host_reg), actual_address);
break;
case RegSize_32:
m_emit->Ldr(GetHostReg32(result.host_reg), actual_address);
break;
default:
UnreachableCode();
break;
default:
UnreachableCode();
break;
}
}

View file

@ -836,7 +836,8 @@ void CodeGenerator::EmitDec(HostReg to_reg, RegSize size)
}
}
void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value)
void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value,
bool assume_amount_masked /* = true */)
{
DebugAssert(amount_value.IsConstant() || amount_value.IsInHostRegister());
@ -904,7 +905,8 @@ void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, cons
m_emit->pop(m_emit->rcx);
}
void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value)
void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value,
bool assume_amount_masked /* = true */)
{
DebugAssert(amount_value.IsConstant() || amount_value.IsInHostRegister());
@ -972,7 +974,8 @@ void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, cons
m_emit->pop(m_emit->rcx);
}
void CodeGenerator::EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value)
void CodeGenerator::EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value,
bool assume_amount_masked /* = true */)
{
DebugAssert(amount_value.IsConstant() || amount_value.IsInHostRegister());

View file

@ -71,9 +71,6 @@ constexpr RegSize HostPointerSize = RegSize_64;
constexpr u32 MAX_NEAR_HOST_BYTES_PER_INSTRUCTION = 64;
constexpr u32 MAX_FAR_HOST_BYTES_PER_INSTRUCTION = 128;
// Are shifts implicitly masked to 0..31?
constexpr bool SHIFTS_ARE_IMPLICITLY_MASKED = true;
// Alignment of code stoarge.
constexpr u32 CODE_STORAGE_ALIGNMENT = 4096;
@ -102,9 +99,6 @@ constexpr RegSize HostPointerSize = RegSize_64;
constexpr u32 MAX_NEAR_HOST_BYTES_PER_INSTRUCTION = 64;
constexpr u32 MAX_FAR_HOST_BYTES_PER_INSTRUCTION = 128;
// Are shifts implicitly masked to 0..31?
constexpr bool SHIFTS_ARE_IMPLICITLY_MASKED = true;
// Alignment of code stoarge.
constexpr u32 CODE_STORAGE_ALIGNMENT = 4096;