Search
lxdream.org :: lxdream/src/aica/armdasm.c
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 (18 years ago)
permissions -rw-r--r--
last change Add armdasm
view annotate diff log raw
     1 /*
     2  * armdasm.c    21 Aug 2004  - ARM7tdmi (ARMv4) disassembler
     3  *
     4  * Copyright (c) 2004 Nathan Keynes. Distribution and modification permitted
     5  * under the terms of the GNU General Public License version 2 or later.
     6  */
     8 #include "armcore.h"
    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" };
    37                          /* fsxc */
    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 )
    44 {
    45     uint32_t ir = arm_mem_read_long(pc);
    47     if( COND(ir) == 0x0F ) {
    48     	UNIMP(ir);
    49     	return pc+4;
    50     }
    51     char *cond = conditionNames[COND(ir)];
    53 	switch( GRP(ir) ) {
    54 	case 0:
    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));
    60 				break;
    61 			case 0x01000000: /* MRS Rd, CPSR */
    62 				snprintf(buf, len, "MRS%s    R%d, CPSR", cond, RD(ir));
    63 				break;
    64 			case 0x01400000: /* MRS Rd, SPSR */
    65 				snprintf(buf, len, "MRS%s    R%d, SPSR", cond, RD(ir));
    66 				break;
    67 			case 0x01200000: /* MSR CPSR, Rm */
    68 				snprintf(buf, len, "MSR%s    CPSR_%s, R%d", cond, FSXC(ir), RM(ir));
    69 				break;
    70 			case 0x01600000: /* MSR SPSR, Rm */
    71 				snprintf(buf, len, "MSR%s    SPSR_%s, R%d", cond, FSXC(ir), RM(ir));
    72 				break;
    73 			case 0x03200000: /* MSR CPSR, imm */
    74 				snprintf(buf, len, "MSR%s    CPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
    75 				break;
    76 			case 0x03600000: /* MSR SPSR, imm */
    77 				snprintf(buf, len, "MSR%s    SPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
    78 				break;
    79 			default:
    80 				UNIMP();
    81 			}
    82 		} else if( (ir & 0x0E000090) == 0x00000090 ) {
    83 			/* Neither are these */
    84 			switch( (ir>>5)&0x03 ) {
    85 			case 0:
    86 				/* Arithmetic extension area */
    87 				switch(OPCODE(ir)) {
    88 				case 0: /* MUL */
    89 					snprintf(buf,len, "MUL%s    R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir) );
    90 					break;
    91 				case 1: /* MULS */
    92 					break;
    93 				case 2: /* MLA */
    94 					snprintf(buf,len, "MLA%s    R%d, R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir), RD(ir) );
    95 					break;
    96 				case 3: /* MLAS */
    97 					break;
    98 				case 8: /* UMULL */
    99 					snprintf(buf,len, "UMULL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   100 					break;
   101 				case 9: /* UMULLS */
   102 					break;
   103 				case 10: /* UMLAL */
   104 					snprintf(buf,len, "UMLAL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   105 					break;
   106 				case 11: /* UMLALS */
   107 					break;
   108 				case 12: /* SMULL */
   109 					snprintf(buf,len, "SMULL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   110 					break;
   111 				case 13: /* SMULLS */
   112 					break;
   113 				case 14: /* SMLAL */
   114 					snprintf(buf,len, "SMLAL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   115 					break;
   116 				case 15: /* SMLALS */
   118 					break;
   119 				case 16: /* SWP */
   120 					snprintf(buf,len, "SWP%s    R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
   121 					break;
   122 				case 20: /* SWPB */
   123 					snprintf(buf,len, "SWPB%s   R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
   124 					break;
   125 				default:
   126 					UNIMP(ir);
   127 				}
   128 				break;
   129 			case 1:
   130 				if( LFLAG(ir) ) {
   131 					/* LDRH */
   132 				} else {
   133 					/* STRH */
   134 				}
   135 				break;
   136 			case 2:
   137 				if( LFLAG(ir) ) {
   138 					/* LDRSB */
   139 				} else {
   140 					UNIMP(ir);
   141 				}
   142 				break;
   143 			case 3:
   144 				if( LFLAG(ir) ) {
   145 					/* LDRSH */
   146 				} else {
   147 					UNIMP(ir);
   148 				}
   149 				break;
   150 			}
   151 		} else {
   152 			/* Data processing */
   154 			switch(OPCODE(ir)) {
   155 			case 0: /* AND Rd, Rn, operand */
   156 				RD(ir) = RN(ir) & arm_get_shift_operand(ir);
   157 				break;
   158 			case 1: /* ANDS Rd, Rn, operand */
   159 				operand = arm_get_shift_operand_s(ir) & RN(ir);
   160 				RD(ir) = operand;
   161 				if( RDn(ir) == 15 ) {
   162 					arm_restore_cpsr();
   163 				} else {
   164 					armr.n = operand>>31;
   165 					armr.z = (operand == 0);
   166 					armr.c = armr.shift_c;
   167 				}
   168 				break;
   169 			case 2: /* EOR Rd, Rn, operand */
   170 				RD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
   171 				break;
   172 			case 3: /* EORS Rd, Rn, operand */
   173 				operand = arm_get_shift_operand_s(ir) ^ RN(ir);
   174 				RD(ir) = operand;
   175 				if( RDn(ir) == 15 ) {
   176 					arm_restore_cpsr();
   177 				} else {
   178 					armr.n = operand>>31;
   179 					armr.z = (operand == 0);
   180 					armr.c = armr.shift_c;
   181 				}
   182 				break;
   183 			case 4: /* SUB Rd, Rn, operand */
   184 				RD(ir) = RN(ir) - arm_get_shift_operand(ir);
   185 				break;
   186 			case 5: /* SUBS Rd, Rn, operand */
   187 			    operand = RN(ir);
   188 				operand2 = arm_get_shift_operand(ir)
   189 				tmp = operand - operand2;
   190 				RD(ir) = tmp;
   191 				if( RDn(ir) == 15 ) {
   192 					arm_restore_cpsr();
   193 				} else {
   194 					armr.n = tmp>>31;
   195 					armr.z = (tmp == 0);
   196 					armr.c = IS_NOTBORROW(tmp,operand,operand2);
   197 					armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   198 				}
   199 				break;
   200 			case 6: /* RSB Rd, operand, Rn */
   201 				RD(ir) = arm_get_shift_operand(ir) - RN(ir);
   202 				break;
   203 			case 7: /* RSBS Rd, operand, Rn */
   204 				operand = arm_get_shift_operand(ir);
   205 			    operand2 = RN(ir);
   206 				tmp = operand - operand2;
   207 				RD(ir) = tmp;
   208 				if( RDn(ir) == 15 ) {
   209 					arm_restore_cpsr();
   210 				} else {
   211 					armr.n = tmp>>31;
   212 					armr.z = (tmp == 0);
   213 					armr.c = IS_NOTBORROW(tmp,operand,operand2);
   214 					armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   215 				}
   216 				break;
   217 			case 8: /* ADD Rd, Rn, operand */
   218 				RD(ir) = RN(ir) + arm_get_shift_operand(ir);
   219 				break;
   220 			case 9: /* ADDS Rd, Rn, operand */
   221 				operand = arm_get_shift_operand(ir);
   222 			    operand2 = RN(ir);
   223 				tmp = operand + operand2
   224 				RD(ir) = tmp;
   225 				if( RDn(ir) == 15 ) {
   226 					arm_restore_cpsr();
   227 				} else {
   228 					armr.n = tmp>>31;
   229 					armr.z = (tmp == 0);
   230 					armr.c = IS_CARRY(tmp,operand,operand2);
   231 					armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
   232 				}
   233 				break;			
   234 			case 10: /* ADC */
   235 			case 11: /* ADCS */
   236 			case 12: /* SBC */
   237 			case 13: /* SBCS */
   238 			case 14: /* RSC */
   239 			case 15: /* RSCS */
   240 				break;
   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;
   246 				break;
   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;
   252 				break;				
   253 			case 21: /* CMP Rn, operand */
   254 			    operand = RN(ir);
   255 				operand2 = arm_get_shift_operand(ir)
   256 				tmp = operand - operand2;
   257 				armr.n = tmp>>31;
   258 				armr.z = (tmp == 0);
   259 				armr.c = IS_NOTBORROW(tmp,operand,operand2);
   260 				armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   261 				break;
   262 			case 23: /* CMN Rn, operand */
   263 			    operand = RN(ir);
   264 				operand2 = arm_get_shift_operand(ir)
   265 				tmp = operand + operand2;
   266 				armr.n = tmp>>31;
   267 				armr.z = (tmp == 0);
   268 				armr.c = IS_CARRY(tmp,operand,operand2);
   269 				armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
   270 				break;
   271 			case 24: /* ORR Rd, Rn, operand */
   272 				RD(ir) = RN(ir) | arm_get_shift_operand(ir);
   273 				break;
   274 			case 25: /* ORRS Rd, Rn, operand */
   275 				operand = arm_get_shift_operand_s(ir) | RN(ir);
   276 				RD(ir) = operand;
   277 				if( RDn(ir) == 15 ) {
   278 					arm_restore_cpsr();
   279 				} else {
   280 					armr.n = operand>>31;
   281 					armr.z = (operand == 0);
   282 					armr.c = armr.shift_c;
   283 				}
   284 				break;
   285 			case 26: /* MOV Rd, operand */
   286 				RD(ir) = arm_get_shift_operand(ir);
   287 				break;
   288 			case 27: /* MOVS Rd, operand */
   289 				operand = arm_get_shift_operand_s(ir);
   290 				RD(ir) = operand;
   291 				if( RDn(ir) == 15 ) {
   292 					arm_restore_cpsr();
   293 				} else {
   294 					armr.n = operand>>31;
   295 					armr.z = (operand == 0);
   296 					armr.c = armr.shift_c;
   297 				}
   298 				break;
   299 			case 28: /* BIC Rd, Rn, operand */
   300 				RD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
   301 				break;
   302 			case 29: /* BICS Rd, Rn, operand */
   303 				operand = RN(ir) & (~arm_get_shift_operand_s(ir));
   304 				RD(ir) = operand;
   305 				if( RDn(ir) == 15 ) {
   306 					arm_restore_cpsr();
   307 				} else {
   308 					armr.n = operand>>31;
   309 					armr.z = (operand == 0);
   310 					armr.c = armr.shift_c;
   311 				}
   312 				break;
   313 			case 30: /* MVN Rd, operand */
   314 				RD(ir) = ~arm_get_shift_operand(ir);
   315 				break;
   316 			case 31: /* MVNS Rd, operand */
   317 				operand = ~arm_get_shift_operand_s(ir);
   318 				RD(ir) = operand;
   319 				if( RDn(ir) == 15 ) {
   320 					arm_restore_cpsr();
   321 				} else {
   322 					armr.n = operand>>31;
   323 					armr.z = (operand == 0);
   324 					armr.c = armr.shift_c;
   325 				}
   326 				break;
   327 			default:
   328 				UNIMP(ir);
   329 			}
   330 		}
   331 		break;
   332 	case 1: /* Load/store */
   333 		break;
   334 	case 2: /* Load/store multiple, branch*/
   335 		break;
   336 	case 3: /* Copro */
   337 		break;
   338 	}
   342 	return pc+4;
   343 }
.