From fc33f1d374f85333875b9ac095e4917b2f4be437 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Tue, 2 Aug 2016 10:16:30 +0100 Subject: [PATCH] Implement more instructions SXTB, SXTH, SXTAB, SXTAH, UXTB, UXTH, UXTAB, UXTAH, REV16 --- src/frontend/decoder/arm.h | 26 ++--- .../disassembler/disassembler_arm.cpp | 69 +++++++++++--- .../translate/translate_arm/extension.cpp | 94 +++++++++++++++++-- .../translate/translate_arm/reversal.cpp | 18 +++- .../translate/translate_arm/translate_arm.h | 1 + 5 files changed, 170 insertions(+), 38 deletions(-) diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h index cda45304..e8bbe5d8 100644 --- a/src/frontend/decoder/arm.h +++ b/src/frontend/decoder/arm.h @@ -143,18 +143,18 @@ boost::optional&> DecodeArm(u32 instruction) { INST(&V::arm_UDF, "UDF", "111001111111------------1111----"), // all // Extension instructions - //INST(&V::arm_SXTB, "SXTB", "cccc011010101111ddddrr000111mmmm"), // v6 - //INST(&V::arm_SXTB16, "SXTB16", "cccc011010001111ddddrr000111mmmm"), // v6 - //INST(&V::arm_SXTH, "SXTH", "cccc011010111111ddddrr000111mmmm"), // v6 - //INST(&V::arm_SXTAB, "SXTAB", "cccc01101010nnnnddddrr000111mmmm"), // v6 - //INST(&V::arm_SXTAB16, "SXTAB16", "cccc01101000nnnnddddrr000111mmmm"), // v6 - //INST(&V::arm_SXTAH, "SXTAH", "cccc01101011nnnnddddrr000111mmmm"), // v6 - //INST(&V::arm_UXTB, "UXTB", "cccc011011101111ddddrr000111mmmm"), // v6 - //INST(&V::arm_UXTB16, "UXTB16", "cccc011011001111ddddrr000111mmmm"), // v6 - //INST(&V::arm_UXTH, "UXTH", "cccc011011111111ddddrr000111mmmm"), // v6 - //INST(&V::arm_UXTAB, "UXTAB", "cccc01101110nnnnddddrr000111mmmm"), // v6 - //INST(&V::arm_UXTAB16, "UXTAB16", "cccc01101100nnnnddddrr000111mmmm"), // v6 - //INST(&V::arm_UXTAH, "UXTAH", "cccc01101111nnnnddddrr000111mmmm"), // v6 + INST(&V::arm_SXTB, "SXTB", "cccc011010101111ddddrr000111mmmm"), // v6 + INST(&V::arm_SXTB16, "SXTB16", "cccc011010001111ddddrr000111mmmm"), // v6 + INST(&V::arm_SXTH, "SXTH", "cccc011010111111ddddrr000111mmmm"), // v6 + INST(&V::arm_SXTAB, "SXTAB", "cccc01101010nnnnddddrr000111mmmm"), // v6 + INST(&V::arm_SXTAB16, "SXTAB16", "cccc01101000nnnnddddrr000111mmmm"), // v6 + INST(&V::arm_SXTAH, "SXTAH", "cccc01101011nnnnddddrr000111mmmm"), // v6 + INST(&V::arm_UXTB, "UXTB", "cccc011011101111ddddrr000111mmmm"), // v6 + INST(&V::arm_UXTB16, "UXTB16", "cccc011011001111ddddrr000111mmmm"), // v6 + INST(&V::arm_UXTH, "UXTH", "cccc011011111111ddddrr000111mmmm"), // v6 + INST(&V::arm_UXTAB, "UXTAB", "cccc01101110nnnnddddrr000111mmmm"), // v6 + INST(&V::arm_UXTAB16, "UXTAB16", "cccc01101100nnnnddddrr000111mmmm"), // v6 + INST(&V::arm_UXTAH, "UXTAH", "cccc01101111nnnnddddrr000111mmmm"), // v6 // Hint instructions //INST(&V::arm_PLD, "PLD", "111101---101----1111------------"), // v5E @@ -236,7 +236,7 @@ boost::optional&> DecodeArm(u32 instruction) { // Reversal instructions INST(&V::arm_REV, "REV", "cccc011010111111dddd11110011mmmm"), // v6 - //INST(&V::arm_REV16, "REV16", "cccc011010111111dddd11111011mmmm"), // v6 + INST(&V::arm_REV16, "REV16", "cccc011010111111dddd11111011mmmm"), // v6 INST(&V::arm_REVSH, "REVSH", "cccc011011111111dddd11111011mmmm"), // v6 // Saturation instructions diff --git a/src/frontend/disassembler/disassembler_arm.cpp b/src/frontend/disassembler/disassembler_arm.cpp index ec361742..4a086ab7 100644 --- a/src/frontend/disassembler/disassembler_arm.cpp +++ b/src/frontend/disassembler/disassembler_arm.cpp @@ -66,6 +66,21 @@ public: return ""; } + std::string RorStr(Reg m, SignExtendRotation rotate) { + switch (rotate) { + case SignExtendRotation::ROR_0: + return RegToString(m); + case SignExtendRotation::ROR_8: + return Common::StringFromFormat("%s, ror #8", RegToString(m)); + case SignExtendRotation::ROR_16: + return Common::StringFromFormat("%s, ror #16", RegToString(m)); + case SignExtendRotation::ROR_24: + return Common::StringFromFormat("%s, ror #24", RegToString(m)); + } + assert(false); + return ""; + } + // Branch instructions std::string arm_B(Cond cond, Imm24 imm24) { s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8; @@ -245,7 +260,9 @@ public: } // Exception generation instructions - std::string arm_BKPT(Cond cond, Imm12 imm12, Imm4 imm4) { return "ice"; } + std::string arm_BKPT(Cond cond, Imm12 imm12, Imm4 imm4) { + return Common::StringFromFormat("bkpt #%hu", imm12 << 4 | imm4); + } std::string arm_SVC(Cond cond, Imm24 imm24) { return Common::StringFromFormat("svc%s #%u", CondToString(cond), imm24); } @@ -254,18 +271,42 @@ public: } // Extension functions - std::string arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; } - std::string arm_SXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; } - std::string arm_SXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; } - std::string arm_SXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; } - std::string arm_SXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; } - std::string arm_SXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; } - std::string arm_UXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; } - std::string arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; } - std::string arm_UXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; } - std::string arm_UXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; } - std::string arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; } - std::string arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; } + std::string arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { + return Common::StringFromFormat("sxtab%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RorStr(m, rotate).c_str()); + } + std::string arm_SXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { + return Common::StringFromFormat("sxtab16%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RorStr(m, rotate).c_str()); + } + std::string arm_SXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { + return Common::StringFromFormat("sxtah%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RorStr(m, rotate).c_str()); + } + std::string arm_SXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { + return Common::StringFromFormat("sxtb%s %s, %s", CondToString(cond), RegToString(d), RorStr(m, rotate).c_str()); + } + std::string arm_SXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { + return Common::StringFromFormat("sxtb16%s %s, %s", CondToString(cond), RegToString(d), RorStr(m, rotate).c_str()); + } + std::string arm_SXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { + return Common::StringFromFormat("sxth%s %s, %s", CondToString(cond), RegToString(d), RorStr(m, rotate).c_str()); + } + std::string arm_UXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { + return Common::StringFromFormat("uxtab%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RorStr(m, rotate).c_str()); + } + std::string arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { + return Common::StringFromFormat("uxtab16%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RorStr(m, rotate).c_str()); + } + std::string arm_UXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { + return Common::StringFromFormat("uxtah%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RorStr(m, rotate).c_str()); + } + std::string arm_UXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { + return Common::StringFromFormat("uxtb%s %s, %s", CondToString(cond), RegToString(d), RorStr(m, rotate).c_str()); + } + std::string arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { + return Common::StringFromFormat("uxtb16%s %s, %s", CondToString(cond), RegToString(d), RorStr(m, rotate).c_str()); + } + std::string arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { + return Common::StringFromFormat("uxth%s %s, %s", CondToString(cond), RegToString(d), RorStr(m, rotate).c_str()); + } // Hint instructions std::string arm_PLD() { return ""; } @@ -313,7 +354,7 @@ public: // Miscellaneous instructions std::string arm_CLZ(Cond cond, Reg d, Reg m) { return "ice"; } - std::string arm_NOP() { return "ice"; } + std::string arm_NOP() { return "nop"; } std::string arm_SEL(Cond cond, Reg n, Reg d, Reg m) { return "ice"; } // Unsigned sum of absolute difference functions diff --git a/src/frontend/translate/translate_arm/extension.cpp b/src/frontend/translate/translate_arm/extension.cpp index 671c6767..552c0111 100644 --- a/src/frontend/translate/translate_arm/extension.cpp +++ b/src/frontend/translate/translate_arm/extension.cpp @@ -9,8 +9,34 @@ namespace Dynarmic { namespace Arm { +IR::Value ArmTranslatorVisitor::SignZeroExtendRor(Reg m, SignExtendRotation rotate) { + IR::Value rotated, reg_m = ir.GetRegister(m); + switch (rotate) { + case SignExtendRotation::ROR_0: + rotated = reg_m; + break; + case SignExtendRotation::ROR_8: + rotated = ir.RotateRight(reg_m, ir.Imm8(8), ir.Imm1(0)).result; + break; + case SignExtendRotation::ROR_16: + rotated = ir.RotateRight(reg_m, ir.Imm8(16), ir.Imm1(0)).result; + break; + case SignExtendRotation::ROR_24: + rotated = ir.RotateRight(reg_m, ir.Imm8(24), ir.Imm1(0)).result; + } + return rotated; +} + bool ArmTranslatorVisitor::arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { - return InterpretThisInstruction(); + if (d == Reg::PC || m == Reg::PC) + return UnpredictableInstruction(); + if (ConditionPassed(cond)) { + auto rotated = SignZeroExtendRor(m, rotate); + auto reg_n = ir.GetRegister(n); + auto result = ir.Add(reg_n, ir.SignExtendByteToWord(ir.LeastSignificantByte(rotated))); + ir.SetRegister(d, result); + } + return true; } bool ArmTranslatorVisitor::arm_SXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { @@ -18,11 +44,26 @@ bool ArmTranslatorVisitor::arm_SXTAB16(Cond cond, Reg n, Reg d, SignExtendRotati } bool ArmTranslatorVisitor::arm_SXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { - return InterpretThisInstruction(); + if (d == Reg::PC || m == Reg::PC) + return UnpredictableInstruction(); + if (ConditionPassed(cond)) { + auto rotated = SignZeroExtendRor(m, rotate); + auto reg_n = ir.GetRegister(n); + auto result = ir.Add(reg_n, ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated))); + ir.SetRegister(d, result); + } + return true; } bool ArmTranslatorVisitor::arm_SXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { - return InterpretThisInstruction(); + if (d == Reg::PC || m == Reg::PC) + return UnpredictableInstruction(); + if (ConditionPassed(cond)) { + auto rotated = SignZeroExtendRor(m, rotate); + auto result = ir.SignExtendByteToWord(ir.LeastSignificantByte(rotated)); + ir.SetRegister(d, result); + } + return true; } bool ArmTranslatorVisitor::arm_SXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { @@ -30,11 +71,26 @@ bool ArmTranslatorVisitor::arm_SXTB16(Cond cond, Reg d, SignExtendRotation rotat } bool ArmTranslatorVisitor::arm_SXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { - return InterpretThisInstruction(); + if (d == Reg::PC || m == Reg::PC) + return UnpredictableInstruction(); + if (ConditionPassed(cond)) { + auto rotated = SignZeroExtendRor(m, rotate); + auto result = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated)); + ir.SetRegister(d, result); + } + return true; } bool ArmTranslatorVisitor::arm_UXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { - return InterpretThisInstruction(); + if (d == Reg::PC || m == Reg::PC) + return UnpredictableInstruction(); + if (ConditionPassed(cond)) { + auto rotated = SignZeroExtendRor(m, rotate); + auto reg_n = ir.GetRegister(n); + auto result = ir.Add(reg_n, ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated))); + ir.SetRegister(d, result); + } + return true; } bool ArmTranslatorVisitor::arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { @@ -42,11 +98,26 @@ bool ArmTranslatorVisitor::arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotati } bool ArmTranslatorVisitor::arm_UXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { - return InterpretThisInstruction(); + if (d == Reg::PC || m == Reg::PC) + return UnpredictableInstruction(); + if (ConditionPassed(cond)) { + auto rotated = SignZeroExtendRor(m, rotate); + auto reg_n = ir.GetRegister(n); + auto result = ir.Add(reg_n, ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(rotated))); + ir.SetRegister(d, result); + } + return true; } bool ArmTranslatorVisitor::arm_UXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { - return InterpretThisInstruction(); + if (d == Reg::PC || m == Reg::PC) + return UnpredictableInstruction(); + if (ConditionPassed(cond)) { + auto rotated = SignZeroExtendRor(m, rotate); + auto result = ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated)); + ir.SetRegister(d, result); + } + return true; } bool ArmTranslatorVisitor::arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { @@ -54,7 +125,14 @@ bool ArmTranslatorVisitor::arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotat } bool ArmTranslatorVisitor::arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { - return InterpretThisInstruction(); + if (d == Reg::PC || m == Reg::PC) + return UnpredictableInstruction(); + if (ConditionPassed(cond)) { + auto rotated = SignZeroExtendRor(m, rotate); + auto result = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(rotated)); + ir.SetRegister(d, result); + } + return true; } } // namespace Arm diff --git a/src/frontend/translate/translate_arm/reversal.cpp b/src/frontend/translate/translate_arm/reversal.cpp index 82cee812..d24d5614 100644 --- a/src/frontend/translate/translate_arm/reversal.cpp +++ b/src/frontend/translate/translate_arm/reversal.cpp @@ -11,7 +11,8 @@ namespace Arm { bool ArmTranslatorVisitor::arm_REV(Cond cond, Reg d, Reg m) { // REV , - ASSERT(d != Reg::PC && m != Reg::PC); + if (d == Reg::PC || m == Reg::PC) + return UnpredictableInstruction(); if (ConditionPassed(cond)) { auto result = ir.ByteReverseWord(ir.GetRegister(m)); @@ -21,12 +22,23 @@ bool ArmTranslatorVisitor::arm_REV(Cond cond, Reg d, Reg m) { } bool ArmTranslatorVisitor::arm_REV16(Cond cond, Reg d, Reg m) { - return InterpretThisInstruction(); + if (d == Reg::PC || m == Reg::PC) + return UnpredictableInstruction(); + + if (ConditionPassed(cond)) { + auto reg_m = ir.GetRegister(m); + auto lo = ir.And(ir.LogicalShiftRight(reg_m, ir.Imm8(8), ir.Imm1(0)).result, ir.Imm32(0x00FF00FF)); + auto hi = ir.And(ir.LogicalShiftLeft(reg_m, ir.Imm8(8), ir.Imm1(0)).result, ir.Imm32(0xFF00FF00)); + auto result = ir.Or(lo, hi); + ir.SetRegister(d, result); + } + return true; } bool ArmTranslatorVisitor::arm_REVSH(Cond cond, Reg d, Reg m) { // REVSH , - ASSERT(d != Reg::PC && m != Reg::PC); + if (d == Reg::PC || m == Reg::PC) + return UnpredictableInstruction(); if (ConditionPassed(cond)) { auto rev_half = ir.ByteReverseHalf(ir.LeastSignificantHalf(ir.GetRegister(m))); diff --git a/src/frontend/translate/translate_arm/translate_arm.h b/src/frontend/translate/translate_arm/translate_arm.h index b1ade784..f24a6e0b 100644 --- a/src/frontend/translate/translate_arm/translate_arm.h +++ b/src/frontend/translate/translate_arm/translate_arm.h @@ -60,6 +60,7 @@ struct ArmTranslatorVisitor final { IREmitter::ResultAndCarry EmitImmShift(IR::Value value, ShiftType type, Imm5 imm5, IR::Value carry_in); IREmitter::ResultAndCarry EmitRegShift(IR::Value value, ShiftType type, IR::Value amount, IR::Value carry_in); + IR::Value SignZeroExtendRor(Reg m, SignExtendRotation rotate); // Data processing instructions bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);