diff options
| author | James Molloy <james.molloy@arm.com> | 2012-02-09 10:56:31 +0000 | 
|---|---|---|
| committer | James Molloy <james.molloy@arm.com> | 2012-02-09 10:56:31 +0000 | 
| commit | d9ba4fd48f4f801b2f1f8e8e7ef21409d95cf648 (patch) | |
| tree | c02c0353336fcfd417d7968efa396a95b1725391 /llvm | |
| parent | 7345626a5b86bc6c7ff2f86050ad255b16283f40 (diff) | |
| download | bcm5719-llvm-d9ba4fd48f4f801b2f1f8e8e7ef21409d95cf648.tar.gz bcm5719-llvm-d9ba4fd48f4f801b2f1f8e8e7ef21409d95cf648.zip  | |
Teach the MC and disassembler about SoftFail, and hook it up to UNPREDICTABLE on ARM. Wire this to tBLX in order to provide test coverage.
llvm-svn: 150169
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrFormats.td | 8 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb.td | 1 | ||||
| -rw-r--r-- | llvm/test/MC/Disassembler/ARM/unpredictables-thumb.txt | 5 | ||||
| -rw-r--r-- | llvm/utils/TableGen/FixedLenDecoderEmitter.cpp | 78 | 
4 files changed, 90 insertions, 2 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 0c10b01b6c7..81229f47790 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -290,6 +290,14 @@ class InstTemplate<AddrMode am, int sz, IndexMode im,  class Encoding {    field bits<32> Inst; +  // Mask of bits that cause an encoding to be UNPREDICTABLE. +  // If a bit is set, then if the corresponding bit in the +  // target encoding differs from its value in the "Inst" field, +  // the instruction is UNPREDICTABLE (SoftFail in abstract parlance). +  field bits<32> Unpredictable = 0; +  // SoftFail is the generic name for this field, but we alias it so +  // as to make it more obvious what it means in ARM-land. +  field bits<32> SoftFail = Unpredictable;  }  class InstARM<AddrMode am, int sz, IndexMode im, diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index 30aa424343c..9bbf8e60320 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -387,6 +387,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {      bits<4> Rm;      let Inst{6-3} = Rm;      let Inst{2-0} = 0b000; +    let Unpredictable{2-0} = 0b111;    }  } diff --git a/llvm/test/MC/Disassembler/ARM/unpredictables-thumb.txt b/llvm/test/MC/Disassembler/ARM/unpredictables-thumb.txt new file mode 100644 index 00000000000..e7645f0a59e --- /dev/null +++ b/llvm/test/MC/Disassembler/ARM/unpredictables-thumb.txt @@ -0,0 +1,5 @@ +# RUN: llvm-mc --disassemble %s -triple=thumbv7 |& FileCheck %s + +0x01 0x47 +# CHECK: 3:1: warning: potentially undefined +# CHECK: bx r0 diff --git a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp index c0a0a80f1da..e0d9eb55e78 100644 --- a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -17,6 +17,7 @@  #include "FixedLenDecoderEmitter.h"  #include "CodeGenTarget.h"  #include "llvm/TableGen/Record.h" +#include "llvm/ADT/APInt.h"  #include "llvm/ADT/StringExtras.h"  #include "llvm/Support/Debug.h"  #include "llvm/Support/raw_ostream.h" @@ -285,8 +286,19 @@ protected:    void insnWithID(insn_t &Insn, unsigned Opcode) const {      BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst"); -    for (unsigned i = 0; i < BitWidth; ++i) -      Insn.push_back(bitFromBits(Bits, i)); +    // We may have a SoftFail bitmask, which specifies a mask where an encoding +    // may differ from the value in "Inst" and yet still be valid, but the +    // disassembler should return SoftFail instead of Success. +    // +    // This is used for marking UNPREDICTABLE instructions in the ARM world. +    BitsInit *SFBits = AllInstructions[Opcode]->TheDef->getValueAsBitsInit("SoftFail"); + +    for (unsigned i = 0; i < BitWidth; ++i) { +      if (SFBits && bitFromBits(*SFBits, i) == BIT_TRUE) +        Insn.push_back(BIT_UNSET); +      else +        Insn.push_back(bitFromBits(Bits, i)); +    }    }    // Returns the record name. @@ -334,6 +346,8 @@ protected:    // Returns true if predicate matches were emitted, false otherwise.    bool emitPredicateMatch(raw_ostream &o, unsigned &Indentation,unsigned Opc); +  void emitSoftFailCheck(raw_ostream &o, unsigned Indentation, unsigned Opc); +    // Emits code to decode the singleton.  Return true if we have matched all the    // well-known bits.    bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc); @@ -800,6 +814,64 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,    return Predicates->getSize() > 0;  } +void FilterChooser::emitSoftFailCheck(raw_ostream &o, unsigned Indentation, unsigned Opc) { +  BitsInit *SFBits = AllInstructions[Opc]->TheDef->getValueAsBitsInit("SoftFail"); +  if (!SFBits) return; +  BitsInit *InstBits = AllInstructions[Opc]->TheDef->getValueAsBitsInit("Inst"); + +  APInt PositiveMask(BitWidth, 0ULL); +  APInt NegativeMask(BitWidth, 0ULL); +  for (unsigned i = 0; i < BitWidth; ++i) { +    bit_value_t B = bitFromBits(*SFBits, i); +    bit_value_t IB = bitFromBits(*InstBits, i); + +    if (B != BIT_TRUE) continue; + +    switch (IB) { +    case BIT_FALSE: +      // The bit is meant to be false, so emit a check to see if it is true. +      PositiveMask.setBit(i); +      break; +    case BIT_TRUE: +      // The bit is meant to be true, so emit a check to see if it is false. +      NegativeMask.setBit(i); +      break; +    default: +      // The bit is not set; this must be an error! +      StringRef Name = AllInstructions[Opc]->TheDef->getName(); +      errs() << "SoftFail Conflict: bit SoftFail{" << i << "} in " +             << Name +             << " is set but Inst{" << i <<"} is unset!\n" +             << "  - You can only mark a bit as SoftFail if it is fully defined" +             << " (1/0 - not '?') in Inst\n"; +      o << "#error SoftFail Conflict, " << Name << "::SoftFail{" << i  +        << "} set but Inst{" << i << "} undefined!\n"; +    } +  } + +  bool NeedPositiveMask = PositiveMask.getBoolValue(); +  bool NeedNegativeMask = NegativeMask.getBoolValue(); + +  if (!NeedPositiveMask && !NeedNegativeMask) +    return; + +  std::string PositiveMaskStr = PositiveMask.toString(16, /*signed=*/false); +  std::string NegativeMaskStr = NegativeMask.toString(16, /*signed=*/false); +  StringRef BitExt = ""; +  if (BitWidth > 32) +    BitExt = "ULL"; + +  o.indent(Indentation) << "if ("; +  if (NeedPositiveMask) +    o << "insn & 0x" << PositiveMaskStr << BitExt; +  if (NeedPositiveMask && NeedNegativeMask) +    o << " || "; +  if (NeedNegativeMask) +    o << "~insn & 0x" << NegativeMaskStr << BitExt; +  o << ")\n"; +  o.indent(Indentation+2) << "S = MCDisassembler::SoftFail;\n"; +} +  // Emits code to decode the singleton.  Return true if we have matched all the  // well-known bits.  bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, @@ -822,6 +894,7 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,      if (!emitPredicateMatch(o, Indentation, Opc))        o << "1";      o << ") {\n"; +    emitSoftFailCheck(o, Indentation+2, Opc);      o.indent(Indentation) << "  MI.setOpcode(" << Opc << ");\n";      std::vector<OperandInfo>& InsnOperands = Operands[Opc];      for (std::vector<OperandInfo>::iterator @@ -871,6 +944,7 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,      else        o << ") {\n";    } +  emitSoftFailCheck(o, Indentation+2, Opc);    o.indent(Indentation) << "  MI.setOpcode(" << Opc << ");\n";    std::vector<OperandInfo>& InsnOperands = Operands[Opc];    for (std::vector<OperandInfo>::iterator  | 

