]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/ArmDisassemblerLib/ThumbDisassembler.c
ARM Packages: Removed trailing spaces
[mirror_edk2.git] / ArmPkg / Library / ArmDisassemblerLib / ThumbDisassembler.c
index 02958c85c209cb99b8c5602284d7daa6389ad444..108cda9442983b10575ea7a5fd5f6da17a346552 100644 (file)
@@ -1,9 +1,16 @@
 /** @file\r
-  Default exception handler\r
+  Thumb Dissassembler. Still a work in progress.\r
 \r
-  Copyright (c) 2008-2010, Apple Inc. All rights reserved.\r
-  \r
-  All rights reserved. This program and the accompanying materials\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.<BR>\r
+\r
+  This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
   http://opensource.org/licenses/bsd-license.php\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
-#define LOAD_STORE_MULTIPLE_FORMAT1   5 \r
-#define PUSH_FORMAT                   6 \r
-#define POP_FORMAT                  106 \r
+#define LOAD_STORE_MULTIPLE_FORMAT1   5\r
+#define PUSH_FORMAT                   6\r
+#define POP_FORMAT                  106\r
 #define IMMED_8                       7\r
 #define CONDITIONAL_BRANCH            8\r
 #define UNCONDITIONAL_BRANCH          9\r
@@ -44,10 +55,50 @@ 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
+#define IT_BLOCK                     24\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
+#define ADD_IMM12_1REG              231\r
+#define THUMB2_IMM16                232\r
+#define MRC_THUMB2                  233\r
+#define MRRC_THUMB2                 234\r
+#define THUMB2_MRS                  235\r
+#define THUMB2_MSR                  236\r
+\r
+\r
 \r
 \r
 typedef struct {\r
@@ -59,15 +110,15 @@ typedef struct {
 \r
 THUMB_INSTRUCTIONS gOpThumb[] = {\r
 // Thumb 16-bit instrucitons\r
-//         Op      Mask    Format\r
-  { "ADC" , 0x4140, 0xffc0, DATA_FORMAT5 },\r
-\r
+//          Op       Mask   Format\r
+  { "ADC" , 0x4140, 0xffc0, DATA_FORMAT5 },  // ADC <Rndn>, <Rm>\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
   { "ADD" , 0x4400, 0xff00, DATA_FORMAT8 },   // A8.6.9\r
   { "ADD" , 0xa000, 0xf100, DATA_FORMAT6_PC },\r
-  { "ADD" , 0xa800, 0xf800, DATA_FORMAT6_SP }, \r
+  { "ADD" , 0xa800, 0xf800, DATA_FORMAT6_SP },\r
   { "ADD" , 0xb000, 0xff80, DATA_FORMAT7 },\r
 \r
   { "AND" , 0x4000, 0xffc0, DATA_FORMAT5 },\r
@@ -82,6 +133,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
@@ -93,22 +146,23 @@ THUMB_INSTRUCTIONS gOpThumb[] = {
   { "EOR" , 0x4040, 0xffc0, DATA_FORMAT5 },\r
 \r
   { "LDMIA" , 0xc800, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1 },\r
-  { "LDR"   , 0x6800, 0xf800, LOAD_STORE_FORMAT1 },\r
-  { "LDR"   , 0x5800, 0xfe00, LOAD_STORE_FORMAT2 },\r
+  { "LDR"   , 0x6800, 0xf800, LOAD_STORE_FORMAT1 },  // LDR <Rt>, [<Rn> {,#<imm>}]\r
+  { "LDR"   , 0x5800, 0xfe00, LOAD_STORE_FORMAT2 },  // STR <Rt>, [<Rn>, <Rm>]\r
   { "LDR"   , 0x4800, 0xf800, LOAD_STORE_FORMAT3 },\r
-  { "LDR"   , 0x9800, 0xf800, LOAD_STORE_FORMAT4 },\r
-  { "LDRB"  , 0x7800, 0xf800, LOAD_STORE_FORMAT1 },\r
-  { "LDRB"  , 0x5c00, 0xfe00, LOAD_STORE_FORMAT2 },\r
-  { "LDRH"  , 0x8800, 0xf800, LOAD_STORE_FORMAT1 },\r
+  { "LDR"   , 0x9800, 0xf800, LOAD_STORE_FORMAT4 },  // LDR <Rt>, [SP, #<imm>]\r
+  { "LDRB"  , 0x7800, 0xf800, LOAD_STORE_FORMAT1_B },\r
+  { "LDRB"  , 0x5c00, 0xfe00, LOAD_STORE_FORMAT2 },  // STR <Rt>, [<Rn>, <Rm>]\r
+  { "LDRH"  , 0x8800, 0xf800, LOAD_STORE_FORMAT1_H },\r
   { "LDRH"  , 0x7a00, 0xfe00, LOAD_STORE_FORMAT2 },\r
-  { "LDRSB" , 0x5600, 0xfe00, LOAD_STORE_FORMAT2 },\r
+  { "LDRSB" , 0x5600, 0xfe00, LOAD_STORE_FORMAT2 },  // STR <Rt>, [<Rn>, <Rm>]\r
   { "LDRSH" , 0x5e00, 0xfe00, LOAD_STORE_FORMAT2 },\r
\r
+\r
   { "MOVS", 0x0000, 0xffc0, DATA_FORMAT5 },   // LSL with imm5 == 0 is a MOVS, so this must go before LSL\r
   { "LSL" , 0x0000, 0xf800, DATA_FORMAT4 },\r
   { "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
@@ -117,7 +171,7 @@ THUMB_INSTRUCTIONS gOpThumb[] = {
   { "MUL" , 0x4340, 0xffc0, DATA_FORMAT5 },\r
   { "MVN" , 0x41c0, 0xffc0, DATA_FORMAT5 },\r
   { "NEG" , 0x4240, 0xffc0, DATA_FORMAT5 },\r
-  { "ORR" , 0x4180, 0xffc0, DATA_FORMAT5 },\r
+  { "ORR" , 0x4300, 0xffc0, DATA_FORMAT5 },\r
   { "POP" , 0xbc00, 0xfe00, POP_FORMAT },\r
   { "PUSH", 0xb400, 0xfe00, PUSH_FORMAT },\r
 \r
@@ -130,82 +184,209 @@ THUMB_INSTRUCTIONS gOpThumb[] = {
   { "SETEND" , 0xb650, 0xfff0, ENDIAN_FORMAT },\r
 \r
   { "STMIA" , 0xc000, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1 },\r
-  { "STR"   , 0x6000, 0xf800, LOAD_STORE_FORMAT1 },\r
-  { "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"  , 0x5800, 0xfe00, LOAD_STORE_FORMAT2 },\r
-  { "STRH"  , 0x8000, 0xf800, LOAD_STORE_FORMAT1 },\r
-  { "STRH"  , 0x5200, 0xfe00, LOAD_STORE_FORMAT2 },\r
+  { "STR"   , 0x6000, 0xf800, LOAD_STORE_FORMAT1 },   // STR  <Rt>, [<Rn> {,#<imm>}]\r
+  { "STR"   , 0x5000, 0xfe00, LOAD_STORE_FORMAT2 },   // STR  <Rt>, [<Rn>, <Rm>]\r
+  { "STR"   , 0x9000, 0xf800, LOAD_STORE_FORMAT4 },   // STR  <Rt>, [SP, #<imm>]\r
+  { "STRB"  , 0x7000, 0xf800, LOAD_STORE_FORMAT1_B }, // STRB <Rt>, [<Rn>, #<imm5>]\r
+  { "STRB"  , 0x5400, 0xfe00, LOAD_STORE_FORMAT2 },   // STRB <Rt>, [<Rn>, <Rm>]\r
+  { "STRH"  , 0x8000, 0xf800, LOAD_STORE_FORMAT1_H }, // STRH <Rt>, [<Rn>{,#<imm>}]\r
+  { "STRH"  , 0x5200, 0xfe00, LOAD_STORE_FORMAT2 },   // STRH <Rt>, [<Rn>, <Rm>]\r
 \r
   { "SUB" , 0x1e00, 0xfe00, DATA_FORMAT2 },\r
   { "SUB" , 0x3800, 0xf800, DATA_FORMAT3 },\r
   { "SUB" , 0x1a00, 0xfe00, DATA_FORMAT1 },\r
   { "SUB" , 0xb080, 0xff80, DATA_FORMAT7 },\r
 \r
+  { "SBC" , 0x4180, 0xffc0, DATA_FORMAT5 },\r
+\r
   { "SWI" , 0xdf00, 0xff00, IMMED_8 },\r
   { "SXTB", 0xb240, 0xffc0, DATA_FORMAT5 },\r
   { "SXTH", 0xb200, 0xffc0, DATA_FORMAT5 },\r
   { "TST" , 0x4200, 0xffc0, DATA_FORMAT5 },\r
   { "UXTB", 0xb2c0, 0xffc0, DATA_FORMAT5 },\r
-  { "UXTH", 0xb280, 0xffc0, DATA_FORMAT5 }\r
+  { "UXTH", 0xb280, 0xffc0, DATA_FORMAT5 },\r
+\r
+  { "IT",   0xbf00, 0xff00, IT_BLOCK }\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
-  \r
-#if 0  \r
-  \r
-  // 32-bit Thumb instructions  op1 01\r
-  \r
-  //  1110 100x x0xx xxxx xxxx xxxx xxxx xxxx Load/store multiple\r
+//Instruct  OpCode      OpCode Mask  Addressig Mode\r
+\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
+  { "MOV",  0xf04f0000, 0xfbef8000, ADD_IMM12_1REG }, // MOV  <Rd>, #<const>\r
+  { "MOVW", 0xf2400000, 0xfbe08000, THUMB2_IMM16 },   // MOVW <Rd>, #<const>\r
+  { "MOVT", 0xf2c00000, 0xfbe08000, THUMB2_IMM16 },   // MOVT <Rd>, #<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
+  { "MRC",   0xee100000, 0xff100000, MRC_THUMB2 },  // MRC  <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>\r
+  { "MRC2",  0xfe100000, 0xff100000, MRC_THUMB2 },  // MRC2 <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>\r
+  { "MRRC",  0xec500000, 0xfff00000, MRRC_THUMB2 },  // MRRC <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>\r
+  { "MRRC2", 0xfc500000, 0xfff00000, MRRC_THUMB2 },  // MRR2 <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>\r
+\r
+  { "MRS",   0xf3ef8000, 0xfffff0ff, THUMB2_MRS  }, // MRS  <Rd>, CPSR\r
+  { "MSR",   0xf3808000, 0xfff0fcff, THUMB2_MSR  }, // MSR  CPSR_fs, <Rn>\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
+  { "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
+  { "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", 0xf9100800, 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
+  { "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
+  { "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_IA_FORMAT },    // SRS{IA}<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_IA_FORMAT },    // RFE{IA}<c> <Rn>{!}\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
-\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
-\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
-\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
+  { "RFE"  , 0xe990c000, 0xffd0ffff, RFE_FORMAT }        // RFE{IA}<c> <Rn>{!}\r
+};\r
+\r
+CHAR8 *gShiftType[] = {\r
+  "LSL",\r
+  "LSR",\r
+  "ASR",\r
+  "ROR"\r
 };\r
 \r
 CHAR8 mThumbMregListStr[4*15 + 1];\r
@@ -218,24 +399,24 @@ ThumbMRegList (
   UINTN     Index, Start, End;\r
   CHAR8     *Str;\r
   BOOLEAN   First;\r
\r
+\r
   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
       for (Index++; ((RegBitMask & (1 << Index)) != 0) && (Index <= 9); Index++) {\r
         End = Index;\r
       }\r
-      \r
+\r
       if (!First) {\r
         AsciiStrCat  (Str, ",");\r
       } else {\r
         First = FALSE;\r
       }\r
-      \r
+\r
       if (Start == End) {\r
         AsciiStrCat  (Str, gReg[Start]);\r
       } else {\r
@@ -249,7 +430,7 @@ ThumbMRegList (
     AsciiStrCat  (Str, "ERROR");\r
   }\r
   AsciiStrCat  (Str, "}");\r
-  \r
+\r
   // BugBug: Make caller pass in buffer it is cleaner\r
   return mThumbMregListStr;\r
 }\r
@@ -263,33 +444,47 @@ SignExtend32 (
   if (((Data & TopBit) == 0) || (TopBit == BIT31)) {\r
     return Data;\r
   }\r
\r
+\r
   do {\r
     TopBit <<= 1;\r
-    Data |= TopBit; \r
+    Data |= TopBit;\r
   } while ((TopBit & BIT31) != BIT31);\r
 \r
   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
-  \r
-  We cheat and only decode instructions that access \r
+  Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to\r
+  point to next instructin.\r
+\r
+  We cheat and only decode instructions that access\r
   memory. If the instruction is not found we dump the instruction in hex.\r
-   \r
-  @param  OpCodePtrPtr  Pointer to pointer of ARM Thumb instruction to disassemble.  \r
+\r
+  @param  OpCodePtrPtr  Pointer to pointer of ARM Thumb instruction to disassemble.\r
   @param  Buf           Buffer to sprintf disassembly into.\r
-  @param  Size          Size of Buf in bytes. \r
+  @param  Size          Size of Buf in bytes.\r
   @param  Extended    TRUE dump hex for instruction too.\r
-  \r
+\r
 **/\r
 VOID\r
 DisassembleThumbInstruction (\r
   IN  UINT16    **OpCodePtrPtr,\r
   OUT CHAR8     *Buf,\r
   OUT UINTN     Size,\r
+  OUT UINT32    *ItBlock,\r
   IN  BOOLEAN   Extended\r
   )\r
 {\r
@@ -298,15 +493,18 @@ 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
+  //BOOLEAN ItFlag;\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
+  UINT32  Mask;\r
 \r
   OpCodePtr = *OpCodePtrPtr;\r
   OpCode = **OpCodePtrPtr;\r
-  \r
+\r
   // Thumb2 is a stream of 16-bit instructions not a 32-bit instruction.\r
   OpCode32 = (((UINT32)OpCode) << 16) | *(OpCodePtr + 1);\r
 \r
@@ -321,53 +519,70 @@ DisassembleThumbInstruction (
 \r
   // Increment by the minimum instruction size, Thumb2 could be bigger\r
   *OpCodePtrPtr += 1;\r
-  \r
+\r
+  // Manage IT Block ItFlag TRUE means we are in an IT block\r
+  /*if (*ItBlock != 0) {\r
+    ItFlag = TRUE;\r
+    *ItBlock -= 1;\r
+  } else {\r
+    ItFlag = FALSE;\r
+  }*/\r
+\r
   for (Index = 0; Index < sizeof (gOpThumb)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r
     if ((OpCode & gOpThumb[Index].Mask) == gOpThumb[Index].OpCode) {\r
       if (Extended) {\r
-        Offset = AsciiSPrint (Buf, Size, "0x%04x       %-6a", OpCode, gOpThumb[Index].Start);   \r
+        Offset = AsciiSPrint (Buf, Size, "0x%04x       %-6a", OpCode, gOpThumb[Index].Start);\r
       } else {\r
-        Offset = AsciiSPrint (Buf, Size, "%-6a", gOpThumb[Index].Start);   \r
+        Offset = AsciiSPrint (Buf, Size, "%-6a", gOpThumb[Index].Start);\r
       }\r
       switch (gOpThumb[Index].AddressMode) {\r
       case LOAD_STORE_FORMAT1:\r
         // 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
+        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
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d, r%d]", Rd, Rn, Rm);\r
         return;\r
       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
+\r
       case LOAD_STORE_MULTIPLE_FORMAT1:\r
         // <Rn>!, {r0-r7}\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d!, %a", (OpCode >> 8) & 7, ThumbMRegList (OpCode & 0xff));   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d!, %a", (OpCode >> 8) & 7, ThumbMRegList (OpCode & 0xff));\r
         return;\r
\r
+\r
       case POP_FORMAT:\r
         // POP {r0-r7,pc}\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT15 : 0)));   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT15 : 0)));\r
         return;\r
 \r
       case PUSH_FORMAT:\r
         // PUSH {r0-r7,lr}\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT14 : 0)));   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT14 : 0)));\r
         return;\r
 \r
-      \r
+\r
       case IMMED_8:\r
         // A6.7 <immed_8>\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%x", OpCode & 0xff);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%x", OpCode & 0xff);\r
         return;\r
 \r
       case CONDITIONAL_BRANCH:\r
@@ -376,77 +591,119 @@ DisassembleThumbInstruction (
         Cond = gCondition[(OpCode >> 8) & 0xf];\r
         Buf[Offset-5] = *Cond++;\r
         Buf[Offset-4] = *Cond;\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x",  PC + 4 + SignExtend32 ((OpCode & 0xff) << 1, BIT8));   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x",  PC + 4 + SignExtend32 ((OpCode & 0xff) << 1, BIT8));\r
         return;\r
       case UNCONDITIONAL_BRANCH_SHORT:\r
         // A6.3.2 B  <target_address>\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", PC + 4 + SignExtend32 ((OpCode & 0x3ff) << 1, BIT11));   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", PC + 4 + SignExtend32 ((OpCode & 0x3ff) << 1, BIT11));\r
         return;\r
\r
+\r
       case BRANCH_EXCHANGE:\r
         // A6.3.3 BX|BLX <Rm>\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[Rn | (H2 ? 8:0)]);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[Rn | (H2 ? 8:0)]);\r
         return;\r
 \r
       case DATA_FORMAT1:\r
         // A6.4.3  <Rd>, <Rn>, <Rm>\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, r%d", Rd, Rn, Rm);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, r%d", Rd, Rn, Rm);\r
         return;\r
       case DATA_FORMAT2:\r
         // A6.4.3  <Rd>, <Rn>, #3_bit_immed\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rd, Rn, Rm);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rd, Rn, Rm);\r
         return;\r
       case DATA_FORMAT3:\r
         // A6.4.3  <Rd>|<Rn>, #imm8\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, #0x%x", (OpCode >> 8) & 7, OpCode & 0xff);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, #0x%x", (OpCode >> 8) & 7, OpCode & 0xff);\r
         return;\r
       case DATA_FORMAT4:\r
         // A6.4.3  <Rd>|<Rm>, #immed_5\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rn, Rd, (OpCode >> 6) & 0x1f);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rn, Rd, (OpCode >> 6) & 0x1f);\r
         return;\r
       case DATA_FORMAT5:\r
         // A6.4.3  <Rd>|<Rm>, <Rm>|<Rs>\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d", Rd, Rn);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d", Rd, Rn);\r
         return;\r
       case DATA_FORMAT6_SP:\r
         // A6.4.3  <Rd>, <reg>, #<8_Bit_immed>\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, sp, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, sp, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2);\r
         return;\r
       case DATA_FORMAT6_PC:\r
         // A6.4.3  <Rd>, <reg>, #<8_Bit_immed>\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, pc, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, pc, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2);\r
         return;\r
       case DATA_FORMAT7:\r
         // A6.4.3  SP, SP, #<7_Bit_immed>\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " sp, sp, 0x%x", (OpCode & 0x7f)*4);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " sp, sp, 0x%x", (OpCode & 0x7f)*4);\r
         return;\r
       case DATA_FORMAT8:\r
         // A6.4.3  <Rd>|<Rn>, <Rm>\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd | (H1 ? 8:0)], gReg[Rn | (H2 ? 8:0)]);   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd | (H1 ? 8:0)], gReg[Rn | (H2 ? 8:0)]);\r
         return;\r
-      \r
+\r
       case CPS_FORMAT:\r
         // A7.1.24\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, "%a %a%a%a", imod ? "ID":"IE", ((OpCode & BIT2) == 0) ? "":"a",  ((OpCode & BIT1) == 0) ? "":"i", ((OpCode & BIT0) == 0) ? "":"f");   \r
+        AsciiSPrint (&Buf[Offset], Size - Offset, "%a %a%a%a", imod ? "ID":"IE", ((OpCode & BIT2) == 0) ? "":"a",  ((OpCode & BIT1) == 0) ? "":"i", ((OpCode & BIT0) == 0) ? "":"f");\r
         return;\r
 \r
       case ENDIAN_FORMAT:\r
         // A7.1.24\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " %a", (OpCode & BIT3) == 0 ? "LE":"BE");   \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
+      case IT_BLOCK:\r
+        // ITSTATE = cond:mask   OpCode[7:4]:OpCode[3:0]\r
+        // ITSTATE[7:5] == cond[3:1]\r
+        // ITSTATE[4] == 1st Instruction cond[0]\r
+        // ITSTATE[3] == 2st Instruction cond[0]\r
+        // ITSTATE[2] == 3st Instruction cond[0]\r
+        // ITSTATE[1] == 4st Instruction cond[0]\r
+        // ITSTATE[0] == 1 4 instruction IT block. 0 means 0,1,2 or 3 instructions\r
+        // 1st one  in ITSTATE low bits defines the number of instructions\r
+        Mask = (OpCode & 0xf);\r
+        if ((Mask & 0x1) == 0x1) {\r
+          *ItBlock = 4;\r
+          Offset +=  AsciiSPrint (&Buf[Offset], Size - Offset, "%a%a%a", (Mask & BIT3)?"T":"E", (Mask & BIT2)?"T":"E", (Mask & BIT1)?"T":"E");\r
+        } else if ((OpCode & 0x3) == 0x2) {\r
+          *ItBlock = 3;\r
+          Offset +=  AsciiSPrint (&Buf[Offset], Size - Offset, "%a%a", (Mask & BIT3)?"T":"E", (Mask & BIT2)?"T":"E");\r
+        } else if ((OpCode & 0x7) == 0x4) {\r
+          *ItBlock = 2;\r
+          Offset +=  AsciiSPrint (&Buf[Offset], Size - Offset, "%a", (Mask & BIT3)?"T":"E");\r
+        } else if ((OpCode & 0xf) == 0x8) {\r
+          *ItBlock = 1;\r
+        }\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gCondition[(OpCode >> 4) & 0xf]);\r
         return;\r
       }\r
     }\r
   }\r
 \r
-  \r
+\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
-        Offset = AsciiSPrint (Buf, Size, "0x%04x       %-6a", OpCode32, gOpThumb2[Index].Start);   \r
+        Offset = AsciiSPrint (Buf, Size, "0x%04x   %-6a", OpCode32, gOpThumb2[Index].Start);\r
       } else {\r
-        Offset = AsciiSPrint (Buf, Size, "       %-6a", gOpThumb2[Index].Start);   \r
+        Offset = AsciiSPrint (Buf, Size, "   %-6a", gOpThumb2[Index].Start);\r
       }\r
       switch (gOpThumb2[Index].AddressMode) {\r
       case B_T3:\r
@@ -455,37 +712,306 @@ DisassembleThumbInstruction (
         Buf[Offset-4] = *Cond;\r
         // S:J2:J1:imm6:imm11:0\r
         Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3f000);\r
-        Target |= (OpCode & BIT11) ? BIT18 : 0;  // J2\r
-        Target |= (OpCode & BIT13) ? BIT17 : 0;  // J1\r
-        Target |= (OpCode & BIT26) ? BIT19 : 0;  // S\r
-        Target = SignExtend32 (Target, BIT19);\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", Target);   \r
+        Target |= ((OpCode32 & BIT11) == BIT11)? BIT19 : 0;  // J2\r
+        Target |= ((OpCode32 & BIT13) == BIT13)? BIT18 : 0;  // J1\r
+        Target |= ((OpCode32 & BIT26) == BIT26)? BIT20 : 0;  // S\r
+        Target = SignExtend32 (Target, BIT20);\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target);\r
         return;\r
       case B_T4:\r
         // S:I1:I2:imm10:imm11:0\r
         Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3ff000);\r
-        S  = (OpCode & BIT26);\r
-        J1 = (OpCode & BIT13);\r
-        J2 = (OpCode & BIT11);\r
-        Target |= !(J2 ^ S) ? BIT21 : 0;  // I2\r
-        Target |= !(J1 ^ S) ? BIT22 : 0;  // I1\r
-        Target |= (OpCode & BIT26) ? BIT23 : 0;  // S\r
-        Target = SignExtend32 (Target, BIT23);\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", Target);   \r
+        S  = (OpCode32 & BIT26) == BIT26;\r
+        J1 = (OpCode32 & BIT13) == BIT13;\r
+        J2 = (OpCode32 & BIT11) == BIT11;\r
+        Target |= (!(J2 ^ S) ? BIT22 : 0);  // I2\r
+        Target |= (!(J1 ^ S) ? BIT23 : 0);  // I1\r
+        Target |= (S ? BIT24 : 0);  // S\r
+        Target = SignExtend32 (Target, BIT24);\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target);\r
         return;\r
 \r
       case BL_T2:\r
-        // S:I1:I2:imm10:imm11:0\r
-        Target = ((OpCode32 << 2) & 0x1ffc) + ((OpCode32 >> 3) & 0x7fe000);\r
-        S  = (OpCode & BIT26);\r
-        J1 = (OpCode & BIT13);\r
-        J2 = (OpCode & BIT11);\r
-        Target |= !(J2 ^ S) ? BIT22 : 0;  // I2\r
-        Target |= !(J1 ^ S) ? BIT23 : 0;  // I1\r
-        Target |= (OpCode & BIT26) ? BIT24 : 0;  // S\r
-        Target = SignExtend32 (Target, BIT24);\r
-        AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", Target);   \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
+        Target |= (!(J2 ^ S) ? BIT23 : 0);  // I2\r
+        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", 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
+        // <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", U?"":"-" , OpCode32 & 0xff, W?"!":"");\r
+          }\r
+        } else {\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, "], #%a0x%x", U?"":"-", OpCode32 & 0xff);\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_IMM12_1REG:\r
+        // MOV{S} <Rd>, #<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, #0x%x", gReg[Rd], Target);\r
+        return;\r
+\r
+      case THUMB2_IMM16:\r
+        // MOVW <Rd>, #<const>   i:imm3:imm8\r
+        Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
+        Target |= ((OpCode32 >> 4) & 0xf0000);\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #0x%x", gReg[Rd], 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 MRC_THUMB2:\r
+        // MRC  <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>\r
+        coproc = (OpCode32 >> 8)  & 0xf;\r
+        opc1   = (OpCode32 >> 20) & 0xf;\r
+        opc2   = (OpCode32 >> 5)  & 0x7;\r
+        CRn    = (OpCode32 >> 16) & 0xf;\r
+        CRm    = OpCode32 & 0xf;\r
+        Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " p%d,#%d,%a,c%d,c%d", coproc, opc1, gReg[Rt], CRn, CRm);\r
+        if (opc2 != 0) {\r
+          AsciiSPrint (&Buf[Offset], Size - Offset, ",#%d,", opc2);\r
+        }\r
+        return;\r
+\r
+      case MRRC_THUMB2:\r
+        // MRC  <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>,<opc2>\r
+        coproc = (OpCode32 >> 8)  & 0xf;\r
+        opc1   = (OpCode32 >> 20) & 0xf;\r
+        CRn    = (OpCode32 >> 16) & 0xf;\r
+        CRm    = OpCode32 & 0xf;\r
+        Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " p%d,#%d,%a,%a,c%d", coproc, opc1, gReg[Rt], gReg[Rt2], CRm);\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_MRS:\r
+        // MRS <Rd>, CPSR\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " %a, CPSR", gReg[Rd]);\r
+        return;\r
+\r
+      case THUMB2_MSR:\r
+        // MRS CPSR_<fields>, <Rd>\r
+        Target = (OpCode32 >> 10) & 3;\r
+        AsciiSPrint (&Buf[Offset], Size - Offset, " CPSR_%a%a, %a", (Target & 2) == 0 ? "":"f", (Target & 1) == 0 ? "":"s", gReg[Rd]);\r
+        return;\r
+\r
+      case THUMB2_NO_ARGS:\r
+      default:\r
+        break;\r
       }\r
     }\r
   }\r
@@ -505,32 +1031,34 @@ DisassembleArmInstruction (
 \r
 \r
 /**\r
-  Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to \r
-  point to next instructin. \r
-  \r
-  We cheat and only decode instructions that access \r
+  Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to\r
+  point to next instructin.\r
+\r
+  We cheat and only decode instructions that access\r
   memory. If the instruction is not found we dump the instruction in hex.\r
-   \r
-  @param  OpCodePtrPtr  Pointer to pointer of ARM Thumb instruction to disassemble.  \r
+\r
+  @param  OpCodePtrPtr  Pointer to pointer of ARM Thumb instruction to disassemble.\r
   @param  Thumb         TRUE for Thumb(2), FALSE for ARM instruction stream\r
   @param  Extended      TRUE dump hex for instruction too.\r
+  @param  ItBlock       Size of IT Block\r
   @param  Buf           Buffer to sprintf disassembly into.\r
-  @param  Size          Size of Buf in bytes. \r
-  \r
+  @param  Size          Size of Buf in bytes.\r
+\r
 **/\r
 VOID\r
 DisassembleInstruction (\r
   IN  UINT8     **OpCodePtr,\r
   IN  BOOLEAN   Thumb,\r
   IN  BOOLEAN   Extended,\r
+  IN OUT UINT32 *ItBlock,\r
   OUT CHAR8     *Buf,\r
   OUT UINTN     Size\r
   )\r
 {\r
   if (Thumb) {\r
-    DisassembleThumbInstruction ((UINT16 **)OpCodePtr, Buf, Size, Extended);\r
+    DisassembleThumbInstruction ((UINT16 **)OpCodePtr, Buf, Size, ItBlock, Extended);\r
   } else {\r
     DisassembleArmInstruction ((UINT32 **)OpCodePtr, Buf, Size, Extended);\r
   }\r
 }\r
\r
+\r