| 183 | /// general shapes they are special cases of, or they decode as those instead. |
| 184 | EKittyInsnTypeArm32 decodeInsnType(uint32_t instr) |
| 185 | { |
| 186 | // cond == 0b1111 is not a condition at all: it marks the unconditional |
| 187 | // instruction space (BLX immediate, PLD, RFE, and the whole of Advanced |
| 188 | // SIMD). Those encodings are unrelated to the ones decoded below, so |
| 189 | // decoding them with the same masks produced pure fiction - `vqsub.u8` |
| 190 | // read as MOVT, `rfeia` as POP_PC, and BLX's halfword-offset form read as |
| 191 | // BL with a target two bytes off. |
| 192 | if (bits(instr, 31, 28) == 0xF) |
| 193 | return EKittyInsnTypeArm32::UNKNOWN; |
| 194 | |
| 195 | // Bit 25 means opposite things either side of bits 27-26: in |
| 196 | // data-processing it selects an *immediate* operand, in load/store it |
| 197 | // selects a *register* offset. Named for the bit rather than for either |
| 198 | // meaning, so neither reading can be misapplied to the other space. |
| 199 | const bool bBit25 = bit(instr, 25); |
| 200 | |
| 201 | // Bits 27-26 == 00 is shared between data-processing, the multiplies and |
| 202 | // the "extra load/store" (halfword / doubleword / signed) encodings. Bit |
| 203 | // 4 and bit 7 are what separate them: with a register operand and both |
| 204 | // set, this is not data-processing at all. Without that test |
| 205 | // `STRH R0,[R0],-R6` and `UMULL` both decoded as ADD, and the |
| 206 | // destination register then received a fabricated address. |
| 207 | const bool bExtraSpace = !bBit25 && bit(instr, 4) && bit(instr, 7); |
| 208 | |
| 209 | if ((instr & 0x0C000000) == 0x00000000 && !bExtraSpace) |
| 210 | { |
| 211 | // Against PC these are ADR, and the register form is its own type: |
| 212 | // its target needs Rm, so nothing here can resolve it. |
| 213 | const bool bAgainstPc = bits(instr, 19, 16) == 15; |
| 214 | const bool bAdrReg = bAgainstPc && !bBit25; |
| 215 | |