Home | History | Annotate | Download | only in ArmDisassemblerLib
      1 /** @file
      2   Thumb Dissassembler. Still a work in progress.
      3 
      4   Wrong output is a bug, so please fix it.
      5   Hex output means there is not yet an entry or a decode bug.
      6   gOpThumb[] are Thumb 16-bit, and gOpThumb2[] work on the 32-bit
      7   16-bit stream of Thumb2 instruction. Then there are big case
      8   statements to print everything out. If you are adding instructions
      9   try to reuse existing case entries if possible.
     10 
     11   Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
     12 
     13   This program and the accompanying materials
     14   are licensed and made available under the terms and conditions of the BSD License
     15   which accompanies this distribution.  The full text of the license may be found at
     16   http://opensource.org/licenses/bsd-license.php
     17 
     18   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     19   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     20 
     21 **/
     22 
     23 #include <Base.h>
     24 #include <Library/BaseLib.h>
     25 #include <Library/DebugLib.h>
     26 #include <Library/PrintLib.h>
     27 
     28 extern CHAR8 *gCondition[];
     29 
     30 extern CHAR8 *gReg[];
     31 
     32 // Thumb address modes
     33 #define LOAD_STORE_FORMAT1            1
     34 #define LOAD_STORE_FORMAT1_H        101
     35 #define LOAD_STORE_FORMAT1_B        111
     36 #define LOAD_STORE_FORMAT2            2
     37 #define LOAD_STORE_FORMAT3            3
     38 #define LOAD_STORE_FORMAT4            4
     39 #define LOAD_STORE_MULTIPLE_FORMAT1   5
     40 #define PUSH_FORMAT                   6
     41 #define POP_FORMAT                  106
     42 #define IMMED_8                       7
     43 #define CONDITIONAL_BRANCH            8
     44 #define UNCONDITIONAL_BRANCH          9
     45 #define UNCONDITIONAL_BRANCH_SHORT  109
     46 #define BRANCH_EXCHANGE              10
     47 #define DATA_FORMAT1                 11
     48 #define DATA_FORMAT2                 12
     49 #define DATA_FORMAT3                 13
     50 #define DATA_FORMAT4                 14
     51 #define DATA_FORMAT5                 15
     52 #define DATA_FORMAT6_SP              16
     53 #define DATA_FORMAT6_PC             116
     54 #define DATA_FORMAT7                 17
     55 #define DATA_FORMAT8                 19
     56 #define CPS_FORMAT                   20
     57 #define ENDIAN_FORMAT                21
     58 #define DATA_CBZ                     22
     59 #define ADR_FORMAT                   23
     60 #define IT_BLOCK                     24
     61 
     62 // Thumb2 address modes
     63 #define B_T3                        200
     64 #define B_T4                        201
     65 #define BL_T2                       202
     66 #define POP_T2                      203
     67 #define POP_T3                      204
     68 #define STM_FORMAT                  205
     69 #define LDM_REG_IMM12_SIGNED        206
     70 #define LDM_REG_IMM12_LSL           207
     71 #define LDM_REG_IMM8                208
     72 #define LDM_REG_IMM12               209
     73 #define LDM_REG_INDIRECT_LSL        210
     74 #define LDM_REG_IMM8_SIGNED         211
     75 #define LDRD_REG_IMM8               212
     76 #define LDREXB                      213
     77 #define LDREXD                      214
     78 #define SRS_FORMAT                  215
     79 #define RFE_FORMAT                  216
     80 #define LDRD_REG_IMM8_SIGNED        217
     81 #define ADD_IMM12                   218
     82 #define ADD_IMM5                    219
     83 #define ADR_THUMB2                  220
     84 #define CMN_THUMB2                  221
     85 #define ASR_IMM5                    222
     86 #define ASR_3REG                    223
     87 #define BFC_THUMB2                  224
     88 #define CDP_THUMB2                  225
     89 #define THUMB2_NO_ARGS              226
     90 #define THUMB2_2REGS                227
     91 #define ADD_IMM5_2REG               228
     92 #define CPD_THUMB2                  229
     93 #define THUMB2_4REGS                230
     94 #define ADD_IMM12_1REG              231
     95 #define THUMB2_IMM16                232
     96 #define MRC_THUMB2                  233
     97 #define MRRC_THUMB2                 234
     98 #define THUMB2_MRS                  235
     99 #define THUMB2_MSR                  236
    100 
    101 
    102 
    103 
    104 typedef struct {
    105   CHAR8   *Start;
    106   UINT32  OpCode;
    107   UINT32  Mask;
    108   UINT32  AddressMode;
    109 } THUMB_INSTRUCTIONS;
    110 
    111 THUMB_INSTRUCTIONS gOpThumb[] = {
    112 // Thumb 16-bit instrucitons
    113 //          Op       Mask   Format
    114   { "ADC" , 0x4140, 0xffc0, DATA_FORMAT5 },  // ADC <Rndn>, <Rm>
    115   { "ADR",  0xa000, 0xf800, ADR_FORMAT   },  // ADR <Rd>, <label>
    116   { "ADD" , 0x1c00, 0xfe00, DATA_FORMAT2 },
    117   { "ADD" , 0x3000, 0xf800, DATA_FORMAT3 },
    118   { "ADD" , 0x1800, 0xfe00, DATA_FORMAT1 },
    119   { "ADD" , 0x4400, 0xff00, DATA_FORMAT8 },   // A8.6.9
    120   { "ADD" , 0xa000, 0xf100, DATA_FORMAT6_PC },
    121   { "ADD" , 0xa800, 0xf800, DATA_FORMAT6_SP },
    122   { "ADD" , 0xb000, 0xff80, DATA_FORMAT7 },
    123 
    124   { "AND" , 0x4000, 0xffc0, DATA_FORMAT5 },
    125 
    126   { "ASR" , 0x1000, 0xf800, DATA_FORMAT4 },
    127   { "ASR" , 0x4100, 0xffc0, DATA_FORMAT5 },
    128 
    129   { "B"   , 0xd000, 0xf000, CONDITIONAL_BRANCH },
    130   { "B"   , 0xe000, 0xf800, UNCONDITIONAL_BRANCH_SHORT },
    131   { "BLX" , 0x4780, 0xff80, BRANCH_EXCHANGE },
    132   { "BX"  , 0x4700, 0xff87, BRANCH_EXCHANGE },
    133 
    134   { "BIC" , 0x4380, 0xffc0, DATA_FORMAT5 },
    135   { "BKPT", 0xdf00, 0xff00, IMMED_8 },
    136   { "CBZ",  0xb100, 0xfd00, DATA_CBZ },
    137   { "CBNZ", 0xb900, 0xfd00, DATA_CBZ },
    138   { "CMN" , 0x42c0, 0xffc0, DATA_FORMAT5 },
    139 
    140   { "CMP" , 0x2800, 0xf800, DATA_FORMAT3 },
    141   { "CMP" , 0x4280, 0xffc0, DATA_FORMAT5 },
    142   { "CMP" , 0x4500, 0xff00, DATA_FORMAT8 },
    143 
    144   { "CPS" , 0xb660, 0xffe8, CPS_FORMAT },
    145   { "MOV" , 0x4600, 0xff00, DATA_FORMAT8 },
    146   { "EOR" , 0x4040, 0xffc0, DATA_FORMAT5 },
    147 
    148   { "LDMIA" , 0xc800, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1 },
    149   { "LDR"   , 0x6800, 0xf800, LOAD_STORE_FORMAT1 },  // LDR <Rt>, [<Rn> {,#<imm>}]
    150   { "LDR"   , 0x5800, 0xfe00, LOAD_STORE_FORMAT2 },  // STR <Rt>, [<Rn>, <Rm>]
    151   { "LDR"   , 0x4800, 0xf800, LOAD_STORE_FORMAT3 },
    152   { "LDR"   , 0x9800, 0xf800, LOAD_STORE_FORMAT4 },  // LDR <Rt>, [SP, #<imm>]
    153   { "LDRB"  , 0x7800, 0xf800, LOAD_STORE_FORMAT1_B },
    154   { "LDRB"  , 0x5c00, 0xfe00, LOAD_STORE_FORMAT2 },  // STR <Rt>, [<Rn>, <Rm>]
    155   { "LDRH"  , 0x8800, 0xf800, LOAD_STORE_FORMAT1_H },
    156   { "LDRH"  , 0x7a00, 0xfe00, LOAD_STORE_FORMAT2 },
    157   { "LDRSB" , 0x5600, 0xfe00, LOAD_STORE_FORMAT2 },  // STR <Rt>, [<Rn>, <Rm>]
    158   { "LDRSH" , 0x5e00, 0xfe00, LOAD_STORE_FORMAT2 },
    159 
    160   { "MOVS", 0x0000, 0xffc0, DATA_FORMAT5 },   // LSL with imm5 == 0 is a MOVS, so this must go before LSL
    161   { "LSL" , 0x0000, 0xf800, DATA_FORMAT4 },
    162   { "LSL" , 0x4080, 0xffc0, DATA_FORMAT5 },
    163   { "LSR" , 0x0001, 0xf800, DATA_FORMAT4 },
    164   { "LSR" , 0x40c0, 0xffc0, DATA_FORMAT5 },
    165   { "LSRS", 0x0800, 0xf800, DATA_FORMAT4 },  // LSRS <Rd>, <Rm>, #<imm5>
    166 
    167   { "MOVS", 0x2000, 0xf800, DATA_FORMAT3 },
    168   { "MOV" , 0x1c00, 0xffc0, DATA_FORMAT3 },
    169   { "MOV" , 0x4600, 0xff00, DATA_FORMAT8 },
    170 
    171   { "MUL" , 0x4340, 0xffc0, DATA_FORMAT5 },
    172   { "MVN" , 0x41c0, 0xffc0, DATA_FORMAT5 },
    173   { "NEG" , 0x4240, 0xffc0, DATA_FORMAT5 },
    174   { "ORR" , 0x4300, 0xffc0, DATA_FORMAT5 },
    175   { "POP" , 0xbc00, 0xfe00, POP_FORMAT },
    176   { "PUSH", 0xb400, 0xfe00, PUSH_FORMAT },
    177 
    178   { "REV"   , 0xba00, 0xffc0, DATA_FORMAT5 },
    179   { "REV16" , 0xba40, 0xffc0, DATA_FORMAT5 },
    180   { "REVSH" , 0xbac0, 0xffc0, DATA_FORMAT5 },
    181 
    182   { "ROR"    , 0x41c0, 0xffc0, DATA_FORMAT5 },
    183   { "SBC"    , 0x4180, 0xffc0, DATA_FORMAT5 },
    184   { "SETEND" , 0xb650, 0xfff0, ENDIAN_FORMAT },
    185 
    186   { "STMIA" , 0xc000, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1 },
    187   { "STR"   , 0x6000, 0xf800, LOAD_STORE_FORMAT1 },   // STR  <Rt>, [<Rn> {,#<imm>}]
    188   { "STR"   , 0x5000, 0xfe00, LOAD_STORE_FORMAT2 },   // STR  <Rt>, [<Rn>, <Rm>]
    189   { "STR"   , 0x9000, 0xf800, LOAD_STORE_FORMAT4 },   // STR  <Rt>, [SP, #<imm>]
    190   { "STRB"  , 0x7000, 0xf800, LOAD_STORE_FORMAT1_B }, // STRB <Rt>, [<Rn>, #<imm5>]
    191   { "STRB"  , 0x5400, 0xfe00, LOAD_STORE_FORMAT2 },   // STRB <Rt>, [<Rn>, <Rm>]
    192   { "STRH"  , 0x8000, 0xf800, LOAD_STORE_FORMAT1_H }, // STRH <Rt>, [<Rn>{,#<imm>}]
    193   { "STRH"  , 0x5200, 0xfe00, LOAD_STORE_FORMAT2 },   // STRH <Rt>, [<Rn>, <Rm>]
    194 
    195   { "SUB" , 0x1e00, 0xfe00, DATA_FORMAT2 },
    196   { "SUB" , 0x3800, 0xf800, DATA_FORMAT3 },
    197   { "SUB" , 0x1a00, 0xfe00, DATA_FORMAT1 },
    198   { "SUB" , 0xb080, 0xff80, DATA_FORMAT7 },
    199 
    200   { "SBC" , 0x4180, 0xffc0, DATA_FORMAT5 },
    201 
    202   { "SWI" , 0xdf00, 0xff00, IMMED_8 },
    203   { "SXTB", 0xb240, 0xffc0, DATA_FORMAT5 },
    204   { "SXTH", 0xb200, 0xffc0, DATA_FORMAT5 },
    205   { "TST" , 0x4200, 0xffc0, DATA_FORMAT5 },
    206   { "UXTB", 0xb2c0, 0xffc0, DATA_FORMAT5 },
    207   { "UXTH", 0xb280, 0xffc0, DATA_FORMAT5 },
    208 
    209   { "IT",   0xbf00, 0xff00, IT_BLOCK }
    210 
    211 };
    212 
    213 THUMB_INSTRUCTIONS gOpThumb2[] = {
    214 //Instruct  OpCode      OpCode Mask  Addressig Mode
    215 
    216   { "ADR", 0xf2af0000, 0xfbff8000, ADR_THUMB2    },  // ADDR <Rd>, <label> ;Needs to go before ADDW
    217   { "CMN", 0xf1100f00, 0xfff08f00, CMN_THUMB2    },  // CMN <Rn>, #<const> ;Needs to go before ADD
    218   { "CMN", 0xeb100f00, 0xfff08f00, ADD_IMM5_2REG },  // CMN <Rn>, <Rm> {,<shift> #<const>}
    219   { "CMP", 0xf1a00f00, 0xfff08f00, CMN_THUMB2    },  // CMP <Rn>, #<const>
    220   { "TEQ", 0xf0900f00, 0xfff08f00, CMN_THUMB2    },  // CMP <Rn>, #<const>
    221   { "TEQ", 0xea900f00, 0xfff08f00, ADD_IMM5_2REG },  // CMN <Rn>, <Rm> {,<shift> #<const>}
    222   { "TST", 0xf0100f00, 0xfff08f00, CMN_THUMB2    },  // CMP <Rn>, #<const>
    223   { "TST", 0xea100f00, 0xfff08f00, ADD_IMM5_2REG },  // TST <Rn>, <Rm> {,<shift> #<const>}
    224 
    225   { "MOV",  0xf04f0000, 0xfbef8000, ADD_IMM12_1REG }, // MOV  <Rd>, #<const>
    226   { "MOVW", 0xf2400000, 0xfbe08000, THUMB2_IMM16 },   // MOVW <Rd>, #<const>
    227   { "MOVT", 0xf2c00000, 0xfbe08000, THUMB2_IMM16 },   // MOVT <Rd>, #<const>
    228 
    229   { "ADC",  0xf1400000, 0xfbe08000, ADD_IMM12 }, // ADC{S}  <Rd>, <Rn>, #<const>
    230   { "ADC",  0xeb400000, 0xffe08000, ADD_IMM5  }, // ADC{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}
    231   { "ADD",  0xf1000000, 0xfbe08000, ADD_IMM12 }, // ADD{S}  <Rd>, <Rn>, #<const>
    232   { "ADD",  0xeb000000, 0xffe08000, ADD_IMM5  }, // ADD{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}
    233   { "ADDW", 0xf2000000, 0xfbe08000, ADD_IMM12 }, // ADDW{S} <Rd>, <Rn>, #<const>
    234   { "AND",  0xf0000000, 0xfbe08000, ADD_IMM12 }, // AND{S}  <Rd>, <Rn>, #<const>
    235   { "AND",  0xea000000, 0xffe08000, ADD_IMM5  }, // AND{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}
    236   { "BIC",  0xf0200000, 0xfbe08000, ADD_IMM12 }, // BIC{S}  <Rd>, <Rn>, #<const>
    237   { "BIC",  0xea200000, 0xffe08000, ADD_IMM5  }, // BIC{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}
    238   { "EOR",  0xf0800000, 0xfbe08000, ADD_IMM12 }, // EOR{S}  <Rd>, <Rn>, #<const>
    239   { "EOR",  0xea800000, 0xffe08000, ADD_IMM5  }, // EOR{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}
    240   { "ORN",  0xf0600000, 0xfbe08000, ADD_IMM12 }, // ORN{S}  <Rd>, <Rn>, #<const>
    241   { "ORN",  0xea600000, 0xffe08000, ADD_IMM5  }, // ORN{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}
    242   { "ORR",  0xf0400000, 0xfbe08000, ADD_IMM12 }, // ORR{S}  <Rd>, <Rn>, #<const>
    243   { "ORR",  0xea400000, 0xffe08000, ADD_IMM5  }, // ORR{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}
    244   { "RSB",  0xf1c00000, 0xfbe08000, ADD_IMM12 }, // RSB{S}  <Rd>, <Rn>, #<const>
    245   { "RSB",  0xebc00000, 0xffe08000, ADD_IMM5  }, // RSB{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}
    246   { "SBC",  0xf1600000, 0xfbe08000, ADD_IMM12 }, // SBC{S}  <Rd>, <Rn>, #<const>
    247   { "SBC",  0xeb600000, 0xffe08000, ADD_IMM5  }, // SBC{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}
    248   { "SUB",  0xf1a00000, 0xfbe08000, ADD_IMM12 }, // SUB{S}  <Rd>, <Rn>, #<const>
    249   { "SUB",  0xeba00000, 0xffe08000, ADD_IMM5  }, // SUB{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}
    250 
    251   { "ASR",  0xea4f0020, 0xffef8030, ASR_IMM5 },  // ARS  <Rd>, <Rm> #<const>} imm3:imm2
    252   { "ASR",  0xfa40f000, 0xffe0f0f0, ASR_3REG },  // ARS  <Rd>, <Rn>, <Rm>
    253   { "LSR",  0xea4f0010, 0xffef8030, ASR_IMM5 },  // LSR  <Rd>, <Rm> #<const>} imm3:imm2
    254   { "LSR",  0xfa20f000, 0xffe0f0f0, ASR_3REG },  // LSR  <Rd>, <Rn>, <Rm>
    255   { "ROR",  0xea4f0030, 0xffef8030, ASR_IMM5 },  // ROR  <Rd>, <Rm> #<const>} imm3:imm2
    256   { "ROR",  0xfa60f000, 0xffe0f0f0, ASR_3REG },  // ROR  <Rd>, <Rn>, <Rm>
    257 
    258   { "BFC",  0xf36f0000, 0xffff8010, BFC_THUMB2 },   // BFC  <Rd>, #<lsb>, #<width>
    259   { "BIC",  0xf3600000, 0xfff08010, BFC_THUMB2 },   // BIC  <Rn>, <Rd>, #<lsb>, #<width>
    260   { "SBFX", 0xf3400000, 0xfff08010, BFC_THUMB2 },   // SBFX <Rn>, <Rd>, #<lsb>, #<width>
    261   { "UBFX", 0xf3c00000, 0xfff08010, BFC_THUMB2 },   // UBFX <Rn>, <Rd>, #<lsb>, #<width>
    262 
    263   { "CPD",  0xee000000, 0xff000010, CPD_THUMB2 },  // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>
    264   { "CPD2", 0xfe000000, 0xff000010, CPD_THUMB2 },  // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>
    265 
    266   { "MRC",   0xee100000, 0xff100000, MRC_THUMB2 },  // MRC  <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>
    267   { "MRC2",  0xfe100000, 0xff100000, MRC_THUMB2 },  // MRC2 <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>
    268   { "MRRC",  0xec500000, 0xfff00000, MRRC_THUMB2 },  // MRRC <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>
    269   { "MRRC2", 0xfc500000, 0xfff00000, MRRC_THUMB2 },  // MRR2 <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>
    270 
    271   { "MRS",   0xf3ef8000, 0xfffff0ff, THUMB2_MRS  }, // MRS  <Rd>, CPSR
    272   { "MSR",   0xf3808000, 0xfff0fcff, THUMB2_MSR  }, // MSR  CPSR_fs, <Rn>
    273 
    274   { "CLREX", 0xf3bf8f2f, 0xfffffff, THUMB2_NO_ARGS }, // CLREX
    275 
    276   { "CLZ",   0xfab0f080, 0xfff0f0f0, THUMB2_2REGS },  // CLZ    <Rd>,<Rm>
    277   { "MOV",   0xec4f0000, 0xfff0f0f0, THUMB2_2REGS },  // MOV    <Rd>,<Rm>
    278   { "MOVS",  0xec5f0000, 0xfff0f0f0, THUMB2_2REGS },  // MOVS   <Rd>,<Rm>
    279   { "RBIT",  0xfb90f0a0, 0xfff0f0f0, THUMB2_2REGS },  // RBIT   <Rd>,<Rm>
    280   { "REV",   0xfb90f080, 0xfff0f0f0, THUMB2_2REGS },  // REV    <Rd>,<Rm>
    281   { "REV16", 0xfa90f090, 0xfff0f0f0, THUMB2_2REGS },  // REV16  <Rd>,<Rm>
    282   { "REVSH", 0xfa90f0b0, 0xfff0f0f0, THUMB2_2REGS },  // REVSH  <Rd>,<Rm>
    283   { "RRX",   0xea4f0030, 0xfffff0f0, THUMB2_2REGS },  // RRX    <Rd>,<Rm>
    284   { "RRXS",  0xea5f0030, 0xfffff0f0, THUMB2_2REGS },  // RRXS   <Rd>,<Rm>
    285 
    286   { "MLA",   0xfb000000, 0xfff000f0, THUMB2_4REGS }, // MLA <Rd>, <Rn>, <Rm>, <Ra>
    287   { "MLS",   0xfb000010, 0xfff000f0, THUMB2_4REGS }, // MLA <Rd>, <Rn>, <Rm>, <Ra>
    288 
    289 
    290   { "SMLABB",  0xfb100000, 0xfff000f0, THUMB2_4REGS }, // SMLABB   <Rd>, <Rn>, <Rm>, <Ra>
    291   { "SMLABT",  0xfb100010, 0xfff000f0, THUMB2_4REGS }, // SMLABT   <Rd>, <Rn>, <Rm>, <Ra>
    292   { "SMLABB",  0xfb100020, 0xfff000f0, THUMB2_4REGS }, // SMLATB   <Rd>, <Rn>, <Rm>, <Ra>
    293   { "SMLATT",  0xfb100030, 0xfff000f0, THUMB2_4REGS }, // SMLATT   <Rd>, <Rn>, <Rm>, <Ra>
    294   { "SMLAWB",  0xfb300000, 0xfff000f0, THUMB2_4REGS }, // SMLAWB   <Rd>, <Rn>, <Rm>, <Ra>
    295   { "SMLAWT",  0xfb300010, 0xfff000f0, THUMB2_4REGS }, // SMLAWT   <Rd>, <Rn>, <Rm>, <Ra>
    296   { "SMLSD",   0xfb400000, 0xfff000f0, THUMB2_4REGS }, // SMLSD    <Rd>, <Rn>, <Rm>, <Ra>
    297   { "SMLSDX",  0xfb400010, 0xfff000f0, THUMB2_4REGS }, // SMLSDX   <Rd>, <Rn>, <Rm>, <Ra>
    298   { "SMMLA",   0xfb500000, 0xfff000f0, THUMB2_4REGS }, // SMMLA    <Rd>, <Rn>, <Rm>, <Ra>
    299   { "SMMLAR",  0xfb500010, 0xfff000f0, THUMB2_4REGS }, // SMMLAR   <Rd>, <Rn>, <Rm>, <Ra>
    300   { "SMMLS",   0xfb600000, 0xfff000f0, THUMB2_4REGS }, // SMMLS    <Rd>, <Rn>, <Rm>, <Ra>
    301   { "SMMLSR",  0xfb600010, 0xfff000f0, THUMB2_4REGS }, // SMMLSR   <Rd>, <Rn>, <Rm>, <Ra>
    302   { "USADA8",  0xfb700000, 0xfff000f0, THUMB2_4REGS }, // USADA8   <Rd>, <Rn>, <Rm>, <Ra>
    303   { "SMLAD",   0xfb200000, 0xfff000f0, THUMB2_4REGS }, // SMLAD    <Rd>, <Rn>, <Rm>, <Ra>
    304   { "SMLADX",  0xfb200010, 0xfff000f0, THUMB2_4REGS }, // SMLADX   <Rd>, <Rn>, <Rm>, <Ra>
    305 
    306 
    307   { "B",    0xf0008000, 0xf800d000, B_T3  },             // B<c> <label>
    308   { "B",    0xf0009000, 0xf800d000, B_T4  },             // B<c> <label>
    309   { "BL",   0xf000d000, 0xf800d000, B_T4  },             // BL<c> <label>
    310   { "BLX",  0xf000c000, 0xf800d000, BL_T2 },             // BLX<c> <label>
    311 
    312   { "POP",   0xe8bd0000, 0xffff2000, POP_T2 },           // POP <registers>
    313   { "POP",   0xf85d0b04, 0xffff0fff, POP_T3 },           // POP <register>
    314   { "PUSH",  0xe8ad0000, 0xffffa000, POP_T2 },           // PUSH <registers>
    315   { "PUSH",  0xf84d0d04, 0xffff0fff, POP_T3 },           // PUSH <register>
    316   { "STM"  , 0xe8800000, 0xffd0a000,  STM_FORMAT },      // STM <Rn>{!},<registers>
    317   { "STMDB", 0xe9800000, 0xffd0a000,  STM_FORMAT },      // STMDB <Rn>{!},<registers>
    318   { "LDM"  , 0xe8900000, 0xffd02000,  STM_FORMAT },      // LDM <Rn>{!},<registers>
    319   { "LDMDB", 0xe9100000, 0xffd02000,  STM_FORMAT },      // LDMDB <Rn>{!},<registers>
    320 
    321   { "LDR",   0xf8d00000, 0xfff00000,  LDM_REG_IMM12 },          // LDR   <rt>, [<rn>, {, #<imm12>]}
    322   { "LDRB",  0xf8900000, 0xfff00000,  LDM_REG_IMM12 },          // LDRB  <rt>, [<rn>, {, #<imm12>]}
    323   { "LDRH",  0xf8b00000, 0xfff00000,  LDM_REG_IMM12 },          // LDRH  <rt>, [<rn>, {, #<imm12>]}
    324   { "LDRSB", 0xf9900000, 0xfff00000,  LDM_REG_IMM12 },          // LDRSB <rt>, [<rn>, {, #<imm12>]}
    325   { "LDRSH", 0xf9b00000, 0xfff00000,  LDM_REG_IMM12 },          // LDRSH <rt>, [<rn>, {, #<imm12>]}
    326 
    327   { "LDR",   0xf85f0000, 0xff7f0000,  LDM_REG_IMM12_SIGNED },   // LDR   <Rt>, <label>
    328   { "LDRB",  0xf81f0000, 0xff7f0000,  LDM_REG_IMM12_SIGNED },   // LDRB  <Rt>, <label>
    329   { "LDRH",  0xf83f0000, 0xff7f0000,  LDM_REG_IMM12_SIGNED },   // LDRH  <Rt>, <label>
    330   { "LDRSB", 0xf91f0000, 0xff7f0000,  LDM_REG_IMM12_SIGNED },   // LDRSB <Rt>, <label>
    331   { "LDRSH", 0xf93f0000, 0xff7f0000,  LDM_REG_IMM12_SIGNED },   // LDRSB <Rt>, <label>
    332 
    333   { "LDR",   0xf8500000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // LDR   <rt>, [<rn>, <rm> {, LSL #<imm2>]}
    334   { "LDRB",  0xf8100000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // LDRB  <rt>, [<rn>, <rm> {, LSL #<imm2>]}
    335   { "LDRH",  0xf8300000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // LDRH  <rt>, [<rn>, <rm> {, LSL #<imm2>]}
    336   { "LDRSB", 0xf9100000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // LDRSB <rt>, [<rn>, <rm> {, LSL #<imm2>]}
    337   { "LDRSH", 0xf9300000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // LDRSH <rt>, [<rn>, <rm> {, LSL #<imm2>]}
    338 
    339   { "LDR",   0xf8500800, 0xfff00800,  LDM_REG_IMM8 },           // LDR    <rt>, [<rn>, {, #<imm8>]}
    340   { "LDRBT", 0xf8100e00, 0xfff00f00,  LDM_REG_IMM8 },           // LDRBT  <rt>, [<rn>, {, #<imm8>]}
    341   { "LDRHT", 0xf8300e00, 0xfff00f00,  LDM_REG_IMM8 },           // LDRHT  <rt>, [<rn>, {, #<imm8>]}
    342   { "LDRSB", 0xf9100800, 0xfff00800,  LDM_REG_IMM8 },           // LDRHT  <rt>, [<rn>, {, #<imm8>]}  {!} form?
    343   { "LDRSBT",0xf9100e00, 0xfff00f00,  LDM_REG_IMM8 },           // LDRHBT <rt>, [<rn>, {, #<imm8>]}  {!} form?
    344   { "LDRSH" ,0xf9300800, 0xfff00800,  LDM_REG_IMM8 },           // LDRSH  <rt>, [<rn>, {, #<imm8>]}
    345   { "LDRSHT",0xf9300e00, 0xfff00f00,  LDM_REG_IMM8 },           // LDRSHT <rt>, [<rn>, {, #<imm8>]}
    346   { "LDRT",  0xf8500e00, 0xfff00f00,  LDM_REG_IMM8 },           // LDRT   <rt>, [<rn>, {, #<imm8>]}
    347 
    348   { "LDRD",  0xe8500000, 0xfe500000,  LDRD_REG_IMM8_SIGNED },   // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}
    349   { "LDRD",  0xe8500000, 0xfe500000,  LDRD_REG_IMM8       },    // LDRD <rt>, <rt2>, <label>
    350 
    351   { "LDREX",  0xe8500f00, 0xfff00f00,  LDM_REG_IMM8 },           // LDREX <Rt>, [Rn, {#imm8}]]
    352   { "LDREXB", 0xe8d00f4f, 0xfff00fff,  LDREXB  },                // LDREXB <Rt>, [<Rn>]
    353   { "LDREXH", 0xe8d00f5f, 0xfff00fff,  LDREXB  },                // LDREXH <Rt>, [<Rn>]
    354 
    355   { "LDREXD", 0xe8d00f4f, 0xfff00fff,  LDREXD  },                // LDREXD <Rt>, <Rt2>, [<Rn>]
    356 
    357   { "STR",   0xf8c00000, 0xfff00000,  LDM_REG_IMM12 },          // STR   <rt>, [<rn>, {, #<imm12>]}
    358   { "STRB",  0xf8800000, 0xfff00000,  LDM_REG_IMM12 },          // STRB  <rt>, [<rn>, {, #<imm12>]}
    359   { "STRH",  0xf8a00000, 0xfff00000,  LDM_REG_IMM12 },          // STRH  <rt>, [<rn>, {, #<imm12>]}
    360 
    361   { "STR",   0xf8400000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // STR   <rt>, [<rn>, <rm> {, LSL #<imm2>]}
    362   { "STRB",  0xf8000000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // STRB  <rt>, [<rn>, <rm> {, LSL #<imm2>]}
    363   { "STRH",  0xf8200000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // STRH  <rt>, [<rn>, <rm> {, LSL #<imm2>]}
    364 
    365   { "STR",   0xf8400800, 0xfff00800,  LDM_REG_IMM8 },           // STR    <rt>, [<rn>, {, #<imm8>]}
    366   { "STRH",  0xf8200800, 0xfff00800,  LDM_REG_IMM8 },           // STRH   <rt>, [<rn>, {, #<imm8>]}
    367   { "STRBT", 0xf8000e00, 0xfff00f00,  LDM_REG_IMM8 },           // STRBT  <rt>, [<rn>, {, #<imm8>]}
    368   { "STRHT", 0xf8200e00, 0xfff00f00,  LDM_REG_IMM8 },           // STRHT  <rt>, [<rn>, {, #<imm8>]}
    369   { "STRT",  0xf8400e00, 0xfff00f00,  LDM_REG_IMM8 },           // STRT   <rt>, [<rn>, {, #<imm8>]}
    370 
    371   { "STRD",  0xe8400000, 0xfe500000,  LDRD_REG_IMM8_SIGNED },    // STRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}
    372 
    373   { "STREX",  0xe8400f00, 0xfff00f00,  LDM_REG_IMM8 },           // STREX <Rt>, [Rn, {#imm8}]]
    374   { "STREXB", 0xe8c00f4f, 0xfff00fff,  LDREXB  },                // STREXB <Rd>, <Rt>, [<Rn>]
    375   { "STREXH", 0xe8c00f5f, 0xfff00fff,  LDREXB  },                // STREXH <Rd>, <Rt>, [<Rn>]
    376 
    377   { "STREXD", 0xe8d00f4f, 0xfff00fff,  LDREXD  },                // STREXD <Rd>, <Rt>, <Rt2>, [<Rn>]
    378 
    379   { "SRSDB", 0xe80dc000, 0xffdffff0, SRS_FORMAT },       // SRSDB<c> SP{!},#<mode>
    380   { "SRS"  , 0xe98dc000, 0xffdffff0, SRS_FORMAT },       // SRS{IA}<c> SP{!},#<mode>
    381   { "RFEDB", 0xe810c000, 0xffd0ffff, RFE_FORMAT },       // RFEDB<c> <Rn>{!}
    382   { "RFE"  , 0xe990c000, 0xffd0ffff, RFE_FORMAT }        // RFE{IA}<c> <Rn>{!}
    383 };
    384 
    385 CHAR8 *gShiftType[] = {
    386   "LSL",
    387   "LSR",
    388   "ASR",
    389   "ROR"
    390 };
    391 
    392 CHAR8 mThumbMregListStr[4*15 + 1];
    393 
    394 CHAR8 *
    395 ThumbMRegList (
    396   UINT32  RegBitMask
    397   )
    398 {
    399   UINTN     Index, Start, End;
    400   BOOLEAN   First;
    401 
    402   mThumbMregListStr[0] = '\0';
    403   AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "{");
    404 
    405   for (Index = 0, First = TRUE; Index <= 15; Index++) {
    406     if ((RegBitMask & (1 << Index)) != 0) {
    407       Start = End = Index;
    408       for (Index++; ((RegBitMask & (1 << Index)) != 0) && (Index <= 9); Index++) {
    409         End = Index;
    410       }
    411 
    412       if (!First) {
    413         AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, ",");
    414       } else {
    415         First = FALSE;
    416       }
    417 
    418       if (Start == End) {
    419         AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, gReg[Start]);
    420       } else {
    421         AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, gReg[Start]);
    422         AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "-");
    423         AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, gReg[End]);
    424       }
    425     }
    426   }
    427   if (First) {
    428     AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "ERROR");
    429   }
    430   AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "}");
    431 
    432   // BugBug: Make caller pass in buffer it is cleaner
    433   return mThumbMregListStr;
    434 }
    435 
    436 UINT32
    437 SignExtend32 (
    438   IN  UINT32  Data,
    439   IN  UINT32  TopBit
    440   )
    441 {
    442   if (((Data & TopBit) == 0) || (TopBit == BIT31)) {
    443     return Data;
    444   }
    445 
    446   do {
    447     TopBit <<= 1;
    448     Data |= TopBit;
    449   } while ((TopBit & BIT31) != BIT31);
    450 
    451   return Data;
    452 }
    453 
    454 //
    455 // Some instructions specify the PC is always considered aligned
    456 // The PC is after the instruction that is excuting. So you pass
    457 // in the instruction address and you get back the aligned answer
    458 //
    459 UINT32
    460 PCAlign4 (
    461   IN  UINT32  Data
    462   )
    463 {
    464   return (Data + 4) & 0xfffffffc;
    465 }
    466 
    467 /**
    468   Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
    469   point to next instructin.
    470 
    471   We cheat and only decode instructions that access
    472   memory. If the instruction is not found we dump the instruction in hex.
    473 
    474   @param  OpCodePtrPtr  Pointer to pointer of ARM Thumb instruction to disassemble.
    475   @param  Buf           Buffer to sprintf disassembly into.
    476   @param  Size          Size of Buf in bytes.
    477   @param  Extended    TRUE dump hex for instruction too.
    478 
    479 **/
    480 VOID
    481 DisassembleThumbInstruction (
    482   IN  UINT16    **OpCodePtrPtr,
    483   OUT CHAR8     *Buf,
    484   OUT UINTN     Size,
    485   OUT UINT32    *ItBlock,
    486   IN  BOOLEAN   Extended
    487   )
    488 {
    489   UINT16  *OpCodePtr;
    490   UINT16  OpCode;
    491   UINT32  OpCode32;
    492   UINT32  Index;
    493   UINT32  Offset;
    494   UINT16  Rd, Rn, Rm, Rt, Rt2;
    495   BOOLEAN H1, H2, imod;
    496   //BOOLEAN ItFlag;
    497   UINT32  PC, Target, msbit, lsbit;
    498   CHAR8   *Cond;
    499   BOOLEAN S, J1, J2, P, U, W;
    500   UINT32  coproc, opc1, opc2, CRd, CRn, CRm;
    501   UINT32  Mask;
    502 
    503   OpCodePtr = *OpCodePtrPtr;
    504   OpCode = **OpCodePtrPtr;
    505 
    506   // Thumb2 is a stream of 16-bit instructions not a 32-bit instruction.
    507   OpCode32 = (((UINT32)OpCode) << 16) | *(OpCodePtr + 1);
    508 
    509   // These register names match branch form, but not others
    510   Rd = OpCode & 0x7;
    511   Rn = (OpCode >> 3) & 0x7;
    512   Rm = (OpCode >> 6) & 0x7;
    513   H1 = (OpCode & BIT7) != 0;
    514   H2 = (OpCode & BIT6) != 0;
    515   imod = (OpCode & BIT4) != 0;
    516   PC = (UINT32)(UINTN)OpCodePtr;
    517 
    518   // Increment by the minimum instruction size, Thumb2 could be bigger
    519   *OpCodePtrPtr += 1;
    520 
    521   // Manage IT Block ItFlag TRUE means we are in an IT block
    522   /*if (*ItBlock != 0) {
    523     ItFlag = TRUE;
    524     *ItBlock -= 1;
    525   } else {
    526     ItFlag = FALSE;
    527   }*/
    528 
    529   for (Index = 0; Index < sizeof (gOpThumb)/sizeof (THUMB_INSTRUCTIONS); Index++) {
    530     if ((OpCode & gOpThumb[Index].Mask) == gOpThumb[Index].OpCode) {
    531       if (Extended) {
    532         Offset = AsciiSPrint (Buf, Size, "0x%04x       %-6a", OpCode, gOpThumb[Index].Start);
    533       } else {
    534         Offset = AsciiSPrint (Buf, Size, "%-6a", gOpThumb[Index].Start);
    535       }
    536       switch (gOpThumb[Index].AddressMode) {
    537       case LOAD_STORE_FORMAT1:
    538         // A6.5.1  <Rd>, [<Rn>, #<5_bit_offset>]
    539         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 4) & 0x7c);
    540         return;
    541       case LOAD_STORE_FORMAT1_H:
    542         // A6.5.1  <Rd>, [<Rn>, #<5_bit_offset>]
    543         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 5) & 0x3e);
    544         return;
    545       case LOAD_STORE_FORMAT1_B:
    546         // A6.5.1  <Rd>, [<Rn>, #<5_bit_offset>]
    547         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 6) & 0x1f);
    548         return;
    549 
    550       case LOAD_STORE_FORMAT2:
    551         // A6.5.1  <Rd>, [<Rn>, <Rm>]
    552         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d, r%d]", Rd, Rn, Rm);
    553         return;
    554       case LOAD_STORE_FORMAT3:
    555         // A6.5.1 <Rd>, [PC, #<8_bit_offset>]
    556         Target = (OpCode & 0xff) << 2;
    557         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [pc, #0x%x] ;0x%08x", (OpCode >> 8) & 7, Target, PCAlign4 (PC) + Target);
    558         return;
    559       case LOAD_STORE_FORMAT4:
    560         // Rt, [SP, #imm8]
    561         Target = (OpCode & 0xff) << 2;
    562         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [sp, #0x%x]", (OpCode >> 8) & 7, Target);
    563         return;
    564 
    565       case LOAD_STORE_MULTIPLE_FORMAT1:
    566         // <Rn>!, {r0-r7}
    567         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d!, %a", (OpCode >> 8) & 7, ThumbMRegList (OpCode & 0xff));
    568         return;
    569 
    570       case POP_FORMAT:
    571         // POP {r0-r7,pc}
    572         AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT15 : 0)));
    573         return;
    574 
    575       case PUSH_FORMAT:
    576         // PUSH {r0-r7,lr}
    577         AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT14 : 0)));
    578         return;
    579 
    580 
    581       case IMMED_8:
    582         // A6.7 <immed_8>
    583         AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%x", OpCode & 0xff);
    584         return;
    585 
    586       case CONDITIONAL_BRANCH:
    587         // A6.3.1 B<cond> <target_address>
    588         // Patch in the condition code. A little hack but based on "%-6a"
    589         Cond = gCondition[(OpCode >> 8) & 0xf];
    590         Buf[Offset-5] = *Cond++;
    591         Buf[Offset-4] = *Cond;
    592         AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x",  PC + 4 + SignExtend32 ((OpCode & 0xff) << 1, BIT8));
    593         return;
    594       case UNCONDITIONAL_BRANCH_SHORT:
    595         // A6.3.2 B  <target_address>
    596         AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", PC + 4 + SignExtend32 ((OpCode & 0x3ff) << 1, BIT11));
    597         return;
    598 
    599       case BRANCH_EXCHANGE:
    600         // A6.3.3 BX|BLX <Rm>
    601         AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[Rn | (H2 ? 8:0)]);
    602         return;
    603 
    604       case DATA_FORMAT1:
    605         // A6.4.3  <Rd>, <Rn>, <Rm>
    606         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, r%d", Rd, Rn, Rm);
    607         return;
    608       case DATA_FORMAT2:
    609         // A6.4.3  <Rd>, <Rn>, #3_bit_immed
    610         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rd, Rn, Rm);
    611         return;
    612       case DATA_FORMAT3:
    613         // A6.4.3  <Rd>|<Rn>, #imm8
    614         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, #0x%x", (OpCode >> 8) & 7, OpCode & 0xff);
    615         return;
    616       case DATA_FORMAT4:
    617         // A6.4.3  <Rd>|<Rm>, #immed_5
    618         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rn, Rd, (OpCode >> 6) & 0x1f);
    619         return;
    620       case DATA_FORMAT5:
    621         // A6.4.3  <Rd>|<Rm>, <Rm>|<Rs>
    622         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d", Rd, Rn);
    623         return;
    624       case DATA_FORMAT6_SP:
    625         // A6.4.3  <Rd>, <reg>, #<8_Bit_immed>
    626         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, sp, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2);
    627         return;
    628       case DATA_FORMAT6_PC:
    629         // A6.4.3  <Rd>, <reg>, #<8_Bit_immed>
    630         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, pc, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2);
    631         return;
    632       case DATA_FORMAT7:
    633         // A6.4.3  SP, SP, #<7_Bit_immed>
    634         AsciiSPrint (&Buf[Offset], Size - Offset, " sp, sp, 0x%x", (OpCode & 0x7f)*4);
    635         return;
    636       case DATA_FORMAT8:
    637         // A6.4.3  <Rd>|<Rn>, <Rm>
    638         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd | (H1 ? 8:0)], gReg[Rn | (H2 ? 8:0)]);
    639         return;
    640 
    641       case CPS_FORMAT:
    642         // A7.1.24
    643         AsciiSPrint (&Buf[Offset], Size - Offset, "%a %a%a%a", imod ? "ID":"IE", ((OpCode & BIT2) == 0) ? "":"a",  ((OpCode & BIT1) == 0) ? "":"i", ((OpCode & BIT0) == 0) ? "":"f");
    644         return;
    645 
    646       case ENDIAN_FORMAT:
    647         // A7.1.24
    648         AsciiSPrint (&Buf[Offset], Size - Offset, " %a", (OpCode & BIT3) == 0 ? "LE":"BE");
    649         return;
    650 
    651       case DATA_CBZ:
    652         // CB{N}Z <Rn>, <Lable>
    653         Target = ((OpCode >> 2) & 0x3e) | (((OpCode & BIT9) == BIT9) ? BIT6 : 0);
    654         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %08x", gReg[Rd], PC + 4 + Target);
    655         return;
    656 
    657       case ADR_FORMAT:
    658         // ADR <Rd>, <Label>
    659         Target = (OpCode & 0xff) << 2;
    660         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %08x", gReg[(OpCode >> 8) & 7], PCAlign4 (PC) + Target);
    661         return;
    662 
    663       case IT_BLOCK:
    664         // ITSTATE = cond:mask   OpCode[7:4]:OpCode[3:0]
    665         // ITSTATE[7:5] == cond[3:1]
    666         // ITSTATE[4] == 1st Instruction cond[0]
    667         // ITSTATE[3] == 2st Instruction cond[0]
    668         // ITSTATE[2] == 3st Instruction cond[0]
    669         // ITSTATE[1] == 4st Instruction cond[0]
    670         // ITSTATE[0] == 1 4 instruction IT block. 0 means 0,1,2 or 3 instructions
    671         // 1st one  in ITSTATE low bits defines the number of instructions
    672         Mask = (OpCode & 0xf);
    673         if ((Mask & 0x1) == 0x1) {
    674           *ItBlock = 4;
    675           Offset +=  AsciiSPrint (&Buf[Offset], Size - Offset, "%a%a%a", (Mask & BIT3)?"T":"E", (Mask & BIT2)?"T":"E", (Mask & BIT1)?"T":"E");
    676         } else if ((OpCode & 0x3) == 0x2) {
    677           *ItBlock = 3;
    678           Offset +=  AsciiSPrint (&Buf[Offset], Size - Offset, "%a%a", (Mask & BIT3)?"T":"E", (Mask & BIT2)?"T":"E");
    679         } else if ((OpCode & 0x7) == 0x4) {
    680           *ItBlock = 2;
    681           Offset +=  AsciiSPrint (&Buf[Offset], Size - Offset, "%a", (Mask & BIT3)?"T":"E");
    682         } else if ((OpCode & 0xf) == 0x8) {
    683           *ItBlock = 1;
    684         }
    685         AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gCondition[(OpCode >> 4) & 0xf]);
    686         return;
    687       }
    688     }
    689   }
    690 
    691 
    692   // Thumb2 are 32-bit instructions
    693   *OpCodePtrPtr += 1;
    694   Rt  = (OpCode32 >> 12) & 0xf;
    695   Rt2 = (OpCode32 >> 8) & 0xf;
    696   Rd  = (OpCode32 >> 8) & 0xf;
    697   Rm  = (OpCode32 & 0xf);
    698   Rn  = (OpCode32 >> 16) & 0xf;
    699   for (Index = 0; Index < sizeof (gOpThumb2)/sizeof (THUMB_INSTRUCTIONS); Index++) {
    700     if ((OpCode32 & gOpThumb2[Index].Mask) == gOpThumb2[Index].OpCode) {
    701       if (Extended) {
    702         Offset = AsciiSPrint (Buf, Size, "0x%04x   %-6a", OpCode32, gOpThumb2[Index].Start);
    703       } else {
    704         Offset = AsciiSPrint (Buf, Size, "   %-6a", gOpThumb2[Index].Start);
    705       }
    706       switch (gOpThumb2[Index].AddressMode) {
    707       case B_T3:
    708         Cond = gCondition[(OpCode32 >> 22) & 0xf];
    709         Buf[Offset-5] = *Cond++;
    710         Buf[Offset-4] = *Cond;
    711         // S:J2:J1:imm6:imm11:0
    712         Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3f000);
    713         Target |= ((OpCode32 & BIT11) == BIT11)? BIT19 : 0;  // J2
    714         Target |= ((OpCode32 & BIT13) == BIT13)? BIT18 : 0;  // J1
    715         Target |= ((OpCode32 & BIT26) == BIT26)? BIT20 : 0;  // S
    716         Target = SignExtend32 (Target, BIT20);
    717         AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target);
    718         return;
    719       case B_T4:
    720         // S:I1:I2:imm10:imm11:0
    721         Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3ff000);
    722         S  = (OpCode32 & BIT26) == BIT26;
    723         J1 = (OpCode32 & BIT13) == BIT13;
    724         J2 = (OpCode32 & BIT11) == BIT11;
    725         Target |= (!(J2 ^ S) ? BIT22 : 0);  // I2
    726         Target |= (!(J1 ^ S) ? BIT23 : 0);  // I1
    727         Target |= (S ? BIT24 : 0);  // S
    728         Target = SignExtend32 (Target, BIT24);
    729         AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target);
    730         return;
    731 
    732       case BL_T2:
    733         // BLX  S:I1:I2:imm10:imm11:0
    734         Target = ((OpCode32 << 1) & 0xffc) + ((OpCode32 >> 4) & 0x3ff000);
    735         S  = (OpCode32 & BIT26) == BIT26;
    736         J1 = (OpCode32 & BIT13) == BIT13;
    737         J2 = (OpCode32 & BIT11) == BIT11;
    738         Target |= (!(J2 ^ S) ? BIT23 : 0);  // I2
    739         Target |= (!(J1 ^ S) ? BIT24 : 0);  // I1
    740         Target |= (S ? BIT25 : 0);  // S
    741         Target = SignExtend32 (Target, BIT25);
    742         AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PCAlign4 (PC) + Target);
    743         return;
    744 
    745       case POP_T2:
    746         // <reglist>  some must be zero, handled in table
    747         AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList (OpCode32 & 0xffff));
    748         return;
    749 
    750       case POP_T3:
    751         // <register>
    752         AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[(OpCode32 >> 12) & 0xf]);
    753         return;
    754 
    755       case STM_FORMAT:
    756         // <Rn>{!}, <registers>
    757         W = (OpCode32 & BIT21) == BIT21;
    758         AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, %a", gReg[(OpCode32 >> 16) & 0xf], W ? "!":"", ThumbMRegList (OpCode32 & 0xffff));
    759         return;
    760 
    761       case LDM_REG_IMM12_SIGNED:
    762         // <rt>, <label>
    763         Target = OpCode32 & 0xfff;
    764         if ((OpCode32 & BIT23) == 0) {
    765           // U == 0 means subtrack, U == 1 means add
    766           Target = -Target;
    767         }
    768         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[(OpCode32 >> 12) & 0xf], PCAlign4 (PC) + Target);
    769         return;
    770 
    771       case LDM_REG_INDIRECT_LSL:
    772         // <rt>, [<rn>, <rm> {, LSL #<imm2>]}
    773         Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a, %a", gReg[Rt], gReg[Rn], gReg[Rm]);
    774         if (((OpCode32 >> 4) & 3) == 0) {
    775           AsciiSPrint (&Buf[Offset], Size - Offset, "]");
    776         } else {
    777           AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL #%d]", (OpCode32 >> 4) & 3);
    778         }
    779         return;
    780 
    781       case LDM_REG_IMM12:
    782         // <rt>, [<rn>, {, #<imm12>]}
    783         Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);
    784         if ((OpCode32 & 0xfff) == 0) {
    785           AsciiSPrint (&Buf[Offset], Size - Offset, "]");
    786         } else {
    787           AsciiSPrint (&Buf[Offset], Size - Offset, ", #0x%x]", OpCode32 & 0xfff);
    788         }
    789         return;
    790 
    791       case LDM_REG_IMM8:
    792         // <rt>, [<rn>, {, #<imm8>}]{!}
    793         W = (OpCode32 & BIT8) == BIT8;
    794         U = (OpCode32 & BIT9) == BIT9;
    795         P = (OpCode32 & BIT10) == BIT10;
    796         Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);
    797         if (P) {
    798           if ((OpCode32 & 0xff) == 0) {
    799             AsciiSPrint (&Buf[Offset], Size - Offset, "]%a", W?"!":"");
    800           } else {
    801             AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", U?"":"-" , OpCode32 & 0xff, W?"!":"");
    802           }
    803         } else {
    804           AsciiSPrint (&Buf[Offset], Size - Offset, "], #%a0x%x", U?"":"-", OpCode32 & 0xff);
    805         }
    806         return;
    807 
    808       case LDRD_REG_IMM8_SIGNED:
    809         // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}
    810         P = (OpCode32 & BIT24) == BIT24;  // index = P
    811         U = (OpCode32 & BIT23) == BIT23;
    812         W = (OpCode32 & BIT21) == BIT21;
    813         Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, [%a", gReg[Rt], gReg[Rt2], gReg[Rn]);
    814         if (P) {
    815           if ((OpCode32 & 0xff) == 0) {
    816             AsciiSPrint (&Buf[Offset], Size - Offset, "]");
    817           } else {
    818             AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", U?"":"-", (OpCode32 & 0xff) << 2, W?"!":"");
    819           }
    820         } else {
    821           if ((OpCode32 & 0xff) != 0) {
    822             AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x", U?"":"-", (OpCode32 & 0xff) << 2);
    823           }
    824         }
    825         return;
    826 
    827       case LDRD_REG_IMM8:
    828         // LDRD <rt>, <rt2>, <label>
    829         Target = (OpCode32 & 0xff) << 2;
    830         if ((OpCode32 & BIT23) == 0) {
    831           // U == 0 means subtrack, U == 1 means add
    832           Target = -Target;
    833         }
    834         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a", gReg[Rt], gReg[Rt2], PC + 4 + Target);
    835         return;
    836 
    837       case LDREXB:
    838         // LDREXB <Rt>, [Rn]
    839         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a]", gReg[Rt], gReg[Rn]);
    840         return;
    841 
    842       case LDREXD:
    843         // LDREXD <Rt>, <Rt2>, [<Rn>]
    844         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, ,%a, [%a]", gReg[Rt], gReg[Rt2], gReg[Rn]);
    845         return;
    846 
    847       case SRS_FORMAT:
    848         // SP{!}, #<mode>
    849         W = (OpCode32 & BIT21) == BIT21;
    850         AsciiSPrint (&Buf[Offset], Size - Offset, " SP%a, #0x%x", W?"!":"", OpCode32 & 0x1f);
    851         return;
    852 
    853       case RFE_FORMAT:
    854         // <Rn>{!}
    855         W = (OpCode32 & BIT21) == BIT21;
    856         AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, #0x%x", gReg[Rn], W?"!":"");
    857         return;
    858 
    859       case ADD_IMM12:
    860         // ADD{S} <Rd>, <Rn>, #<const>   i:imm3:imm8
    861         if ((OpCode32 & BIT20) == BIT20) {
    862           Buf[Offset - 3] = 'S';  // assume %-6a
    863         }
    864         Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);
    865         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #0x%x", gReg[Rd], gReg[Rn], Target);
    866         return;
    867 
    868       case ADD_IMM12_1REG:
    869         // MOV{S} <Rd>, #<const>   i:imm3:imm8
    870         if ((OpCode32 & BIT20) == BIT20) {
    871           Buf[Offset - 3] = 'S';  // assume %-6a
    872         }
    873         Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);
    874         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #0x%x", gReg[Rd], Target);
    875         return;
    876 
    877       case THUMB2_IMM16:
    878         // MOVW <Rd>, #<const>   i:imm3:imm8
    879         Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);
    880         Target |= ((OpCode32 >> 4) & 0xf0000);
    881         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #0x%x", gReg[Rd], Target);
    882         return;
    883 
    884       case ADD_IMM5:
    885         // ADC{S}  <Rd>, <Rn>, <Rm> {,LSL #<const>} imm3:imm2
    886         if ((OpCode32 & BIT20) == BIT20) {
    887           Buf[Offset - 3] = 'S';  // assume %-6a
    888         }
    889         Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);
    890         Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a", gReg[Rd], gReg[Rn], gReg[Rm]);
    891         if (Target != 0) {
    892           AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL %d", gShiftType[(OpCode >> 5) & 3], Target);
    893         }
    894         return;
    895 
    896       case ADD_IMM5_2REG:
    897         // CMP  <Rn>, <Rm> {,LSL #<const>} imm3:imm2
    898         Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);
    899         Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rn], gReg[Rm]);
    900         if (Target != 0) {
    901           AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL %d", gShiftType[(OpCode >> 5) & 3], Target);
    902         }
    903 
    904 
    905       case ASR_IMM5:
    906         // ARS  <Rd>, <Rm> #<const>} imm3:imm2
    907         if ((OpCode32 & BIT20) == BIT20) {
    908           Buf[Offset - 3] = 'S';  // assume %-6a
    909         }
    910         Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);
    911         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a #%d", gReg[Rd], gReg[Rm], Target);
    912         return;
    913 
    914       case ASR_3REG:
    915         // ARS  <Rd>, <Rn>, <Rm>
    916         if ((OpCode32 & BIT20) == BIT20) {
    917           Buf[Offset - 3] = 'S';  // assume %-6a
    918         }
    919         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a %a", gReg[Rd], gReg[Rn], gReg[Rm]);
    920         return;
    921 
    922       case ADR_THUMB2:
    923         // ADDR <Rd>, <label>
    924         Target = (OpCode32 & 0xff) | ((OpCode32 >> 8) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);
    925         if ((OpCode & (BIT23 | BIT21)) == (BIT23 | BIT21)) {
    926           Target = PCAlign4 (PC) - Target;
    927         } else {
    928           Target = PCAlign4 (PC) + Target;
    929         }
    930         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, 0x%08x", gReg[Rd], Target);
    931         return;
    932 
    933       case CMN_THUMB2:
    934         // CMN <Rn>, #<const>}
    935         Target = (OpCode32 & 0xff) | ((OpCode >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);
    936         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #0x%x", gReg[Rn], Target);
    937         return;
    938 
    939       case BFC_THUMB2:
    940         // BFI <Rd>, <Rn>, #<lsb>, #<width>
    941         msbit = OpCode32 & 0x1f;
    942         lsbit = ((OpCode32 >> 6) & 3) | ((OpCode >> 10) &  0x1c);
    943         if ((Rn == 0xf) & (AsciiStrCmp (gOpThumb2[Index].Start, "BFC") == 0)){
    944           // BFC <Rd>, #<lsb>, #<width>
    945           AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #%d, #%d", gReg[Rd], lsbit, msbit - lsbit + 1);
    946         } else if (AsciiStrCmp (gOpThumb2[Index].Start, "BFI") == 0) {
    947           AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #%d, #%d", gReg[Rd], gReg[Rn], lsbit, msbit - lsbit + 1);
    948         } else {
    949           AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #%d, #%d", gReg[Rd], gReg[Rn], lsbit, msbit + 1);
    950         }
    951         return;
    952 
    953       case CPD_THUMB2:
    954         // <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>
    955         coproc = (OpCode32 >> 8)  & 0xf;
    956         opc1   = (OpCode32 >> 20) & 0xf;
    957         opc2   = (OpCode32 >> 5)  & 0x7;
    958         CRd    = (OpCode32 >> 12) & 0xf;
    959         CRn    = (OpCode32 >> 16) & 0xf;
    960         CRm    = OpCode32 & 0xf;
    961         Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " p%d,#%d,c%d,c%d,c%d", coproc, opc1, CRd, CRn, CRm);
    962         if (opc2 != 0) {
    963           AsciiSPrint (&Buf[Offset], Size - Offset, ",#%d,", opc2);
    964         }
    965         return;
    966 
    967       case MRC_THUMB2:
    968         // MRC  <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>
    969         coproc = (OpCode32 >> 8)  & 0xf;
    970         opc1   = (OpCode32 >> 20) & 0xf;
    971         opc2   = (OpCode32 >> 5)  & 0x7;
    972         CRn    = (OpCode32 >> 16) & 0xf;
    973         CRm    = OpCode32 & 0xf;
    974         Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " p%d,#%d,%a,c%d,c%d", coproc, opc1, gReg[Rt], CRn, CRm);
    975         if (opc2 != 0) {
    976           AsciiSPrint (&Buf[Offset], Size - Offset, ",#%d,", opc2);
    977         }
    978         return;
    979 
    980       case MRRC_THUMB2:
    981         // MRC  <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>,<opc2>
    982         coproc = (OpCode32 >> 8)  & 0xf;
    983         opc1   = (OpCode32 >> 20) & 0xf;
    984         CRn    = (OpCode32 >> 16) & 0xf;
    985         CRm    = OpCode32 & 0xf;
    986         Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " p%d,#%d,%a,%a,c%d", coproc, opc1, gReg[Rt], gReg[Rt2], CRm);
    987         return;
    988 
    989       case THUMB2_2REGS:
    990         // <Rd>, <Rm>
    991         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd], gReg[Rm]);
    992         return;
    993 
    994       case THUMB2_4REGS:
    995         // <Rd>, <Rn>, <Rm>, <Ra>
    996         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a, %a", gReg[Rd], gReg[Rn], gReg[Rm], gReg[Rt]);
    997         return;
    998 
    999       case THUMB2_MRS:
   1000         // MRS <Rd>, CPSR
   1001         AsciiSPrint (&Buf[Offset], Size - Offset, " %a, CPSR", gReg[Rd]);
   1002         return;
   1003 
   1004       case THUMB2_MSR:
   1005         // MRS CPSR_<fields>, <Rd>
   1006         Target = (OpCode32 >> 10) & 3;
   1007         AsciiSPrint (&Buf[Offset], Size - Offset, " CPSR_%a%a, %a", (Target & 2) == 0 ? "":"f", (Target & 1) == 0 ? "":"s", gReg[Rd]);
   1008         return;
   1009 
   1010       case THUMB2_NO_ARGS:
   1011       default:
   1012         break;
   1013       }
   1014     }
   1015   }
   1016 
   1017   AsciiSPrint (Buf, Size, "0x%08x", OpCode32);
   1018 }
   1019 
   1020 
   1021 
   1022 VOID
   1023 DisassembleArmInstruction (
   1024   IN  UINT32    **OpCodePtr,
   1025   OUT CHAR8     *Buf,
   1026   OUT UINTN     Size,
   1027   IN  BOOLEAN   Extended
   1028   );
   1029 
   1030 
   1031 /**
   1032   Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
   1033   point to next instructin.
   1034 
   1035   We cheat and only decode instructions that access
   1036   memory. If the instruction is not found we dump the instruction in hex.
   1037 
   1038   @param  OpCodePtrPtr  Pointer to pointer of ARM Thumb instruction to disassemble.
   1039   @param  Thumb         TRUE for Thumb(2), FALSE for ARM instruction stream
   1040   @param  Extended      TRUE dump hex for instruction too.
   1041   @param  ItBlock       Size of IT Block
   1042   @param  Buf           Buffer to sprintf disassembly into.
   1043   @param  Size          Size of Buf in bytes.
   1044 
   1045 **/
   1046 VOID
   1047 DisassembleInstruction (
   1048   IN  UINT8     **OpCodePtr,
   1049   IN  BOOLEAN   Thumb,
   1050   IN  BOOLEAN   Extended,
   1051   IN OUT UINT32 *ItBlock,
   1052   OUT CHAR8     *Buf,
   1053   OUT UINTN     Size
   1054   )
   1055 {
   1056   if (Thumb) {
   1057     DisassembleThumbInstruction ((UINT16 **)OpCodePtr, Buf, Size, ItBlock, Extended);
   1058   } else {
   1059     DisassembleArmInstruction ((UINT32 **)OpCodePtr, Buf, Size, Extended);
   1060   }
   1061 }
   1062 
   1063