ARM: enable decoding of pc-relative PLD/PLI
authorAmaury de la Vieuville <amaury.dlv@gmail.com>
Mon, 24 Jun 2013 09:11:38 +0000 (09:11 +0000)
committerAmaury de la Vieuville <amaury.dlv@gmail.com>
Mon, 24 Jun 2013 09:11:38 +0000 (09:11 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184701 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMInstrThumb2.td
lib/Target/ARM/Disassembler/ARMDisassembler.cpp
test/MC/Disassembler/ARM/invalid-LDR-thumb.txt [new file with mode: 0644]
test/MC/Disassembler/ARM/thumb2.txt

index 2693f3290458625b977711352fa35f85c3df721a..5448ee3457dda3360a61818987acef3069926ef4 100644 (file)
@@ -1024,17 +1024,19 @@ multiclass T2I_ld<bit signed, bits<2> opcod, string opc,
   def pci : T2Ipc <(outs target:$Rt), (ins t2ldrlabel:$addr), iii,
                    opc, ".w\t$Rt, $addr",
                    [(set target:$Rt, (opnode (ARMWrapper tconstpool:$addr)))]> {
-    bits<4> Rt;
-    bits<13> addr;
     let isReMaterializable = 1;
     let Inst{31-27} = 0b11111;
     let Inst{26-25} = 0b00;
     let Inst{24} = signed;
-    let Inst{23} = addr{12}; // add = (U == '1')
     let Inst{22-21} = opcod;
     let Inst{20} = 1; // load
     let Inst{19-16} = 0b1111; // Rn
+
+    bits<4> Rt;
     let Inst{15-12} = Rt{3-0};
+
+    bits<13> addr;
+    let Inst{23} = addr{12}; // add = (U == '1')
     let Inst{11-0}  = addr{11-0};
 
     let DecoderMethod = "DecodeT2LoadLabel";
@@ -1564,16 +1566,17 @@ multiclass T2Ipl<bits<1> write, bits<1> instr, string opc> {
               Sched<[WritePreLd]> {
     let Inst{31-25} = 0b1111100;
     let Inst{24} = instr;
+    let Inst{23} = 1;
     let Inst{22} = 0;
     let Inst{21} = write;
     let Inst{20} = 1;
     let Inst{15-12} = 0b1111;
 
     bits<17> addr;
-    let addr{12}    = 1;           // add = TRUE
     let Inst{19-16} = addr{16-13}; // Rn
-    let Inst{23}    = addr{12};    // U
     let Inst{11-0}  = addr{11-0};  // imm12
+
+    let DecoderMethod = "DecodeT2LoadImm12";
   }
 
   def i8 : T2Ii8<(outs), (ins t2addrmode_negimm8:$addr), IIC_Preload, opc,
@@ -1592,6 +1595,8 @@ multiclass T2Ipl<bits<1> write, bits<1> instr, string opc> {
     bits<13> addr;
     let Inst{19-16} = addr{12-9}; // Rn
     let Inst{7-0}   = addr{7-0};  // imm8
+
+    let DecoderMethod = "DecodeT2LoadImm8";
   }
 
   def s : T2Iso<(outs), (ins t2addrmode_so_reg:$addr), IIC_Preload, opc,
@@ -1605,7 +1610,7 @@ multiclass T2Ipl<bits<1> write, bits<1> instr, string opc> {
     let Inst{21} = write;
     let Inst{20} = 1;
     let Inst{15-12} = 0b1111;
-    let Inst{11-6} = 0000000;
+    let Inst{11-6} = 0b000000;
 
     bits<10> addr;
     let Inst{19-16} = addr{9-6}; // Rn
@@ -1614,10 +1619,28 @@ multiclass T2Ipl<bits<1> write, bits<1> instr, string opc> {
 
     let DecoderMethod = "DecodeT2LoadShift";
   }
-  // FIXME: We should have a separate 'pci' variant here. As-is we represent
-  // it via the i12 variant, which it's related to, but that means we can
-  // represent negative immediates, which aren't legal for anything except
-  // the 'pci' case (Rn == 15).
+
+  // pci variant is very similar to i12, but supports negative offsets
+  // from the PC.
+  def pci : T2Iso<(outs), (ins t2ldrlabel:$addr), IIC_Preload, opc,
+                 "\t$addr",
+                 [(ARMPreload (ARMWrapper tconstpool:$addr),
+                              (i32 write), (i32 instr))]>,
+                 Sched<[WritePreLd]> {
+    let Inst{31-25} = 0b1111100;
+    let Inst{24} = instr;
+    let Inst{22} = 0;
+    let Inst{21} = write;
+    let Inst{20} = 1;
+    let Inst{19-16} = 0b1111;
+    let Inst{15-12} = 0b1111;
+
+    bits<13> addr;
+    let Inst{23}   = addr{12};   // add = (U == '1')
+    let Inst{11-0} = addr{11-0}; // imm12
+
+    let DecoderMethod = "DecodeT2LoadLabel";
+  }
 }
 
 defm t2PLD  : T2Ipl<0, 0, "pld">,  Requires<[IsThumb2]>;
index 39a5af9e60555c4b14a1a4beafb68298be7aa073..186bc9c0ea4daaf925cdfd55c60813f29bfe5003 100644 (file)
@@ -3199,38 +3199,51 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
   unsigned Rt = fieldFromInstruction(Insn, 12, 4);
   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
 
-  if (Rn == 0xF) {
+  if (Rn == 15) {
     switch (Inst.getOpcode()) {
-      case ARM::t2LDRBs:
-        Inst.setOpcode(ARM::t2LDRBpci);
-        break;
-      case ARM::t2LDRHs:
-        Inst.setOpcode(ARM::t2LDRHpci);
-        break;
-      case ARM::t2LDRSHs:
-        Inst.setOpcode(ARM::t2LDRSHpci);
-        break;
-      case ARM::t2LDRSBs:
-        Inst.setOpcode(ARM::t2LDRSBpci);
-        break;
-      case ARM::t2LDRs:
-        Inst.setOpcode(ARM::t2LDRpci);
-        break;
-      case ARM::t2PLDs: {
-        Inst.setOpcode(ARM::t2PLDi12);
-        Inst.addOperand(MCOperand::CreateReg(ARM::PC));
-        int imm = fieldFromInstruction(Insn, 0, 12);
-        if (!fieldFromInstruction(Insn, 23, 1)) imm *= -1;
-        Inst.addOperand(MCOperand::CreateImm(imm));
-        return S;
-      }
-      default:
-        return MCDisassembler::Fail;
+    case ARM::t2LDRBs:
+      Inst.setOpcode(ARM::t2LDRBpci);
+      break;
+    case ARM::t2LDRHs:
+      Inst.setOpcode(ARM::t2LDRHpci);
+      break;
+    case ARM::t2LDRSHs:
+      Inst.setOpcode(ARM::t2LDRSHpci);
+      break;
+    case ARM::t2LDRSBs:
+      Inst.setOpcode(ARM::t2LDRSBpci);
+      break;
+    case ARM::t2LDRs:
+      Inst.setOpcode(ARM::t2LDRpci);
+      break;
+    case ARM::t2PLDs:
+      Inst.setOpcode(ARM::t2PLDpci);
+      break;
+    case ARM::t2PLIs:
+      Inst.setOpcode(ARM::t2PLIpci);
+      break;
+    default:
+      return MCDisassembler::Fail;
     }
 
     return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
   }
 
+  if (Rt == 15) {
+    switch (Inst.getOpcode()) {
+    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;
+    default:
+      break;
+    }
+  }
+
   switch (Inst.getOpcode()) {
     case ARM::t2PLDs:
     case ARM::t2PLDWs:
@@ -3278,14 +3291,36 @@ static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
     case ARM::t2LDRSHi8:
       Inst.setOpcode(ARM::t2LDRSHpci);
       break;
+    case ARM::t2PLDi8:
+      Inst.setOpcode(ARM::t2PLDpci);
+      break;
+    case ARM::t2PLIi8:
+      Inst.setOpcode(ARM::t2PLIpci);
+      break;
     default:
       return MCDisassembler::Fail;
     }
     return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
   }
 
-  if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
-    return MCDisassembler::Fail;
+  if (Rt == 15) {
+    switch (Inst.getOpcode()) {
+    case ARM::t2LDRSHi8:
+      return MCDisassembler::Fail;
+    default:
+      break;
+    }
+  }
+
+  switch (Inst.getOpcode()) {
+  case ARM::t2PLDi8:
+  case ARM::t2PLIi8:
+    break;
+  default:
+    if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
+      return MCDisassembler::Fail;
+  }
+
   if (!Check(S, DecodeT2AddrModeImm8(Inst, imm, Address, Decoder)))
     return MCDisassembler::Fail;
   return S;
@@ -3317,14 +3352,39 @@ static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn,
     case ARM::t2LDRSBi12:
       Inst.setOpcode(ARM::t2LDRSBpci);
       break;
+    case ARM::t2PLDi12:
+      Inst.setOpcode(ARM::t2PLDpci);
+      break;
+    case ARM::t2PLIi12:
+      Inst.setOpcode(ARM::t2PLIpci);
+      break;
     default:
       return MCDisassembler::Fail;
     }
     return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
   }
 
-  if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
-    return MCDisassembler::Fail;
+  if (Rt == 15) {
+    switch (Inst.getOpcode()) {
+    case ARM::t2LDRSHi12:
+      return MCDisassembler::Fail;
+    case ARM::t2LDRHi12:
+      Inst.setOpcode(ARM::t2PLDi12);
+      break;
+    default:
+      break;
+    }
+  }
+
+  switch (Inst.getOpcode()) {
+  case ARM::t2PLDi12:
+  case ARM::t2PLIi12:
+    break;
+  default:
+    if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
+      return MCDisassembler::Fail;
+  }
+
   if (!Check(S, DecodeT2AddrModeImm12(Inst, imm, Address, Decoder)))
     return MCDisassembler::Fail;
   return S;
@@ -3377,11 +3437,27 @@ static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
   unsigned U = fieldFromInstruction(Insn, 23, 1);
   int imm = fieldFromInstruction(Insn, 0, 12);
 
-  // FIXME: detect and decode PLD properly
-  if (Inst.getOpcode() == ARM::t2LDRBpci && Rt == 15) {
-    Inst.setOpcode(ARM::t2PLDi12);
-    Inst.addOperand(MCOperand::CreateReg(ARM::PC));
-  } else {
+  if (Rt == 15) {
+    switch (Inst.getOpcode()) {
+      case ARM::t2LDRBpci:
+      case ARM::t2LDRHpci:
+        Inst.setOpcode(ARM::t2PLDpci);
+        break;
+      case ARM::t2LDRSBpci:
+        Inst.setOpcode(ARM::t2PLIpci);
+        break;
+      case ARM::t2LDRSHpci:
+        return MCDisassembler::Fail;
+      default:
+        break;
+    }
+  }
+
+  switch(Inst.getOpcode()) {
+  case ARM::t2PLDpci:
+  case ARM::t2PLIpci:
+    break;
+  default:
     if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
       return MCDisassembler::Fail;
   }
@@ -3528,7 +3604,10 @@ static DecodeStatus DecodeT2LdStPre(MCInst &Inst, unsigned Insn,
       break;
     case ARM::t2LDRSB_PRE:
     case ARM::t2LDRSB_POST:
-      Inst.setOpcode(ARM::t2LDRSBpci);
+      if (Rt == 15)
+        Inst.setOpcode(ARM::t2PLIpci);
+      else
+        Inst.setOpcode(ARM::t2LDRSBpci);
       break;
     case ARM::t2LDRSH_PRE:
     case ARM::t2LDRSH_POST:
diff --git a/test/MC/Disassembler/ARM/invalid-LDR-thumb.txt b/test/MC/Disassembler/ARM/invalid-LDR-thumb.txt
new file mode 100644 (file)
index 0000000..5786a34
--- /dev/null
@@ -0,0 +1,10 @@
+# invalid LDRSHs   Rt=PC
+# RUN: echo "0x30 0xf9 0x00 0xf0" | llvm-mc -triple=thumbv7 -disassemble 2>&1 | FileCheck %s
+
+# invalid LDRSHi8  Rt=PC
+# RUN: echo "0x30 0xf9 0x00 0xfc" | llvm-mc -triple=thumbv7 -disassemble 2>&1 | FileCheck %s
+
+# invalid LDRSHi12 Rt=PC
+# RUN: echo "0xb0 0xf9 0x00 0xf0" | llvm-mc -triple=thumbv7 -disassemble 2>&1 | FileCheck %s
+
+# CHECK: invalid instruction encoding
index 482cca8bbc281ab58ab2d119e4db7c9cf24b6571..b2c6fb88fcf69272350ca45060aef5b97c92fefa 100644 (file)
 0x1d 0xf8 0x12 0xf0
 0x1d 0xf8 0x02 0xf0
 
+#------------------------------------------------------------------------------
+# PLD(literal)
+#------------------------------------------------------------------------------
+# CHECK: pld [pc, #-0]
+# CHECK: pld [pc, #455]
+# CHECK: pld [pc, #0]
+
+0x1f 0xf8 0x00 0xf0
+0x9f 0xf8 0xc7 0xf1
+0x9f 0xf8 0x00 0xf0
+
 #------------------------------------------------------------------------------
 # PLI(immediate)
 #------------------------------------------------------------------------------
 0x1d 0xf9 0x12 0xf0
 0x1d 0xf9 0x02 0xf0
 
+#------------------------------------------------------------------------------
+# PLI(literal)
+#------------------------------------------------------------------------------
+# CHECK: pli [pc, #-0]
+# CHECK: pli [pc, #-328]
+# CHECK: pli [pc, #0]
+
+0x1f 0xf9 0x00 0xf0
+0x1f 0xf9 0x48 0xf1
+0x9f 0xf9 0x00 0xf0
+
 
 #------------------------------------------------------------------------------
 # QADD/QADD16/QADD8