revision 4:7d6f596ce577
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 4:7d6f596ce577 |
parent | 3:999d7586a739 |
child | 5:d85c2e81ce2d |
author | nkeynes |
date | Sat Oct 02 05:49:12 2004 +0000 (19 years ago) |
Add armdasm
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +00001.2 +++ b/src/aica/armdasm.c Sat Oct 02 05:49:12 2004 +00001.3 @@ -0,0 +1,343 @@1.4 +/*1.5 + * armdasm.c 21 Aug 2004 - ARM7tdmi (ARMv4) disassembler1.6 + *1.7 + * Copyright (c) 2004 Nathan Keynes. Distribution and modification permitted1.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 + operand21.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 +}
.