Add post-decode checking of HVC instruction.
authorCharlie Turner <charlie.turner@arm.com>
Mon, 1 Dec 2014 08:50:27 +0000 (08:50 +0000)
committerCharlie Turner <charlie.turner@arm.com>
Mon, 1 Dec 2014 08:50:27 +0000 (08:50 +0000)
Add checkDecodedInstruction for post-decode checking of instructions, to catch
the corner cases like HVC that don't fit into the general pattern. Needed to
check for an invalid condition field in instruction encoding despite HVC not
taking a predicate.

Patch by Matthew Wahab.

Change-Id: I48e28de981d7a9e43569594da3c45fb478b4f795

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222992 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/Disassembler/ARMDisassembler.cpp
test/MC/Disassembler/ARM/invalid-virtexts.arm.txt [new file with mode: 0644]

index ef6541890bf287b7fbfabb5b7c1fcf0acd16210c..99d3331a368f01edb2ccf5c326a430ec7d8a3b2f 100644 (file)
@@ -405,6 +405,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 +452,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
diff --git a/test/MC/Disassembler/ARM/invalid-virtexts.arm.txt b/test/MC/Disassembler/ARM/invalid-virtexts.arm.txt
new file mode 100644 (file)
index 0000000..1daada9
--- /dev/null
@@ -0,0 +1,10 @@
+# RUN: not llvm-mc -disassemble -triple armv7a -mcpu=cortex-a15 %s 2>&1 | FileCheck --check-prefix=CHECK-ARM %s
+
+# HVC (ARM)
+[0x7f,0xff,0x4f,0xf1]
+# CHECK-ARM:   warning: invalid instruction encoding
+
+[0x70,0xff,0x4f,0x01]
+[0x7f,0xff,0x4f,0xd1]
+# CHECK-ARM:   warning: potentially undefined instruction encoding
+# CHECK-ARM:   warning: potentially undefined instruction encoding