Search
lxdream.org :: lxdream/src/aica/armdasm.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armdasm.c
changeset 4:7d6f596ce577
next7:976a16e92aab
author nkeynes
date Sat Oct 02 05:49:12 2004 +0000 (15 years ago)
permissions -rw-r--r--
last change Add armdasm
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/aica/armdasm.c Sat Oct 02 05:49:12 2004 +0000
1.3 @@ -0,0 +1,343 @@
1.4 +/*
1.5 + * armdasm.c 21 Aug 2004 - ARM7tdmi (ARMv4) disassembler
1.6 + *
1.7 + * Copyright (c) 2004 Nathan Keynes. Distribution and modification permitted
1.8 + * under the terms of the GNU General Public License version 2 or later.
1.9 + */
1.10 +
1.11 +#include "armcore.h"
1.12 +
1.13 +#define COND(ir) (ir>>28)
1.14 +#define OPCODE(ir) ((ir>>20)&0x1F)
1.15 +#define GRP(ir) ((ir>>26)&0x03)
1.16 +#define IFLAG(ir) (ir&0x02000000)
1.17 +#define SFLAG(ir) (ir&0x00100000)
1.18 +#define PFLAG(ir) (ir&0x01000000)
1.19 +#define UFLAG(ir) (ir&0x00800000)
1.20 +#define BFLAG(ir) (ir&0x00400000)
1.21 +#define WFLAG(ir) (IR&0x00200000)
1.22 +#define LFLAG(ir) SFLAG(ir)
1.23 +#define RN(ir) ((ir>>16)&0x0F)
1.24 +#define RD(ir) ((ir>>12)&0x0F)
1.25 +#define RS(ir) ((ir>>8)&0x0F)
1.26 +#define RM(ir) (ir&0x0F)
1.27 +
1.28 +#define IMM8(ir) (ir&0xFF)
1.29 +#define IMM12(ir) (ir&0xFFF)
1.30 +#define SHIFTIMM(ir) ((ir>>7)0x1F)
1.31 +#define IMMROT(ir) ((ir>>7)&1E)
1.32 +#define SHIFT(ir) ((ir>>4)&0x07)
1.33 +#define DISP24(ir) ((ir&0x00FFFFFF))
1.34 +#define FSXC(ir) msrFieldMask[RN(ir)]
1.35 +#define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
1.36 +
1.37 +char *conditionNames[] = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
1.38 + "HI", "LS", "GE", "LT", "GT", "LE", " " /*AL*/, "NV" };
1.39 +
1.40 + /* fsxc */
1.41 +char *msrFieldMask[] = { "", "c", "x", "xc", "s", "sc", "sx", "sxc",
1.42 + "f", "fc", "fx", "fxc", "fs", "fsc", "fsx", "fsxc" };
1.43 +
1.44 +#define UNIMP(ir) snprintf( buf, len, "??? " )
1.45 +
1.46 +int arm_disasm_instruction( int pc, char *buf, int len )
1.47 +{
1.48 + uint32_t ir = arm_mem_read_long(pc);
1.49 +
1.50 + if( COND(ir) == 0x0F ) {
1.51 + UNIMP(ir);
1.52 + return pc+4;
1.53 + }
1.54 + char *cond = conditionNames[COND(ir)];
1.55 +
1.56 + switch( GRP(ir) ) {
1.57 + case 0:
1.58 + if( (ir & 0x0D900000) == 0x01000000 ) {
1.59 + /* Instructions that aren't actual data processing */
1.60 + switch( ir & 0x0FF000F0 ) {
1.61 + case 0x01200010: /* BXcc */
1.62 + snprintf(buf, len, "BX%s R%d", cond, RM(ir));
1.63 + break;
1.64 + case 0x01000000: /* MRS Rd, CPSR */
1.65 + snprintf(buf, len, "MRS%s R%d, CPSR", cond, RD(ir));
1.66 + break;
1.67 + case 0x01400000: /* MRS Rd, SPSR */
1.68 + snprintf(buf, len, "MRS%s R%d, SPSR", cond, RD(ir));
1.69 + break;
1.70 + case 0x01200000: /* MSR CPSR, Rm */
1.71 + snprintf(buf, len, "MSR%s CPSR_%s, R%d", cond, FSXC(ir), RM(ir));
1.72 + break;
1.73 + case 0x01600000: /* MSR SPSR, Rm */
1.74 + snprintf(buf, len, "MSR%s SPSR_%s, R%d", cond, FSXC(ir), RM(ir));
1.75 + break;
1.76 + case 0x03200000: /* MSR CPSR, imm */
1.77 + snprintf(buf, len, "MSR%s CPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
1.78 + break;
1.79 + case 0x03600000: /* MSR SPSR, imm */
1.80 + snprintf(buf, len, "MSR%s SPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
1.81 + break;
1.82 + default:
1.83 + UNIMP();
1.84 + }
1.85 + } else if( (ir & 0x0E000090) == 0x00000090 ) {
1.86 + /* Neither are these */
1.87 + switch( (ir>>5)&0x03 ) {
1.88 + case 0:
1.89 + /* Arithmetic extension area */
1.90 + switch(OPCODE(ir)) {
1.91 + case 0: /* MUL */
1.92 + snprintf(buf,len, "MUL%s R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir) );
1.93 + break;
1.94 + case 1: /* MULS */
1.95 + break;
1.96 + case 2: /* MLA */
1.97 + snprintf(buf,len, "MLA%s R%d, R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir), RD(ir) );
1.98 + break;
1.99 + case 3: /* MLAS */
1.100 + break;
1.101 + case 8: /* UMULL */
1.102 + snprintf(buf,len, "UMULL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
1.103 + break;
1.104 + case 9: /* UMULLS */
1.105 + break;
1.106 + case 10: /* UMLAL */
1.107 + snprintf(buf,len, "UMLAL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
1.108 + break;
1.109 + case 11: /* UMLALS */
1.110 + break;
1.111 + case 12: /* SMULL */
1.112 + snprintf(buf,len, "SMULL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
1.113 + break;
1.114 + case 13: /* SMULLS */
1.115 + break;
1.116 + case 14: /* SMLAL */
1.117 + snprintf(buf,len, "SMLAL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
1.118 + break;
1.119 + case 15: /* SMLALS */
1.120 +
1.121 + break;
1.122 + case 16: /* SWP */
1.123 + snprintf(buf,len, "SWP%s R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
1.124 + break;
1.125 + case 20: /* SWPB */
1.126 + snprintf(buf,len, "SWPB%s R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
1.127 + break;
1.128 + default:
1.129 + UNIMP(ir);
1.130 + }
1.131 + break;
1.132 + case 1:
1.133 + if( LFLAG(ir) ) {
1.134 + /* LDRH */
1.135 + } else {
1.136 + /* STRH */
1.137 + }
1.138 + break;
1.139 + case 2:
1.140 + if( LFLAG(ir) ) {
1.141 + /* LDRSB */
1.142 + } else {
1.143 + UNIMP(ir);
1.144 + }
1.145 + break;
1.146 + case 3:
1.147 + if( LFLAG(ir) ) {
1.148 + /* LDRSH */
1.149 + } else {
1.150 + UNIMP(ir);
1.151 + }
1.152 + break;
1.153 + }
1.154 + } else {
1.155 + /* Data processing */
1.156 +
1.157 + switch(OPCODE(ir)) {
1.158 + case 0: /* AND Rd, Rn, operand */
1.159 + RD(ir) = RN(ir) & arm_get_shift_operand(ir);
1.160 + break;
1.161 + case 1: /* ANDS Rd, Rn, operand */
1.162 + operand = arm_get_shift_operand_s(ir) & RN(ir);
1.163 + RD(ir) = operand;
1.164 + if( RDn(ir) == 15 ) {
1.165 + arm_restore_cpsr();
1.166 + } else {
1.167 + armr.n = operand>>31;
1.168 + armr.z = (operand == 0);
1.169 + armr.c = armr.shift_c;
1.170 + }
1.171 + break;
1.172 + case 2: /* EOR Rd, Rn, operand */
1.173 + RD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
1.174 + break;
1.175 + case 3: /* EORS Rd, Rn, operand */
1.176 + operand = arm_get_shift_operand_s(ir) ^ RN(ir);
1.177 + RD(ir) = operand;
1.178 + if( RDn(ir) == 15 ) {
1.179 + arm_restore_cpsr();
1.180 + } else {
1.181 + armr.n = operand>>31;
1.182 + armr.z = (operand == 0);
1.183 + armr.c = armr.shift_c;
1.184 + }
1.185 + break;
1.186 + case 4: /* SUB Rd, Rn, operand */
1.187 + RD(ir) = RN(ir) - arm_get_shift_operand(ir);
1.188 + break;
1.189 + case 5: /* SUBS Rd, Rn, operand */
1.190 + operand = RN(ir);
1.191 + operand2 = arm_get_shift_operand(ir)
1.192 + tmp = operand - operand2;
1.193 + RD(ir) = tmp;
1.194 + if( RDn(ir) == 15 ) {
1.195 + arm_restore_cpsr();
1.196 + } else {
1.197 + armr.n = tmp>>31;
1.198 + armr.z = (tmp == 0);
1.199 + armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.200 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.201 + }
1.202 + break;
1.203 + case 6: /* RSB Rd, operand, Rn */
1.204 + RD(ir) = arm_get_shift_operand(ir) - RN(ir);
1.205 + break;
1.206 + case 7: /* RSBS Rd, operand, Rn */
1.207 + operand = arm_get_shift_operand(ir);
1.208 + operand2 = RN(ir);
1.209 + tmp = operand - operand2;
1.210 + RD(ir) = tmp;
1.211 + if( RDn(ir) == 15 ) {
1.212 + arm_restore_cpsr();
1.213 + } else {
1.214 + armr.n = tmp>>31;
1.215 + armr.z = (tmp == 0);
1.216 + armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.217 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.218 + }
1.219 + break;
1.220 + case 8: /* ADD Rd, Rn, operand */
1.221 + RD(ir) = RN(ir) + arm_get_shift_operand(ir);
1.222 + break;
1.223 + case 9: /* ADDS Rd, Rn, operand */
1.224 + operand = arm_get_shift_operand(ir);
1.225 + operand2 = RN(ir);
1.226 + tmp = operand + operand2
1.227 + RD(ir) = tmp;
1.228 + if( RDn(ir) == 15 ) {
1.229 + arm_restore_cpsr();
1.230 + } else {
1.231 + armr.n = tmp>>31;
1.232 + armr.z = (tmp == 0);
1.233 + armr.c = IS_CARRY(tmp,operand,operand2);
1.234 + armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
1.235 + }
1.236 + break;
1.237 + case 10: /* ADC */
1.238 + case 11: /* ADCS */
1.239 + case 12: /* SBC */
1.240 + case 13: /* SBCS */
1.241 + case 14: /* RSC */
1.242 + case 15: /* RSCS */
1.243 + break;
1.244 + case 17: /* TST Rn, operand */
1.245 + operand = arm_get_shift_operand_s(ir) & RN(ir);
1.246 + armr.n = operand>>31;
1.247 + armr.z = (operand == 0);
1.248 + armr.c = armr.shift_c;
1.249 + break;
1.250 + case 19: /* TEQ Rn, operand */
1.251 + operand = arm_get_shift_operand_s(ir) ^ RN(ir);
1.252 + armr.n = operand>>31;
1.253 + armr.z = (operand == 0);
1.254 + armr.c = armr.shift_c;
1.255 + break;
1.256 + case 21: /* CMP Rn, operand */
1.257 + operand = RN(ir);
1.258 + operand2 = arm_get_shift_operand(ir)
1.259 + tmp = operand - operand2;
1.260 + armr.n = tmp>>31;
1.261 + armr.z = (tmp == 0);
1.262 + armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.263 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.264 + break;
1.265 + case 23: /* CMN Rn, operand */
1.266 + operand = RN(ir);
1.267 + operand2 = arm_get_shift_operand(ir)
1.268 + tmp = operand + operand2;
1.269 + armr.n = tmp>>31;
1.270 + armr.z = (tmp == 0);
1.271 + armr.c = IS_CARRY(tmp,operand,operand2);
1.272 + armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
1.273 + break;
1.274 + case 24: /* ORR Rd, Rn, operand */
1.275 + RD(ir) = RN(ir) | arm_get_shift_operand(ir);
1.276 + break;
1.277 + case 25: /* ORRS Rd, Rn, operand */
1.278 + operand = arm_get_shift_operand_s(ir) | RN(ir);
1.279 + RD(ir) = operand;
1.280 + if( RDn(ir) == 15 ) {
1.281 + arm_restore_cpsr();
1.282 + } else {
1.283 + armr.n = operand>>31;
1.284 + armr.z = (operand == 0);
1.285 + armr.c = armr.shift_c;
1.286 + }
1.287 + break;
1.288 + case 26: /* MOV Rd, operand */
1.289 + RD(ir) = arm_get_shift_operand(ir);
1.290 + break;
1.291 + case 27: /* MOVS Rd, operand */
1.292 + operand = arm_get_shift_operand_s(ir);
1.293 + RD(ir) = operand;
1.294 + if( RDn(ir) == 15 ) {
1.295 + arm_restore_cpsr();
1.296 + } else {
1.297 + armr.n = operand>>31;
1.298 + armr.z = (operand == 0);
1.299 + armr.c = armr.shift_c;
1.300 + }
1.301 + break;
1.302 + case 28: /* BIC Rd, Rn, operand */
1.303 + RD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
1.304 + break;
1.305 + case 29: /* BICS Rd, Rn, operand */
1.306 + operand = RN(ir) & (~arm_get_shift_operand_s(ir));
1.307 + RD(ir) = operand;
1.308 + if( RDn(ir) == 15 ) {
1.309 + arm_restore_cpsr();
1.310 + } else {
1.311 + armr.n = operand>>31;
1.312 + armr.z = (operand == 0);
1.313 + armr.c = armr.shift_c;
1.314 + }
1.315 + break;
1.316 + case 30: /* MVN Rd, operand */
1.317 + RD(ir) = ~arm_get_shift_operand(ir);
1.318 + break;
1.319 + case 31: /* MVNS Rd, operand */
1.320 + operand = ~arm_get_shift_operand_s(ir);
1.321 + RD(ir) = operand;
1.322 + if( RDn(ir) == 15 ) {
1.323 + arm_restore_cpsr();
1.324 + } else {
1.325 + armr.n = operand>>31;
1.326 + armr.z = (operand == 0);
1.327 + armr.c = armr.shift_c;
1.328 + }
1.329 + break;
1.330 + default:
1.331 + UNIMP(ir);
1.332 + }
1.333 + }
1.334 + break;
1.335 + case 1: /* Load/store */
1.336 + break;
1.337 + case 2: /* Load/store multiple, branch*/
1.338 + break;
1.339 + case 3: /* Copro */
1.340 + break;
1.341 + }
1.342 +
1.343 +
1.344 +
1.345 + return pc+4;
1.346 +}
.