Search
lxdream.org :: lxdream/src/aica/armdasm.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armdasm.c
changeset 64:f8864188e83f
prev60:d09f85b2a583
next302:96b5cc24309c
author nkeynes
date Wed Jan 03 09:00:17 2007 +0000 (17 years ago)
permissions -rw-r--r--
last change Adjust timers when they're read rather than waiting until the next time
slice. Also temporarily cut the CPU time by 4.
Initialize the FRQCR register to 0x0E0A for convenience
view annotate diff log raw
     1 /**
     2  * $Id: armdasm.c,v 1.11 2006-01-03 12:20:36 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, %s", cond, 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, %s", cond, 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, %s", cond, 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, %s", cond, 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", cond, 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 }
.