[Thumb2] Improve disassembly of memory hints
authorOliver Stannard <oliver.stannard@arm.com>
Thu, 23 Oct 2014 08:52:58 +0000 (08:52 +0000)
committerOliver Stannard <oliver.stannard@arm.com>
Thu, 23 Oct 2014 08:52:58 +0000 (08:52 +0000)
Currently, the ARM disassembler will disassemble the Thumb2 memory hint
instructions (PLD, PLDW and PLI), even for targets which do not have
these instructions. This patch adds the required checks to the
disassmebler.

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

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

index 04b856866e114548da2523666135ee30accf5327..b85b7eba79475402bd6757848be04f8c77b8129b 100644 (file)
@@ -3269,6 +3269,11 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
 
   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
 
+  uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
+                                                          .getFeatureBits();
+  bool hasMP = featureBits & ARM::FeatureMP;
+  bool hasV7Ops = featureBits & ARM::HasV7Ops;
+
   if (Rn == 15) {
     switch (Inst.getOpcode()) {
     case ARM::t2LDRBs:
   if (Rn == 15) {
     switch (Inst.getOpcode()) {
     case ARM::t2LDRBs:
@@ -3304,11 +3309,10 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
     case ARM::t2LDRSHs:
       return MCDisassembler::Fail;
     case ARM::t2LDRHs:
     case ARM::t2LDRSHs:
       return MCDisassembler::Fail;
     case ARM::t2LDRHs:
-      // FIXME: this instruction is only available with MP extensions,
-      // this should be checked first but we don't have access to the
-      // feature bits here.
       Inst.setOpcode(ARM::t2PLDWs);
       break;
       Inst.setOpcode(ARM::t2PLDWs);
       break;
+    case ARM::t2LDRSBs:
+      Inst.setOpcode(ARM::t2PLIs);
     default:
       break;
     }
     default:
       break;
     }
@@ -3316,8 +3320,14 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
 
   switch (Inst.getOpcode()) {
     case ARM::t2PLDs:
 
   switch (Inst.getOpcode()) {
     case ARM::t2PLDs:
-    case ARM::t2PLDWs:
+      break;
     case ARM::t2PLIs:
     case ARM::t2PLIs:
+      if (!hasV7Ops)
+        return MCDisassembler::Fail;
+      break;
+    case ARM::t2PLDWs:
+      if (!hasV7Ops || !hasMP)
+        return MCDisassembler::Fail;
       break;
     default:
       if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
       break;
     default:
       if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
@@ -3343,6 +3353,12 @@ static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
   unsigned imm = fieldFromInstruction(Insn, 0, 8);
   imm |= (U << 8);
   imm |= (Rn << 9);
   unsigned imm = fieldFromInstruction(Insn, 0, 8);
   imm |= (U << 8);
   imm |= (Rn << 9);
+  unsigned add = fieldFromInstruction(Insn, 9, 1);
+
+  uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
+                                                          .getFeatureBits();
+  bool hasMP = featureBits & ARM::FeatureMP;
+  bool hasV7Ops = featureBits & ARM::HasV7Ops;
 
   if (Rn == 15) {
     switch (Inst.getOpcode()) {
 
   if (Rn == 15) {
     switch (Inst.getOpcode()) {
@@ -3377,6 +3393,13 @@ static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
     switch (Inst.getOpcode()) {
     case ARM::t2LDRSHi8:
       return MCDisassembler::Fail;
     switch (Inst.getOpcode()) {
     case ARM::t2LDRSHi8:
       return MCDisassembler::Fail;
+    case ARM::t2LDRHi8:
+      if (!add)
+        Inst.setOpcode(ARM::t2PLDWi8);
+      break;
+    case ARM::t2LDRSBi8:
+      Inst.setOpcode(ARM::t2PLIi8);
+      break;
     default:
       break;
     }
     default:
       break;
     }
@@ -3384,9 +3407,15 @@ static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
 
   switch (Inst.getOpcode()) {
   case ARM::t2PLDi8:
 
   switch (Inst.getOpcode()) {
   case ARM::t2PLDi8:
+    break;
   case ARM::t2PLIi8:
   case ARM::t2PLIi8:
-  case ARM::t2PLDWi8:
+    if (!hasV7Ops)
+      return MCDisassembler::Fail;
     break;
     break;
+  case ARM::t2PLDWi8:
+      if (!hasV7Ops || !hasMP)
+        return MCDisassembler::Fail;
+      break;
   default:
     if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
       return MCDisassembler::Fail;
   default:
     if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
       return MCDisassembler::Fail;
@@ -3406,6 +3435,11 @@ static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn,
   unsigned imm = fieldFromInstruction(Insn, 0, 12);
   imm |= (Rn << 13);
 
   unsigned imm = fieldFromInstruction(Insn, 0, 12);
   imm |= (Rn << 13);
 
+  uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
+                                                          .getFeatureBits();
+  bool hasMP = (featureBits & ARM::FeatureMP);
+  bool hasV7Ops = (featureBits & ARM::HasV7Ops);
+
   if (Rn == 15) {
     switch (Inst.getOpcode()) {
     case ARM::t2LDRi12:
   if (Rn == 15) {
     switch (Inst.getOpcode()) {
     case ARM::t2LDRi12:
@@ -3440,7 +3474,10 @@ static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn,
     case ARM::t2LDRSHi12:
       return MCDisassembler::Fail;
     case ARM::t2LDRHi12:
     case ARM::t2LDRSHi12:
       return MCDisassembler::Fail;
     case ARM::t2LDRHi12:
-      Inst.setOpcode(ARM::t2PLDi12);
+      Inst.setOpcode(ARM::t2PLDWi12);
+      break;
+    case ARM::t2LDRSBi12:
+      Inst.setOpcode(ARM::t2PLIi12);
       break;
     default:
       break;
       break;
     default:
       break;
@@ -3449,9 +3486,15 @@ static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn,
 
   switch (Inst.getOpcode()) {
   case ARM::t2PLDi12:
 
   switch (Inst.getOpcode()) {
   case ARM::t2PLDi12:
-  case ARM::t2PLDWi12:
+    break;
   case ARM::t2PLIi12:
   case ARM::t2PLIi12:
+    if (!hasV7Ops)
+      return MCDisassembler::Fail;
     break;
     break;
+  case ARM::t2PLDWi12:
+      if (!hasV7Ops || !hasMP)
+        return MCDisassembler::Fail;
+      break;
   default:
     if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
       return MCDisassembler::Fail;
   default:
     if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
       return MCDisassembler::Fail;
@@ -3509,6 +3552,10 @@ static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
   unsigned U = fieldFromInstruction(Insn, 23, 1);
   int imm = fieldFromInstruction(Insn, 0, 12);
 
   unsigned U = fieldFromInstruction(Insn, 23, 1);
   int imm = fieldFromInstruction(Insn, 0, 12);
 
+  uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
+                                                          .getFeatureBits();
+  bool hasV7Ops = (featureBits & ARM::HasV7Ops);
+
   if (Rt == 15) {
     switch (Inst.getOpcode()) {
       case ARM::t2LDRBpci:
   if (Rt == 15) {
     switch (Inst.getOpcode()) {
       case ARM::t2LDRBpci:
@@ -3527,7 +3574,10 @@ static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
 
   switch(Inst.getOpcode()) {
   case ARM::t2PLDpci:
 
   switch(Inst.getOpcode()) {
   case ARM::t2PLDpci:
+    break;
   case ARM::t2PLIpci:
   case ARM::t2PLIpci:
+    if (!hasV7Ops)
+      return MCDisassembler::Fail;
     break;
   default:
     if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
     break;
   default:
     if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
diff --git a/test/MC/Disassembler/ARM/thumb2-preloads.txt b/test/MC/Disassembler/ARM/thumb2-preloads.txt
new file mode 100644 (file)
index 0000000..dec4d64
--- /dev/null
@@ -0,0 +1,69 @@
+# RUN: not llvm-mc -triple=thumbv6t2-none-eabi -disassemble            < %s 2>/dev/null | FileCheck %s --check-prefix=V6T2
+# RUN: not llvm-mc -triple=thumbv7a-none-eabi  -disassemble -mattr=-mp < %s 2>/dev/null | FileCheck %s --check-prefix=V6T2 --check-prefix=V7
+# RUN:     llvm-mc -triple=thumbv7a-none-eabi  -disassemble -mattr=+mp < %s 2>/dev/null | FileCheck %s --check-prefix=V6T2 --check-prefix=V7 --check-prefix=MP
+# RUN: not llvm-mc -triple=thumbv7m-none-eabi  -disassemble            < %s 2>/dev/null | FileCheck %s --check-prefix=V6T2 --check-prefix=V7
+
+# RUN: not llvm-mc -triple=thumbv6t2-none-eabi -disassemble            < %s 2>&1 >/dev/null | FileCheck %s --check-prefix=MP-ERR --check-prefix=V7-ERR
+# RUN: not llvm-mc -triple=thumbv7a-none-eabi  -disassemble -mattr=-mp < %s 2>&1 >/dev/null | FileCheck %s --check-prefix=MP-ERR
+# RUN:     llvm-mc -triple=thumbv7a-none-eabi  -disassemble -mattr=+mp < %s 2>&1 >/dev/null
+# RUN: not llvm-mc -triple=thumbv7m-none-eabi  -disassemble            < %s 2>&1 >/dev/null | FileCheck %s --check-prefix=MP-ERR
+
+# V6T2: pld     [r1, #3]
+[0x91,0xf8,0x03,0xf0]
+
+# V6T2: pld     [r2, #-5]
+[0x12,0xf8,0x05,0xfc]
+
+# MP: pldw    [r3, #4]
+# MP-ERR: invalid instruction encoding
+# MP-ERR-NEXT: [0xb3,0xf8,0x04,0xf0]
+[0xb3,0xf8,0x04,0xf0]
+
+# MP: pldw    [r4, #-6]
+# MP-ERR: invalid instruction encoding
+# MP-ERR-NEXT: [0x34,0xf8,0x06,0xfc]
+[0x34,0xf8,0x06,0xfc]
+
+# V6T2: pld     [pc, #8]
+[0x9f,0xf8,0x08,0xf0]
+
+# V6T2: pld     [pc, #-5]
+[0x1f,0xf8,0x05,0xf0]
+
+# V6T2: pld     [r5, r6]
+[0x15,0xf8,0x06,0xf0]
+
+# V6T2: pld     [r7, r8, lsl #1]
+[0x17,0xf8,0x18,0xf0]
+
+# MP: pldw    [r9, r10]
+# MP-ERR: invalid instruction encoding
+# MP-ERR-NEXT: [0x39,0xf8,0x0a,0xf0]
+[0x39,0xf8,0x0a,0xf0]
+
+# MP: pldw    [r11, r12, lsl #2]
+# MP-ERR: invalid instruction encoding
+# MP-ERR-NEXT: [0x3b,0xf8,0x2c,0xf0]
+[0x3b,0xf8,0x2c,0xf0]
+
+# V7: pli     [r1, #10]
+# V7-ERR: invalid instruction encoding
+# V7-ERR-NEXT: [0x91,0xf9,0x0a,0xf0]
+[0x91,0xf9,0x0a,0xf0]
+
+# V7: pli     [r2, #-3]
+# V7-ERR: invalid instruction encoding
+# V7-ERR-NEXT: [0x12,0xf9,0x03,0xfc]
+[0x12,0xf9,0x03,0xfc]
+
+# V7: pli     [pc, #6]
+# V7-ERR: invalid instruction encoding
+# V7-ERR-NEXT: [0x9f,0xf9,0x06,0xf0]
+[0x9f,0xf9,0x06,0xf0]
+
+# V7: pli     [pc, #-8]
+# V7-ERR: invalid instruction encoding
+# V7-ERR-NEXT: [0x1f,0xf9,0x08,0xf0]
+[0x1f,0xf9,0x08,0xf0]
+
+# NO-ERR-NOT: invalid instruction encoding