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