Search
lxdream.org :: lxdream/src/aica/armdasm.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armdasm.c
changeset 7:976a16e92aab
prev4:7d6f596ce577
next11:0a82ef380c45
author nkeynes
date Sun Dec 12 07:44:09 2004 +0000 (15 years ago)
permissions -rw-r--r--
last change More progress on arm
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 "aica/armcore.h"
     9 #include <stdlib.h>
    11 #define COND(ir) (ir>>28)
    12 #define OPCODE(ir) ((ir>>20)&0x1F)
    13 #define GRP(ir) ((ir>>26)&0x03)
    14 #define IFLAG(ir) (ir&0x02000000)
    15 #define SFLAG(ir) (ir&0x00100000)
    16 #define PFLAG(ir) (ir&0x01000000)
    17 #define UFLAG(ir) (ir&0x00800000)
    18 #define BFLAG(ir) (ir&0x00400000)
    19 #define WFLAG(ir) (ir&0x00200000)
    20 #define LFLAG(ir) SFLAG(ir)
    21 #define RN(ir) ((ir>>16)&0x0F)
    22 #define RD(ir) ((ir>>12)&0x0F)
    23 #define RS(ir) ((ir>>8)&0x0F)
    24 #define RM(ir) (ir&0x0F)
    26 #define IMM8(ir) (ir&0xFF)
    27 #define IMM12(ir) (ir&0xFFF)
    28 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
    29 #define IMMROT(ir) ((ir>>7)&0x1E)
    30 #define SHIFT(ir) ((ir>>4)&0x07)
    31 #define DISP24(ir) ((ir&0x00FFFFFF))
    32 #define FSXC(ir) msrFieldMask[RN(ir)]
    33 #define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
    35 char *conditionNames[] = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", 
    36                            "HI", "LS", "GE", "LT", "GT", "LE", "  " /*AL*/, "NV" };
    38                          /* fsxc */
    39 char *msrFieldMask[] = { "", "c", "x", "xc", "s", "sc", "sx", "sxc",
    40 	                     "f", "fc", "fx", "fxc", "fs", "fsc", "fsx", "fsxc" };
    41 char *ldmModes[] = { "DA", "IA", "DB", "IB" };
    43 #define UNIMP(ir) snprintf( buf, len, "???     " )
    45 int arm_disasm_shift_operand( uint32_t ir, char *buf, int len )
    46 {
    47 	uint32_t operand, tmp;
    48 	if( IFLAG(ir) == 0 ) {
    49 		switch(SHIFT(ir)) {
    50 		case 0: /* (Rm << imm) */
    51 			return snprintf(buf, len, "R%d << %d", RM(ir), SHIFTIMM(ir) );
    52 		case 1: /* (Rm << Rs) */
    53 			return snprintf(buf, len, "R%d << R%d", RM(ir), RS(ir) );
    54 		case 2: /* (Rm >> imm) */
    55 			return snprintf(buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
    56 		case 3: /* (Rm >> Rs) */
    57 			return snprintf(buf, len, "R%d >> R%d", RM(ir), RS(ir) );
    58 		case 4: /* (Rm >>> imm) */
    59 			return snprintf(buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
    60 		case 5: /* (Rm >>> Rs) */
    61 			return snprintf(buf, len, "R%d >>> R%d", RM(ir), RS(ir) );
    62 		case 6:
    63 			tmp = SHIFTIMM(ir);
    64 			if( tmp == 0 ) /* RRX aka rotate with carry */
    65 				return snprintf(buf, len, "R%d roc 1", RM(ir) );
    66 			else
    67 				return snprintf(buf, len, "R%d rot %d", RM(ir), SHIFTIMM(ir) );
    68 		case 7:
    69 			return snprintf(buf, len, "R%d rot R%d", RM(ir), RS(ir) );
    70 		}
    71 	} else {
    72 		operand = IMM8(ir);
    73 		tmp = IMMROT(ir);
    74 		operand = ROTATE_RIGHT_LONG(operand, tmp);
    75 		return snprintf(buf, len, "%08X", operand );
    76 	}
    77 }
    79 static int arm_disasm_address_index( uint32_t ir, char *buf, int len )
    80 {
    81 	uint32_t tmp;
    83 	switch(SHIFT(ir)) {
    84 	case 0: /* (Rm << imm) */
    85 		return snprintf( buf, len, "R%d << %d", RM(ir), SHIFTIMM(ir) );
    86 	case 2: /* (Rm >> imm) */
    87 		return snprintf( buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
    88 	case 4: /* (Rm >>> imm) */
    89 		return snprintf( buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
    90 	case 6:
    91 		tmp = SHIFTIMM(ir);
    92 		if( tmp == 0 ) /* RRX aka rotate with carry */
    93 			return snprintf( buf, len, "R%d roc 1", RM(ir) );
    94 		else
    95 			return snprintf( buf, len, "R%d rot %d", RM(ir), tmp );
    96 	default: 
    97 		return UNIMP(ir);
    98 	}
    99 }
   101 static int arm_disasm_address_operand( uint32_t ir, char *buf, int len )
   102 {
   103     char  shift[32];
   105 	char sign = UFLAG(ir) ? '-' : '+';
   106 	/* I P U . W */
   107 	switch( (ir>>21)&0x19 ) {
   108 	case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
   109 	case 1:
   110 		return snprintf( buf, len, "[R%d], R%d %c= %04X", RN(ir), RN(ir), sign, IMM12(ir) );
   111 	case 8: /* Rn - imm offset  [5.2.2 A5-20] */
   112 		return snprintf( buf, len, "[R%d %c %04X]", RN(ir), sign, IMM12(ir) );
   113 	case 9: /* Rn -= imm offset (pre-indexed)  [5.2.5 A5-24] */
   114 		return snprintf( buf, len, "[R%d %c= %04X]", RN(ir), sign, IMM12(ir) );
   115 	case 16: /* Rn -= Rm (post-indexed)  [5.2.10 A5-32 ] */
   116 	case 17:
   117 		arm_disasm_address_index( ir, shift, sizeof(shift) );
   118 		return snprintf( buf, len, "[R%d], R%d %c= %s", RN(ir), RN(ir), sign, shift );
   119 	case 24: /* Rn - Rm  [5.2.4 A5-23] */
   120 		arm_disasm_address_index( ir, shift, sizeof(shift) );
   121 		return snprintf( buf, len, "[R%d %c %s]", RN(ir), sign, shift );
   122 	case 25: /* RN -= Rm (pre-indexed)  [5.2.7 A5-26] */
   123 		arm_disasm_address_index( ir, shift, sizeof(shift) );
   124 		return snprintf( buf, len, "[R%d %c= %s]", RN(ir), sign, shift );
   125 	default:
   126 		return UNIMP(ir); /* Unreachable */
   127 	}
   128 }
   130 int arm_disasm_instruction( uint32_t pc, char *buf, int len )
   131 {
   132 	char operand[32];
   133     uint32_t ir = arm_mem_read_long(pc);
   134 	int i,j;
   136     if( COND(ir) == 0x0F ) {
   137     	UNIMP(ir);
   138     	return pc+4;
   139     }
   140     char *cond = conditionNames[COND(ir)];
   142 	switch( GRP(ir) ) {
   143 	case 0:
   144 		if( (ir & 0x0D900000) == 0x01000000 ) {
   145 			/* Instructions that aren't actual data processing */
   146 			switch( ir & 0x0FF000F0 ) {
   147 			case 0x01200010: /* BXcc */
   148 				snprintf(buf, len, "BX%s     R%d", cond, RM(ir));
   149 				break;
   150 			case 0x01000000: /* MRS Rd, CPSR */
   151 				snprintf(buf, len, "MRS%s    R%d, CPSR", cond, RD(ir));
   152 				break;
   153 			case 0x01400000: /* MRS Rd, SPSR */
   154 				snprintf(buf, len, "MRS%s    R%d, SPSR", cond, RD(ir));
   155 				break;
   156 			case 0x01200000: /* MSR CPSR, Rm */
   157 				snprintf(buf, len, "MSR%s    CPSR_%s, R%d", cond, FSXC(ir), RM(ir));
   158 				break;
   159 			case 0x01600000: /* MSR SPSR, Rm */
   160 				snprintf(buf, len, "MSR%s    SPSR_%s, R%d", cond, FSXC(ir), RM(ir));
   161 				break;
   162 			case 0x03200000: /* MSR CPSR, imm */
   163 				snprintf(buf, len, "MSR%s    CPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
   164 				break;
   165 			case 0x03600000: /* MSR SPSR, imm */
   166 				snprintf(buf, len, "MSR%s    SPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
   167 				break;
   168 			default:
   169 				UNIMP();
   170 			}
   171 		} else if( (ir & 0x0E000090) == 0x00000090 ) {
   172 			/* Neither are these */
   173 			switch( (ir>>5)&0x03 ) {
   174 			case 0:
   175 				/* Arithmetic extension area */
   176 				switch(OPCODE(ir)) {
   177 				case 0: /* MUL */
   178 					snprintf(buf,len, "MUL%s    R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir) );
   179 					break;
   180 				case 1: /* MULS */
   181 					break;
   182 				case 2: /* MLA */
   183 					snprintf(buf,len, "MLA%s    R%d, R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir), RD(ir) );
   184 					break;
   185 				case 3: /* MLAS */
   186 					break;
   187 				case 8: /* UMULL */
   188 					snprintf(buf,len, "UMULL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   189 					break;
   190 				case 9: /* UMULLS */
   191 					break;
   192 				case 10: /* UMLAL */
   193 					snprintf(buf,len, "UMLAL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   194 					break;
   195 				case 11: /* UMLALS */
   196 					break;
   197 				case 12: /* SMULL */
   198 					snprintf(buf,len, "SMULL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   199 					break;
   200 				case 13: /* SMULLS */
   201 					break;
   202 				case 14: /* SMLAL */
   203 					snprintf(buf,len, "SMLAL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   204 					break;
   205 				case 15: /* SMLALS */
   207 					break;
   208 				case 16: /* SWP */
   209 					snprintf(buf,len, "SWP%s    R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
   210 					break;
   211 				case 20: /* SWPB */
   212 					snprintf(buf,len, "SWPB%s   R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
   213 					break;
   214 				default:
   215 					UNIMP(ir);
   216 				}
   217 				break;
   218 			case 1:
   219 				if( LFLAG(ir) ) {
   220 					/* LDRH */
   221 				} else {
   222 					/* STRH */
   223 				}
   224 				break;
   225 			case 2:
   226 				if( LFLAG(ir) ) {
   227 					/* LDRSB */
   228 				} else {
   229 					UNIMP(ir);
   230 				}
   231 				break;
   232 			case 3:
   233 				if( LFLAG(ir) ) {
   234 					/* LDRSH */
   235 				} else {
   236 					UNIMP(ir);
   237 				}
   238 				break;
   239 			}
   240 		} else {
   241 			/* Data processing */
   243 			switch(OPCODE(ir)) {
   244 			case 0: /* AND Rd, Rn, operand */
   245 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   246 				snprintf(buf, len, "AND%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   247 				break;
   248 			case 1: /* ANDS Rd, Rn, operand */
   249 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   250 				snprintf(buf, len, "ANDS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   251 				break;
   252 			case 2: /* EOR Rd, Rn, operand */
   253 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   254 				snprintf(buf, len, "EOR%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   255 				break;
   256 			case 3: /* EORS Rd, Rn, operand */
   257 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   258 				snprintf(buf, len, "EORS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   259 				break;
   260 			case 4: /* SUB Rd, Rn, operand */
   261 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   262 				snprintf(buf, len, "SUB%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   263 				break;
   264 			case 5: /* SUBS Rd, Rn, operand */
   265 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   266 				snprintf(buf, len, "SUBS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   267 				break;
   268 			case 6: /* RSB Rd, Rn, operand */
   269 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   270 				snprintf(buf, len, "RSB%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   271 				break;
   272 			case 7: /* RSBS Rd, Rn, operand */
   273 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   274 				snprintf(buf, len, "RSBS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   275 				break;
   276 			case 8: /* ADD Rd, Rn, operand */
   277 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   278 				snprintf(buf, len, "ADD%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   279 				break;
   280 			case 9: /* ADDS Rd, Rn, operand */
   281 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   282 				snprintf(buf, len, "ADDS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   283 				break;
   284 			case 10: /* ADC Rd, Rn, operand */
   285 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   286 				snprintf(buf, len, "ADC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   287 				break;
   288 			case 11: /* ADCS Rd, Rn, operand */
   289 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   290 				snprintf(buf, len, "ADCS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   291 				break;
   292 			case 12: /* SBC Rd, Rn, operand */
   293 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   294 				snprintf(buf, len, "SBC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   295 				break;
   296 			case 13: /* SBCS Rd, Rn, operand */
   297 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   298 				snprintf(buf, len, "SBCS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   299 				break;
   300 			case 14: /* RSC Rd, Rn, operand */
   301 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   302 				snprintf(buf, len, "RSC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   303 				break;
   304 			case 15: /* RSCS Rd, Rn, operand */
   305 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   306 				snprintf(buf, len, "RSCS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   307 				break;
   308 			case 16: /* TST Rd, Rn, operand */
   309 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   310 				snprintf(buf, len, "TST%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   311 				break;
   312 			case 18: /* TEQ Rd, Rn, operand */
   313 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   314 				snprintf(buf, len, "TEQ%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   315 				break;
   316 			case 20: /* CMP Rd, Rn, operand */
   317 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   318 				snprintf(buf, len, "CMP%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   319 				break;
   320 			case 22: /* CMN Rd, Rn, operand */
   321 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   322 				snprintf(buf, len, "CMN%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   323 				break;
   324 			case 24: /* ORR Rd, Rn, operand */
   325 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   326 				snprintf(buf, len, "ORR%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   327 				break;
   328 			case 25: /* ORRS Rd, Rn, operand */
   329 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   330 				snprintf(buf, len, "ORRS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   331 				break;
   332 			case 26: /* MOV Rd, Rn, operand */
   333 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   334 				snprintf(buf, len, "MOV%s    R%d, %s", cond, RD(ir), operand);
   335 				break;
   336 			case 27: /* MOVS Rd, Rn, operand */
   337 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   338 				snprintf(buf, len, "MOVS%s   R%d, %s", cond, RD(ir), operand);
   339 				break;
   340 			case 28: /* BIC Rd, Rn, operand */
   341 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   342 				snprintf(buf, len, "BIC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   343 				break;
   344 			case 29: /* BICS Rd, Rn, operand */
   345 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   346 				snprintf(buf, len, "BICS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   347 				break;
   348 			case 30: /* MVN Rd, Rn, operand */
   349 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   350 				snprintf(buf, len, "MVN%s    R%d, %s", cond, RD(ir), operand);
   351 				break;
   352 			case 31: /* MVNS Rd, Rn, operand */
   353 				arm_disasm_shift_operand(ir, operand, sizeof(operand));
   354 				snprintf(buf, len, "MVNS%s   R%d, %s", cond, RD(ir), operand);
   355 				break;
   356 			default:
   357 				UNIMP(ir);
   358 			}
   359 		}
   360 		break;
   361 	case 1: /* Load/store */
   362 		arm_disasm_address_operand( ir, operand, sizeof(operand) );
   363 		switch( (ir>>20)&0x17 ) {
   364 			case 0:
   365 			case 16:
   366 			case 18:
   367 				snprintf(buf, len, "STR%s    R%d, %s", cond, RD(ir), operand );
   368 				break;
   369 			case 1:
   370 			case 17:
   371 			case 19:
   372 				snprintf(buf, len, "LDR%s    R%d, %s", cond, RD(ir), operand );
   373 				break;
   374 			case 2:
   375 				snprintf(buf, len, "STRT%s   R%d, %s", cond, RD(ir), operand );
   376 				break;
   377 			case 3:
   378 				snprintf(buf, len, "LDRT%s   R%d, %s", cond, RD(ir), operand );
   379 				break;
   380 			case 4:
   381 			case 20:
   382 			case 22:
   383 				snprintf(buf, len, "STRB%s   R%d, %s", cond, RD(ir), operand );
   384 				break;
   385 			case 5:
   386 			case 21:
   387 			case 23:
   388 				snprintf(buf, len, "LDRB%s   R%d, %s", cond, RD(ir), operand );
   389 				break;
   390 			case 6:
   391 				snprintf(buf, len, "STRBT%s  R%d, %s", cond, RD(ir), operand );
   392 				break;
   393 			case 7: 
   394 				snprintf(buf, len, "LDRBT%s  R%d, %s", cond, RD(ir), operand );
   395 				break;
   396 		}
   397 		break;
   398 	case 2: /* Load/store multiple, branch*/
   399 		j = snprintf( buf, len, LFLAG(ir) ? "LDM%s%s  R%d%c,":"STM%s%s  R%d%c,", 
   400 	              ldmModes[(ir>>23)&0x03], cond, RN(ir), WFLAG(ir)?'!':' ' );
   401 		buf += j;
   402 		len -= j;
   403 		for( i = 0; i<16 && len > 2; i++ ) {
   404 			if( (ir >> i)&1 ) {
   405 				j = snprintf( buf, len, "R%d", i );
   406 				buf+=j;
   407 				len-=j;
   408 			}
   409 		}
   410 		if( SFLAG(ir) && len > 0 ) {
   411 			buf[0] = '^';
   412 			buf[1] = '\0';
   413 		}
   414 		break;
   415 	case 3: /* Copro */
   416 		UNIMP(ir);
   417 		break;
   418 	}
   422 	return pc+4;
   423 }
.