diff options
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb2.td | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 83 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 25 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp | 9 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp | 30 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp | 4 | 
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.  | 

