CPU/Recompiler: Implement andi/xori, combine BitwiseImmediate
This commit is contained in:
parent
6157aa9d21
commit
51600c5bc0
|
@ -70,12 +70,14 @@ bool CodeGenerator::CompileInstruction(const CodeBlockInstruction& cbi)
|
||||||
switch (cbi.instruction.op)
|
switch (cbi.instruction.op)
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
case InstructionOp::lui:
|
case InstructionOp::ori:
|
||||||
result = Compile_lui(cbi);
|
case InstructionOp::andi:
|
||||||
|
case InstructionOp::xori:
|
||||||
|
result = Compile_BitwiseImmediate(cbi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InstructionOp::ori:
|
case InstructionOp::lui:
|
||||||
result = Compile_ori(cbi);
|
result = Compile_lui(cbi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InstructionOp::addiu:
|
case InstructionOp::addiu:
|
||||||
|
@ -359,7 +361,6 @@ Value CodeGenerator::OrValues(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 (lhs.HasConstantValue(0))
|
if (lhs.HasConstantValue(0))
|
||||||
{
|
{
|
||||||
EmitCopyValue(res.host_reg, rhs);
|
EmitCopyValue(res.host_reg, rhs);
|
||||||
|
@ -376,6 +377,89 @@ Value CodeGenerator::OrValues(const Value& lhs, const Value& rhs)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value CodeGenerator::AndValues(const Value& lhs, const Value& rhs)
|
||||||
|
{
|
||||||
|
DebugAssert(lhs.size == rhs.size);
|
||||||
|
if (lhs.IsConstant() && rhs.IsConstant())
|
||||||
|
{
|
||||||
|
// compile-time
|
||||||
|
u64 new_cv = lhs.constant_value & rhs.constant_value;
|
||||||
|
switch (lhs.size)
|
||||||
|
{
|
||||||
|
case RegSize_8:
|
||||||
|
return Value::FromConstantU8(Truncate8(new_cv));
|
||||||
|
|
||||||
|
case RegSize_16:
|
||||||
|
return Value::FromConstantU16(Truncate16(new_cv));
|
||||||
|
|
||||||
|
case RegSize_32:
|
||||||
|
return Value::FromConstantU32(Truncate32(new_cv));
|
||||||
|
|
||||||
|
case RegSize_64:
|
||||||
|
return Value::FromConstantU64(new_cv);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return Value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: and with -1 -> noop
|
||||||
|
Value res = m_register_cache.AllocateScratch(lhs.size);
|
||||||
|
if (lhs.HasConstantValue(0) || rhs.HasConstantValue(0))
|
||||||
|
{
|
||||||
|
EmitXor(res.host_reg, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
|
EmitAnd(res.host_reg, rhs);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value CodeGenerator::XorValues(const Value& lhs, const Value& rhs)
|
||||||
|
{
|
||||||
|
DebugAssert(lhs.size == rhs.size);
|
||||||
|
if (lhs.IsConstant() && rhs.IsConstant())
|
||||||
|
{
|
||||||
|
// compile-time
|
||||||
|
u64 new_cv = lhs.constant_value ^ rhs.constant_value;
|
||||||
|
switch (lhs.size)
|
||||||
|
{
|
||||||
|
case RegSize_8:
|
||||||
|
return Value::FromConstantU8(Truncate8(new_cv));
|
||||||
|
|
||||||
|
case RegSize_16:
|
||||||
|
return Value::FromConstantU16(Truncate16(new_cv));
|
||||||
|
|
||||||
|
case RegSize_32:
|
||||||
|
return Value::FromConstantU32(Truncate32(new_cv));
|
||||||
|
|
||||||
|
case RegSize_64:
|
||||||
|
return Value::FromConstantU64(new_cv);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return Value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Value res = m_register_cache.AllocateScratch(lhs.size);
|
||||||
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
|
if (lhs.HasConstantValue(0))
|
||||||
|
{
|
||||||
|
EmitCopyValue(res.host_reg, rhs);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else if (rhs.HasConstantValue(0))
|
||||||
|
{
|
||||||
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmitCopyValue(res.host_reg, lhs);
|
||||||
|
EmitXor(res.host_reg, rhs);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
void CodeGenerator::BlockPrologue()
|
void CodeGenerator::BlockPrologue()
|
||||||
{
|
{
|
||||||
EmitStoreCPUStructField(offsetof(Core, m_exception_raised), Value::FromConstantU8(0));
|
EmitStoreCPUStructField(offsetof(Core, m_exception_raised), Value::FromConstantU8(0));
|
||||||
|
@ -571,14 +655,34 @@ bool CodeGenerator::Compile_lui(const CodeBlockInstruction& cbi)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CodeGenerator::Compile_ori(const CodeBlockInstruction& cbi)
|
bool CodeGenerator::Compile_BitwiseImmediate(const CodeBlockInstruction& cbi)
|
||||||
{
|
{
|
||||||
InstructionPrologue(cbi, 1);
|
InstructionPrologue(cbi, 1);
|
||||||
|
|
||||||
// rt <- rs | zext(imm)
|
// rt <- rs op zext(imm)
|
||||||
m_register_cache.WriteGuestRegister(cbi.instruction.i.rt,
|
Value rs = m_register_cache.ReadGuestRegister(cbi.instruction.i.rs);
|
||||||
OrValues(m_register_cache.ReadGuestRegister(cbi.instruction.i.rs),
|
Value imm = Value::FromConstantU32(cbi.instruction.i.imm_zext32());
|
||||||
Value::FromConstantU32(cbi.instruction.i.imm_zext32())));
|
Value result;
|
||||||
|
switch (cbi.instruction.op)
|
||||||
|
{
|
||||||
|
case InstructionOp::ori:
|
||||||
|
result = OrValues(rs, imm);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InstructionOp::andi:
|
||||||
|
result = AndValues(rs, imm);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InstructionOp::xori:
|
||||||
|
result = XorValues(rs, imm);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UnreachableCode();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_register_cache.WriteGuestRegister(cbi.instruction.i.rt, std::move(result));
|
||||||
|
|
||||||
InstructionEpilogue(cbi);
|
InstructionEpilogue(cbi);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -128,6 +128,8 @@ public:
|
||||||
Value ShlValues(const Value& lhs, const Value& rhs);
|
Value ShlValues(const Value& lhs, const Value& rhs);
|
||||||
Value ShrValues(const Value& lhs, const Value& rhs);
|
Value ShrValues(const Value& lhs, const Value& rhs);
|
||||||
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 XorValues(const Value& lhs, const Value& rhs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Host register setup
|
// Host register setup
|
||||||
|
@ -156,7 +158,7 @@ private:
|
||||||
bool CompileInstruction(const CodeBlockInstruction& cbi);
|
bool CompileInstruction(const CodeBlockInstruction& cbi);
|
||||||
bool Compile_Fallback(const CodeBlockInstruction& cbi);
|
bool Compile_Fallback(const CodeBlockInstruction& cbi);
|
||||||
bool Compile_lui(const CodeBlockInstruction& cbi);
|
bool Compile_lui(const CodeBlockInstruction& cbi);
|
||||||
bool Compile_ori(const CodeBlockInstruction& cbi);
|
bool Compile_BitwiseImmediate(const CodeBlockInstruction& cbi);
|
||||||
bool Compile_sll(const CodeBlockInstruction& cbi);
|
bool Compile_sll(const CodeBlockInstruction& cbi);
|
||||||
bool Compile_sllv(const CodeBlockInstruction& cbi);
|
bool Compile_sllv(const CodeBlockInstruction& cbi);
|
||||||
bool Compile_srl(const CodeBlockInstruction& cbi);
|
bool Compile_srl(const CodeBlockInstruction& cbi);
|
||||||
|
|
Loading…
Reference in New Issue