OSDN Git Service

[ARM64] Register-offset loads and stores with the 'option' field equal to 00x or...
authorBradley Smith <bradley.smith@arm.com>
Wed, 9 Apr 2014 14:41:38 +0000 (14:41 +0000)
committerBradley Smith <bradley.smith@arm.com>
Wed, 9 Apr 2014 14:41:38 +0000 (14:41 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205858 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp
test/MC/Disassembler/ARM64/basic-a64-undefined.txt [new file with mode: 0644]

index 44c501f..b522939 100644 (file)
@@ -1262,70 +1262,61 @@ static DecodeStatus DecodeRegOffsetLdStInstruction(llvm::MCInst &Inst,
   unsigned Rm = fieldFromInstruction(insn, 16, 5);
   unsigned extendHi = fieldFromInstruction(insn, 13, 3);
   unsigned extendLo = fieldFromInstruction(insn, 12, 1);
-  unsigned extend = 0;
+  unsigned extend = (extendHi << 1) | extendLo;
+
+  // All RO load-store instructions are undefined if option == 00x or 10x.
+  if (extend >> 2 == 0x0 || extend >> 2 == 0x2)
+    return Fail;
 
   switch (Inst.getOpcode()) {
   default:
     return Fail;
   case ARM64::LDRSWro:
-    extend = (extendHi << 1) | extendLo;
     DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
     break;
   case ARM64::LDRXro:
   case ARM64::STRXro:
-    extend = (extendHi << 1) | extendLo;
     DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
     break;
   case ARM64::LDRWro:
   case ARM64::STRWro:
-    extend = (extendHi << 1) | extendLo;
     DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
     break;
   case ARM64::LDRQro:
   case ARM64::STRQro:
-    extend = (extendHi << 1) | extendLo;
     DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder);
     break;
   case ARM64::LDRDro:
   case ARM64::STRDro:
-    extend = (extendHi << 1) | extendLo;
     DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder);
     break;
   case ARM64::LDRSro:
   case ARM64::STRSro:
-    extend = (extendHi << 1) | extendLo;
     DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder);
     break;
   case ARM64::LDRHro:
-    extend = (extendHi << 1) | extendLo;
     DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder);
     break;
   case ARM64::LDRBro:
-    extend = (extendHi << 1) | extendLo;
     DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder);
     break;
   case ARM64::LDRBBro:
   case ARM64::STRBBro:
   case ARM64::LDRSBWro:
-    extend = (extendHi << 1) | extendLo;
     DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
     break;
   case ARM64::LDRHHro:
   case ARM64::STRHHro:
   case ARM64::LDRSHWro:
-    extend = (extendHi << 1) | extendLo;
     DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
     break;
   case ARM64::LDRSHXro:
-    extend = (extendHi << 1) | extendLo;
     DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
     break;
   case ARM64::LDRSBXro:
-    extend = (extendHi << 1) | extendLo;
     DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
     break;
   case ARM64::PRFMro:
-    extend = (extendHi << 1) | extendLo;
     Inst.addOperand(MCOperand::CreateImm(Rt));
   }
 
diff --git a/test/MC/Disassembler/ARM64/basic-a64-undefined.txt b/test/MC/Disassembler/ARM64/basic-a64-undefined.txt
new file mode 100644 (file)
index 0000000..a2b66c2
--- /dev/null
@@ -0,0 +1,7 @@
+# These spawn another process so they're rather expensive. Not many.
+
+# LDR/STR: undefined if option field is 10x or 00x.
+# RUN: echo "0x00 0x08 0x20 0xf8" | llvm-mc -triple arm64 -disassemble 2>&1 | FileCheck %s
+# RUN: echo "0x00 0x88 0x00 0xf8" | llvm-mc -triple arm64 -disassemble 2>&1 | FileCheck %s
+
+# CHECK: invalid instruction encoding