1 //===- ThumbDisassemblerCore.h - Thumb disassembler helpers -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is part of the ARM Disassembler.
11 // It contains code for disassembling a Thumb instr. It is to be included by
12 // ARMDisassemblerCore.cpp because it contains the static DisassembleThumbFrm()
13 // function which acts as the dispatcher to disassemble a Thumb instruction.
15 //===----------------------------------------------------------------------===//
17 ///////////////////////////////
19 // Utility Functions //
21 ///////////////////////////////
23 // Utilities for 16-bit Thumb instructions.
25 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
27 [ tRm ] [ tRn ] [ tRd ]
40 // Extract tRt: Inst{10-8}.
41 static inline unsigned getT1tRt(uint32_t insn
) {
42 return slice(insn
, 10, 8);
45 // Extract tRm: Inst{8-6}.
46 static inline unsigned getT1tRm(uint32_t insn
) {
47 return slice(insn
, 8, 6);
50 // Extract tRn: Inst{5-3}.
51 static inline unsigned getT1tRn(uint32_t insn
) {
52 return slice(insn
, 5, 3);
55 // Extract tRd: Inst{2-0}.
56 static inline unsigned getT1tRd(uint32_t insn
) {
57 return slice(insn
, 2, 0);
60 // Extract [D:Rd]: Inst{7:2-0}.
61 static inline unsigned getT1Rd(uint32_t insn
) {
62 return slice(insn
, 7, 7) << 3 | slice(insn
, 2, 0);
65 // Extract Rm: Inst{6-3}.
66 static inline unsigned getT1Rm(uint32_t insn
) {
67 return slice(insn
, 6, 3);
70 // Extract imm3: Inst{8-6}.
71 static inline unsigned getT1Imm3(uint32_t insn
) {
72 return slice(insn
, 8, 6);
75 // Extract imm5: Inst{10-6}.
76 static inline unsigned getT1Imm5(uint32_t insn
) {
77 return slice(insn
, 10, 6);
80 // Extract i:imm5: Inst{9:7-3}.
81 static inline unsigned getT1Imm6(uint32_t insn
) {
82 return slice(insn
, 9, 9) << 5 | slice(insn
, 7, 3);
85 // Extract imm7: Inst{6-0}.
86 static inline unsigned getT1Imm7(uint32_t insn
) {
87 return slice(insn
, 6, 0);
90 // Extract imm8: Inst{7-0}.
91 static inline unsigned getT1Imm8(uint32_t insn
) {
92 return slice(insn
, 7, 0);
95 // Extract imm11: Inst{10-0}.
96 static inline unsigned getT1Imm11(uint32_t insn
) {
97 return slice(insn
, 10, 0);
100 // Extract cond: Inst{11-8}.
101 static inline unsigned getT1Cond(uint32_t insn
) {
102 return slice(insn
, 11, 8);
105 static inline bool IsGPR(unsigned RegClass
) {
106 return RegClass
== ARM::GPRRegClassID
|| RegClass
== ARM::rGPRRegClassID
;
109 // Utilities for 32-bit Thumb instructions.
111 // Extract imm4: Inst{19-16}.
112 static inline unsigned getImm4(uint32_t insn
) {
113 return slice(insn
, 19, 16);
116 // Extract imm3: Inst{14-12}.
117 static inline unsigned getImm3(uint32_t insn
) {
118 return slice(insn
, 14, 12);
121 // Extract imm8: Inst{7-0}.
122 static inline unsigned getImm8(uint32_t insn
) {
123 return slice(insn
, 7, 0);
126 // A8.6.61 LDRB (immediate, Thumb) and friends
129 static inline int decodeImm8(uint32_t insn
) {
130 int Offset
= getImm8(insn
);
131 return slice(insn
, 9, 9) ? Offset
: -Offset
;
134 // Extract imm12: Inst{11-0}.
135 static inline unsigned getImm12(uint32_t insn
) {
136 return slice(insn
, 11, 0);
139 // A8.6.63 LDRB (literal) and friends
142 static inline int decodeImm12(uint32_t insn
) {
143 int Offset
= getImm12(insn
);
144 return slice(insn
, 23, 23) ? Offset
: -Offset
;
147 // Extract imm2: Inst{7-6}.
148 static inline unsigned getImm2(uint32_t insn
) {
149 return slice(insn
, 7, 6);
152 // For BFI, BFC, t2SBFX, and t2UBFX.
153 // Extract lsb: Inst{14-12:7-6}.
154 static inline unsigned getLsb(uint32_t insn
) {
155 return getImm3(insn
) << 2 | getImm2(insn
);
159 // Extract msb: Inst{4-0}.
160 static inline unsigned getMsb(uint32_t insn
) {
161 return slice(insn
, 4, 0);
164 // For t2SBFX and t2UBFX.
165 // Extract widthminus1: Inst{4-0}.
166 static inline unsigned getWidthMinus1(uint32_t insn
) {
167 return slice(insn
, 4, 0);
170 // For t2ADDri12 and t2SUBri12.
171 // imm12 = i:imm3:imm8;
172 static inline unsigned getIImm3Imm8(uint32_t insn
) {
173 return slice(insn
, 26, 26) << 11 | getImm3(insn
) << 8 | getImm8(insn
);
176 // For t2MOVi16 and t2MOVTi16.
177 // imm16 = imm4:i:imm3:imm8;
178 static inline unsigned getImm16(uint32_t insn
) {
179 return getImm4(insn
) << 12 | slice(insn
, 26, 26) << 11 |
180 getImm3(insn
) << 8 | getImm8(insn
);
183 // Inst{5-4} encodes the shift type.
184 static inline unsigned getShiftTypeBits(uint32_t insn
) {
185 return slice(insn
, 5, 4);
188 // Inst{14-12}:Inst{7-6} encodes the imm5 shift amount.
189 static inline unsigned getShiftAmtBits(uint32_t insn
) {
190 return getImm3(insn
) << 2 | getImm2(insn
);
194 // Encoding T1 ARMv6T2, ARMv7
195 // LLVM-specific encoding for #<lsb> and #<width>
196 static inline bool getBitfieldInvMask(uint32_t insn
, uint32_t &mask
) {
197 uint32_t lsb
= getImm3(insn
) << 2 | getImm2(insn
);
198 uint32_t msb
= getMsb(insn
);
201 DEBUG(errs() << "Encoding error: msb < lsb\n");
204 for (uint32_t i
= lsb
; i
<= msb
; ++i
)
210 // A8.4 Shifts applied to a register
211 // A8.4.1 Constant shifts
212 // A8.4.3 Pseudocode details of instruction-specified shifts and rotates
214 // decodeImmShift() returns the shift amount and the the shift opcode.
215 // Note that, as of Jan-06-2010, LLVM does not support rrx shifted operands yet.
216 static inline unsigned decodeImmShift(unsigned bits2
, unsigned imm5
,
217 ARM_AM::ShiftOpc
&ShOp
) {
219 assert(imm5
< 32 && "Invalid imm5 argument");
221 default: assert(0 && "No such value");
223 ShOp
= (imm5
== 0 ? ARM_AM::no_shift
: ARM_AM::lsl
);
227 return (imm5
== 0 ? 32 : imm5
);
230 return (imm5
== 0 ? 32 : imm5
);
232 ShOp
= (imm5
== 0 ? ARM_AM::rrx
: ARM_AM::ror
);
233 return (imm5
== 0 ? 1 : imm5
);
237 // A6.3.2 Modified immediate constants in Thumb instructions
239 // ThumbExpandImm() returns the modified immediate constant given an imm12 for
240 // Thumb data-processing instructions with modified immediate.
241 // See also A6.3.1 Data-processing (modified immediate).
242 static inline unsigned ThumbExpandImm(unsigned imm12
) {
243 assert(imm12
<= 0xFFF && "Invalid imm12 argument");
245 // If the leading two bits is 0b00, the modified immediate constant is
246 // obtained by splatting the low 8 bits into the first byte, every other byte,
247 // or every byte of a 32-bit value.
249 // Otherwise, a rotate right of '1':imm12<6:0> by the amount imm12<11:7> is
252 if (slice(imm12
, 11, 10) == 0) {
253 unsigned short control
= slice(imm12
, 9, 8);
254 unsigned imm8
= slice(imm12
, 7, 0);
257 assert(0 && "No such value");
262 return imm8
<< 16 | imm8
;
264 return imm8
<< 24 | imm8
<< 8;
266 return imm8
<< 24 | imm8
<< 16 | imm8
<< 8 | imm8
;
269 // A rotate is required.
270 unsigned Val
= 1 << 7 | slice(imm12
, 6, 0);
271 unsigned Amt
= slice(imm12
, 11, 7);
272 return ARM_AM::rotr32(Val
, Amt
);
276 static inline int decodeImm32_B_EncodingT3(uint32_t insn
) {
277 bool S
= slice(insn
, 26, 26);
278 bool J1
= slice(insn
, 13, 13);
279 bool J2
= slice(insn
, 11, 11);
280 unsigned Imm21
= slice(insn
, 21, 16) << 12 | slice(insn
, 10, 0) << 1;
281 if (S
) Imm21
|= 1 << 20;
282 if (J2
) Imm21
|= 1 << 19;
283 if (J1
) Imm21
|= 1 << 18;
285 return SignExtend32
<21>(Imm21
);
288 static inline int decodeImm32_B_EncodingT4(uint32_t insn
) {
289 unsigned S
= slice(insn
, 26, 26);
290 bool I1
= slice(insn
, 13, 13) == S
;
291 bool I2
= slice(insn
, 11, 11) == S
;
292 unsigned Imm25
= slice(insn
, 25, 16) << 12 | slice(insn
, 10, 0) << 1;
293 if (S
) Imm25
|= 1 << 24;
294 if (I1
) Imm25
|= 1 << 23;
295 if (I2
) Imm25
|= 1 << 22;
297 return SignExtend32
<25>(Imm25
);
300 static inline int decodeImm32_BL(uint32_t insn
) {
301 unsigned S
= slice(insn
, 26, 26);
302 bool I1
= slice(insn
, 13, 13) == S
;
303 bool I2
= slice(insn
, 11, 11) == S
;
304 unsigned Imm25
= slice(insn
, 25, 16) << 12 | slice(insn
, 10, 0) << 1;
305 if (S
) Imm25
|= 1 << 24;
306 if (I1
) Imm25
|= 1 << 23;
307 if (I2
) Imm25
|= 1 << 22;
309 return SignExtend32
<25>(Imm25
);
312 static inline int decodeImm32_BLX(uint32_t insn
) {
313 unsigned S
= slice(insn
, 26, 26);
314 bool I1
= slice(insn
, 13, 13) == S
;
315 bool I2
= slice(insn
, 11, 11) == S
;
316 unsigned Imm25
= slice(insn
, 25, 16) << 12 | slice(insn
, 10, 1) << 2;
317 if (S
) Imm25
|= 1 << 24;
318 if (I1
) Imm25
|= 1 << 23;
319 if (I2
) Imm25
|= 1 << 22;
321 return SignExtend32
<25>(Imm25
);
324 // See, for example, A8.6.221 SXTAB16.
325 static inline unsigned decodeRotate(uint32_t insn
) {
326 unsigned rotate
= slice(insn
, 5, 4);
330 ///////////////////////////////////////////////
332 // Thumb1 instruction disassembly functions. //
334 ///////////////////////////////////////////////
336 // See "Utilities for 16-bit Thumb instructions" for register naming convention.
338 // A6.2.1 Shift (immediate), add, subtract, move, and compare
340 // shift immediate: tRd CPSR tRn imm5
341 // add/sub register: tRd CPSR tRn tRm
342 // add/sub 3-bit immediate: tRd CPSR tRn imm3
343 // add/sub 8-bit immediate: tRt CPSR tRt(TIED_TO) imm8
344 // mov/cmp immediate: tRt [CPSR] imm8 (CPSR present for mov)
348 static bool DisassembleThumb1General(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
349 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
351 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
352 unsigned &OpIdx
= NumOpsAdded
;
356 assert(NumOps
>= 2 && OpInfo
[0].RegClass
== ARM::tGPRRegClassID
357 && "Invalid arguments");
359 bool Imm3
= (Opcode
== ARM::tADDi3
|| Opcode
== ARM::tSUBi3
);
361 // Use Rt implies use imm8.
362 bool UseRt
= (Opcode
== ARM::tADDi8
|| Opcode
== ARM::tSUBi8
||
363 Opcode
== ARM::tMOVi8
|| Opcode
== ARM::tCMPi8
);
365 // Add the destination operand.
366 MI
.addOperand(MCOperand::CreateReg(
367 getRegisterEnum(B
, ARM::tGPRRegClassID
,
368 UseRt
? getT1tRt(insn
) : getT1tRd(insn
))));
371 // Check whether the next operand to be added is a CCR Register.
372 if (OpInfo
[OpIdx
].RegClass
== ARM::CCRRegClassID
) {
373 assert(OpInfo
[OpIdx
].isOptionalDef() && "Optional def operand expected");
374 MI
.addOperand(MCOperand::CreateReg(B
->InITBlock() ? 0 : ARM::CPSR
));
378 // Check whether the next operand to be added is a Thumb1 Register.
379 assert(OpIdx
< NumOps
&& "More operands expected");
380 if (OpInfo
[OpIdx
].RegClass
== ARM::tGPRRegClassID
) {
381 // For UseRt, the reg operand is tied to the first reg operand.
382 MI
.addOperand(MCOperand::CreateReg(
383 getRegisterEnum(B
, ARM::tGPRRegClassID
,
384 UseRt
? getT1tRt(insn
) : getT1tRn(insn
))));
388 // Special case for tMOVSr.
392 // The next available operand is either a reg operand or an imm operand.
393 if (OpInfo
[OpIdx
].RegClass
== ARM::tGPRRegClassID
) {
394 // Three register operand instructions.
395 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::tGPRRegClassID
,
398 assert(OpInfo
[OpIdx
].RegClass
< 0 &&
399 !OpInfo
[OpIdx
].isPredicate() && !OpInfo
[OpIdx
].isOptionalDef()
400 && "Pure imm operand expected");
401 MI
.addOperand(MCOperand::CreateImm(UseRt
? getT1Imm8(insn
)
402 : (Imm3
? getT1Imm3(insn
)
403 : getT1Imm5(insn
))));
410 // A6.2.2 Data-processing
412 // tCMPr, tTST, tCMN: tRd tRn
413 // tMVN, tRSB: tRd CPSR tRn
414 // Others: tRd CPSR tRd(TIED_TO) tRn
415 static bool DisassembleThumb1DP(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
416 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
418 const TargetInstrDesc
&TID
= ARMInsts
[Opcode
];
419 const TargetOperandInfo
*OpInfo
= TID
.OpInfo
;
420 unsigned &OpIdx
= NumOpsAdded
;
424 assert(NumOps
>= 2 && OpInfo
[0].RegClass
== ARM::tGPRRegClassID
&&
425 (OpInfo
[1].RegClass
== ARM::CCRRegClassID
426 || OpInfo
[1].RegClass
== ARM::tGPRRegClassID
)
427 && "Invalid arguments");
429 // Add the destination operand.
430 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::tGPRRegClassID
,
434 // Check whether the next operand to be added is a CCR Register.
435 if (OpInfo
[OpIdx
].RegClass
== ARM::CCRRegClassID
) {
436 assert(OpInfo
[OpIdx
].isOptionalDef() && "Optional def operand expected");
437 MI
.addOperand(MCOperand::CreateReg(B
->InITBlock() ? 0 : ARM::CPSR
));
441 // We have either { tRd(TIED_TO), tRn } or { tRn } remaining.
442 // Process the TIED_TO operand first.
444 assert(OpIdx
< NumOps
&& OpInfo
[OpIdx
].RegClass
== ARM::tGPRRegClassID
445 && "Thumb reg operand expected");
447 if ((Idx
= TID
.getOperandConstraint(OpIdx
, TOI::TIED_TO
)) != -1) {
448 // The reg operand is tied to the first reg operand.
449 MI
.addOperand(MI
.getOperand(Idx
));
453 // Process possible next reg operand.
454 if (OpIdx
< NumOps
&& OpInfo
[OpIdx
].RegClass
== ARM::tGPRRegClassID
) {
456 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::tGPRRegClassID
,
464 // A6.2.3 Special data instructions and branch and exchange
466 // tADDhirr: Rd Rd(TIED_TO) Rm
468 // tMOVr, tMOVgpr2gpr, tMOVgpr2tgpr, tMOVtgpr2gpr: Rd|tRd Rm|tRn
469 // tBX_RET: 0 operand
470 // tBX_RET_vararg: Rm
472 static bool DisassembleThumb1Special(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
473 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
475 // tBX_RET has 0 operand.
479 // BX/BLX has 1 reg operand: Rm.
481 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
487 const TargetInstrDesc
&TID
= ARMInsts
[Opcode
];
488 const TargetOperandInfo
*OpInfo
= TID
.OpInfo
;
489 unsigned &OpIdx
= NumOpsAdded
;
493 // Add the destination operand.
494 unsigned RegClass
= OpInfo
[OpIdx
].RegClass
;
495 MI
.addOperand(MCOperand::CreateReg(
496 getRegisterEnum(B
, RegClass
,
497 IsGPR(RegClass
) ? getT1Rd(insn
)
501 // We have either { Rd(TIED_TO), Rm } or { Rm|tRn } remaining.
502 // Process the TIED_TO operand first.
504 assert(OpIdx
< NumOps
&& "More operands expected");
506 if ((Idx
= TID
.getOperandConstraint(OpIdx
, TOI::TIED_TO
)) != -1) {
507 // The reg operand is tied to the first reg operand.
508 MI
.addOperand(MI
.getOperand(Idx
));
512 // The next reg operand is either Rm or tRn.
513 assert(OpIdx
< NumOps
&& "More operands expected");
514 RegClass
= OpInfo
[OpIdx
].RegClass
;
515 MI
.addOperand(MCOperand::CreateReg(
516 getRegisterEnum(B
, RegClass
,
517 IsGPR(RegClass
) ? getT1Rm(insn
)
524 // A8.6.59 LDR (literal)
526 // tLDRpci: tRt imm8*4
527 static bool DisassembleThumb1LdPC(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
528 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
530 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
531 if (!OpInfo
) return false;
533 assert(NumOps
>= 2 && OpInfo
[0].RegClass
== ARM::tGPRRegClassID
&&
534 (OpInfo
[1].RegClass
< 0 &&
535 !OpInfo
[1].isPredicate() &&
536 !OpInfo
[1].isOptionalDef())
537 && "Invalid arguments");
539 // Add the destination operand.
540 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::tGPRRegClassID
,
543 // And the (imm8 << 2) operand.
544 MI
.addOperand(MCOperand::CreateImm(getT1Imm8(insn
) << 2));
551 // Thumb specific addressing modes (see ARMInstrThumb.td):
553 // t_addrmode_rr := reg + reg
555 // t_addrmode_s4 := reg + reg
558 // t_addrmode_s2 := reg + reg
561 // t_addrmode_s1 := reg + reg
564 // t_addrmode_sp := sp + imm8 * 4
567 // A6.2.4 Load/store single data item
569 // Load/Store Register (reg|imm): tRd tRn imm5 tRm
570 // Load Register Signed Byte|Halfword: tRd tRn tRm
571 static bool DisassembleThumb1LdSt(unsigned opA
, MCInst
&MI
, unsigned Opcode
,
572 uint32_t insn
, unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
574 const TargetInstrDesc
&TID
= ARMInsts
[Opcode
];
575 const TargetOperandInfo
*OpInfo
= TID
.OpInfo
;
576 unsigned &OpIdx
= NumOpsAdded
;
578 // Table A6-5 16-bit Thumb Load/store instructions
579 // opA = 0b0101 for STR/LDR (register) and friends.
580 // Otherwise, we have STR/LDR (immediate) and friends.
581 bool Imm5
= (opA
!= 5);
584 && OpInfo
[0].RegClass
== ARM::tGPRRegClassID
585 && OpInfo
[1].RegClass
== ARM::tGPRRegClassID
586 && "Expect >= 2 operands and first two as thumb reg operands");
588 // Add the destination reg and the base reg.
589 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::tGPRRegClassID
,
591 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::tGPRRegClassID
,
595 // We have either { imm5, tRm } or { tRm } remaining.
596 // Process the imm5 first. Note that STR/LDR (register) should skip the imm5
597 // offset operand for t_addrmode_s[1|2|4].
599 assert(OpIdx
< NumOps
&& "More operands expected");
601 if (OpInfo
[OpIdx
].RegClass
< 0 && !OpInfo
[OpIdx
].isPredicate() &&
602 !OpInfo
[OpIdx
].isOptionalDef()) {
604 MI
.addOperand(MCOperand::CreateImm(Imm5
? getT1Imm5(insn
) : 0));
608 // The next reg operand is tRm, the offset.
609 assert(OpIdx
< NumOps
&& OpInfo
[OpIdx
].RegClass
== ARM::tGPRRegClassID
610 && "Thumb reg operand expected");
611 MI
.addOperand(MCOperand::CreateReg(
613 : getRegisterEnum(B
, ARM::tGPRRegClassID
,
620 // A6.2.4 Load/store single data item
622 // Load/Store Register SP relative: tRt ARM::SP imm8
623 static bool DisassembleThumb1LdStSP(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
624 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
626 assert((Opcode
== ARM::tLDRspi
|| Opcode
== ARM::tSTRspi
)
627 && "Unexpected opcode");
629 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
630 if (!OpInfo
) return false;
632 assert(NumOps
>= 3 &&
633 OpInfo
[0].RegClass
== ARM::tGPRRegClassID
&&
634 OpInfo
[1].RegClass
== ARM::GPRRegClassID
&&
635 (OpInfo
[2].RegClass
< 0 &&
636 !OpInfo
[2].isPredicate() &&
637 !OpInfo
[2].isOptionalDef())
638 && "Invalid arguments");
640 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::tGPRRegClassID
,
642 MI
.addOperand(MCOperand::CreateReg(ARM::SP
));
643 MI
.addOperand(MCOperand::CreateImm(getT1Imm8(insn
)));
648 // Table A6-1 16-bit Thumb instruction encoding
651 // tADDrPCi: tRt imm8
652 static bool DisassembleThumb1AddPCi(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
653 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
655 assert(Opcode
== ARM::tADDrPCi
&& "Unexpected opcode");
657 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
658 if (!OpInfo
) return false;
660 assert(NumOps
>= 2 && OpInfo
[0].RegClass
== ARM::tGPRRegClassID
&&
661 (OpInfo
[1].RegClass
< 0 &&
662 !OpInfo
[1].isPredicate() &&
663 !OpInfo
[1].isOptionalDef())
664 && "Invalid arguments");
666 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::tGPRRegClassID
,
668 MI
.addOperand(MCOperand::CreateImm(getT1Imm8(insn
)));
673 // Table A6-1 16-bit Thumb instruction encoding
674 // A8.6.8 ADD (SP plus immediate)
676 // tADDrSPi: tRt ARM::SP imm8
677 static bool DisassembleThumb1AddSPi(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
678 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
680 assert(Opcode
== ARM::tADDrSPi
&& "Unexpected opcode");
682 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
683 if (!OpInfo
) return false;
685 assert(NumOps
>= 3 &&
686 OpInfo
[0].RegClass
== ARM::tGPRRegClassID
&&
687 OpInfo
[1].RegClass
== ARM::GPRRegClassID
&&
688 (OpInfo
[2].RegClass
< 0 &&
689 !OpInfo
[2].isPredicate() &&
690 !OpInfo
[2].isOptionalDef())
691 && "Invalid arguments");
693 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::tGPRRegClassID
,
695 MI
.addOperand(MCOperand::CreateReg(ARM::SP
));
696 MI
.addOperand(MCOperand::CreateImm(getT1Imm8(insn
)));
701 // tPUSH, tPOP: Pred-Imm Pred-CCR register_list
703 // where register_list = low registers + [lr] for PUSH or
704 // low registers + [pc] for POP
706 // "low registers" is specified by Inst{7-0}
707 // lr|pc is specified by Inst{8}
708 static bool DisassembleThumb1PushPop(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
709 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
711 assert((Opcode
== ARM::tPUSH
|| Opcode
== ARM::tPOP
) && "Unexpected opcode");
713 unsigned &OpIdx
= NumOpsAdded
;
715 // Handling the two predicate operands before the reglist.
716 if (B
->DoPredicateOperands(MI
, Opcode
, insn
, NumOps
))
719 DEBUG(errs() << "Expected predicate operands not found.\n");
723 unsigned RegListBits
= slice(insn
, 8, 8) << (Opcode
== ARM::tPUSH
? 14 : 15)
726 // Fill the variadic part of reglist.
727 for (unsigned i
= 0; i
< 16; ++i
) {
728 if ((RegListBits
>> i
) & 1) {
729 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
738 // A6.2.5 Miscellaneous 16-bit instructions
739 // Delegate to DisassembleThumb1PushPop() for tPUSH & tPOP.
741 // tADDspi, tSUBspi: ARM::SP ARM::SP(TIED_TO) imm7
742 // t2IT: firstcond=Inst{7-4} mask=Inst{3-0}
743 // tCBNZ, tCBZ: tRd imm6*2
745 // tNOP, tSEV, tYIELD, tWFE, tWFI:
746 // no operand (except predicate pair)
747 // tSETENDBE, tSETENDLE, :
750 static bool DisassembleThumb1Misc(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
751 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
756 if (Opcode
== ARM::tPUSH
|| Opcode
== ARM::tPOP
)
757 return DisassembleThumb1PushPop(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
759 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
761 // Predicate operands are handled elsewhere.
763 OpInfo
[0].isPredicate() && OpInfo
[1].isPredicate() &&
764 OpInfo
[0].RegClass
< 0 && OpInfo
[1].RegClass
== ARM::CCRRegClassID
) {
768 if (Opcode
== ARM::tADDspi
|| Opcode
== ARM::tSUBspi
) {
769 // Special case handling for tADDspi and tSUBspi.
770 // A8.6.8 ADD (SP plus immediate) & A8.6.215 SUB (SP minus immediate)
771 MI
.addOperand(MCOperand::CreateReg(ARM::SP
));
772 MI
.addOperand(MCOperand::CreateReg(ARM::SP
));
773 MI
.addOperand(MCOperand::CreateImm(getT1Imm7(insn
)));
778 if (Opcode
== ARM::t2IT
) {
779 // Special case handling for If-Then.
781 // Tag the (firstcond[0] bit << 4) along with mask.
784 MI
.addOperand(MCOperand::CreateImm(slice(insn
, 7, 4)));
786 // firstcond[0] and mask
787 MI
.addOperand(MCOperand::CreateImm(slice(insn
, 4, 0)));
792 if (Opcode
== ARM::tBKPT
) {
793 MI
.addOperand(MCOperand::CreateImm(getT1Imm8(insn
))); // breakpoint value
798 // CPS has a singleton $opt operand that contains the following information:
799 // opt{4-0} = don't care
800 // opt{5} = 0 (false)
801 // opt{8-6} = AIF from Inst{2-0}
802 // opt{10-9} = 1:imod from Inst{4} with 0b10 as enable and 0b11 as disable
803 if (Opcode
== ARM::tCPS
) {
804 unsigned Option
= slice(insn
, 2, 0) << 6 | slice(insn
, 4, 4) << 9 | 1 << 10;
805 MI
.addOperand(MCOperand::CreateImm(Option
));
810 assert(NumOps
>= 2 && OpInfo
[0].RegClass
== ARM::tGPRRegClassID
&&
811 (OpInfo
[1].RegClass
< 0 || OpInfo
[1].RegClass
==ARM::tGPRRegClassID
)
812 && "Expect >=2 operands");
814 // Add the destination operand.
815 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::tGPRRegClassID
,
818 if (OpInfo
[1].RegClass
== ARM::tGPRRegClassID
) {
819 // Two register instructions.
820 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::tGPRRegClassID
,
824 assert((Opcode
== ARM::tCBNZ
|| Opcode
== ARM::tCBZ
) &&"Unexpected opcode");
825 MI
.addOperand(MCOperand::CreateImm(getT1Imm6(insn
) * 2));
833 // A8.6.53 LDM / LDMIA
834 // A8.6.189 STM / STMIA
836 // tLDM_UPD/tSTM_UPD: tRt tRt AM4ModeImm Pred-Imm Pred-CCR register_list
837 // tLDM: tRt AM4ModeImm Pred-Imm Pred-CCR register_list
838 static bool DisassembleThumb1LdStMul(bool Ld
, MCInst
&MI
, unsigned Opcode
,
839 uint32_t insn
, unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
841 assert((Opcode
== ARM::tLDM
|| Opcode
== ARM::tLDM_UPD
||
842 Opcode
== ARM::tSTM_UPD
) && "Unexpected opcode");
844 unsigned &OpIdx
= NumOpsAdded
;
846 unsigned tRt
= getT1tRt(insn
);
850 // WB register, if necessary.
851 if (Opcode
== ARM::tLDM_UPD
|| Opcode
== ARM::tSTM_UPD
) {
852 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
857 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
861 // A8.6.53 LDM / LDMIA / LDMFD - Encoding T1
862 // A8.6.53 STM / STMIA / STMEA - Encoding T1
863 MI
.addOperand(MCOperand::CreateImm(ARM_AM::getAM4ModeImm(ARM_AM::ia
)));
866 // Handling the two predicate operands before the reglist.
867 if (B
->DoPredicateOperands(MI
, Opcode
, insn
, NumOps
))
870 DEBUG(errs() << "Expected predicate operands not found.\n");
874 unsigned RegListBits
= slice(insn
, 7, 0);
876 // Fill the variadic part of reglist.
877 for (unsigned i
= 0; i
< 8; ++i
) {
878 if ((RegListBits
>> i
) & 1) {
879 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::tGPRRegClassID
,
888 static bool DisassembleThumb1LdMul(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
889 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
890 return DisassembleThumb1LdStMul(true, MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
894 static bool DisassembleThumb1StMul(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
895 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
896 return DisassembleThumb1LdStMul(false, MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
900 // A8.6.16 B Encoding T1
901 // cond = Inst{11-8} & imm8 = Inst{7-0}
902 // imm32 = SignExtend(imm8:'0', 32)
904 // tBcc: offset Pred-Imm Pred-CCR
905 // tSVC: imm8 Pred-Imm Pred-CCR
906 // tTRAP: 0 operand (early return)
907 static bool DisassembleThumb1CondBr(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
908 unsigned short NumOps
, unsigned &NumOpsAdded
, BO
) {
910 if (Opcode
== ARM::tTRAP
)
913 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
914 if (!OpInfo
) return false;
916 assert(NumOps
== 3 && OpInfo
[0].RegClass
< 0 &&
917 OpInfo
[1].isPredicate() && OpInfo
[2].RegClass
== ARM::CCRRegClassID
918 && "Exactly 3 operands expected");
920 unsigned Imm8
= getT1Imm8(insn
);
921 MI
.addOperand(MCOperand::CreateImm(
922 Opcode
== ARM::tBcc
? SignExtend32
<9>(Imm8
<< 1) + 4
925 // Predicate operands by ARMBasicMCBuilder::TryPredicateAndSBitModifier().
931 // A8.6.16 B Encoding T2
932 // imm11 = Inst{10-0}
933 // imm32 = SignExtend(imm11:'0', 32)
936 static bool DisassembleThumb1Br(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
937 unsigned short NumOps
, unsigned &NumOpsAdded
, BO
) {
939 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
940 if (!OpInfo
) return false;
942 assert(NumOps
== 1 && OpInfo
[0].RegClass
< 0 && "1 imm operand expected");
944 unsigned Imm11
= getT1Imm11(insn
);
946 // When executing a Thumb instruction, PC reads as the address of the current
947 // instruction plus 4. The assembler subtracts 4 from the difference between
948 // the branch instruction and the target address, disassembler has to add 4 to
950 MI
.addOperand(MCOperand::CreateImm(SignExtend32
<12>(Imm11
<< 1) + 4));
958 // See A6.2 16-bit Thumb instruction encoding for instruction classes
959 // corresponding to op.
961 // Table A6-1 16-bit Thumb instruction encoding (abridged)
962 // op Instruction or instruction class
963 // ------ --------------------------------------------------------------------
964 // 00xxxx Shift (immediate), add, subtract, move, and compare on page A6-7
965 // 010000 Data-processing on page A6-8
966 // 010001 Special data instructions and branch and exchange on page A6-9
967 // 01001x Load from Literal Pool, see LDR (literal) on page A8-122
968 // 0101xx Load/store single data item on page A6-10
971 // 10100x Generate PC-relative address, see ADR on page A8-32
972 // 10101x Generate SP-relative address, see ADD (SP plus immediate) on
974 // 1011xx Miscellaneous 16-bit instructions on page A6-11
975 // 11000x Store multiple registers, see STM / STMIA / STMEA on page A8-374
976 // 11001x Load multiple registers, see LDM / LDMIA / LDMFD on page A8-110 a
977 // 1101xx Conditional branch, and Supervisor Call on page A6-13
978 // 11100x Unconditional Branch, see B on page A8-44
980 static bool DisassembleThumb1(uint16_t op
, MCInst
&MI
, unsigned Opcode
,
981 uint32_t insn
, unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
983 unsigned op1
= slice(op
, 5, 4);
984 unsigned op2
= slice(op
, 3, 2);
985 unsigned op3
= slice(op
, 1, 0);
986 unsigned opA
= slice(op
, 5, 2);
989 // A6.2.1 Shift (immediate), add, subtract, move, and compare
990 return DisassembleThumb1General(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
996 // A6.2.2 Data-processing
997 return DisassembleThumb1DP(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
999 // A6.2.3 Special data instructions and branch and exchange
1000 return DisassembleThumb1Special(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
1003 // A8.6.59 LDR (literal)
1004 return DisassembleThumb1LdPC(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
1008 // A6.2.4 Load/store single data item
1009 return DisassembleThumb1LdSt(opA
, MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
1017 // A6.2.4 Load/store single data item
1018 return DisassembleThumb1LdSt(opA
, MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
1021 // A6.2.4 Load/store single data item
1022 return DisassembleThumb1LdStSP(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
1026 return DisassembleThumb1AddPCi(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
1029 // A8.6.8 ADD (SP plus immediate)
1030 return DisassembleThumb1AddSPi(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
1034 // A6.2.5 Miscellaneous 16-bit instructions
1035 return DisassembleThumb1Misc(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
1042 // A8.6.189 STM / STMIA / STMEA
1043 return DisassembleThumb1StMul(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
1045 // A8.6.53 LDM / LDMIA / LDMFD
1046 return DisassembleThumb1LdMul(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
1049 // A6.2.6 Conditional branch, and Supervisor Call
1050 return DisassembleThumb1CondBr(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
1052 // Unconditional Branch, see B on page A8-44
1053 return DisassembleThumb1Br(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
1055 assert(0 && "Unreachable code");
1060 assert(0 && "Unreachable code");
1067 ///////////////////////////////////////////////
1069 // Thumb2 instruction disassembly functions. //
1071 ///////////////////////////////////////////////
1073 ///////////////////////////////////////////////////////////
1075 // Note: the register naming follows the ARM convention! //
1077 ///////////////////////////////////////////////////////////
1079 static inline bool Thumb2SRSOpcode(unsigned Opcode
) {
1083 case ARM::t2SRSDBW
: case ARM::t2SRSDB
:
1084 case ARM::t2SRSIAW
: case ARM::t2SRSIA
:
1089 static inline bool Thumb2RFEOpcode(unsigned Opcode
) {
1093 case ARM::t2RFEDBW
: case ARM::t2RFEDB
:
1094 case ARM::t2RFEIAW
: case ARM::t2RFEIA
:
1099 // t2SRS[IA|DB]W/t2SRS[IA|DB]: mode_imm = Inst{4-0}
1100 static bool DisassembleThumb2SRS(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
1101 unsigned short NumOps
, unsigned &NumOpsAdded
) {
1102 MI
.addOperand(MCOperand::CreateImm(slice(insn
, 4, 0)));
1107 // t2RFE[IA|DB]W/t2RFE[IA|DB]: Rn
1108 static bool DisassembleThumb2RFE(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
1109 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1110 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1116 static bool DisassembleThumb2LdStMul(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
1117 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1119 if (Thumb2SRSOpcode(Opcode
))
1120 return DisassembleThumb2SRS(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
);
1122 if (Thumb2RFEOpcode(Opcode
))
1123 return DisassembleThumb2RFE(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
1125 assert((Opcode
== ARM::t2LDM
|| Opcode
== ARM::t2LDM_UPD
||
1126 Opcode
== ARM::t2STM
|| Opcode
== ARM::t2STM_UPD
)
1127 && "Unexpected opcode");
1128 assert(NumOps
>= 5 && "Thumb2 LdStMul expects NumOps >= 5");
1130 unsigned &OpIdx
= NumOpsAdded
;
1134 unsigned Base
= getRegisterEnum(B
, ARM::GPRRegClassID
, decodeRn(insn
));
1136 // Writeback to base.
1137 if (Opcode
== ARM::t2LDM_UPD
|| Opcode
== ARM::t2STM_UPD
) {
1138 MI
.addOperand(MCOperand::CreateReg(Base
));
1142 MI
.addOperand(MCOperand::CreateReg(Base
));
1145 ARM_AM::AMSubMode SubMode
= getAMSubModeForBits(getPUBits(insn
));
1146 MI
.addOperand(MCOperand::CreateImm(ARM_AM::getAM4ModeImm(SubMode
)));
1149 // Handling the two predicate operands before the reglist.
1150 if (B
->DoPredicateOperands(MI
, Opcode
, insn
, NumOps
))
1153 DEBUG(errs() << "Expected predicate operands not found.\n");
1157 unsigned RegListBits
= insn
& ((1 << 16) - 1);
1159 // Fill the variadic part of reglist.
1160 for (unsigned i
= 0; i
< 16; ++i
) {
1161 if ((RegListBits
>> i
) & 1) {
1162 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1172 // t2LDREXD: Rd Rs Rn
1173 // t2LDREXB, t2LDREXH: Rd Rn
1174 // t2STREX: Rs Rd Rn
1175 // t2STREXD: Rm Rd Rs Rn
1176 // t2STREXB, t2STREXH: Rm Rd Rn
1177 static bool DisassembleThumb2LdStEx(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
1178 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1180 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
1181 if (!OpInfo
) return false;
1183 unsigned &OpIdx
= NumOpsAdded
;
1188 && OpInfo
[0].RegClass
== ARM::GPRRegClassID
1189 && OpInfo
[1].RegClass
== ARM::GPRRegClassID
1190 && "Expect >=2 operands and first two as reg operands");
1192 bool isStore
= (ARM::t2STREX
<= Opcode
&& Opcode
<= ARM::t2STREXH
);
1193 bool isSW
= (Opcode
== ARM::t2LDREX
|| Opcode
== ARM::t2STREX
);
1194 bool isDW
= (Opcode
== ARM::t2LDREXD
|| Opcode
== ARM::t2STREXD
);
1196 // Add the destination operand for store.
1198 MI
.addOperand(MCOperand::CreateReg(
1199 getRegisterEnum(B
, ARM::GPRRegClassID
,
1200 isSW
? decodeRs(insn
) : decodeRm(insn
))));
1204 // Source operand for store and destination operand for load.
1205 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1209 // Thumb2 doubleword complication: with an extra source/destination operand.
1211 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1216 // Finally add the pointer operand.
1217 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1224 // LLVM, as of Jan-05-2010, does not output <Rt2>, i.e., Rs, in the asm.
1225 // Whereas the ARM Arch. Manual does not require that t2 = t+1 like in ARM ISA.
1227 // t2LDRDi8: Rd Rs Rn imm8s4 (offset mode)
1228 // t2LDRDpci: Rd Rs imm8s4 (Not decoded, prefer the generic t2LDRDi8 version)
1229 // t2STRDi8: Rd Rs Rn imm8s4 (offset mode)
1231 // Ditto for t2LDRD_PRE, t2LDRD_POST, t2STRD_PRE, t2STRD_POST, which are for
1232 // disassembly only and do not have a tied_to writeback base register operand.
1233 static bool DisassembleThumb2LdStDual(MCInst
&MI
, unsigned Opcode
,
1234 uint32_t insn
, unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1236 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
1237 if (!OpInfo
) return false;
1240 && OpInfo
[0].RegClass
== ARM::GPRRegClassID
1241 && OpInfo
[1].RegClass
== ARM::GPRRegClassID
1242 && OpInfo
[2].RegClass
== ARM::GPRRegClassID
1243 && OpInfo
[3].RegClass
< 0
1244 && "Expect >= 4 operands and first 3 as reg operands");
1246 // Add the <Rt> <Rt2> operands.
1247 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1249 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1251 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1254 // Finally add (+/-)imm8*4, depending on the U bit.
1255 int Offset
= getImm8(insn
) * 4;
1256 if (getUBit(insn
) == 0)
1258 MI
.addOperand(MCOperand::CreateImm(Offset
));
1264 // PC-based defined for Codegen, which do not get decoded by design:
1266 // t2TBB, t2TBH: Rm immDontCare immDontCare
1268 // Generic version defined for disassembly:
1270 // t2TBBgen, t2TBHgen: Rn Rm Pred-Imm Pred-CCR
1271 static bool DisassembleThumb2TB(MCInst
&MI
, unsigned Opcode
,
1272 uint32_t insn
, unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1274 assert(NumOps
>= 2 && "Expect >= 2 operands");
1276 // The generic version of TBB/TBH needs a base register.
1277 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1279 // Add the index register.
1280 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1287 static inline bool Thumb2ShiftOpcode(unsigned Opcode
) {
1291 case ARM::t2MOVCClsl
: case ARM::t2MOVCClsr
:
1292 case ARM::t2MOVCCasr
: case ARM::t2MOVCCror
:
1293 case ARM::t2LSLri
: case ARM::t2LSRri
:
1294 case ARM::t2ASRri
: case ARM::t2RORri
:
1299 // A6.3.11 Data-processing (shifted register)
1301 // Two register operands (Rn=0b1111 no 1st operand reg): Rs Rm
1302 // Two register operands (Rs=0b1111 no dst operand reg): Rn Rm
1303 // Three register operands: Rs Rn Rm
1304 // Three register operands: (Rn=0b1111 Conditional Move) Rs Ro(TIED_TO) Rm
1306 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
1307 // register with shift forms: (Rm, ConstantShiftSpecifier).
1308 // Constant shift specifier: Imm = (ShOp | ShAmt<<3).
1310 // There are special instructions, like t2MOVsra_flag and t2MOVsrl_flag, which
1311 // only require two register operands: Rd, Rm in ARM Reference Manual terms, and
1312 // nothing else, because the shift amount is already specified.
1313 // Similar case holds for t2MOVrx, t2ADDrr, ..., etc.
1314 static bool DisassembleThumb2DPSoReg(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
1315 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1317 const TargetInstrDesc
&TID
= ARMInsts
[Opcode
];
1318 const TargetOperandInfo
*OpInfo
= TID
.OpInfo
;
1319 unsigned &OpIdx
= NumOpsAdded
;
1321 // Special case handling.
1322 if (Opcode
== ARM::t2BR_JT
) {
1324 && OpInfo
[0].RegClass
== ARM::GPRRegClassID
1325 && OpInfo
[1].RegClass
== ARM::GPRRegClassID
1326 && OpInfo
[2].RegClass
< 0
1327 && OpInfo
[3].RegClass
< 0
1328 && "Exactly 4 operands expect and first two as reg operands");
1329 // Only need to populate the src reg operand.
1330 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1332 MI
.addOperand(MCOperand::CreateReg(0));
1333 MI
.addOperand(MCOperand::CreateImm(0));
1334 MI
.addOperand(MCOperand::CreateImm(0));
1342 && (OpInfo
[0].RegClass
== ARM::GPRRegClassID
||
1343 OpInfo
[0].RegClass
== ARM::rGPRRegClassID
)
1344 && (OpInfo
[1].RegClass
== ARM::GPRRegClassID
||
1345 OpInfo
[1].RegClass
== ARM::rGPRRegClassID
)
1346 && "Expect >= 2 operands and first two as reg operands");
1348 bool ThreeReg
= (NumOps
> 2 && (OpInfo
[2].RegClass
== ARM::GPRRegClassID
||
1349 OpInfo
[2].RegClass
== ARM::rGPRRegClassID
));
1350 bool NoDstReg
= (decodeRs(insn
) == 0xF);
1352 // Build the register operands, followed by the constant shift specifier.
1354 MI
.addOperand(MCOperand::CreateReg(
1355 getRegisterEnum(B
, OpInfo
[0].RegClass
,
1356 NoDstReg
? decodeRn(insn
) : decodeRs(insn
))));
1361 if ((Idx
= TID
.getOperandConstraint(OpIdx
, TOI::TIED_TO
)) != -1) {
1362 // Process tied_to operand constraint.
1363 MI
.addOperand(MI
.getOperand(Idx
));
1365 } else if (!NoDstReg
) {
1366 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, OpInfo
[1].RegClass
,
1370 DEBUG(errs() << "Thumb2 encoding error: d==15 for three-reg operands.\n");
1375 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, OpInfo
[OpIdx
].RegClass
,
1379 if (NumOps
== OpIdx
)
1382 if (OpInfo
[OpIdx
].RegClass
< 0 && !OpInfo
[OpIdx
].isPredicate()
1383 && !OpInfo
[OpIdx
].isOptionalDef()) {
1385 if (Thumb2ShiftOpcode(Opcode
))
1386 MI
.addOperand(MCOperand::CreateImm(getShiftAmtBits(insn
)));
1388 // Build the constant shift specifier operand.
1389 unsigned bits2
= getShiftTypeBits(insn
);
1390 unsigned imm5
= getShiftAmtBits(insn
);
1391 ARM_AM::ShiftOpc ShOp
= ARM_AM::no_shift
;
1392 unsigned ShAmt
= decodeImmShift(bits2
, imm5
, ShOp
);
1393 MI
.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp
, ShAmt
)));
1401 // A6.3.1 Data-processing (modified immediate)
1403 // Two register operands: Rs Rn ModImm
1404 // One register operands (Rs=0b1111 no explicit dest reg): Rn ModImm
1405 // One register operands (Rn=0b1111 no explicit src reg): Rs ModImm -
1408 // ModImm = ThumbExpandImm(i:imm3:imm8)
1409 static bool DisassembleThumb2DPModImm(MCInst
&MI
, unsigned Opcode
,
1410 uint32_t insn
, unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1412 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
1413 unsigned &OpIdx
= NumOpsAdded
;
1417 unsigned RdRegClassID
= OpInfo
[0].RegClass
;
1418 assert(NumOps
>= 2 && (RdRegClassID
== ARM::GPRRegClassID
||
1419 RdRegClassID
== ARM::rGPRRegClassID
)
1420 && "Expect >= 2 operands and first one as reg operand");
1422 unsigned RnRegClassID
= OpInfo
[1].RegClass
;
1423 bool TwoReg
= (RnRegClassID
== ARM::GPRRegClassID
1424 || RnRegClassID
== ARM::rGPRRegClassID
);
1425 bool NoDstReg
= (decodeRs(insn
) == 0xF);
1427 // Build the register operands, followed by the modified immediate.
1429 MI
.addOperand(MCOperand::CreateReg(
1430 getRegisterEnum(B
, RdRegClassID
,
1431 NoDstReg
? decodeRn(insn
) : decodeRs(insn
))));
1436 DEBUG(errs()<<"Thumb2 encoding error: d==15 for DPModImm 2-reg instr.\n");
1439 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, RnRegClassID
,
1444 // The modified immediate operand should come next.
1445 assert(OpIdx
< NumOps
&& OpInfo
[OpIdx
].RegClass
< 0 &&
1446 !OpInfo
[OpIdx
].isPredicate() && !OpInfo
[OpIdx
].isOptionalDef()
1447 && "Pure imm operand expected");
1450 // A6.3.2 Modified immediate constants in Thumb instructions
1451 unsigned imm12
= getIImm3Imm8(insn
);
1452 MI
.addOperand(MCOperand::CreateImm(ThumbExpandImm(imm12
)));
1458 static inline bool Thumb2SaturateOpcode(unsigned Opcode
) {
1460 case ARM::t2SSAT
: case ARM::t2SSAT16
:
1461 case ARM::t2USAT
: case ARM::t2USAT16
:
1468 /// DisassembleThumb2Sat - Disassemble Thumb2 saturate instructions:
1469 /// o t2SSAT, t2USAT: Rs sat_pos Rn shamt
1470 /// o t2SSAT16, t2USAT16: Rs sat_pos Rn
1471 static bool DisassembleThumb2Sat(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
1472 unsigned &NumOpsAdded
, BO B
) {
1473 const TargetInstrDesc
&TID
= ARMInsts
[Opcode
];
1474 NumOpsAdded
= TID
.getNumOperands() - 2; // ignore predicate operands
1476 // Disassemble the register def.
1477 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
1480 unsigned Pos
= slice(insn
, 4, 0);
1481 if (Opcode
== ARM::t2SSAT
|| Opcode
== ARM::t2SSAT16
)
1483 MI
.addOperand(MCOperand::CreateImm(Pos
));
1485 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
1488 if (NumOpsAdded
== 4) {
1489 ARM_AM::ShiftOpc Opc
= (slice(insn
, 21, 21) != 0 ?
1490 ARM_AM::asr
: ARM_AM::lsl
);
1491 // Inst{14-12:7-6} encodes the imm5 shift amount.
1492 unsigned ShAmt
= slice(insn
, 14, 12) << 2 | slice(insn
, 7, 6);
1494 if (Opc
== ARM_AM::asr
)
1497 Opc
= ARM_AM::no_shift
;
1499 MI
.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(Opc
, ShAmt
)));
1504 // A6.3.3 Data-processing (plain binary immediate)
1506 // o t2ADDri12, t2SUBri12: Rs Rn imm12
1507 // o t2LEApcrel (ADR): Rs imm12
1508 // o t2BFC (BFC): Rs Ro(TIED_TO) bf_inv_mask_imm
1509 // o t2BFI (BFI) (Currently not defined in LLVM as of Jan-07-2010)
1510 // o t2MOVi16: Rs imm16
1511 // o t2MOVTi16: Rs imm16
1512 // o t2SBFX (SBFX): Rs Rn lsb width
1513 // o t2UBFX (UBFX): Rs Rn lsb width
1514 // o t2BFI (BFI): Rs Rn lsb width
1515 static bool DisassembleThumb2DPBinImm(MCInst
&MI
, unsigned Opcode
,
1516 uint32_t insn
, unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1518 const TargetInstrDesc
&TID
= ARMInsts
[Opcode
];
1519 const TargetOperandInfo
*OpInfo
= TID
.OpInfo
;
1520 unsigned &OpIdx
= NumOpsAdded
;
1524 unsigned RdRegClassID
= OpInfo
[0].RegClass
;
1525 assert(NumOps
>= 2 && (RdRegClassID
== ARM::GPRRegClassID
||
1526 RdRegClassID
== ARM::rGPRRegClassID
)
1527 && "Expect >= 2 operands and first one as reg operand");
1529 unsigned RnRegClassID
= OpInfo
[1].RegClass
;
1530 bool TwoReg
= (RnRegClassID
== ARM::GPRRegClassID
1531 || RnRegClassID
== ARM::rGPRRegClassID
);
1533 // Build the register operand(s), followed by the immediate(s).
1535 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, RdRegClassID
,
1540 assert(NumOps
>= 3 && "Expect >= 3 operands");
1542 if ((Idx
= TID
.getOperandConstraint(OpIdx
, TOI::TIED_TO
)) != -1) {
1543 // Process tied_to operand constraint.
1544 MI
.addOperand(MI
.getOperand(Idx
));
1546 // Add src reg operand.
1547 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, RnRegClassID
,
1553 if (Opcode
== ARM::t2BFI
) {
1554 // Add val reg operand.
1555 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, RnRegClassID
,
1560 assert(OpInfo
[OpIdx
].RegClass
< 0 && !OpInfo
[OpIdx
].isPredicate()
1561 && !OpInfo
[OpIdx
].isOptionalDef()
1562 && "Pure imm operand expected");
1564 // Pre-increment OpIdx.
1567 if (Opcode
== ARM::t2ADDri12
|| Opcode
== ARM::t2SUBri12
1568 || Opcode
== ARM::t2LEApcrel
)
1569 MI
.addOperand(MCOperand::CreateImm(getIImm3Imm8(insn
)));
1570 else if (Opcode
== ARM::t2MOVi16
|| Opcode
== ARM::t2MOVTi16
)
1571 MI
.addOperand(MCOperand::CreateImm(getImm16(insn
)));
1572 else if (Opcode
== ARM::t2BFC
|| Opcode
== ARM::t2BFI
) {
1574 if (getBitfieldInvMask(insn
, mask
))
1575 MI
.addOperand(MCOperand::CreateImm(mask
));
1579 // Handle the case of: lsb width
1580 assert((Opcode
== ARM::t2SBFX
|| Opcode
== ARM::t2UBFX
)
1581 && "Unexpected opcode");
1582 MI
.addOperand(MCOperand::CreateImm(getLsb(insn
)));
1583 MI
.addOperand(MCOperand::CreateImm(getWidthMinus1(insn
) + 1));
1591 // A6.3.4 Table A6-15 Miscellaneous control instructions
1595 static inline bool t2MiscCtrlInstr(uint32_t insn
) {
1596 if (slice(insn
, 31, 20) == 0xf3b && slice(insn
, 15, 14) == 2 &&
1597 slice(insn
, 12, 12) == 0)
1603 // A6.3.4 Branches and miscellaneous control
1606 // Branches: t2B, t2Bcc -> imm operand
1608 // Branches: t2TPsoft -> no operand
1610 // A8.6.23 BL, BLX (immediate)
1611 // Branches (defined in ARMInstrThumb.td): tBLr9, tBLXi_r9 -> imm operand
1616 // Miscellaneous control: t2DMBsy (and its t2DMB variants),
1617 // t2DSBsy (and its t2DSB varianst), t2ISBsy, t2CLREX
1618 // -> no operand (except pred-imm pred-ccr for CLREX, memory barrier variants)
1620 // Hint: t2NOP, t2YIELD, t2WFE, t2WFI, t2SEV
1621 // -> no operand (except pred-imm pred-ccr)
1623 // t2DBG -> imm4 = Inst{3-0}
1625 // t2MRS/t2MRSsys -> Rs
1626 // t2MSR/t2MSRsys -> Rn mask=Inst{11-8}
1627 // t2SMC -> imm4 = Inst{19-16}
1628 static bool DisassembleThumb2BrMiscCtrl(MCInst
&MI
, unsigned Opcode
,
1629 uint32_t insn
, unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1634 if (t2MiscCtrlInstr(insn
))
1649 // CPS has a singleton $opt operand that contains the following information:
1650 // opt{4-0} = mode from Inst{4-0}
1651 // opt{5} = changemode from Inst{8}
1652 // opt{8-6} = AIF from Inst{7-5}
1653 // opt{10-9} = imod from Inst{10-9} with 0b10 as enable and 0b11 as disable
1654 if (Opcode
== ARM::t2CPS
) {
1655 unsigned Option
= slice(insn
, 4, 0) | slice(insn
, 8, 8) << 5 |
1656 slice(insn
, 7, 5) << 6 | slice(insn
, 10, 9) << 9;
1657 MI
.addOperand(MCOperand::CreateImm(Option
));
1662 // DBG has its option specified in Inst{3-0}.
1663 if (Opcode
== ARM::t2DBG
) {
1664 MI
.addOperand(MCOperand::CreateImm(slice(insn
, 3, 0)));
1669 // MRS and MRSsys take one GPR reg Rs.
1670 if (Opcode
== ARM::t2MRS
|| Opcode
== ARM::t2MRSsys
) {
1671 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1676 // BXJ takes one GPR reg Rn.
1677 if (Opcode
== ARM::t2BXJ
) {
1678 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1683 // MSR and MSRsys take one GPR reg Rn, followed by the mask.
1684 if (Opcode
== ARM::t2MSR
|| Opcode
== ARM::t2MSRsys
|| Opcode
== ARM::t2BXJ
) {
1685 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1687 MI
.addOperand(MCOperand::CreateImm(slice(insn
, 11, 8)));
1692 if (Opcode
== ARM::t2SMC
) {
1693 MI
.addOperand(MCOperand::CreateImm(slice(insn
, 19, 16)));
1698 // Add the imm operand.
1703 assert(0 && "Unexpected opcode");
1706 Offset
= decodeImm32_B_EncodingT4(insn
);
1709 Offset
= decodeImm32_B_EncodingT3(insn
);
1712 Offset
= decodeImm32_BL(insn
);
1715 Offset
= decodeImm32_BLX(insn
);
1718 // When executing a Thumb instruction, PC reads as the address of the current
1719 // instruction plus 4. The assembler subtracts 4 from the difference between
1720 // the branch instruction and the target address, disassembler has to add 4 to
1722 MI
.addOperand(MCOperand::CreateImm(Offset
+ 4));
1729 static inline bool Thumb2PreloadOpcode(unsigned Opcode
) {
1733 case ARM::t2PLDi12
: case ARM::t2PLDi8
: case ARM::t2PLDpci
:
1735 case ARM::t2PLDWi12
: case ARM::t2PLDWi8
: case ARM::t2PLDWpci
:
1737 case ARM::t2PLIi12
: case ARM::t2PLIi8
: case ARM::t2PLIpci
:
1743 static bool DisassembleThumb2PreLoad(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
1744 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1746 // Preload Data/Instruction requires either 2 or 3 operands.
1747 // t2PLDi12, t2PLDi8, t2PLDpci: Rn [+/-]imm12/imm8
1749 // t2PLDs: Rn Rm imm2=Inst{5-4}
1750 // Same pattern applies for t2PLDW* and t2PLI*.
1752 const TargetInstrDesc
&TID
= ARMInsts
[Opcode
];
1753 const TargetOperandInfo
*OpInfo
= TID
.OpInfo
;
1754 unsigned &OpIdx
= NumOpsAdded
;
1758 assert(NumOps
>= 2 &&
1759 OpInfo
[0].RegClass
== ARM::GPRRegClassID
&&
1760 "Expect >= 2 operands and first one as reg operand");
1762 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1766 if (OpInfo
[OpIdx
].RegClass
== ARM::GPRRegClassID
) {
1767 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1770 assert(OpInfo
[OpIdx
].RegClass
< 0 && !OpInfo
[OpIdx
].isPredicate()
1771 && !OpInfo
[OpIdx
].isOptionalDef()
1772 && "Pure imm operand expected");
1774 if (Opcode
== ARM::t2PLDpci
|| Opcode
== ARM::t2PLDWpci
||
1775 Opcode
== ARM::t2PLIpci
) {
1776 bool Negative
= slice(insn
, 23, 23) == 0;
1777 unsigned Imm12
= getImm12(insn
);
1778 Offset
= Negative
? -1 - Imm12
: 1 * Imm12
;
1779 } else if (Opcode
== ARM::t2PLDi8
|| Opcode
== ARM::t2PLDWi8
||
1780 Opcode
== ARM::t2PLIi8
) {
1781 // A8.6.117 Encoding T2: add = FALSE
1782 unsigned Imm8
= getImm8(insn
);
1784 } else // The i12 forms. See, for example, A8.6.117 Encoding T1.
1785 Offset
= decodeImm12(insn
);
1786 MI
.addOperand(MCOperand::CreateImm(Offset
));
1790 if (OpIdx
< NumOps
&& OpInfo
[OpIdx
].RegClass
< 0 &&
1791 !OpInfo
[OpIdx
].isPredicate() && !OpInfo
[OpIdx
].isOptionalDef()) {
1792 // Fills in the shift amount for t2PLDs, t2PLDWs, t2PLIs.
1793 MI
.addOperand(MCOperand::CreateImm(slice(insn
, 5, 4)));
1800 // A8.6.63 LDRB (literal)
1801 // A8.6.79 LDRSB (literal)
1802 // A8.6.75 LDRH (literal)
1803 // A8.6.83 LDRSH (literal)
1804 // A8.6.59 LDR (literal)
1806 // These instrs calculate an address from the PC value and an immediate offset.
1807 // Rd Rn=PC (+/-)imm12 (+ if Inst{23} == 0b1)
1808 static bool DisassembleThumb2Ldpci(MCInst
&MI
, unsigned Opcode
,
1809 uint32_t insn
, unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1811 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
1812 if (!OpInfo
) return false;
1814 assert(NumOps
>= 2 &&
1815 OpInfo
[0].RegClass
== ARM::GPRRegClassID
&&
1816 OpInfo
[1].RegClass
< 0 &&
1817 "Expect >= 2 operands, first as reg, and second as imm operand");
1819 // Build the register operand, followed by the (+/-)imm12 immediate.
1821 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1824 MI
.addOperand(MCOperand::CreateImm(decodeImm12(insn
)));
1831 // A6.3.10 Store single data item
1832 // A6.3.9 Load byte, memory hints
1833 // A6.3.8 Load halfword, memory hints
1838 // t2LDRi12: Rd Rn (+)imm12
1839 // t2LDRi8: Rd Rn (+/-)imm8 (+ if Inst{9} == 0b1)
1840 // t2LDRs: Rd Rn Rm ConstantShiftSpecifier (see also
1841 // DisassembleThumb2DPSoReg)
1842 // t2LDR_POST: Rd Rn Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
1843 // t2LDR_PRE: Rd Rn Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
1845 // t2STRi12: Rd Rn (+)imm12
1846 // t2STRi8: Rd Rn (+/-)imm8 (+ if Inst{9} == 0b1)
1847 // t2STRs: Rd Rn Rm ConstantShiftSpecifier (see also
1848 // DisassembleThumb2DPSoReg)
1849 // t2STR_POST: Rn Rd Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
1850 // t2STR_PRE: Rn Rd Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
1852 // Note that for indexed modes, the Rn(TIED_TO) operand needs to be populated
1853 // correctly, as LLVM AsmPrinter depends on it. For indexed stores, the first
1854 // operand is Rn; for all the other instructions, Rd is the first operand.
1856 // Delegates to DisassembleThumb2PreLoad() for preload data/instruction.
1857 // Delegates to DisassembleThumb2Ldpci() for load * literal operations.
1858 static bool DisassembleThumb2LdSt(bool Load
, MCInst
&MI
, unsigned Opcode
,
1859 uint32_t insn
, unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1861 unsigned Rn
= decodeRn(insn
);
1863 if (Thumb2PreloadOpcode(Opcode
))
1864 return DisassembleThumb2PreLoad(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
1866 // See, for example, A6.3.7 Load word: Table A6-18 Load word.
1867 if (Load
&& Rn
== 15)
1868 return DisassembleThumb2Ldpci(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
1870 const TargetInstrDesc
&TID
= ARMInsts
[Opcode
];
1871 const TargetOperandInfo
*OpInfo
= TID
.OpInfo
;
1872 unsigned &OpIdx
= NumOpsAdded
;
1876 assert(NumOps
>= 3 &&
1877 OpInfo
[0].RegClass
== ARM::GPRRegClassID
&&
1878 OpInfo
[1].RegClass
== ARM::GPRRegClassID
&&
1879 "Expect >= 3 operands and first two as reg operands");
1881 bool ThreeReg
= (OpInfo
[2].RegClass
== ARM::GPRRegClassID
);
1882 bool TIED_TO
= ThreeReg
&& TID
.getOperandConstraint(2, TOI::TIED_TO
) != -1;
1883 bool Imm12
= !ThreeReg
&& slice(insn
, 23, 23) == 1; // ARMInstrThumb2.td
1885 // Build the register operands, followed by the immediate.
1886 unsigned R0
, R1
, R2
= 0;
1887 unsigned Rd
= decodeRd(insn
);
1890 if (!Load
&& TIED_TO
) {
1900 Imm
= decodeImm8(insn
);
1902 R2
= decodeRm(insn
);
1903 // See, for example, A8.6.64 LDRB (register).
1904 // And ARMAsmPrinter::printT2AddrModeSoRegOperand().
1905 // LSL is the default shift opc, and LLVM does not expect it to be encoded
1906 // as part of the immediate operand.
1907 // Imm = ARM_AM::getSORegOpc(ARM_AM::lsl, slice(insn, 5, 4));
1908 Imm
= slice(insn
, 5, 4);
1912 Imm
= getImm12(insn
);
1914 Imm
= decodeImm8(insn
);
1917 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1920 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1925 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::GPRRegClassID
,
1930 assert(OpInfo
[OpIdx
].RegClass
< 0 && !OpInfo
[OpIdx
].isPredicate()
1931 && !OpInfo
[OpIdx
].isOptionalDef()
1932 && "Pure imm operand expected");
1934 MI
.addOperand(MCOperand::CreateImm(Imm
));
1940 // A6.3.12 Data-processing (register)
1942 // Two register operands [rotate]: Rs Rm [rotation(= (rotate:'000'))]
1943 // Three register operands only: Rs Rn Rm
1944 // Three register operands [rotate]: Rs Rn Rm [rotation(= (rotate:'000'))]
1946 // Parallel addition and subtraction 32-bit Thumb instructions: Rs Rn Rm
1948 // Miscellaneous operations: Rs [Rn] Rm
1949 static bool DisassembleThumb2DPReg(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
1950 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
1952 const TargetInstrDesc
&TID
= ARMInsts
[Opcode
];
1953 const TargetOperandInfo
*OpInfo
= TID
.OpInfo
;
1954 unsigned &OpIdx
= NumOpsAdded
;
1958 assert(NumOps
>= 2 &&
1959 OpInfo
[0].RegClass
== ARM::rGPRRegClassID
&&
1960 OpInfo
[1].RegClass
== ARM::rGPRRegClassID
&&
1961 "Expect >= 2 operands and first two as reg operands");
1963 // Build the register operands, followed by the optional rotation amount.
1965 bool ThreeReg
= NumOps
> 2 && OpInfo
[2].RegClass
== ARM::rGPRRegClassID
;
1967 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
1972 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
1977 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
1981 if (OpIdx
< NumOps
&& OpInfo
[OpIdx
].RegClass
< 0
1982 && !OpInfo
[OpIdx
].isPredicate() && !OpInfo
[OpIdx
].isOptionalDef()) {
1983 // Add the rotation amount immediate.
1984 MI
.addOperand(MCOperand::CreateImm(decodeRotate(insn
)));
1991 // A6.3.16 Multiply, multiply accumulate, and absolute difference
1993 // t2MLA, t2MLS, t2SMMLA, t2SMMLS: Rs Rn Rm Ra=Inst{15-12}
1994 // t2MUL, t2SMMUL: Rs Rn Rm
1995 // t2SMLA[BB|BT|TB|TT|WB|WT]: Rs Rn Rm Ra=Inst{15-12}
1996 // t2SMUL[BB|BT|TB|TT|WB|WT]: Rs Rn Rm
1998 // Dual halfword multiply: t2SMUAD[X], t2SMUSD[X], t2SMLAD[X], t2SMLSD[X]:
1999 // Rs Rn Rm Ra=Inst{15-12}
2001 // Unsigned Sum of Absolute Differences [and Accumulate]
2002 // Rs Rn Rm [Ra=Inst{15-12}]
2003 static bool DisassembleThumb2Mul(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
2004 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
2006 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
2008 assert(NumOps
>= 3 &&
2009 OpInfo
[0].RegClass
== ARM::rGPRRegClassID
&&
2010 OpInfo
[1].RegClass
== ARM::rGPRRegClassID
&&
2011 OpInfo
[2].RegClass
== ARM::rGPRRegClassID
&&
2012 "Expect >= 3 operands and first three as reg operands");
2014 // Build the register operands.
2016 bool FourReg
= NumOps
> 3 && OpInfo
[3].RegClass
== ARM::rGPRRegClassID
;
2018 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
2021 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
2024 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
2028 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
2031 NumOpsAdded
= FourReg
? 4 : 3;
2036 // A6.3.17 Long multiply, long multiply accumulate, and divide
2038 // t2SMULL, t2UMULL, t2SMLAL, t2UMLAL, t2UMAAL: RdLo RdHi Rn Rm
2039 // where RdLo = Inst{15-12} and RdHi = Inst{11-8}
2041 // Halfword multiple accumulate long: t2SMLAL<x><y>: RdLo RdHi Rn Rm
2042 // where RdLo = Inst{15-12} and RdHi = Inst{11-8}
2044 // Dual halfword multiple: t2SMLALD[X], t2SMLSLD[X]: RdLo RdHi Rn Rm
2045 // where RdLo = Inst{15-12} and RdHi = Inst{11-8}
2047 // Signed/Unsigned divide: t2SDIV, t2UDIV: Rs Rn Rm
2048 static bool DisassembleThumb2LongMul(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
2049 unsigned short NumOps
, unsigned &NumOpsAdded
, BO B
) {
2051 const TargetOperandInfo
*OpInfo
= ARMInsts
[Opcode
].OpInfo
;
2053 assert(NumOps
>= 3 &&
2054 OpInfo
[0].RegClass
== ARM::rGPRRegClassID
&&
2055 OpInfo
[1].RegClass
== ARM::rGPRRegClassID
&&
2056 OpInfo
[2].RegClass
== ARM::rGPRRegClassID
&&
2057 "Expect >= 3 operands and first three as reg operands");
2059 bool FourReg
= NumOps
> 3 && OpInfo
[3].RegClass
== ARM::rGPRRegClassID
;
2061 // Build the register operands.
2064 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
2067 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
2070 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
2073 MI
.addOperand(MCOperand::CreateReg(getRegisterEnum(B
, ARM::rGPRRegClassID
,
2084 // See A6.3 32-bit Thumb instruction encoding for instruction classes
2085 // corresponding to (op1, op2, op).
2087 // Table A6-9 32-bit Thumb instruction encoding
2088 // op1 op2 op Instruction class, see
2089 // --- ------- -- -----------------------------------------------------------
2090 // 01 00xx0xx - Load/store multiple on page A6-23
2091 // 00xx1xx - Load/store dual, load/store exclusive, table branch on
2093 // 01xxxxx - Data-processing (shifted register) on page A6-31
2094 // 1xxxxxx - Coprocessor instructions on page A6-40
2095 // 10 x0xxxxx 0 Data-processing (modified immediate) on page A6-15
2096 // x1xxxxx 0 Data-processing (plain binary immediate) on page A6-19
2097 // - 1 Branches and miscellaneous control on page A6-20
2098 // 11 000xxx0 - Store single data item on page A6-30
2099 // 001xxx0 - Advanced SIMD element or structure load/store instructions
2101 // 00xx001 - Load byte, memory hints on page A6-28
2102 // 00xx011 - Load halfword, memory hints on page A6-26
2103 // 00xx101 - Load word on page A6-25
2104 // 00xx111 - UNDEFINED
2105 // 010xxxx - Data-processing (register) on page A6-33
2106 // 0110xxx - Multiply, multiply accumulate, and absolute difference on
2108 // 0111xxx - Long multiply, long multiply accumulate, and divide on
2110 // 1xxxxxx - Coprocessor instructions on page A6-40
2112 static bool DisassembleThumb2(uint16_t op1
, uint16_t op2
, uint16_t op
,
2113 MCInst
&MI
, unsigned Opcode
, uint32_t insn
, unsigned short NumOps
,
2114 unsigned &NumOpsAdded
, BO B
) {
2118 if (slice(op2
, 6, 5) == 0) {
2119 if (slice(op2
, 2, 2) == 0) {
2120 // Load/store multiple.
2121 return DisassembleThumb2LdStMul(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
2125 // Load/store dual, load/store exclusive, table branch, otherwise.
2126 assert(slice(op2
, 2, 2) == 1 && "Thumb2 encoding error!");
2127 if ((ARM::t2LDREX
<= Opcode
&& Opcode
<= ARM::t2LDREXH
) ||
2128 (ARM::t2STREX
<= Opcode
&& Opcode
<= ARM::t2STREXH
)) {
2129 // Load/store exclusive.
2130 return DisassembleThumb2LdStEx(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
2133 if (Opcode
== ARM::t2LDRDi8
||
2134 Opcode
== ARM::t2LDRD_PRE
|| Opcode
== ARM::t2LDRD_POST
||
2135 Opcode
== ARM::t2STRDi8
||
2136 Opcode
== ARM::t2STRD_PRE
|| Opcode
== ARM::t2STRD_POST
) {
2138 return DisassembleThumb2LdStDual(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
2141 if (Opcode
== ARM::t2TBBgen
|| Opcode
== ARM::t2TBHgen
) {
2143 return DisassembleThumb2TB(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
2145 } else if (slice(op2
, 6, 5) == 1) {
2146 // Data-processing (shifted register).
2147 return DisassembleThumb2DPSoReg(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
2150 // FIXME: A6.3.18 Coprocessor instructions
2151 // But see ThumbDisassembler::getInstruction().
2156 if (slice(op2
, 5, 5) == 0)
2157 // Data-processing (modified immediate)
2158 return DisassembleThumb2DPModImm(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
2160 if (Thumb2SaturateOpcode(Opcode
))
2161 return DisassembleThumb2Sat(MI
, Opcode
, insn
, NumOpsAdded
, B
);
2163 // Data-processing (plain binary immediate)
2164 return DisassembleThumb2DPBinImm(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
2167 // Branches and miscellaneous control on page A6-20.
2168 return DisassembleThumb2BrMiscCtrl(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
2171 switch (slice(op2
, 6, 5)) {
2173 // Load/store instructions...
2174 if (slice(op2
, 0, 0) == 0) {
2175 if (slice(op2
, 4, 4) == 0) {
2176 // Store single data item on page A6-30
2177 return DisassembleThumb2LdSt(false, MI
,Opcode
,insn
,NumOps
,NumOpsAdded
,
2180 // FIXME: Advanced SIMD element or structure load/store instructions.
2181 // But see ThumbDisassembler::getInstruction().
2185 // Table A6-9 32-bit Thumb instruction encoding: Load byte|halfword|word
2186 return DisassembleThumb2LdSt(true, MI
, Opcode
, insn
, NumOps
,
2191 if (slice(op2
, 4, 4) == 0) {
2192 // A6.3.12 Data-processing (register)
2193 return DisassembleThumb2DPReg(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
2194 } else if (slice(op2
, 3, 3) == 0) {
2195 // A6.3.16 Multiply, multiply accumulate, and absolute difference
2196 return DisassembleThumb2Mul(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
, B
);
2198 // A6.3.17 Long multiply, long multiply accumulate, and divide
2199 return DisassembleThumb2LongMul(MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
2204 // FIXME: A6.3.18 Coprocessor instructions
2205 // But see ThumbDisassembler::getInstruction().
2212 assert(0 && "Thumb2 encoding error!");
2219 static bool DisassembleThumbFrm(MCInst
&MI
, unsigned Opcode
, uint32_t insn
,
2220 unsigned short NumOps
, unsigned &NumOpsAdded
, BO Builder
) {
2222 uint16_t HalfWord
= slice(insn
, 31, 16);
2224 if (HalfWord
== 0) {
2225 // A6.2 16-bit Thumb instruction encoding
2227 uint16_t op
= slice(insn
, 15, 10);
2228 return DisassembleThumb1(op
, MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,
2232 unsigned bits15_11
= slice(HalfWord
, 15, 11);
2234 // A6.1 Thumb instruction set encoding
2235 if (!(bits15_11
== 0x1D || bits15_11
== 0x1E || bits15_11
== 0x1F)) {
2236 assert("Bits[15:11] first halfword of Thumb2 instruction is out of range");
2240 // A6.3 32-bit Thumb instruction encoding
2242 uint16_t op1
= slice(HalfWord
, 12, 11);
2243 uint16_t op2
= slice(HalfWord
, 10, 4);
2244 uint16_t op
= slice(insn
, 15, 15);
2246 return DisassembleThumb2(op1
, op2
, op
, MI
, Opcode
, insn
, NumOps
, NumOpsAdded
,