CPU/Recompiler: Implement srlv/srrv instructions

This commit is contained in:
Connor McLaughlin 2019-11-20 00:32:41 +10:00
parent 82cbb6e1b8
commit 6157aa9d21
3 changed files with 46 additions and 0 deletions

View file

@ -90,10 +90,18 @@ bool CodeGenerator::CompileInstruction(const CodeBlockInstruction& cbi)
result = Compile_sll(cbi); result = Compile_sll(cbi);
break; break;
case InstructionFunct::sllv:
result = Compile_sllv(cbi);
break;
case InstructionFunct::srl: case InstructionFunct::srl:
result = Compile_srl(cbi); result = Compile_srl(cbi);
break; break;
case InstructionFunct::srlv:
result = Compile_srlv(cbi);
break;
default: default:
result = Compile_Fallback(cbi); result = Compile_Fallback(cbi);
break; break;
@ -589,6 +597,22 @@ bool CodeGenerator::Compile_sll(const CodeBlockInstruction& cbi)
return true; 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) bool CodeGenerator::Compile_srl(const CodeBlockInstruction& cbi)
{ {
InstructionPrologue(cbi, 1); InstructionPrologue(cbi, 1);
@ -602,6 +626,22 @@ bool CodeGenerator::Compile_srl(const CodeBlockInstruction& cbi)
return true; 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) bool CodeGenerator::Compile_addiu(const CodeBlockInstruction& cbi)
{ {
InstructionPrologue(cbi, 1); InstructionPrologue(cbi, 1);

View file

@ -158,7 +158,9 @@ private:
bool Compile_lui(const CodeBlockInstruction& cbi); bool Compile_lui(const CodeBlockInstruction& cbi);
bool Compile_ori(const CodeBlockInstruction& cbi); bool Compile_ori(const CodeBlockInstruction& cbi);
bool Compile_sll(const CodeBlockInstruction& cbi); bool Compile_sll(const CodeBlockInstruction& cbi);
bool Compile_sllv(const CodeBlockInstruction& cbi);
bool Compile_srl(const CodeBlockInstruction& cbi); bool Compile_srl(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;

View file

@ -37,6 +37,9 @@ constexpr RegSize HostPointerSize = RegSize_64;
// A reasonable "maximum" number of bytes per instruction. // A reasonable "maximum" number of bytes per instruction.
constexpr u32 MAX_HOST_BYTES_PER_INSTRUCTION = 128; constexpr u32 MAX_HOST_BYTES_PER_INSTRUCTION = 128;
// Are shifts implicitly masked to 0..31?
constexpr bool SHIFTS_ARE_IMPLICITLY_MASKED = true;
#else #else
using HostReg = void; using HostReg = void;
using CodeEmitter = void; using CodeEmitter = void;
@ -46,6 +49,7 @@ enum : u32
}; };
constexpr HostReg HostReg_Invalid = static_cast<HostReg>(HostReg_Count); constexpr HostReg HostReg_Invalid = static_cast<HostReg>(HostReg_Count);
constexpr OperandSize HostPointerSize = OperandSize_64; constexpr OperandSize HostPointerSize = OperandSize_64;
constexpr bool SHIFTS_ARE_IMPLICITLY_MASKED = false;
#endif #endif
} // namespace Recompiler } // namespace Recompiler