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:
Connor McLaughlin 2019-12-13 00:51:38 +10:00
parent 41298a74e1
commit 44c76f3bf3
4 changed files with 216 additions and 47 deletions

View file

@ -329,8 +329,15 @@ Value CodeGenerator::AddValues(const Value& lhs, const Value& rhs, bool set_flag
} }
else else
{ {
EmitCopyValue(res.host_reg, lhs); if (lhs.IsInHostRegister())
EmitAdd(res.host_reg, rhs, set_flags); {
EmitAdd(res.host_reg, lhs.host_reg, rhs, set_flags);
}
else
{
EmitCopyValue(res.host_reg, lhs);
EmitAdd(res.host_reg, res.host_reg, rhs, set_flags);
}
return res; return res;
} }
} }
@ -369,8 +376,16 @@ Value CodeGenerator::SubValues(const Value& lhs, const Value& rhs, bool set_flag
} }
else else
{ {
EmitCopyValue(res.host_reg, lhs); if (lhs.IsInHostRegister())
EmitSub(res.host_reg, rhs, set_flags); {
EmitSub(res.host_reg, lhs.host_reg, rhs, set_flags);
}
else
{
EmitCopyValue(res.host_reg, lhs);
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);
EmitCopyValue(res.host_reg, lhs); if (rhs.HasConstantValue(0))
if (!rhs.HasConstantValue(0)) {
EmitShl(res.host_reg, res.size, rhs); EmitCopyValue(res.host_reg, lhs);
}
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);
EmitCopyValue(res.host_reg, lhs); if (rhs.HasConstantValue(0))
if (!rhs.HasConstantValue(0)) {
EmitShr(res.host_reg, res.size, rhs); EmitCopyValue(res.host_reg, lhs);
}
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);
EmitCopyValue(res.host_reg, lhs); if (rhs.HasConstantValue(0))
if (!rhs.HasConstantValue(0)) {
EmitSar(res.host_reg, res.size, rhs); EmitCopyValue(res.host_reg, lhs);
}
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;
} }
EmitCopyValue(res.host_reg, lhs); if (lhs.IsInHostRegister())
EmitOr(res.host_reg, rhs); {
EmitOr(res.host_reg, lhs.host_reg, rhs);
}
else
{
EmitCopyValue(res.host_reg, lhs);
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;
} }
EmitCopyValue(res.host_reg, lhs); if (lhs.IsInHostRegister())
EmitAnd(res.host_reg, rhs); {
EmitAnd(res.host_reg, lhs.host_reg, rhs);
}
else
{
EmitCopyValue(res.host_reg, lhs);
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;
} }
EmitCopyValue(res.host_reg, lhs); if (lhs.IsInHostRegister())
EmitXor(res.host_reg, rhs); {
EmitXor(res.host_reg, lhs.host_reg, rhs);
}
else
{
EmitCopyValue(res.host_reg, lhs);
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);

View file

@ -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);

View file

@ -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))

View file

@ -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;
} }