mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-03 17:31:50 +00:00
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@150169 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f41ab77847
commit
3015dfb7d7
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
5
test/MC/Disassembler/ARM/unpredictables-thumb.txt
Normal file
5
test/MC/Disassembler/ARM/unpredictables-thumb.txt
Normal file
@ -0,0 +1,5 @@
|
||||
# RUN: llvm-mc --disassemble %s -triple=thumbv7 |& FileCheck %s
|
||||
|
||||
0x01 0x47
|
||||
# CHECK: 3:1: warning: potentially undefined
|
||||
# CHECK: bx r0
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user