From 6df58246166ec7452e758f4898a8dd24714d64e1 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 21 Nov 2020 02:02:05 +1000 Subject: [PATCH] CPU/Recompiler: Support targets where shifts aren't implicitly masked --- src/core/cpu_recompiler_code_generator.cpp | 26 +++++++-------- src/core/cpu_recompiler_code_generator.h | 12 +++---- .../cpu_recompiler_code_generator_aarch64.cpp | 33 ++++++++++--------- .../cpu_recompiler_code_generator_x64.cpp | 9 +++-- src/core/cpu_recompiler_types.h | 6 ---- 5 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/core/cpu_recompiler_code_generator.cpp b/src/core/cpu_recompiler_code_generator.cpp index f78e40776..f02c0d112 100644 --- a/src/core/cpu_recompiler_code_generator.cpp +++ b/src/core/cpu_recompiler_code_generator.cpp @@ -493,7 +493,7 @@ std::pair CodeGenerator::MulValues(const Value& lhs, const Value& return std::make_pair(std::move(hi), std::move(lo)); } -Value CodeGenerator::ShlValues(const Value& lhs, const Value& rhs) +Value CodeGenerator::ShlValues(const Value& lhs, const Value& rhs, bool assume_amount_masked /* = true */) { DebugAssert(lhs.size == rhs.size); if (lhs.IsConstant() && rhs.IsConstant()) @@ -528,18 +528,18 @@ Value CodeGenerator::ShlValues(const Value& lhs, const Value& rhs) { if (lhs.IsInHostRegister()) { - EmitShl(res.host_reg, lhs.host_reg, res.size, rhs); + EmitShl(res.host_reg, lhs.host_reg, res.size, rhs, assume_amount_masked); } else { EmitCopyValue(res.host_reg, lhs); - EmitShl(res.host_reg, res.host_reg, res.size, rhs); + EmitShl(res.host_reg, res.host_reg, res.size, rhs, assume_amount_masked); } } return res; } -Value CodeGenerator::ShrValues(const Value& lhs, const Value& rhs) +Value CodeGenerator::ShrValues(const Value& lhs, const Value& rhs, bool assume_amount_masked /* = true */) { DebugAssert(lhs.size == rhs.size); if (lhs.IsConstant() && rhs.IsConstant()) @@ -574,18 +574,18 @@ Value CodeGenerator::ShrValues(const Value& lhs, const Value& rhs) { if (lhs.IsInHostRegister()) { - EmitShr(res.host_reg, lhs.host_reg, res.size, rhs); + EmitShr(res.host_reg, lhs.host_reg, res.size, rhs, assume_amount_masked); } else { EmitCopyValue(res.host_reg, lhs); - EmitShr(res.host_reg, res.host_reg, res.size, rhs); + EmitShr(res.host_reg, res.host_reg, res.size, rhs, assume_amount_masked); } } return res; } -Value CodeGenerator::SarValues(const Value& lhs, const Value& rhs) +Value CodeGenerator::SarValues(const Value& lhs, const Value& rhs, bool assume_amount_masked /* = true */) { DebugAssert(lhs.size == rhs.size); if (lhs.IsConstant() && rhs.IsConstant()) @@ -623,12 +623,12 @@ Value CodeGenerator::SarValues(const Value& lhs, const Value& rhs) { if (lhs.IsInHostRegister()) { - EmitSar(res.host_reg, lhs.host_reg, res.size, rhs); + EmitSar(res.host_reg, lhs.host_reg, res.size, rhs, assume_amount_masked); } else { EmitCopyValue(res.host_reg, lhs); - EmitSar(res.host_reg, res.host_reg, res.size, rhs); + EmitSar(res.host_reg, res.host_reg, res.size, rhs, assume_amount_masked); } } return res; @@ -1183,8 +1183,6 @@ bool CodeGenerator::Compile_Shift(const CodeBlockInstruction& cbi) // rd <- rt op (rs & 0x1F) shamt = m_register_cache.ReadGuestRegister(cbi.instruction.r.rs); shamt_spec = SpeculativeReadReg(cbi.instruction.r.rs); - if constexpr (!SHIFTS_ARE_IMPLICITLY_MASKED) - EmitAnd(shamt.host_reg, shamt.host_reg, Value::FromConstantU32(0x1F)); } Value result; @@ -1194,7 +1192,7 @@ bool CodeGenerator::Compile_Shift(const CodeBlockInstruction& cbi) case InstructionFunct::sll: case InstructionFunct::sllv: { - result = ShlValues(rt, shamt); + result = ShlValues(rt, shamt, false); if (rt_spec && shamt_spec) result_spec = *rt_spec << *shamt_spec; } @@ -1203,7 +1201,7 @@ bool CodeGenerator::Compile_Shift(const CodeBlockInstruction& cbi) case InstructionFunct::srl: case InstructionFunct::srlv: { - result = ShrValues(rt, shamt); + result = ShrValues(rt, shamt, false); if (rt_spec && shamt_spec) result_spec = *rt_spec >> *shamt_spec; } @@ -1212,7 +1210,7 @@ bool CodeGenerator::Compile_Shift(const CodeBlockInstruction& cbi) case InstructionFunct::sra: case InstructionFunct::srav: { - result = SarValues(rt, shamt); + result = SarValues(rt, shamt, false); if (rt_spec && shamt_spec) result_spec = static_cast(static_cast(*rt_spec) << *shamt_spec); } diff --git a/src/core/cpu_recompiler_code_generator.h b/src/core/cpu_recompiler_code_generator.h index 9dd87c857..1756d2ae4 100644 --- a/src/core/cpu_recompiler_code_generator.h +++ b/src/core/cpu_recompiler_code_generator.h @@ -52,9 +52,9 @@ public: bool signed_divide); void EmitInc(HostReg to_reg, RegSize size); void EmitDec(HostReg to_reg, RegSize size); - void EmitShl(HostReg to_reg, HostReg from_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, HostReg from_reg, RegSize size, const Value& amount_value); + void EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value, bool assume_amount_masked = true); + void EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value, bool assume_amount_masked = true); + void EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value, bool assume_amount_masked = true); void EmitAnd(HostReg to_reg, HostReg from_reg, const Value& value); void EmitOr(HostReg to_reg, HostReg from_reg, const Value& value); void EmitXor(HostReg to_reg, HostReg from_reg, const Value& value); @@ -158,9 +158,9 @@ public: Value AddValues(const Value& lhs, const Value& rhs, bool set_flags); Value SubValues(const Value& lhs, const Value& rhs, bool set_flags); std::pair MulValues(const Value& lhs, const Value& rhs, bool signed_multiply); - Value ShlValues(const Value& lhs, const Value& rhs); - Value ShrValues(const Value& lhs, const Value& rhs); - Value SarValues(const Value& lhs, const Value& rhs); + Value ShlValues(const Value& lhs, const Value& rhs, bool assume_amount_masked = true); + Value ShrValues(const Value& lhs, const Value& rhs, bool assume_amount_masked = true); + Value SarValues(const Value& lhs, const Value& rhs, bool assume_amount_masked = true); Value OrValues(const Value& lhs, const Value& rhs); Value AndValues(const Value& lhs, const Value& rhs); Value XorValues(const Value& lhs, const Value& rhs); diff --git a/src/core/cpu_recompiler_code_generator_aarch64.cpp b/src/core/cpu_recompiler_code_generator_aarch64.cpp index 59a2fb74c..25bfe301b 100644 --- a/src/core/cpu_recompiler_code_generator_aarch64.cpp +++ b/src/core/cpu_recompiler_code_generator_aarch64.cpp @@ -632,7 +632,8 @@ void CodeGenerator::EmitDec(HostReg to_reg, RegSize size) #endif } -void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value) +void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value, + bool assume_amount_masked /* = true */) { switch (size) { @@ -663,7 +664,8 @@ void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, cons } } -void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value) +void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value, + bool assume_amount_masked /* = true */) { switch (size) { @@ -694,7 +696,8 @@ void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, cons } } -void CodeGenerator::EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value) +void CodeGenerator::EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value, + bool assume_amount_masked /* = true */) { switch (size) { @@ -1295,21 +1298,21 @@ void CodeGenerator::EmitLoadGuestRAMFastmem(const Value& address, RegSize size, switch (size) { - case RegSize_8: - m_emit->Ldrb(GetHostReg32(result.host_reg), actual_address); - break; + case RegSize_8: + m_emit->Ldrb(GetHostReg32(result.host_reg), actual_address); + break; - case RegSize_16: - m_emit->Ldrh(GetHostReg32(result.host_reg), actual_address); - break; + case RegSize_16: + m_emit->Ldrh(GetHostReg32(result.host_reg), actual_address); + break; - case RegSize_32: - m_emit->Ldr(GetHostReg32(result.host_reg), actual_address); - break; + case RegSize_32: + m_emit->Ldr(GetHostReg32(result.host_reg), actual_address); + break; - default: - UnreachableCode(); - break; + default: + UnreachableCode(); + break; } } diff --git a/src/core/cpu_recompiler_code_generator_x64.cpp b/src/core/cpu_recompiler_code_generator_x64.cpp index 53bbfd35c..c40f477a2 100644 --- a/src/core/cpu_recompiler_code_generator_x64.cpp +++ b/src/core/cpu_recompiler_code_generator_x64.cpp @@ -836,7 +836,8 @@ void CodeGenerator::EmitDec(HostReg to_reg, RegSize size) } } -void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value) +void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value, + bool assume_amount_masked /* = true */) { DebugAssert(amount_value.IsConstant() || amount_value.IsInHostRegister()); @@ -904,7 +905,8 @@ void CodeGenerator::EmitShl(HostReg to_reg, HostReg from_reg, RegSize size, cons m_emit->pop(m_emit->rcx); } -void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value) +void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value, + bool assume_amount_masked /* = true */) { DebugAssert(amount_value.IsConstant() || amount_value.IsInHostRegister()); @@ -972,7 +974,8 @@ void CodeGenerator::EmitShr(HostReg to_reg, HostReg from_reg, RegSize size, cons m_emit->pop(m_emit->rcx); } -void CodeGenerator::EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value) +void CodeGenerator::EmitSar(HostReg to_reg, HostReg from_reg, RegSize size, const Value& amount_value, + bool assume_amount_masked /* = true */) { DebugAssert(amount_value.IsConstant() || amount_value.IsInHostRegister()); diff --git a/src/core/cpu_recompiler_types.h b/src/core/cpu_recompiler_types.h index a20c3aa49..44f8d5dcf 100644 --- a/src/core/cpu_recompiler_types.h +++ b/src/core/cpu_recompiler_types.h @@ -71,9 +71,6 @@ constexpr RegSize HostPointerSize = RegSize_64; constexpr u32 MAX_NEAR_HOST_BYTES_PER_INSTRUCTION = 64; constexpr u32 MAX_FAR_HOST_BYTES_PER_INSTRUCTION = 128; -// Are shifts implicitly masked to 0..31? -constexpr bool SHIFTS_ARE_IMPLICITLY_MASKED = true; - // Alignment of code stoarge. constexpr u32 CODE_STORAGE_ALIGNMENT = 4096; @@ -102,9 +99,6 @@ constexpr RegSize HostPointerSize = RegSize_64; constexpr u32 MAX_NEAR_HOST_BYTES_PER_INSTRUCTION = 64; constexpr u32 MAX_FAR_HOST_BYTES_PER_INSTRUCTION = 128; -// Are shifts implicitly masked to 0..31? -constexpr bool SHIFTS_ARE_IMPLICITLY_MASKED = true; - // Alignment of code stoarge. constexpr u32 CODE_STORAGE_ALIGNMENT = 4096;