Search
lxdream.org :: lxdream/src/aica/armdasm.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armdasm.c
changeset 736:a02d1475ccfd
prev561:533f6b478071
next811:7ff871670e58
author nkeynes
date Mon Jul 14 07:44:42 2008 +0000 (13 years ago)
permissions -rw-r--r--
last change Re-indent everything consistently
Fix include guards for consistency as well
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 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] };
    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] };
    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     return 0;
   125 }
   127 static int arm_disasm_address_index( uint32_t ir, char *buf, int len )
   128 {
   129     uint32_t tmp;
   131     switch(SHIFT(ir)) {
   132     case 0: /* (Rm << imm) */
   133         tmp = SHIFTIMM(ir);
   134         if( tmp != 0 ) {
   135             return snprintf( buf, len, "R%d << %d", RM(ir), tmp );
   136         } else {
   137             return snprintf( buf, len, "R%d", RM(ir) );
   138         }
   139     case 2: /* (Rm >> imm) */
   140         return snprintf( buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
   141     case 4: /* (Rm >>> imm) */
   142         return snprintf( buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
   143     case 6:
   144         tmp = SHIFTIMM(ir);
   145         if( tmp == 0 ) /* RRX aka rotate with carry */
   146             return snprintf( buf, len, "R%d roc 1", RM(ir) );
   147         else
   148             return snprintf( buf, len, "R%d rot %d", RM(ir), tmp );
   149     default: 
   150         return UNIMP(ir);
   151     }
   152 }
   154 static int arm_disasm_address_operand( uint32_t ir, char *buf, int len,  int pc )
   155 {
   156     char  shift[32];
   158     char sign = UFLAG(ir) ? '+' : '-';
   159     /* I P U . W */
   160     switch( (ir>>21)&0x19 ) {
   161     case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
   162     case 1:
   163         return snprintf( buf, len, "[R%d], R%d %c= #%04Xh", RN(ir), RN(ir), sign, IMM12(ir) );
   164     case 8: /* Rn - imm offset  [5.2.2 A5-20] */
   165         if( RN(ir) == 15 ) { /* PC relative - decode here */
   166             uint32_t addr = pc + 8 + (UFLAG(ir) ? IMM12(ir) : -IMM12(ir));
   167             return snprintf( buf, len, "[$%08Xh] <- #%08Xh", addr,
   168                     arm_read_long( addr ) );
   169         } else {
   170             return snprintf( buf, len, "[R%d %c #%04Xh]", RN(ir), sign, IMM12(ir) );
   171         }
   172     case 9: /* Rn -= imm offset (pre-indexed)  [5.2.5 A5-24] */
   173         return snprintf( buf, len, "[R%d %c= #%04Xh]", RN(ir), sign, IMM12(ir) );
   174     case 16: /* Rn -= Rm (post-indexed)  [5.2.10 A5-32 ] */
   175     case 17:
   176         arm_disasm_address_index( ir, shift, sizeof(shift) );
   177         return snprintf( buf, len, "[R%d], R%d %c= %s", RN(ir), RN(ir), sign, shift );
   178     case 24: /* Rn - Rm  [5.2.4 A5-23] */
   179         arm_disasm_address_index( ir, shift, sizeof(shift) );
   180         return snprintf( buf, len, "[R%d %c %s]", RN(ir), sign, shift );
   181     case 25: /* RN -= Rm (pre-indexed)  [5.2.7 A5-26] */
   182         arm_disasm_address_index( ir, shift, sizeof(shift) );
   183         return snprintf( buf, len, "[R%d %c= %s]", RN(ir), sign, shift );
   184     default:
   185         return UNIMP(ir); /* Unreachable */
   186     }
   187 }
   189 uint32_t arm_disasm_instruction( uint32_t pc, char *buf, int len, char *opcode )
   190 {
   191     char operand[64];
   192     uint32_t ir = arm_read_long(pc);
   193     int i,j;
   195     sprintf( opcode, "%02X %02X %02X %02X", ir&0xFF, (ir>>8) & 0xFF,
   196              (ir>>16)&0xFF, (ir>>24) );
   198     if( COND(ir) == 0x0F ) {
   199         UNIMP(ir);
   200         return pc+4;
   201     }
   202     char *cond = conditionNames[COND(ir)];
   204     switch( GRP(ir) ) {
   205     case 0:
   206         if( (ir & 0x0D900000) == 0x01000000 ) {
   207             /* Instructions that aren't actual data processing */
   208             switch( ir & 0x0FF000F0 ) {
   209             case 0x01200010: /* BXcc */
   210                 snprintf(buf, len, "BX%s     R%d", cond, RM(ir));
   211                 break;
   212             case 0x01000000: /* MRS Rd, CPSR */
   213                 snprintf(buf, len, "MRS%s    R%d, CPSR", cond, RD(ir));
   214                 break;
   215             case 0x01400000: /* MRS Rd, SPSR */
   216                 snprintf(buf, len, "MRS%s    R%d, SPSR", cond, RD(ir));
   217                 break;
   218             case 0x01200000: /* MSR CPSR, Rm */
   219                 snprintf(buf, len, "MSR%s    CPSR_%s, R%d", cond, FSXC(ir), RM(ir));
   220                 break;
   221             case 0x01600000: /* MSR SPSR, Rm */
   222                 snprintf(buf, len, "MSR%s    SPSR_%s, R%d", cond, FSXC(ir), RM(ir));
   223                 break;
   224             case 0x03200000: /* MSR CPSR, imm */
   225                 snprintf(buf, len, "MSR%s    CPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
   226                 break;
   227             case 0x03600000: /* MSR SPSR, imm */
   228                 snprintf(buf, len, "MSR%s    SPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
   229                 break;
   230             default:
   231                 UNIMP();
   232             }
   233         } else if( (ir & 0x0E000090) == 0x00000090 ) {
   234             /* Neither are these */
   235             switch( (ir>>5)&0x03 ) {
   236             case 0:
   237                 /* Arithmetic extension area */
   238                 switch(OPCODE(ir)) {
   239                 case 0: /* MUL */
   240                     snprintf(buf,len, "MUL%s    R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir) );
   241                     break;
   242                 case 1: /* MULS */
   243                     break;
   244                 case 2: /* MLA */
   245                     snprintf(buf,len, "MLA%s    R%d, R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir), RD(ir) );
   246                     break;
   247                 case 3: /* MLAS */
   248                     break;
   249                 case 8: /* UMULL */
   250                     snprintf(buf,len, "UMULL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   251                     break;
   252                 case 9: /* UMULLS */
   253                     break;
   254                 case 10: /* UMLAL */
   255                     snprintf(buf,len, "UMLAL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   256                     break;
   257                 case 11: /* UMLALS */
   258                     break;
   259                 case 12: /* SMULL */
   260                     snprintf(buf,len, "SMULL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   261                     break;
   262                 case 13: /* SMULLS */
   263                     break;
   264                 case 14: /* SMLAL */
   265                     snprintf(buf,len, "SMLAL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
   266                     break;
   267                 case 15: /* SMLALS */
   269                     break;
   270                 case 16: /* SWP */
   271                     snprintf(buf,len, "SWP%s    R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
   272                     break;
   273                 case 20: /* SWPB */
   274                     snprintf(buf,len, "SWPB%s   R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
   275                     break;
   276                 default:
   277                     UNIMP(ir);
   278                 }
   279                 break;
   280                 case 1:
   281                     if( LFLAG(ir) ) {
   282                         /* LDRH */
   283                     } else {
   284                         /* STRH */
   285                     }
   286                     UNIMP(ir);
   287                     break;
   288                 case 2:
   289                     if( LFLAG(ir) ) {
   290                         /* LDRSB */
   291                     } else {
   292                     }
   293                     UNIMP(ir);
   294                     break;
   295                 case 3:
   296                     if( LFLAG(ir) ) {
   297                         /* LDRSH */
   298                     } else {
   299                     }
   300                     UNIMP(ir);
   301                     break;
   302             }
   303         } else {
   304             /* Data processing */
   306             switch(OPCODE(ir)) {
   307             case 0: /* AND Rd, Rn, operand */
   308                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   309                 snprintf(buf, len, "AND%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   310                 break;
   311             case 1: /* ANDS Rd, Rn, operand */
   312                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   313                 snprintf(buf, len, "ANDS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   314                 break;
   315             case 2: /* EOR Rd, Rn, operand */
   316                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   317                 snprintf(buf, len, "EOR%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   318                 break;
   319             case 3: /* EORS Rd, Rn, operand */
   320                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   321                 snprintf(buf, len, "EORS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   322                 break;
   323             case 4: /* SUB Rd, Rn, operand */
   324                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   325                 snprintf(buf, len, "SUB%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   326                 break;
   327             case 5: /* SUBS Rd, Rn, operand */
   328                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   329                 snprintf(buf, len, "SUBS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   330                 break;
   331             case 6: /* RSB Rd, Rn, operand */
   332                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   333                 snprintf(buf, len, "RSB%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   334                 break;
   335             case 7: /* RSBS Rd, Rn, operand */
   336                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   337                 snprintf(buf, len, "RSBS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   338                 break;
   339             case 8: /* ADD Rd, Rn, operand */
   340                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   341                 snprintf(buf, len, "ADD%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   342                 break;
   343             case 9: /* ADDS Rd, Rn, operand */
   344                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   345                 snprintf(buf, len, "ADDS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   346                 break;
   347             case 10: /* ADC Rd, Rn, operand */
   348                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   349                 snprintf(buf, len, "ADC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   350                 break;
   351             case 11: /* ADCS Rd, Rn, operand */
   352                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   353                 snprintf(buf, len, "ADCS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   354                 break;
   355             case 12: /* SBC Rd, Rn, operand */
   356                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   357                 snprintf(buf, len, "SBC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   358                 break;
   359             case 13: /* SBCS Rd, Rn, operand */
   360                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   361                 snprintf(buf, len, "SBCS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   362                 break;
   363             case 14: /* RSC Rd, Rn, operand */
   364                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   365                 snprintf(buf, len, "RSC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   366                 break;
   367             case 15: /* RSCS Rd, Rn, operand */
   368                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   369                 snprintf(buf, len, "RSCS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   370                 break;
   371             case 17: /* TST Rd, Rn, operand */
   372                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   373                 snprintf(buf, len, "TST%s    R%d, %s", cond, RN(ir), operand);
   374                 break;
   375             case 19: /* TEQ Rd, Rn, operand */
   376                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   377                 snprintf(buf, len, "TEQ%s    R%d, %s", cond, RN(ir), operand);
   378                 break;
   379             case 21: /* CMP Rd, Rn, operand */
   380                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   381                 snprintf(buf, len, "CMP%s    R%d, %s", cond, RN(ir), operand);
   382                 break;
   383             case 23: /* CMN Rd, Rn, operand */
   384                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   385                 snprintf(buf, len, "CMN%s    R%d, %s", cond, RN(ir), operand);
   386                 break;
   387             case 24: /* ORR Rd, Rn, operand */
   388                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   389                 snprintf(buf, len, "ORR%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   390                 break;
   391             case 25: /* ORRS Rd, Rn, operand */
   392                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   393                 snprintf(buf, len, "ORRS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   394                 break;
   395             case 26: /* MOV Rd, operand */
   396                 if( ir == 0xE1A00000 ) {
   397                     /* Not technically a different instruction,
   398                      * but this one is commonly used as a NOP,
   399                      * so... 
   400                      */
   401                     snprintf(buf, len, "NOP");
   402                 } else {
   403                     arm_disasm_shift_operand(ir, operand, sizeof(operand));
   404                     snprintf(buf, len, "MOV%s    R%d, %s", cond, RD(ir), operand);
   405                 }
   406                 break;
   407             case 27: /* MOVS Rd, operand */
   408                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   409                 snprintf(buf, len, "MOVS%s   R%d, %s", cond, RD(ir), operand);
   410                 break;
   411             case 28: /* BIC Rd, Rn, operand */
   412                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   413                 snprintf(buf, len, "BIC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   414                 break;
   415             case 29: /* BICS Rd, Rn, operand */
   416                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   417                 snprintf(buf, len, "BICS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
   418                 break;
   419             case 30: /* MVN Rd, Rn, operand */
   420                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   421                 snprintf(buf, len, "MVN%s    R%d, %s", cond, RD(ir), operand);
   422                 break;
   423             case 31: /* MVNS Rd, Rn, operand */
   424                 arm_disasm_shift_operand(ir, operand, sizeof(operand));
   425                 snprintf(buf, len, "MVNS%s   R%d, %s", cond, RD(ir), operand);
   426                 break;
   427             default:
   428                 UNIMP(ir);
   429             }
   430         }
   431         break;
   432     case 1: /* Load/store */
   433         arm_disasm_address_operand( ir, operand, sizeof(operand), pc );
   434         switch( (ir>>20)&0x17 ) {
   435         case 0:
   436         case 16:
   437         case 18:
   438             snprintf(buf, len, "STR%s    R%d, %s", cond, RD(ir), operand );
   439             break;
   440         case 1:
   441         case 17:
   442         case 19:
   443             snprintf(buf, len, "LDR%s    R%d, %s", cond, RD(ir), operand );
   444             break;
   445         case 2:
   446             snprintf(buf, len, "STRT%s   R%d, %s", cond, RD(ir), operand );
   447             break;
   448         case 3:
   449             snprintf(buf, len, "LDRT%s   R%d, %s", cond, RD(ir), operand );
   450             break;
   451         case 4:
   452         case 20:
   453         case 22:
   454             snprintf(buf, len, "STRB%s   R%d, %s", cond, RD(ir), operand );
   455             break;
   456         case 5:
   457         case 21:
   458         case 23:
   459             snprintf(buf, len, "LDRB%s   R%d, %s", cond, RD(ir), operand );
   460             break;
   461         case 6:
   462             snprintf(buf, len, "STRBT%s  R%d, %s", cond, RD(ir), operand );
   463             break;
   464         case 7: 
   465             snprintf(buf, len, "LDRBT%s  R%d, %s", cond, RD(ir), operand );
   466             break;
   467         }
   468         break;
   469         case 2: 
   470             if( (ir & 0x02000000) == 0x02000000 ) {
   471                 int32_t offset = SIGNEXT24(ir&0x00FFFFFF) << 2;
   472                 if( (ir & 0x01000000) == 0x01000000 ) { 
   473                     snprintf( buf, len, "BL%s     $%08Xh", cond, pc + offset + 8 );
   474                 } else {
   475                     snprintf( buf, len, "B%s      $%08Xh", cond, pc + offset + 8 );
   476                 }
   477             } else {
   478                 /* Load/store multiple */
   479                 j = snprintf( buf, len, LFLAG(ir) ? "LDM%s%s  R%d%c,":"STM%s%s  R%d%c,", 
   480                         ldmModes[(ir>>23)&0x03], cond, RN(ir), WFLAG(ir)?'!':' ' );
   481                 buf += j;
   482                 len -= j;
   483                 for( i = 0; i<16 && len > 2; i++ ) {
   484                     if( ir & (1<<i) ) {
   485                         j = snprintf( buf, len, "R%d", i );
   486                         buf+=j;
   487                         len-=j;
   488                     }
   489                 }
   490                 if( BFLAG(ir) && len > 0 ) {
   491                     buf[0] = '^';
   492                     buf[1] = '\0';
   493                 }
   494             }
   495             break;
   496         case 3: /* Copro */
   497             if( (ir & 0x0F000000) == 0x0F000000 ) {
   498                 snprintf( buf, len, "SWI%s    #%08Xh", cond, SIGNEXT24(ir) );
   499             } else {
   500                 UNIMP(ir);
   501             }
   502             break;
   503     }
   507     return pc+4;
   508 }
   511 uint32_t armt_disasm_instruction( uint32_t pc, char *buf, int len, char *opcode )
   512 {
   513     uint32_t ir = arm_read_word(pc);
   514     sprintf( opcode, "%02X %02X", ir&0xFF, (ir>>8) );
   515     UNIMP(ir);
   516     return pc+2;
   517 }
.