2 Thumb Dissassembler. Still a work in progress.
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.
11 Copyright (c) 2008-2010, Apple Inc. All rights reserved.
13 All rights reserved. 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
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.
24 #include <Library/BaseLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/PrintLib.h>
28 extern CHAR8
*gCondition
[];
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
41 #define POP_FORMAT 106
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
57 #define ENDIAN_FORMAT 21
61 // Thumb2 address modes
67 #define STM_FORMAT 205
68 #define LDM_REG_IMM12_SIGNED 206
69 #define LDM_REG_IMM12_LSL 207
70 #define LDM_REG_IMM8 208
71 #define LDM_REG_IMM12 209
72 #define LDM_REG_INDIRECT_LSL 210
73 #define LDM_REG_IMM8_SIGNED 211
74 #define LDRD_REG_IMM8 212
77 #define SRS_FORMAT 215
78 #define RFE_FORMAT 216
79 #define LDRD_REG_IMM8_SIGNED 217
82 #define ADR_THUMB2 220
83 #define CMN_THUMB2 221
86 #define BFC_THUMB2 224
87 #define CDP_THUMB2 225
88 #define THUMB2_NO_ARGS 226
89 #define THUMB2_2REGS 227
90 #define ADD_IMM5_2REG 228
91 #define CPD_THUMB2 229
92 #define THUMB2_4REGS 230
100 } THUMB_INSTRUCTIONS
;
102 THUMB_INSTRUCTIONS gOpThumb
[] = {
103 // Thumb 16-bit instrucitons
105 { "ADC" , 0x4140, 0xffc0, DATA_FORMAT5
},
106 { "ADR", 0xa000, 0xf800, ADR_FORMAT
}, // ADR <Rd>, <label>
107 { "ADD" , 0x1c00, 0xfe00, DATA_FORMAT2
},
108 { "ADD" , 0x3000, 0xf800, DATA_FORMAT3
},
109 { "ADD" , 0x1800, 0xfe00, DATA_FORMAT1
},
110 { "ADD" , 0x4400, 0xff00, DATA_FORMAT8
}, // A8.6.9
111 { "ADD" , 0xa000, 0xf100, DATA_FORMAT6_PC
},
112 { "ADD" , 0xa800, 0xf800, DATA_FORMAT6_SP
},
113 { "ADD" , 0xb000, 0xff80, DATA_FORMAT7
},
115 { "AND" , 0x4000, 0xffc0, DATA_FORMAT5
},
117 { "ASR" , 0x1000, 0xf800, DATA_FORMAT4
},
118 { "ASR" , 0x4100, 0xffc0, DATA_FORMAT5
},
120 { "B" , 0xd000, 0xf000, CONDITIONAL_BRANCH
},
121 { "B" , 0xe000, 0xf800, UNCONDITIONAL_BRANCH_SHORT
},
122 { "BLX" , 0x4780, 0xff80, BRANCH_EXCHANGE
},
123 { "BX" , 0x4700, 0xff87, BRANCH_EXCHANGE
},
125 { "BIC" , 0x4380, 0xffc0, DATA_FORMAT5
},
126 { "BKPT", 0xdf00, 0xff00, IMMED_8
},
127 { "CBZ", 0xb100, 0xfd00, DATA_CBZ
},
128 { "CBNZ", 0xb900, 0xfd00, DATA_CBZ
},
129 { "CMN" , 0x42c0, 0xffc0, DATA_FORMAT5
},
131 { "CMP" , 0x2800, 0xf800, DATA_FORMAT3
},
132 { "CMP" , 0x4280, 0xffc0, DATA_FORMAT5
},
133 { "CMP" , 0x4500, 0xff00, DATA_FORMAT8
},
135 { "CPS" , 0xb660, 0xffe8, CPS_FORMAT
},
136 { "MOV" , 0x4600, 0xff00, DATA_FORMAT8
},
137 { "EOR" , 0x4040, 0xffc0, DATA_FORMAT5
},
139 { "LDMIA" , 0xc800, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1
},
140 { "LDR" , 0x6800, 0xf800, LOAD_STORE_FORMAT1
},
141 { "LDR" , 0x5800, 0xfe00, LOAD_STORE_FORMAT2
},
142 { "LDR" , 0x4800, 0xf800, LOAD_STORE_FORMAT3
},
143 { "LDR" , 0x9800, 0xf800, LOAD_STORE_FORMAT4
},
144 { "LDRB" , 0x7800, 0xf800, LOAD_STORE_FORMAT1_B
},
145 { "LDRB" , 0x5c00, 0xfe00, LOAD_STORE_FORMAT2
},
146 { "LDRH" , 0x8800, 0xf800, LOAD_STORE_FORMAT1_H
},
147 { "LDRH" , 0x7a00, 0xfe00, LOAD_STORE_FORMAT2
},
148 { "LDRSB" , 0x5600, 0xfe00, LOAD_STORE_FORMAT2
},
149 { "LDRSH" , 0x5e00, 0xfe00, LOAD_STORE_FORMAT2
},
151 { "MOVS", 0x0000, 0xffc0, DATA_FORMAT5
}, // LSL with imm5 == 0 is a MOVS, so this must go before LSL
152 { "LSL" , 0x0000, 0xf800, DATA_FORMAT4
},
153 { "LSL" , 0x4080, 0xffc0, DATA_FORMAT5
},
154 { "LSR" , 0x0001, 0xf800, DATA_FORMAT4
},
155 { "LSR" , 0x40c0, 0xffc0, DATA_FORMAT5
},
156 { "LSRS", 0x0800, 0xf800, DATA_FORMAT4
}, // LSRS <Rd>, <Rm>, #<imm5>
158 { "MOVS", 0x2000, 0xf800, DATA_FORMAT3
},
159 { "MOV" , 0x1c00, 0xffc0, DATA_FORMAT3
},
160 { "MOV" , 0x4600, 0xff00, DATA_FORMAT8
},
162 { "MUL" , 0x4340, 0xffc0, DATA_FORMAT5
},
163 { "MVN" , 0x41c0, 0xffc0, DATA_FORMAT5
},
164 { "NEG" , 0x4240, 0xffc0, DATA_FORMAT5
},
165 { "ORR" , 0x4180, 0xffc0, DATA_FORMAT5
},
166 { "POP" , 0xbc00, 0xfe00, POP_FORMAT
},
167 { "PUSH", 0xb400, 0xfe00, PUSH_FORMAT
},
169 { "REV" , 0xba00, 0xffc0, DATA_FORMAT5
},
170 { "REV16" , 0xba40, 0xffc0, DATA_FORMAT5
},
171 { "REVSH" , 0xbac0, 0xffc0, DATA_FORMAT5
},
173 { "ROR" , 0x41c0, 0xffc0, DATA_FORMAT5
},
174 { "SBC" , 0x4180, 0xffc0, DATA_FORMAT5
},
175 { "SETEND" , 0xb650, 0xfff0, ENDIAN_FORMAT
},
177 { "STMIA" , 0xc000, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1
},
178 { "STR" , 0x6000, 0xf800, LOAD_STORE_FORMAT1
},
179 { "STR" , 0x5000, 0xfe00, LOAD_STORE_FORMAT2
},
180 { "STR" , 0x4000, 0xf800, LOAD_STORE_FORMAT3
},
181 { "STR" , 0x9000, 0xf800, LOAD_STORE_FORMAT4
},
182 { "STRB" , 0x7000, 0xf800, LOAD_STORE_FORMAT1_B
},
183 { "STRB" , 0x5800, 0xfe00, LOAD_STORE_FORMAT2
},
184 { "STRH" , 0x8000, 0xf800, LOAD_STORE_FORMAT1_H
},
185 { "STRH" , 0x5200, 0xfe00, LOAD_STORE_FORMAT2
},
187 { "SUB" , 0x1e00, 0xfe00, DATA_FORMAT2
},
188 { "SUB" , 0x3800, 0xf800, DATA_FORMAT3
},
189 { "SUB" , 0x1a00, 0xfe00, DATA_FORMAT1
},
190 { "SUB" , 0xb080, 0xff80, DATA_FORMAT7
},
192 { "SWI" , 0xdf00, 0xff00, IMMED_8
},
193 { "SXTB", 0xb240, 0xffc0, DATA_FORMAT5
},
194 { "SXTH", 0xb200, 0xffc0, DATA_FORMAT5
},
195 { "TST" , 0x4200, 0xffc0, DATA_FORMAT5
},
196 { "UXTB", 0xb2c0, 0xffc0, DATA_FORMAT5
},
197 { "UXTH", 0xb280, 0xffc0, DATA_FORMAT5
}
201 THUMB_INSTRUCTIONS gOpThumb2
[] = {
202 //Instruct OpCode OpCode Mask Addressig Mode
204 { "ADR", 0xf2af0000, 0xfbff8000, ADR_THUMB2
}, // ADDR <Rd>, <label> ;Needs to go before ADDW
205 { "CMN", 0xf1100f00, 0xfff08f00, CMN_THUMB2
}, // CMN <Rn>, #<const> ;Needs to go before ADD
206 { "CMN", 0xeb100f00, 0xfff08f00, ADD_IMM5_2REG
}, // CMN <Rn>, <Rm> {,<shift> #<const>}
207 { "CMP", 0xf1a00f00, 0xfff08f00, CMN_THUMB2
}, // CMP <Rn>, #<const>
208 { "TEQ", 0xf0900f00, 0xfff08f00, CMN_THUMB2
}, // CMP <Rn>, #<const>
209 { "TEQ", 0xea900f00, 0xfff08f00, ADD_IMM5_2REG
}, // CMN <Rn>, <Rm> {,<shift> #<const>}
210 { "TST", 0xf0100f00, 0xfff08f00, CMN_THUMB2
}, // CMP <Rn>, #<const>
211 { "TST", 0xea100f00, 0xfff08f00, ADD_IMM5_2REG
}, // TST <Rn>, <Rm> {,<shift> #<const>}
213 { "ADC", 0xf1400000, 0xfbe08000, ADD_IMM12
}, // ADC{S} <Rd>, <Rn>, #<const>
214 { "ADC", 0xeb400000, 0xffe08000, ADD_IMM5
}, // ADC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
215 { "ADD", 0xf1000000, 0xfbe08000, ADD_IMM12
}, // ADD{S} <Rd>, <Rn>, #<const>
216 { "ADD", 0xeb000000, 0xffe08000, ADD_IMM5
}, // ADD{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
217 { "ADDW", 0xf2000000, 0xfbe08000, ADD_IMM12
}, // ADDW{S} <Rd>, <Rn>, #<const>
218 { "AND", 0xf0000000, 0xfbe08000, ADD_IMM12
}, // AND{S} <Rd>, <Rn>, #<const>
219 { "AND", 0xea000000, 0xffe08000, ADD_IMM5
}, // AND{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
220 { "BIC", 0xf0200000, 0xfbe08000, ADD_IMM12
}, // BIC{S} <Rd>, <Rn>, #<const>
221 { "BIC", 0xea200000, 0xffe08000, ADD_IMM5
}, // BIC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
222 { "EOR", 0xf0800000, 0xfbe08000, ADD_IMM12
}, // EOR{S} <Rd>, <Rn>, #<const>
223 { "EOR", 0xea800000, 0xffe08000, ADD_IMM5
}, // EOR{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
224 { "ORN", 0xf0600000, 0xfbe08000, ADD_IMM12
}, // ORN{S} <Rd>, <Rn>, #<const>
225 { "ORN", 0xea600000, 0xffe08000, ADD_IMM5
}, // ORN{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
226 { "ORR", 0xf0400000, 0xfbe08000, ADD_IMM12
}, // ORR{S} <Rd>, <Rn>, #<const>
227 { "ORR", 0xea400000, 0xffe08000, ADD_IMM5
}, // ORR{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
228 { "RSB", 0xf1c00000, 0xfbe08000, ADD_IMM12
}, // RSB{S} <Rd>, <Rn>, #<const>
229 { "RSB", 0xebc00000, 0xffe08000, ADD_IMM5
}, // RSB{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
230 { "SBC", 0xf1600000, 0xfbe08000, ADD_IMM12
}, // SBC{S} <Rd>, <Rn>, #<const>
231 { "SBC", 0xeb600000, 0xffe08000, ADD_IMM5
}, // SBC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
232 { "SUB", 0xf1a00000, 0xfbe08000, ADD_IMM12
}, // SUB{S} <Rd>, <Rn>, #<const>
233 { "SUB", 0xeba00000, 0xffe08000, ADD_IMM5
}, // SUB{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
235 { "ASR", 0xea4f0020, 0xffef8030, ASR_IMM5
}, // ARS <Rd>, <Rm> #<const>} imm3:imm2
236 { "ASR", 0xfa40f000, 0xffe0f0f0, ASR_3REG
}, // ARS <Rd>, <Rn>, <Rm>
237 { "LSR", 0xea4f0010, 0xffef8030, ASR_IMM5
}, // LSR <Rd>, <Rm> #<const>} imm3:imm2
238 { "LSR", 0xfa20f000, 0xffe0f0f0, ASR_3REG
}, // LSR <Rd>, <Rn>, <Rm>
239 { "ROR", 0xea4f0030, 0xffef8030, ASR_IMM5
}, // ROR <Rd>, <Rm> #<const>} imm3:imm2
240 { "ROR", 0xfa60f000, 0xffe0f0f0, ASR_3REG
}, // ROR <Rd>, <Rn>, <Rm>
242 { "BFC", 0xf36f0000, 0xffff8010, BFC_THUMB2
}, // BFC <Rd>, #<lsb>, #<width>
243 { "BIC", 0xf3600000, 0xfff08010, BFC_THUMB2
}, // BIC <Rn>, <Rd>, #<lsb>, #<width>
244 { "SBFX", 0xf3400000, 0xfff08010, BFC_THUMB2
}, // SBFX <Rn>, <Rd>, #<lsb>, #<width>
245 { "UBFX", 0xf3c00000, 0xfff08010, BFC_THUMB2
}, // UBFX <Rn>, <Rd>, #<lsb>, #<width>
247 { "CPD", 0xee000000, 0xff000010, CPD_THUMB2
}, // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>
248 { "CPD2", 0xfe000000, 0xff000010, CPD_THUMB2
}, // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>
250 { "CLREX", 0xf3bf8f2f, 0xfffffff, THUMB2_NO_ARGS
}, // CLREX
252 { "CLZ", 0xfab0f080, 0xfff0f0f0, THUMB2_2REGS
}, // CLZ <Rd>,<Rm>
253 { "MOV", 0xec4f0000, 0xfff0f0f0, THUMB2_2REGS
}, // MOV <Rd>,<Rm>
254 { "MOVS", 0xec5f0000, 0xfff0f0f0, THUMB2_2REGS
}, // MOVS <Rd>,<Rm>
255 { "RBIT", 0xfb90f0a0, 0xfff0f0f0, THUMB2_2REGS
}, // RBIT <Rd>,<Rm>
256 { "REV", 0xfb90f080, 0xfff0f0f0, THUMB2_2REGS
}, // REV <Rd>,<Rm>
257 { "REV16", 0xfa90f090, 0xfff0f0f0, THUMB2_2REGS
}, // REV16 <Rd>,<Rm>
258 { "REVSH", 0xfa90f0b0, 0xfff0f0f0, THUMB2_2REGS
}, // REVSH <Rd>,<Rm>
259 { "RRX", 0xea4f0030, 0xfffff0f0, THUMB2_2REGS
}, // RRX <Rd>,<Rm>
260 { "RRXS", 0xea5f0030, 0xfffff0f0, THUMB2_2REGS
}, // RRXS <Rd>,<Rm>
262 { "MLA", 0xfb000000, 0xfff000f0, THUMB2_4REGS
}, // MLA <Rd>, <Rn>, <Rm>, <Ra>
263 { "MLS", 0xfb000010, 0xfff000f0, THUMB2_4REGS
}, // MLA <Rd>, <Rn>, <Rm>, <Ra>
266 { "SMLABB", 0xfb100000, 0xfff000f0, THUMB2_4REGS
}, // SMLABB <Rd>, <Rn>, <Rm>, <Ra>
267 { "SMLABT", 0xfb100010, 0xfff000f0, THUMB2_4REGS
}, // SMLABT <Rd>, <Rn>, <Rm>, <Ra>
268 { "SMLABB", 0xfb100020, 0xfff000f0, THUMB2_4REGS
}, // SMLATB <Rd>, <Rn>, <Rm>, <Ra>
269 { "SMLATT", 0xfb100030, 0xfff000f0, THUMB2_4REGS
}, // SMLATT <Rd>, <Rn>, <Rm>, <Ra>
270 { "SMLAWB", 0xfb300000, 0xfff000f0, THUMB2_4REGS
},// SMLAWB <Rd>, <Rn>, <Rm>, <Ra>
271 { "SMLAWT", 0xfb300010, 0xfff000f0, THUMB2_4REGS
},// SMLAWT <Rd>, <Rn>, <Rm>, <Ra>
272 { "SMLSD", 0xfb400000, 0xfff000f0, THUMB2_4REGS
},// SMLSD <Rd>, <Rn>, <Rm>, <Ra>
273 { "SMLSDX", 0xfb400010, 0xfff000f0, THUMB2_4REGS
},// SMLSDX <Rd>, <Rn>, <Rm>, <Ra>
274 { "SMMLA", 0xfb500000, 0xfff000f0, THUMB2_4REGS
},// SMMLA <Rd>, <Rn>, <Rm>, <Ra>
275 { "SMMLAR", 0xfb500010, 0xfff000f0, THUMB2_4REGS
},// SMMLAR <Rd>, <Rn>, <Rm>, <Ra>
276 { "SMMLS", 0xfb600000, 0xfff000f0, THUMB2_4REGS
},// SMMLS <Rd>, <Rn>, <Rm>, <Ra>
277 { "SMMLSR", 0xfb600010, 0xfff000f0, THUMB2_4REGS
},// SMMLSR <Rd>, <Rn>, <Rm>, <Ra>
278 { "USADA8", 0xfb700000, 0xfff000f0, THUMB2_4REGS
},// USADA8 <Rd>, <Rn>, <Rm>, <Ra>
279 { "SMLAD", 0xfb200000, 0xfff000f0, THUMB2_4REGS
},// SMLAD <Rd>, <Rn>, <Rm>, <Ra>
280 { "SMLADX", 0xfb200010, 0xfff000f0, THUMB2_4REGS
},// SMLADX <Rd>, <Rn>, <Rm>, <Ra>
283 { "B", 0xf0008000, 0xf800d000, B_T3
}, // B<c> <label>
284 { "B", 0xf0009000, 0xf800d000, B_T4
}, // B<c> <label>
285 { "BL", 0xf000d000, 0xf800d000, B_T4
}, // BL<c> <label>
286 { "BLX", 0xf000c000, 0xf800d000, BL_T2
}, // BLX<c> <label>
288 { "POP", 0xe8bd0000, 0xffff2000, POP_T2
}, // POP <registers>
289 { "POP", 0xf85d0b04, 0xffff0fff, POP_T3
}, // POP <register>
290 { "PUSH", 0xe8ad0000, 0xffffa000, POP_T2
}, // PUSH <registers>
291 { "PUSH", 0xf84d0d04, 0xffff0fff, POP_T3
}, // PUSH <register>
292 { "STM" , 0xe8800000, 0xffd0a000, STM_FORMAT
}, // STM <Rn>{!},<registers>
293 { "STMDB", 0xe9800000, 0xffd0a000, STM_FORMAT
}, // STMDB <Rn>{!},<registers>
294 { "LDM" , 0xe8900000, 0xffd02000, STM_FORMAT
}, // LDM <Rn>{!},<registers>
295 { "LDMDB", 0xe9100000, 0xffd02000, STM_FORMAT
}, // LDMDB <Rn>{!},<registers>
297 { "LDR", 0xf8d00000, 0xfff00000, LDM_REG_IMM12
}, // LDR <rt>, [<rn>, {, #<imm12>]}
298 { "LDRB", 0xf8900000, 0xfff00000, LDM_REG_IMM12
}, // LDRB <rt>, [<rn>, {, #<imm12>]}
299 { "LDRH", 0xf8b00000, 0xfff00000, LDM_REG_IMM12
}, // LDRH <rt>, [<rn>, {, #<imm12>]}
300 { "LDRSB", 0xf9900000, 0xfff00000, LDM_REG_IMM12
}, // LDRSB <rt>, [<rn>, {, #<imm12>]}
301 { "LDRSH", 0xf9b00000, 0xfff00000, LDM_REG_IMM12
}, // LDRSH <rt>, [<rn>, {, #<imm12>]}
303 { "LDR", 0xf85f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDR <Rt>, <label>
304 { "LDRB", 0xf81f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDRB <Rt>, <label>
305 { "LDRH", 0xf83f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDRH <Rt>, <label>
306 { "LDRSB", 0xf91f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDRSB <Rt>, <label>
307 { "LDRSH", 0xf93f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDRSB <Rt>, <label>
309 { "LDR", 0xf8500000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDR <rt>, [<rn>, <rm> {, LSL #<imm2>]}
310 { "LDRB", 0xf8100000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDRB <rt>, [<rn>, <rm> {, LSL #<imm2>]}
311 { "LDRH", 0xf8300000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDRH <rt>, [<rn>, <rm> {, LSL #<imm2>]}
312 { "LDRSB", 0xf9100000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDRSB <rt>, [<rn>, <rm> {, LSL #<imm2>]}
313 { "LDRSH", 0xf9300000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDRSH <rt>, [<rn>, <rm> {, LSL #<imm2>]}
315 { "LDR", 0xf8500800, 0xfff00800, LDM_REG_IMM8
}, // LDR <rt>, [<rn>, {, #<imm8>]}
316 { "LDRBT", 0xf8100e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRBT <rt>, [<rn>, {, #<imm8>]}
317 { "LDRHT", 0xf8300e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRHT <rt>, [<rn>, {, #<imm8>]}
318 { "LDRSB", 0xf9900800, 0xfff00800, LDM_REG_IMM8
}, // LDRHT <rt>, [<rn>, {, #<imm8>]} {!} form?
319 { "LDRSBT",0xf9100e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRHBT <rt>, [<rn>, {, #<imm8>]} {!} form?
320 { "LDRSH" ,0xf9300800, 0xfff00800, LDM_REG_IMM8
}, // LDRSH <rt>, [<rn>, {, #<imm8>]}
321 { "LDRSHT",0xf9300e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRSHT <rt>, [<rn>, {, #<imm8>]}
322 { "LDRT", 0xf8500e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRT <rt>, [<rn>, {, #<imm8>]}
324 { "LDRD", 0xe8500000, 0xfe500000, LDRD_REG_IMM8_SIGNED
}, // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}
325 { "LDRD", 0xe8500000, 0xfe500000, LDRD_REG_IMM8
}, // LDRD <rt>, <rt2>, <label>
327 { "LDREX", 0xe8500f00, 0xfff00f00, LDM_REG_IMM8
}, // LDREX <Rt>, [Rn, {#imm8}]]
328 { "LDREXB", 0xe8d00f4f, 0xfff00fff, LDREXB
}, // LDREXB <Rt>, [<Rn>]
329 { "LDREXH", 0xe8d00f5f, 0xfff00fff, LDREXB
}, // LDREXH <Rt>, [<Rn>]
331 { "LDREXD", 0xe8d00f4f, 0xfff00fff, LDREXD
}, // LDREXD <Rt>, <Rt2>, [<Rn>]
333 { "STR", 0xf8c00000, 0xfff00000, LDM_REG_IMM12
}, // STR <rt>, [<rn>, {, #<imm12>]}
334 { "STRB", 0xf8800000, 0xfff00000, LDM_REG_IMM12
}, // STRB <rt>, [<rn>, {, #<imm12>]}
335 { "STRH", 0xf8a00000, 0xfff00000, LDM_REG_IMM12
}, // STRH <rt>, [<rn>, {, #<imm12>]}
337 { "STR", 0xf8400000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // STR <rt>, [<rn>, <rm> {, LSL #<imm2>]}
338 { "STRB", 0xf8000000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // STRB <rt>, [<rn>, <rm> {, LSL #<imm2>]}
339 { "STRH", 0xf8200000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // STRH <rt>, [<rn>, <rm> {, LSL #<imm2>]}
341 { "STR", 0xf8400800, 0xfff00800, LDM_REG_IMM8
}, // STR <rt>, [<rn>, {, #<imm8>]}
342 { "STRH", 0xf8200800, 0xfff00800, LDM_REG_IMM8
}, // STRH <rt>, [<rn>, {, #<imm8>]}
343 { "STRBT", 0xf8000e00, 0xfff00f00, LDM_REG_IMM8
}, // STRBT <rt>, [<rn>, {, #<imm8>]}
344 { "STRHT", 0xf8200e00, 0xfff00f00, LDM_REG_IMM8
}, // STRHT <rt>, [<rn>, {, #<imm8>]}
345 { "STRT", 0xf8400e00, 0xfff00f00, LDM_REG_IMM8
}, // STRT <rt>, [<rn>, {, #<imm8>]}
347 { "STRD", 0xe8400000, 0xfe500000, LDRD_REG_IMM8_SIGNED
}, // STRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}
349 { "STREX", 0xe8400f00, 0xfff00f00, LDM_REG_IMM8
}, // STREX <Rt>, [Rn, {#imm8}]]
350 { "STREXB", 0xe8c00f4f, 0xfff00fff, LDREXB
}, // STREXB <Rd>, <Rt>, [<Rn>]
351 { "STREXH", 0xe8c00f5f, 0xfff00fff, LDREXB
}, // STREXH <Rd>, <Rt>, [<Rn>]
353 { "STREXD", 0xe8d00f4f, 0xfff00fff, LDREXD
}, // STREXD <Rd>, <Rt>, <Rt2>, [<Rn>]
355 { "SRSDB", 0xe80dc000, 0xffdffff0, SRS_FORMAT
}, // SRSDB<c> SP{!},#<mode>
356 { "SRS" , 0xe98dc000, 0xffdffff0, SRS_FORMAT
}, // SRS{IA}<c> SP{!},#<mode>
357 { "RFEDB", 0xe810c000, 0xffd0ffff, RFE_FORMAT
}, // RFEDB<c> <Rn>{!}
358 { "RFE" , 0xe990c000, 0xffd0ffff, RFE_FORMAT
} // RFE{IA}<c> <Rn>{!}
361 CHAR8
*gShiftType
[] = {
368 CHAR8 mThumbMregListStr
[4*15 + 1];
375 UINTN Index
, Start
, End
;
379 Str
= mThumbMregListStr
;
381 AsciiStrCat (Str
, "{");
383 for (Index
= 0, First
= TRUE
; Index
<= 15; Index
++) {
384 if ((RegBitMask
& (1 << Index
)) != 0) {
386 for (Index
++; ((RegBitMask
& (1 << Index
)) != 0) && (Index
<= 9); Index
++) {
391 AsciiStrCat (Str
, ",");
397 AsciiStrCat (Str
, gReg
[Start
]);
399 AsciiStrCat (Str
, gReg
[Start
]);
400 AsciiStrCat (Str
, "-");
401 AsciiStrCat (Str
, gReg
[End
]);
406 AsciiStrCat (Str
, "ERROR");
408 AsciiStrCat (Str
, "}");
410 // BugBug: Make caller pass in buffer it is cleaner
411 return mThumbMregListStr
;
420 if (((Data
& TopBit
) == 0) || (TopBit
== BIT31
)) {
427 } while ((TopBit
& BIT31
) != BIT31
);
433 // Some instructions specify the PC is always considered aligned
434 // The PC is after the instruction that is excuting. So you pass
435 // in the instruction address and you get back the aligned answer
442 return (Data
+ 4) & 0xfffffffc;
446 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
447 point to next instructin.
449 We cheat and only decode instructions that access
450 memory. If the instruction is not found we dump the instruction in hex.
452 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.
453 @param Buf Buffer to sprintf disassembly into.
454 @param Size Size of Buf in bytes.
455 @param Extended TRUE dump hex for instruction too.
459 DisassembleThumbInstruction (
460 IN UINT16
**OpCodePtrPtr
,
471 UINT16 Rd
, Rn
, Rm
, Rt
, Rt2
;
472 BOOLEAN H1
, H2
, imod
;
473 UINT32 PC
, Target
, msbit
, lsbit
;
475 BOOLEAN S
, J1
, J2
, P
, U
, W
;
476 UINT32 coproc
, opc1
, opc2
, CRd
, CRn
, CRm
;
478 OpCodePtr
= *OpCodePtrPtr
;
479 OpCode
= **OpCodePtrPtr
;
481 // Thumb2 is a stream of 16-bit instructions not a 32-bit instruction.
482 OpCode32
= (((UINT32
)OpCode
) << 16) | *(OpCodePtr
+ 1);
484 // These register names match branch form, but not others
486 Rn
= (OpCode
>> 3) & 0x7;
487 Rm
= (OpCode
>> 6) & 0x7;
488 H1
= (OpCode
& BIT7
) != 0;
489 H2
= (OpCode
& BIT6
) != 0;
490 imod
= (OpCode
& BIT4
) != 0;
491 PC
= (UINT32
)(UINTN
)OpCodePtr
;
493 // Increment by the minimum instruction size, Thumb2 could be bigger
496 for (Index
= 0; Index
< sizeof (gOpThumb
)/sizeof (THUMB_INSTRUCTIONS
); Index
++) {
497 if ((OpCode
& gOpThumb
[Index
].Mask
) == gOpThumb
[Index
].OpCode
) {
499 Offset
= AsciiSPrint (Buf
, Size
, "0x%04x %-6a", OpCode
, gOpThumb
[Index
].Start
);
501 Offset
= AsciiSPrint (Buf
, Size
, "%-6a", gOpThumb
[Index
].Start
);
503 switch (gOpThumb
[Index
].AddressMode
) {
504 case LOAD_STORE_FORMAT1
:
505 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]
506 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [r%d #0x%x]", Rd
, Rn
, (OpCode
>> 4) & 0x7c);
508 case LOAD_STORE_FORMAT1_H
:
509 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]
510 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [r%d #0x%x]", Rd
, Rn
, (OpCode
>> 5) & 0x3e);
512 case LOAD_STORE_FORMAT1_B
:
513 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]
514 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [r%d #0x%x]", Rd
, Rn
, (OpCode
>> 6) & 0x1f);
517 case LOAD_STORE_FORMAT2
:
518 // A6.5.1 <Rd>, [<Rn>, <Rm>]
519 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [r%d, r%d]", Rd
, Rn
, Rm
);
521 case LOAD_STORE_FORMAT3
:
522 // A6.5.1 <Rd>, [PC, #<8_bit_offset>]
523 Target
= (OpCode
& 0xff) << 2;
524 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [pc, #0x%x] ;0x%08x", (OpCode
>> 8) & 7, Target
, PCAlign4 (PC
) + Target
);
526 case LOAD_STORE_FORMAT4
:
528 Target
= (OpCode
& 0xff) << 2;
529 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [sp, #0x%x]", (OpCode
>> 8) & 7, Target
);
532 case LOAD_STORE_MULTIPLE_FORMAT1
:
534 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d!, %a", (OpCode
>> 8) & 7, ThumbMRegList (OpCode
& 0xff));
539 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", ThumbMRegList ((OpCode
& 0xff) | ((OpCode
& BIT8
) == BIT8
? BIT15
: 0)));
544 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", ThumbMRegList ((OpCode
& 0xff) | ((OpCode
& BIT8
) == BIT8
? BIT14
: 0)));
550 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%x", OpCode
& 0xff);
553 case CONDITIONAL_BRANCH
:
554 // A6.3.1 B<cond> <target_address>
555 // Patch in the condition code. A little hack but based on "%-6a"
556 Cond
= gCondition
[(OpCode
>> 8) & 0xf];
557 Buf
[Offset
-5] = *Cond
++;
558 Buf
[Offset
-4] = *Cond
;
559 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%04x", PC
+ 4 + SignExtend32 ((OpCode
& 0xff) << 1, BIT8
));
561 case UNCONDITIONAL_BRANCH_SHORT
:
562 // A6.3.2 B <target_address>
563 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%04x", PC
+ 4 + SignExtend32 ((OpCode
& 0x3ff) << 1, BIT11
));
566 case BRANCH_EXCHANGE
:
567 // A6.3.3 BX|BLX <Rm>
568 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", gReg
[Rn
| (H2
? 8:0)]);
572 // A6.4.3 <Rd>, <Rn>, <Rm>
573 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, r%d, r%d", Rd
, Rn
, Rm
);
576 // A6.4.3 <Rd>, <Rn>, #3_bit_immed
577 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, r%d, 0x%x", Rd
, Rn
, Rm
);
580 // A6.4.3 <Rd>|<Rn>, #imm8
581 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, #0x%x", (OpCode
>> 8) & 7, OpCode
& 0xff);
584 // A6.4.3 <Rd>|<Rm>, #immed_5
585 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, r%d, 0x%x", Rn
, Rd
, (OpCode
>> 6) & 0x1f);
588 // A6.4.3 <Rd>|<Rm>, <Rm>|<Rs>
589 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, r%d", Rd
, Rn
);
591 case DATA_FORMAT6_SP
:
592 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>
593 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, sp, 0x%x", (OpCode
>> 8) & 7, (OpCode
& 0xff) << 2);
595 case DATA_FORMAT6_PC
:
596 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>
597 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, pc, 0x%x", (OpCode
>> 8) & 7, (OpCode
& 0xff) << 2);
600 // A6.4.3 SP, SP, #<7_Bit_immed>
601 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " sp, sp, 0x%x", (OpCode
& 0x7f)*4);
604 // A6.4.3 <Rd>|<Rn>, <Rm>
605 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a", gReg
[Rd
| (H1
? 8:0)], gReg
[Rn
| (H2
? 8:0)]);
610 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "%a %a%a%a", imod
? "ID":"IE", ((OpCode
& BIT2
) == 0) ? "":"a", ((OpCode
& BIT1
) == 0) ? "":"i", ((OpCode
& BIT0
) == 0) ? "":"f");
615 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", (OpCode
& BIT3
) == 0 ? "LE":"BE");
619 // CB{N}Z <Rn>, <Lable>
620 Target
= ((OpCode
>> 2) & 0x3e) | (((OpCode
& BIT9
) == BIT9
) ? BIT6
: 0);
621 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %08x", gReg
[Rd
], PC
+ 4 + Target
);
626 Target
= (OpCode
& 0xff) << 2;
627 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %08x", gReg
[(OpCode
>> 8) & 7], PCAlign4 (PC
) + Target
);
634 // Thumb2 are 32-bit instructions
636 Rt
= (OpCode32
>> 12) & 0xf;
637 Rt2
= (OpCode32
>> 8) & 0xf;
638 Rd
= (OpCode32
>> 8) & 0xf;
639 Rm
= (OpCode32
& 0xf);
640 Rn
= (OpCode32
>> 16) & 0xf;
641 for (Index
= 0; Index
< sizeof (gOpThumb2
)/sizeof (THUMB_INSTRUCTIONS
); Index
++) {
642 if ((OpCode32
& gOpThumb2
[Index
].Mask
) == gOpThumb2
[Index
].OpCode
) {
644 Offset
= AsciiSPrint (Buf
, Size
, "0x%04x %-6a", OpCode32
, gOpThumb2
[Index
].Start
);
646 Offset
= AsciiSPrint (Buf
, Size
, " %-6a", gOpThumb2
[Index
].Start
);
648 switch (gOpThumb2
[Index
].AddressMode
) {
650 Cond
= gCondition
[(OpCode32
>> 22) & 0xf];
651 Buf
[Offset
-5] = *Cond
++;
652 Buf
[Offset
-4] = *Cond
;
653 // S:J2:J1:imm6:imm11:0
654 Target
= ((OpCode32
<< 1) & 0xffe) + ((OpCode32
>> 4) & 0x3f000);
655 Target
|= ((OpCode32
& BIT11
) == BIT11
)? BIT19
: 0; // J2
656 Target
|= ((OpCode32
& BIT13
) == BIT13
)? BIT18
: 0; // J1
657 Target
|= ((OpCode32
& BIT26
) == BIT26
)? BIT20
: 0; // S
658 Target
= SignExtend32 (Target
, BIT20
);
659 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%08x", PC
+ 4 + Target
);
662 // S:I1:I2:imm10:imm11:0
663 Target
= ((OpCode32
<< 1) & 0xffe) + ((OpCode32
>> 4) & 0x3ff000);
664 S
= (OpCode32
& BIT26
) == BIT26
;
665 J1
= (OpCode32
& BIT13
) == BIT13
;
666 J2
= (OpCode32
& BIT11
) == BIT11
;
667 Target
|= (!(J2
^ S
) ? BIT22
: 0); // I2
668 Target
|= (!(J1
^ S
) ? BIT23
: 0); // I1
669 Target
|= (S
? BIT24
: 0); // S
670 Target
= SignExtend32 (Target
, BIT24
);
671 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%08x", PC
+ 4 + Target
);
675 // BLX S:I1:I2:imm10:imm11:0
676 Target
= ((OpCode32
<< 1) & 0xffc) + ((OpCode32
>> 4) & 0x3ff000);
677 S
= (OpCode32
& BIT26
) == BIT26
;
678 J1
= (OpCode32
& BIT13
) == BIT13
;
679 J2
= (OpCode32
& BIT11
) == BIT11
;
680 Target
|= (!(J2
^ S
) ? BIT23
: 0); // I2
681 Target
|= (!(J1
^ S
) ? BIT24
: 0); // I1
682 Target
|= (S
? BIT25
: 0); // S
683 Target
= SignExtend32 (Target
, BIT25
);
684 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%08x", PCAlign4 (PC
) + Target
);
688 // <reglist> some must be zero, handled in table
689 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", ThumbMRegList (OpCode32
& 0xffff));
694 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", gReg
[(OpCode32
>> 12) & 0xf]);
698 // <Rn>{!}, <registers>
699 W
= (OpCode32
& BIT21
) == BIT21
;
700 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a%a, %a", gReg
[(OpCode32
>> 16) & 0xf], W
? "!":"", ThumbMRegList (OpCode32
& 0xffff));
703 case LDM_REG_IMM12_SIGNED
:
705 Target
= OpCode32
& 0xfff;
706 if ((OpCode32
& BIT23
) == 0) {
707 // U == 0 means subtrack, U == 1 means add
710 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a", gReg
[(OpCode32
>> 12) & 0xf], PCAlign4 (PC
) + Target
);
713 case LDM_REG_INDIRECT_LSL
:
714 // <rt>, [<rn>, <rm> {, LSL #<imm2>]}
715 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, [%a, %a", gReg
[Rt
], gReg
[Rn
], gReg
[Rm
]);
716 if (((OpCode32
>> 4) && 3) == 0) {
717 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "]");
719 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", LSL #%d]", (OpCode32
>> 4) && 3);
724 // <rt>, [<rn>, {, #<imm12>]}
725 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, [%a", gReg
[Rt
], gReg
[Rn
]);
726 if ((OpCode32
&& 0xfff) == 0) {
727 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "]");
729 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", #0x%x]", OpCode32
& 0xfff);
735 // <rt>, [<rn>, {, #<imm8>}]{!}
736 W
= (OpCode32
& BIT8
) == BIT8
;
737 U
= (OpCode32
& BIT9
) == BIT9
;
738 P
= (OpCode32
& BIT10
) == BIT10
;
739 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, [%a", gReg
[Rt
], gReg
[Rn
]);
741 if ((OpCode32
&& 0xff) == 0) {
742 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "]%a", W
?"!":"");
744 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", #%a0x%x]%a", OpCode32
& 0xff, U
?"":"-" , W
?"!":"");
747 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "], #%a0x%x]", OpCode32
& 0xff, U
?"":"-");
751 case LDRD_REG_IMM8_SIGNED
:
752 // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}
753 P
= (OpCode32
& BIT24
) == BIT24
; // index = P
754 U
= (OpCode32
& BIT23
) == BIT23
;
755 W
= (OpCode32
& BIT21
) == BIT21
;
756 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, [%a", gReg
[Rt
], gReg
[Rt2
], gReg
[Rn
]);
758 if ((OpCode32
&& 0xff) == 0) {
759 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "]");
761 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", #%a0x%x]%a", U
?"":"-", (OpCode32
& 0xff) << 2, W
?"!":"");
764 if ((OpCode32
&& 0xff) != 0) {
765 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", #%a0x%x", U
?"":"-", (OpCode32
& 0xff) << 2);
771 // LDRD <rt>, <rt2>, <label>
772 Target
= (OpCode32
& 0xff) << 2;
773 if ((OpCode32
& BIT23
) == 0) {
774 // U == 0 means subtrack, U == 1 means add
777 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, %a", gReg
[Rt
], gReg
[Rt2
], PC
+ 4 + Target
);
782 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, [%a]", gReg
[Rt
], gReg
[Rn
]);
786 // LDREXD <Rt>, <Rt2>, [<Rn>]
787 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, ,%a, [%a]", gReg
[Rt
], gReg
[Rt2
], gReg
[Rn
]);
792 W
= (OpCode32
& BIT21
) == BIT21
;
793 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " SP%a, #0x%x", W
?"!":"", OpCode32
& 0x1f);
798 W
= (OpCode32
& BIT21
) == BIT21
;
799 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a%a, #0x%x", gReg
[Rn
], W
?"!":"");
803 // ADD{S} <Rd>, <Rn>, #<const> i:imm3:imm8
804 if ((OpCode32
& BIT20
) == BIT20
) {
805 Buf
[Offset
- 3] = 'S'; // assume %-6a
807 Target
= (OpCode32
& 0xff) | ((OpCode32
>> 4) & 0x700) | ((OpCode
& BIT26
) == BIT26
? BIT11
: 0);
808 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, #0x%x", gReg
[Rd
], gReg
[Rn
], Target
);
812 // ADC{S} <Rd>, <Rn>, <Rm> {,LSL #<const>} imm3:imm2
813 if ((OpCode32
& BIT20
) == BIT20
) {
814 Buf
[Offset
- 3] = 'S'; // assume %-6a
816 Target
= ((OpCode32
>> 6) & 3) | ((OpCode32
>> 10) & 0x1c0);
817 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, %a", gReg
[Rd
], gReg
[Rn
], gReg
[Rm
]);
819 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", LSL %d", gShiftType
[(OpCode
>> 5) & 3], Target
);
824 // CMP <Rn>, <Rm> {,LSL #<const>} imm3:imm2
825 Target
= ((OpCode32
>> 6) & 3) | ((OpCode32
>> 10) & 0x1c0);
826 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a", gReg
[Rn
], gReg
[Rm
]);
828 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", LSL %d", gShiftType
[(OpCode
>> 5) & 3], Target
);
833 // ARS <Rd>, <Rm> #<const>} imm3:imm2
834 if ((OpCode32
& BIT20
) == BIT20
) {
835 Buf
[Offset
- 3] = 'S'; // assume %-6a
837 Target
= ((OpCode32
>> 6) & 3) | ((OpCode32
>> 10) & 0x1c0);
838 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a #%d", gReg
[Rd
], gReg
[Rm
], Target
);
842 // ARS <Rd>, <Rn>, <Rm>
843 if ((OpCode32
& BIT20
) == BIT20
) {
844 Buf
[Offset
- 3] = 'S'; // assume %-6a
846 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a %a", gReg
[Rd
], gReg
[Rn
], gReg
[Rm
]);
850 // ADDR <Rd>, <label>
851 Target
= (OpCode32
& 0xff) | ((OpCode32
>> 8) & 0x700) | ((OpCode
& BIT26
) == BIT26
? BIT11
: 0);
852 if ((OpCode
& (BIT23
| BIT21
)) == (BIT23
| BIT21
)) {
853 Target
= PCAlign4 (PC
) - Target
;
855 Target
= PCAlign4 (PC
) + Target
;
857 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, 0x%08x", gReg
[Rd
], Target
);
861 // CMN <Rn>, #<const>}
862 Target
= (OpCode32
& 0xff) | ((OpCode
>> 4) && 0x700) | ((OpCode
& BIT26
) == BIT26
? BIT11
: 0);
863 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, #0x%x", gReg
[Rn
], Target
);
867 // BFI <Rd>, <Rn>, #<lsb>, #<width>
868 msbit
= OpCode32
& 0x1f;
869 lsbit
= ((OpCode32
>> 6) & 3) | ((OpCode
>> 10) & 0x1c);
870 if ((Rn
== 0xf) & (AsciiStrCmp (gOpThumb2
[Index
].Start
, "BFC") == 0)){
871 // BFC <Rd>, #<lsb>, #<width>
872 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, #%d, #%d", gReg
[Rd
], lsbit
, msbit
- lsbit
+ 1);
873 } else if (AsciiStrCmp (gOpThumb2
[Index
].Start
, "BFI") == 0) {
874 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, #%d, #%d", gReg
[Rd
], gReg
[Rn
], lsbit
, msbit
- lsbit
+ 1);
876 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, #%d, #%d", gReg
[Rd
], gReg
[Rn
], lsbit
, msbit
+ 1);
881 // <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>
882 coproc
= (OpCode32
>> 8) & 0xf;
883 opc1
= (OpCode32
>> 20) & 0xf;
884 opc2
= (OpCode32
>> 5) & 0x7;
885 CRd
= (OpCode32
>> 12) & 0xf;
886 CRn
= (OpCode32
>> 16) & 0xf;
887 CRm
= OpCode32
& 0xf;
888 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " p%d,#%d,c%d,c%d,c%d", coproc
, opc1
, CRd
, CRn
, CRm
);
890 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ",#%d,", opc2
);
896 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a", gReg
[Rd
], gReg
[Rm
]);
900 // <Rd>, <Rn>, <Rm>, <Ra>
901 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, %a, %a", gReg
[Rd
], gReg
[Rn
], gReg
[Rm
], gReg
[Rt
]);
911 AsciiSPrint (Buf
, Size
, "0x%08x", OpCode32
);
917 DisassembleArmInstruction (
918 IN UINT32
**OpCodePtr
,
926 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
927 point to next instructin.
929 We cheat and only decode instructions that access
930 memory. If the instruction is not found we dump the instruction in hex.
932 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.
933 @param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream
934 @param Extended TRUE dump hex for instruction too.
935 @param Buf Buffer to sprintf disassembly into.
936 @param Size Size of Buf in bytes.
940 DisassembleInstruction (
941 IN UINT8
**OpCodePtr
,
949 DisassembleThumbInstruction ((UINT16
**)OpCodePtr
, Buf
, Size
, Extended
);
951 DisassembleArmInstruction ((UINT32
**)OpCodePtr
, Buf
, Size
, Extended
);