From 09de3819ebbabd2b5680636bc5c43a43552e34bb Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Wed, 20 Nov 2019 00:57:40 +1000 Subject: [PATCH] CPU/Recompiler: Implement sra/srav instructions --- src/core/cpu_recompiler_code_generator.cpp | 50 +++++++++++++++++++++- src/core/cpu_recompiler_code_generator.h | 1 + 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/core/cpu_recompiler_code_generator.cpp b/src/core/cpu_recompiler_code_generator.cpp index fe7d69928..8a23cce81 100644 --- a/src/core/cpu_recompiler_code_generator.cpp +++ b/src/core/cpu_recompiler_code_generator.cpp @@ -90,11 +90,13 @@ bool CodeGenerator::CompileInstruction(const CodeBlockInstruction& cbi) { case InstructionFunct::sll: case InstructionFunct::srl: + case InstructionFunct::sra: result = Compile_ShiftImmediate(cbi); break; case InstructionFunct::sllv: case InstructionFunct::srlv: + case InstructionFunct::srav: result = Compile_ShiftVariable(cbi); break; @@ -268,7 +270,7 @@ Value CodeGenerator::ShlValues(const Value& lhs, const Value& rhs) if (lhs.IsConstant() && rhs.IsConstant()) { // compile-time - u64 new_cv = lhs.constant_value << rhs.constant_value; + u64 new_cv = lhs.constant_value << (rhs.constant_value & 0x1F); switch (lhs.size) { case RegSize_8: @@ -301,7 +303,7 @@ Value CodeGenerator::ShrValues(const Value& lhs, const Value& rhs) if (lhs.IsConstant() && rhs.IsConstant()) { // compile-time - u64 new_cv = lhs.constant_value >> rhs.constant_value; + u64 new_cv = lhs.constant_value >> (rhs.constant_value & 0x1F); switch (lhs.size) { case RegSize_8: @@ -328,6 +330,42 @@ Value CodeGenerator::ShrValues(const Value& lhs, const Value& rhs) return res; } +Value CodeGenerator::SarValues(const Value& lhs, const Value& rhs) +{ + DebugAssert(lhs.size == rhs.size); + if (lhs.IsConstant() && rhs.IsConstant()) + { + // compile-time + switch (lhs.size) + { + case RegSize_8: + return Value::FromConstantU8( + static_cast(static_cast(Truncate8(lhs.constant_value)) >> (rhs.constant_value & 0x1F))); + + case RegSize_16: + return Value::FromConstantU16( + static_cast(static_cast(Truncate16(lhs.constant_value)) >> (rhs.constant_value & 0x1F))); + + case RegSize_32: + return Value::FromConstantU32( + static_cast(static_cast(Truncate32(lhs.constant_value)) >> (rhs.constant_value & 0x1F))); + + case RegSize_64: + return Value::FromConstantU64( + static_cast(static_cast(lhs.constant_value) >> (rhs.constant_value & 0x3F))); + + default: + return Value(); + } + } + + Value res = m_register_cache.AllocateScratch(lhs.size); + EmitCopyValue(res.host_reg, lhs); + if (!rhs.HasConstantValue(0)) + EmitSar(res.host_reg, res.size, rhs); + return res; +} + Value CodeGenerator::OrValues(const Value& lhs, const Value& rhs) { DebugAssert(lhs.size == rhs.size); @@ -688,6 +726,10 @@ bool CodeGenerator::Compile_ShiftImmediate(const CodeBlockInstruction& cbi) result = ShrValues(rt, shamt); break; + case InstructionFunct::sra: + result = SarValues(rt, shamt); + break; + default: UnreachableCode(); break; @@ -720,6 +762,10 @@ bool CodeGenerator::Compile_ShiftVariable(const CodeBlockInstruction& cbi) result = ShrValues(rt, shamt); break; + case InstructionFunct::srav: + result = SarValues(rt, shamt); + break; + default: UnreachableCode(); break; diff --git a/src/core/cpu_recompiler_code_generator.h b/src/core/cpu_recompiler_code_generator.h index afe9b8934..d66a18d89 100644 --- a/src/core/cpu_recompiler_code_generator.h +++ b/src/core/cpu_recompiler_code_generator.h @@ -127,6 +127,7 @@ public: Value MulValues(const Value& lhs, const Value& rhs); 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 OrValues(const Value& lhs, const Value& rhs); Value AndValues(const Value& lhs, const Value& rhs); Value XorValues(const Value& lhs, const Value& rhs);