]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/ArmDisassemblerLib/ThumbDisassembler.c
More updated
[mirror_edk2.git] / ArmPkg / Library / ArmDisassemblerLib / ThumbDisassembler.c
index f06a6bc2c5ab7a24461a621f454c091a993c587d..f9c84bb890f92a02989973b0672d3d5a6eea1fcc 100644 (file)
@@ -1,5 +1,12 @@
 /** @file\r
-  Default exception handler\r
+  Thumb Dissassembler. Still a work in progress.\r
+\r
+  Wrong output is a bug, so please fix it. \r
+  Hex output means there is not yet an entry or a decode bug.\r
+  gOpThumb[] are Thumb 16-bit, and gOpThumb2[] work on the 32-bit \r
+  16-bit stream of Thumb2 instruction. Then there are big case \r
+  statements to print everything out. If you are adding instructions\r
+  try to reuse existing case entries if possible.\r
 \r
   Copyright (c) 2008-2010, Apple Inc. All rights reserved.\r
   \r
 \r
 #include <Base.h>\r
 #include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
 #include <Library/PrintLib.h>\r
 \r
 extern CHAR8 *gCondition[];\r
 \r
 extern CHAR8 *gReg[];\r
 \r
+// Thumb address modes\r
 #define LOAD_STORE_FORMAT1            1\r
+#define LOAD_STORE_FORMAT1_H        101\r
+#define LOAD_STORE_FORMAT1_B        111 \r
 #define LOAD_STORE_FORMAT2            2\r
 #define LOAD_STORE_FORMAT3            3\r
 #define LOAD_STORE_FORMAT4            4\r
@@ -44,10 +55,41 @@ extern CHAR8 *gReg[];
 #define DATA_FORMAT8                 19\r
 #define CPS_FORMAT                   20\r
 #define ENDIAN_FORMAT                21\r
-     \r
+#define DATA_CBZ                     22\r
+#define ADR_FORMAT                   23\r
+\r
+// Thumb2 address modes\r
 #define B_T3                        200\r
 #define B_T4                        201\r
 #define BL_T2                       202\r
+#define POP_T2                      203\r
+#define POP_T3                      204\r
+#define STM_FORMAT                  205\r
+#define LDM_REG_IMM12_SIGNED        206\r
+#define LDM_REG_IMM12_LSL           207\r
+#define LDM_REG_IMM8                208\r
+#define LDM_REG_IMM12               209\r
+#define LDM_REG_INDIRECT_LSL        210\r
+#define LDM_REG_IMM8_SIGNED         211\r
+#define LDRD_REG_IMM8               212\r
+#define LDREXB                      213\r
+#define LDREXD                      214\r
+#define SRS_FORMAT                  215\r
+#define RFE_FORMAT                  216\r
+#define LDRD_REG_IMM8_SIGNED        217\r
+#define ADD_IMM12                   218\r
+#define ADD_IMM5                    219\r
+#define ADR_THUMB2                  220\r
+#define CMN_THUMB2                  221\r
+#define ASR_IMM5                    222\r
+#define ASR_3REG                    223\r
+#define BFC_THUMB2                  224\r
+#define CDP_THUMB2                  225\r
+#define THUMB2_NO_ARGS              226\r
+#define THUMB2_2REGS                227\r
+#define ADD_IMM5_2REG               228\r
+#define CPD_THUMB2                  229\r
+#define THUMB2_4REGS                230\r
 \r
 \r
 typedef struct {\r
@@ -59,9 +101,9 @@ typedef struct {
 \r
 THUMB_INSTRUCTIONS gOpThumb[] = {\r
 // Thumb 16-bit instrucitons\r
-//         Op      Mask    Format\r
+//          Op       Mask   Format\r
   { "ADC" , 0x4140, 0xffc0, DATA_FORMAT5 },\r
-\r
+  { "ADR",  0xa000, 0xf800, ADR_FORMAT   },  // ADR <Rd>, <label>\r
   { "ADD" , 0x1c00, 0xfe00, DATA_FORMAT2 },\r
   { "ADD" , 0x3000, 0xf800, DATA_FORMAT3 },\r
   { "ADD" , 0x1800, 0xfe00, DATA_FORMAT1 },\r
@@ -82,6 +124,8 @@ THUMB_INSTRUCTIONS gOpThumb[] = {
 \r
   { "BIC" , 0x4380, 0xffc0, DATA_FORMAT5 },\r
   { "BKPT", 0xdf00, 0xff00, IMMED_8 },\r
+  { "CBZ",  0xb100, 0xfd00, DATA_CBZ },\r
+  { "CBNZ", 0xb900, 0xfd00, DATA_CBZ },\r
   { "CMN" , 0x42c0, 0xffc0, DATA_FORMAT5 },\r
 \r
   { "CMP" , 0x2800, 0xf800, DATA_FORMAT3 },\r
@@ -97,9 +141,9 @@ THUMB_INSTRUCTIONS gOpThumb[] = {
   { "LDR"   , 0x5800, 0xfe00, LOAD_STORE_FORMAT2 },\r
   { "LDR"   , 0x4800, 0xf800, LOAD_STORE_FORMAT3 },\r
   { "LDR"   , 0x9800, 0xf800, LOAD_STORE_FORMAT4 },\r
-  { "LDRB"  , 0x7800, 0xf800, LOAD_STORE_FORMAT1 },\r
+  { "LDRB"  , 0x7800, 0xf800, LOAD_STORE_FORMAT1_B },\r
   { "LDRB"  , 0x5c00, 0xfe00, LOAD_STORE_FORMAT2 },\r
-  { "LDRH"  , 0x8800, 0xf800, LOAD_STORE_FORMAT1 },\r
+  { "LDRH"  , 0x8800, 0xf800, LOAD_STORE_FORMAT1_H },\r
   { "LDRH"  , 0x7a00, 0xfe00, LOAD_STORE_FORMAT2 },\r
   { "LDRSB" , 0x5600, 0xfe00, LOAD_STORE_FORMAT2 },\r
   { "LDRSH" , 0x5e00, 0xfe00, LOAD_STORE_FORMAT2 },\r
@@ -109,6 +153,7 @@ THUMB_INSTRUCTIONS gOpThumb[] = {
   { "LSL" , 0x4080, 0xffc0, DATA_FORMAT5 },\r
   { "LSR" , 0x0001, 0xf800, DATA_FORMAT4 },\r
   { "LSR" , 0x40c0, 0xffc0, DATA_FORMAT5 },\r
+  { "LSRS", 0x0800, 0xf800, DATA_FORMAT4 },  // LSRS <Rd>, <Rm>, #<imm5>\r
 \r
   { "MOVS", 0x2000, 0xf800, DATA_FORMAT3 },\r
   { "MOV" , 0x1c00, 0xffc0, DATA_FORMAT3 },\r
@@ -134,9 +179,9 @@ THUMB_INSTRUCTIONS gOpThumb[] = {
   { "STR"   , 0x5000, 0xfe00, LOAD_STORE_FORMAT2 },\r
   { "STR"   , 0x4000, 0xf800, LOAD_STORE_FORMAT3 },\r
   { "STR"   , 0x9000, 0xf800, LOAD_STORE_FORMAT4 },\r
-  { "STRB"  , 0x7000, 0xf800, LOAD_STORE_FORMAT1 },\r
+  { "STRB"  , 0x7000, 0xf800, LOAD_STORE_FORMAT1_B },\r
   { "STRB"  , 0x5800, 0xfe00, LOAD_STORE_FORMAT2 },\r
-  { "STRH"  , 0x8000, 0xf800, LOAD_STORE_FORMAT1 },\r
+  { "STRH"  , 0x8000, 0xf800, LOAD_STORE_FORMAT1_H },\r
   { "STRH"  , 0x5200, 0xfe00, LOAD_STORE_FORMAT2 },\r
 \r
   { "SUB" , 0x1e00, 0xfe00, DATA_FORMAT2 },\r
@@ -150,62 +195,174 @@ THUMB_INSTRUCTIONS gOpThumb[] = {
   { "TST" , 0x4200, 0xffc0, DATA_FORMAT5 },\r
   { "UXTB", 0xb2c0, 0xffc0, DATA_FORMAT5 },\r
   { "UXTH", 0xb280, 0xffc0, DATA_FORMAT5 }\r
+\r
 };\r
 \r
 THUMB_INSTRUCTIONS gOpThumb2[] = {\r
-  { "B",    0xf0008000, 0xf800d000, B_T3  },\r
-  { "B",    0xf0009000, 0xf800d000, B_T4  },\r
-  { "BL",   0xf000d000, 0xf800d000, B_T4  },\r
-  { "BLX",  0xf000c000, 0xf800d000, BL_T2 }\r
-  // ADD POP PUSH STR(B)(D) LDR(B)(D) EOR MOV ADDS SUBS STM\r
-#if 0  \r
+//Instruct  OpCode      OpCode Mask  Addressig Mode\r
   \r
-  // 32-bit Thumb instructions  op1 01\r
+  { "ADR", 0xf2af0000, 0xfbff8000, ADR_THUMB2    },  // ADDR <Rd>, <label> ;Needs to go before ADDW \r
+  { "CMN", 0xf1100f00, 0xfff08f00, CMN_THUMB2    },  // CMN <Rn>, #<const> ;Needs to go before ADD\r
+  { "CMN", 0xeb100f00, 0xfff08f00, ADD_IMM5_2REG },  // CMN <Rn>, <Rm> {,<shift> #<const>}\r
+  { "CMP", 0xf1a00f00, 0xfff08f00, CMN_THUMB2    },  // CMP <Rn>, #<const>\r
+  { "TEQ", 0xf0900f00, 0xfff08f00, CMN_THUMB2    },  // CMP <Rn>, #<const>\r
+  { "TEQ", 0xea900f00, 0xfff08f00, ADD_IMM5_2REG },  // CMN <Rn>, <Rm> {,<shift> #<const>}\r
+  { "TST", 0xf0100f00, 0xfff08f00, CMN_THUMB2    },  // CMP <Rn>, #<const>\r
+  { "TST", 0xea100f00, 0xfff08f00, ADD_IMM5_2REG },  // TST <Rn>, <Rm> {,<shift> #<const>}\r
+\r
+  { "ADC",  0xf1400000, 0xfbe08000, ADD_IMM12 }, // ADC{S}  <Rd>, <Rn>, #<const>\r
+  { "ADC",  0xeb400000, 0xffe08000, ADD_IMM5  }, // ADC{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
+  { "ADD",  0xf1000000, 0xfbe08000, ADD_IMM12 }, // ADD{S}  <Rd>, <Rn>, #<const>\r
+  { "ADD",  0xeb000000, 0xffe08000, ADD_IMM5  }, // ADD{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
+  { "ADDW", 0xf2000000, 0xfbe08000, ADD_IMM12 }, // ADDW{S} <Rd>, <Rn>, #<const>\r
+  { "AND",  0xf0000000, 0xfbe08000, ADD_IMM12 }, // AND{S}  <Rd>, <Rn>, #<const>\r
+  { "AND",  0xea000000, 0xffe08000, ADD_IMM5  }, // AND{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
+  { "BIC",  0xf0200000, 0xfbe08000, ADD_IMM12 }, // BIC{S}  <Rd>, <Rn>, #<const>\r
+  { "BIC",  0xea200000, 0xffe08000, ADD_IMM5  }, // BIC{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
+  { "EOR",  0xf0800000, 0xfbe08000, ADD_IMM12 }, // EOR{S}  <Rd>, <Rn>, #<const>\r
+  { "EOR",  0xea800000, 0xffe08000, ADD_IMM5  }, // EOR{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
+  { "ORN",  0xf0600000, 0xfbe08000, ADD_IMM12 }, // ORN{S}  <Rd>, <Rn>, #<const>\r
+  { "ORN",  0xea600000, 0xffe08000, ADD_IMM5  }, // ORN{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
+  { "ORR",  0xf0400000, 0xfbe08000, ADD_IMM12 }, // ORR{S}  <Rd>, <Rn>, #<const>\r
+  { "ORR",  0xea400000, 0xffe08000, ADD_IMM5  }, // ORR{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
+  { "RSB",  0xf1c00000, 0xfbe08000, ADD_IMM12 }, // RSB{S}  <Rd>, <Rn>, #<const>\r
+  { "RSB",  0xebc00000, 0xffe08000, ADD_IMM5  }, // RSB{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
+  { "SBC",  0xf1600000, 0xfbe08000, ADD_IMM12 }, // SBC{S}  <Rd>, <Rn>, #<const>\r
+  { "SBC",  0xeb600000, 0xffe08000, ADD_IMM5  }, // SBC{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
+  { "SUB",  0xf1a00000, 0xfbe08000, ADD_IMM12 }, // SUB{S}  <Rd>, <Rn>, #<const>\r
+  { "SUB",  0xeba00000, 0xffe08000, ADD_IMM5  }, // SUB{S}  <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
+\r
+  { "ASR",  0xea4f0020, 0xffef8030, ASR_IMM5 },  // ARS  <Rd>, <Rm> #<const>} imm3:imm2\r
+  { "ASR",  0xfa40f000, 0xffe0f0f0, ASR_3REG },  // ARS  <Rd>, <Rn>, <Rm> \r
+  { "LSR",  0xea4f0010, 0xffef8030, ASR_IMM5 },  // LSR  <Rd>, <Rm> #<const>} imm3:imm2\r
+  { "LSR",  0xfa20f000, 0xffe0f0f0, ASR_3REG },  // LSR  <Rd>, <Rn>, <Rm> \r
+  { "ROR",  0xea4f0030, 0xffef8030, ASR_IMM5 },  // ROR  <Rd>, <Rm> #<const>} imm3:imm2\r
+  { "ROR",  0xfa60f000, 0xffe0f0f0, ASR_3REG },  // ROR  <Rd>, <Rn>, <Rm> \r
+\r
+  { "BFC",  0xf36f0000, 0xffff8010, BFC_THUMB2 },   // BFC  <Rd>, #<lsb>, #<width>\r
+  { "BIC",  0xf3600000, 0xfff08010, BFC_THUMB2 },   // BIC  <Rn>, <Rd>, #<lsb>, #<width>\r
+  { "SBFX", 0xf3400000, 0xfff08010, BFC_THUMB2 },   // SBFX <Rn>, <Rd>, #<lsb>, #<width>\r
+  { "UBFX", 0xf3c00000, 0xfff08010, BFC_THUMB2 },   // UBFX <Rn>, <Rd>, #<lsb>, #<width>\r
+\r
+  { "CPD",  0xee000000, 0xff000010, CPD_THUMB2 },  // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>\r
+  { "CPD2", 0xfe000000, 0xff000010, CPD_THUMB2 },  // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>\r
+\r
+  { "CLREX", 0xf3bf8f2f, 0xfffffff, THUMB2_NO_ARGS }, // CLREX\r
+\r
+  { "CLZ",   0xfab0f080, 0xfff0f0f0, THUMB2_2REGS },  // CLZ    <Rd>,<Rm>\r
+  { "MOV",   0xec4f0000, 0xfff0f0f0, THUMB2_2REGS },  // MOV    <Rd>,<Rm>\r
+  { "MOVS",  0xec5f0000, 0xfff0f0f0, THUMB2_2REGS },  // MOVS   <Rd>,<Rm>\r
+  { "RBIT",  0xfb90f0a0, 0xfff0f0f0, THUMB2_2REGS },  // RBIT   <Rd>,<Rm>\r
+  { "REV",   0xfb90f080, 0xfff0f0f0, THUMB2_2REGS },  // REV    <Rd>,<Rm>\r
+  { "REV16", 0xfa90f090, 0xfff0f0f0, THUMB2_2REGS },  // REV16  <Rd>,<Rm>\r
+  { "REVSH", 0xfa90f0b0, 0xfff0f0f0, THUMB2_2REGS },  // REVSH  <Rd>,<Rm>\r
+  { "RRX",   0xea4f0030, 0xfffff0f0, THUMB2_2REGS },  // RRX    <Rd>,<Rm>\r
+  { "RRXS",  0xea5f0030, 0xfffff0f0, THUMB2_2REGS },  // RRXS   <Rd>,<Rm>\r
+\r
+  { "MLA",   0xfb000000, 0xfff000f0, THUMB2_4REGS }, // MLA <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "MLS",   0xfb000010, 0xfff000f0, THUMB2_4REGS }, // MLA <Rd>, <Rn>, <Rm>, <Ra>\r
+\r
+\r
+  { "SMLABB",  0xfb100000, 0xfff000f0, THUMB2_4REGS }, // SMLABB   <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMLABT",  0xfb100010, 0xfff000f0, THUMB2_4REGS }, // SMLABT   <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMLABB",  0xfb100020, 0xfff000f0, THUMB2_4REGS }, // SMLATB   <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMLATT",  0xfb100030, 0xfff000f0, THUMB2_4REGS }, // SMLATT   <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMLAWB",  0xfb300000, 0xfff000f0, THUMB2_4REGS },// SMLAWB   <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMLAWT",  0xfb300010, 0xfff000f0, THUMB2_4REGS },// SMLAWT   <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMLSD",   0xfb400000, 0xfff000f0, THUMB2_4REGS },// SMLSD    <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMLSDX",  0xfb400010, 0xfff000f0, THUMB2_4REGS },// SMLSDX   <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMMLA",   0xfb500000, 0xfff000f0, THUMB2_4REGS },// SMMLA    <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMMLAR",  0xfb500010, 0xfff000f0, THUMB2_4REGS },// SMMLAR   <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMMLS",   0xfb600000, 0xfff000f0, THUMB2_4REGS },// SMMLS    <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMMLSR",  0xfb600010, 0xfff000f0, THUMB2_4REGS },// SMMLSR   <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "USADA8",  0xfb700000, 0xfff000f0, THUMB2_4REGS },// USADA8   <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMLAD",   0xfb200000, 0xfff000f0, THUMB2_4REGS },// SMLAD    <Rd>, <Rn>, <Rm>, <Ra>\r
+  { "SMLADX",  0xfb200010, 0xfff000f0, THUMB2_4REGS },// SMLADX   <Rd>, <Rn>, <Rm>, <Ra>\r
+\r
+\r
+  { "B",    0xf0008000, 0xf800d000, B_T3  },             // B<c> <label>\r
+  { "B",    0xf0009000, 0xf800d000, B_T4  },             // B<c> <label>\r
+  { "BL",   0xf000d000, 0xf800d000, B_T4  },             // BL<c> <label>\r
+  { "BLX",  0xf000c000, 0xf800d000, BL_T2 },             // BLX<c> <label>\r
+\r
+  { "POP",   0xe8bd0000, 0xffff2000, POP_T2 },           // POP <registers>\r
+  { "POP",   0xf85d0b04, 0xffff0fff, POP_T3 },           // POP <register>\r
+  { "PUSH",  0xe8ad0000, 0xffffa000, POP_T2 },           // PUSH <registers>\r
+  { "PUSH",  0xf84d0d04, 0xffff0fff, POP_T3 },           // PUSH <register>\r
+  { "STM"  , 0xe8800000, 0xffd0a000,  STM_FORMAT },      // STM <Rn>{!},<registers>\r
+  { "STMDB", 0xe9800000, 0xffd0a000,  STM_FORMAT },      // STMDB <Rn>{!},<registers>\r
+  { "LDM"  , 0xe8900000, 0xffd02000,  STM_FORMAT },      // LDM <Rn>{!},<registers>\r
+  { "LDMDB", 0xe9100000, 0xffd02000,  STM_FORMAT },      // LDMDB <Rn>{!},<registers>\r
   \r
-  //  1110 100x x0xx xxxx xxxx xxxx xxxx xxxx Load/store multiple\r
-  { "SRSDB", 0xe80dc000, 0xffdffff0, SRS_FORMAT },       // SRSDB<c> SP{!},#<mode>\r
-  { "SRS"  , 0xe98dc000, 0xffdffff0, SRS_IA_FORMAT },    // SRS{IA}<c> SP{!},#<mode>\r
-  { "RFEDB", 0xe810c000, 0xffd0ffff, RFE_FORMAT },       // RFEDB<c> <Rn>{!}\r
-  { "RFE"  , 0xe990c000, 0xffd0ffff, RFE_IA_FORMAT },    // RFE{IA}<c> <Rn>{!}\r
+  { "LDR",   0xf8d00000, 0xfff00000,  LDM_REG_IMM12 },          // LDR   <rt>, [<rn>, {, #<imm12>]}\r
+  { "LDRB",  0xf8900000, 0xfff00000,  LDM_REG_IMM12 },          // LDRB  <rt>, [<rn>, {, #<imm12>]}\r
+  { "LDRH",  0xf8b00000, 0xfff00000,  LDM_REG_IMM12 },          // LDRH  <rt>, [<rn>, {, #<imm12>]}\r
+  { "LDRSB", 0xf9900000, 0xfff00000,  LDM_REG_IMM12 },          // LDRSB <rt>, [<rn>, {, #<imm12>]}\r
+  { "LDRSH", 0xf9b00000, 0xfff00000,  LDM_REG_IMM12 },          // LDRSH <rt>, [<rn>, {, #<imm12>]}\r
+\r
+  { "LDR",   0xf85f0000, 0xff7f0000,  LDM_REG_IMM12_SIGNED },   // LDR   <Rt>, <label> \r
+  { "LDRB",  0xf81f0000, 0xff7f0000,  LDM_REG_IMM12_SIGNED },   // LDRB  <Rt>, <label> \r
+  { "LDRH",  0xf83f0000, 0xff7f0000,  LDM_REG_IMM12_SIGNED },   // LDRH  <Rt>, <label> \r
+  { "LDRSB", 0xf91f0000, 0xff7f0000,  LDM_REG_IMM12_SIGNED },   // LDRSB <Rt>, <label> \r
+  { "LDRSH", 0xf93f0000, 0xff7f0000,  LDM_REG_IMM12_SIGNED },   // LDRSB <Rt>, <label> \r
   \r
-  { "STM"  , 0xe8800000, 0xffd00000,  STM_FORMAT },      // STM<c>.W <Rn>{!},<registers>\r
-  { "LDM"  , 0xe8900000, 0xffd00000,  STM_FORMAT },      // LDR<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]\r
-  { "POP"  , 0xe8bd0000, 0xffff2000,  REGLIST_FORMAT },  // POP<c>.W <registers> >1 register\r
-  { "POP"  , 0xf85d0b04, 0xffff0fff,  RT_FORMAT },       // POP<c>.W <registers>  1 register\r
+  { "LDR",   0xf8500000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // LDR   <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
+  { "LDRB",  0xf8100000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // LDRB  <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
+  { "LDRH",  0xf8300000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // LDRH  <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
+  { "LDRSB", 0xf9100000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // LDRSB <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
+  { "LDRSH", 0xf9300000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // LDRSH <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
+\r
+  { "LDR",   0xf8500800, 0xfff00800,  LDM_REG_IMM8 },           // LDR    <rt>, [<rn>, {, #<imm8>]}\r
+  { "LDRBT", 0xf8100e00, 0xfff00f00,  LDM_REG_IMM8 },           // LDRBT  <rt>, [<rn>, {, #<imm8>]}\r
+  { "LDRHT", 0xf8300e00, 0xfff00f00,  LDM_REG_IMM8 },           // LDRHT  <rt>, [<rn>, {, #<imm8>]}\r
+  { "LDRSB", 0xf9900800, 0xfff00800,  LDM_REG_IMM8 },           // LDRHT  <rt>, [<rn>, {, #<imm8>]}  {!} form? \r
+  { "LDRSBT",0xf9100e00, 0xfff00f00,  LDM_REG_IMM8 },           // LDRHBT <rt>, [<rn>, {, #<imm8>]}  {!} form? \r
+  { "LDRSH" ,0xf9300800, 0xfff00800,  LDM_REG_IMM8 },           // LDRSH  <rt>, [<rn>, {, #<imm8>]}  \r
+  { "LDRSHT",0xf9300e00, 0xfff00f00,  LDM_REG_IMM8 },           // LDRSHT <rt>, [<rn>, {, #<imm8>]}   \r
+  { "LDRT",  0xf8500e00, 0xfff00f00,  LDM_REG_IMM8 },           // LDRT   <rt>, [<rn>, {, #<imm8>]}    \r
+\r
+  { "LDRD",  0xe8500000, 0xfe500000,  LDRD_REG_IMM8_SIGNED },   // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
+  { "LDRD",  0xe8500000, 0xfe500000,  LDRD_REG_IMM8       },    // LDRD <rt>, <rt2>, <label>\r
+   \r
+  { "LDREX",  0xe8500f00, 0xfff00f00,  LDM_REG_IMM8 },           // LDREX <Rt>, [Rn, {#imm8}]]                     \r
+  { "LDREXB", 0xe8d00f4f, 0xfff00fff,  LDREXB  },                // LDREXB <Rt>, [<Rn>]                     \r
+  { "LDREXH", 0xe8d00f5f, 0xfff00fff,  LDREXB  },                // LDREXH <Rt>, [<Rn>]                     \r
\r
+  { "LDREXD", 0xe8d00f4f, 0xfff00fff,  LDREXD  },                // LDREXD <Rt>, <Rt2>, [<Rn>]                     \r
+\r
+  { "STR",   0xf8c00000, 0xfff00000,  LDM_REG_IMM12 },          // STR   <rt>, [<rn>, {, #<imm12>]}  \r
+  { "STRB",  0xf8800000, 0xfff00000,  LDM_REG_IMM12 },          // STRB  <rt>, [<rn>, {, #<imm12>]}\r
+  { "STRH",  0xf8a00000, 0xfff00000,  LDM_REG_IMM12 },          // STRH  <rt>, [<rn>, {, #<imm12>]}\r
\r
+  { "STR",   0xf8400000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // STR   <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
+  { "STRB",  0xf8000000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // STRB  <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
+  { "STRH",  0xf8200000, 0xfff00fc0,  LDM_REG_INDIRECT_LSL },   // STRH  <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
 \r
-  { "STMDB", 0xe9000000, 0xffd00000,  STM_FORMAT },      // STMDB\r
-  { "PUSH" , 0xe8bd0000, 0xffffa000,  REGLIST_FORMAT },  // PUSH<c>.W <registers>  >1 register\r
-  { "PUSH" , 0xf84d0b04, 0xffff0fff,  RT_FORMAT },       // PUSH<c>.W <registers>   1 register\r
-  { "LDMDB", 0xe9102000, 0xffd02000,  STM_FORMAT },      // LDMDB<c> <Rn>{!},<registers>\r
+  { "STR",   0xf8400800, 0xfff00800,  LDM_REG_IMM8 },           // STR    <rt>, [<rn>, {, #<imm8>]}\r
+  { "STRH",  0xf8200800, 0xfff00800,  LDM_REG_IMM8 },           // STRH   <rt>, [<rn>, {, #<imm8>]}\r
+  { "STRBT", 0xf8000e00, 0xfff00f00,  LDM_REG_IMM8 },           // STRBT  <rt>, [<rn>, {, #<imm8>]}\r
+  { "STRHT", 0xf8200e00, 0xfff00f00,  LDM_REG_IMM8 },           // STRHT  <rt>, [<rn>, {, #<imm8>]}\r
+  { "STRT",  0xf8400e00, 0xfff00f00,  LDM_REG_IMM8 },           // STRT   <rt>, [<rn>, {, #<imm8>]}    \r
 \r
-  //  1110 100x x1xx xxxx xxxx xxxx xxxx xxxx Load/store dual,\r
-  { "STREX" , 0xe0400000, 0xfff000f0, 3REG_IMM8_FORMAT },  // STREX<c> <Rd>,<Rt>,[<Rn>{,#<imm>}]\r
-  { "STREXB", 0xe8c00f40, 0xfff00ff0, 3REG_FORMAT },       // STREXB<c> <Rd>,<Rt>,[<Rn>]\r
-  { "STREXD", 0xe8c00070, 0xfff000f0, 4REG_FORMAT },       // STREXD<c> <Rd>,<Rt>,<Rt2>,[<Rn>]\r
-  { "STREXH", 0xe8c00f70, 0xfff00ff0, 3REG_FORMAT },       // STREXH<c> <Rd>,<Rt>,[<Rn>]\r
-  { "STRH",   0xf8c00000, 0xfff00000, 2REG_IMM8_FORMAT },  // STRH<c>.W <Rt>,[<Rn>{,#<imm12>}]\r
-  { "STRH",   0xf8200000, 0xfff00000,  },                  // STRH<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]\r
+  { "STRD",  0xe8400000, 0xfe500000,  LDRD_REG_IMM8_SIGNED },    // STRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
 \r
+  { "STREX",  0xe8400f00, 0xfff00f00,  LDM_REG_IMM8 },           // STREX <Rt>, [Rn, {#imm8}]]                     \r
+  { "STREXB", 0xe8c00f4f, 0xfff00fff,  LDREXB  },                // STREXB <Rd>, <Rt>, [<Rn>]                     \r
+  { "STREXH", 0xe8c00f5f, 0xfff00fff,  LDREXB  },                // STREXH <Rd>, <Rt>, [<Rn>]                     \r
\r
+  { "STREXD", 0xe8d00f4f, 0xfff00fff,  LDREXD  },                // STREXD <Rd>, <Rt>, <Rt2>, [<Rn>]                     \r
 \r
+  { "SRSDB", 0xe80dc000, 0xffdffff0, SRS_FORMAT },       // SRSDB<c> SP{!},#<mode>\r
+  { "SRS"  , 0xe98dc000, 0xffdffff0, SRS_FORMAT },       // SRS{IA}<c> SP{!},#<mode>\r
+  { "RFEDB", 0xe810c000, 0xffd0ffff, RFE_FORMAT },       // RFEDB<c> <Rn>{!}\r
+  { "RFE"  , 0xe990c000, 0xffd0ffff, RFE_FORMAT }        // RFE{IA}<c> <Rn>{!}\r
+};\r
 \r
-  //  1110 101x xxxx xxxx xxxx xxxx xxxx xxxx Data-processing\r
-  //  1110 11xx xxxx xxxx xxxx xxxx xxxx xxxx Coprocessor\r
-  \r
-  //  1111 0x0x xxxx xxxx 0xxx xxxx xxxx xxxx Data-processing modified immediate\r
-  //  1111 0x1x xxxx xxxx 0xxx xxxx xxxx xxxx Data-processing plain immediate\r
-  //  1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx Branches\r
-  \r
-  //  1111 1000 xxx0 xxxx xxxx xxxx xxxx xxxx Store single data item\r
-  //  1111 1001 xxx0 xxxx xxxx xxxx xxxx xxxx SIMD or load/store\r
-  //  1111 100x x001 xxxx xxxx xxxx xxxx xxxx Load byte, memory hints \r
-  //  1111 100x x011 xxxx xxxx xxxx xxxx xxxx Load halfword, memory hints\r
-  //  1111 100x x101 xxxx xxxx xxxx xxxx xxxx Load word \r
-\r
-  //  1111 1 010 xxxx xxxx xxxx xxxx xxxx xxxx Data-processing register\r
-  //  1111 1 011 0xxx xxxx xxxx xxxx xxxx xxxx Multiply\r
-  //  1111 1 011 1xxx xxxx xxxx xxxx xxxx xxxx Long Multiply\r
-  //  1111 1 1xx xxxx xxxx xxxx xxxx xxxx xxxx Coprocessor \r
-#endif\r
+CHAR8 *gShiftType[] = {\r
+  "LSL",\r
+  "LSR",\r
+  "ASR",\r
+  "ROR"\r
 };\r
 \r
 CHAR8 mThumbMregListStr[4*15 + 1];\r
@@ -222,7 +379,7 @@ ThumbMRegList (
   Str = mThumbMregListStr;\r
   *Str = '\0';\r
   AsciiStrCat  (Str, "{");\r
-  // R0 - R7, PC\r
+  \r
   for (Index = 0, First = TRUE; Index <= 15; Index++) {\r
     if ((RegBitMask & (1 << Index)) != 0) {\r
       Start = End = Index;\r
@@ -272,6 +429,19 @@ SignExtend32 (
   return Data;\r
 }\r
 \r
+//\r
+// Some instructions specify the PC is always considered aligned \r
+// The PC is after the instruction that is excuting. So you pass\r
+// in the instruction address and you get back the aligned answer\r
+//\r
+UINT32\r
+PCAlign4 (\r
+  IN  UINT32  Data\r
+  )\r
+{\r
+  return (Data + 4) & 0xfffffffc;\r
+}\r
+\r
 /**\r
   Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to \r
   point to next instructin. \r
@@ -298,11 +468,12 @@ DisassembleThumbInstruction (
   UINT32  OpCode32;\r
   UINT32  Index;\r
   UINT32  Offset;\r
-  UINT16  Rd, Rn, Rm;\r
+  UINT16  Rd, Rn, Rm, Rt, Rt2;\r
   BOOLEAN H1, H2, imod;\r
-  UINT32  PC, Target;\r
+  UINT32  PC, Target, msbit, lsbit;\r
   CHAR8   *Cond;\r
-  BOOLEAN S, J1, J2;\r
+  BOOLEAN S, J1, J2, P, U, W;\r
+  UINT32  coproc, opc1, opc2, CRd, CRn, CRm; \r
 \r
   OpCodePtr = *OpCodePtrPtr;\r
   OpCode = **OpCodePtrPtr;\r
@@ -334,6 +505,15 @@ DisassembleThumbInstruction (
         // A6.5.1  <Rd>, [<Rn>, #<5_bit_offset>]\r
         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 4) & 0x7c);   \r
         return;\r
+      case LOAD_STORE_FORMAT1_H:\r
+        // A6.5.1  <Rd>, [<Rn>, #<5_bit_offset>]\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 5) & 0x3e);   \r
+        return;\r
+      case LOAD_STORE_FORMAT1_B:\r
+        // A6.5.1  <Rd>, [<Rn>, #<5_bit_offset>]\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 6) & 0x1f);   \r
+        return;\r
+\r
       case LOAD_STORE_FORMAT2:\r
         // A6.5.1  <Rd>, [<Rn>, <Rm>]\r
         AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d, r%d]", Rd, Rn, Rm);   \r
@@ -341,12 +521,12 @@ DisassembleThumbInstruction (
       case LOAD_STORE_FORMAT3:\r
         // A6.5.1 <Rd>, [PC, #<8_bit_offset>]\r
         Target = (OpCode & 0xff) << 2;\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [pc, #0x%x] ;0x%08x", (OpCode >> 8) & 7, Target, PC + 4 + Target);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [pc, #0x%x] ;0x%08x", (OpCode >> 8) & 7, Target, PCAlign4 (PC) + Target);   \r
         return;\r
       case LOAD_STORE_FORMAT4:\r
         // Rt, [SP, #imm8]\r
         Target = (OpCode & 0xff) << 2;\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [sp, #0x%x]", (OpCode >> 8) & 7, Target, PC + 3 + Target);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [sp, #0x%x]", (OpCode >> 8) & 7, Target);   \r
         return;\r
       \r
       case LOAD_STORE_MULTIPLE_FORMAT1:\r
@@ -434,6 +614,18 @@ DisassembleThumbInstruction (
         // A7.1.24\r
         AsciiSPrint (&Buf[Offset], Size - Offset, " %a", (OpCode & BIT3) == 0 ? "LE":"BE");   \r
         return;\r
+\r
+      case DATA_CBZ:\r
+        // CB{N}Z <Rn>, <Lable>\r
+        Target = ((OpCode >> 2) & 0x3e) | (((OpCode & BIT9) == BIT9) ? BIT6 : 0);\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %08x", gReg[Rd], PC + 4 + Target); \r
+        return;\r
+\r
+      case ADR_FORMAT:\r
+        // ADR <Rd>, <Label>\r
+        Target = (OpCode & 0xff) << 2;\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %08x", gReg[(OpCode >> 8) & 7], PCAlign4 (PC) + Target); \r
+        return;\r
       }\r
     }\r
   }\r
@@ -441,6 +633,11 @@ DisassembleThumbInstruction (
   \r
   // Thumb2 are 32-bit instructions\r
   *OpCodePtrPtr += 1;\r
+  Rt  = (OpCode32 >> 12) & 0xf;\r
+  Rt2 = (OpCode32 >> 8) & 0xf;\r
+  Rd  = (OpCode32 >> 8) & 0xf;\r
+  Rm  = (OpCode32 & 0xf);\r
+  Rn  = (OpCode32 >> 16) & 0xf;\r
   for (Index = 0; Index < sizeof (gOpThumb2)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r
     if ((OpCode32 & gOpThumb2[Index].Mask) == gOpThumb2[Index].OpCode) {\r
       if (Extended) {\r
@@ -475,8 +672,8 @@ DisassembleThumbInstruction (
         return;\r
 \r
       case BL_T2:\r
-        // S:I1:I2:imm10:imm11:00\r
-        Target = ((OpCode32 << 2) & 0x1ffc) + ((OpCode32 >> 3) & 0x7fe000);\r
+        // BLX  S:I1:I2:imm10:imm11:0\r
+        Target = ((OpCode32 << 1) & 0xffc) + ((OpCode32 >> 4) & 0x3ff000);\r
         S  = (OpCode32 & BIT26) == BIT26;\r
         J1 = (OpCode32 & BIT13) == BIT13;\r
         J2 = (OpCode32 & BIT11) == BIT11;\r
@@ -484,8 +681,229 @@ DisassembleThumbInstruction (
         Target |= (!(J1 ^ S) ? BIT24 : 0);  // I1\r
         Target |= (S ? BIT25 : 0);  // S\r
         Target = SignExtend32 (Target, BIT25);\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PCAlign4 (PC) + Target);   \r
+        return;\r
+\r
+      case POP_T2:\r
+        // <reglist>  some must be zero, handled in table\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList (OpCode32 & 0xffff));\r
+        return;\r
+\r
+      case POP_T3:\r
+        // <register> \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[(OpCode32 >> 12) & 0xf]);\r
+        return;\r
+\r
+      case STM_FORMAT:\r
+        // <Rn>{!}, <registers>\r
+        W = (OpCode32 & BIT21) == BIT21;\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, %a", gReg[(OpCode32 >> 16) & 0xf], W ? "!":"", ThumbMRegList (OpCode32 & 0xffff));\r
+        return;\r
+\r
+      case LDM_REG_IMM12_SIGNED:\r
+        // <rt>, <label>\r
+        Target = OpCode32 & 0xfff; \r
+        if ((OpCode32 & BIT23) == 0) {\r
+          // U == 0 means subtrack, U == 1 means add\r
+          Target = -Target;\r
+        }\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[(OpCode32 >> 12) & 0xf], PCAlign4 (PC) + Target);\r
+        return;\r
+\r
+      case LDM_REG_INDIRECT_LSL:\r
+        // <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
+        Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a, %a", gReg[Rt], gReg[Rn], gReg[Rm]);\r
+        if (((OpCode32 >> 4) && 3) == 0) {\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
+        } else {\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL #%d]", (OpCode32 >> 4) && 3);\r
+        }\r
+        return;\r
+      \r
+      case LDM_REG_IMM12:\r
+        // <rt>, [<rn>, {, #<imm12>]}\r
+        Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);\r
+        if ((OpCode32 && 0xfff) == 0) {\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
+        } else {\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, ", #0x%x]", OpCode32 & 0xfff);\r
+        }\r
+        return;\r
+\r
+      case LDM_REG_IMM8:\r
+        ASSERT (FALSE);\r
+        // <rt>, [<rn>, {, #<imm8>}]{!}\r
+        W = (OpCode32 & BIT8) == BIT8;\r
+        U = (OpCode32 & BIT9) == BIT9;\r
+        P = (OpCode32 & BIT10) == BIT10;\r
+        Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);\r
+        if (P) {\r
+          if ((OpCode32 && 0xff) == 0) {\r
+            AsciiSPrint (&Buf[Offset], Size - Offset, "]%a", W?"!":"");\r
+          } else {\r
+            AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", OpCode32 & 0xff, U?"":"-" , W?"!":"");\r
+          }\r
+        } else {\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, "], #%a0x%x]", OpCode32 & 0xff, U?"":"-");\r
+        }\r
+        return;\r
+\r
+      case LDRD_REG_IMM8_SIGNED:\r
+        // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
+        P = (OpCode32 & BIT24) == BIT24;  // index = P\r
+        U = (OpCode32 & BIT23) == BIT23;  \r
+        W = (OpCode32 & BIT21) == BIT21;\r
+        Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, [%a", gReg[Rt], gReg[Rt2], gReg[Rn]);\r
+        if (P) {\r
+          if ((OpCode32 && 0xff) == 0) {\r
+            AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
+          } else {\r
+            AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", U?"":"-", (OpCode32 & 0xff) << 2, W?"!":"");\r
+          }\r
+        } else {\r
+          if ((OpCode32 && 0xff) != 0) {\r
+            AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x", U?"":"-", (OpCode32 & 0xff) << 2);\r
+          }\r
+        }\r
+        return;\r
+\r
+      case LDRD_REG_IMM8: \r
+        // LDRD <rt>, <rt2>, <label>   \r
+        Target = (OpCode32 & 0xff) << 2; \r
+        if ((OpCode32 & BIT23) == 0) {\r
+          // U == 0 means subtrack, U == 1 means add\r
+          Target = -Target;\r
+        }\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a", gReg[Rt], gReg[Rt2], PC + 4 + Target);\r
+        return;\r
+\r
+      case LDREXB:\r
+        // LDREXB <Rt>, [Rn]\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a]", gReg[Rt], gReg[Rn]);\r
+        return;\r
+\r
+      case LDREXD:\r
+        // LDREXD <Rt>, <Rt2>, [<Rn>]\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, ,%a, [%a]", gReg[Rt], gReg[Rt2], gReg[Rn]);\r
+        return;\r
+      \r
+      case SRS_FORMAT:\r
+        // SP{!}, #<mode>\r
+        W = (OpCode32 & BIT21) == BIT21;\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " SP%a, #0x%x", W?"!":"", OpCode32 & 0x1f);\r
+        return;\r
+\r
+      case RFE_FORMAT:\r
+        // <Rn>{!}\r
+        W = (OpCode32 & BIT21) == BIT21;\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, #0x%x", gReg[Rn], W?"!":"");\r
+        return;\r
+      \r
+      case ADD_IMM12:\r
+        // ADD{S} <Rd>, <Rn>, #<const>   i:imm3:imm8\r
+        if ((OpCode32 & BIT20) == BIT20) {\r
+          Buf[Offset - 3] = 'S';  // assume %-6a\r
+        }\r
+        Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #0x%x", gReg[Rd], gReg[Rn], Target); \r
+        return;\r
+\r
+      case ADD_IMM5:\r
+        // ADC{S}  <Rd>, <Rn>, <Rm> {,LSL #<const>} imm3:imm2\r
+        if ((OpCode32 & BIT20) == BIT20) {\r
+          Buf[Offset - 3] = 'S';  // assume %-6a\r
+        }\r
+        Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
+        Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a", gReg[Rd], gReg[Rn], gReg[Rm]); \r
+        if (Target != 0) {\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL %d", gShiftType[(OpCode >> 5) & 3], Target); \r
+        }\r
+        return;\r
+\r
+      case ADD_IMM5_2REG:\r
+        // CMP  <Rn>, <Rm> {,LSL #<const>} imm3:imm2\r
+        Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
+        Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rn], gReg[Rm]); \r
+        if (Target != 0) {\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL %d", gShiftType[(OpCode >> 5) & 3], Target); \r
+        }\r
+\r
+\r
+      case ASR_IMM5:\r
+        // ARS  <Rd>, <Rm> #<const>} imm3:imm2\r
+        if ((OpCode32 & BIT20) == BIT20) {\r
+          Buf[Offset - 3] = 'S';  // assume %-6a\r
+        }\r
+        Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a #%d", gReg[Rd], gReg[Rm], Target); \r
+        return;\r
+\r
+      case ASR_3REG:\r
+        // ARS  <Rd>, <Rn>, <Rm>\r
+        if ((OpCode32 & BIT20) == BIT20) {\r
+          Buf[Offset - 3] = 'S';  // assume %-6a\r
+        }\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a %a", gReg[Rd], gReg[Rn], gReg[Rm]); \r
+        return;\r
+\r
+      case ADR_THUMB2:\r
+        // ADDR <Rd>, <label>\r
+        Target = (OpCode32 & 0xff) | ((OpCode32 >> 8) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
+        if ((OpCode & (BIT23 | BIT21)) == (BIT23 | BIT21)) {\r
+          Target = PCAlign4 (PC) - Target;\r
+        } else {\r
+          Target = PCAlign4 (PC) + Target;\r
+        }\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, 0x%08x", gReg[Rd], Target); \r
+        return;\r
+\r
+      case CMN_THUMB2:\r
+        // CMN <Rn>, #<const>}\r
+        Target = (OpCode32 & 0xff) | ((OpCode >> 4) && 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #0x%x", gReg[Rn], Target); \r
+        return;\r
+\r
+      case BFC_THUMB2:\r
+        // BFI <Rd>, <Rn>, #<lsb>, #<width>\r
+        msbit = OpCode32 & 0x1f;\r
+        lsbit = ((OpCode32 >> 6) & 3) | ((OpCode >> 10) &  0x1c);\r
+        if ((Rn == 0xf) & (AsciiStrCmp (gOpThumb2[Index].Start, "BFC") == 0)){\r
+          // BFC <Rd>, #<lsb>, #<width>\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #%d, #%d", gReg[Rd], lsbit, msbit - lsbit + 1); \r
+        } else if (AsciiStrCmp (gOpThumb2[Index].Start, "BFI") == 0) {\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #%d, #%d", gReg[Rd], gReg[Rn], lsbit, msbit - lsbit + 1); \r
+        } else {\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #%d, #%d", gReg[Rd], gReg[Rn], lsbit, msbit + 1); \r
+        }\r
+        return;\r
+\r
+      case CPD_THUMB2:\r
+        // <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>\r
+        coproc = (OpCode32 >> 8)  & 0xf;\r
+        opc1   = (OpCode32 >> 20) & 0xf;\r
+        opc2   = (OpCode32 >> 5)  & 0x7;\r
+        CRd    = (OpCode32 >> 12) & 0xf;\r
+        CRn    = (OpCode32 >> 16) & 0xf;\r
+        CRm    = OpCode32 & 0xf;\r
+        Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " p%d,#%d,c%d,c%d,c%d", coproc, opc1, CRd, CRn, CRm);\r
+        if (opc2 != 0) {\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, ",#%d,", opc2);\r
+        }\r
         return;\r
+\r
+      case THUMB2_2REGS:\r
+        // <Rd>, <Rm>\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd], gReg[Rm]);\r
+        return;\r
+\r
+      case THUMB2_4REGS:\r
+        // <Rd>, <Rn>, <Rm>, <Ra>\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a, %a", gReg[Rd], gReg[Rn], gReg[Rm], gReg[Rt]);\r
+        return;\r
+\r
+      case THUMB2_NO_ARGS:\r
+      default:\r
+        break;\r
       }\r
     }\r
   }\r