aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Anderson <resistor@mac.com>2011-08-30 22:58:27 +0000
committerOwen Anderson <resistor@mac.com>2011-08-30 22:58:27 +0000
commiteaca928a3798e1fa7072457b94eccdd5b53b5d5f (patch)
treee789ff3f5a70d37138b8fb3cd4f61195a759c4c2
parent21df36c57afc588c8073a070a47e3ba45fa87270 (diff)
Fix issues with disassembly of IT instructions involving condition codes other the EQ/NE. Discovered by roundtrip testing.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138840 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td4
-rw-r--r--lib/Target/ARM/Disassembler/ARMDisassembler.cpp58
-rw-r--r--test/MC/Disassembler/ARM/thumb2.txt12
3 files changed, 44 insertions, 30 deletions
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index a7652f670a..e82e32186d 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -19,7 +19,6 @@ def it_pred_asmoperand : AsmOperandClass {
def it_pred : Operand<i32> {
let PrintMethod = "printMandatoryPredicateOperand";
let ParserMatchClass = it_pred_asmoperand;
- let DecoderMethod = "DecodeITCond";
}
// IT block condition mask
@@ -27,7 +26,6 @@ def it_mask_asmoperand : AsmOperandClass { let Name = "ITMask"; }
def it_mask : Operand<i32> {
let PrintMethod = "printThumbITMask";
let ParserMatchClass = it_mask_asmoperand;
- let DecoderMethod = "DecodeITMask";
}
// Shifted operands. No register controlled shifts for Thumb2.
@@ -3013,6 +3011,8 @@ def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask),
bits<4> mask;
let Inst{7-4} = cc;
let Inst{3-0} = mask;
+
+ let DecoderMethod = "DecodeIT";
}
// Branch and Exchange Jazelle -- for disassembly only
diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index c3ad2907c9..f4ca9ecc5d 100644
--- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -230,9 +230,7 @@ static DecodeStatus DecodeThumbBCCTargetOperand(llvm::MCInst &Inst,unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
-static DecodeStatus DecodeITCond(llvm::MCInst &Inst, unsigned Val,
- uint64_t Address, const void *Decoder);
-static DecodeStatus DecodeITMask(llvm::MCInst &Inst, unsigned Val,
+static DecodeStatus DecodeIT(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
#include "ARMGenDisassemblerTables.inc"
@@ -480,18 +478,20 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
// code and mask operands so that we can apply them correctly
// to the subsequent instructions.
if (MI.getOpcode() == ARM::t2IT) {
+ // (3 - the number of trailing zeros) is the number of then / else.
unsigned firstcond = MI.getOperand(0).getImm();
- uint32_t mask = MI.getOperand(1).getImm();
- unsigned zeros = CountTrailingZeros_32(mask);
- mask >>= zeros+1;
-
- for (unsigned i = 0; i < 4 - (zeros+1); ++i) {
- if (firstcond ^ (mask & 1))
- ITBlock.push_back(firstcond ^ 1);
+ unsigned Mask = MI.getOperand(1).getImm();
+ unsigned CondBit0 = Mask >> 4 & 1;
+ unsigned NumTZ = CountTrailingZeros_32(Mask);
+ assert(NumTZ <= 3 && "Invalid IT mask!");
+ for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
+ bool T = ((Mask >> Pos) & 1) == CondBit0;
+ if (T)
+ ITBlock.insert(ITBlock.begin(), firstcond);
else
- ITBlock.push_back(firstcond);
- mask >>= 1;
+ ITBlock.insert(ITBlock.begin(), firstcond ^ 1);
}
+
ITBlock.push_back(firstcond);
}
@@ -3109,7 +3109,7 @@ static DecodeStatus DecodeVLD3LN(llvm::MCInst &Inst, unsigned Insn,
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(align));
- if (Rm != 0xF) {
+ if (Rm != 0xF) {
if (Rm != 0xD)
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
else
@@ -3345,26 +3345,28 @@ static DecodeStatus DecodeVMOVRRS(llvm::MCInst &Inst, unsigned Insn,
return S;
}
-static DecodeStatus DecodeITCond(llvm::MCInst &Inst, unsigned Cond,
- uint64_t Address, const void *Decoder) {
+static DecodeStatus DecodeIT(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
- if (Cond == 0xF) {
- Cond = 0xE;
+ unsigned pred = fieldFromInstruction16(Insn, 4, 4);
+ // The InstPrinter needs to have the low bit of the predicate in
+ // the mask operand to be able to print it properly.
+ unsigned mask = fieldFromInstruction16(Insn, 0, 5);
+
+ if (pred == 0xF) {
+ pred = 0xE;
CHECK(S, Unpredictable);
}
- Inst.addOperand(MCOperand::CreateImm(Cond));
- return S;
-}
-
-static DecodeStatus DecodeITMask(llvm::MCInst &Inst, unsigned Mask,
- uint64_t Address, const void *Decoder) {
- DecodeStatus S = Success;
- if (Mask == 0) {
- Mask = 0x8;
+ if ((mask & 0xF) == 0) {
+ // Preserve the high bit of the mask, which is the low bit of
+ // the predicate.
+ mask &= 0x10;
+ mask |= 0x8;
CHECK(S, Unpredictable);
}
- Inst.addOperand(MCOperand::CreateImm(Mask));
+
+ Inst.addOperand(MCOperand::CreateImm(pred));
+ Inst.addOperand(MCOperand::CreateImm(mask));
return S;
}
-
diff --git a/test/MC/Disassembler/ARM/thumb2.txt b/test/MC/Disassembler/ARM/thumb2.txt
index 11171d83ef..c53910b4fc 100644
--- a/test/MC/Disassembler/ARM/thumb2.txt
+++ b/test/MC/Disassembler/ARM/thumb2.txt
@@ -39,3 +39,15 @@
0x00 0xbf
0xf5 0x1b
0x11 0x1d
+
+# CHECK: ittee ls
+# CHECK: addls r0, r1, r2
+# CHECK: nopls
+# CHECK: subhi r5, r6, r7
+# CHECK: addhi r1, r2, #4
+
+0x99 0xbf
+0x88 0x18
+0x00 0xbf
+0xf5 0x1b
+0x11 0x1d