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);