summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Target/ARM/ARMInstrThumb2.td1
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp83
-rw-r--r--llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp25
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp9
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp30
-rw-r--r--llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp4
6 files changed, 88 insertions, 64 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
index 1f7d28a4c8b..61e157ba986 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -25,6 +25,7 @@ def it_mask_asmoperand : AsmOperandClass { let Name = "ITMask"; }
def it_mask : Operand<i32> {
let PrintMethod = "printThumbITMask";
let ParserMatchClass = it_mask_asmoperand;
+ let EncoderMethod = "getITMaskOpValue";
}
// t2_shift_imm: An integer that encodes a shift amount and the type of shift
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index f8dc24a4267..1e9341182f3 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -90,6 +90,16 @@ static cl::opt<bool> AddBuildAttributes("arm-add-build-attributes",
enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
+static inline unsigned extractITMaskBit(unsigned Mask, unsigned Position) {
+ // Position==0 means we're not in an IT block at all. Position==1
+ // means we want the first state bit, which is always 0 (Then).
+ // Position==2 means we want the second state bit, stored at bit 3
+ // of Mask, and so on downwards. So (5 - Position) will shift the
+ // right bit down to bit 0, including the always-0 bit at bit 4 for
+ // the mandatory initial Then.
+ return (Mask >> (5 - Position) & 1);
+}
+
class UnwindContext {
using Locs = SmallVector<SMLoc, 4>;
@@ -226,11 +236,10 @@ class ARMAsmParser : public MCTargetAsmParser {
}
// Emit the IT instruction
- unsigned Mask = getITMaskEncoding();
MCInst ITInst;
ITInst.setOpcode(ARM::t2IT);
ITInst.addOperand(MCOperand::createImm(ITState.Cond));
- ITInst.addOperand(MCOperand::createImm(Mask));
+ ITInst.addOperand(MCOperand::createImm(ITState.Mask));
Out.EmitInstruction(ITInst, getSTI());
// Emit the conditonal instructions
@@ -288,27 +297,10 @@ class ARMAsmParser : public MCTargetAsmParser {
return MRI->getSubReg(QReg, ARM::dsub_0);
}
- // Get the encoding of the IT mask, as it will appear in an IT instruction.
- unsigned getITMaskEncoding() {
- assert(inITBlock());
- unsigned Mask = ITState.Mask;
- unsigned TZ = countTrailingZeros(Mask);
- if ((ITState.Cond & 1) == 0) {
- assert(Mask && TZ <= 3 && "illegal IT mask value!");
- Mask ^= (0xE << TZ) & 0xF;
- }
- return Mask;
- }
-
// Get the condition code corresponding to the current IT block slot.
ARMCC::CondCodes currentITCond() {
- unsigned MaskBit;
- if (ITState.CurPosition == 1)
- MaskBit = 1;
- else
- MaskBit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
-
- return MaskBit ? ITState.Cond : ARMCC::getOppositeCondition(ITState.Cond);
+ unsigned MaskBit = extractITMaskBit(ITState.Mask, ITState.CurPosition);
+ return MaskBit ? ARMCC::getOppositeCondition(ITState.Cond) : ITState.Cond;
}
// Invert the condition of the current IT block slot without changing any
@@ -338,7 +330,7 @@ class ARMAsmParser : public MCTargetAsmParser {
// Keep any existing condition bits.
NewMask |= ITState.Mask & (0xE << TZ);
// Insert the new condition bit.
- NewMask |= (Cond == ITState.Cond) << TZ;
+ NewMask |= (Cond != ITState.Cond) << TZ;
// Move the trailing 1 down one bit.
NewMask |= 1 << (TZ - 1);
ITState.Mask = NewMask;
@@ -353,9 +345,10 @@ class ARMAsmParser : public MCTargetAsmParser {
ITState.IsExplicit = false;
}
- // Create a new explicit IT block with the given condition and mask. The mask
- // should be in the parsed format, with a 1 implying 't', regardless of the
- // low bit of the condition.
+ // Create a new explicit IT block with the given condition and mask.
+ // The mask should be in the format used in ARMOperand and
+ // MCOperand, with a 1 implying 'e', regardless of the low bit of
+ // the condition.
void startExplicitITBlock(ARMCC::CondCodes Cond, unsigned Mask) {
assert(!inITBlock());
ITState.Cond = Cond;
@@ -3355,10 +3348,10 @@ void ARMOperand::print(raw_ostream &OS) const {
break;
case k_ITCondMask: {
static const char *const MaskStr[] = {
- "(invalid)", "(teee)", "(tee)", "(teet)",
- "(te)", "(tete)", "(tet)", "(tett)",
- "(t)", "(ttee)", "(tte)", "(ttet)",
- "(tt)", "(ttte)", "(ttt)", "(tttt)"
+ "(invalid)", "(tttt)", "(ttt)", "(ttte)",
+ "(tt)", "(ttet)", "(tte)", "(ttee)",
+ "(t)", "(tett)", "(tet)", "(tete)",
+ "(te)", "(teet)", "(tee)", "(teee)",
};
assert((ITMask.Mask & 0xf) == ITMask.Mask);
OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
@@ -6272,11 +6265,14 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
- // Handle the IT instruction ITMask. Convert it to a bitmask. This
- // is the mask as it will be for the IT encoding if the conditional
- // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
- // where the conditional bit0 is zero, the instruction post-processing
- // will adjust the mask accordingly.
+ // Handle the mask for IT instructions. In ARMOperand and MCOperand,
+ // this is stored in a format independent of the condition code: the
+ // lowest set bit indicates the end of the encoding, and above that,
+ // a 1 bit indicates 'else', and an 0 indicates 'then'. E.g.
+ // IT -> 1000
+ // ITx -> x100 (ITT -> 0100, ITE -> 1100)
+ // ITxy -> xy10 (e.g. ITET -> 1010)
+ // ITxyz -> xyz1 (e.g. ITEET -> 1101)
if (Mnemonic == "it") {
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
if (ITMask.size() > 3) {
@@ -6289,7 +6285,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
}
Mask >>= 1;
- if (ITMask[i - 1] == 't')
+ if (ITMask[i - 1] == 'e')
Mask |= 8;
}
Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
@@ -6681,11 +6677,10 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
unsigned Cond = Inst.getOperand(0).getImm();
unsigned Mask = Inst.getOperand(1).getImm();
- // Mask hasn't been modified to the IT instruction encoding yet so
- // conditions only allowing a 't' are a block of 1s starting at bit 3
- // followed by all 0s. Easiest way is to just list the 4 possibilities.
- if (Cond == ARMCC::AL && Mask != 8 && Mask != 12 && Mask != 14 &&
- Mask != 15)
+ // Conditions only allowing a 't' are those with no set bit except
+ // the lowest-order one that indicates the end of the sequence. In
+ // other words, powers of 2.
+ if (Cond == ARMCC::AL && countPopulation(Mask) != 1)
return Error(Loc, "unpredictable IT predicate sequence");
break;
}
@@ -9260,15 +9255,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst,
}
case ARM::ITasm:
case ARM::t2IT: {
- MCOperand &MO = Inst.getOperand(1);
- unsigned Mask = MO.getImm();
- ARMCC::CondCodes Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
-
// Set up the IT block state according to the IT instruction we just
// matched.
assert(!inITBlock() && "nested IT blocks?!");
- startExplicitITBlock(Cond, Mask);
- MO.setImm(getITMaskEncoding());
+ startExplicitITBlock(ARMCC::CondCodes(Inst.getOperand(0).getImm()),
+ Inst.getOperand(1).getImm());
break;
}
case ARM::t2LSLrr:
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index ef71cacfa92..bc9d5a0913f 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -63,22 +63,19 @@ namespace {
return ITStates.size() == 1;
}
- // Called when decoding an IT instruction. Sets the IT state for the following
- // instructions that for the IT block. Firstcond and Mask correspond to the
- // fields in the IT instruction encoding.
+ // Called when decoding an IT instruction. Sets the IT state for
+ // the following instructions that for the IT block. Firstcond
+ // corresponds to the field in the IT instruction encoding; Mask
+ // is in the MCOperand format in which 1 means 'else' and 0 'then'.
void setITState(char Firstcond, char Mask) {
// (3 - the number of trailing zeros) is the number of then / else.
- unsigned CondBit0 = Firstcond & 1;
unsigned NumTZ = countTrailingZeros<uint8_t>(Mask);
unsigned char CCBits = static_cast<unsigned char>(Firstcond & 0xf);
assert(NumTZ <= 3 && "Invalid IT mask!");
// push condition codes onto the stack the correct order for the pops
for (unsigned Pos = NumTZ+1; Pos <= 3; ++Pos) {
- bool T = ((Mask >> Pos) & 1) == CondBit0;
- if (T)
- ITStates.push_back(CCBits);
- else
- ITStates.push_back(CCBits ^ 1);
+ unsigned Else = (Mask >> Pos) & 1;
+ ITStates.push_back(CCBits ^ Else);
}
ITStates.push_back(CCBits);
}
@@ -5176,6 +5173,16 @@ static DecodeStatus DecodeIT(MCInst &Inst, unsigned Insn,
if (mask == 0x0)
return MCDisassembler::Fail;
+ // IT masks are encoded as a sequence of replacement low-order bits
+ // for the condition code. So if the low bit of the starting
+ // condition code is 1, then we have to flip all the bits above the
+ // terminating bit (which is the lowest 1 bit).
+ if (pred & 1) {
+ unsigned LowBit = mask & -mask;
+ unsigned BitsAboveLowBit = 0xF & (-LowBit << 1);
+ mask ^= BitsAboveLowBit;
+ }
+
Inst.addOperand(MCOperand::createImm(pred));
Inst.addOperand(MCOperand::createImm(mask));
return S;
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
index 271959c38de..52576840a5f 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
@@ -1039,16 +1039,13 @@ void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
// (3 - the number of trailing zeros) is the number of then / else.
unsigned Mask = MI->getOperand(OpNum).getImm();
- unsigned Firstcond = MI->getOperand(OpNum - 1).getImm();
- unsigned CondBit0 = Firstcond & 1;
unsigned NumTZ = countTrailingZeros(Mask);
assert(NumTZ <= 3 && "Invalid IT mask!");
for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
- bool T = ((Mask >> Pos) & 1) == CondBit0;
- if (T)
- O << 't';
- else
+ if ((Mask >> Pos) & 1)
O << 'e';
+ else
+ O << 't';
}
}
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
index e84fe35ee20..13dca6dc1de 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
@@ -162,6 +162,9 @@ public:
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ uint32_t getITMaskOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
/// operand.
@@ -829,6 +832,33 @@ getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
return Val;
}
+/// getITMaskOpValue - Return the architectural encoding of an IT
+/// predication mask, given the MCOperand format.
+uint32_t ARMMCCodeEmitter::
+getITMaskOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand MaskMO = MI.getOperand(OpIdx);
+ assert(MaskMO.isImm() && "Unexpected operand type!");
+
+ unsigned Mask = MaskMO.getImm();
+
+ // IT masks are encoded as a sequence of replacement low-order bits
+ // for the condition code. So if the low bit of the starting
+ // condition code is 1, then we have to flip all the bits above the
+ // terminating bit (which is the lowest 1 bit).
+ assert(OpIdx > 0 && "IT mask appears first!");
+ const MCOperand CondMO = MI.getOperand(OpIdx-1);
+ assert(CondMO.isImm() && "Unexpected operand type!");
+ if (CondMO.getImm() & 1) {
+ unsigned LowBit = Mask & -Mask;
+ unsigned BitsAboveLowBit = 0xF & (-LowBit << 1);
+ Mask ^= BitsAboveLowBit;
+ }
+
+ return Mask;
+}
+
/// getThumbAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label
/// target.
uint32_t ARMMCCodeEmitter::
diff --git a/llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp b/llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp
index 70c07f50b03..715ad743ab5 100644
--- a/llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp
+++ b/llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp
@@ -245,7 +245,7 @@ bool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) {
unsigned NPredReg = 0;
ARMCC::CondCodes NCC = getITInstrPredicate(*NMI, NPredReg);
if (NCC == CC || NCC == OCC) {
- Mask |= (NCC & 1) << Pos;
+ Mask |= ((NCC ^ CC) & 1) << Pos;
// Add implicit use of ITSTATE.
NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/,
true/*isImp*/, false/*isKill*/));
@@ -269,8 +269,6 @@ bool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) {
// Finalize IT mask.
Mask |= (1 << Pos);
- // Tag along (firstcond[0] << 4) with the mask.
- Mask |= (CC & 1) << 4;
MIB.addImm(Mask);
// Last instruction in IT block kills ITSTATE.
OpenPOWER on IntegriCloud