| 79 | } |
| 80 | |
| 81 | KittyInsnArm32 decodeInsn(uint32_t instr, uint32_t address) |
| 82 | { |
| 83 | KittyInsnArm32 insn{}; |
| 84 | |
| 85 | EKittyInsnTypeArm32 insn_type = decodeInsnType(instr); |
| 86 | if (insn_type == EKittyInsnTypeArm32::UNKNOWN) |
| 87 | return insn; |
| 88 | |
| 89 | insn.bytes = instr; |
| 90 | insn.address = address; |
| 91 | insn.type = insn_type; |
| 92 | insn.typeStr = typeToString(insn_type); |
| 93 | |
| 94 | switch (insn_type) |
| 95 | { |
| 96 | case EKittyInsnTypeArm32::UNKNOWN: |
| 97 | return insn; |
| 98 | |
| 99 | case EKittyInsnTypeArm32::ADD: |
| 100 | case EKittyInsnTypeArm32::SUB: |
| 101 | case EKittyInsnTypeArm32::MOV: |
| 102 | case EKittyInsnTypeArm32::ADR: |
| 103 | { |
| 104 | bool I = bit(instr, 25); |
| 105 | uint32_t rn = bits(instr, 19, 16); |
| 106 | uint32_t rd = bits(instr, 15, 12); |
| 107 | uint32_t imm12 = bits(instr, 11, 0); |
| 108 | uint32_t imm8 = bits(imm12, 7, 0); |
| 109 | uint32_t rot = bits(imm12, 11, 8) * 2u; |
| 110 | uint32_t imm32 = ror32(imm8, rot); |
| 111 | insn.rd = regName(rd); |
| 112 | |
| 113 | if (insn_type != EKittyInsnTypeArm32::MOV) |
| 114 | insn.rn = regName(rn); |
| 115 | |
| 116 | if (!I) |
| 117 | insn.rt = regName(imm12); |
| 118 | else |
| 119 | insn.immediate = I ? imm32 : 0; |
| 120 | |
| 121 | if (rn == 15) |
| 122 | insn.target = address + 8u + insn.immediate; |
| 123 | |
| 124 | break; |
| 125 | } |
| 126 | |
| 127 | case EKittyInsnTypeArm32::LDRH: |
| 128 | case EKittyInsnTypeArm32::LDRSH: |
| 129 | case EKittyInsnTypeArm32::LDRSB: |
| 130 | case EKittyInsnTypeArm32::STRH: |
| 131 | { |
| 132 | bool U = bit(instr, 23); |
| 133 | uint32_t rn = bits(instr, 19, 16); |
| 134 | uint32_t rd = bits(instr, 15, 12); |
| 135 | uint32_t immH = bits(instr, 11, 8); |
| 136 | uint32_t immL = bits(instr, 3, 0); |
| 137 | uint32_t offset = (immH << 4) | immL; |
| 138 | insn.rd = regName(rd); |
nothing calls this directly
no test coverage detected