CPU/Recompiler: Combine shift instructions

This commit is contained in:
Connor McLaughlin 2019-11-20 00:49:07 +10:00
parent 51600c5bc0
commit 4f436461ff
2 changed files with 50 additions and 55 deletions

View file

@ -89,19 +89,13 @@ bool CodeGenerator::CompileInstruction(const CodeBlockInstruction& cbi)
switch (cbi.instruction.r.funct) switch (cbi.instruction.r.funct)
{ {
case InstructionFunct::sll: case InstructionFunct::sll:
result = Compile_sll(cbi);
break;
case InstructionFunct::sllv:
result = Compile_sllv(cbi);
break;
case InstructionFunct::srl: case InstructionFunct::srl:
result = Compile_srl(cbi); result = Compile_ShiftImmediate(cbi);
break; break;
case InstructionFunct::sllv:
case InstructionFunct::srlv: case InstructionFunct::srlv:
result = Compile_srlv(cbi); result = Compile_ShiftVariable(cbi);
break; break;
default: default:
@ -643,18 +637,6 @@ bool CodeGenerator::Compile_Fallback(const CodeBlockInstruction& cbi)
return true; return true;
} }
bool CodeGenerator::Compile_lui(const CodeBlockInstruction& cbi)
{
InstructionPrologue(cbi, 1);
// rt <- (imm << 16)
m_register_cache.WriteGuestRegister(cbi.instruction.i.rt,
Value::FromConstantU32(cbi.instruction.i.imm_zext32() << 16));
InstructionEpilogue(cbi);
return true;
}
bool CodeGenerator::Compile_BitwiseImmediate(const CodeBlockInstruction& cbi) bool CodeGenerator::Compile_BitwiseImmediate(const CodeBlockInstruction& cbi)
{ {
InstructionPrologue(cbi, 1); InstructionPrologue(cbi, 1);
@ -688,59 +670,74 @@ bool CodeGenerator::Compile_BitwiseImmediate(const CodeBlockInstruction& cbi)
return true; return true;
} }
bool CodeGenerator::Compile_sll(const CodeBlockInstruction& cbi) bool CodeGenerator::Compile_ShiftImmediate(const CodeBlockInstruction& cbi)
{ {
InstructionPrologue(cbi, 1); InstructionPrologue(cbi, 1);
// rd <- rt << shamt // rd <- rt op shamt
m_register_cache.WriteGuestRegister(cbi.instruction.r.rd, Value rt = m_register_cache.ReadGuestRegister(cbi.instruction.r.rt);
ShlValues(m_register_cache.ReadGuestRegister(cbi.instruction.r.rt), Value shamt = Value::FromConstantU32(cbi.instruction.r.shamt);
Value::FromConstantU32(cbi.instruction.r.shamt))); Value result;
switch (cbi.instruction.r.funct)
{
case InstructionFunct::sll:
result = ShlValues(rt, shamt);
break;
case InstructionFunct::srl:
result = ShrValues(rt, shamt);
break;
default:
UnreachableCode();
break;
}
m_register_cache.WriteGuestRegister(cbi.instruction.r.rd, std::move(result));
InstructionEpilogue(cbi); InstructionEpilogue(cbi);
return true; return true;
} }
bool CodeGenerator::Compile_sllv(const CodeBlockInstruction& cbi) bool CodeGenerator::Compile_ShiftVariable(const CodeBlockInstruction& cbi)
{ {
InstructionPrologue(cbi, 1); InstructionPrologue(cbi, 1);
// rd <- rt << rs // rd <- rt op (rs & 0x1F)
Value shift_amount = m_register_cache.ReadGuestRegister(cbi.instruction.r.rs); Value rt = m_register_cache.ReadGuestRegister(cbi.instruction.r.rt);
Value shamt = m_register_cache.ReadGuestRegister(cbi.instruction.r.rs);
if constexpr (!SHIFTS_ARE_IMPLICITLY_MASKED) if constexpr (!SHIFTS_ARE_IMPLICITLY_MASKED)
EmitAnd(shift_amount.host_reg, Value::FromConstantU32(0x1F)); EmitAnd(shamt.host_reg, Value::FromConstantU32(0x1F));
m_register_cache.WriteGuestRegister( Value result;
cbi.instruction.r.rd, ShlValues(m_register_cache.ReadGuestRegister(cbi.instruction.r.rt), shift_amount)); switch (cbi.instruction.r.funct)
{
case InstructionFunct::sllv:
result = ShlValues(rt, shamt);
break;
InstructionEpilogue(cbi); case InstructionFunct::srlv:
return true; result = ShrValues(rt, shamt);
} break;
bool CodeGenerator::Compile_srl(const CodeBlockInstruction& cbi) default:
{ UnreachableCode();
InstructionPrologue(cbi, 1); break;
}
// rd <- rt >> shamt m_register_cache.WriteGuestRegister(cbi.instruction.r.rd, std::move(result));
m_register_cache.WriteGuestRegister(cbi.instruction.r.rd,
ShrValues(m_register_cache.ReadGuestRegister(cbi.instruction.r.rt),
Value::FromConstantU32(cbi.instruction.r.shamt)));
InstructionEpilogue(cbi); InstructionEpilogue(cbi);
return true; return true;
} }
bool CodeGenerator::Compile_srlv(const CodeBlockInstruction& cbi) bool CodeGenerator::Compile_lui(const CodeBlockInstruction& cbi)
{ {
InstructionPrologue(cbi, 1); InstructionPrologue(cbi, 1);
// rd <- rt << rs // rt <- (imm << 16)
Value shift_amount = m_register_cache.ReadGuestRegister(cbi.instruction.r.rs); m_register_cache.WriteGuestRegister(cbi.instruction.i.rt,
if constexpr (!SHIFTS_ARE_IMPLICITLY_MASKED) Value::FromConstantU32(cbi.instruction.i.imm_zext32() << 16));
EmitAnd(shift_amount.host_reg, Value::FromConstantU32(0x1F));
m_register_cache.WriteGuestRegister(
cbi.instruction.r.rd, ShrValues(m_register_cache.ReadGuestRegister(cbi.instruction.r.rt), shift_amount));
InstructionEpilogue(cbi); InstructionEpilogue(cbi);
return true; return true;

View file

@ -157,12 +157,10 @@ 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_BitwiseImmediate(const CodeBlockInstruction& cbi); bool Compile_BitwiseImmediate(const CodeBlockInstruction& cbi);
bool Compile_sll(const CodeBlockInstruction& cbi); bool Compile_ShiftImmediate(const CodeBlockInstruction& cbi);
bool Compile_sllv(const CodeBlockInstruction& cbi); bool Compile_ShiftVariable(const CodeBlockInstruction& cbi);
bool Compile_srl(const CodeBlockInstruction& cbi); bool Compile_lui(const CodeBlockInstruction& cbi);
bool Compile_srlv(const CodeBlockInstruction& cbi);
bool Compile_addiu(const CodeBlockInstruction& cbi); bool Compile_addiu(const CodeBlockInstruction& cbi);
Core* m_cpu; Core* m_cpu;