mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-14 14:24:05 +00:00
Allow the MCDisassembler to return a "soft fail" status code, indicating an instruction that is disassemblable, but invalid. Only used for ARM UNPREDICTABLE instructions at the moment.
Patch by James Molloy. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137830 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -25,6 +25,34 @@ struct EDInstInfo;
|
|||||||
/// and provides an array of assembly instructions.
|
/// and provides an array of assembly instructions.
|
||||||
class MCDisassembler {
|
class MCDisassembler {
|
||||||
public:
|
public:
|
||||||
|
/// Ternary decode status. Most backends will just use Fail and
|
||||||
|
/// Success, however some have a concept of an instruction with
|
||||||
|
/// understandable semantics but which is architecturally
|
||||||
|
/// incorrect. An example of this is ARM UNPREDICTABLE instructions
|
||||||
|
/// which are disassemblable but cause undefined behaviour.
|
||||||
|
///
|
||||||
|
/// Because it makes sense to disassemble these instructions, there
|
||||||
|
/// is a "soft fail" failure mode that indicates the MCInst& is
|
||||||
|
/// valid but architecturally incorrect.
|
||||||
|
///
|
||||||
|
/// The enum numbers are deliberately chosen such that reduction
|
||||||
|
/// from Success->SoftFail ->Fail can be done with a simple
|
||||||
|
/// bitwise-AND:
|
||||||
|
///
|
||||||
|
/// LEFT & TOP = | Success Unpredictable Fail
|
||||||
|
/// --------------+-----------------------------------
|
||||||
|
/// Success | Success Unpredictable Fail
|
||||||
|
/// Unpredictable | Unpredictable Unpredictable Fail
|
||||||
|
/// Fail | Fail Fail Fail
|
||||||
|
///
|
||||||
|
/// An easy way of encoding this is as 0b11, 0b01, 0b00 for
|
||||||
|
/// Success, SoftFail, Fail respectively.
|
||||||
|
enum DecodeStatus {
|
||||||
|
Fail = 0,
|
||||||
|
SoftFail = 1,
|
||||||
|
Success = 3
|
||||||
|
};
|
||||||
|
|
||||||
/// Constructor - Performs initial setup for the disassembler.
|
/// Constructor - Performs initial setup for the disassembler.
|
||||||
MCDisassembler() : GetOpInfo(0), DisInfo(0), Ctx(0) {}
|
MCDisassembler() : GetOpInfo(0), DisInfo(0), Ctx(0) {}
|
||||||
|
|
||||||
@ -41,8 +69,11 @@ public:
|
|||||||
/// @param address - The address, in the memory space of region, of the first
|
/// @param address - The address, in the memory space of region, of the first
|
||||||
/// byte of the instruction.
|
/// byte of the instruction.
|
||||||
/// @param vStream - The stream to print warnings and diagnostic messages on.
|
/// @param vStream - The stream to print warnings and diagnostic messages on.
|
||||||
/// @return - True if the instruction is valid; false otherwise.
|
/// @return - MCDisassembler::Success if the instruction is valid,
|
||||||
virtual bool getInstruction(MCInst& instr,
|
/// MCDisassembler::SoftFail if the instruction was
|
||||||
|
/// disassemblable but invalid,
|
||||||
|
/// MCDisassembler::Fail if the instruction was invalid.
|
||||||
|
virtual DecodeStatus getInstruction(MCInst& instr,
|
||||||
uint64_t& size,
|
uint64_t& size,
|
||||||
const MemoryObject ®ion,
|
const MemoryObject ®ion,
|
||||||
uint64_t address,
|
uint64_t address,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -40,11 +40,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// getInstruction - See MCDisassembler.
|
/// getInstruction - See MCDisassembler.
|
||||||
bool getInstruction(MCInst &instr,
|
DecodeStatus getInstruction(MCInst &instr,
|
||||||
uint64_t &size,
|
uint64_t &size,
|
||||||
const MemoryObject ®ion,
|
const MemoryObject ®ion,
|
||||||
uint64_t address,
|
uint64_t address,
|
||||||
raw_ostream &vStream) const;
|
raw_ostream &vStream) const;
|
||||||
|
|
||||||
/// getEDInfo - See MCDisassembler.
|
/// getEDInfo - See MCDisassembler.
|
||||||
EDInstInfo *getEDInfo() const;
|
EDInstInfo *getEDInfo() const;
|
||||||
@ -64,11 +64,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// getInstruction - See MCDisassembler.
|
/// getInstruction - See MCDisassembler.
|
||||||
bool getInstruction(MCInst &instr,
|
DecodeStatus getInstruction(MCInst &instr,
|
||||||
uint64_t &size,
|
uint64_t &size,
|
||||||
const MemoryObject ®ion,
|
const MemoryObject ®ion,
|
||||||
uint64_t address,
|
uint64_t address,
|
||||||
raw_ostream &vStream) const;
|
raw_ostream &vStream) const;
|
||||||
|
|
||||||
/// getEDInfo - See MCDisassembler.
|
/// getEDInfo - See MCDisassembler.
|
||||||
EDInstInfo *getEDInfo() const;
|
EDInstInfo *getEDInfo() const;
|
||||||
|
@ -493,7 +493,7 @@ EDInstInfo *MBlazeDisassembler::getEDInfo() const {
|
|||||||
// Public interface for the disassembler
|
// Public interface for the disassembler
|
||||||
//
|
//
|
||||||
|
|
||||||
bool MBlazeDisassembler::getInstruction(MCInst &instr,
|
MCDisassembler::DecodeStatus MBlazeDisassembler::getInstruction(MCInst &instr,
|
||||||
uint64_t &size,
|
uint64_t &size,
|
||||||
const MemoryObject ®ion,
|
const MemoryObject ®ion,
|
||||||
uint64_t address,
|
uint64_t address,
|
||||||
@ -508,7 +508,7 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
|
|||||||
|
|
||||||
// We want to read exactly 4 bytes of data.
|
// We want to read exactly 4 bytes of data.
|
||||||
if (region.readBytes(address, 4, (uint8_t*)bytes, &read) == -1 || read < 4)
|
if (region.readBytes(address, 4, (uint8_t*)bytes, &read) == -1 || read < 4)
|
||||||
return false;
|
return Fail;
|
||||||
|
|
||||||
// Encoded as a big-endian 32-bit word in the stream.
|
// Encoded as a big-endian 32-bit word in the stream.
|
||||||
insn = (bytes[0]<<24) | (bytes[1]<<16) | (bytes[2]<< 8) | (bytes[3]<<0);
|
insn = (bytes[0]<<24) | (bytes[1]<<16) | (bytes[2]<< 8) | (bytes[3]<<0);
|
||||||
@ -517,7 +517,7 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
|
|||||||
// that it is a valid instruction.
|
// that it is a valid instruction.
|
||||||
unsigned opcode = getOPCODE(insn);
|
unsigned opcode = getOPCODE(insn);
|
||||||
if (opcode == UNSUPPORTED)
|
if (opcode == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
|
|
||||||
instr.setOpcode(opcode);
|
instr.setOpcode(opcode);
|
||||||
|
|
||||||
@ -529,11 +529,11 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
|
|||||||
uint64_t tsFlags = MBlazeInsts[opcode].TSFlags;
|
uint64_t tsFlags = MBlazeInsts[opcode].TSFlags;
|
||||||
switch ((tsFlags & MBlazeII::FormMask)) {
|
switch ((tsFlags & MBlazeII::FormMask)) {
|
||||||
default:
|
default:
|
||||||
return false;
|
return Fail;
|
||||||
|
|
||||||
case MBlazeII::FRRRR:
|
case MBlazeII::FRRRR:
|
||||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED || RB == UNSUPPORTED)
|
if (RD == UNSUPPORTED || RA == UNSUPPORTED || RB == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RD));
|
instr.addOperand(MCOperand::CreateReg(RD));
|
||||||
instr.addOperand(MCOperand::CreateReg(RB));
|
instr.addOperand(MCOperand::CreateReg(RB));
|
||||||
instr.addOperand(MCOperand::CreateReg(RA));
|
instr.addOperand(MCOperand::CreateReg(RA));
|
||||||
@ -541,7 +541,7 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
|
|||||||
|
|
||||||
case MBlazeII::FRRR:
|
case MBlazeII::FRRR:
|
||||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED || RB == UNSUPPORTED)
|
if (RD == UNSUPPORTED || RA == UNSUPPORTED || RB == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RD));
|
instr.addOperand(MCOperand::CreateReg(RD));
|
||||||
instr.addOperand(MCOperand::CreateReg(RA));
|
instr.addOperand(MCOperand::CreateReg(RA));
|
||||||
instr.addOperand(MCOperand::CreateReg(RB));
|
instr.addOperand(MCOperand::CreateReg(RB));
|
||||||
@ -550,23 +550,23 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
|
|||||||
case MBlazeII::FRI:
|
case MBlazeII::FRI:
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
default:
|
default:
|
||||||
return false;
|
return Fail;
|
||||||
case MBlaze::MFS:
|
case MBlaze::MFS:
|
||||||
if (RD == UNSUPPORTED)
|
if (RD == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RD));
|
instr.addOperand(MCOperand::CreateReg(RD));
|
||||||
instr.addOperand(MCOperand::CreateImm(insn&0x3FFF));
|
instr.addOperand(MCOperand::CreateImm(insn&0x3FFF));
|
||||||
break;
|
break;
|
||||||
case MBlaze::MTS:
|
case MBlaze::MTS:
|
||||||
if (RA == UNSUPPORTED)
|
if (RA == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateImm(insn&0x3FFF));
|
instr.addOperand(MCOperand::CreateImm(insn&0x3FFF));
|
||||||
instr.addOperand(MCOperand::CreateReg(RA));
|
instr.addOperand(MCOperand::CreateReg(RA));
|
||||||
break;
|
break;
|
||||||
case MBlaze::MSRSET:
|
case MBlaze::MSRSET:
|
||||||
case MBlaze::MSRCLR:
|
case MBlaze::MSRCLR:
|
||||||
if (RD == UNSUPPORTED)
|
if (RD == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RD));
|
instr.addOperand(MCOperand::CreateReg(RD));
|
||||||
instr.addOperand(MCOperand::CreateImm(insn&0x7FFF));
|
instr.addOperand(MCOperand::CreateImm(insn&0x7FFF));
|
||||||
break;
|
break;
|
||||||
@ -575,7 +575,7 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
|
|||||||
|
|
||||||
case MBlazeII::FRRI:
|
case MBlazeII::FRRI:
|
||||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RD));
|
instr.addOperand(MCOperand::CreateReg(RD));
|
||||||
instr.addOperand(MCOperand::CreateReg(RA));
|
instr.addOperand(MCOperand::CreateReg(RA));
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
@ -592,35 +592,35 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
|
|||||||
|
|
||||||
case MBlazeII::FCRR:
|
case MBlazeII::FCRR:
|
||||||
if (RA == UNSUPPORTED || RB == UNSUPPORTED)
|
if (RA == UNSUPPORTED || RB == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RA));
|
instr.addOperand(MCOperand::CreateReg(RA));
|
||||||
instr.addOperand(MCOperand::CreateReg(RB));
|
instr.addOperand(MCOperand::CreateReg(RB));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MBlazeII::FCRI:
|
case MBlazeII::FCRI:
|
||||||
if (RA == UNSUPPORTED)
|
if (RA == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RA));
|
instr.addOperand(MCOperand::CreateReg(RA));
|
||||||
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
|
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MBlazeII::FRCR:
|
case MBlazeII::FRCR:
|
||||||
if (RD == UNSUPPORTED || RB == UNSUPPORTED)
|
if (RD == UNSUPPORTED || RB == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RD));
|
instr.addOperand(MCOperand::CreateReg(RD));
|
||||||
instr.addOperand(MCOperand::CreateReg(RB));
|
instr.addOperand(MCOperand::CreateReg(RB));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MBlazeII::FRCI:
|
case MBlazeII::FRCI:
|
||||||
if (RD == UNSUPPORTED)
|
if (RD == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RD));
|
instr.addOperand(MCOperand::CreateReg(RD));
|
||||||
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
|
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MBlazeII::FCCR:
|
case MBlazeII::FCCR:
|
||||||
if (RB == UNSUPPORTED)
|
if (RB == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RB));
|
instr.addOperand(MCOperand::CreateReg(RB));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -630,7 +630,7 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
|
|||||||
|
|
||||||
case MBlazeII::FRRCI:
|
case MBlazeII::FRRCI:
|
||||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RD));
|
instr.addOperand(MCOperand::CreateReg(RD));
|
||||||
instr.addOperand(MCOperand::CreateReg(RA));
|
instr.addOperand(MCOperand::CreateReg(RA));
|
||||||
instr.addOperand(MCOperand::CreateImm(getSHT(insn)));
|
instr.addOperand(MCOperand::CreateImm(getSHT(insn)));
|
||||||
@ -638,35 +638,35 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
|
|||||||
|
|
||||||
case MBlazeII::FRRC:
|
case MBlazeII::FRRC:
|
||||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RD));
|
instr.addOperand(MCOperand::CreateReg(RD));
|
||||||
instr.addOperand(MCOperand::CreateReg(RA));
|
instr.addOperand(MCOperand::CreateReg(RA));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MBlazeII::FRCX:
|
case MBlazeII::FRCX:
|
||||||
if (RD == UNSUPPORTED)
|
if (RD == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RD));
|
instr.addOperand(MCOperand::CreateReg(RD));
|
||||||
instr.addOperand(MCOperand::CreateImm(getFSL(insn)));
|
instr.addOperand(MCOperand::CreateImm(getFSL(insn)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MBlazeII::FRCS:
|
case MBlazeII::FRCS:
|
||||||
if (RD == UNSUPPORTED || RS == UNSUPPORTED)
|
if (RD == UNSUPPORTED || RS == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RD));
|
instr.addOperand(MCOperand::CreateReg(RD));
|
||||||
instr.addOperand(MCOperand::CreateReg(RS));
|
instr.addOperand(MCOperand::CreateReg(RS));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MBlazeII::FCRCS:
|
case MBlazeII::FCRCS:
|
||||||
if (RS == UNSUPPORTED || RA == UNSUPPORTED)
|
if (RS == UNSUPPORTED || RA == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RS));
|
instr.addOperand(MCOperand::CreateReg(RS));
|
||||||
instr.addOperand(MCOperand::CreateReg(RA));
|
instr.addOperand(MCOperand::CreateReg(RA));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MBlazeII::FCRCX:
|
case MBlazeII::FCRCX:
|
||||||
if (RA == UNSUPPORTED)
|
if (RA == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RA));
|
instr.addOperand(MCOperand::CreateReg(RA));
|
||||||
instr.addOperand(MCOperand::CreateImm(getFSL(insn)));
|
instr.addOperand(MCOperand::CreateImm(getFSL(insn)));
|
||||||
break;
|
break;
|
||||||
@ -677,13 +677,13 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
|
|||||||
|
|
||||||
case MBlazeII::FCR:
|
case MBlazeII::FCR:
|
||||||
if (RB == UNSUPPORTED)
|
if (RB == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RB));
|
instr.addOperand(MCOperand::CreateReg(RB));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MBlazeII::FRIR:
|
case MBlazeII::FRIR:
|
||||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
||||||
return false;
|
return Fail;
|
||||||
instr.addOperand(MCOperand::CreateReg(RD));
|
instr.addOperand(MCOperand::CreateReg(RD));
|
||||||
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
|
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
|
||||||
instr.addOperand(MCOperand::CreateReg(RA));
|
instr.addOperand(MCOperand::CreateReg(RA));
|
||||||
@ -693,7 +693,7 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
|
|||||||
// We always consume 4 bytes of data on success
|
// We always consume 4 bytes of data on success
|
||||||
size = 4;
|
size = 4;
|
||||||
|
|
||||||
return true;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MCDisassembler *createMBlazeDisassembler(const Target &T) {
|
static MCDisassembler *createMBlazeDisassembler(const Target &T) {
|
||||||
|
@ -40,7 +40,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// getInstruction - See MCDisassembler.
|
/// getInstruction - See MCDisassembler.
|
||||||
bool getInstruction(MCInst &instr,
|
MCDisassembler::DecodeStatus getInstruction(MCInst &instr,
|
||||||
uint64_t &size,
|
uint64_t &size,
|
||||||
const MemoryObject ®ion,
|
const MemoryObject ®ion,
|
||||||
uint64_t address,
|
uint64_t address,
|
||||||
|
@ -106,11 +106,12 @@ static void logger(void* arg, const char* log) {
|
|||||||
// Public interface for the disassembler
|
// Public interface for the disassembler
|
||||||
//
|
//
|
||||||
|
|
||||||
bool X86GenericDisassembler::getInstruction(MCInst &instr,
|
MCDisassembler::DecodeStatus
|
||||||
uint64_t &size,
|
X86GenericDisassembler::getInstruction(MCInst &instr,
|
||||||
const MemoryObject ®ion,
|
uint64_t &size,
|
||||||
uint64_t address,
|
const MemoryObject ®ion,
|
||||||
raw_ostream &vStream) const {
|
uint64_t address,
|
||||||
|
raw_ostream &vStream) const {
|
||||||
InternalInstruction internalInstr;
|
InternalInstruction internalInstr;
|
||||||
|
|
||||||
int ret = decodeInstruction(&internalInstr,
|
int ret = decodeInstruction(&internalInstr,
|
||||||
@ -123,11 +124,11 @@ bool X86GenericDisassembler::getInstruction(MCInst &instr,
|
|||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
size = internalInstr.readerCursor - address;
|
size = internalInstr.readerCursor - address;
|
||||||
return false;
|
return Fail;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
size = internalInstr.length;
|
size = internalInstr.length;
|
||||||
return !translateInstruction(instr, internalInstr);
|
return (!translateInstruction(instr, internalInstr)) ? Success : Fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,11 +112,11 @@ public:
|
|||||||
~X86GenericDisassembler();
|
~X86GenericDisassembler();
|
||||||
|
|
||||||
/// getInstruction - See MCDisassembler.
|
/// getInstruction - See MCDisassembler.
|
||||||
bool getInstruction(MCInst &instr,
|
DecodeStatus getInstruction(MCInst &instr,
|
||||||
uint64_t &size,
|
uint64_t &size,
|
||||||
const MemoryObject ®ion,
|
const MemoryObject ®ion,
|
||||||
uint64_t address,
|
uint64_t address,
|
||||||
raw_ostream &vStream) const;
|
raw_ostream &vStream) const;
|
||||||
|
|
||||||
/// getEDInfo - See MCDisassembler.
|
/// getEDInfo - See MCDisassembler.
|
||||||
EDInstInfo *getEDInfo() const;
|
EDInstInfo *getEDInfo() const;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
|
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {potentially undefined instruction encoding}
|
||||||
|
|
||||||
# Opcode=140 Name=LDRB_POST Format=ARM_FORMAT_LDFRM(6)
|
# Opcode=140 Name=LDRB_POST Format=ARM_FORMAT_LDFRM(6)
|
||||||
# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||||
|
@ -65,15 +65,26 @@ static bool PrintInsts(const MCDisassembler &DisAsm,
|
|||||||
for (Index = 0; Index < Bytes.size(); Index += Size) {
|
for (Index = 0; Index < Bytes.size(); Index += Size) {
|
||||||
MCInst Inst;
|
MCInst Inst;
|
||||||
|
|
||||||
if (DisAsm.getInstruction(Inst, Size, memoryObject, Index,
|
MCDisassembler::DecodeStatus S;
|
||||||
/*REMOVE*/ nulls())) {
|
S = DisAsm.getInstruction(Inst, Size, memoryObject, Index,
|
||||||
Printer.printInst(&Inst, Out);
|
/*REMOVE*/ nulls());
|
||||||
Out << "\n";
|
switch (S) {
|
||||||
} else {
|
case MCDisassembler::Fail:
|
||||||
SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
|
SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
|
||||||
"invalid instruction encoding", "warning");
|
"invalid instruction encoding", "warning");
|
||||||
if (Size == 0)
|
if (Size == 0)
|
||||||
Size = 1; // skip illegible bytes
|
Size = 1; // skip illegible bytes
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MCDisassembler::SoftFail:
|
||||||
|
SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
|
||||||
|
"potentially undefined instruction encoding", "warning");
|
||||||
|
// Fall through
|
||||||
|
|
||||||
|
case MCDisassembler::Success:
|
||||||
|
Printer.printInst(&Inst, Out);
|
||||||
|
Out << "\n";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,5 +128,15 @@ void DisassemblerEmitter::run(raw_ostream &OS) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ARM and Thumb have a CHECK() macro to deal with DecodeStatuses.
|
||||||
|
if (Target.getName() == "ARM" ||
|
||||||
|
Target.getName() == "Thumb") {
|
||||||
|
FixedLenDecoderEmitter(Records,
|
||||||
|
"CHECK(S, ", ");",
|
||||||
|
"S", "Fail",
|
||||||
|
"DecodeStatus S = Success;\n(void)S;").run(OS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FixedLenDecoderEmitter(Records).run(OS);
|
FixedLenDecoderEmitter(Records).run(OS);
|
||||||
}
|
}
|
||||||
|
@ -238,19 +238,24 @@ protected:
|
|||||||
// Width of instructions
|
// Width of instructions
|
||||||
unsigned BitWidth;
|
unsigned BitWidth;
|
||||||
|
|
||||||
|
// Parent emitter
|
||||||
|
const FixedLenDecoderEmitter *Emitter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FilterChooser(const FilterChooser &FC) :
|
FilterChooser(const FilterChooser &FC) :
|
||||||
AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes),
|
AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes),
|
||||||
Operands(FC.Operands), Filters(FC.Filters),
|
Operands(FC.Operands), Filters(FC.Filters),
|
||||||
FilterBitValues(FC.FilterBitValues), Parent(FC.Parent),
|
FilterBitValues(FC.FilterBitValues), Parent(FC.Parent),
|
||||||
BestIndex(FC.BestIndex), BitWidth(FC.BitWidth) { }
|
BestIndex(FC.BestIndex), BitWidth(FC.BitWidth),
|
||||||
|
Emitter(FC.Emitter) { }
|
||||||
|
|
||||||
FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
|
FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
|
||||||
const std::vector<unsigned> &IDs,
|
const std::vector<unsigned> &IDs,
|
||||||
std::map<unsigned, std::vector<OperandInfo> > &Ops,
|
std::map<unsigned, std::vector<OperandInfo> > &Ops,
|
||||||
unsigned BW) :
|
unsigned BW,
|
||||||
|
const FixedLenDecoderEmitter *E) :
|
||||||
AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(),
|
AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(),
|
||||||
Parent(NULL), BestIndex(-1), BitWidth(BW) {
|
Parent(NULL), BestIndex(-1), BitWidth(BW), Emitter(E) {
|
||||||
for (unsigned i = 0; i < BitWidth; ++i)
|
for (unsigned i = 0; i < BitWidth; ++i)
|
||||||
FilterBitValues.push_back(BIT_UNFILTERED);
|
FilterBitValues.push_back(BIT_UNFILTERED);
|
||||||
|
|
||||||
@ -264,7 +269,8 @@ public:
|
|||||||
FilterChooser &parent) :
|
FilterChooser &parent) :
|
||||||
AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
|
AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
|
||||||
Filters(), FilterBitValues(ParentFilterBitValues),
|
Filters(), FilterBitValues(ParentFilterBitValues),
|
||||||
Parent(&parent), BestIndex(-1), BitWidth(parent.BitWidth) {
|
Parent(&parent), BestIndex(-1), BitWidth(parent.BitWidth),
|
||||||
|
Emitter(parent.Emitter) {
|
||||||
doFilter();
|
doFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,17 +569,17 @@ unsigned Filter::usefulness() const {
|
|||||||
void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation,
|
void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation,
|
||||||
std::string Namespace) {
|
std::string Namespace) {
|
||||||
o.indent(Indentation) <<
|
o.indent(Indentation) <<
|
||||||
"static bool decode" << Namespace << "Instruction" << BitWidth
|
"static MCDisassembler::DecodeStatus decode" << Namespace << "Instruction" << BitWidth
|
||||||
<< "(MCInst &MI, uint" << BitWidth << "_t insn, uint64_t Address, "
|
<< "(MCInst &MI, uint" << BitWidth << "_t insn, uint64_t Address, "
|
||||||
<< "const void *Decoder) {\n";
|
<< "const void *Decoder) {\n";
|
||||||
o.indent(Indentation) << " unsigned tmp = 0;\n (void)tmp;\n";
|
o.indent(Indentation) << " unsigned tmp = 0;\n (void)tmp;\n" << Emitter->Locals << "\n";
|
||||||
|
|
||||||
++Indentation; ++Indentation;
|
++Indentation; ++Indentation;
|
||||||
// Emits code to decode the instructions.
|
// Emits code to decode the instructions.
|
||||||
emit(o, Indentation);
|
emit(o, Indentation);
|
||||||
|
|
||||||
o << '\n';
|
o << '\n';
|
||||||
o.indent(Indentation) << "return false;\n";
|
o.indent(Indentation) << "return " << Emitter->ReturnFail << ";\n";
|
||||||
--Indentation; --Indentation;
|
--Indentation; --Indentation;
|
||||||
|
|
||||||
o.indent(Indentation) << "}\n";
|
o.indent(Indentation) << "}\n";
|
||||||
@ -744,8 +750,8 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Decoder != "")
|
if (Decoder != "")
|
||||||
o.indent(Indentation) << " if (!" << Decoder
|
o.indent(Indentation) << " " << Emitter->GuardPrefix << Decoder
|
||||||
<< "(MI, tmp, Address, Decoder)) return false;\n";
|
<< "(MI, tmp, Address, Decoder)" << Emitter->GuardPostfix << "\n";
|
||||||
else
|
else
|
||||||
o.indent(Indentation) << " MI.addOperand(MCOperand::CreateImm(tmp));\n";
|
o.indent(Indentation) << " MI.addOperand(MCOperand::CreateImm(tmp));\n";
|
||||||
|
|
||||||
@ -776,15 +782,15 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
|
|||||||
I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) {
|
I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) {
|
||||||
// If a custom instruction decoder was specified, use that.
|
// If a custom instruction decoder was specified, use that.
|
||||||
if (I->numFields() == 0 && I->Decoder.size()) {
|
if (I->numFields() == 0 && I->Decoder.size()) {
|
||||||
o.indent(Indentation) << " if (!" << I->Decoder
|
o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder
|
||||||
<< "(MI, insn, Address, Decoder)) return false;\n";
|
<< "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
emitBinaryParser(o, Indentation, *I);
|
emitBinaryParser(o, Indentation, *I);
|
||||||
}
|
}
|
||||||
|
|
||||||
o.indent(Indentation) << " return true; // " << nameWithID(Opc)
|
o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc)
|
||||||
<< '\n';
|
<< '\n';
|
||||||
o.indent(Indentation) << "}\n";
|
o.indent(Indentation) << "}\n";
|
||||||
return true;
|
return true;
|
||||||
@ -821,14 +827,14 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
|
|||||||
I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) {
|
I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) {
|
||||||
// If a custom instruction decoder was specified, use that.
|
// If a custom instruction decoder was specified, use that.
|
||||||
if (I->numFields() == 0 && I->Decoder.size()) {
|
if (I->numFields() == 0 && I->Decoder.size()) {
|
||||||
o.indent(Indentation) << " if (!" << I->Decoder
|
o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder
|
||||||
<< "(MI, insn, Address, Decoder)) return false;\n";
|
<< "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
emitBinaryParser(o, Indentation, *I);
|
emitBinaryParser(o, Indentation, *I);
|
||||||
}
|
}
|
||||||
o.indent(Indentation) << " return true; // " << nameWithID(Opc)
|
o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc)
|
||||||
<< '\n';
|
<< '\n';
|
||||||
o.indent(Indentation) << "}\n";
|
o.indent(Indentation) << "}\n";
|
||||||
|
|
||||||
@ -1426,7 +1432,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o)
|
|||||||
|
|
||||||
// Emit the decoder for this namespace+width combination.
|
// Emit the decoder for this namespace+width combination.
|
||||||
FilterChooser FC(NumberedInstructions, I->second, Operands,
|
FilterChooser FC(NumberedInstructions, I->second, Operands,
|
||||||
8*I->first.second);
|
8*I->first.second, this);
|
||||||
FC.emitTop(o, 0, I->first.first);
|
FC.emitTop(o, 0, I->first.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +49,16 @@ struct OperandInfo {
|
|||||||
|
|
||||||
class FixedLenDecoderEmitter : public TableGenBackend {
|
class FixedLenDecoderEmitter : public TableGenBackend {
|
||||||
public:
|
public:
|
||||||
FixedLenDecoderEmitter(RecordKeeper &R) :
|
FixedLenDecoderEmitter(RecordKeeper &R,
|
||||||
|
std::string GPrefix = "if (",
|
||||||
|
std::string GPostfix = " == MCDisassembler::Fail) return MCDisassembler::Fail;",
|
||||||
|
std::string ROK = "MCDisassembler::Success",
|
||||||
|
std::string RFail = "MCDisassembler::Fail",
|
||||||
|
std::string L = "") :
|
||||||
Records(R), Target(R),
|
Records(R), Target(R),
|
||||||
NumberedInstructions(Target.getInstructionsByEnumValue()) {}
|
NumberedInstructions(Target.getInstructionsByEnumValue()),
|
||||||
|
GuardPrefix(GPrefix), GuardPostfix(GPostfix),
|
||||||
|
ReturnOK(ROK), ReturnFail(RFail), Locals(L) {}
|
||||||
|
|
||||||
// run - Output the code emitter
|
// run - Output the code emitter
|
||||||
void run(raw_ostream &o);
|
void run(raw_ostream &o);
|
||||||
@ -62,7 +69,10 @@ private:
|
|||||||
std::vector<const CodeGenInstruction*> NumberedInstructions;
|
std::vector<const CodeGenInstruction*> NumberedInstructions;
|
||||||
std::vector<unsigned> Opcodes;
|
std::vector<unsigned> Opcodes;
|
||||||
std::map<unsigned, std::vector<OperandInfo> > Operands;
|
std::map<unsigned, std::vector<OperandInfo> > Operands;
|
||||||
|
public:
|
||||||
|
std::string GuardPrefix, GuardPostfix;
|
||||||
|
std::string ReturnOK, ReturnFail;
|
||||||
|
std::string Locals;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end llvm namespace
|
} // end llvm namespace
|
||||||
|
Reference in New Issue
Block a user