src/arm/decoder-thumb.c (view raw)
1#include "decoder.h"
2
3#include "arm.h"
4#include "decoder-inlines.h"
5#include "emitter-thumb.h"
6#include "isa-inlines.h"
7
8#include <stdio.h>
9#include <string.h>
10
11#define DEFINE_THUMB_DECODER(NAME, MNEMONIC, BODY) \
12 static void _ThumbDecode ## NAME (uint16_t opcode, struct ARMInstructionInfo* info) { \
13 UNUSED(opcode); \
14 info->mnemonic = ARM_MN_ ## MNEMONIC; \
15 BODY; \
16 }
17
18#define DEFINE_IMMEDIATE_5_DECODER_DATA_THUMB(NAME, IMMEDIATE, MNEMONIC, WIDTH) \
19 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
20 info->op3.immediate = IMMEDIATE; \
21 info->op1.reg = opcode & 0x0007; \
22 info->op2.reg = (opcode >> 3) & 0x0007; \
23 info->affectsCPSR = 1; \
24 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
25 ARM_OPERAND_AFFECTED_1 | \
26 ARM_OPERAND_REGISTER_2 | \
27 ARM_OPERAND_IMMEDIATE_3;)
28
29#define DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC, CYCLES, WIDTH) \
30 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
31 info->op1.reg = opcode & 0x0007; \
32 info->memory.baseReg = (opcode >> 3) & 0x0007; \
33 info->memory.offset.immediate = IMMEDIATE * WIDTH; \
34 info->memory.width = (enum ARMMemoryAccessType) WIDTH; \
35 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
36 ARM_OPERAND_AFFECTED_1 | \
37 ARM_OPERAND_MEMORY_2; \
38 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
39 ARM_MEMORY_IMMEDIATE_OFFSET; \
40 CYCLES)
41
42#define DEFINE_IMMEDIATE_5_DECODER_MEM_LOAD_THUMB(NAME, IMMEDIATE, MNEMONIC, WIDTH) \
43 DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC, LOAD_CYCLES, WIDTH)
44
45#define DEFINE_IMMEDIATE_5_DECODER_MEM_STORE_THUMB(NAME, IMMEDIATE, MNEMONIC, WIDTH) \
46 DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC, STORE_CYCLES, WIDTH)
47
48#define DEFINE_IMMEDIATE_5_DECODER_THUMB(NAME, MNEMONIC, TYPE, WIDTH) \
49 COUNT_5(DEFINE_IMMEDIATE_5_DECODER_ ## TYPE ## _THUMB, NAME ## _, MNEMONIC, WIDTH)
50
51DEFINE_IMMEDIATE_5_DECODER_THUMB(LSL1, LSL, DATA,)
52DEFINE_IMMEDIATE_5_DECODER_THUMB(LSR1, LSR, DATA,)
53DEFINE_IMMEDIATE_5_DECODER_THUMB(ASR1, ASR, DATA,)
54DEFINE_IMMEDIATE_5_DECODER_THUMB(LDR1, LDR, MEM_LOAD, 4)
55DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRB1, LDR, MEM_LOAD, 1)
56DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRH1, LDR, MEM_LOAD, 2)
57DEFINE_IMMEDIATE_5_DECODER_THUMB(STR1, STR, MEM_STORE, 4)
58DEFINE_IMMEDIATE_5_DECODER_THUMB(STRB1, STR, MEM_STORE, 1)
59DEFINE_IMMEDIATE_5_DECODER_THUMB(STRH1, STR, MEM_STORE, 2)
60
61#define DEFINE_DATA_FORM_1_DECODER_EX_THUMB(NAME, RM, MNEMONIC) \
62 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
63 info->op1.reg = opcode & 0x0007; \
64 info->op2.reg = (opcode >> 3) & 0x0007; \
65 info->op3.reg = RM; \
66 info->affectsCPSR = 1; \
67 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
68 ARM_OPERAND_AFFECTED_1 | \
69 ARM_OPERAND_REGISTER_2 | \
70 ARM_OPERAND_REGISTER_3;)
71
72#define DEFINE_DATA_FORM_1_DECODER_THUMB(NAME) \
73 COUNT_3(DEFINE_DATA_FORM_1_DECODER_EX_THUMB, NAME ## 3_R, NAME)
74
75DEFINE_DATA_FORM_1_DECODER_THUMB(ADD)
76DEFINE_DATA_FORM_1_DECODER_THUMB(SUB)
77
78#define DEFINE_DATA_FORM_2_DECODER_EX_THUMB(NAME, IMMEDIATE, MNEMONIC) \
79 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
80 info->op1.reg = opcode & 0x0007; \
81 info->op2.reg = (opcode >> 3) & 0x0007; \
82 info->op3.immediate = IMMEDIATE; \
83 info->affectsCPSR = 1; \
84 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
85 ARM_OPERAND_AFFECTED_1 | \
86 ARM_OPERAND_REGISTER_2 | \
87 ARM_OPERAND_IMMEDIATE_3;)
88
89#define DEFINE_DATA_FORM_2_DECODER_THUMB(NAME) \
90 COUNT_3(DEFINE_DATA_FORM_2_DECODER_EX_THUMB, NAME ## 1_, NAME)
91
92DEFINE_DATA_FORM_2_DECODER_THUMB(ADD)
93DEFINE_DATA_FORM_2_DECODER_THUMB(SUB)
94
95#define DEFINE_DATA_FORM_3_DECODER_EX_THUMB(NAME, RD, MNEMONIC, AFFECTED) \
96 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
97 info->op1.reg = RD; \
98 info->op2.immediate = opcode & 0x00FF; \
99 info->affectsCPSR = 1; \
100 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
101 AFFECTED | \
102 ARM_OPERAND_IMMEDIATE_2;)
103
104#define DEFINE_DATA_FORM_3_DECODER_THUMB(NAME, MNEMONIC, AFFECTED) \
105 COUNT_3(DEFINE_DATA_FORM_3_DECODER_EX_THUMB, NAME ## _R, MNEMONIC, AFFECTED)
106
107DEFINE_DATA_FORM_3_DECODER_THUMB(ADD2, ADD, ARM_OPERAND_AFFECTED_1)
108DEFINE_DATA_FORM_3_DECODER_THUMB(CMP1, CMP, ARM_OPERAND_NONE)
109DEFINE_DATA_FORM_3_DECODER_THUMB(MOV1, MOV, ARM_OPERAND_AFFECTED_1)
110DEFINE_DATA_FORM_3_DECODER_THUMB(SUB2, SUB, ARM_OPERAND_AFFECTED_1)
111
112#define DEFINE_DATA_FORM_5_DECODER_THUMB(NAME, MNEMONIC, AFFECTED) \
113 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
114 info->op1.reg = opcode & 0x0007; \
115 info->op2.reg = (opcode >> 3) & 0x0007; \
116 info->affectsCPSR = 1; \
117 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
118 AFFECTED | \
119 ARM_OPERAND_REGISTER_2;)
120
121DEFINE_DATA_FORM_5_DECODER_THUMB(AND, AND, ARM_OPERAND_AFFECTED_1)
122DEFINE_DATA_FORM_5_DECODER_THUMB(EOR, EOR, ARM_OPERAND_AFFECTED_1)
123DEFINE_DATA_FORM_5_DECODER_THUMB(LSL2, LSL, ARM_OPERAND_AFFECTED_1)
124DEFINE_DATA_FORM_5_DECODER_THUMB(LSR2, LSR, ARM_OPERAND_AFFECTED_1)
125DEFINE_DATA_FORM_5_DECODER_THUMB(ASR2, ASR, ARM_OPERAND_AFFECTED_1)
126DEFINE_DATA_FORM_5_DECODER_THUMB(ADC, ADC, ARM_OPERAND_AFFECTED_1)
127DEFINE_DATA_FORM_5_DECODER_THUMB(SBC, SBC, ARM_OPERAND_AFFECTED_1)
128DEFINE_DATA_FORM_5_DECODER_THUMB(ROR, ROR, ARM_OPERAND_AFFECTED_1)
129DEFINE_DATA_FORM_5_DECODER_THUMB(TST, TST, ARM_OPERAND_NONE)
130DEFINE_DATA_FORM_5_DECODER_THUMB(NEG, NEG, ARM_OPERAND_AFFECTED_1)
131DEFINE_DATA_FORM_5_DECODER_THUMB(CMP2, CMP, ARM_OPERAND_NONE)
132DEFINE_DATA_FORM_5_DECODER_THUMB(CMN, CMN, ARM_OPERAND_NONE)
133DEFINE_DATA_FORM_5_DECODER_THUMB(ORR, ORR, ARM_OPERAND_AFFECTED_1)
134DEFINE_DATA_FORM_5_DECODER_THUMB(MUL, MUL, ARM_OPERAND_AFFECTED_1)
135DEFINE_DATA_FORM_5_DECODER_THUMB(BIC, BIC, ARM_OPERAND_AFFECTED_1)
136DEFINE_DATA_FORM_5_DECODER_THUMB(MVN, MVN, ARM_OPERAND_AFFECTED_1)
137
138#define DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME, H1, H2, MNEMONIC, AFFECTED, CPSR) \
139 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
140 info->op1.reg = (opcode & 0x0007) | H1; \
141 info->op2.reg = ((opcode >> 3) & 0x0007) | H2; \
142 info->branches = info->op1.reg == ARM_PC; \
143 info->affectsCPSR = CPSR; \
144 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
145 AFFECTED | \
146 ARM_OPERAND_REGISTER_2;)
147
148
149#define DEFINE_DECODER_WITH_HIGH_THUMB(NAME, MNEMONIC, AFFECTED, CPSR) \
150 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 00, 0, 0, MNEMONIC, AFFECTED, CPSR) \
151 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 01, 0, 8, MNEMONIC, AFFECTED, CPSR) \
152 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 10, 8, 0, MNEMONIC, AFFECTED, CPSR) \
153 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 11, 8, 8, MNEMONIC, AFFECTED, CPSR)
154
155DEFINE_DECODER_WITH_HIGH_THUMB(ADD4, ADD, ARM_OPERAND_AFFECTED_1, 0)
156DEFINE_DECODER_WITH_HIGH_THUMB(CMP3, CMP, ARM_OPERAND_NONE, 1)
157DEFINE_DECODER_WITH_HIGH_THUMB(MOV3, MOV, ARM_OPERAND_AFFECTED_1, 0)
158
159#define DEFINE_IMMEDIATE_WITH_REGISTER_DATA_THUMB(NAME, RD, MNEMONIC, REG) \
160 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
161 info->op1.reg = RD; \
162 info->op2.reg = REG; \
163 info->op3.immediate = (opcode & 0x00FF) << 2; \
164 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
165 ARM_OPERAND_AFFECTED_1 | \
166 ARM_OPERAND_REGISTER_2 | \
167 ARM_OPERAND_IMMEDIATE_3;)
168
169#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, CYCLES) \
170 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
171 info->op1.reg = RD; \
172 info->memory.baseReg = REG; \
173 info->memory.offset.immediate = (opcode & 0x00FF) << 2; \
174 info->memory.width = ARM_ACCESS_WORD; \
175 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
176 ARM_OPERAND_AFFECTED_1 | \
177 ARM_OPERAND_MEMORY_2; \
178 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
179 ARM_MEMORY_IMMEDIATE_OFFSET; \
180 CYCLES;)
181
182#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_LOAD_THUMB(NAME, RD, MNEMONIC, REG) \
183 DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, LOAD_CYCLES)
184
185#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_STORE_THUMB(NAME, RD, MNEMONIC, REG) \
186 DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, STORE_CYCLES)
187
188#define DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(NAME, MNEMONIC, TYPE, REG) \
189 COUNT_3(DEFINE_IMMEDIATE_WITH_REGISTER_ ## TYPE ## _THUMB, NAME ## _R, MNEMONIC, REG)
190
191DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR3, LDR, MEM_LOAD, ARM_PC)
192DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR4, LDR, MEM_LOAD, ARM_SP)
193DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(STR3, STR, MEM_STORE, ARM_SP)
194
195DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD5, ADD, DATA, ARM_PC)
196DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD6, ADD, DATA, ARM_SP)
197
198#define DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB(NAME, RM, MNEMONIC, CYCLES, TYPE) \
199 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
200 info->memory.offset.reg = RM; \
201 info->op1.reg = opcode & 0x0007; \
202 info->memory.baseReg = (opcode >> 3) & 0x0007; \
203 info->memory.width = TYPE; \
204 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
205 ARM_OPERAND_AFFECTED_1 | \
206 ARM_OPERAND_MEMORY_2; \
207 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
208 ARM_MEMORY_REGISTER_OFFSET; \
209 CYCLES;)
210
211#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, MNEMONIC, CYCLES, TYPE) \
212 COUNT_3(DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB, NAME ## _R, MNEMONIC, CYCLES, TYPE)
213
214DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, LDR, LOAD_CYCLES, ARM_ACCESS_WORD)
215DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, LDR, LOAD_CYCLES, ARM_ACCESS_BYTE)
216DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, LDR, LOAD_CYCLES, ARM_ACCESS_HALFWORD)
217DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_BYTE)
218DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_HALFWORD)
219DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, STR, STORE_CYCLES, ARM_ACCESS_WORD)
220DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, STR, STORE_CYCLES, ARM_ACCESS_BYTE)
221DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, STR, STORE_CYCLES, ARM_ACCESS_HALFWORD)
222
223#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, MNEMONIC, DIRECTION, ADDITIONAL_REG) \
224 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
225 info->memory.baseReg = RN; \
226 info->op1.immediate = (opcode & 0xFF) | ADDITIONAL_REG; \
227 info->branches = info->op1.immediate & (1 << ARM_PC); \
228 info->operandFormat = ARM_OPERAND_MEMORY_1; \
229 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
230 ARM_MEMORY_POST_INCREMENT | DIRECTION;)
231
232#define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME) \
233 COUNT_3(DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB, NAME ## IA_R, NAME, ARM_MEMORY_INCREMENT_AFTER, 0)
234
235DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDM)
236DEFINE_LOAD_STORE_MULTIPLE_THUMB(STM)
237
238#define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \
239 DEFINE_THUMB_DECODER(B ## COND, B, \
240 int8_t immediate = opcode; \
241 info->op1.immediate = immediate << 1; \
242 info->branches = 1; \
243 info->condition = ARM_CONDITION_ ## COND; \
244 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;)
245
246DEFINE_CONDITIONAL_BRANCH_THUMB(EQ)
247DEFINE_CONDITIONAL_BRANCH_THUMB(NE)
248DEFINE_CONDITIONAL_BRANCH_THUMB(CS)
249DEFINE_CONDITIONAL_BRANCH_THUMB(CC)
250DEFINE_CONDITIONAL_BRANCH_THUMB(MI)
251DEFINE_CONDITIONAL_BRANCH_THUMB(PL)
252DEFINE_CONDITIONAL_BRANCH_THUMB(VS)
253DEFINE_CONDITIONAL_BRANCH_THUMB(VC)
254DEFINE_CONDITIONAL_BRANCH_THUMB(LS)
255DEFINE_CONDITIONAL_BRANCH_THUMB(HI)
256DEFINE_CONDITIONAL_BRANCH_THUMB(GE)
257DEFINE_CONDITIONAL_BRANCH_THUMB(LT)
258DEFINE_CONDITIONAL_BRANCH_THUMB(GT)
259DEFINE_CONDITIONAL_BRANCH_THUMB(LE)
260
261#define DEFINE_SP_MODIFY_THUMB(NAME, MNEMONIC) \
262 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
263 info->op1.reg = ARM_SP; \
264 info->op2.immediate = (opcode & 0x7F) << 2; \
265 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
266 ARM_OPERAND_AFFECTED_1 | \
267 ARM_OPERAND_IMMEDIATE_2;)
268
269DEFINE_SP_MODIFY_THUMB(ADD7, ADD)
270DEFINE_SP_MODIFY_THUMB(SUB4, SUB)
271
272DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 0)
273DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 1 << ARM_PC)
274DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, 0)
275DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, 1 << ARM_LR)
276
277DEFINE_THUMB_DECODER(ILL, ILL, info->traps = 1;)
278DEFINE_THUMB_DECODER(BKPT, BKPT, info->traps = 1;)
279
280DEFINE_THUMB_DECODER(B, B,
281 int16_t immediate = (opcode & 0x07FF) << 5;
282 info->op1.immediate = (((int32_t) immediate) >> 4);
283 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
284 info->branches = 1;)
285
286DEFINE_THUMB_DECODER(BL1, BLH,
287 int16_t immediate = (opcode & 0x07FF) << 5;
288 info->op1.immediate = (((int32_t) immediate) << 7);
289 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;)
290
291DEFINE_THUMB_DECODER(BL2, BL,
292 info->op1.immediate = (opcode & 0x07FF) << 1;
293 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
294 info->branches = 1;)
295
296DEFINE_THUMB_DECODER(BX, BX,
297 info->op1.reg = (opcode >> 3) & 0xF;
298 info->operandFormat = ARM_OPERAND_REGISTER_1;
299 info->branches = 1;)
300
301DEFINE_THUMB_DECODER(SWI, SWI,
302 info->op1.immediate = opcode & 0xFF;
303 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
304 info->traps = 1;)
305
306typedef void (*ThumbDecoder)(uint16_t opcode, struct ARMInstructionInfo* info);
307
308static const ThumbDecoder _thumbDecoderTable[0x400] = {
309 DECLARE_THUMB_EMITTER_BLOCK(_ThumbDecode)
310};
311
312void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info) {
313 info->opcode = opcode;
314 info->branches = 0;
315 info->traps = 0;
316 info->affectsCPSR = 0;
317 info->condition = ARM_CONDITION_AL;
318 info->sDataCycles = 0;
319 info->nDataCycles = 0;
320 info->sInstructionCycles = 1;
321 info->nInstructionCycles = 0;
322 info->iCycles = 0;
323 info->cCycles = 0;
324 ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6];
325 decoder(opcode, info);
326}
327
328const char* armMnemonicStrings[] = {
329 "ill",
330 "adc",
331 "add",
332 "and",
333 "asr",
334 "b",
335 "bic",
336 "bkpt",
337 "bl",
338 "blh",
339 "bx",
340 "cmn",
341 "cmp",
342 "eor",
343 "ldm",
344 "ldr",
345 "lsl",
346 "lsr",
347 "mov",
348 "mul",
349 "mvn",
350 "neg",
351 "orr",
352 "ror",
353 "sbc",
354 "stm",
355 "str",
356 "sub",
357 "swi",
358 "tst"
359};
360
361const char* armDirectionStrings[] = {
362 "da",
363 "ia",
364 "db",
365 "da"
366};
367
368const char* armAccessTypeStrings[] = {
369 "",
370 "b",
371 "h",
372 "",
373 "",
374 "",
375 "",
376 "",
377 "",
378 "sb",
379 "sh",
380 ""
381 ""
382};
383
384int ARMDisassembleThumb(uint16_t opcode, uint32_t pc, char* buffer, int blen) {
385 struct ARMInstructionInfo info;
386 ARMDecodeThumb(opcode, &info);
387 const char* mnemonic = armMnemonicStrings[info.mnemonic];
388 int written;
389 int total = 0;
390 const char* cond = "";
391 if (info.condition != ARM_CONDITION_AL && info.condition < ARM_CONDITION_NV) {
392 cond = _armConditions[info.condition];
393 }
394 const char* flags = "";
395 switch (info.mnemonic) {
396 case ARM_MN_LDM:
397 case ARM_MN_STM:
398 flags = armDirectionStrings[MEMORY_FORMAT_TO_DIRECTION(info.memory.format)];
399 break;
400 case ARM_MN_LDR:
401 case ARM_MN_STR:
402 flags = armAccessTypeStrings[info.memory.width];
403 break;
404 default:
405 break;
406 }
407 written = snprintf(buffer, blen - 1, "%s%s%s ", mnemonic, flags, cond);
408 ADVANCE(written);
409
410 switch (info.mnemonic) {
411 case ARM_MN_LDM:
412 case ARM_MN_STM:
413 written = _decodeRegister(info.memory.baseReg, buffer, blen);
414 ADVANCE(written);
415 strncpy(buffer, "!, ", blen - 1);
416 ADVANCE(3);
417 written = _decodeRegisterList(info.op1.immediate, buffer, blen);
418 ADVANCE(written);
419 break;
420 case ARM_MN_B:
421 written = _decodePCRelative(info.op1.immediate, pc, buffer, blen);
422 ADVANCE(written);
423 break;
424 default:
425 if (info.operandFormat & ARM_OPERAND_IMMEDIATE_1) {
426 written = snprintf(buffer, blen - 1, "#%i", info.op1.immediate);
427 ADVANCE(written);
428 } else if (info.operandFormat & ARM_OPERAND_MEMORY_1) {
429 written = _decodeMemory(info.memory, pc, buffer, blen);
430 ADVANCE(written);
431 } else if (info.operandFormat & ARM_OPERAND_REGISTER_1) {
432 written = _decodeRegister(info.op1.reg, buffer, blen);
433 ADVANCE(written);
434 }
435 if (info.operandFormat & ARM_OPERAND_2) {
436 strncpy(buffer, ", ", blen);
437 ADVANCE(2);
438 }
439 if (info.operandFormat & ARM_OPERAND_IMMEDIATE_2) {
440 written = snprintf(buffer, blen - 1, "#%i", info.op2.immediate);
441 ADVANCE(written);
442 } else if (info.operandFormat & ARM_OPERAND_MEMORY_2) {
443 written = _decodeMemory(info.memory, pc, buffer, blen);
444 ADVANCE(written);
445 } else if (info.operandFormat & ARM_OPERAND_REGISTER_2) {
446 written = _decodeRegister(info.op2.reg, buffer, blen);
447 ADVANCE(written);
448 }
449 if (info.operandFormat & ARM_OPERAND_3) {
450 strncpy(buffer, ", ", blen - 1);
451 ADVANCE(2);
452 }
453 if (info.operandFormat & ARM_OPERAND_IMMEDIATE_3) {
454 written = snprintf(buffer, blen - 1, "#%i", info.op3.immediate);
455 ADVANCE(written);
456 } else if (info.operandFormat & ARM_OPERAND_MEMORY_3) {
457 written = _decodeMemory(info.memory, pc, buffer, blen);
458 ADVANCE(written);
459 } else if (info.operandFormat & ARM_OPERAND_REGISTER_3) {
460 written = _decodeRegister(info.op1.reg, buffer, blen);
461 ADVANCE(written);
462 }
463 break;
464 }
465 buffer[blen - 1] = '\0';
466 return total;
467}