Search
lxdream.org :: lxdream/src/aica/armdasm.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armdasm.c
changeset 1091:186558374345
prev998:1754a8c6a9cf
author nkeynes
date Tue Dec 15 08:46:37 2009 +1000 (11 years ago)
permissions -rw-r--r--
last change Add side-by-side x86+sh4 disassembly output
Print SH4 state information and disassembly of the current block when
crashing.
Fix delay slot instruction in conditional branch not being marked as a
delay-slot instruction in the branch-not-taken path.
Rename REG_* defines in cpu.h to avoid conflict with translation defs
view annotate diff log raw
     1 /**
     2  * $Id$
     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 IMMSPLIT8(ir) (((ir&0xF00)>>4)|(ir&0x0F))
    41 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
    42 #define IMMROT(ir) ((ir>>7)&0x1E)
    43 #define SHIFT(ir) ((ir>>4)&0x07)
    44 #define DISP24(ir) ((ir&0x00FFFFFF))
    45 #define FSXC(ir) msrFieldMask[RN(ir)]
    46 #define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
    47 #define SIGNEXT24(n) (((n)&0x00800000) ? ((n)|0xFF000000) : ((n)&0x00FFFFFF))
    51 const struct reg_desc_struct arm_reg_map[] = 
    52 { {"R0", REG_TYPE_INT, &armr.r[0]}, {"R1", REG_TYPE_INT, &armr.r[1]},
    53         {"R2", REG_TYPE_INT, &armr.r[2]}, {"R3", REG_TYPE_INT, &armr.r[3]},
    54         {"R4", REG_TYPE_INT, &armr.r[4]}, {"R5", REG_TYPE_INT, &armr.r[5]},
    55         {"R6", REG_TYPE_INT, &armr.r[6]}, {"R7", REG_TYPE_INT, &armr.r[7]},
    56         {"R8", REG_TYPE_INT, &armr.r[8]}, {"R9", REG_TYPE_INT, &armr.r[9]},
    57         {"R10",REG_TYPE_INT, &armr.r[10]}, {"R11",REG_TYPE_INT, &armr.r[11]},
    58         {"R12",REG_TYPE_INT, &armr.r[12]}, {"R13",REG_TYPE_INT, &armr.r[13]},
    59         {"R14",REG_TYPE_INT, &armr.r[14]}, {"R15",REG_TYPE_INT, &armr.r[15]},
    61         /* Block of FPA registers (arm-elf-gdb seems to expect these).
    62          * Oddly enough the ARM7TDMI doesn't have them */
    63         {"F0",REG_TYPE_NONE, NULL}, {"F1",REG_TYPE_NONE, NULL},
    64         {"F2",REG_TYPE_NONE, NULL}, {"F3",REG_TYPE_NONE, NULL},
    65         {"F4",REG_TYPE_NONE, NULL}, {"F5",REG_TYPE_NONE, NULL},
    66         {"F6",REG_TYPE_NONE, NULL}, {"F7",REG_TYPE_NONE, NULL},
    67         {"FPS",REG_TYPE_NONE, NULL},
    69         /* System registers */
    70         {"CPSR", REG_TYPE_INT, &armr.cpsr}, {"SPSR", REG_TYPE_INT, &armr.spsr},
    71         {NULL, 0, NULL} };
    73 /* Implementation of get_register - ARM has no pseudo registers so this
    74  * is pretty simple
    75  */
    76 void *arm_get_register( int reg )
    77 {
    78     if( reg < 0 || reg >= 27 )
    79         return NULL;
    80     return arm_reg_map[reg].value;
    81 }
    83 const struct cpu_desc_struct arm_cpu_desc = 
    84 { "ARM7", arm_disasm_instruction, arm_get_register, arm_has_page,
    85         arm_read_phys, arm_write_phys, arm_read_phys, arm_write_phys,
    86         arm_execute_instruction, arm_set_breakpoint, arm_clear_breakpoint, 
    87         arm_get_breakpoint, 4, (char *)&armr, sizeof(armr), arm_reg_map, 26, 26,
    88         &armr.r[15] };
    89 const struct cpu_desc_struct armt_cpu_desc = 
    90 { "ARM7T", armt_disasm_instruction, arm_get_register, arm_has_page, 
    91         arm_read_phys, arm_write_phys, arm_read_phys, arm_write_phys,
    92         arm_execute_instruction,  arm_set_breakpoint, arm_clear_breakpoint, 
    93         arm_get_breakpoint, 2, (char*)&armr, sizeof(armr), arm_reg_map, 26, 26,
    94         &armr.r[15] };
    99 char *conditionNames[] = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", 
   100         "HI", "LS", "GE", "LT", "GT", "LE", "  " /*AL*/, "NV" };
   102 /* fsxc */
   103 char *msrFieldMask[] = { "", "c", "x", "xc", "s", "sc", "sx", "sxc",
   104         "f", "fc", "fx", "fxc", "fs", "fsc", "fsx", "fsxc" };
   105 char *ldmModes[] = { "DA", "IA", "DB", "IB" };
   107 #define UNIMP(ir) snprintf( buf, len, "???     " )
   109 int arm_disasm_shift_operand( uint32_t ir, char *buf, int len )
   110 {
   111     uint32_t operand, tmp;
   112     if( IFLAG(ir) == 0 ) {
   113         switch(SHIFT(ir)) {
   114         case 0: /* (Rm << imm) */
   115             tmp = SHIFTIMM(ir);
   116             if( tmp != 0 ) {
   117                 return snprintf(buf, len, "R%d << %d", RM(ir), tmp );
   118             } else {
   119                 return snprintf(buf, len, "R%d", RM(ir));
   120             }
   121         case 1: /* (Rm << Rs) */
   122             return snprintf(buf, len, "R%d << R%d", RM(ir), RS(ir) );
   123         case 2: /* (Rm >> imm) */
   124             return snprintf(buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
   125         case 3: /* (Rm >> Rs) */
   126             return snprintf(buf, len, "R%d >> R%d", RM(ir), RS(ir) );
   127         case 4: /* (Rm >>> imm) */
   128             return snprintf(buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
   129         case 5: /* (Rm >>> Rs) */
   130             return snprintf(buf, len, "R%d >>> R%d", RM(ir), RS(ir) );
   131         case 6:
   132             tmp = SHIFTIMM(ir);
   133             if( tmp == 0 ) /* RRX aka rotate with carry */
   134                 return snprintf(buf, len, "R%d roc 1", RM(ir) );
   135             else
   136                 return snprintf(buf, len, "R%d rot %d", RM(ir), SHIFTIMM(ir) );
   137         case 7:
   138             return snprintf(buf, len, "R%d rot R%d", RM(ir), RS(ir) );
   139         }
   140     } else {
   141         operand = IMM8(ir);
   142         tmp = IMMROT(ir);
   143         operand = ROTATE_RIGHT_LONG(operand, tmp);
   144         return snprintf(buf, len, "#%08Xh", operand );
   145     }
   146     return 0;
   147 }
   149 static int arm_disasm_address_index( uint32_t ir, char *buf, int len )
   150 {
   151     uint32_t tmp;
   153     switch(SHIFT(ir)) {
   154     case 0: /* (Rm << imm) */
   155         tmp = SHIFTIMM(ir);
   156         if( tmp != 0 ) {
   157             return snprintf( buf, len, "R%d << %d", RM(ir), tmp );
   158         } else {
   159             return snprintf( buf, len, "R%d", RM(ir) );
   160         }
   161     case 2: /* (Rm >> imm) */
   162         return snprintf( buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
   163     case 4: /* (Rm >>> imm) */
   164         return snprintf( buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
   165     case 6:
   166         tmp = SHIFTIMM(ir);
   167         if( tmp == 0 ) /* RRX aka rotate with carry */
   168             return snprintf( buf, len, "R%d roc 1", RM(ir) );
   169         else
   170             return snprintf( buf, len, "R%d rot %d", RM(ir), tmp );
   171     default: 
   172         return UNIMP(ir);
   173     }
   174 }
   176 static int arm_disasm_address_operand( uint32_t ir, char *buf, int len,  int pc )
   177 {
   178     char  shift[32];
   180     char sign = UFLAG(ir) ? '+' : '-';
   181     /* I P U . W */
   182     switch( (ir>>21)&0x19 ) {
   183     case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
   184     case 1:
   185         return snprintf( buf, len, "[R%d], R%d %c= #%04Xh", RN(ir), RN(ir), sign, IMM12(ir) );
   186     case 8: /* Rn - imm offset  [5.2.2 A5-20] */
   187         if( RN(ir) == 15 ) { /* PC relative - decode here */
   188             uint32_t addr = pc + 8 + (UFLAG(ir) ? IMM12(ir) : -IMM12(ir));
   189             return snprintf( buf, len, "[$%08Xh] <- #%08Xh", addr,
   190                     arm_read_long( addr ) );
   191         } else {
   192             return snprintf( buf, len, "[R%d %c #%04Xh]", RN(ir), sign, IMM12(ir) );
   193         }
   194     case 9: /* Rn -= imm offset (pre-indexed)  [5.2.5 A5-24] */
   195         return snprintf( buf, len, "[R%d %c= #%04Xh]", RN(ir), sign, IMM12(ir) );
   196     case 16: /* Rn -= Rm (post-indexed)  [5.2.10 A5-32 ] */
   197     case 17:
   198         arm_disasm_address_index( ir, shift, sizeof(shift) );
   199         return snprintf( buf, len, "[R%d], R%d %c= %s", RN(ir), RN(ir), sign, shift );
   200     case 24: /* Rn - Rm  [5.2.4 A5-23] */
   201         arm_disasm_address_index( ir, shift, sizeof(shift) );
   202         return snprintf( buf, len, "[R%d %c %s]", RN(ir), sign, shift );
   203     case 25: /* RN -= Rm (pre-indexed)  [5.2.7 A5-26] */
   204         arm_disasm_address_index( ir, shift, sizeof(shift) );
   205         return snprintf( buf, len, "[R%d %c= %s]", RN(ir), sign, shift );
   206     default:
   207         return UNIMP(ir); /* Unreachable */
   208     }
   209 }
   211 static int arm_disasm_address3_operand( uint32_t ir, char *buf, int len, int pc )
   212 {
   213 	char sign = UFLAG(ir) ? '+' : '-';
   215 	switch( (ir>>21) & 0x0B) {
   216     case 0: /* Rn -= Rm (post-indexed) [5.3.7 A5-48] */
   217     case 1: /* UNPREDICTABLE */
   218     	return snprintf( buf, len, "[R%d], R%d %c= R%d", RN(ir), RN(ir), sign, RM(ir) ) ;
   219     case 2: /* Rn -= imm (post-indexed) [5.3.6 A5-46] */
   220     case 3: /* UNPREDICTABLE */
   221     	return snprintf( buf, len, "[R%d], R%d %c= #%04Xh", RN(ir), RN(ir), sign, IMMSPLIT8(ir) );
   222     case 8: /* Rn - Rm [5.3.3 A5-38] */
   223     	return snprintf( buf, len, "[R%d %c R%d]", RN(ir), sign, RM(ir) );
   224     case 9: /* Rn -= Rm (pre-indexed) [5.3.5 A5-42] */
   225     	return snprintf( buf, len, "[R%d %c= R%d]", RN(ir), sign, RM(ir) );
   226     case 10: /* Rn - imm offset [5.3.2 A5-36] */
   227     	return snprintf( buf, len, "[R%d %c #%04Xh]", RN(ir), sign, IMMSPLIT8(ir) );
   228     case 11: /* Rn -= imm offset (pre-indexed) [5.3.4 A5-40] */
   229     	return snprintf( buf, len, "[R%d %c= #%04Xh]", RN(ir), sign, IMMSPLIT8(ir) );
   230     default:
   231     	return UNIMP(ir); /* Unreachable */
   232     }
   233 }
   235 uint32_t arm_disasm_instruction( uint32_t pc, char *buf, int len, char *opcode )
   236 {
   237     char operand[64];
   238     uint32_t ir = arm_read_long(pc);
   239     int i,j;
   241     sprintf( opcode, "%08X", ir );
   243     if( COND(ir) == 0x0F ) {
   244         UNIMP(ir);
   245         return pc+4;
   246     }
   247     char *cond = conditionNames[COND(ir)];
   249     switch( GRP(ir) ) {
   250     case 0:
   251         if( (ir & 0x0D900000) == 0x01000000 ) {
   252             /* Instructions that aren't actual data processing */
   253             switch( ir & 0x0FF000F0 ) {
   254             case 0x01200010: /* BXcc */
   255                 snprintf(buf, len, "BX%s     R%d", cond, RM(ir));
   256                 break;
   257             case 0x01000000: /* MRS Rd, CPSR */
   258                 snprintf(buf, len, "MRS%s    R%d, CPSR", cond, RD(ir));
   259                 break;
   260             case 0x01400000: /* MRS Rd, SPSR */
   261                 snprintf(buf, len, "MRS%s    R%d, SPSR", cond, RD(ir));
   262                 break;
   263             case 0x01200000: /* MSR CPSR, Rm */
   264                 snprintf(buf, len, "MSR%s    CPSR_%s, R%d", cond, FSXC(ir), RM(ir));
   265                 break;
   266             case 0x01600000: /* MSR SPSR, Rm */
   267                 snprintf(buf, len, "MSR%s    SPSR_%s, R%d", cond, FSXC(ir), RM(ir));
   268                 break;
   269             case 0x03200000: /* MSR CPSR, imm */
   270                 snprintf(buf, len, "MSR%s    CPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
   271                 break;
   272             case 0x03600000: /* MSR SPSR, imm */
   273                 snprintf(buf, len, "MSR%s    SPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
   274                 break;
   275             default:
   276                 UNIMP();
   277             }
   278         } else if( (ir & 0x0E000090) == 0x00000090 ) {
   279             /* Neither are these */
   280             switch( (ir>>5)&0x03 ) {
   281             case 0:
   282                 /* Arithmetic extension area */
   283                 switch(OPCODE(ir)) {
   284                 case 0: /* MUL */
   285                     snprintf(buf,len, "MUL%s    R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir) );
   286                     break;
   287                 case 1: /* MULS */
   288                     break;
   289                 case 2: /* MLA */
   290                     snprintf(buf,len, "MLA%s    R%d, R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir), RD(ir) );
   291                     break;
   292                 case 3: /* MLAS */
   293                     break;
   294                 case 8: /* UMULL */
   295                     snprintf(buf,len, "UMULL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   296                     break;
   297                 case 9: /* UMULLS */
   298                     break;
   299                 case 10: /* UMLAL */
   300                     snprintf(buf,len, "UMLAL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   301                     break;
   302                 case 11: /* UMLALS */
   303                     break;
   304                 case 12: /* SMULL */
   305                     snprintf(buf,len, "SMULL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   306                     break;
   307                 case 13: /* SMULLS */
   308                     break;
   309                 case 14: /* SMLAL */
   310                     snprintf(buf,len, "SMLAL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   311                     break;
   312                 case 15: /* SMLALS */
   314                     break;
   315                 case 16: /* SWP */
   316                     snprintf(buf,len, "SWP%s    R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
   317                     break;
   318                 case 20: /* SWPB */
   319                     snprintf(buf,len, "SWPB%s   R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
   320                     break;
   321                 default:
   322                     UNIMP(ir);
   323                 }
   324                 break;
   325                 case 1:
   326                     arm_disasm_address3_operand( ir, operand, sizeof(operand), pc );
   327                     if( LFLAG(ir) ) { /* LDRH */
   328                         snprintf(buf, len, "LDR%sH    R%d, %s", cond, RD(ir), operand );
   329                     } else { /* STRH */
   330                         snprintf(buf, len, "STR%sH    R%d, %s", cond, RD(ir), operand );
   331                     }
   332                     break;
   333                 case 2:
   334                     if( LFLAG(ir) ) {  /* LDRSB */
   335                         arm_disasm_address3_operand( ir, operand, sizeof(operand), pc );
   336                         snprintf(buf, len, "LDR%sSB    R%d, %s", cond, RD(ir), operand );                       
   337                     } else {
   338                         UNIMP(ir);
   339                     }
   340                     break;
   341                 case 3:
   342                     if( LFLAG(ir) ) { /* LDRSH */
   343                         arm_disasm_address3_operand( ir, operand, sizeof(operand), pc );
   344                         snprintf(buf, len, "LDR%sSH    R%d, %s", cond, RD(ir), operand );                       
   345                     } else {
   346                         UNIMP(ir);
   347                     }
   348                     break;
   349             }
   350         } else {
   351             /* Data processing */
   353             switch(OPCODE(ir)) {
   354             case 0: /* AND Rd, Rn, operand */
   355                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   356                 snprintf(buf, len, "AND%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   357                 break;
   358             case 1: /* ANDS Rd, Rn, operand */
   359                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   360                 snprintf(buf, len, "ANDS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   361                 break;
   362             case 2: /* EOR Rd, Rn, operand */
   363                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   364                 snprintf(buf, len, "EOR%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   365                 break;
   366             case 3: /* EORS Rd, Rn, operand */
   367                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   368                 snprintf(buf, len, "EORS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   369                 break;
   370             case 4: /* SUB Rd, Rn, operand */
   371                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   372                 snprintf(buf, len, "SUB%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   373                 break;
   374             case 5: /* SUBS Rd, Rn, operand */
   375                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   376                 snprintf(buf, len, "SUBS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   377                 break;
   378             case 6: /* RSB Rd, Rn, operand */
   379                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   380                 snprintf(buf, len, "RSB%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   381                 break;
   382             case 7: /* RSBS Rd, Rn, operand */
   383                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   384                 snprintf(buf, len, "RSBS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   385                 break;
   386             case 8: /* ADD Rd, Rn, operand */
   387                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   388                 snprintf(buf, len, "ADD%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   389                 break;
   390             case 9: /* ADDS Rd, Rn, operand */
   391                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   392                 snprintf(buf, len, "ADDS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   393                 break;
   394             case 10: /* ADC Rd, Rn, operand */
   395                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   396                 snprintf(buf, len, "ADC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   397                 break;
   398             case 11: /* ADCS Rd, Rn, operand */
   399                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   400                 snprintf(buf, len, "ADCS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   401                 break;
   402             case 12: /* SBC Rd, Rn, operand */
   403                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   404                 snprintf(buf, len, "SBC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   405                 break;
   406             case 13: /* SBCS Rd, Rn, operand */
   407                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   408                 snprintf(buf, len, "SBCS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   409                 break;
   410             case 14: /* RSC Rd, Rn, operand */
   411                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   412                 snprintf(buf, len, "RSC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   413                 break;
   414             case 15: /* RSCS Rd, Rn, operand */
   415                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   416                 snprintf(buf, len, "RSCS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   417                 break;
   418             case 17: /* TST Rd, Rn, operand */
   419                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   420                 snprintf(buf, len, "TST%s    R%d, %s", cond, RN(ir), operand);
   421                 break;
   422             case 19: /* TEQ Rd, Rn, operand */
   423                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   424                 snprintf(buf, len, "TEQ%s    R%d, %s", cond, RN(ir), operand);
   425                 break;
   426             case 21: /* CMP Rd, Rn, operand */
   427                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   428                 snprintf(buf, len, "CMP%s    R%d, %s", cond, RN(ir), operand);
   429                 break;
   430             case 23: /* CMN Rd, Rn, operand */
   431                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   432                 snprintf(buf, len, "CMN%s    R%d, %s", cond, RN(ir), operand);
   433                 break;
   434             case 24: /* ORR Rd, Rn, operand */
   435                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   436                 snprintf(buf, len, "ORR%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   437                 break;
   438             case 25: /* ORRS Rd, Rn, operand */
   439                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   440                 snprintf(buf, len, "ORRS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   441                 break;
   442             case 26: /* MOV Rd, operand */
   443                 if( ir == 0xE1A00000 ) {
   444                     /* Not technically a different instruction,
   445                      * but this one is commonly used as a NOP,
   446                      * so... 
   447                      */
   448                     snprintf(buf, len, "NOP");
   449                 } else {
   450                     arm_disasm_shift_operand(ir, operand, sizeof(operand));
   451                     snprintf(buf, len, "MOV%s    R%d, %s", cond, RD(ir), operand);
   452                 }
   453                 break;
   454             case 27: /* MOVS Rd, operand */
   455                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   456                 snprintf(buf, len, "MOVS%s   R%d, %s", cond, RD(ir), operand);
   457                 break;
   458             case 28: /* BIC Rd, Rn, operand */
   459                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   460                 snprintf(buf, len, "BIC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   461                 break;
   462             case 29: /* BICS Rd, Rn, operand */
   463                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   464                 snprintf(buf, len, "BICS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   465                 break;
   466             case 30: /* MVN Rd, Rn, operand */
   467                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   468                 snprintf(buf, len, "MVN%s    R%d, %s", cond, RD(ir), operand);
   469                 break;
   470             case 31: /* MVNS Rd, Rn, operand */
   471                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   472                 snprintf(buf, len, "MVNS%s   R%d, %s", cond, RD(ir), operand);
   473                 break;
   474             default:
   475                 UNIMP(ir);
   476             }
   477         }
   478         break;
   479     case 1: /* Load/store */
   480         arm_disasm_address_operand( ir, operand, sizeof(operand), pc );
   481         switch( (ir>>20)&0x17 ) {
   482         case 0:
   483         case 16:
   484         case 18:
   485             snprintf(buf, len, "STR%s    R%d, %s", cond, RD(ir), operand );
   486             break;
   487         case 1:
   488         case 17:
   489         case 19:
   490             snprintf(buf, len, "LDR%s    R%d, %s", cond, RD(ir), operand );
   491             break;
   492         case 2:
   493             snprintf(buf, len, "STRT%s   R%d, %s", cond, RD(ir), operand );
   494             break;
   495         case 3:
   496             snprintf(buf, len, "LDRT%s   R%d, %s", cond, RD(ir), operand );
   497             break;
   498         case 4:
   499         case 20:
   500         case 22:
   501             snprintf(buf, len, "STRB%s   R%d, %s", cond, RD(ir), operand );
   502             break;
   503         case 5:
   504         case 21:
   505         case 23:
   506             snprintf(buf, len, "LDRB%s   R%d, %s", cond, RD(ir), operand );
   507             break;
   508         case 6:
   509             snprintf(buf, len, "STRBT%s  R%d, %s", cond, RD(ir), operand );
   510             break;
   511         case 7: 
   512             snprintf(buf, len, "LDRBT%s  R%d, %s", cond, RD(ir), operand );
   513             break;
   514         }
   515         break;
   516         case 2: 
   517             if( (ir & 0x02000000) == 0x02000000 ) {
   518                 int32_t offset = SIGNEXT24(ir&0x00FFFFFF) << 2;
   519                 if( (ir & 0x01000000) == 0x01000000 ) { 
   520                     snprintf( buf, len, "BL%s     $%08Xh", cond, pc + offset + 8 );
   521                 } else {
   522                     snprintf( buf, len, "B%s      $%08Xh", cond, pc + offset + 8 );
   523                 }
   524             } else {
   525                 /* Load/store multiple */
   526                 j = snprintf( buf, len, LFLAG(ir) ? "LDM%s%s  R%d%c,":"STM%s%s  R%d%c,", 
   527                         ldmModes[(ir>>23)&0x03], cond, RN(ir), WFLAG(ir)?'!':' ' );
   528                 buf += j;
   529                 len -= j;
   530                 for( i = 0; i<16 && len > 2; i++ ) {
   531                     if( ir & (1<<i) ) {
   532                         j = snprintf( buf, len, "R%d", i );
   533                         buf+=j;
   534                         len-=j;
   535                     }
   536                 }
   537                 if( BFLAG(ir) && len > 0 ) {
   538                     buf[0] = '^';
   539                     buf[1] = '\0';
   540                 }
   541             }
   542             break;
   543         case 3: /* Copro */
   544             if( (ir & 0x0F000000) == 0x0F000000 ) {
   545                 snprintf( buf, len, "SWI%s    #%08Xh", cond, SIGNEXT24(ir) );
   546             } else {
   547                 UNIMP(ir);
   548             }
   549             break;
   550     }
   554     return pc+4;
   555 }
   558 uint32_t armt_disasm_instruction( uint32_t pc, char *buf, int len, char *opcode )
   559 {
   560     uint32_t ir = arm_read_word(pc);
   561     sprintf( opcode, "%02X %02X", ir&0xFF, (ir>>8) );
   562     UNIMP(ir);
   563     return pc+2;
   564 }
.