src/arm/decoder.c (view raw)
1#include "decoder.h"
2
3#include "decoder-inlines.h"
4
5#define ADVANCE(AMOUNT) \
6 if (AMOUNT > blen) { \
7 buffer[blen - 1] = '\0'; \
8 return total; \
9 } \
10 total += AMOUNT; \
11 buffer += AMOUNT; \
12 blen -= AMOUNT;
13
14static int _decodeRegister(int reg, char* buffer, int blen);
15static int _decodeRegisterList(int list, char* buffer, int blen);
16static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen);
17static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen);
18static int _decodeShift(union ARMOperand operand, bool reg, char* buffer, int blen);
19
20static const char* _armConditions[] = {
21 "eq",
22 "ne",
23 "cs",
24 "cc",
25 "mi",
26 "pl",
27 "vs",
28 "vc",
29 "hi",
30 "ls",
31 "ge",
32 "lt",
33 "gt",
34 "le",
35 "al",
36 "nv"
37};
38
39static int _decodeRegister(int reg, char* buffer, int blen) {
40 switch (reg) {
41 case ARM_SP:
42 strncpy(buffer, "sp", blen - 1);
43 return 2;
44 case ARM_LR:
45 strncpy(buffer, "lr", blen - 1);
46 return 2;
47 case ARM_PC:
48 strncpy(buffer, "pc", blen - 1);
49 return 2;
50 case ARM_CPSR:
51 strncpy(buffer, "cpsr", blen - 1);
52 return 4;
53 case ARM_SPSR:
54 strncpy(buffer, "spsr", blen - 1);
55 return 4;
56 default:
57 return snprintf(buffer, blen - 1, "r%i", reg);
58 }
59}
60
61static int _decodeRegisterList(int list, char* buffer, int blen) {
62 if (blen <= 0) {
63 return 0;
64 }
65 int total = 0;
66 strncpy(buffer, "{", blen - 1);
67 ADVANCE(1);
68 int i;
69 int start = -1;
70 int end = -1;
71 int written;
72 for (i = 0; i <= ARM_PC; ++i) {
73 if (list & 1) {
74 if (start < 0) {
75 start = i;
76 end = i;
77 } else if (end + 1 == i) {
78 end = i;
79 } else {
80 if (end > start) {
81 written = _decodeRegister(start, buffer, blen);
82 ADVANCE(written);
83 strncpy(buffer, "-", blen - 1);
84 ADVANCE(1);
85 }
86 written = _decodeRegister(end, buffer, blen);
87 ADVANCE(written);
88 strncpy(buffer, ",", blen - 1);
89 ADVANCE(1);
90 start = i;
91 end = i;
92 }
93 }
94 list >>= 1;
95 }
96 if (start >= 0) {
97 if (end > start) {
98 written = _decodeRegister(start, buffer, blen);
99 ADVANCE(written);
100 strncpy(buffer, "-", blen - 1);
101 ADVANCE(1);
102 }
103 written = _decodeRegister(end, buffer, blen);
104 ADVANCE(written);
105 }
106 strncpy(buffer, "}", blen - 1);
107 ADVANCE(1);
108 return total;
109}
110
111static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen) {
112 return snprintf(buffer, blen - 1, "$%08X", address + pc);
113}
114
115static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen) {
116 if (blen <= 1) {
117 return 0;
118 }
119 int total = 0;
120 strncpy(buffer, "[", blen - 1);
121 ADVANCE(1);
122 int written;
123 if (memory.format & ARM_MEMORY_REGISTER_BASE) {
124 if (memory.baseReg == ARM_PC && memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
125 written = _decodePCRelative(memory.offset.immediate, pc, buffer, blen);
126 ADVANCE(written);
127 } else {
128 written = _decodeRegister(memory.baseReg, buffer, blen);
129 ADVANCE(written);
130 if (memory.format & (ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_IMMEDIATE_OFFSET) && !(memory.format & ARM_MEMORY_POST_INCREMENT)) {
131 strncpy(buffer, ", ", blen - 1);
132 ADVANCE(2);
133 }
134 }
135 }
136 if (memory.format & ARM_MEMORY_POST_INCREMENT) {
137 strncpy(buffer, "], ", blen - 1);
138 ADVANCE(3);
139 }
140 if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) {
141 if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
142 written = snprintf(buffer, blen - 1, "#-%i", memory.offset.immediate);
143 ADVANCE(written);
144 } else {
145 written = snprintf(buffer, blen - 1, "#%i", memory.offset.immediate);
146 ADVANCE(written);
147 }
148 } else if (memory.format & ARM_MEMORY_REGISTER_OFFSET) {
149 if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
150 strncpy(buffer, "-", blen - 1);
151 ADVANCE(1);
152 }
153 written = _decodeRegister(memory.offset.reg, buffer, blen);
154 ADVANCE(written);
155 }
156 if (memory.format & ARM_MEMORY_SHIFTED_OFFSET) {
157 written = _decodeShift(memory.offset, false, buffer, blen);
158 ADVANCE(written);
159 }
160
161 if (!(memory.format & ARM_MEMORY_POST_INCREMENT)) {
162 strncpy(buffer, "]", blen - 1);
163 ADVANCE(1);
164 }
165 if ((memory.format & (ARM_MEMORY_PRE_INCREMENT | ARM_MEMORY_WRITEBACK)) == (ARM_MEMORY_PRE_INCREMENT | ARM_MEMORY_WRITEBACK)) {
166 strncpy(buffer, "!", blen - 1);
167 ADVANCE(1);
168 }
169 return total;
170}
171
172static int _decodeShift(union ARMOperand op, bool reg, char* buffer, int blen) {
173 if (blen <= 1) {
174 return 0;
175 }
176 int total = 0;
177 strncpy(buffer, ", ", blen - 1);
178 ADVANCE(2);
179 int written;
180 switch (op.shifterOp) {
181 case ARM_SHIFT_LSL:
182 strncpy(buffer, "lsl ", blen - 1);
183 ADVANCE(4);
184 break;
185 case ARM_SHIFT_LSR:
186 strncpy(buffer, "lsr ", blen - 1);
187 ADVANCE(4);
188 break;
189 case ARM_SHIFT_ASR:
190 strncpy(buffer, "asr ", blen - 1);
191 ADVANCE(4);
192 break;
193 case ARM_SHIFT_ROR:
194 strncpy(buffer, "ror ", blen - 1);
195 ADVANCE(4);
196 break;
197 case ARM_SHIFT_RRX:
198 strncpy(buffer, "rrx", blen - 1);
199 ADVANCE(3);
200 return total;
201 }
202 if (!reg) {
203 written = snprintf(buffer, blen - 1, "#%i", op.shifterImm);
204 } else {
205 written = _decodeRegister(op.shifterReg, buffer, blen);
206 }
207 ADVANCE(written);
208 return total;
209}
210
211static const char* _armMnemonicStrings[] = {
212 "ill",
213 "adc",
214 "add",
215 "and",
216 "asr",
217 "b",
218 "bic",
219 "bkpt",
220 "bl",
221 "blh",
222 "bx",
223 "cmn",
224 "cmp",
225 "eor",
226 "ldm",
227 "ldr",
228 "lsl",
229 "lsr",
230 "mla",
231 "mov",
232 "mrs",
233 "msr",
234 "mul",
235 "mvn",
236 "neg",
237 "orr",
238 "ror",
239 "rsb",
240 "rsc",
241 "sbc",
242 "smlal",
243 "smull",
244 "stm",
245 "str",
246 "sub",
247 "swi",
248 "swp",
249 "teq",
250 "tst",
251 "umlal",
252 "umull",
253
254 "ill"
255};
256
257static const char* _armDirectionStrings[] = {
258 "da",
259 "ia",
260 "db",
261 "ib"
262};
263
264static const char* _armAccessTypeStrings[] = {
265 "",
266 "b",
267 "h",
268 "",
269 "",
270 "",
271 "",
272 "",
273
274 "",
275 "sb",
276 "sh",
277 "",
278 "",
279 "",
280 "",
281 "",
282
283 "",
284 "bt",
285 "",
286 "",
287 "t",
288 "",
289 "",
290 ""
291};
292
293int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, int blen) {
294 const char* mnemonic = _armMnemonicStrings[info->mnemonic];
295 int written;
296 int total = 0;
297 const char* cond = "";
298 if (info->condition != ARM_CONDITION_AL && info->condition < ARM_CONDITION_NV) {
299 cond = _armConditions[info->condition];
300 }
301 const char* flags = "";
302 switch (info->mnemonic) {
303 case ARM_MN_LDM:
304 case ARM_MN_STM:
305 flags = _armDirectionStrings[MEMORY_FORMAT_TO_DIRECTION(info->memory.format)];
306 break;
307 case ARM_MN_LDR:
308 case ARM_MN_STR:
309 case ARM_MN_SWP:
310 flags = _armAccessTypeStrings[info->memory.width];
311 break;
312 case ARM_MN_ADD:
313 case ARM_MN_ADC:
314 case ARM_MN_AND:
315 case ARM_MN_BIC:
316 case ARM_MN_EOR:
317 case ARM_MN_MOV:
318 case ARM_MN_MVN:
319 case ARM_MN_ORR:
320 case ARM_MN_RSB:
321 case ARM_MN_RSC:
322 case ARM_MN_SBC:
323 case ARM_MN_SUB:
324 if (info->affectsCPSR && info->execMode == MODE_ARM) {
325 flags = "s";
326 }
327 break;
328 default:
329 break;
330 }
331 written = snprintf(buffer, blen - 1, "%s%s%s ", mnemonic, cond, flags);
332 ADVANCE(written);
333
334 switch (info->mnemonic) {
335 case ARM_MN_LDM:
336 case ARM_MN_STM:
337 written = _decodeRegister(info->memory.baseReg, buffer, blen);
338 ADVANCE(written);
339 if (info->memory.format & ARM_MEMORY_WRITEBACK) {
340 strncpy(buffer, "!", blen - 1);
341 ADVANCE(1);
342 }
343 strncpy(buffer, ", ", blen - 1);
344 ADVANCE(2);
345 written = _decodeRegisterList(info->op1.immediate, buffer, blen);
346 ADVANCE(written);
347 if (info->memory.format & ARM_MEMORY_SPSR_SWAP) {
348 strncpy(buffer, "^", blen - 1);
349 ADVANCE(1);
350 }
351 break;
352 case ARM_MN_B:
353 written = _decodePCRelative(info->op1.immediate, pc, buffer, blen);
354 ADVANCE(written);
355 break;
356 default:
357 if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) {
358 written = snprintf(buffer, blen - 1, "#%i", info->op1.immediate);
359 ADVANCE(written);
360 } else if (info->operandFormat & ARM_OPERAND_MEMORY_1) {
361 written = _decodeMemory(info->memory, pc, buffer, blen);
362 ADVANCE(written);
363 } else if (info->operandFormat & ARM_OPERAND_REGISTER_1) {
364 written = _decodeRegister(info->op1.reg, buffer, blen);
365 ADVANCE(written);
366 }
367 if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_1) {
368 written = _decodeShift(info->op1, true, buffer, blen);
369 ADVANCE(written);
370 } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_1) {
371 written = _decodeShift(info->op1, false, buffer, blen);
372 ADVANCE(written);
373 }
374 if (info->operandFormat & ARM_OPERAND_2) {
375 strncpy(buffer, ", ", blen);
376 ADVANCE(2);
377 }
378 if (info->operandFormat & ARM_OPERAND_IMMEDIATE_2) {
379 written = snprintf(buffer, blen - 1, "#%i", info->op2.immediate);
380 ADVANCE(written);
381 } else if (info->operandFormat & ARM_OPERAND_MEMORY_2) {
382 written = _decodeMemory(info->memory, pc, buffer, blen);
383 ADVANCE(written);
384 } else if (info->operandFormat & ARM_OPERAND_REGISTER_2) {
385 written = _decodeRegister(info->op2.reg, buffer, blen);
386 ADVANCE(written);
387 }
388 if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_2) {
389 written = _decodeShift(info->op2, true, buffer, blen);
390 ADVANCE(written);
391 } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_2) {
392 written = _decodeShift(info->op2, false, buffer, blen);
393 ADVANCE(written);
394 }
395 if (info->operandFormat & ARM_OPERAND_3) {
396 strncpy(buffer, ", ", blen - 1);
397 ADVANCE(2);
398 }
399 if (info->operandFormat & ARM_OPERAND_IMMEDIATE_3) {
400 written = snprintf(buffer, blen - 1, "#%i", info->op3.immediate);
401 ADVANCE(written);
402 } else if (info->operandFormat & ARM_OPERAND_MEMORY_3) {
403 written = _decodeMemory(info->memory, pc, buffer, blen);
404 ADVANCE(written);
405 } else if (info->operandFormat & ARM_OPERAND_REGISTER_3) {
406 written = _decodeRegister(info->op3.reg, buffer, blen);
407 ADVANCE(written);
408 }
409 if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_3) {
410 written = _decodeShift(info->op3, true, buffer, blen);
411 ADVANCE(written);
412 } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_3) {
413 written = _decodeShift(info->op3, false, buffer, blen);
414 ADVANCE(written);
415 }
416 if (info->operandFormat & ARM_OPERAND_4) {
417 strncpy(buffer, ", ", blen - 1);
418 ADVANCE(2);
419 }
420 if (info->operandFormat & ARM_OPERAND_IMMEDIATE_4) {
421 written = snprintf(buffer, blen - 1, "#%i", info->op4.immediate);
422 ADVANCE(written);
423 } else if (info->operandFormat & ARM_OPERAND_MEMORY_4) {
424 written = _decodeMemory(info->memory, pc, buffer, blen);
425 ADVANCE(written);
426 } else if (info->operandFormat & ARM_OPERAND_REGISTER_4) {
427 written = _decodeRegister(info->op4.reg, buffer, blen);
428 ADVANCE(written);
429 }
430 if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_4) {
431 written = _decodeShift(info->op4, true, buffer, blen);
432 ADVANCE(written);
433 } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_4) {
434 written = _decodeShift(info->op4, false, buffer, blen);
435 ADVANCE(written);
436 }
437 break;
438 }
439 buffer[blen - 1] = '\0';
440 return total;
441}