2 * armdasm.c 21 Aug 2004 - ARM7tdmi (ARMv4) disassembler
4 * Copyright (c) 2004 Nathan Keynes. Distribution and modification permitted
5 * under the terms of the GNU General Public License version 2 or later.
10 #define COND(ir) (ir>>28)
11 #define OPCODE(ir) ((ir>>20)&0x1F)
12 #define GRP(ir) ((ir>>26)&0x03)
13 #define IFLAG(ir) (ir&0x02000000)
14 #define SFLAG(ir) (ir&0x00100000)
15 #define PFLAG(ir) (ir&0x01000000)
16 #define UFLAG(ir) (ir&0x00800000)
17 #define BFLAG(ir) (ir&0x00400000)
18 #define WFLAG(ir) (IR&0x00200000)
19 #define LFLAG(ir) SFLAG(ir)
20 #define RN(ir) ((ir>>16)&0x0F)
21 #define RD(ir) ((ir>>12)&0x0F)
22 #define RS(ir) ((ir>>8)&0x0F)
23 #define RM(ir) (ir&0x0F)
25 #define IMM8(ir) (ir&0xFF)
26 #define IMM12(ir) (ir&0xFFF)
27 #define SHIFTIMM(ir) ((ir>>7)0x1F)
28 #define IMMROT(ir) ((ir>>7)&1E)
29 #define SHIFT(ir) ((ir>>4)&0x07)
30 #define DISP24(ir) ((ir&0x00FFFFFF))
31 #define FSXC(ir) msrFieldMask[RN(ir)]
32 #define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
34 char *conditionNames[] = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
35 "HI", "LS", "GE", "LT", "GT", "LE", " " /*AL*/, "NV" };
38 char *msrFieldMask[] = { "", "c", "x", "xc", "s", "sc", "sx", "sxc",
39 "f", "fc", "fx", "fxc", "fs", "fsc", "fsx", "fsxc" };
41 #define UNIMP(ir) snprintf( buf, len, "??? " )
43 int arm_disasm_instruction( int pc, char *buf, int len )
45 uint32_t ir = arm_mem_read_long(pc);
47 if( COND(ir) == 0x0F ) {
51 char *cond = conditionNames[COND(ir)];
55 if( (ir & 0x0D900000) == 0x01000000 ) {
56 /* Instructions that aren't actual data processing */
57 switch( ir & 0x0FF000F0 ) {
58 case 0x01200010: /* BXcc */
59 snprintf(buf, len, "BX%s R%d", cond, RM(ir));
61 case 0x01000000: /* MRS Rd, CPSR */
62 snprintf(buf, len, "MRS%s R%d, CPSR", cond, RD(ir));
64 case 0x01400000: /* MRS Rd, SPSR */
65 snprintf(buf, len, "MRS%s R%d, SPSR", cond, RD(ir));
67 case 0x01200000: /* MSR CPSR, Rm */
68 snprintf(buf, len, "MSR%s CPSR_%s, R%d", cond, FSXC(ir), RM(ir));
70 case 0x01600000: /* MSR SPSR, Rm */
71 snprintf(buf, len, "MSR%s SPSR_%s, R%d", cond, FSXC(ir), RM(ir));
73 case 0x03200000: /* MSR CPSR, imm */
74 snprintf(buf, len, "MSR%s CPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
76 case 0x03600000: /* MSR SPSR, imm */
77 snprintf(buf, len, "MSR%s SPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
82 } else if( (ir & 0x0E000090) == 0x00000090 ) {
83 /* Neither are these */
84 switch( (ir>>5)&0x03 ) {
86 /* Arithmetic extension area */
89 snprintf(buf,len, "MUL%s R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir) );
94 snprintf(buf,len, "MLA%s R%d, R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir), RD(ir) );
99 snprintf(buf,len, "UMULL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
104 snprintf(buf,len, "UMLAL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
106 case 11: /* UMLALS */
109 snprintf(buf,len, "SMULL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
111 case 13: /* SMULLS */
114 snprintf(buf,len, "SMLAL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
116 case 15: /* SMLALS */
120 snprintf(buf,len, "SWP%s R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
123 snprintf(buf,len, "SWPB%s R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
152 /* Data processing */
155 case 0: /* AND Rd, Rn, operand */
156 RD(ir) = RN(ir) & arm_get_shift_operand(ir);
158 case 1: /* ANDS Rd, Rn, operand */
159 operand = arm_get_shift_operand_s(ir) & RN(ir);
161 if( RDn(ir) == 15 ) {
164 armr.n = operand>>31;
165 armr.z = (operand == 0);
166 armr.c = armr.shift_c;
169 case 2: /* EOR Rd, Rn, operand */
170 RD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
172 case 3: /* EORS Rd, Rn, operand */
173 operand = arm_get_shift_operand_s(ir) ^ RN(ir);
175 if( RDn(ir) == 15 ) {
178 armr.n = operand>>31;
179 armr.z = (operand == 0);
180 armr.c = armr.shift_c;
183 case 4: /* SUB Rd, Rn, operand */
184 RD(ir) = RN(ir) - arm_get_shift_operand(ir);
186 case 5: /* SUBS Rd, Rn, operand */
188 operand2 = arm_get_shift_operand(ir)
189 tmp = operand - operand2;
191 if( RDn(ir) == 15 ) {
196 armr.c = IS_NOTBORROW(tmp,operand,operand2);
197 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
200 case 6: /* RSB Rd, operand, Rn */
201 RD(ir) = arm_get_shift_operand(ir) - RN(ir);
203 case 7: /* RSBS Rd, operand, Rn */
204 operand = arm_get_shift_operand(ir);
206 tmp = operand - operand2;
208 if( RDn(ir) == 15 ) {
213 armr.c = IS_NOTBORROW(tmp,operand,operand2);
214 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
217 case 8: /* ADD Rd, Rn, operand */
218 RD(ir) = RN(ir) + arm_get_shift_operand(ir);
220 case 9: /* ADDS Rd, Rn, operand */
221 operand = arm_get_shift_operand(ir);
223 tmp = operand + operand2
225 if( RDn(ir) == 15 ) {
230 armr.c = IS_CARRY(tmp,operand,operand2);
231 armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
241 case 17: /* TST Rn, operand */
242 operand = arm_get_shift_operand_s(ir) & RN(ir);
243 armr.n = operand>>31;
244 armr.z = (operand == 0);
245 armr.c = armr.shift_c;
247 case 19: /* TEQ Rn, operand */
248 operand = arm_get_shift_operand_s(ir) ^ RN(ir);
249 armr.n = operand>>31;
250 armr.z = (operand == 0);
251 armr.c = armr.shift_c;
253 case 21: /* CMP Rn, operand */
255 operand2 = arm_get_shift_operand(ir)
256 tmp = operand - operand2;
259 armr.c = IS_NOTBORROW(tmp,operand,operand2);
260 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
262 case 23: /* CMN Rn, operand */
264 operand2 = arm_get_shift_operand(ir)
265 tmp = operand + operand2;
268 armr.c = IS_CARRY(tmp,operand,operand2);
269 armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
271 case 24: /* ORR Rd, Rn, operand */
272 RD(ir) = RN(ir) | arm_get_shift_operand(ir);
274 case 25: /* ORRS Rd, Rn, operand */
275 operand = arm_get_shift_operand_s(ir) | RN(ir);
277 if( RDn(ir) == 15 ) {
280 armr.n = operand>>31;
281 armr.z = (operand == 0);
282 armr.c = armr.shift_c;
285 case 26: /* MOV Rd, operand */
286 RD(ir) = arm_get_shift_operand(ir);
288 case 27: /* MOVS Rd, operand */
289 operand = arm_get_shift_operand_s(ir);
291 if( RDn(ir) == 15 ) {
294 armr.n = operand>>31;
295 armr.z = (operand == 0);
296 armr.c = armr.shift_c;
299 case 28: /* BIC Rd, Rn, operand */
300 RD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
302 case 29: /* BICS Rd, Rn, operand */
303 operand = RN(ir) & (~arm_get_shift_operand_s(ir));
305 if( RDn(ir) == 15 ) {
308 armr.n = operand>>31;
309 armr.z = (operand == 0);
310 armr.c = armr.shift_c;
313 case 30: /* MVN Rd, operand */
314 RD(ir) = ~arm_get_shift_operand(ir);
316 case 31: /* MVNS Rd, operand */
317 operand = ~arm_get_shift_operand_s(ir);
319 if( RDn(ir) == 15 ) {
322 armr.n = operand>>31;
323 armr.z = (operand == 0);
324 armr.c = armr.shift_c;
332 case 1: /* Load/store */
334 case 2: /* Load/store multiple, branch*/
.