mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 06:15:38 +00:00
CPU/Recompiler: Support three-operand basic operations
e.g. add r1, r2, r3. This eliminates the extra move on ARM.
This commit is contained in:
parent
41298a74e1
commit
44c76f3bf3
|
@ -328,9 +328,16 @@ Value CodeGenerator::AddValues(const Value& lhs, const Value& rhs, bool set_flag
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (lhs.IsInHostRegister())
|
||||||
|
{
|
||||||
|
EmitAdd(res.host_reg, lhs.host_reg, rhs, set_flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
EmitCopyValue(res.host_reg, lhs);
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
EmitAdd(res.host_reg, rhs, set_flags);
|
EmitAdd(res.host_reg, res.host_reg, rhs, set_flags);
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -368,9 +375,17 @@ Value CodeGenerator::SubValues(const Value& lhs, const Value& rhs, bool set_flag
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (lhs.IsInHostRegister())
|
||||||
|
{
|
||||||
|
EmitSub(res.host_reg, lhs.host_reg, rhs, set_flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
EmitCopyValue(res.host_reg, lhs);
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
EmitSub(res.host_reg, rhs, set_flags);
|
EmitSub(res.host_reg, res.host_reg, rhs, set_flags);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,9 +484,22 @@ Value CodeGenerator::ShlValues(const Value& lhs, const Value& rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
Value res = m_register_cache.AllocateScratch(lhs.size);
|
Value res = m_register_cache.AllocateScratch(lhs.size);
|
||||||
|
if (rhs.HasConstantValue(0))
|
||||||
|
{
|
||||||
EmitCopyValue(res.host_reg, lhs);
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
if (!rhs.HasConstantValue(0))
|
}
|
||||||
EmitShl(res.host_reg, res.size, rhs);
|
else
|
||||||
|
{
|
||||||
|
if (lhs.IsInHostRegister())
|
||||||
|
{
|
||||||
|
EmitShl(res.host_reg, lhs.host_reg, res.size, rhs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
|
EmitShl(res.host_reg, res.host_reg, res.size, rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,9 +530,22 @@ Value CodeGenerator::ShrValues(const Value& lhs, const Value& rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
Value res = m_register_cache.AllocateScratch(lhs.size);
|
Value res = m_register_cache.AllocateScratch(lhs.size);
|
||||||
|
if (rhs.HasConstantValue(0))
|
||||||
|
{
|
||||||
EmitCopyValue(res.host_reg, lhs);
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
if (!rhs.HasConstantValue(0))
|
}
|
||||||
EmitShr(res.host_reg, res.size, rhs);
|
else
|
||||||
|
{
|
||||||
|
if (lhs.IsInHostRegister())
|
||||||
|
{
|
||||||
|
EmitShr(res.host_reg, lhs.host_reg, res.size, rhs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
|
EmitShr(res.host_reg, res.host_reg, res.size, rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,9 +579,22 @@ Value CodeGenerator::SarValues(const Value& lhs, const Value& rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
Value res = m_register_cache.AllocateScratch(lhs.size);
|
Value res = m_register_cache.AllocateScratch(lhs.size);
|
||||||
|
if (rhs.HasConstantValue(0))
|
||||||
|
{
|
||||||
EmitCopyValue(res.host_reg, lhs);
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
if (!rhs.HasConstantValue(0))
|
}
|
||||||
EmitSar(res.host_reg, res.size, rhs);
|
else
|
||||||
|
{
|
||||||
|
if (lhs.IsInHostRegister())
|
||||||
|
{
|
||||||
|
EmitSar(res.host_reg, lhs.host_reg, res.size, rhs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
|
EmitSar(res.host_reg, res.host_reg, res.size, rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,8 +636,15 @@ Value CodeGenerator::OrValues(const Value& lhs, const Value& rhs)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lhs.IsInHostRegister())
|
||||||
|
{
|
||||||
|
EmitOr(res.host_reg, lhs.host_reg, rhs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
EmitCopyValue(res.host_reg, lhs);
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
EmitOr(res.host_reg, rhs);
|
EmitOr(res.host_reg, res.host_reg, rhs);
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,12 +678,19 @@ Value CodeGenerator::AndValues(const Value& lhs, const Value& rhs)
|
||||||
Value res = m_register_cache.AllocateScratch(lhs.size);
|
Value res = m_register_cache.AllocateScratch(lhs.size);
|
||||||
if (lhs.HasConstantValue(0) || rhs.HasConstantValue(0))
|
if (lhs.HasConstantValue(0) || rhs.HasConstantValue(0))
|
||||||
{
|
{
|
||||||
EmitXor(res.host_reg, res);
|
EmitXor(res.host_reg, res.host_reg, res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lhs.IsInHostRegister())
|
||||||
|
{
|
||||||
|
EmitAnd(res.host_reg, lhs.host_reg, rhs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
EmitCopyValue(res.host_reg, lhs);
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
EmitAnd(res.host_reg, rhs);
|
EmitAnd(res.host_reg, res.host_reg, rhs);
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,8 +733,17 @@ Value CodeGenerator::XorValues(const Value& lhs, const Value& rhs)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lhs.IsInHostRegister())
|
||||||
|
{
|
||||||
|
EmitXor(res.host_reg, lhs.host_reg, rhs);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
EmitCopyValue(res.host_reg, lhs);
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
EmitXor(res.host_reg, rhs);
|
EmitXor(res.host_reg, res.host_reg, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -942,7 +1019,7 @@ 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);
|
||||||
if constexpr (!SHIFTS_ARE_IMPLICITLY_MASKED)
|
if constexpr (!SHIFTS_ARE_IMPLICITLY_MASKED)
|
||||||
EmitAnd(shamt.host_reg, Value::FromConstantU32(0x1F));
|
EmitAnd(shamt.host_reg, shamt.host_reg, Value::FromConstantU32(0x1F));
|
||||||
}
|
}
|
||||||
|
|
||||||
Value result;
|
Value result;
|
||||||
|
@ -1414,10 +1491,7 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi)
|
||||||
if (write_mask != UINT32_C(0xFFFFFFFF))
|
if (write_mask != UINT32_C(0xFFFFFFFF))
|
||||||
{
|
{
|
||||||
// need to adjust the mask
|
// need to adjust the mask
|
||||||
Value scratch = m_register_cache.AllocateScratch(RegSize_32);
|
value = AndValues(value, Value::FromConstantU32(write_mask));
|
||||||
EmitCopyValue(scratch.host_reg, value);
|
|
||||||
EmitAnd(scratch.host_reg, Value::FromConstantU32(write_mask));
|
|
||||||
value = std::move(scratch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitStoreCPUStructField(offset, value);
|
EmitStoreCPUStructField(offset, value);
|
||||||
|
@ -1447,11 +1521,10 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi)
|
||||||
EmitLoadCPUStructField(sr.host_reg, RegSize_32, offsetof(Core, m_cop0_regs.sr.bits));
|
EmitLoadCPUStructField(sr.host_reg, RegSize_32, offsetof(Core, m_cop0_regs.sr.bits));
|
||||||
{
|
{
|
||||||
Value new_mode_bits = m_register_cache.AllocateScratch(RegSize_32);
|
Value new_mode_bits = m_register_cache.AllocateScratch(RegSize_32);
|
||||||
EmitCopyValue(new_mode_bits.host_reg, sr);
|
EmitShr(new_mode_bits.host_reg, sr.host_reg, new_mode_bits.size, Value::FromConstantU32(2));
|
||||||
EmitShr(new_mode_bits.host_reg, new_mode_bits.size, Value::FromConstantU32(2));
|
EmitAnd(new_mode_bits.host_reg, new_mode_bits.host_reg, Value::FromConstantU32(mode_bits_mask));
|
||||||
EmitAnd(new_mode_bits.host_reg, Value::FromConstantU32(mode_bits_mask));
|
EmitAnd(sr.host_reg, sr.host_reg, Value::FromConstantU32(~mode_bits_mask));
|
||||||
EmitAnd(sr.host_reg, Value::FromConstantU32(~mode_bits_mask));
|
EmitOr(sr.host_reg, sr.host_reg, new_mode_bits);
|
||||||
EmitOr(sr.host_reg, new_mode_bits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitStoreCPUStructField(offsetof(Core, m_cop0_regs.sr.bits), sr);
|
EmitStoreCPUStructField(offsetof(Core, m_cop0_regs.sr.bits), sr);
|
||||||
|
|
|
@ -48,18 +48,18 @@ public:
|
||||||
void EmitSignExtend(HostReg to_reg, RegSize to_size, HostReg from_reg, RegSize from_size);
|
void EmitSignExtend(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 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, HostReg from_reg, const Value& value, bool set_flags);
|
||||||
void EmitSub(HostReg to_reg, const Value& value, bool set_flags);
|
void EmitSub(HostReg to_reg, HostReg from_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);
|
||||||
void EmitDec(HostReg to_reg, RegSize size);
|
void EmitDec(HostReg to_reg, RegSize size);
|
||||||
void EmitShl(HostReg to_reg, RegSize size, const Value& amount_value);
|
void EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value);
|
||||||
void EmitShr(HostReg to_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, RegSize size, const Value& amount_value);
|
void EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value);
|
||||||
void EmitAnd(HostReg to_reg, const Value& value);
|
void EmitAnd(HostReg to_reg, HostReg from_reg, const Value& value);
|
||||||
void EmitOr(HostReg to_reg, const Value& value);
|
void EmitOr(HostReg to_reg, HostReg from_reg, const Value& value);
|
||||||
void EmitXor(HostReg to_reg, const Value& value);
|
void EmitXor(HostReg to_reg, HostReg from_reg, const Value& value);
|
||||||
void EmitTest(HostReg to_reg, const Value& value);
|
void EmitTest(HostReg to_reg, const Value& value);
|
||||||
void EmitNot(HostReg to_reg, RegSize size);
|
void EmitNot(HostReg to_reg, RegSize size);
|
||||||
void EmitSetConditionResult(HostReg to_reg, RegSize to_size, Condition condition);
|
void EmitSetConditionResult(HostReg to_reg, RegSize to_size, Condition condition);
|
||||||
|
|
|
@ -366,7 +366,7 @@ void CodeGenerator::EmitCopyValue(HostReg to_reg, const Value& value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenerator::EmitAdd(HostReg to_reg, const Value& value, bool set_flags)
|
void CodeGenerator::EmitAdd(HostReg to_reg, HostReg from_reg, const Value& value, bool set_flags)
|
||||||
{
|
{
|
||||||
DebugAssert(value.IsConstant() || value.IsInHostRegister());
|
DebugAssert(value.IsConstant() || value.IsInHostRegister());
|
||||||
|
|
||||||
|
@ -374,6 +374,9 @@ void CodeGenerator::EmitAdd(HostReg to_reg, const Value& value, bool set_flags)
|
||||||
{
|
{
|
||||||
case RegSize_8:
|
case RegSize_8:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg8(to_reg), GetHostReg8(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->add(GetHostReg8(to_reg), SignExtend32(Truncate8(value.constant_value)));
|
m_emit->add(GetHostReg8(to_reg), SignExtend32(Truncate8(value.constant_value)));
|
||||||
else
|
else
|
||||||
|
@ -383,6 +386,9 @@ void CodeGenerator::EmitAdd(HostReg to_reg, const Value& value, bool set_flags)
|
||||||
|
|
||||||
case RegSize_16:
|
case RegSize_16:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg16(to_reg), GetHostReg16(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->add(GetHostReg16(to_reg), SignExtend32(Truncate16(value.constant_value)));
|
m_emit->add(GetHostReg16(to_reg), SignExtend32(Truncate16(value.constant_value)));
|
||||||
else
|
else
|
||||||
|
@ -392,6 +398,9 @@ void CodeGenerator::EmitAdd(HostReg to_reg, const Value& value, bool set_flags)
|
||||||
|
|
||||||
case RegSize_32:
|
case RegSize_32:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg32(to_reg), GetHostReg32(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->add(GetHostReg32(to_reg), Truncate32(value.constant_value));
|
m_emit->add(GetHostReg32(to_reg), Truncate32(value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -401,6 +410,9 @@ void CodeGenerator::EmitAdd(HostReg to_reg, const Value& value, bool set_flags)
|
||||||
|
|
||||||
case RegSize_64:
|
case RegSize_64:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg64(to_reg), GetHostReg64(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
{
|
{
|
||||||
if (!Xbyak::inner::IsInInt32(value.constant_value))
|
if (!Xbyak::inner::IsInInt32(value.constant_value))
|
||||||
|
@ -423,7 +435,7 @@ void CodeGenerator::EmitAdd(HostReg to_reg, const Value& value, bool set_flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenerator::EmitSub(HostReg to_reg, const Value& value, bool set_flags)
|
void CodeGenerator::EmitSub(HostReg to_reg, HostReg from_reg, const Value& value, bool set_flags)
|
||||||
{
|
{
|
||||||
DebugAssert(value.IsConstant() || value.IsInHostRegister());
|
DebugAssert(value.IsConstant() || value.IsInHostRegister());
|
||||||
|
|
||||||
|
@ -431,6 +443,9 @@ void CodeGenerator::EmitSub(HostReg to_reg, const Value& value, bool set_flags)
|
||||||
{
|
{
|
||||||
case RegSize_8:
|
case RegSize_8:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg8(to_reg), GetHostReg8(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->sub(GetHostReg8(to_reg), SignExtend32(Truncate8(value.constant_value)));
|
m_emit->sub(GetHostReg8(to_reg), SignExtend32(Truncate8(value.constant_value)));
|
||||||
else
|
else
|
||||||
|
@ -440,6 +455,9 @@ void CodeGenerator::EmitSub(HostReg to_reg, const Value& value, bool set_flags)
|
||||||
|
|
||||||
case RegSize_16:
|
case RegSize_16:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg16(to_reg), GetHostReg16(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->sub(GetHostReg16(to_reg), SignExtend32(Truncate16(value.constant_value)));
|
m_emit->sub(GetHostReg16(to_reg), SignExtend32(Truncate16(value.constant_value)));
|
||||||
else
|
else
|
||||||
|
@ -449,6 +467,9 @@ void CodeGenerator::EmitSub(HostReg to_reg, const Value& value, bool set_flags)
|
||||||
|
|
||||||
case RegSize_32:
|
case RegSize_32:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg32(to_reg), GetHostReg32(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->sub(GetHostReg32(to_reg), Truncate32(value.constant_value));
|
m_emit->sub(GetHostReg32(to_reg), Truncate32(value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -458,6 +479,9 @@ void CodeGenerator::EmitSub(HostReg to_reg, const Value& value, bool set_flags)
|
||||||
|
|
||||||
case RegSize_64:
|
case RegSize_64:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg64(to_reg), GetHostReg64(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
{
|
{
|
||||||
if (!Xbyak::inner::IsInInt32(value.constant_value))
|
if (!Xbyak::inner::IsInInt32(value.constant_value))
|
||||||
|
@ -691,7 +715,7 @@ void CodeGenerator::EmitDec(HostReg to_reg, RegSize size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenerator::EmitShl(HostReg to_reg, RegSize size, const Value& amount_value)
|
void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value)
|
||||||
{
|
{
|
||||||
DebugAssert(amount_value.IsConstant() || amount_value.IsInHostRegister());
|
DebugAssert(amount_value.IsConstant() || amount_value.IsInHostRegister());
|
||||||
|
|
||||||
|
@ -708,6 +732,9 @@ void CodeGenerator::EmitShl(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
{
|
{
|
||||||
case RegSize_8:
|
case RegSize_8:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg8(to_reg), GetHostReg8(from_reg));
|
||||||
|
|
||||||
if (amount_value.IsConstant())
|
if (amount_value.IsConstant())
|
||||||
m_emit->shl(GetHostReg8(to_reg), Truncate8(amount_value.constant_value));
|
m_emit->shl(GetHostReg8(to_reg), Truncate8(amount_value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -717,6 +744,9 @@ void CodeGenerator::EmitShl(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
|
|
||||||
case RegSize_16:
|
case RegSize_16:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg16(to_reg), GetHostReg16(from_reg));
|
||||||
|
|
||||||
if (amount_value.IsConstant())
|
if (amount_value.IsConstant())
|
||||||
m_emit->shl(GetHostReg16(to_reg), Truncate8(amount_value.constant_value));
|
m_emit->shl(GetHostReg16(to_reg), Truncate8(amount_value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -726,6 +756,9 @@ void CodeGenerator::EmitShl(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
|
|
||||||
case RegSize_32:
|
case RegSize_32:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg32(to_reg), GetHostReg32(from_reg));
|
||||||
|
|
||||||
if (amount_value.IsConstant())
|
if (amount_value.IsConstant())
|
||||||
m_emit->shl(GetHostReg32(to_reg), Truncate32(amount_value.constant_value));
|
m_emit->shl(GetHostReg32(to_reg), Truncate32(amount_value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -735,6 +768,9 @@ void CodeGenerator::EmitShl(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
|
|
||||||
case RegSize_64:
|
case RegSize_64:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg64(to_reg), GetHostReg64(from_reg));
|
||||||
|
|
||||||
if (amount_value.IsConstant())
|
if (amount_value.IsConstant())
|
||||||
m_emit->shl(GetHostReg64(to_reg), Truncate32(amount_value.constant_value));
|
m_emit->shl(GetHostReg64(to_reg), Truncate32(amount_value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -747,7 +783,7 @@ void CodeGenerator::EmitShl(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
m_emit->pop(m_emit->rcx);
|
m_emit->pop(m_emit->rcx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenerator::EmitShr(HostReg to_reg, RegSize size, const Value& amount_value)
|
void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value)
|
||||||
{
|
{
|
||||||
DebugAssert(amount_value.IsConstant() || amount_value.IsInHostRegister());
|
DebugAssert(amount_value.IsConstant() || amount_value.IsInHostRegister());
|
||||||
|
|
||||||
|
@ -764,6 +800,9 @@ void CodeGenerator::EmitShr(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
{
|
{
|
||||||
case RegSize_8:
|
case RegSize_8:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg8(to_reg), GetHostReg8(from_reg));
|
||||||
|
|
||||||
if (amount_value.IsConstant())
|
if (amount_value.IsConstant())
|
||||||
m_emit->shr(GetHostReg8(to_reg), Truncate8(amount_value.constant_value));
|
m_emit->shr(GetHostReg8(to_reg), Truncate8(amount_value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -773,6 +812,9 @@ void CodeGenerator::EmitShr(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
|
|
||||||
case RegSize_16:
|
case RegSize_16:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg16(to_reg), GetHostReg16(from_reg));
|
||||||
|
|
||||||
if (amount_value.IsConstant())
|
if (amount_value.IsConstant())
|
||||||
m_emit->shr(GetHostReg16(to_reg), Truncate8(amount_value.constant_value));
|
m_emit->shr(GetHostReg16(to_reg), Truncate8(amount_value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -782,6 +824,9 @@ void CodeGenerator::EmitShr(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
|
|
||||||
case RegSize_32:
|
case RegSize_32:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg32(to_reg), GetHostReg32(from_reg));
|
||||||
|
|
||||||
if (amount_value.IsConstant())
|
if (amount_value.IsConstant())
|
||||||
m_emit->shr(GetHostReg32(to_reg), Truncate32(amount_value.constant_value));
|
m_emit->shr(GetHostReg32(to_reg), Truncate32(amount_value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -791,6 +836,9 @@ void CodeGenerator::EmitShr(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
|
|
||||||
case RegSize_64:
|
case RegSize_64:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg64(to_reg), GetHostReg64(from_reg));
|
||||||
|
|
||||||
if (amount_value.IsConstant())
|
if (amount_value.IsConstant())
|
||||||
m_emit->shr(GetHostReg64(to_reg), Truncate32(amount_value.constant_value));
|
m_emit->shr(GetHostReg64(to_reg), Truncate32(amount_value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -803,7 +851,7 @@ void CodeGenerator::EmitShr(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
m_emit->pop(m_emit->rcx);
|
m_emit->pop(m_emit->rcx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenerator::EmitSar(HostReg to_reg, RegSize size, const Value& amount_value)
|
void CodeGenerator::EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value)
|
||||||
{
|
{
|
||||||
DebugAssert(amount_value.IsConstant() || amount_value.IsInHostRegister());
|
DebugAssert(amount_value.IsConstant() || amount_value.IsInHostRegister());
|
||||||
|
|
||||||
|
@ -820,6 +868,9 @@ void CodeGenerator::EmitSar(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
{
|
{
|
||||||
case RegSize_8:
|
case RegSize_8:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg8(to_reg), GetHostReg8(from_reg));
|
||||||
|
|
||||||
if (amount_value.IsConstant())
|
if (amount_value.IsConstant())
|
||||||
m_emit->sar(GetHostReg8(to_reg), Truncate8(amount_value.constant_value));
|
m_emit->sar(GetHostReg8(to_reg), Truncate8(amount_value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -829,6 +880,9 @@ void CodeGenerator::EmitSar(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
|
|
||||||
case RegSize_16:
|
case RegSize_16:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg16(to_reg), GetHostReg16(from_reg));
|
||||||
|
|
||||||
if (amount_value.IsConstant())
|
if (amount_value.IsConstant())
|
||||||
m_emit->sar(GetHostReg16(to_reg), Truncate8(amount_value.constant_value));
|
m_emit->sar(GetHostReg16(to_reg), Truncate8(amount_value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -838,6 +892,9 @@ void CodeGenerator::EmitSar(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
|
|
||||||
case RegSize_32:
|
case RegSize_32:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg32(to_reg), GetHostReg32(from_reg));
|
||||||
|
|
||||||
if (amount_value.IsConstant())
|
if (amount_value.IsConstant())
|
||||||
m_emit->sar(GetHostReg32(to_reg), Truncate32(amount_value.constant_value));
|
m_emit->sar(GetHostReg32(to_reg), Truncate32(amount_value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -847,6 +904,9 @@ void CodeGenerator::EmitSar(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
|
|
||||||
case RegSize_64:
|
case RegSize_64:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg64(to_reg), GetHostReg64(from_reg));
|
||||||
|
|
||||||
if (amount_value.IsConstant())
|
if (amount_value.IsConstant())
|
||||||
m_emit->sar(GetHostReg64(to_reg), Truncate32(amount_value.constant_value));
|
m_emit->sar(GetHostReg64(to_reg), Truncate32(amount_value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -859,13 +919,16 @@ void CodeGenerator::EmitSar(HostReg to_reg, RegSize size, const Value& amount_va
|
||||||
m_emit->pop(m_emit->rcx);
|
m_emit->pop(m_emit->rcx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenerator::EmitAnd(HostReg to_reg, const Value& value)
|
void CodeGenerator::EmitAnd(HostReg to_reg, HostReg from_reg, const Value& value)
|
||||||
{
|
{
|
||||||
DebugAssert(value.IsConstant() || value.IsInHostRegister());
|
DebugAssert(value.IsConstant() || value.IsInHostRegister());
|
||||||
switch (value.size)
|
switch (value.size)
|
||||||
{
|
{
|
||||||
case RegSize_8:
|
case RegSize_8:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg8(to_reg), GetHostReg8(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->and_(GetHostReg8(to_reg), Truncate32(value.constant_value & UINT32_C(0xFF)));
|
m_emit->and_(GetHostReg8(to_reg), Truncate32(value.constant_value & UINT32_C(0xFF)));
|
||||||
else
|
else
|
||||||
|
@ -875,6 +938,9 @@ void CodeGenerator::EmitAnd(HostReg to_reg, const Value& value)
|
||||||
|
|
||||||
case RegSize_16:
|
case RegSize_16:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg16(to_reg), GetHostReg16(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->and_(GetHostReg16(to_reg), Truncate32(value.constant_value & UINT32_C(0xFFFF)));
|
m_emit->and_(GetHostReg16(to_reg), Truncate32(value.constant_value & UINT32_C(0xFFFF)));
|
||||||
else
|
else
|
||||||
|
@ -884,6 +950,9 @@ void CodeGenerator::EmitAnd(HostReg to_reg, const Value& value)
|
||||||
|
|
||||||
case RegSize_32:
|
case RegSize_32:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg32(to_reg), GetHostReg32(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->and_(GetHostReg32(to_reg), Truncate32(value.constant_value));
|
m_emit->and_(GetHostReg32(to_reg), Truncate32(value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -893,6 +962,9 @@ void CodeGenerator::EmitAnd(HostReg to_reg, const Value& value)
|
||||||
|
|
||||||
case RegSize_64:
|
case RegSize_64:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg64(to_reg), GetHostReg64(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
{
|
{
|
||||||
if (!Xbyak::inner::IsInInt32(value.constant_value))
|
if (!Xbyak::inner::IsInInt32(value.constant_value))
|
||||||
|
@ -915,13 +987,16 @@ void CodeGenerator::EmitAnd(HostReg to_reg, const Value& value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenerator::EmitOr(HostReg to_reg, const Value& value)
|
void CodeGenerator::EmitOr(HostReg to_reg, HostReg from_reg, const Value& value)
|
||||||
{
|
{
|
||||||
DebugAssert(value.IsConstant() || value.IsInHostRegister());
|
DebugAssert(value.IsConstant() || value.IsInHostRegister());
|
||||||
switch (value.size)
|
switch (value.size)
|
||||||
{
|
{
|
||||||
case RegSize_8:
|
case RegSize_8:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg8(to_reg), GetHostReg8(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->or_(GetHostReg8(to_reg), Truncate32(value.constant_value & UINT32_C(0xFF)));
|
m_emit->or_(GetHostReg8(to_reg), Truncate32(value.constant_value & UINT32_C(0xFF)));
|
||||||
else
|
else
|
||||||
|
@ -931,6 +1006,9 @@ void CodeGenerator::EmitOr(HostReg to_reg, const Value& value)
|
||||||
|
|
||||||
case RegSize_16:
|
case RegSize_16:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg16(to_reg), GetHostReg16(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->or_(GetHostReg16(to_reg), Truncate32(value.constant_value & UINT32_C(0xFFFF)));
|
m_emit->or_(GetHostReg16(to_reg), Truncate32(value.constant_value & UINT32_C(0xFFFF)));
|
||||||
else
|
else
|
||||||
|
@ -940,6 +1018,9 @@ void CodeGenerator::EmitOr(HostReg to_reg, const Value& value)
|
||||||
|
|
||||||
case RegSize_32:
|
case RegSize_32:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg32(to_reg), GetHostReg32(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->or_(GetHostReg32(to_reg), Truncate32(value.constant_value));
|
m_emit->or_(GetHostReg32(to_reg), Truncate32(value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -949,6 +1030,9 @@ void CodeGenerator::EmitOr(HostReg to_reg, const Value& value)
|
||||||
|
|
||||||
case RegSize_64:
|
case RegSize_64:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg64(to_reg), GetHostReg64(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
{
|
{
|
||||||
if (!Xbyak::inner::IsInInt32(value.constant_value))
|
if (!Xbyak::inner::IsInInt32(value.constant_value))
|
||||||
|
@ -971,13 +1055,16 @@ void CodeGenerator::EmitOr(HostReg to_reg, const Value& value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenerator::EmitXor(HostReg to_reg, const Value& value)
|
void CodeGenerator::EmitXor(HostReg to_reg, HostReg from_reg, const Value& value)
|
||||||
{
|
{
|
||||||
DebugAssert(value.IsConstant() || value.IsInHostRegister());
|
DebugAssert(value.IsConstant() || value.IsInHostRegister());
|
||||||
switch (value.size)
|
switch (value.size)
|
||||||
{
|
{
|
||||||
case RegSize_8:
|
case RegSize_8:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg8(to_reg), GetHostReg8(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->xor_(GetHostReg8(to_reg), Truncate32(value.constant_value & UINT32_C(0xFF)));
|
m_emit->xor_(GetHostReg8(to_reg), Truncate32(value.constant_value & UINT32_C(0xFF)));
|
||||||
else
|
else
|
||||||
|
@ -987,6 +1074,9 @@ void CodeGenerator::EmitXor(HostReg to_reg, const Value& value)
|
||||||
|
|
||||||
case RegSize_16:
|
case RegSize_16:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg16(to_reg), GetHostReg16(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->xor_(GetHostReg16(to_reg), Truncate32(value.constant_value & UINT32_C(0xFFFF)));
|
m_emit->xor_(GetHostReg16(to_reg), Truncate32(value.constant_value & UINT32_C(0xFFFF)));
|
||||||
else
|
else
|
||||||
|
@ -996,6 +1086,9 @@ void CodeGenerator::EmitXor(HostReg to_reg, const Value& value)
|
||||||
|
|
||||||
case RegSize_32:
|
case RegSize_32:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg32(to_reg), GetHostReg32(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
m_emit->xor_(GetHostReg32(to_reg), Truncate32(value.constant_value));
|
m_emit->xor_(GetHostReg32(to_reg), Truncate32(value.constant_value));
|
||||||
else
|
else
|
||||||
|
@ -1005,6 +1098,9 @@ void CodeGenerator::EmitXor(HostReg to_reg, const Value& value)
|
||||||
|
|
||||||
case RegSize_64:
|
case RegSize_64:
|
||||||
{
|
{
|
||||||
|
if (to_reg != from_reg)
|
||||||
|
m_emit->mov(GetHostReg64(to_reg), GetHostReg64(from_reg));
|
||||||
|
|
||||||
if (value.IsConstant())
|
if (value.IsConstant())
|
||||||
{
|
{
|
||||||
if (!Xbyak::inner::IsInInt32(value.constant_value))
|
if (!Xbyak::inner::IsInInt32(value.constant_value))
|
||||||
|
|
|
@ -394,7 +394,7 @@ Value RegisterCache::ReadGuestRegister(Reg guest_reg, bool cache /* = true */, b
|
||||||
if (force_host_register)
|
if (force_host_register)
|
||||||
{
|
{
|
||||||
Value temp = AllocateScratch(RegSize_32, forced_host_reg);
|
Value temp = AllocateScratch(RegSize_32, forced_host_reg);
|
||||||
m_code_generator.EmitXor(temp.host_reg, temp);
|
m_code_generator.EmitXor(temp.host_reg, temp.host_reg, temp);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue