diff options
Diffstat (limited to 'lib/Target/ARM/Disassembler/ARMDisassembler.cpp')
-rw-r--r-- | lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index ef65418..4d5122a 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -176,8 +176,6 @@ static DecodeStatus DecodePredicateOperand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder); static DecodeStatus DecodeCCOutOperand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder); -static DecodeStatus DecodeSOImmOperand(MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder); static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSPRRegListOperand(MCInst &Inst, unsigned Val, @@ -405,6 +403,28 @@ static MCDisassembler *createThumbDisassembler(const Target &T, return new ThumbDisassembler(STI, Ctx); } +// Post-decoding checks +static DecodeStatus checkDecodedInstruction(MCInst &MI, uint64_t &Size, + uint64_t Address, raw_ostream &OS, + raw_ostream &CS, + uint32_t Insn, + DecodeStatus Result) +{ + switch (MI.getOpcode()) { + case ARM::HVC: { + // HVC is undefined if condition = 0xf otherwise upredictable + // if condition != 0xe + uint32_t Cond = (Insn >> 28) & 0xF; + if (Cond == 0xF) + return MCDisassembler::Fail; + if (Cond != 0xE) + return MCDisassembler::SoftFail; + return Result; + } + default: return Result; + } +} + DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address, raw_ostream &OS, @@ -430,7 +450,7 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size, decodeInstruction(DecoderTableARM32, MI, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) { Size = 4; - return Result; + return checkDecodedInstruction(MI, Size, Address, OS, CS, Insn, Result); } // VFP and NEON instructions, similarly, are shared between ARM @@ -1113,15 +1133,6 @@ static DecodeStatus DecodeCCOutOperand(MCInst &Inst, unsigned Val, return MCDisassembler::Success; } -static DecodeStatus DecodeSOImmOperand(MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder) { - uint32_t imm = Val & 0xFF; - uint32_t rot = (Val & 0xF00) >> 7; - uint32_t rot_imm = (imm >> rot) | (imm << ((32-rot) & 0x1F)); - Inst.addOperand(MCOperand::CreateImm(rot_imm)); - return MCDisassembler::Success; -} - static DecodeStatus DecodeSORegImmOperand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; @@ -4960,7 +4971,7 @@ static DecodeStatus DecodeT2ShifterImmOperand(MCInst &Inst, uint32_t Val, DecodeStatus S = MCDisassembler::Success; // Shift of "asr #32" is not allowed in Thumb2 mode. - if (Val == 0x20) S = MCDisassembler::SoftFail; + if (Val == 0x20) S = MCDisassembler::Fail; Inst.addOperand(MCOperand::CreateImm(Val)); return S; } |