diff options
| author | 2015-08-06 13:55:56 +0200 | |
|---|---|---|
| committer | 2015-08-06 15:50:54 +0200 | |
| commit | 3425cfe54a46512a2ef35e5254c2d32e14ace69a (patch) | |
| tree | da545082e7f2c2e158f56f504ffa35e1fc986a48 /src/core/arm/disassembler | |
| parent | Disassembler: ARMv6K hint instructions (diff) | |
| download | yuzu-3425cfe54a46512a2ef35e5254c2d32e14ace69a.tar.gz yuzu-3425cfe54a46512a2ef35e5254c2d32e14ace69a.tar.xz yuzu-3425cfe54a46512a2ef35e5254c2d32e14ace69a.zip | |
Disassembler: ARMv6K REX instructions
Diffstat (limited to 'src/core/arm/disassembler')
| -rw-r--r-- | src/core/arm/disassembler/arm_disasm.cpp | 92 | ||||
| -rw-r--r-- | src/core/arm/disassembler/arm_disasm.h | 11 |
2 files changed, 97 insertions, 6 deletions
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp index bb87043a4..8eec64d48 100644 --- a/src/core/arm/disassembler/arm_disasm.cpp +++ b/src/core/arm/disassembler/arm_disasm.cpp | |||
| @@ -38,6 +38,7 @@ static const char *opcode_names[] = { | |||
| 38 | "blx", | 38 | "blx", |
| 39 | "bx", | 39 | "bx", |
| 40 | "cdp", | 40 | "cdp", |
| 41 | "clrex", | ||
| 41 | "clz", | 42 | "clz", |
| 42 | "cmn", | 43 | "cmn", |
| 43 | "cmp", | 44 | "cmp", |
| @@ -47,6 +48,10 @@ static const char *opcode_names[] = { | |||
| 47 | "ldr", | 48 | "ldr", |
| 48 | "ldrb", | 49 | "ldrb", |
| 49 | "ldrbt", | 50 | "ldrbt", |
| 51 | "ldrex", | ||
| 52 | "ldrexb", | ||
| 53 | "ldrexd", | ||
| 54 | "ldrexh", | ||
| 50 | "ldrh", | 55 | "ldrh", |
| 51 | "ldrsb", | 56 | "ldrsb", |
| 52 | "ldrsh", | 57 | "ldrsh", |
| @@ -73,6 +78,10 @@ static const char *opcode_names[] = { | |||
| 73 | "str", | 78 | "str", |
| 74 | "strb", | 79 | "strb", |
| 75 | "strbt", | 80 | "strbt", |
| 81 | "strex", | ||
| 82 | "strexb", | ||
| 83 | "strexd", | ||
| 84 | "strexh", | ||
| 76 | "strh", | 85 | "strh", |
| 77 | "strt", | 86 | "strt", |
| 78 | "sub", | 87 | "sub", |
| @@ -178,6 +187,8 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
| 178 | return DisassembleBX(insn); | 187 | return DisassembleBX(insn); |
| 179 | case OP_CDP: | 188 | case OP_CDP: |
| 180 | return "cdp"; | 189 | return "cdp"; |
| 190 | case OP_CLREX: | ||
| 191 | return "clrex"; | ||
| 181 | case OP_CLZ: | 192 | case OP_CLZ: |
| 182 | return DisassembleCLZ(insn); | 193 | return DisassembleCLZ(insn); |
| 183 | case OP_LDC: | 194 | case OP_LDC: |
| @@ -194,6 +205,15 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
| 194 | case OP_STRBT: | 205 | case OP_STRBT: |
| 195 | case OP_STRT: | 206 | case OP_STRT: |
| 196 | return DisassembleMem(insn); | 207 | return DisassembleMem(insn); |
| 208 | case OP_LDREX: | ||
| 209 | case OP_LDREXB: | ||
| 210 | case OP_LDREXD: | ||
| 211 | case OP_LDREXH: | ||
| 212 | case OP_STREX: | ||
| 213 | case OP_STREXB: | ||
| 214 | case OP_STREXD: | ||
| 215 | case OP_STREXH: | ||
| 216 | return DisassembleREX(opcode, insn); | ||
| 197 | case OP_LDRH: | 217 | case OP_LDRH: |
| 198 | case OP_LDRSB: | 218 | case OP_LDRSB: |
| 199 | case OP_LDRSH: | 219 | case OP_LDRSH: |
| @@ -687,6 +707,36 @@ std::string ARM_Disasm::DisassemblePLD(uint32_t insn) | |||
| 687 | } | 707 | } |
| 688 | } | 708 | } |
| 689 | 709 | ||
| 710 | std::string ARM_Disasm::DisassembleREX(Opcode opcode, uint32_t insn) { | ||
| 711 | uint32_t rn = BITS(insn, 16, 19); | ||
| 712 | uint32_t rd = BITS(insn, 12, 15); | ||
| 713 | uint32_t rt = BITS(insn, 0, 3); | ||
| 714 | uint32_t cond = BITS(insn, 28, 31); | ||
| 715 | |||
| 716 | switch (opcode) { | ||
| 717 | case OP_STREX: | ||
| 718 | case OP_STREXB: | ||
| 719 | case OP_STREXH: | ||
| 720 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], | ||
| 721 | cond_to_str(cond), rd, rt, rn); | ||
| 722 | case OP_STREXD: | ||
| 723 | return Common::StringFromFormat("%s%s\tr%d, r%d, r%d, [r%d]", opcode_names[opcode], | ||
| 724 | cond_to_str(cond), rd, rt, rt + 1, rn); | ||
| 725 | |||
| 726 | // for LDREX instructions, rd corresponds to Rt from reference manual | ||
| 727 | case OP_LDREX: | ||
| 728 | case OP_LDREXB: | ||
| 729 | case OP_LDREXH: | ||
| 730 | return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode], | ||
| 731 | cond_to_str(cond), rd, rn); | ||
| 732 | case OP_LDREXD: | ||
| 733 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], | ||
| 734 | cond_to_str(cond), rd, rd + 1, rn); | ||
| 735 | default: | ||
| 736 | return opcode_names[OP_UNDEFINED]; | ||
| 737 | } | ||
| 738 | } | ||
| 739 | |||
| 690 | std::string ARM_Disasm::DisassembleSWI(uint32_t insn) | 740 | std::string ARM_Disasm::DisassembleSWI(uint32_t insn) |
| 691 | { | 741 | { |
| 692 | uint8_t cond = (insn >> 28) & 0xf; | 742 | uint8_t cond = (insn >> 28) & 0xf; |
| @@ -739,12 +789,9 @@ Opcode ARM_Disasm::Decode00(uint32_t insn) { | |||
| 739 | } | 789 | } |
| 740 | uint32_t bits7_4 = (insn >> 4) & 0xf; | 790 | uint32_t bits7_4 = (insn >> 4) & 0xf; |
| 741 | if (bits7_4 == 0x9) { | 791 | if (bits7_4 == 0x9) { |
| 742 | if ((insn & 0x0ff00ff0) == 0x01000090) { | 792 | uint32_t bit24 = BIT(insn, 24); |
| 743 | // Swp instruction | 793 | if (bit24) { |
| 744 | uint8_t bit22 = (insn >> 22) & 0x1; | 794 | return DecodeSyncPrimitive(insn); |
| 745 | if (bit22) | ||
| 746 | return OP_SWPB; | ||
| 747 | return OP_SWP; | ||
| 748 | } | 795 | } |
| 749 | // One of the multiply instructions | 796 | // One of the multiply instructions |
| 750 | return DecodeMUL(insn); | 797 | return DecodeMUL(insn); |
| @@ -778,6 +825,10 @@ Opcode ARM_Disasm::Decode01(uint32_t insn) { | |||
| 778 | // Pre-load | 825 | // Pre-load |
| 779 | return OP_PLD; | 826 | return OP_PLD; |
| 780 | } | 827 | } |
| 828 | if (insn == 0xf57ff01f) { | ||
| 829 | // Clear-Exclusive | ||
| 830 | return OP_CLREX; | ||
| 831 | } | ||
| 781 | if (is_load) { | 832 | if (is_load) { |
| 782 | if (is_byte) { | 833 | if (is_byte) { |
| 783 | // Load byte | 834 | // Load byte |
| @@ -868,6 +919,35 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) { | |||
| 868 | return OP_MCR; | 919 | return OP_MCR; |
| 869 | } | 920 | } |
| 870 | 921 | ||
| 922 | Opcode ARM_Disasm::DecodeSyncPrimitive(uint32_t insn) { | ||
| 923 | uint32_t op = BITS(insn, 20, 23); | ||
| 924 | uint32_t bit22 = BIT(insn, 22); | ||
| 925 | switch (op) { | ||
| 926 | case 0x0: | ||
| 927 | if (bit22) | ||
| 928 | return OP_SWPB; | ||
| 929 | return OP_SWP; | ||
| 930 | case 0x8: | ||
| 931 | return OP_STREX; | ||
| 932 | case 0x9: | ||
| 933 | return OP_LDREX; | ||
| 934 | case 0xA: | ||
| 935 | return OP_STREXD; | ||
| 936 | case 0xB: | ||
| 937 | return OP_LDREXD; | ||
| 938 | case 0xC: | ||
| 939 | return OP_STREXB; | ||
| 940 | case 0xD: | ||
| 941 | return OP_LDREXB; | ||
| 942 | case 0xE: | ||
| 943 | return OP_STREXH; | ||
| 944 | case 0xF: | ||
| 945 | return OP_LDREXH; | ||
| 946 | default: | ||
| 947 | return OP_UNDEFINED; | ||
| 948 | } | ||
| 949 | } | ||
| 950 | |||
| 871 | Opcode ARM_Disasm::DecodeMUL(uint32_t insn) { | 951 | Opcode ARM_Disasm::DecodeMUL(uint32_t insn) { |
| 872 | uint8_t bit24 = (insn >> 24) & 0x1; | 952 | uint8_t bit24 = (insn >> 24) & 0x1; |
| 873 | if (bit24 != 0) { | 953 | if (bit24 != 0) { |
diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h index a4e4adf2f..d04fd21eb 100644 --- a/src/core/arm/disassembler/arm_disasm.h +++ b/src/core/arm/disassembler/arm_disasm.h | |||
| @@ -20,6 +20,7 @@ enum Opcode { | |||
| 20 | OP_BLX, | 20 | OP_BLX, |
| 21 | OP_BX, | 21 | OP_BX, |
| 22 | OP_CDP, | 22 | OP_CDP, |
| 23 | OP_CLREX, | ||
| 23 | OP_CLZ, | 24 | OP_CLZ, |
| 24 | OP_CMN, | 25 | OP_CMN, |
| 25 | OP_CMP, | 26 | OP_CMP, |
| @@ -29,6 +30,10 @@ enum Opcode { | |||
| 29 | OP_LDR, | 30 | OP_LDR, |
| 30 | OP_LDRB, | 31 | OP_LDRB, |
| 31 | OP_LDRBT, | 32 | OP_LDRBT, |
| 33 | OP_LDREX, | ||
| 34 | OP_LDREXB, | ||
| 35 | OP_LDREXD, | ||
| 36 | OP_LDREXH, | ||
| 32 | OP_LDRH, | 37 | OP_LDRH, |
| 33 | OP_LDRSB, | 38 | OP_LDRSB, |
| 34 | OP_LDRSH, | 39 | OP_LDRSH, |
| @@ -55,6 +60,10 @@ enum Opcode { | |||
| 55 | OP_STR, | 60 | OP_STR, |
| 56 | OP_STRB, | 61 | OP_STRB, |
| 57 | OP_STRBT, | 62 | OP_STRBT, |
| 63 | OP_STREX, | ||
| 64 | OP_STREXB, | ||
| 65 | OP_STREXD, | ||
| 66 | OP_STREXH, | ||
| 58 | OP_STRH, | 67 | OP_STRH, |
| 59 | OP_STRT, | 68 | OP_STRT, |
| 60 | OP_SUB, | 69 | OP_SUB, |
| @@ -122,6 +131,7 @@ class ARM_Disasm { | |||
| 122 | static Opcode Decode01(uint32_t insn); | 131 | static Opcode Decode01(uint32_t insn); |
| 123 | static Opcode Decode10(uint32_t insn); | 132 | static Opcode Decode10(uint32_t insn); |
| 124 | static Opcode Decode11(uint32_t insn); | 133 | static Opcode Decode11(uint32_t insn); |
| 134 | static Opcode DecodeSyncPrimitive(uint32_t insn); | ||
| 125 | static Opcode DecodeMUL(uint32_t insn); | 135 | static Opcode DecodeMUL(uint32_t insn); |
| 126 | static Opcode DecodeMSRImmAndHints(uint32_t insn); | 136 | static Opcode DecodeMSRImmAndHints(uint32_t insn); |
| 127 | static Opcode DecodeLDRH(uint32_t insn); | 137 | static Opcode DecodeLDRH(uint32_t insn); |
| @@ -143,6 +153,7 @@ class ARM_Disasm { | |||
| 143 | static std::string DisassembleMSR(uint32_t insn); | 153 | static std::string DisassembleMSR(uint32_t insn); |
| 144 | static std::string DisassembleNoOperands(Opcode opcode, uint32_t insn); | 154 | static std::string DisassembleNoOperands(Opcode opcode, uint32_t insn); |
| 145 | static std::string DisassemblePLD(uint32_t insn); | 155 | static std::string DisassemblePLD(uint32_t insn); |
| 156 | static std::string DisassembleREX(Opcode opcode, uint32_t insn); | ||
| 146 | static std::string DisassembleSWI(uint32_t insn); | 157 | static std::string DisassembleSWI(uint32_t insn); |
| 147 | static std::string DisassembleSWP(Opcode opcode, uint32_t insn); | 158 | static std::string DisassembleSWP(Opcode opcode, uint32_t insn); |
| 148 | }; | 159 | }; |