filename | src/aica/armdasm.c |
changeset | 30:89b30313d757 |
prev | 14:fc481a638848 |
next | 43:0cf3e339cc59 |
author | nkeynes |
date | Sun Dec 25 05:57:00 2005 +0000 (18 years ago) |
permissions | -rw-r--r-- |
last change | Change timeslice to nanoseconds (was microseconds) Generize single step (now steps through active CPU) Add lots of header blocks |
view | annotate | diff | log | raw |
1 /**
2 * $Id: armdasm.c,v 1.6 2005-12-25 05:57:00 nkeynes Exp $
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 SHIFTIMM(ir) ((ir>>7)&0x1F)
41 #define IMMROT(ir) ((ir>>7)&0x1E)
42 #define SHIFT(ir) ((ir>>4)&0x07)
43 #define DISP24(ir) ((ir&0x00FFFFFF))
44 #define FSXC(ir) msrFieldMask[RN(ir)]
45 #define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
46 #define SIGNEXT24(n) ((n&0x00800000) ? (n|0xFF000000) : (n&0x00FFFFFF))
50 const struct reg_desc_struct arm_reg_map[] =
51 { {"R0", REG_INT, &armr.r[0]}, {"R1", REG_INT, &armr.r[1]},
52 {"R2", REG_INT, &armr.r[2]}, {"R3", REG_INT, &armr.r[3]},
53 {"R4", REG_INT, &armr.r[4]}, {"R5", REG_INT, &armr.r[5]},
54 {"R6", REG_INT, &armr.r[6]}, {"R7", REG_INT, &armr.r[7]},
55 {"R8", REG_INT, &armr.r[8]}, {"R9", REG_INT, &armr.r[9]},
56 {"R10",REG_INT, &armr.r[10]}, {"R11",REG_INT, &armr.r[11]},
57 {"R12",REG_INT, &armr.r[12]}, {"R13",REG_INT, &armr.r[13]},
58 {"R14",REG_INT, &armr.r[14]}, {"R15",REG_INT, &armr.r[15]},
59 {"CPSR", REG_INT, &armr.cpsr}, {"SPSR", REG_INT, &armr.spsr},
60 {NULL, 0, NULL} };
63 const struct cpu_desc_struct arm_cpu_desc =
64 { "ARM7", arm_disasm_instruction, arm_execute_instruction, arm_has_page, 4,
65 (char *)&armr, sizeof(armr), arm_reg_map,
66 &armr.r[15], &armr.icount };
67 const struct cpu_desc_struct armt_cpu_desc =
68 { "ARM7T", armt_disasm_instruction, arm_execute_instruction, arm_has_page, 2,
69 (char*)&armr, sizeof(armr), arm_reg_map,
70 &armr.r[15], &armr.icount };
75 char *conditionNames[] = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
76 "HI", "LS", "GE", "LT", "GT", "LE", " " /*AL*/, "NV" };
78 /* fsxc */
79 char *msrFieldMask[] = { "", "c", "x", "xc", "s", "sc", "sx", "sxc",
80 "f", "fc", "fx", "fxc", "fs", "fsc", "fsx", "fsxc" };
81 char *ldmModes[] = { "DA", "IA", "DB", "IB" };
83 #define UNIMP(ir) snprintf( buf, len, "??? " )
85 int arm_disasm_shift_operand( uint32_t ir, char *buf, int len )
86 {
87 uint32_t operand, tmp;
88 if( IFLAG(ir) == 0 ) {
89 switch(SHIFT(ir)) {
90 case 0: /* (Rm << imm) */
91 tmp = SHIFTIMM(ir);
92 if( tmp != 0 ) {
93 return snprintf(buf, len, "R%d << %d", RM(ir), tmp );
94 } else {
95 return snprintf(buf, len, "R%d", RM(ir));
96 }
97 case 1: /* (Rm << Rs) */
98 return snprintf(buf, len, "R%d << R%d", RM(ir), RS(ir) );
99 case 2: /* (Rm >> imm) */
100 return snprintf(buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
101 case 3: /* (Rm >> Rs) */
102 return snprintf(buf, len, "R%d >> R%d", RM(ir), RS(ir) );
103 case 4: /* (Rm >>> imm) */
104 return snprintf(buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
105 case 5: /* (Rm >>> Rs) */
106 return snprintf(buf, len, "R%d >>> R%d", RM(ir), RS(ir) );
107 case 6:
108 tmp = SHIFTIMM(ir);
109 if( tmp == 0 ) /* RRX aka rotate with carry */
110 return snprintf(buf, len, "R%d roc 1", RM(ir) );
111 else
112 return snprintf(buf, len, "R%d rot %d", RM(ir), SHIFTIMM(ir) );
113 case 7:
114 return snprintf(buf, len, "R%d rot R%d", RM(ir), RS(ir) );
115 }
116 } else {
117 operand = IMM8(ir);
118 tmp = IMMROT(ir);
119 operand = ROTATE_RIGHT_LONG(operand, tmp);
120 return snprintf(buf, len, "%08X", operand );
121 }
122 }
124 static int arm_disasm_address_index( uint32_t ir, char *buf, int len )
125 {
126 uint32_t tmp;
128 switch(SHIFT(ir)) {
129 case 0: /* (Rm << imm) */
130 tmp = SHIFTIMM(ir);
131 if( tmp != 0 ) {
132 return snprintf( buf, len, "R%d << %d", RM(ir), tmp );
133 } else {
134 return snprintf( buf, len, "R%d", RM(ir) );
135 }
136 case 2: /* (Rm >> imm) */
137 return snprintf( buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
138 case 4: /* (Rm >>> imm) */
139 return snprintf( buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
140 case 6:
141 tmp = SHIFTIMM(ir);
142 if( tmp == 0 ) /* RRX aka rotate with carry */
143 return snprintf( buf, len, "R%d roc 1", RM(ir) );
144 else
145 return snprintf( buf, len, "R%d rot %d", RM(ir), tmp );
146 default:
147 return UNIMP(ir);
148 }
149 }
151 static int arm_disasm_address_operand( uint32_t ir, char *buf, int len, int pc )
152 {
153 char shift[32];
155 char sign = UFLAG(ir) ? '+' : '-';
156 /* I P U . W */
157 switch( (ir>>21)&0x19 ) {
158 case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
159 case 1:
160 return snprintf( buf, len, "[R%d], R%d %c= %04X", RN(ir), RN(ir), sign, IMM12(ir) );
161 case 8: /* Rn - imm offset [5.2.2 A5-20] */
162 if( RN(ir) == 15 ) { /* PC relative - decode here */
163 return snprintf( buf, len, "[$%08Xh]", pc + 8 +
164 (UFLAG(ir) ? IMM12(ir) : -IMM12(ir)) );
165 } else {
166 return snprintf( buf, len, "[R%d %c %04X]", RN(ir), sign, IMM12(ir) );
167 }
168 case 9: /* Rn -= imm offset (pre-indexed) [5.2.5 A5-24] */
169 return snprintf( buf, len, "[R%d %c= %04X]", RN(ir), sign, IMM12(ir) );
170 case 16: /* Rn -= Rm (post-indexed) [5.2.10 A5-32 ] */
171 case 17:
172 arm_disasm_address_index( ir, shift, sizeof(shift) );
173 return snprintf( buf, len, "[R%d], R%d %c= %s", RN(ir), RN(ir), sign, shift );
174 case 24: /* Rn - Rm [5.2.4 A5-23] */
175 arm_disasm_address_index( ir, shift, sizeof(shift) );
176 return snprintf( buf, len, "[R%d %c %s]", RN(ir), sign, shift );
177 case 25: /* RN -= Rm (pre-indexed) [5.2.7 A5-26] */
178 arm_disasm_address_index( ir, shift, sizeof(shift) );
179 return snprintf( buf, len, "[R%d %c= %s]", RN(ir), sign, shift );
180 default:
181 return UNIMP(ir); /* Unreachable */
182 }
183 }
185 uint32_t arm_disasm_instruction( uint32_t pc, char *buf, int len, char *opcode )
186 {
187 char operand[32];
188 uint32_t ir = arm_read_long(pc);
189 int i,j;
191 sprintf( opcode, "%02X %02X %02X %02X", ir&0xFF, (ir>>8) & 0xFF,
192 (ir>>16)&0xFF, (ir>>24) );
194 if( COND(ir) == 0x0F ) {
195 UNIMP(ir);
196 return pc+4;
197 }
198 char *cond = conditionNames[COND(ir)];
200 switch( GRP(ir) ) {
201 case 0:
202 if( (ir & 0x0D900000) == 0x01000000 ) {
203 /* Instructions that aren't actual data processing */
204 switch( ir & 0x0FF000F0 ) {
205 case 0x01200010: /* BXcc */
206 snprintf(buf, len, "BX%s R%d", cond, RM(ir));
207 break;
208 case 0x01000000: /* MRS Rd, CPSR */
209 snprintf(buf, len, "MRS%s R%d, CPSR", cond, RD(ir));
210 break;
211 case 0x01400000: /* MRS Rd, SPSR */
212 snprintf(buf, len, "MRS%s R%d, SPSR", cond, RD(ir));
213 break;
214 case 0x01200000: /* MSR CPSR, Rm */
215 snprintf(buf, len, "MSR%s CPSR_%s, R%d", cond, FSXC(ir), RM(ir));
216 break;
217 case 0x01600000: /* MSR SPSR, Rm */
218 snprintf(buf, len, "MSR%s SPSR_%s, R%d", cond, FSXC(ir), RM(ir));
219 break;
220 case 0x03200000: /* MSR CPSR, imm */
221 snprintf(buf, len, "MSR%s CPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
222 break;
223 case 0x03600000: /* MSR SPSR, imm */
224 snprintf(buf, len, "MSR%s SPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
225 break;
226 default:
227 UNIMP();
228 }
229 } else if( (ir & 0x0E000090) == 0x00000090 ) {
230 /* Neither are these */
231 switch( (ir>>5)&0x03 ) {
232 case 0:
233 /* Arithmetic extension area */
234 switch(OPCODE(ir)) {
235 case 0: /* MUL */
236 snprintf(buf,len, "MUL%s R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir) );
237 break;
238 case 1: /* MULS */
239 break;
240 case 2: /* MLA */
241 snprintf(buf,len, "MLA%s R%d, R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir), RD(ir) );
242 break;
243 case 3: /* MLAS */
244 break;
245 case 8: /* UMULL */
246 snprintf(buf,len, "UMULL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
247 break;
248 case 9: /* UMULLS */
249 break;
250 case 10: /* UMLAL */
251 snprintf(buf,len, "UMLAL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
252 break;
253 case 11: /* UMLALS */
254 break;
255 case 12: /* SMULL */
256 snprintf(buf,len, "SMULL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
257 break;
258 case 13: /* SMULLS */
259 break;
260 case 14: /* SMLAL */
261 snprintf(buf,len, "SMLAL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
262 break;
263 case 15: /* SMLALS */
265 break;
266 case 16: /* SWP */
267 snprintf(buf,len, "SWP%s R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
268 break;
269 case 20: /* SWPB */
270 snprintf(buf,len, "SWPB%s R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
271 break;
272 default:
273 UNIMP(ir);
274 }
275 break;
276 case 1:
277 if( LFLAG(ir) ) {
278 /* LDRH */
279 } else {
280 /* STRH */
281 }
282 break;
283 case 2:
284 if( LFLAG(ir) ) {
285 /* LDRSB */
286 } else {
287 UNIMP(ir);
288 }
289 break;
290 case 3:
291 if( LFLAG(ir) ) {
292 /* LDRSH */
293 } else {
294 UNIMP(ir);
295 }
296 break;
297 }
298 } else {
299 /* Data processing */
301 switch(OPCODE(ir)) {
302 case 0: /* AND Rd, Rn, operand */
303 arm_disasm_shift_operand(ir, operand, sizeof(operand));
304 snprintf(buf, len, "AND%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
305 break;
306 case 1: /* ANDS Rd, Rn, operand */
307 arm_disasm_shift_operand(ir, operand, sizeof(operand));
308 snprintf(buf, len, "ANDS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
309 break;
310 case 2: /* EOR Rd, Rn, operand */
311 arm_disasm_shift_operand(ir, operand, sizeof(operand));
312 snprintf(buf, len, "EOR%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
313 break;
314 case 3: /* EORS Rd, Rn, operand */
315 arm_disasm_shift_operand(ir, operand, sizeof(operand));
316 snprintf(buf, len, "EORS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
317 break;
318 case 4: /* SUB Rd, Rn, operand */
319 arm_disasm_shift_operand(ir, operand, sizeof(operand));
320 snprintf(buf, len, "SUB%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
321 break;
322 case 5: /* SUBS Rd, Rn, operand */
323 arm_disasm_shift_operand(ir, operand, sizeof(operand));
324 snprintf(buf, len, "SUBS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
325 break;
326 case 6: /* RSB Rd, Rn, operand */
327 arm_disasm_shift_operand(ir, operand, sizeof(operand));
328 snprintf(buf, len, "RSB%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
329 break;
330 case 7: /* RSBS Rd, Rn, operand */
331 arm_disasm_shift_operand(ir, operand, sizeof(operand));
332 snprintf(buf, len, "RSBS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
333 break;
334 case 8: /* ADD Rd, Rn, operand */
335 arm_disasm_shift_operand(ir, operand, sizeof(operand));
336 snprintf(buf, len, "ADD%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
337 break;
338 case 9: /* ADDS Rd, Rn, operand */
339 arm_disasm_shift_operand(ir, operand, sizeof(operand));
340 snprintf(buf, len, "ADDS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
341 break;
342 case 10: /* ADC Rd, Rn, operand */
343 arm_disasm_shift_operand(ir, operand, sizeof(operand));
344 snprintf(buf, len, "ADC%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
345 break;
346 case 11: /* ADCS Rd, Rn, operand */
347 arm_disasm_shift_operand(ir, operand, sizeof(operand));
348 snprintf(buf, len, "ADCS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
349 break;
350 case 12: /* SBC Rd, Rn, operand */
351 arm_disasm_shift_operand(ir, operand, sizeof(operand));
352 snprintf(buf, len, "SBC%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
353 break;
354 case 13: /* SBCS Rd, Rn, operand */
355 arm_disasm_shift_operand(ir, operand, sizeof(operand));
356 snprintf(buf, len, "SBCS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
357 break;
358 case 14: /* RSC Rd, Rn, operand */
359 arm_disasm_shift_operand(ir, operand, sizeof(operand));
360 snprintf(buf, len, "RSC%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
361 break;
362 case 15: /* RSCS Rd, Rn, operand */
363 arm_disasm_shift_operand(ir, operand, sizeof(operand));
364 snprintf(buf, len, "RSCS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
365 break;
366 case 16: /* TST Rd, Rn, operand */
367 arm_disasm_shift_operand(ir, operand, sizeof(operand));
368 snprintf(buf, len, "TST%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
369 break;
370 case 18: /* TEQ Rd, Rn, operand */
371 arm_disasm_shift_operand(ir, operand, sizeof(operand));
372 snprintf(buf, len, "TEQ%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
373 break;
374 case 20: /* CMP Rd, Rn, operand */
375 arm_disasm_shift_operand(ir, operand, sizeof(operand));
376 snprintf(buf, len, "CMP%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
377 break;
378 case 22: /* CMN Rd, Rn, operand */
379 arm_disasm_shift_operand(ir, operand, sizeof(operand));
380 snprintf(buf, len, "CMN%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
381 break;
382 case 24: /* ORR Rd, Rn, operand */
383 arm_disasm_shift_operand(ir, operand, sizeof(operand));
384 snprintf(buf, len, "ORR%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
385 break;
386 case 25: /* ORRS Rd, Rn, operand */
387 arm_disasm_shift_operand(ir, operand, sizeof(operand));
388 snprintf(buf, len, "ORRS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
389 break;
390 case 26: /* MOV Rd, Rn, operand */
391 arm_disasm_shift_operand(ir, operand, sizeof(operand));
392 snprintf(buf, len, "MOV%s R%d, %s", cond, RD(ir), operand);
393 break;
394 case 27: /* MOVS Rd, Rn, operand */
395 arm_disasm_shift_operand(ir, operand, sizeof(operand));
396 snprintf(buf, len, "MOVS%s R%d, %s", cond, RD(ir), operand);
397 break;
398 case 28: /* BIC Rd, Rn, operand */
399 arm_disasm_shift_operand(ir, operand, sizeof(operand));
400 snprintf(buf, len, "BIC%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
401 break;
402 case 29: /* BICS Rd, Rn, operand */
403 arm_disasm_shift_operand(ir, operand, sizeof(operand));
404 snprintf(buf, len, "BICS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
405 break;
406 case 30: /* MVN Rd, Rn, operand */
407 arm_disasm_shift_operand(ir, operand, sizeof(operand));
408 snprintf(buf, len, "MVN%s R%d, %s", cond, RD(ir), operand);
409 break;
410 case 31: /* MVNS Rd, Rn, operand */
411 arm_disasm_shift_operand(ir, operand, sizeof(operand));
412 snprintf(buf, len, "MVNS%s R%d, %s", cond, RD(ir), operand);
413 break;
414 default:
415 UNIMP(ir);
416 }
417 }
418 break;
419 case 1: /* Load/store */
420 arm_disasm_address_operand( ir, operand, sizeof(operand), pc );
421 switch( (ir>>20)&0x17 ) {
422 case 0:
423 case 16:
424 case 18:
425 snprintf(buf, len, "STR%s R%d, %s", cond, RD(ir), operand );
426 break;
427 case 1:
428 case 17:
429 case 19:
430 snprintf(buf, len, "LDR%s R%d, %s", cond, RD(ir), operand );
431 break;
432 case 2:
433 snprintf(buf, len, "STRT%s R%d, %s", cond, RD(ir), operand );
434 break;
435 case 3:
436 snprintf(buf, len, "LDRT%s R%d, %s", cond, RD(ir), operand );
437 break;
438 case 4:
439 case 20:
440 case 22:
441 snprintf(buf, len, "STRB%s R%d, %s", cond, RD(ir), operand );
442 break;
443 case 5:
444 case 21:
445 case 23:
446 snprintf(buf, len, "LDRB%s R%d, %s", cond, RD(ir), operand );
447 break;
448 case 6:
449 snprintf(buf, len, "STRBT%s R%d, %s", cond, RD(ir), operand );
450 break;
451 case 7:
452 snprintf(buf, len, "LDRBT%s R%d, %s", cond, RD(ir), operand );
453 break;
454 }
455 break;
456 case 2:
457 if( (ir & 0x02000000) == 0x02000000 ) {
458 int32_t offset = SIGNEXT24(ir&0x00FFFFFF) << 2;
459 if( (ir & 0x01000000) == 0x01000000 ) {
460 snprintf( buf, len, "BL%s $%08Xh", cond, pc + offset + 8 );
461 } else {
462 snprintf( buf, len, "B%s $%08Xh", cond, pc + offset + 8 );
463 }
464 } else {
465 /* Load/store multiple */
466 j = snprintf( buf, len, LFLAG(ir) ? "LDM%s%s R%d%c,":"STM%s%s R%d%c,",
467 ldmModes[(ir>>23)&0x03], cond, RN(ir), WFLAG(ir)?'!':' ' );
468 buf += j;
469 len -= j;
470 for( i = 0; i<16 && len > 2; i++ ) {
471 if( (ir >> i)&1 ) {
472 j = snprintf( buf, len, "R%d", i );
473 buf+=j;
474 len-=j;
475 }
476 }
477 if( SFLAG(ir) && len > 0 ) {
478 buf[0] = '^';
479 buf[1] = '\0';
480 }
481 }
482 break;
483 case 3: /* Copro */
484 UNIMP(ir);
485 break;
486 }
490 return pc+4;
491 }
494 uint32_t armt_disasm_instruction( uint32_t pc, char *buf, int len, char *opcode )
495 {
496 uint32_t ir = arm_read_word(pc);
497 sprintf( opcode, "%02X %02X", ir&0xFF, (ir>>8) );
498 UNIMP(ir);
499 return pc+2;
500 }
.