From 56ea2386d3e2f3c398f19d4b9288f01e6302018d Mon Sep 17 00:00:00 2001 From: MerryMage Date: Wed, 21 Dec 2016 14:17:19 +0000 Subject: [PATCH] saturated: Implement SSAT and USAT --- .../translate/translate_arm/saturated.cpp | 48 +++++++++++++++++++ .../translate/translate_arm/translate_arm.h | 20 ++------ 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/frontend/translate/translate_arm/saturated.cpp b/src/frontend/translate/translate_arm/saturated.cpp index 80eb26e2..e8bf6167 100644 --- a/src/frontend/translate/translate_arm/saturated.cpp +++ b/src/frontend/translate/translate_arm/saturated.cpp @@ -9,6 +9,54 @@ namespace Dynarmic { namespace Arm { +// Saturation instructions + +bool ArmTranslatorVisitor::arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) { + if (d == Reg::PC || n == Reg::PC) + return UnpredictableInstruction(); + + size_t saturate_to = static_cast(sat_imm) + 1; + ShiftType shift = !sh ? ShiftType::LSL : ShiftType::ASR; + + // SSAT , #, + if (ConditionPassed(cond)) { + auto operand = EmitImmShift(ir.GetRegister(n), shift, imm5, ir.GetCFlag()); + auto result = ir.SignedSaturation(operand.result, saturate_to); + ir.SetRegister(d, result.result); + ir.OrQFlag(result.overflow); + } + return true; +} + +bool ArmTranslatorVisitor::arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) { + UNUSED(cond, sat_imm, d, n); + return InterpretThisInstruction(); +} + +bool ArmTranslatorVisitor::arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) { + if (d == Reg::PC || n == Reg::PC) + return UnpredictableInstruction(); + + size_t saturate_to = static_cast(sat_imm); + ShiftType shift = !sh ? ShiftType::LSL : ShiftType::ASR; + + // USAT , #, + if (ConditionPassed(cond)) { + auto operand = EmitImmShift(ir.GetRegister(n), shift, imm5, ir.GetCFlag()); + auto result = ir.UnsignedSaturation(operand.result, saturate_to); + ir.SetRegister(d, result.result); + ir.OrQFlag(result.overflow); + } + return true; +} + +bool ArmTranslatorVisitor::arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) { + UNUSED(cond, sat_imm, d, n); + return InterpretThisInstruction(); +} + +// Saturated Add/Subtract instructions + bool ArmTranslatorVisitor::arm_QADD(Cond cond, Reg n, Reg d, Reg m) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) return UnpredictableInstruction(); diff --git a/src/frontend/translate/translate_arm/translate_arm.h b/src/frontend/translate/translate_arm/translate_arm.h index 973f09dd..1707d978 100644 --- a/src/frontend/translate/translate_arm/translate_arm.h +++ b/src/frontend/translate/translate_arm/translate_arm.h @@ -227,22 +227,10 @@ struct ArmTranslatorVisitor final { bool arm_REVSH(Cond cond, Reg d, Reg m); // Saturation instructions - bool arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) { - UNUSED(cond, sat_imm, d, imm5, sh, n); - return InterpretThisInstruction(); - } - bool arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) { - UNUSED(cond, sat_imm, d, n); - return InterpretThisInstruction(); - } - bool arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n) { - UNUSED(cond, sat_imm, d, imm5, sh, n); - return InterpretThisInstruction(); - } - bool arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) { - UNUSED(cond, sat_imm, d, n); - return InterpretThisInstruction(); - } + bool arm_SSAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n); + bool arm_SSAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n); + bool arm_USAT(Cond cond, Imm5 sat_imm, Reg d, Imm5 imm5, bool sh, Reg n); + bool arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n); // Multiply (Normal) instructions bool arm_MLA(Cond cond, bool S, Reg d, Reg a, Reg m, Reg n);