src/arm/decoder-thumb.c (view raw)
1#include "decoder.h"
2
3#include "arm.h"
4#include "emitter-thumb.h"
5#include "isa-inlines.h"
6
7#include <stdio.h>
8#include <string.h>
9
10#define DEFINE_THUMB_DECODER(NAME, MNEMONIC, BODY) \
11 static void _ThumbDecode ## NAME (uint16_t opcode, struct ThumbInstructionInfo* info) { \
12 UNUSED(opcode); \
13 info->mnemonic = THUMB_MN_ ## MNEMONIC; \
14 BODY; \
15 }
16
17#define DEFINE_IMMEDIATE_5_DECODER_DATA_THUMB(NAME, IMMEDIATE, MNEMONIC) \
18 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
19 info->op3.immediate = IMMEDIATE; \
20 info->op1.reg = opcode & 0x0007; \
21 info->op2.reg = (opcode >> 3) & 0x0007; \
22 info->affectsCPSR = 1; \
23 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
24 ARM_OPERAND_AFFECTED_1 | \
25 ARM_OPERAND_REGISTER_2 | \
26 ARM_OPERAND_IMMEDIATE_3;)
27
28#define DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC) \
29 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
30 info->op1.reg = opcode & 0x0007; \
31 info->memory.baseReg = (opcode >> 3) & 0x0007; \
32 info->memory.offset.immediate = IMMEDIATE << 2; \
33 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
34 ARM_OPERAND_AFFECTED_1 | \
35 ARM_OPERAND_MEMORY_2; \
36 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
37 ARM_MEMORY_IMMEDIATE_OFFSET;)
38
39#define DEFINE_IMMEDIATE_5_DECODER_THUMB(NAME, MNEMONIC, TYPE) \
40 COUNT_5(DEFINE_IMMEDIATE_5_DECODER_ ## TYPE ## _THUMB, NAME ## _, MNEMONIC)
41
42DEFINE_IMMEDIATE_5_DECODER_THUMB(LSL1, LSL, DATA)
43DEFINE_IMMEDIATE_5_DECODER_THUMB(LSR1, LSR, DATA)
44DEFINE_IMMEDIATE_5_DECODER_THUMB(ASR1, ASR, DATA)
45DEFINE_IMMEDIATE_5_DECODER_THUMB(LDR1, LDR, MEM)
46DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRB1, LDRB, MEM)
47DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRH1, LDRH, MEM)
48DEFINE_IMMEDIATE_5_DECODER_THUMB(STR1, STR, MEM)
49DEFINE_IMMEDIATE_5_DECODER_THUMB(STRB1, STRB, MEM)
50DEFINE_IMMEDIATE_5_DECODER_THUMB(STRH1, STRH, MEM)
51
52#define DEFINE_DATA_FORM_1_DECODER_EX_THUMB(NAME, RM, MNEMONIC) \
53 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
54 info->op1.reg = opcode & 0x0007; \
55 info->op2.reg = (opcode >> 3) & 0x0007; \
56 info->op3.reg = RM; \
57 info->affectsCPSR = 1; \
58 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
59 ARM_OPERAND_AFFECTED_1 | \
60 ARM_OPERAND_REGISTER_2 | \
61 ARM_OPERAND_REGISTER_3;)
62
63#define DEFINE_DATA_FORM_1_DECODER_THUMB(NAME) \
64 COUNT_3(DEFINE_DATA_FORM_1_DECODER_EX_THUMB, NAME ## 3_R, NAME)
65
66DEFINE_DATA_FORM_1_DECODER_THUMB(ADD)
67DEFINE_DATA_FORM_1_DECODER_THUMB(SUB)
68
69#define DEFINE_DATA_FORM_2_DECODER_EX_THUMB(NAME, IMMEDIATE, MNEMONIC) \
70 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
71 info->op1.reg = opcode & 0x0007; \
72 info->op2.reg = (opcode >> 3) & 0x0007; \
73 info->op3.immediate = IMMEDIATE; \
74 info->affectsCPSR = 1; \
75 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
76 ARM_OPERAND_AFFECTED_1 | \
77 ARM_OPERAND_REGISTER_2 | \
78 ARM_OPERAND_IMMEDIATE_3;)
79
80#define DEFINE_DATA_FORM_2_DECODER_THUMB(NAME) \
81 COUNT_3(DEFINE_DATA_FORM_2_DECODER_EX_THUMB, NAME ## 1_, NAME)
82
83DEFINE_DATA_FORM_2_DECODER_THUMB(ADD)
84DEFINE_DATA_FORM_2_DECODER_THUMB(SUB)
85
86#define DEFINE_DATA_FORM_3_DECODER_EX_THUMB(NAME, RD, MNEMONIC, AFFECTED) \
87 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
88 info->op1.reg = RD; \
89 info->op2.immediate = opcode & 0x00FF; \
90 info->affectsCPSR = 1; \
91 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
92 AFFECTED | \
93 ARM_OPERAND_IMMEDIATE_2;)
94
95#define DEFINE_DATA_FORM_3_DECODER_THUMB(NAME, MNEMONIC, AFFECTED) \
96 COUNT_3(DEFINE_DATA_FORM_3_DECODER_EX_THUMB, NAME ## _R, MNEMONIC, AFFECTED)
97
98DEFINE_DATA_FORM_3_DECODER_THUMB(ADD2, ADD, ARM_OPERAND_AFFECTED_1)
99DEFINE_DATA_FORM_3_DECODER_THUMB(CMP1, CMP, ARM_OPERAND_NONE)
100DEFINE_DATA_FORM_3_DECODER_THUMB(MOV1, MOV, ARM_OPERAND_AFFECTED_1)
101DEFINE_DATA_FORM_3_DECODER_THUMB(SUB2, SUB, ARM_OPERAND_AFFECTED_1)
102
103#define DEFINE_DATA_FORM_5_DECODER_THUMB(NAME, MNEMONIC, AFFECTED) \
104 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
105 info->op1.reg = opcode & 0x0007; \
106 info->op2.reg = (opcode >> 3) & 0x0007; \
107 info->affectsCPSR = 1; \
108 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
109 AFFECTED | \
110 ARM_OPERAND_REGISTER_2;)
111
112DEFINE_DATA_FORM_5_DECODER_THUMB(AND, AND, ARM_OPERAND_AFFECTED_1)
113DEFINE_DATA_FORM_5_DECODER_THUMB(EOR, EOR, ARM_OPERAND_AFFECTED_1)
114DEFINE_DATA_FORM_5_DECODER_THUMB(LSL2, LSL, ARM_OPERAND_AFFECTED_1)
115DEFINE_DATA_FORM_5_DECODER_THUMB(LSR2, LSR, ARM_OPERAND_AFFECTED_1)
116DEFINE_DATA_FORM_5_DECODER_THUMB(ASR2, ASR, ARM_OPERAND_AFFECTED_1)
117DEFINE_DATA_FORM_5_DECODER_THUMB(ADC, ADC, ARM_OPERAND_AFFECTED_1)
118DEFINE_DATA_FORM_5_DECODER_THUMB(SBC, SBC, ARM_OPERAND_AFFECTED_1)
119DEFINE_DATA_FORM_5_DECODER_THUMB(ROR, ROR, ARM_OPERAND_AFFECTED_1)
120DEFINE_DATA_FORM_5_DECODER_THUMB(TST, TST, ARM_OPERAND_AFFECTED_1)
121DEFINE_DATA_FORM_5_DECODER_THUMB(NEG, NEG, ARM_OPERAND_AFFECTED_1)
122DEFINE_DATA_FORM_5_DECODER_THUMB(CMP2, CMP, ARM_OPERAND_NONE)
123DEFINE_DATA_FORM_5_DECODER_THUMB(CMN, CMN, ARM_OPERAND_NONE)
124DEFINE_DATA_FORM_5_DECODER_THUMB(ORR, ORR, ARM_OPERAND_AFFECTED_1)
125DEFINE_DATA_FORM_5_DECODER_THUMB(MUL, MUL, ARM_OPERAND_AFFECTED_1)
126DEFINE_DATA_FORM_5_DECODER_THUMB(BIC, BIC, ARM_OPERAND_AFFECTED_1)
127DEFINE_DATA_FORM_5_DECODER_THUMB(MVN, MVN, ARM_OPERAND_AFFECTED_1)
128
129#define DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME, H1, H2, MNEMONIC, AFFECTED, CPSR) \
130 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
131 info->op1.reg = (opcode & 0x0007) | H1; \
132 info->op2.reg = ((opcode >> 3) & 0x0007) | H2; \
133 info->accessesSpecialRegisters = info->op1.reg > 12 || info->op2.reg > 12; \
134 info->affectsCPSR = CPSR; \
135 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
136 AFFECTED | \
137 ARM_OPERAND_REGISTER_2;)
138
139
140#define DEFINE_DECODER_WITH_HIGH_THUMB(NAME, MNEMONIC, AFFECTED, CPSR) \
141 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 00, 0, 0, MNEMONIC, AFFECTED, CPSR) \
142 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 01, 0, 8, MNEMONIC, AFFECTED, CPSR) \
143 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 10, 8, 0, MNEMONIC, AFFECTED, CPSR) \
144 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 11, 8, 8, MNEMONIC, AFFECTED, CPSR)
145
146DEFINE_DECODER_WITH_HIGH_THUMB(ADD4, ADD, ARM_OPERAND_AFFECTED_1, 0)
147DEFINE_DECODER_WITH_HIGH_THUMB(CMP3, CMP, ARM_OPERAND_NONE, 1)
148DEFINE_DECODER_WITH_HIGH_THUMB(MOV3, MOV, ARM_OPERAND_AFFECTED_1, 0)
149
150#define DEFINE_IMMEDIATE_WITH_REGISTER_DATA_THUMB(NAME, RD, MNEMONIC, REG) \
151 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
152 info->op1.reg = RD; \
153 info->op2.reg = REG; \
154 info->op3.immediate = (opcode & 0x00FF) << 2; \
155 info->accessesSpecialRegisters = 1; \
156 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
157 ARM_OPERAND_AFFECTED_1 | \
158 ARM_OPERAND_REGISTER_2 | \
159 ARM_OPERAND_IMMEDIATE_3;)
160
161#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG) \
162 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
163 info->op1.reg = RD; \
164 info->memory.baseReg = REG; \
165 info->memory.offset.immediate = (opcode & 0x00FF) << 2; \
166 info->accessesSpecialRegisters = 1; \
167 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
168 ARM_OPERAND_AFFECTED_1 | \
169 ARM_OPERAND_MEMORY_2; \
170 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
171 ARM_MEMORY_IMMEDIATE_OFFSET;)
172
173#define DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(NAME, MNEMONIC, TYPE, REG) \
174 COUNT_3(DEFINE_IMMEDIATE_WITH_REGISTER_ ## TYPE ## _THUMB, NAME ## _R, MNEMONIC, REG)
175
176DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR3, LDR, MEM, ARM_PC)
177DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR4, LDR, MEM, ARM_SP)
178DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(STR3, STR, MEM, ARM_SP)
179
180DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD5, ADD, DATA, ARM_PC)
181DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD6, ADD, DATA, ARM_SP)
182
183#define DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB(NAME, RM, MNEMONIC) \
184 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
185 info->memory.offset.reg = RM; \
186 info->op1.reg = opcode & 0x0007; \
187 info->memory.baseReg = (opcode >> 3) & 0x0007; \
188 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
189 ARM_OPERAND_AFFECTED_1 | \
190 ARM_OPERAND_MEMORY_2; \
191 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
192 ARM_MEMORY_REGISTER_OFFSET;)
193
194#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, MNEMONIC) \
195 COUNT_3(DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB, NAME ## _R, MNEMONIC)
196
197DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, LDR)
198DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, LDRB)
199DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, LDRH)
200DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, LDRSB)
201DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, LDRSH)
202DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, STR)
203DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, STRB)
204DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, STRH)
205
206#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, MNEMONIC, SPECIAL_REG, ADDITIONAL_REG) \
207 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
208 info->memory.baseReg = RN; \
209 info->accessesSpecialRegisters = SPECIAL_REG; \
210 info->op1.immediate = (opcode & 0xFF) | ADDITIONAL_REG; \
211 info->operandFormat = ARM_OPERAND_IMMEDIATE_1; \
212 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
213 ARM_MEMORY_POST_INCREMENT;)
214
215#define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME) \
216 COUNT_3(DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB, NAME ## _R, NAME, 0, 0)
217
218DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDMIA)
219DEFINE_LOAD_STORE_MULTIPLE_THUMB(STMIA)
220
221#define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \
222 DEFINE_THUMB_DECODER(B ## COND, B, \
223 int8_t immediate = opcode; \
224 info->op1.immediate = immediate << 1; \
225 info->branches = 1; \
226 info->condition = ARM_CONDITION_ ## COND; \
227 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;)
228
229DEFINE_CONDITIONAL_BRANCH_THUMB(EQ)
230DEFINE_CONDITIONAL_BRANCH_THUMB(NE)
231DEFINE_CONDITIONAL_BRANCH_THUMB(CS)
232DEFINE_CONDITIONAL_BRANCH_THUMB(CC)
233DEFINE_CONDITIONAL_BRANCH_THUMB(MI)
234DEFINE_CONDITIONAL_BRANCH_THUMB(PL)
235DEFINE_CONDITIONAL_BRANCH_THUMB(VS)
236DEFINE_CONDITIONAL_BRANCH_THUMB(VC)
237DEFINE_CONDITIONAL_BRANCH_THUMB(LS)
238DEFINE_CONDITIONAL_BRANCH_THUMB(HI)
239DEFINE_CONDITIONAL_BRANCH_THUMB(GE)
240DEFINE_CONDITIONAL_BRANCH_THUMB(LT)
241DEFINE_CONDITIONAL_BRANCH_THUMB(GT)
242DEFINE_CONDITIONAL_BRANCH_THUMB(LE)
243
244#define DEFINE_SP_MODIFY_THUMB(NAME, MNEMONIC) \
245 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
246 info->op1.reg = ARM_SP; \
247 info->op2.immediate = (opcode & 0x7F) << 2; \
248 info->accessesSpecialRegisters = 1; \
249 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
250 ARM_OPERAND_AFFECTED_1 | \
251 ARM_OPERAND_IMMEDIATE_2;)
252
253DEFINE_SP_MODIFY_THUMB(ADD7, ADD)
254DEFINE_SP_MODIFY_THUMB(SUB4, SUB)
255
256DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP, ARM_SP, POP, 1, 0)
257DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR, ARM_SP, POP, 1, 1 << ARM_PC)
258DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH, ARM_SP, PUSH, 1, 0)
259DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR, ARM_SP, PUSH, 1, 1 << ARM_LR)
260
261DEFINE_THUMB_DECODER(ILL, ILL, info->traps = 1;)
262DEFINE_THUMB_DECODER(BKPT, BKPT, info->traps = 1;)
263
264DEFINE_THUMB_DECODER(B, B,
265 int16_t immediate = (opcode & 0x07FF) << 5;
266 info->op1.immediate = (((int32_t) immediate) >> 4);
267 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
268 info->branches = 1;)
269
270DEFINE_THUMB_DECODER(BL1, BLH,
271 int16_t immediate = (opcode & 0x07FF) << 5;
272 info->op1.immediate = (((int32_t) immediate) << 7);
273 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
274 info->accessesSpecialRegisters = 1;)
275
276DEFINE_THUMB_DECODER(BL2, BL,
277 info->op1.immediate = (opcode & 0x07FF) << 1;
278 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
279 info->accessesSpecialRegisters = 1;
280 info->branches = 1;)
281
282DEFINE_THUMB_DECODER(BX, BX,
283 info->op1.reg = (opcode >> 3) & 0xF;
284 info->operandFormat = ARM_OPERAND_REGISTER_1;
285 info->branches = 1;)
286
287DEFINE_THUMB_DECODER(SWI, SWI,
288 info->op1.immediate = opcode & 0xFF;
289 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
290 info->traps = 1;)
291
292typedef void (*ThumbDecoder)(uint16_t opcode, struct ThumbInstructionInfo* info);
293
294static const ThumbDecoder _thumbDecoderTable[0x400] = {
295 DECLARE_THUMB_EMITTER_BLOCK(_ThumbDecode)
296};
297
298void ARMDecodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info) {
299 info->opcode = opcode;
300 info->branches = 0;
301 info->traps = 0;
302 info->accessesSpecialRegisters = 0;
303 info->affectsCPSR = 0;
304 info->condition = ARM_CONDITION_AL;
305 ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6];
306 decoder(opcode, info);
307}
308
309#define ADVANCE(AMOUNT) \
310 if (AMOUNT > blen) { \
311 buffer[blen - 1] = '\0'; \
312 return total; \
313 } \
314 total += AMOUNT; \
315 buffer += AMOUNT; \
316 blen -= AMOUNT;
317
318static int _decodeRegister(int reg, char* buffer, int blen) {
319 switch (reg) {
320 case ARM_SP:
321 strncpy(buffer, "sp", blen);
322 return 2;
323 case ARM_LR:
324 strncpy(buffer, "lr", blen);
325 return 2;
326 case ARM_PC:
327 strncpy(buffer, "pc", blen);
328 return 2;
329 default:
330 return snprintf(buffer, blen, "r%i", reg);
331 }
332}
333
334static int _decodeRegisterList(int list, char* buffer, int blen) {
335 if (blen <= 0) {
336 return 0;
337 }
338 int total = 0;
339 strncpy(buffer, "{", blen);
340 ADVANCE(1);
341 int i;
342 int start = -1;
343 int end = -1;
344 int written;
345 printf("%x\n", list);
346 for (i = 0; i <= ARM_PC; ++i) {
347 if (list & 1) {
348 if (start < 0) {
349 start = i;
350 end = i;
351 } else if (end + 1 == i) {
352 end = i;
353 } else {
354 if (end > start) {
355 written = _decodeRegister(start, buffer, blen);
356 ADVANCE(written);
357 strncpy(buffer, "-", blen);
358 ADVANCE(1);
359 }
360 written = _decodeRegister(end, buffer, blen);
361 ADVANCE(written);
362 strncpy(buffer, ",", blen);
363 ADVANCE(1);
364 start = i;
365 end = i;
366 }
367 }
368 list >>= 1;
369 }
370 if (start >= 0) {
371 if (end > start) {
372 written = _decodeRegister(start, buffer, blen);
373 ADVANCE(written);
374 strncpy(buffer, "-", blen);
375 ADVANCE(1);
376 }
377 written = _decodeRegister(end, buffer, blen);
378 ADVANCE(written);
379 }
380 strncpy(buffer, "}", blen);
381 ADVANCE(1);
382 return total;
383}
384
385static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen) {
386 return snprintf(buffer, blen, "$%08X", address + pc);
387}
388
389static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen) {
390 if (blen <= 0) {
391 return 0;
392 }
393 int total = 0;
394 strncpy(buffer, "[", blen);
395 ADVANCE(1);
396 int written;
397 if (memory.format & ARM_MEMORY_REGISTER_BASE) {
398 if (memory.baseReg == ARM_PC && memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
399 written = _decodePCRelative(memory.offset.immediate, pc, buffer, blen);
400 ADVANCE(written);
401 } else {
402 written = _decodeRegister(memory.baseReg, buffer, blen);
403 ADVANCE(written);
404 if (memory.format & (ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_IMMEDIATE_OFFSET) && !(memory.format & ARM_MEMORY_POST_INCREMENT)) {
405 strncpy(buffer, ", ", blen);
406 ADVANCE(2);
407 }
408 }
409 }
410 if (memory.format & ARM_MEMORY_POST_INCREMENT) {
411 strncpy(buffer, "], ", blen);
412 ADVANCE(3);
413 }
414 if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) {
415 if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
416 written = snprintf(buffer, blen, "#-%i", memory.offset.immediate);
417 ADVANCE(written);
418 } else {
419 written = snprintf(buffer, blen, "#%i", memory.offset.immediate);
420 ADVANCE(written);
421 }
422 } else if (memory.format & ARM_MEMORY_REGISTER_OFFSET) {
423 if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
424 strncpy(buffer, "-", blen);
425 ADVANCE(1);
426 }
427 written = _decodeRegister(memory.offset.reg, buffer, blen);
428 ADVANCE(written);
429 }
430 // TODO: shifted registers
431
432 if (!(memory.format & ARM_MEMORY_POST_INCREMENT)) {
433 strncpy(buffer, "]", blen);
434 ADVANCE(1);
435 }
436 if (memory.format & ARM_MEMORY_PRE_INCREMENT) {
437 strncpy(buffer, "!", blen);
438 ADVANCE(1);
439 }
440 return total;
441}
442
443static const char* _armConditions[] = {
444 "eq",
445 "ne",
446 "cs",
447 "cc",
448 "mi",
449 "pl",
450 "vs",
451 "vc",
452 "hi",
453 "ls",
454 "ge",
455 "lt",
456 "gt",
457 "le",
458 "al",
459 "nv"
460};
461
462static const char* _thumbMnemonicStrings[] = {
463 "ill",
464 "adc",
465 "add",
466 "and",
467 "asr",
468 "b",
469 "bic",
470 "bkpt",
471 "bl",
472 "blh",
473 "bx",
474 "cmn",
475 "cmp",
476 "eor",
477 "ldmia",
478 "ldr",
479 "ldrb",
480 "ldrh",
481 "ldrsb",
482 "ldrsh",
483 "lsl",
484 "lsr",
485 "mov",
486 "mul",
487 "mvn",
488 "neg",
489 "orr",
490 "pop",
491 "push",
492 "ror",
493 "sbc",
494 "stmia",
495 "str",
496 "strb",
497 "strh",
498 "sub",
499 "swi",
500 "tst"
501};
502
503int ARMDisassembleThumb(uint16_t opcode, uint32_t pc, char* buffer, int blen) {
504 struct ThumbInstructionInfo info;
505 ARMDecodeThumb(opcode, &info);
506 const char* mnemonic = _thumbMnemonicStrings[info.mnemonic];
507 int written;
508 int total = 0;
509 const char* cond = "";
510 if (info.condition != ARM_CONDITION_AL && info.condition < ARM_CONDITION_NV) {
511 cond = _armConditions[info.condition];
512 }
513 written = snprintf(buffer, blen, "%s%s ", mnemonic, cond);
514 ADVANCE(written);
515
516 switch (info.mnemonic) {
517 case THUMB_MN_LDMIA:
518 case THUMB_MN_STMIA:
519 written = _decodeRegister(info.memory.baseReg, buffer, blen);
520 ADVANCE(written);
521 strncpy(buffer, "!, ", blen);
522 ADVANCE(3);
523 // Fall through
524 case THUMB_MN_POP:
525 case THUMB_MN_PUSH:
526 written = _decodeRegisterList(info.op1.immediate, buffer, blen);
527 ADVANCE(written);
528 break;
529 case THUMB_MN_B:
530 written = _decodePCRelative(info.op1.immediate, pc, buffer, blen);
531 ADVANCE(written);
532 break;
533 default:
534 if (info.operandFormat & ARM_OPERAND_IMMEDIATE_1) {
535 written = snprintf(buffer, blen, "#%i", info.op1.immediate);
536 ADVANCE(written);
537 } else if (info.operandFormat & ARM_OPERAND_MEMORY_1) {
538 written = _decodeMemory(info.memory, pc, buffer, blen);
539 ADVANCE(written);
540 } else if (info.operandFormat & ARM_OPERAND_REGISTER_1) {
541 written = _decodeRegister(info.op1.reg, buffer, blen);
542 ADVANCE(written);
543 }
544 if (info.operandFormat & ARM_OPERAND_2) {
545 strncpy(buffer, ", ", blen);
546 ADVANCE(2);
547 }
548 if (info.operandFormat & ARM_OPERAND_IMMEDIATE_2) {
549 written = snprintf(buffer, blen, "#%i", info.op2.immediate);
550 ADVANCE(written);
551 } else if (info.operandFormat & ARM_OPERAND_MEMORY_2) {
552 written = _decodeMemory(info.memory, pc, buffer, blen);
553 ADVANCE(written);
554 } else if (info.operandFormat & ARM_OPERAND_REGISTER_2) {
555 written = _decodeRegister(info.op2.reg, buffer, blen);
556 ADVANCE(written);
557 }
558 if (info.operandFormat & ARM_OPERAND_3) {
559 strncpy(buffer, ", ", blen);
560 ADVANCE(2);
561 }
562 if (info.operandFormat & ARM_OPERAND_IMMEDIATE_3) {
563 written = snprintf(buffer, blen, "#%i", info.op3.immediate);
564 ADVANCE(written);
565 } else if (info.operandFormat & ARM_OPERAND_MEMORY_3) {
566 written = _decodeMemory(info.memory, pc, buffer, blen);
567 ADVANCE(written);
568 } else if (info.operandFormat & ARM_OPERAND_REGISTER_3) {
569 written = _decodeRegister(info.op1.reg, buffer, blen);
570 ADVANCE(written);
571 }
572 break;
573 }
574 buffer[total] = '\0';
575 return total;
576}