mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-18 22:35:39 +00:00
CPU/Recompiler: Support targets where shifts aren't implicitly masked
This commit is contained in:
parent
053d7fdc4b
commit
6df5824616
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue