|
|
|
|
@ -90,10 +90,18 @@ bool CodeGenerator::CompileInstruction(const CodeBlockInstruction& cbi)
|
|
|
|
|
result = Compile_sll(cbi);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case InstructionFunct::sllv:
|
|
|
|
|
result = Compile_sllv(cbi);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case InstructionFunct::srl:
|
|
|
|
|
result = Compile_srl(cbi);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case InstructionFunct::srlv:
|
|
|
|
|
result = Compile_srlv(cbi);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
result = Compile_Fallback(cbi);
|
|
|
|
|
break;
|
|
|
|
|
@ -589,6 +597,22 @@ bool CodeGenerator::Compile_sll(const CodeBlockInstruction& cbi)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CodeGenerator::Compile_sllv(const CodeBlockInstruction& cbi)
|
|
|
|
|
{
|
|
|
|
|
InstructionPrologue(cbi, 1);
|
|
|
|
|
|
|
|
|
|
// rd <- rt << rs
|
|
|
|
|
Value shift_amount = m_register_cache.ReadGuestRegister(cbi.instruction.r.rs);
|
|
|
|
|
if constexpr (!SHIFTS_ARE_IMPLICITLY_MASKED)
|
|
|
|
|
EmitAnd(shift_amount.host_reg, Value::FromConstantU32(0x1F));
|
|
|
|
|
|
|
|
|
|
m_register_cache.WriteGuestRegister(
|
|
|
|
|
cbi.instruction.r.rd, ShlValues(m_register_cache.ReadGuestRegister(cbi.instruction.r.rt), shift_amount));
|
|
|
|
|
|
|
|
|
|
InstructionEpilogue(cbi);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CodeGenerator::Compile_srl(const CodeBlockInstruction& cbi)
|
|
|
|
|
{
|
|
|
|
|
InstructionPrologue(cbi, 1);
|
|
|
|
|
@ -602,6 +626,22 @@ bool CodeGenerator::Compile_srl(const CodeBlockInstruction& cbi)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CodeGenerator::Compile_srlv(const CodeBlockInstruction& cbi)
|
|
|
|
|
{
|
|
|
|
|
InstructionPrologue(cbi, 1);
|
|
|
|
|
|
|
|
|
|
// rd <- rt << rs
|
|
|
|
|
Value shift_amount = m_register_cache.ReadGuestRegister(cbi.instruction.r.rs);
|
|
|
|
|
if constexpr (!SHIFTS_ARE_IMPLICITLY_MASKED)
|
|
|
|
|
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);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CodeGenerator::Compile_addiu(const CodeBlockInstruction& cbi)
|
|
|
|
|
{
|
|
|
|
|
InstructionPrologue(cbi, 1);
|
|
|
|
|
|