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.direction = DIRECTION; \
230 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
231 ARM_MEMORY_POST_INCREMENT;)
232
233#define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME) \
234 COUNT_3(DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB, NAME ## IA_R, NAME, ARM_INCREMENT_AFTER, 0)
235
236DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDM)
237DEFINE_LOAD_STORE_MULTIPLE_THUMB(STM)
238
239#define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \
240 DEFINE_THUMB_DECODER(B ## COND, B, \
241 int8_t immediate = opcode; \
242 info->op1.immediate = immediate << 1; \
243 info->branches = 1; \
244 info->condition = ARM_CONDITION_ ## COND; \
245 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;)
246
247DEFINE_CONDITIONAL_BRANCH_THUMB(EQ)
248DEFINE_CONDITIONAL_BRANCH_THUMB(NE)
249DEFINE_CONDITIONAL_BRANCH_THUMB(CS)
250DEFINE_CONDITIONAL_BRANCH_THUMB(CC)
251DEFINE_CONDITIONAL_BRANCH_THUMB(MI)
252DEFINE_CONDITIONAL_BRANCH_THUMB(PL)
253DEFINE_CONDITIONAL_BRANCH_THUMB(VS)
254DEFINE_CONDITIONAL_BRANCH_THUMB(VC)
255DEFINE_CONDITIONAL_BRANCH_THUMB(LS)
256DEFINE_CONDITIONAL_BRANCH_THUMB(HI)
257DEFINE_CONDITIONAL_BRANCH_THUMB(GE)
258DEFINE_CONDITIONAL_BRANCH_THUMB(LT)
259DEFINE_CONDITIONAL_BRANCH_THUMB(GT)
260DEFINE_CONDITIONAL_BRANCH_THUMB(LE)
261
262#define DEFINE_SP_MODIFY_THUMB(NAME, MNEMONIC) \
263 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
264 info->op1.reg = ARM_SP; \
265 info->op2.immediate = (opcode & 0x7F) << 2; \
266 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
267 ARM_OPERAND_AFFECTED_1 | \
268 ARM_OPERAND_IMMEDIATE_2;)
269
270DEFINE_SP_MODIFY_THUMB(ADD7, ADD)
271DEFINE_SP_MODIFY_THUMB(SUB4, SUB)
272
273DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP, ARM_SP, LDM, ARM_INCREMENT_AFTER, 0)
274DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR, ARM_SP, LDM, ARM_INCREMENT_AFTER, 1 << ARM_PC)
275DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH, ARM_SP, STM, ARM_DECREMENT_BEFORE, 0)
276DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR, ARM_SP, STM, ARM_DECREMENT_BEFORE, 1 << ARM_LR)
277
278DEFINE_THUMB_DECODER(ILL, ILL, info->traps = 1;)
279DEFINE_THUMB_DECODER(BKPT, BKPT, info->traps = 1;)
280
281DEFINE_THUMB_DECODER(B, B,
282 int16_t immediate = (opcode & 0x07FF) << 5;
283 info->op1.immediate = (((int32_t) immediate) >> 4);
284 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
285 info->branches = 1;)
286
287DEFINE_THUMB_DECODER(BL1, BLH,
288 int16_t immediate = (opcode & 0x07FF) << 5;
289 info->op1.immediate = (((int32_t) immediate) << 7);
290 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;)
291
292DEFINE_THUMB_DECODER(BL2, BL,
293 info->op1.immediate = (opcode & 0x07FF) << 1;
294 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
295 info->branches = 1;)
296
297DEFINE_THUMB_DECODER(BX, BX,
298 info->op1.reg = (opcode >> 3) & 0xF;
299 info->operandFormat = ARM_OPERAND_REGISTER_1;
300 info->branches = 1;)
301
302DEFINE_THUMB_DECODER(SWI, SWI,
303 info->op1.immediate = opcode & 0xFF;
304 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
305 info->traps = 1;)
306
307typedef void (*ThumbDecoder)(uint16_t opcode, struct ARMInstructionInfo* info);
308
309static const ThumbDecoder _thumbDecoderTable[0x400] = {
310 DECLARE_THUMB_EMITTER_BLOCK(_ThumbDecode)
311};
312
313void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info) {
314 info->opcode = opcode;
315 info->branches = 0;
316 info->traps = 0;
317 info->affectsCPSR = 0;
318 info->condition = ARM_CONDITION_AL;
319 info->sDataCycles = 0;
320 info->nDataCycles = 0;
321 info->sInstructionCycles = 1;
322 info->nInstructionCycles = 0;
323 info->iCycles = 0;
324 info->cCycles = 0;
325 ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6];
326 decoder(opcode, info);
327}
328
329const char* armMnemonicStrings[] = {
330 "ill",
331 "adc",
332 "add",
333 "and",
334 "asr",
335 "b",
336 "bic",
337 "bkpt",
338 "bl",
339 "blh",
340 "bx",
341 "cmn",
342 "cmp",
343 "eor",
344 "ldm",
345 "ldr",
346 "lsl",
347 "lsr",
348 "mov",
349 "mul",
350 "mvn",
351 "neg",
352 "orr",
353 "ror",
354 "sbc",
355 "stm",
356 "str",
357 "sub",
358 "swi",
359 "tst"
360};
361
362const char* armDirectionStrings[] = {
363 "da",
364 "ia",
365 "db",
366 "da"
367};
368
369const char* armAccessTypeStrings[] = {
370 "",
371 "b",
372 "h",
373 "",
374 "",
375 "",
376 "",
377 "",
378 "",
379 "sb",
380 "sh",
381 ""
382 ""
383};
384
385int ARMDisassembleThumb(uint16_t opcode, uint32_t pc, char* buffer, int blen) {
386 struct ARMInstructionInfo info;
387 ARMDecodeThumb(opcode, &info);
388 const char* mnemonic = armMnemonicStrings[info.mnemonic];
389 int written;
390 int total = 0;
391 const char* cond = "";
392 if (info.condition != ARM_CONDITION_AL && info.condition < ARM_CONDITION_NV) {
393 cond = _armConditions[info.condition];
394 }
395 const char* flags = "";
396 switch (info.mnemonic) {
397 case ARM_MN_LDM:
398 case ARM_MN_STM:
399 flags = armDirectionStrings[info.memory.direction];
400 break;
401 case ARM_MN_LDR:
402 case ARM_MN_STR:
403 flags = armAccessTypeStrings[info.memory.direction];
404 break;
405 default:
406 break;
407 }
408 written = snprintf(buffer, blen - 1, "%s%s%s ", mnemonic, flags, cond);
409 ADVANCE(written);
410
411 switch (info.mnemonic) {
412 case ARM_MN_LDM:
413 case ARM_MN_STM:
414 written = _decodeRegister(info.memory.baseReg, buffer, blen);
415 ADVANCE(written);
416 strncpy(buffer, "!, ", blen - 1);
417 ADVANCE(3);
418 written = _decodeRegisterList(info.op1.immediate, buffer, blen);
419 ADVANCE(written);
420 break;
421 case ARM_MN_B:
422 written = _decodePCRelative(info.op1.immediate, pc, buffer, blen);
423 ADVANCE(written);
424 break;
425 default:
426 if (info.operandFormat & ARM_OPERAND_IMMEDIATE_1) {
427 written = snprintf(buffer, blen - 1, "#%i", info.op1.immediate);
428 ADVANCE(written);
429 } else if (info.operandFormat & ARM_OPERAND_MEMORY_1) {
430 written = _decodeMemory(info.memory, pc, buffer, blen);
431 ADVANCE(written);
432 } else if (info.operandFormat & ARM_OPERAND_REGISTER_1) {
433 written = _decodeRegister(info.op1.reg, buffer, blen);
434 ADVANCE(written);
435 }
436 if (info.operandFormat & ARM_OPERAND_2) {
437 strncpy(buffer, ", ", blen);
438 ADVANCE(2);
439 }
440 if (info.operandFormat & ARM_OPERAND_IMMEDIATE_2) {
441 written = snprintf(buffer, blen - 1, "#%i", info.op2.immediate);
442 ADVANCE(written);
443 } else if (info.operandFormat & ARM_OPERAND_MEMORY_2) {
444 written = _decodeMemory(info.memory, pc, buffer, blen);
445 ADVANCE(written);
446 } else if (info.operandFormat & ARM_OPERAND_REGISTER_2) {
447 written = _decodeRegister(info.op2.reg, buffer, blen);
448 ADVANCE(written);
449 }
450 if (info.operandFormat & ARM_OPERAND_3) {
451 strncpy(buffer, ", ", blen - 1);
452 ADVANCE(2);
453 }
454 if (info.operandFormat & ARM_OPERAND_IMMEDIATE_3) {
455 written = snprintf(buffer, blen - 1, "#%i", info.op3.immediate);
456 ADVANCE(written);
457 } else if (info.operandFormat & ARM_OPERAND_MEMORY_3) {
458 written = _decodeMemory(info.memory, pc, buffer, blen);
459 ADVANCE(written);
460 } else if (info.operandFormat & ARM_OPERAND_REGISTER_3) {
461 written = _decodeRegister(info.op1.reg, buffer, blen);
462 ADVANCE(written);
463 }
464 break;
465 }
466 buffer[blen - 1] = '\0';
467 return total;
468}