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