aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
diff options
context:
space:
mode:
authorOwen Anderson <resistor@mac.com>2011-08-18 22:11:02 +0000
committerOwen Anderson <resistor@mac.com>2011-08-18 22:11:02 +0000
commit14090bf2636edf5e46a2c12a312b1889f5335d7d (patch)
tree3b53b04cfbd9b2e474ef91bc519f37a322fd1a67 /lib/Target/ARM/Disassembler/ARMDisassembler.cpp
parent74af88a6661ad5185924bf39164fb4aa144d32cf (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.cpp29
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));