Improve handling of failure and unpredictable cases for CPS, STR, and SMLA instructions.
authorOwen Anderson <resistor@mac.com>
Thu, 18 Aug 2011 22:11:02 +0000 (22:11 +0000)
committerOwen Anderson <resistor@mac.com>
Thu, 18 Aug 2011 22:11:02 +0000 (22:11 +0000)
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

lib/Target/ARM/Disassembler/ARMDisassembler.cpp
test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt

index 0485c4f132e2eee9de62a2a678559e20ac7e879d..f4c57fca9bdbe530aa6bb32e2d5d065238fd7d76 100644 (file)
@@ -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));
index 5202217b6a71d4578cb03c4e012298accedb6772..6fdb55e691d4823582ae64f0afe2174fcca76470 100644 (file)
@@ -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}
 
 # invalid (imod, M, iflags) combination
 0x93 0x1c 0x02 0xf1