From eaca928a3798e1fa7072457b94eccdd5b53b5d5f Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Tue, 30 Aug 2011 22:58:27 +0000 Subject: [PATCH] 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 --- lib/Target/ARM/ARMInstrThumb2.td | 4 +- .../ARM/Disassembler/ARMDisassembler.cpp | 58 ++++++++++--------- test/MC/Disassembler/ARM/thumb2.txt | 12 ++++ 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index a7652f670a9..e82e32186dd 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 { 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 { 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 c3ad2907c94..f4ca9ecc5d6 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 11171d83ef0..c53910b4fc8 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