filename | src/aica/armdasm.c |
changeset | 813:262efed79218 |
prev | 811:7ff871670e58 |
next | 998:1754a8c6a9cf |
author | nkeynes |
date | Mon Oct 06 01:05:12 2008 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Move bundle/system paths into paths.c, install lxdreamrc into the bundle (Fix OSX bundle missing default configuration) |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * armdasm.c 21 Aug 2004 - ARM7tdmi (ARMv4) disassembler
5 *
6 * Copyright (c) 2005 Nathan Keynes.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #include "aica/armcore.h"
20 #include "aica/armdasm.h"
21 #include <stdlib.h>
23 #define COND(ir) (ir>>28)
24 #define OPCODE(ir) ((ir>>20)&0x1F)
25 #define GRP(ir) ((ir>>26)&0x03)
26 #define IFLAG(ir) (ir&0x02000000)
27 #define SFLAG(ir) (ir&0x00100000)
28 #define PFLAG(ir) (ir&0x01000000)
29 #define UFLAG(ir) (ir&0x00800000)
30 #define BFLAG(ir) (ir&0x00400000)
31 #define WFLAG(ir) (ir&0x00200000)
32 #define LFLAG(ir) SFLAG(ir)
33 #define RN(ir) ((ir>>16)&0x0F)
34 #define RD(ir) ((ir>>12)&0x0F)
35 #define RS(ir) ((ir>>8)&0x0F)
36 #define RM(ir) (ir&0x0F)
38 #define IMM8(ir) (ir&0xFF)
39 #define IMM12(ir) (ir&0xFFF)
40 #define IMMSPLIT8(ir) (((ir&0xF00)>>4)|(ir&0x0F))
41 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
42 #define IMMROT(ir) ((ir>>7)&0x1E)
43 #define SHIFT(ir) ((ir>>4)&0x07)
44 #define DISP24(ir) ((ir&0x00FFFFFF))
45 #define FSXC(ir) msrFieldMask[RN(ir)]
46 #define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
47 #define SIGNEXT24(n) (((n)&0x00800000) ? ((n)|0xFF000000) : ((n)&0x00FFFFFF))
51 const struct reg_desc_struct arm_reg_map[] =
52 { {"R0", REG_INT, &armr.r[0]}, {"R1", REG_INT, &armr.r[1]},
53 {"R2", REG_INT, &armr.r[2]}, {"R3", REG_INT, &armr.r[3]},
54 {"R4", REG_INT, &armr.r[4]}, {"R5", REG_INT, &armr.r[5]},
55 {"R6", REG_INT, &armr.r[6]}, {"R7", REG_INT, &armr.r[7]},
56 {"R8", REG_INT, &armr.r[8]}, {"R9", REG_INT, &armr.r[9]},
57 {"R10",REG_INT, &armr.r[10]}, {"R11",REG_INT, &armr.r[11]},
58 {"R12",REG_INT, &armr.r[12]}, {"R13",REG_INT, &armr.r[13]},
59 {"R14",REG_INT, &armr.r[14]}, {"R15",REG_INT, &armr.r[15]},
60 {"CPSR", REG_INT, &armr.cpsr}, {"SPSR", REG_INT, &armr.spsr},
61 {NULL, 0, NULL} };
64 const struct cpu_desc_struct arm_cpu_desc =
65 { "ARM7", arm_disasm_instruction, arm_execute_instruction, arm_has_page,
66 arm_set_breakpoint, arm_clear_breakpoint, arm_get_breakpoint, 4,
67 (char *)&armr, sizeof(armr), arm_reg_map,
68 &armr.r[15] };
69 const struct cpu_desc_struct armt_cpu_desc =
70 { "ARM7T", armt_disasm_instruction, arm_execute_instruction, arm_has_page,
71 arm_set_breakpoint, arm_clear_breakpoint, arm_get_breakpoint, 2,
72 (char*)&armr, sizeof(armr), arm_reg_map,
73 &armr.r[15] };
78 char *conditionNames[] = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
79 "HI", "LS", "GE", "LT", "GT", "LE", " " /*AL*/, "NV" };
81 /* fsxc */
82 char *msrFieldMask[] = { "", "c", "x", "xc", "s", "sc", "sx", "sxc",
83 "f", "fc", "fx", "fxc", "fs", "fsc", "fsx", "fsxc" };
84 char *ldmModes[] = { "DA", "IA", "DB", "IB" };
86 #define UNIMP(ir) snprintf( buf, len, "??? " )
88 int arm_disasm_shift_operand( uint32_t ir, char *buf, int len )
89 {
90 uint32_t operand, tmp;
91 if( IFLAG(ir) == 0 ) {
92 switch(SHIFT(ir)) {
93 case 0: /* (Rm << imm) */
94 tmp = SHIFTIMM(ir);
95 if( tmp != 0 ) {
96 return snprintf(buf, len, "R%d << %d", RM(ir), tmp );
97 } else {
98 return snprintf(buf, len, "R%d", RM(ir));
99 }
100 case 1: /* (Rm << Rs) */
101 return snprintf(buf, len, "R%d << R%d", RM(ir), RS(ir) );
102 case 2: /* (Rm >> imm) */
103 return snprintf(buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
104 case 3: /* (Rm >> Rs) */
105 return snprintf(buf, len, "R%d >> R%d", RM(ir), RS(ir) );
106 case 4: /* (Rm >>> imm) */
107 return snprintf(buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
108 case 5: /* (Rm >>> Rs) */
109 return snprintf(buf, len, "R%d >>> R%d", RM(ir), RS(ir) );
110 case 6:
111 tmp = SHIFTIMM(ir);
112 if( tmp == 0 ) /* RRX aka rotate with carry */
113 return snprintf(buf, len, "R%d roc 1", RM(ir) );
114 else
115 return snprintf(buf, len, "R%d rot %d", RM(ir), SHIFTIMM(ir) );
116 case 7:
117 return snprintf(buf, len, "R%d rot R%d", RM(ir), RS(ir) );
118 }
119 } else {
120 operand = IMM8(ir);
121 tmp = IMMROT(ir);
122 operand = ROTATE_RIGHT_LONG(operand, tmp);
123 return snprintf(buf, len, "#%08Xh", operand );
124 }
125 return 0;
126 }
128 static int arm_disasm_address_index( uint32_t ir, char *buf, int len )
129 {
130 uint32_t tmp;
132 switch(SHIFT(ir)) {
133 case 0: /* (Rm << imm) */
134 tmp = SHIFTIMM(ir);
135 if( tmp != 0 ) {
136 return snprintf( buf, len, "R%d << %d", RM(ir), tmp );
137 } else {
138 return snprintf( buf, len, "R%d", RM(ir) );
139 }
140 case 2: /* (Rm >> imm) */
141 return snprintf( buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
142 case 4: /* (Rm >>> imm) */
143 return snprintf( buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
144 case 6:
145 tmp = SHIFTIMM(ir);
146 if( tmp == 0 ) /* RRX aka rotate with carry */
147 return snprintf( buf, len, "R%d roc 1", RM(ir) );
148 else
149 return snprintf( buf, len, "R%d rot %d", RM(ir), tmp );
150 default:
151 return UNIMP(ir);
152 }
153 }
155 static int arm_disasm_address_operand( uint32_t ir, char *buf, int len, int pc )
156 {
157 char shift[32];
159 char sign = UFLAG(ir) ? '+' : '-';
160 /* I P U . W */
161 switch( (ir>>21)&0x19 ) {
162 case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
163 case 1:
164 return snprintf( buf, len, "[R%d], R%d %c= #%04Xh", RN(ir), RN(ir), sign, IMM12(ir) );
165 case 8: /* Rn - imm offset [5.2.2 A5-20] */
166 if( RN(ir) == 15 ) { /* PC relative - decode here */
167 uint32_t addr = pc + 8 + (UFLAG(ir) ? IMM12(ir) : -IMM12(ir));
168 return snprintf( buf, len, "[$%08Xh] <- #%08Xh", addr,
169 arm_read_long( addr ) );
170 } else {
171 return snprintf( buf, len, "[R%d %c #%04Xh]", RN(ir), sign, IMM12(ir) );
172 }
173 case 9: /* Rn -= imm offset (pre-indexed) [5.2.5 A5-24] */
174 return snprintf( buf, len, "[R%d %c= #%04Xh]", RN(ir), sign, IMM12(ir) );
175 case 16: /* Rn -= Rm (post-indexed) [5.2.10 A5-32 ] */
176 case 17:
177 arm_disasm_address_index( ir, shift, sizeof(shift) );
178 return snprintf( buf, len, "[R%d], R%d %c= %s", RN(ir), RN(ir), sign, shift );
179 case 24: /* Rn - Rm [5.2.4 A5-23] */
180 arm_disasm_address_index( ir, shift, sizeof(shift) );
181 return snprintf( buf, len, "[R%d %c %s]", RN(ir), sign, shift );
182 case 25: /* RN -= Rm (pre-indexed) [5.2.7 A5-26] */
183 arm_disasm_address_index( ir, shift, sizeof(shift) );
184 return snprintf( buf, len, "[R%d %c= %s]", RN(ir), sign, shift );
185 default:
186 return UNIMP(ir); /* Unreachable */
187 }
188 }
190 static int arm_disasm_address3_operand( uint32_t ir, char *buf, int len, int pc )
191 {
192 char sign = UFLAG(ir) ? '+' : '-';
194 switch( (ir>>21) & 0x0B) {
195 case 0: /* Rn -= Rm (post-indexed) [5.3.7 A5-48] */
196 case 1: /* UNPREDICTABLE */
197 return snprintf( buf, len, "[R%d], R%d %c= R%d", RN(ir), RN(ir), sign, RM(ir) ) ;
198 case 2: /* Rn -= imm (post-indexed) [5.3.6 A5-46] */
199 case 3: /* UNPREDICTABLE */
200 return snprintf( buf, len, "[R%d], R%d %c= #%04Xh", RN(ir), RN(ir), sign, IMMSPLIT8(ir) );
201 case 8: /* Rn - Rm [5.3.3 A5-38] */
202 return snprintf( buf, len, "[R%d %c R%d]", RN(ir), sign, RM(ir) );
203 case 9: /* Rn -= Rm (pre-indexed) [5.3.5 A5-42] */
204 return snprintf( buf, len, "[R%d %c= R%d]", RN(ir), sign, RM(ir) );
205 case 10: /* Rn - imm offset [5.3.2 A5-36] */
206 return snprintf( buf, len, "[R%d %c #%04Xh]", RN(ir), sign, IMMSPLIT8(ir) );
207 case 11: /* Rn -= imm offset (pre-indexed) [5.3.4 A5-40] */
208 return snprintf( buf, len, "[R%d %c= #%04Xh]", RN(ir), sign, IMMSPLIT8(ir) );
209 default:
210 return UNIMP(ir); /* Unreachable */
211 }
212 }
214 uint32_t arm_disasm_instruction( uint32_t pc, char *buf, int len, char *opcode )
215 {
216 char operand[64];
217 uint32_t ir = arm_read_long(pc);
218 int i,j;
220 sprintf( opcode, "%08X", ir );
222 if( COND(ir) == 0x0F ) {
223 UNIMP(ir);
224 return pc+4;
225 }
226 char *cond = conditionNames[COND(ir)];
228 switch( GRP(ir) ) {
229 case 0:
230 if( (ir & 0x0D900000) == 0x01000000 ) {
231 /* Instructions that aren't actual data processing */
232 switch( ir & 0x0FF000F0 ) {
233 case 0x01200010: /* BXcc */
234 snprintf(buf, len, "BX%s R%d", cond, RM(ir));
235 break;
236 case 0x01000000: /* MRS Rd, CPSR */
237 snprintf(buf, len, "MRS%s R%d, CPSR", cond, RD(ir));
238 break;
239 case 0x01400000: /* MRS Rd, SPSR */
240 snprintf(buf, len, "MRS%s R%d, SPSR", cond, RD(ir));
241 break;
242 case 0x01200000: /* MSR CPSR, Rm */
243 snprintf(buf, len, "MSR%s CPSR_%s, R%d", cond, FSXC(ir), RM(ir));
244 break;
245 case 0x01600000: /* MSR SPSR, Rm */
246 snprintf(buf, len, "MSR%s SPSR_%s, R%d", cond, FSXC(ir), RM(ir));
247 break;
248 case 0x03200000: /* MSR CPSR, imm */
249 snprintf(buf, len, "MSR%s CPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
250 break;
251 case 0x03600000: /* MSR SPSR, imm */
252 snprintf(buf, len, "MSR%s SPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
253 break;
254 default:
255 UNIMP();
256 }
257 } else if( (ir & 0x0E000090) == 0x00000090 ) {
258 /* Neither are these */
259 switch( (ir>>5)&0x03 ) {
260 case 0:
261 /* Arithmetic extension area */
262 switch(OPCODE(ir)) {
263 case 0: /* MUL */
264 snprintf(buf,len, "MUL%s R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir) );
265 break;
266 case 1: /* MULS */
267 break;
268 case 2: /* MLA */
269 snprintf(buf,len, "MLA%s R%d, R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir), RD(ir) );
270 break;
271 case 3: /* MLAS */
272 break;
273 case 8: /* UMULL */
274 snprintf(buf,len, "UMULL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
275 break;
276 case 9: /* UMULLS */
277 break;
278 case 10: /* UMLAL */
279 snprintf(buf,len, "UMLAL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
280 break;
281 case 11: /* UMLALS */
282 break;
283 case 12: /* SMULL */
284 snprintf(buf,len, "SMULL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
285 break;
286 case 13: /* SMULLS */
287 break;
288 case 14: /* SMLAL */
289 snprintf(buf,len, "SMLAL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
290 break;
291 case 15: /* SMLALS */
293 break;
294 case 16: /* SWP */
295 snprintf(buf,len, "SWP%s R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
296 break;
297 case 20: /* SWPB */
298 snprintf(buf,len, "SWPB%s R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
299 break;
300 default:
301 UNIMP(ir);
302 }
303 break;
304 case 1:
305 arm_disasm_address3_operand( ir, operand, sizeof(operand), pc );
306 if( LFLAG(ir) ) { /* LDRH */
307 snprintf(buf, len, "LDR%sH R%d, %s", cond, RD(ir), operand );
308 } else { /* STRH */
309 snprintf(buf, len, "STR%sH R%d, %s", cond, RD(ir), operand );
310 }
311 break;
312 case 2:
313 if( LFLAG(ir) ) { /* LDRSB */
314 arm_disasm_address3_operand( ir, operand, sizeof(operand), pc );
315 snprintf(buf, len, "LDR%sSB R%d, %s", cond, RD(ir), operand );
316 } else {
317 UNIMP(ir);
318 }
319 break;
320 case 3:
321 if( LFLAG(ir) ) { /* LDRSH */
322 arm_disasm_address3_operand( ir, operand, sizeof(operand), pc );
323 snprintf(buf, len, "LDR%sSH R%d, %s", cond, RD(ir), operand );
324 } else {
325 UNIMP(ir);
326 }
327 break;
328 }
329 } else {
330 /* Data processing */
332 switch(OPCODE(ir)) {
333 case 0: /* AND Rd, Rn, operand */
334 arm_disasm_shift_operand(ir, operand, sizeof(operand));
335 snprintf(buf, len, "AND%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
336 break;
337 case 1: /* ANDS Rd, Rn, operand */
338 arm_disasm_shift_operand(ir, operand, sizeof(operand));
339 snprintf(buf, len, "ANDS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
340 break;
341 case 2: /* EOR Rd, Rn, operand */
342 arm_disasm_shift_operand(ir, operand, sizeof(operand));
343 snprintf(buf, len, "EOR%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
344 break;
345 case 3: /* EORS Rd, Rn, operand */
346 arm_disasm_shift_operand(ir, operand, sizeof(operand));
347 snprintf(buf, len, "EORS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
348 break;
349 case 4: /* SUB Rd, Rn, operand */
350 arm_disasm_shift_operand(ir, operand, sizeof(operand));
351 snprintf(buf, len, "SUB%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
352 break;
353 case 5: /* SUBS Rd, Rn, operand */
354 arm_disasm_shift_operand(ir, operand, sizeof(operand));
355 snprintf(buf, len, "SUBS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
356 break;
357 case 6: /* RSB Rd, Rn, operand */
358 arm_disasm_shift_operand(ir, operand, sizeof(operand));
359 snprintf(buf, len, "RSB%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
360 break;
361 case 7: /* RSBS Rd, Rn, operand */
362 arm_disasm_shift_operand(ir, operand, sizeof(operand));
363 snprintf(buf, len, "RSBS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
364 break;
365 case 8: /* ADD Rd, Rn, operand */
366 arm_disasm_shift_operand(ir, operand, sizeof(operand));
367 snprintf(buf, len, "ADD%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
368 break;
369 case 9: /* ADDS Rd, Rn, operand */
370 arm_disasm_shift_operand(ir, operand, sizeof(operand));
371 snprintf(buf, len, "ADDS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
372 break;
373 case 10: /* ADC Rd, Rn, operand */
374 arm_disasm_shift_operand(ir, operand, sizeof(operand));
375 snprintf(buf, len, "ADC%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
376 break;
377 case 11: /* ADCS Rd, Rn, operand */
378 arm_disasm_shift_operand(ir, operand, sizeof(operand));
379 snprintf(buf, len, "ADCS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
380 break;
381 case 12: /* SBC Rd, Rn, operand */
382 arm_disasm_shift_operand(ir, operand, sizeof(operand));
383 snprintf(buf, len, "SBC%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
384 break;
385 case 13: /* SBCS Rd, Rn, operand */
386 arm_disasm_shift_operand(ir, operand, sizeof(operand));
387 snprintf(buf, len, "SBCS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
388 break;
389 case 14: /* RSC Rd, Rn, operand */
390 arm_disasm_shift_operand(ir, operand, sizeof(operand));
391 snprintf(buf, len, "RSC%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
392 break;
393 case 15: /* RSCS Rd, Rn, operand */
394 arm_disasm_shift_operand(ir, operand, sizeof(operand));
395 snprintf(buf, len, "RSCS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
396 break;
397 case 17: /* TST Rd, Rn, operand */
398 arm_disasm_shift_operand(ir, operand, sizeof(operand));
399 snprintf(buf, len, "TST%s R%d, %s", cond, RN(ir), operand);
400 break;
401 case 19: /* TEQ Rd, Rn, operand */
402 arm_disasm_shift_operand(ir, operand, sizeof(operand));
403 snprintf(buf, len, "TEQ%s R%d, %s", cond, RN(ir), operand);
404 break;
405 case 21: /* CMP Rd, Rn, operand */
406 arm_disasm_shift_operand(ir, operand, sizeof(operand));
407 snprintf(buf, len, "CMP%s R%d, %s", cond, RN(ir), operand);
408 break;
409 case 23: /* CMN Rd, Rn, operand */
410 arm_disasm_shift_operand(ir, operand, sizeof(operand));
411 snprintf(buf, len, "CMN%s R%d, %s", cond, RN(ir), operand);
412 break;
413 case 24: /* ORR Rd, Rn, operand */
414 arm_disasm_shift_operand(ir, operand, sizeof(operand));
415 snprintf(buf, len, "ORR%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
416 break;
417 case 25: /* ORRS Rd, Rn, operand */
418 arm_disasm_shift_operand(ir, operand, sizeof(operand));
419 snprintf(buf, len, "ORRS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
420 break;
421 case 26: /* MOV Rd, operand */
422 if( ir == 0xE1A00000 ) {
423 /* Not technically a different instruction,
424 * but this one is commonly used as a NOP,
425 * so...
426 */
427 snprintf(buf, len, "NOP");
428 } else {
429 arm_disasm_shift_operand(ir, operand, sizeof(operand));
430 snprintf(buf, len, "MOV%s R%d, %s", cond, RD(ir), operand);
431 }
432 break;
433 case 27: /* MOVS Rd, operand */
434 arm_disasm_shift_operand(ir, operand, sizeof(operand));
435 snprintf(buf, len, "MOVS%s R%d, %s", cond, RD(ir), operand);
436 break;
437 case 28: /* BIC Rd, Rn, operand */
438 arm_disasm_shift_operand(ir, operand, sizeof(operand));
439 snprintf(buf, len, "BIC%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
440 break;
441 case 29: /* BICS Rd, Rn, operand */
442 arm_disasm_shift_operand(ir, operand, sizeof(operand));
443 snprintf(buf, len, "BICS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
444 break;
445 case 30: /* MVN Rd, Rn, operand */
446 arm_disasm_shift_operand(ir, operand, sizeof(operand));
447 snprintf(buf, len, "MVN%s R%d, %s", cond, RD(ir), operand);
448 break;
449 case 31: /* MVNS Rd, Rn, operand */
450 arm_disasm_shift_operand(ir, operand, sizeof(operand));
451 snprintf(buf, len, "MVNS%s R%d, %s", cond, RD(ir), operand);
452 break;
453 default:
454 UNIMP(ir);
455 }
456 }
457 break;
458 case 1: /* Load/store */
459 arm_disasm_address_operand( ir, operand, sizeof(operand), pc );
460 switch( (ir>>20)&0x17 ) {
461 case 0:
462 case 16:
463 case 18:
464 snprintf(buf, len, "STR%s R%d, %s", cond, RD(ir), operand );
465 break;
466 case 1:
467 case 17:
468 case 19:
469 snprintf(buf, len, "LDR%s R%d, %s", cond, RD(ir), operand );
470 break;
471 case 2:
472 snprintf(buf, len, "STRT%s R%d, %s", cond, RD(ir), operand );
473 break;
474 case 3:
475 snprintf(buf, len, "LDRT%s R%d, %s", cond, RD(ir), operand );
476 break;
477 case 4:
478 case 20:
479 case 22:
480 snprintf(buf, len, "STRB%s R%d, %s", cond, RD(ir), operand );
481 break;
482 case 5:
483 case 21:
484 case 23:
485 snprintf(buf, len, "LDRB%s R%d, %s", cond, RD(ir), operand );
486 break;
487 case 6:
488 snprintf(buf, len, "STRBT%s R%d, %s", cond, RD(ir), operand );
489 break;
490 case 7:
491 snprintf(buf, len, "LDRBT%s R%d, %s", cond, RD(ir), operand );
492 break;
493 }
494 break;
495 case 2:
496 if( (ir & 0x02000000) == 0x02000000 ) {
497 int32_t offset = SIGNEXT24(ir&0x00FFFFFF) << 2;
498 if( (ir & 0x01000000) == 0x01000000 ) {
499 snprintf( buf, len, "BL%s $%08Xh", cond, pc + offset + 8 );
500 } else {
501 snprintf( buf, len, "B%s $%08Xh", cond, pc + offset + 8 );
502 }
503 } else {
504 /* Load/store multiple */
505 j = snprintf( buf, len, LFLAG(ir) ? "LDM%s%s R%d%c,":"STM%s%s R%d%c,",
506 ldmModes[(ir>>23)&0x03], cond, RN(ir), WFLAG(ir)?'!':' ' );
507 buf += j;
508 len -= j;
509 for( i = 0; i<16 && len > 2; i++ ) {
510 if( ir & (1<<i) ) {
511 j = snprintf( buf, len, "R%d", i );
512 buf+=j;
513 len-=j;
514 }
515 }
516 if( BFLAG(ir) && len > 0 ) {
517 buf[0] = '^';
518 buf[1] = '\0';
519 }
520 }
521 break;
522 case 3: /* Copro */
523 if( (ir & 0x0F000000) == 0x0F000000 ) {
524 snprintf( buf, len, "SWI%s #%08Xh", cond, SIGNEXT24(ir) );
525 } else {
526 UNIMP(ir);
527 }
528 break;
529 }
533 return pc+4;
534 }
537 uint32_t armt_disasm_instruction( uint32_t pc, char *buf, int len, char *opcode )
538 {
539 uint32_t ir = arm_read_word(pc);
540 sprintf( opcode, "%02X %02X", ir&0xFF, (ir>>8) );
541 UNIMP(ir);
542 return pc+2;
543 }
.