mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-05-06 14:45:42 -04: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));
|
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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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());
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user