diff options
author | Owen Anderson <resistor@mac.com> | 2011-08-18 22:11:02 +0000 |
---|---|---|
committer | Owen Anderson <resistor@mac.com> | 2011-08-18 22:11:02 +0000 |
commit | 14090bf2636edf5e46a2c12a312b1889f5335d7d (patch) | |
tree | 3b53b04cfbd9b2e474ef91bc519f37a322fd1a67 /lib/Target/ARM/Disassembler/ARMDisassembler.cpp | |
parent | 74af88a6661ad5185924bf39164fb4aa144d32cf (diff) |
Improve handling of failure and unpredictable cases for CPS, STR, and SMLA instructions.
Fixes a large class of disassembler crashes found by randomized testing.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137995 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/Disassembler/ARMDisassembler.cpp')
-rw-r--r-- | lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 29 |
1 files changed, 18 insertions, 11 deletions
diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index 0485c4f132..f4c57fca9b 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -1317,27 +1317,34 @@ static DecodeStatus DecodeCPSInstruction(llvm::MCInst &Inst, unsigned Insn, unsigned iflags = fieldFromInstruction32(Insn, 6, 3); unsigned mode = fieldFromInstruction32(Insn, 0, 5); + DecodeStatus S = Success; + // imod == '01' --> UNPREDICTABLE - if (imod == 1) return Fail; + // NOTE: Even though this is technically UNPREDICTABLE, we choose to + // return failure here. The '01' imod value is unprintable, so there's + // nothing useful we could do even if we returned UNPREDICTABLE. - if (M && mode && imod && iflags) { + if (imod == 1) CHECK(S, Fail); + + if (imod && M) { Inst.setOpcode(ARM::CPS3p); Inst.addOperand(MCOperand::CreateImm(imod)); Inst.addOperand(MCOperand::CreateImm(iflags)); Inst.addOperand(MCOperand::CreateImm(mode)); - return Success; - } else if (!mode && !M) { + } else if (imod && !M) { Inst.setOpcode(ARM::CPS2p); Inst.addOperand(MCOperand::CreateImm(imod)); Inst.addOperand(MCOperand::CreateImm(iflags)); - return Success; - } else if (!imod && !iflags && M) { + if (mode) CHECK(S, Unpredictable); + } else if (!imod && M) { Inst.setOpcode(ARM::CPS1p); Inst.addOperand(MCOperand::CreateImm(mode)); - return Success; - } + if (iflags) CHECK(S, Unpredictable); + } else + // imod == '00' && M == '0' --> UNPREDICTABLE + CHECK(S, Unpredictable); - return Fail; + return S; } static DecodeStatus DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn, @@ -2649,7 +2656,7 @@ static DecodeStatus DecodeSTRPreImm(llvm::MCInst &Inst, unsigned Insn, imm |= fieldFromInstruction32(Insn, 23, 1) << 12; unsigned pred = fieldFromInstruction32(Insn, 28, 4); - if (Rn == 0xF || Rn == Rt) return Unpredictable; // UNPREDICTABLE + if (Rn == 0xF || Rn == Rt) CHECK(S, Unpredictable); CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)); CHECK(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)); @@ -2670,7 +2677,7 @@ static DecodeStatus DecodeSTRPreReg(llvm::MCInst &Inst, unsigned Insn, imm |= fieldFromInstruction32(Insn, 23, 1) << 12; unsigned pred = fieldFromInstruction32(Insn, 28, 4); - if (Rn == 0xF || Rn == Rt) return Unpredictable; // UNPREDICTABLE + if (Rn == 0xF || Rn == Rt) CHECK(S, Unpredictable); CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)); CHECK(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)); |