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)); 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); DebugAssert(lhs.size == rhs.size);
if (lhs.IsConstant() && rhs.IsConstant()) if (lhs.IsConstant() && rhs.IsConstant())
@ -528,18 +528,18 @@ Value CodeGenerator::ShlValues(const Value& lhs, const Value& rhs)
{ {
if (lhs.IsInHostRegister()) 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 else
{ {
EmitCopyValue(res.host_reg, lhs); 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; 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); DebugAssert(lhs.size == rhs.size);
if (lhs.IsConstant() && rhs.IsConstant()) if (lhs.IsConstant() && rhs.IsConstant())
@ -574,18 +574,18 @@ Value CodeGenerator::ShrValues(const Value& lhs, const Value& rhs)
{ {
if (lhs.IsInHostRegister()) 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 else
{ {
EmitCopyValue(res.host_reg, lhs); 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; 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); DebugAssert(lhs.size == rhs.size);
if (lhs.IsConstant() && rhs.IsConstant()) if (lhs.IsConstant() && rhs.IsConstant())
@ -623,12 +623,12 @@ Value CodeGenerator::SarValues(const Value& lhs, const Value& rhs)
{ {
if (lhs.IsInHostRegister()) 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 else
{ {
EmitCopyValue(res.host_reg, lhs); 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; return res;
@ -1183,8 +1183,6 @@ bool CodeGenerator::Compile_Shift(const CodeBlockInstruction& cbi)
// rd <- rt op (rs & 0x1F) // rd <- rt op (rs & 0x1F)
shamt = m_register_cache.ReadGuestRegister(cbi.instruction.r.rs); shamt = m_register_cache.ReadGuestRegister(cbi.instruction.r.rs);
shamt_spec = SpeculativeReadReg(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; Value result;
@ -1194,7 +1192,7 @@ bool CodeGenerator::Compile_Shift(const CodeBlockInstruction& cbi)
case InstructionFunct::sll: case InstructionFunct::sll:
case InstructionFunct::sllv: case InstructionFunct::sllv:
{ {
result = ShlValues(rt, shamt); result = ShlValues(rt, shamt, false);
if (rt_spec && shamt_spec) if (rt_spec && shamt_spec)
result_spec = *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::srl:
case InstructionFunct::srlv: case InstructionFunct::srlv:
{ {
result = ShrValues(rt, shamt); result = ShrValues(rt, shamt, false);
if (rt_spec && shamt_spec) if (rt_spec && shamt_spec)
result_spec = *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::sra:
case InstructionFunct::srav: case InstructionFunct::srav:
{ {
result = SarValues(rt, shamt); result = SarValues(rt, shamt, false);
if (rt_spec && shamt_spec) if (rt_spec && shamt_spec)
result_spec = static_cast<u32>(static_cast<s32>(*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); bool signed_divide);
void EmitInc(HostReg to_reg, RegSize size); void EmitInc(HostReg to_reg, RegSize size);
void EmitDec(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 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); 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); 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 EmitAnd(HostReg to_reg, HostReg from_reg, const Value& value);
void EmitOr(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); 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 AddValues(const Value& lhs, const Value& rhs, bool set_flags);
Value SubValues(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, bool assume_amount_masked = true);
Value ShrValues(const Value& lhs, const Value& rhs); Value ShrValues(const Value& lhs, const Value& rhs, bool assume_amount_masked = true);
Value SarValues(const Value& lhs, const Value& rhs); Value SarValues(const Value& lhs, const Value& rhs, bool assume_amount_masked = true);
Value OrValues(const Value& lhs, const Value& rhs); Value OrValues(const Value& lhs, const Value& rhs);
Value AndValues(const Value& lhs, const Value& rhs); Value AndValues(const Value& lhs, const Value& rhs);
Value XorValues(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 #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) 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) 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) switch (size)
{ {
@ -1295,21 +1298,21 @@ void CodeGenerator::EmitLoadGuestRAMFastmem(const Value& address, RegSize size,
switch (size) switch (size)
{ {
case RegSize_8: case RegSize_8:
m_emit->Ldrb(GetHostReg32(result.host_reg), actual_address); m_emit->Ldrb(GetHostReg32(result.host_reg), actual_address);
break; break;
case RegSize_16: case RegSize_16:
m_emit->Ldrh(GetHostReg32(result.host_reg), actual_address); m_emit->Ldrh(GetHostReg32(result.host_reg), actual_address);
break; break;
case RegSize_32: case RegSize_32:
m_emit->Ldr(GetHostReg32(result.host_reg), actual_address); m_emit->Ldr(GetHostReg32(result.host_reg), actual_address);
break; break;
default: default:
UnreachableCode(); UnreachableCode();
break; 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()); 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); 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()); 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); 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()); 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_NEAR_HOST_BYTES_PER_INSTRUCTION = 64;
constexpr u32 MAX_FAR_HOST_BYTES_PER_INSTRUCTION = 128; 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. // Alignment of code stoarge.
constexpr u32 CODE_STORAGE_ALIGNMENT = 4096; 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_NEAR_HOST_BYTES_PER_INSTRUCTION = 64;
constexpr u32 MAX_FAR_HOST_BYTES_PER_INSTRUCTION = 128; 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. // Alignment of code stoarge.
constexpr u32 CODE_STORAGE_ALIGNMENT = 4096; constexpr u32 CODE_STORAGE_ALIGNMENT = 4096;