diff options
| author | 2015-08-07 13:44:02 +0200 | |
|---|---|---|
| committer | 2015-08-09 01:31:10 +0200 | |
| commit | e4ff2442885e42ed5cfecb1ceadebf99da2cd2cf (patch) | |
| tree | ceaf39f2fd6d361e9e2b87b0d1b07927addbe182 /src/core | |
| parent | arm_disasm: ARMv6 packing and sign-extend media instructions (diff) | |
| download | yuzu-e4ff2442885e42ed5cfecb1ceadebf99da2cd2cf.tar.gz yuzu-e4ff2442885e42ed5cfecb1ceadebf99da2cd2cf.tar.xz yuzu-e4ff2442885e42ed5cfecb1ceadebf99da2cd2cf.zip | |
arm_disasm: ARMv6 saturation media instructions
SSAT, SSAT16, USAT, USAT16
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/arm/disassembler/arm_disasm.cpp | 52 | ||||
| -rw-r--r-- | src/core/arm/disassembler/arm_disasm.h | 5 |
2 files changed, 55 insertions, 2 deletions
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp index 3ac867949..d73495fe9 100644 --- a/src/core/arm/disassembler/arm_disasm.cpp +++ b/src/core/arm/disassembler/arm_disasm.cpp | |||
| @@ -76,6 +76,8 @@ static const char *opcode_names[] = { | |||
| 76 | "sev", | 76 | "sev", |
| 77 | "smlal", | 77 | "smlal", |
| 78 | "smull", | 78 | "smull", |
| 79 | "ssat", | ||
| 80 | "ssat16", | ||
| 79 | "stc", | 81 | "stc", |
| 80 | "stm", | 82 | "stm", |
| 81 | "str", | 83 | "str", |
| @@ -101,6 +103,8 @@ static const char *opcode_names[] = { | |||
| 101 | "tst", | 103 | "tst", |
| 102 | "umlal", | 104 | "umlal", |
| 103 | "umull", | 105 | "umull", |
| 106 | "usat", | ||
| 107 | "usat16", | ||
| 104 | "uxtab", | 108 | "uxtab", |
| 105 | "uxtab16", | 109 | "uxtab16", |
| 106 | "uxtah", | 110 | "uxtah", |
| @@ -257,6 +261,11 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
| 257 | return DisassemblePLD(insn); | 261 | return DisassemblePLD(insn); |
| 258 | case OP_SEL: | 262 | case OP_SEL: |
| 259 | return DisassembleSEL(insn); | 263 | return DisassembleSEL(insn); |
| 264 | case OP_SSAT: | ||
| 265 | case OP_SSAT16: | ||
| 266 | case OP_USAT: | ||
| 267 | case OP_USAT16: | ||
| 268 | return DisassembleSAT(opcode, insn); | ||
| 260 | case OP_STC: | 269 | case OP_STC: |
| 261 | return "stc"; | 270 | return "stc"; |
| 262 | case OP_SWI: | 271 | case OP_SWI: |
| @@ -793,8 +802,35 @@ std::string ARM_Disasm::DisassembleREX(Opcode opcode, uint32_t insn) { | |||
| 793 | } | 802 | } |
| 794 | } | 803 | } |
| 795 | 804 | ||
| 796 | std::string ARM_Disasm::DisassembleSEL(uint32_t insn) | 805 | std::string ARM_Disasm::DisassembleSAT(Opcode opcode, uint32_t insn) { |
| 797 | { | 806 | uint32_t cond = BITS(insn, 28, 31); |
| 807 | uint32_t sat_imm = BITS(insn, 16, 20); | ||
| 808 | uint32_t rd = BITS(insn, 12, 15); | ||
| 809 | uint32_t imm5 = BITS(insn, 7, 11); | ||
| 810 | uint32_t sh = BIT(insn, 6); | ||
| 811 | uint32_t rn = BITS(insn, 0, 3); | ||
| 812 | |||
| 813 | std::string shift_part = ""; | ||
| 814 | bool opcode_has_shift = (opcode == OP_SSAT) || (opcode == OP_USAT); | ||
| 815 | if (opcode_has_shift && !(sh == 0 && imm5 == 0)) { | ||
| 816 | if (sh == 0) | ||
| 817 | shift_part += ", LSL #"; | ||
| 818 | else | ||
| 819 | shift_part += ", ASR #"; | ||
| 820 | |||
| 821 | if (imm5 == 0) | ||
| 822 | imm5 = 32; | ||
| 823 | shift_part += std::to_string(imm5); | ||
| 824 | } | ||
| 825 | |||
| 826 | if (opcode == OP_SSAT || opcode == OP_SSAT16) | ||
| 827 | sat_imm++; | ||
| 828 | |||
| 829 | return Common::StringFromFormat("%s%s\tr%u, #%u, r%u%s", opcode_names[opcode], cond_to_str(cond), rd, | ||
| 830 | sat_imm, rn, shift_part.c_str()); | ||
| 831 | } | ||
| 832 | |||
| 833 | std::string ARM_Disasm::DisassembleSEL(uint32_t insn) { | ||
| 798 | uint32_t cond = BITS(insn, 28, 31); | 834 | uint32_t cond = BITS(insn, 28, 31); |
| 799 | uint32_t rn = BITS(insn, 16, 19); | 835 | uint32_t rn = BITS(insn, 16, 19); |
| 800 | uint32_t rd = BITS(insn, 12, 15); | 836 | uint32_t rd = BITS(insn, 12, 15); |
| @@ -1048,12 +1084,18 @@ Opcode ARM_Disasm::DecodePackingSaturationReversal(uint32_t insn) { | |||
| 1048 | return OP_SEL; | 1084 | return OP_SEL; |
| 1049 | break; | 1085 | break; |
| 1050 | case 0x2: | 1086 | case 0x2: |
| 1087 | if (BIT(op2, 0) == 0) | ||
| 1088 | return OP_SSAT; | ||
| 1089 | if (op2 == 0x1) | ||
| 1090 | return OP_SSAT16; | ||
| 1051 | if (op2 == 0x3 && a != 0xf) | 1091 | if (op2 == 0x3 && a != 0xf) |
| 1052 | return OP_SXTAB; | 1092 | return OP_SXTAB; |
| 1053 | if (op2 == 0x3 && a == 0xf) | 1093 | if (op2 == 0x3 && a == 0xf) |
| 1054 | return OP_SXTB; | 1094 | return OP_SXTB; |
| 1055 | break; | 1095 | break; |
| 1056 | case 0x3: | 1096 | case 0x3: |
| 1097 | if (BIT(op2, 0) == 0) | ||
| 1098 | return OP_SSAT; | ||
| 1057 | if (op2 == 0x3 && a != 0xf) | 1099 | if (op2 == 0x3 && a != 0xf) |
| 1058 | return OP_SXTAH; | 1100 | return OP_SXTAH; |
| 1059 | if (op2 == 0x3 && a == 0xf) | 1101 | if (op2 == 0x3 && a == 0xf) |
| @@ -1066,12 +1108,18 @@ Opcode ARM_Disasm::DecodePackingSaturationReversal(uint32_t insn) { | |||
| 1066 | return OP_UXTB16; | 1108 | return OP_UXTB16; |
| 1067 | break; | 1109 | break; |
| 1068 | case 0x6: | 1110 | case 0x6: |
| 1111 | if (BIT(op2, 0) == 0) | ||
| 1112 | return OP_USAT; | ||
| 1113 | if (op2 == 0x1) | ||
| 1114 | return OP_USAT16; | ||
| 1069 | if (op2 == 0x3 && a != 0xf) | 1115 | if (op2 == 0x3 && a != 0xf) |
| 1070 | return OP_UXTAB; | 1116 | return OP_UXTAB; |
| 1071 | if (op2 == 0x3 && a == 0xf) | 1117 | if (op2 == 0x3 && a == 0xf) |
| 1072 | return OP_UXTB; | 1118 | return OP_UXTB; |
| 1073 | break; | 1119 | break; |
| 1074 | case 0x7: | 1120 | case 0x7: |
| 1121 | if (BIT(op2, 0) == 0) | ||
| 1122 | return OP_USAT; | ||
| 1075 | if (op2 == 0x3 && a != 0xf) | 1123 | if (op2 == 0x3 && a != 0xf) |
| 1076 | return OP_UXTAH; | 1124 | return OP_UXTAH; |
| 1077 | if (op2 == 0x3 && a == 0xf) | 1125 | if (op2 == 0x3 && a == 0xf) |
diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h index 20e92fd0e..d8d4faf95 100644 --- a/src/core/arm/disassembler/arm_disasm.h +++ b/src/core/arm/disassembler/arm_disasm.h | |||
| @@ -57,6 +57,8 @@ enum Opcode { | |||
| 57 | OP_SEV, | 57 | OP_SEV, |
| 58 | OP_SMLAL, | 58 | OP_SMLAL, |
| 59 | OP_SMULL, | 59 | OP_SMULL, |
| 60 | OP_SSAT, | ||
| 61 | OP_SSAT16, | ||
| 60 | OP_STC, | 62 | OP_STC, |
| 61 | OP_STM, | 63 | OP_STM, |
| 62 | OP_STR, | 64 | OP_STR, |
| @@ -82,6 +84,8 @@ enum Opcode { | |||
| 82 | OP_TST, | 84 | OP_TST, |
| 83 | OP_UMLAL, | 85 | OP_UMLAL, |
| 84 | OP_UMULL, | 86 | OP_UMULL, |
| 87 | OP_USAT, | ||
| 88 | OP_USAT16, | ||
| 85 | OP_UXTAB, | 89 | OP_UXTAB, |
| 86 | OP_UXTAB16, | 90 | OP_UXTAB16, |
| 87 | OP_UXTAH, | 91 | OP_UXTAH, |
| @@ -171,6 +175,7 @@ class ARM_Disasm { | |||
| 171 | static std::string DisassemblePKH(uint32_t insn); | 175 | static std::string DisassemblePKH(uint32_t insn); |
| 172 | static std::string DisassemblePLD(uint32_t insn); | 176 | static std::string DisassemblePLD(uint32_t insn); |
| 173 | static std::string DisassembleREX(Opcode opcode, uint32_t insn); | 177 | static std::string DisassembleREX(Opcode opcode, uint32_t insn); |
| 178 | static std::string DisassembleSAT(Opcode opcode, uint32_t insn); | ||
| 174 | static std::string DisassembleSEL(uint32_t insn); | 179 | static std::string DisassembleSEL(uint32_t insn); |
| 175 | static std::string DisassembleSWI(uint32_t insn); | 180 | static std::string DisassembleSWI(uint32_t insn); |
| 176 | static std::string DisassembleSWP(Opcode opcode, uint32_t insn); | 181 | static std::string DisassembleSWP(Opcode opcode, uint32_t insn); |