Second of a three-patch series aiming to fix MSR/MRS on Cortex-M. This adds predicate checking to the Disassembler.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139250 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
James Molloy 2011-09-07 19:42:28 +00:00
parent 2c207a0f67
commit a5d5856854
17 changed files with 99 additions and 37 deletions

View File

@ -97,6 +97,7 @@ static bool Check(DecodeStatus &Out, DecodeStatus In) {
return false;
}
// Forward declare these because the autogenerated code will reference them.
// Definitions are further down.
static DecodeStatus DecodeGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
@ -319,6 +320,9 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
raw_ostream &os) const {
uint8_t bytes[4];
assert(!(STI.getFeatureBits() & ARM::ModeThumb) &&
"Asked to disassemble an ARM instruction but Subtarget is in Thumb mode!");
// We want to read exactly 4 bytes of data.
if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1) {
Size = 0;
@ -332,7 +336,7 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
(bytes[0] << 0);
// Calling the auto-generated decoder function.
DecodeStatus result = decodeARMInstruction32(MI, insn, Address, this);
DecodeStatus result = decodeARMInstruction32(MI, insn, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
return result;
@ -342,7 +346,7 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
// FIXME: This shouldn't really exist. It's an artifact of the
// fact that we fail to encode a few instructions properly for Thumb.
MI.clear();
result = decodeCommonInstruction32(MI, insn, Address, this);
result = decodeCommonInstruction32(MI, insn, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
return result;
@ -351,14 +355,14 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
// VFP and NEON instructions, similarly, are shared between ARM
// and Thumb modes.
MI.clear();
result = decodeVFPInstruction32(MI, insn, Address, this);
result = decodeVFPInstruction32(MI, insn, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
return result;
}
MI.clear();
result = decodeNEONDataInstruction32(MI, insn, Address, this);
result = decodeNEONDataInstruction32(MI, insn, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
// Add a fake predicate operand, because we share these instruction
@ -369,7 +373,7 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
}
MI.clear();
result = decodeNEONLoadStoreInstruction32(MI, insn, Address, this);
result = decodeNEONLoadStoreInstruction32(MI, insn, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
// Add a fake predicate operand, because we share these instruction
@ -380,7 +384,7 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
}
MI.clear();
result = decodeNEONDupInstruction32(MI, insn, Address, this);
result = decodeNEONDupInstruction32(MI, insn, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
// Add a fake predicate operand, because we share these instruction
@ -505,6 +509,9 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
raw_ostream &os) const {
uint8_t bytes[4];
assert((STI.getFeatureBits() & ARM::ModeThumb) &&
"Asked to disassemble in Thumb mode but Subtarget is in ARM mode!");
// We want to read exactly 2 bytes of data.
if (Region.readBytes(Address, 2, (uint8_t*)bytes, NULL) == -1) {
Size = 0;
@ -512,7 +519,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
}
uint16_t insn16 = (bytes[1] << 8) | bytes[0];
DecodeStatus result = decodeThumbInstruction16(MI, insn16, Address, this);
DecodeStatus result = decodeThumbInstruction16(MI, insn16, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 2;
AddThumbPredicate(MI);
@ -520,7 +527,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
}
MI.clear();
result = decodeThumbSBitInstruction16(MI, insn16, Address, this);
result = decodeThumbSBitInstruction16(MI, insn16, Address, this, STI);
if (result) {
Size = 2;
bool InITBlock = !ITBlock.empty();
@ -530,7 +537,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
}
MI.clear();
result = decodeThumb2Instruction16(MI, insn16, Address, this);
result = decodeThumb2Instruction16(MI, insn16, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 2;
AddThumbPredicate(MI);
@ -570,7 +577,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
(bytes[1] << 24) |
(bytes[0] << 16);
MI.clear();
result = decodeThumbInstruction32(MI, insn32, Address, this);
result = decodeThumbInstruction32(MI, insn32, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
bool InITBlock = ITBlock.size();
@ -580,7 +587,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
}
MI.clear();
result = decodeThumb2Instruction32(MI, insn32, Address, this);
result = decodeThumb2Instruction32(MI, insn32, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
AddThumbPredicate(MI);
@ -588,7 +595,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
}
MI.clear();
result = decodeCommonInstruction32(MI, insn32, Address, this);
result = decodeCommonInstruction32(MI, insn32, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
AddThumbPredicate(MI);
@ -596,7 +603,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
}
MI.clear();
result = decodeVFPInstruction32(MI, insn32, Address, this);
result = decodeVFPInstruction32(MI, insn32, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
UpdateThumbVFPPredicate(MI);
@ -604,7 +611,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
}
MI.clear();
result = decodeNEONDupInstruction32(MI, insn32, Address, this);
result = decodeNEONDupInstruction32(MI, insn32, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
AddThumbPredicate(MI);
@ -616,7 +623,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
uint32_t NEONLdStInsn = insn32;
NEONLdStInsn &= 0xF0FFFFFF;
NEONLdStInsn |= 0x04000000;
result = decodeNEONLoadStoreInstruction32(MI, NEONLdStInsn, Address, this);
result = decodeNEONLoadStoreInstruction32(MI, NEONLdStInsn, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
AddThumbPredicate(MI);
@ -630,7 +637,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
NEONDataInsn &= 0xF0FFFFFF; // Clear bits 27-24
NEONDataInsn |= (NEONDataInsn & 0x10000000) >> 4; // Move bit 28 to bit 24
NEONDataInsn |= 0x12000000; // Set bits 28 and 25
result = decodeNEONDataInstruction32(MI, NEONDataInsn, Address, this);
result = decodeNEONDataInstruction32(MI, NEONDataInsn, Address, this, STI);
if (result != MCDisassembler::Fail) {
Size = 4;
AddThumbPredicate(MI);

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 | FileCheck %s
# RUN: llvm-mc --disassemble %s -triple=armv7-apple-darwin9 -mattr +mp | FileCheck %s
# CHECK: addpl r4, pc, #318767104
0x4c 0x45 0x8f 0x52

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 |& grep {invalid instruction encoding}
# XFAIL: *
# Opcode=1930 Name=t2LDRD_PRE Format=ARM_FORMAT_THUMBFRM(25)

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# RUN: llvm-mc --disassemble %s -triple=armv7-apple-darwin9 |& grep {invalid instruction encoding}
# XFAIL: *
# Opcode=737 Name=VLD1DUPq8_UPD Format=ARM_FORMAT_NLdSt(30)

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# RUN: llvm-mc --disassemble %s -triple=armv7-apple-darwin9 |& grep {invalid instruction encoding}
# XFAIL: *
# Opcode=1225 Name=VQADDsv16i8 Format=ARM_FORMAT_N3Reg(37)

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# RUN: llvm-mc --disassemble %s -triple=armv7-apple-darwin9 |& grep {invalid instruction encoding}
# XFAIL: *
# Opcode=1641 Name=VST2b32_UPD Format=ARM_FORMAT_NLdSt(30)

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 |& grep {invalid instruction encoding}
# XFAIL: *
# Opcode=1934 Name=t2LDREXD Format=ARM_FORMAT_THUMBFRM(25)

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 |& grep {invalid instruction encoding}
# XFAIL: *
# Opcode=2124 Name=t2STRD_PRE Format=ARM_FORMAT_THUMBFRM(25)

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 |& grep {invalid instruction encoding}
# XFAIL: *
# Opcode=2127 Name=t2STREXB Format=ARM_FORMAT_THUMBFRM(25)

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 | FileCheck %s
# RUN: llvm-mc --disassemble %s -triple=armv7-apple-darwin9 | FileCheck %s
# CHECK: vbif q15, q7, q0
0x50 0xe1 0x7e 0xf3

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc -triple armv7-unknown-unknown -disassemble < %s | FileCheck %s
# RUN: llvm-mc -triple armv7-unknown-unknown -disassemble -mattr +fp16 < %s | FileCheck %s
0x20 0x03 0xf1 0xf3
# CHECK: vabs.s8 d16, d16

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc -triple thumbv7-unknown-unknown -disassemble < %s | FileCheck %s
# RUN: llvm-mc -triple thumbv7-unknown-unknown -disassemble -mattr +fp16 < %s | FileCheck %s
0xf1 0xff 0x20 0x03
# CHECK: vabs.s8 d16, d16

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 | FileCheck %s
# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 | FileCheck %s
# CHECK: push {r0, r1, r2, r3}
# CHECK-NEXT: push {r4, r5, r7, lr}

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 | FileCheck %s
# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 -mattr +t2xtpk,+mp | FileCheck %s
# CHECK: add r5, sp, #68
0x11 0xad
@ -218,8 +218,11 @@
# CHECK: pld [r5, #30]
0x95 0xf8 0x1e 0xf0
# CHECK: stc2 p12, cr15, [r9], {137}
0x89 0xfc 0x89 0xfc
# Test disabled as it was originally checking for
# the ARM encoding of stc2, and thumb2 stc2 is
# not implemented yet.
# CHECK-: stc2 p12, cr15, [r9], {137}
#0x89 0xfc 0x89 0xfc
# CHECK: vmov r1, r0, d11
0x50 0xec 0x1b 0x1b

View File

@ -132,11 +132,12 @@ void DisassemblerEmitter::run(raw_ostream &OS) {
if (Target.getName() == "ARM" ||
Target.getName() == "Thumb") {
FixedLenDecoderEmitter(Records,
"ARM",
"if (!Check(S, ", ")) return MCDisassembler::Fail;",
"S", "MCDisassembler::Fail",
"MCDisassembler::DecodeStatus S = MCDisassembler::Success;\n(void)S;").run(OS);
" MCDisassembler::DecodeStatus S = MCDisassembler::Success;\n(void)S;").run(OS);
return;
}
FixedLenDecoderEmitter(Records).run(OS);
FixedLenDecoderEmitter(Records, Target.getName()).run(OS);
}

View File

@ -330,6 +330,10 @@ protected:
std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals,
insn_t &Insn);
// Emits code to check the Predicates member of an instruction are true.
// Returns true if predicate matches were emitted, false otherwise.
bool emitPredicateMatch(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);
@ -571,8 +575,9 @@ void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation,
o.indent(Indentation) <<
"static MCDisassembler::DecodeStatus decode" << Namespace << "Instruction" << BitWidth
<< "(MCInst &MI, uint" << BitWidth << "_t insn, uint64_t Address, "
<< "const void *Decoder) {\n";
<< "const void *Decoder, const MCSubtargetInfo &STI) {\n";
o.indent(Indentation) << " unsigned tmp = 0;\n (void)tmp;\n" << Emitter->Locals << "\n";
o.indent(Indentation) << " unsigned Bits = STI.getFeatureBits();\n";
++Indentation; ++Indentation;
// Emits code to decode the instructions.
@ -757,6 +762,43 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
}
static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
std::string PredicateNamespace) {
const char *X = str.str().c_str();
if (X[0] == '!')
o << "!(Bits & " << PredicateNamespace << "::" << &X[1] << ")";
else
o << "(Bits & " << PredicateNamespace << "::" << X << ")";
}
bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
unsigned Opc) {
ListInit *Predicates = AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates");
for (unsigned i = 0; i < Predicates->getSize(); ++i) {
Record *Pred = Predicates->getElementAsRecord(i);
if (!Pred->getValue("AssemblerMatcherPredicate"))
continue;
std::string P = Pred->getValueAsString("AssemblerCondString");
if (!P.length())
continue;
if (i != 0)
o << " && ";
StringRef SR(P);
std::pair<StringRef, StringRef> pairs = SR.split(',');
while (pairs.second.size()) {
emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
o << " && ";
pairs = pairs.second.split(',');
}
emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
}
return Predicates->getSize() > 0;
}
// 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,
@ -775,7 +817,9 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
// If we have matched all the well-known bits, just issue a return.
if (Size == 0) {
o.indent(Indentation) << "{\n";
o.indent(Indentation) << "if (";
emitPredicateMatch(o, Indentation, Opc);
o << ") {\n";
o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n";
std::vector<OperandInfo>& InsnOperands = Operands[Opc];
for (std::vector<OperandInfo>::iterator
@ -792,7 +836,7 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc)
<< '\n';
o.indent(Indentation) << "}\n";
o.indent(Indentation) << "}\n"; // Closing predicate block.
return true;
}
@ -804,12 +848,16 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
for (I = Size; I != 0; --I) {
o << "Inst{" << EndBits[I-1] << '-' << StartBits[I-1] << "} ";
if (I > 1)
o << "&& ";
o << " && ";
else
o << "for singleton decoding...\n";
}
o.indent(Indentation) << "if (";
if (emitPredicateMatch(o, Indentation, Opc) > 0) {
o << " &&\n";
o.indent(Indentation+4);
}
for (I = Size; I != 0; --I) {
NumBits = EndBits[I-1] - StartBits[I-1] + 1;

View File

@ -50,6 +50,7 @@ struct OperandInfo {
class FixedLenDecoderEmitter : public TableGenBackend {
public:
FixedLenDecoderEmitter(RecordKeeper &R,
std::string PredicateNamespace,
std::string GPrefix = "if (",
std::string GPostfix = " == MCDisassembler::Fail) return MCDisassembler::Fail;",
std::string ROK = "MCDisassembler::Success",
@ -57,6 +58,7 @@ public:
std::string L = "") :
Records(R), Target(R),
NumberedInstructions(Target.getInstructionsByEnumValue()),
PredicateNamespace(PredicateNamespace),
GuardPrefix(GPrefix), GuardPostfix(GPostfix),
ReturnOK(ROK), ReturnFail(RFail), Locals(L) {}
@ -70,6 +72,7 @@ private:
std::vector<unsigned> Opcodes;
std::map<unsigned, std::vector<OperandInfo> > Operands;
public:
std::string PredicateNamespace;
std::string GuardPrefix, GuardPostfix;
std::string ReturnOK, ReturnFail;
std::string Locals;