[PowerPC] Add asm/disasm support for dcbt with hint
authorHal Finkel <hfinkel@anl.gov>
Thu, 23 Apr 2015 22:47:57 +0000 (22:47 +0000)
committerHal Finkel <hfinkel@anl.gov>
Thu, 23 Apr 2015 22:47:57 +0000 (22:47 +0000)
Add assembler/disassembler support for dcbt/dcbtst (and aliases) with the hint
field specified (non-zero). Unforunately, the syntax for this instruction is
special in that it differs for server vs. embedded cores:
   dcbt ra, rb, th [server]
   dcbt th, ra, rb [embedded]
where th can be omitted when it is 0. dcbtst is the same. Thus we need to play
games in the parser and the printer to flip the operands around on the embedded
cores. We'll use the server syntax as the default (binutils currently uses the
embedded form by default, but IBM is changing that).

We also stop marking dcbtst as having unmodeled side effects (this is not
necessary, it is just a hint like dcbt -- noticed by inspection, so no separate
test case).

llvm-svn: 235657

llvm/include/llvm/IR/IntrinsicsPowerPC.td
llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
llvm/lib/Target/PowerPC/PPCInstrFormats.td
llvm/lib/Target/PowerPC/PPCInstrInfo.td
llvm/test/MC/Disassembler/PowerPC/dcbt.txt [new file with mode: 0644]
llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-bookII.txt
llvm/test/MC/PowerPC/dcbt.s [new file with mode: 0644]
llvm/test/MC/PowerPC/ppc64-encoding-bookII.s

index 74c0172..947a763 100644 (file)
@@ -24,7 +24,8 @@ let TargetPrefix = "ppc" in {  // All intrinsics start with "llvm.ppc.".
   def int_ppc_dcbst : Intrinsic<[], [llvm_ptr_ty], []>;
   def int_ppc_dcbt  : Intrinsic<[], [llvm_ptr_ty],
     [IntrReadWriteArgMem, NoCapture<0>]>;
-  def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty], []>;
+  def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty],
+    [IntrReadWriteArgMem, NoCapture<0>]>;
   def int_ppc_dcbz  : Intrinsic<[], [llvm_ptr_ty], []>;
   def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>;
 
index 90ab7a5..9492e1d 100644 (file)
@@ -801,6 +801,40 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst,
                                       const OperandVector &Operands) {
   int Opcode = Inst.getOpcode();
   switch (Opcode) {
+  case PPC::DCBTx:
+  case PPC::DCBTT:
+  case PPC::DCBTSTx:
+  case PPC::DCBTSTT: {
+    MCInst TmpInst;
+    TmpInst.setOpcode((Opcode == PPC::DCBTx || Opcode == PPC::DCBTT) ?
+                      PPC::DCBT : PPC::DCBTST);
+    TmpInst.addOperand(MCOperand::CreateImm(
+      (Opcode == PPC::DCBTx || Opcode == PPC::DCBTSTx) ? 0 : 16));
+    TmpInst.addOperand(Inst.getOperand(0));
+    TmpInst.addOperand(Inst.getOperand(1));
+    Inst = TmpInst;
+    break;
+  }
+  case PPC::DCBTCT:
+  case PPC::DCBTDS: {
+    MCInst TmpInst;
+    TmpInst.setOpcode(PPC::DCBT);
+    TmpInst.addOperand(Inst.getOperand(2));
+    TmpInst.addOperand(Inst.getOperand(0));
+    TmpInst.addOperand(Inst.getOperand(1));
+    Inst = TmpInst;
+    break;
+  }
+  case PPC::DCBTSTCT:
+  case PPC::DCBTSTDS: {
+    MCInst TmpInst;
+    TmpInst.setOpcode(PPC::DCBTST);
+    TmpInst.addOperand(Inst.getOperand(2));
+    TmpInst.addOperand(Inst.getOperand(0));
+    TmpInst.addOperand(Inst.getOperand(1));
+    Inst = TmpInst;
+    break;
+  }
   case PPC::LAx: {
     MCInst TmpInst;
     TmpInst.setOpcode(PPC::LA);
@@ -1606,6 +1640,21 @@ bool PPCAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
       return true;
   }
 
+  // We'll now deal with an unfortunate special case: the syntax for the dcbt
+  // and dcbtst instructions differs for server vs. embedded cores.
+  //  The syntax for dcbt is:
+  //    dcbt ra, rb, th [server]
+  //    dcbt th, ra, rb [embedded]
+  //  where th can be omitted when it is 0. dcbtst is the same. We take the
+  //  server form to be the default, so swap the operands if we're parsing for
+  //  an embedded core (they'll be swapped again upon printing).
+  if ((STI.getFeatureBits() & PPC::FeatureBookE) != 0 &&
+      Operands.size() == 4 &&
+      (Name == "dcbt" || Name == "dcbtst")) {
+    std::swap(Operands[1], Operands[3]);
+    std::swap(Operands[2], Operands[1]);
+  }
+
   return false;
 }
 
index 046682d..c87499f 100644 (file)
@@ -101,6 +101,38 @@ void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
       return;
     }
   }
+
+  // dcbt[st] is printed manually here because:
+  //  1. The assembly syntax is different between embedded and server targets
+  //  2. We must print the short mnemonics for TH == 0 because the
+  //     embedded/server syntax default will not be stable across assemblers
+  //  The syntax for dcbt is:
+  //    dcbt ra, rb, th [server]
+  //    dcbt th, ra, rb [embedded]
+  //  where th can be omitted when it is 0. dcbtst is the same.
+  if (MI->getOpcode() == PPC::DCBT || MI->getOpcode() == PPC::DCBTST) {
+    unsigned char TH = MI->getOperand(0).getImm();
+    O << "\tdcbt";
+    if (MI->getOpcode() == PPC::DCBTST)
+      O << "st";
+    if (TH == 16)
+      O << "t";
+    O << " ";
+
+    bool IsBookE = (STI.getFeatureBits() & PPC::FeatureBookE) != 0;
+    if (IsBookE && TH != 0 && TH != 16)
+      O << (unsigned int) TH << ", ";
+
+    printOperand(MI, 1, O);
+    O << ", ";
+    printOperand(MI, 2, O);
+
+    if (!IsBookE && TH != 0 && TH != 16)
+      O << ", " << (unsigned int) TH;
+
+    printAnnotation(O, Annot);
+    return;
+  }
   
   // For fast-isel, a COPY_TO_REGCLASS may survive this long.  This is
   // used when converting a 32-bit float to a 64-bit float as part of
index 43c2158..57ac078 100644 (file)
@@ -936,6 +936,21 @@ class DCB_Form<bits<10> xo, bits<5> immfield, dag OOL, dag IOL, string asmstr,
   let Inst{31}    = 0;
 }
 
+class DCB_Form_hint<bits<10> xo, dag OOL, dag IOL, string asmstr,
+                    InstrItinClass itin, list<dag> pattern>
+  : I<31, OOL, IOL, asmstr, itin> {
+  bits<5> TH;
+  bits<5> A;
+  bits<5> B;
+
+  let Pattern = pattern;
+
+  let Inst{6-10}  = TH;
+  let Inst{11-15} = A;
+  let Inst{16-20} = B;
+  let Inst{21-30} = xo;
+  let Inst{31}    = 0;
+}
 
 // DSS_Form - Form X instruction, used for altivec dss* instructions.
 class DSS_Form<bits<1> T, bits<10> xo, dag OOL, dag IOL, string asmstr,
index 8aecb65..b2457b3 100644 (file)
@@ -1369,12 +1369,6 @@ def DCBI   : DCB_Form<470, 0, (outs), (ins memrr:$dst), "dcbi $dst",
 def DCBST  : DCB_Form<54, 0, (outs), (ins memrr:$dst), "dcbst $dst",
                       IIC_LdStDCBF, [(int_ppc_dcbst xoaddr:$dst)]>,
                       PPC970_DGroup_Single;
-def DCBT   : DCB_Form<278, 0, (outs), (ins memrr:$dst), "dcbt $dst",
-                      IIC_LdStDCBF, [(int_ppc_dcbt xoaddr:$dst)]>,
-                      PPC970_DGroup_Single;
-def DCBTST : DCB_Form<246, 0, (outs), (ins memrr:$dst), "dcbtst $dst",
-                      IIC_LdStDCBF, [(int_ppc_dcbtst xoaddr:$dst)]>,
-                      PPC970_DGroup_Single;
 def DCBZ   : DCB_Form<1014, 0, (outs), (ins memrr:$dst), "dcbz $dst",
                       IIC_LdStDCBF, [(int_ppc_dcbz xoaddr:$dst)]>,
                       PPC970_DGroup_Single;
@@ -1382,13 +1376,27 @@ def DCBZL  : DCB_Form<1014, 1, (outs), (ins memrr:$dst), "dcbzl $dst",
                       IIC_LdStDCBF, [(int_ppc_dcbzl xoaddr:$dst)]>,
                       PPC970_DGroup_Single;
 
+let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in {
+def DCBT   : DCB_Form_hint<278, (outs), (ins u5imm:$TH, memrr:$dst),
+                      "dcbt $dst, $TH", IIC_LdStDCBF, []>,
+                      PPC970_DGroup_Single;
+def DCBTST : DCB_Form_hint<246, (outs), (ins u5imm:$TH, memrr:$dst),
+                      "dcbtst $dst, $TH", IIC_LdStDCBF, []>,
+                      PPC970_DGroup_Single;
+} // hasSideEffects = 0
+
 def ICBT  : XForm_icbt<31, 22, (outs), (ins u4imm:$CT, memrr:$src),
                        "icbt $CT, $src", IIC_LdStLoad>, Requires<[HasICBT]>;
 
+def : Pat<(int_ppc_dcbt xoaddr:$dst),
+          (DCBT 0, xoaddr:$dst)>;
+def : Pat<(int_ppc_dcbtst xoaddr:$dst),
+          (DCBTST 0, xoaddr:$dst)>;
+
 def : Pat<(prefetch xoaddr:$dst, (i32 0), imm, (i32 1)),
-          (DCBT xoaddr:$dst)>;   // data prefetch for loads
+          (DCBT 0, xoaddr:$dst)>;   // data prefetch for loads
 def : Pat<(prefetch xoaddr:$dst, (i32 1), imm, (i32 1)),
-          (DCBTST xoaddr:$dst)>; // data prefetch for stores
+          (DCBTST 0, xoaddr:$dst)>; // data prefetch for stores
 def : Pat<(prefetch xoaddr:$dst, (i32 0), imm, (i32 0)),
           (ICBT 0, xoaddr:$dst)>, Requires<[HasICBT]>; // inst prefetch (for read)
 
@@ -3486,6 +3494,17 @@ def : InstAlias<"waitimpl", (WAIT 2)>;
 
 def : InstAlias<"mbar", (MBAR 0)>, Requires<[IsBookE]>;
 
+def DCBTx   : PPCAsmPseudo<"dcbt $dst", (ins memrr:$dst)>;
+def DCBTSTx : PPCAsmPseudo<"dcbtst $dst", (ins memrr:$dst)>;
+
+def DCBTCT : PPCAsmPseudo<"dcbtct $dst, $TH", (ins memrr:$dst, u5imm:$TH)>;
+def DCBTDS : PPCAsmPseudo<"dcbtds $dst, $TH", (ins memrr:$dst, u5imm:$TH)>;
+def DCBTT  : PPCAsmPseudo<"dcbtt $dst", (ins memrr:$dst)>;
+
+def DCBTSTCT : PPCAsmPseudo<"dcbtstct $dst, $TH", (ins memrr:$dst, u5imm:$TH)>;
+def DCBTSTDS : PPCAsmPseudo<"dcbtstds $dst, $TH", (ins memrr:$dst, u5imm:$TH)>;
+def DCBTSTT  : PPCAsmPseudo<"dcbtstt $dst", (ins memrr:$dst)>;
+
 def : InstAlias<"crset $bx", (CREQV crbitrc:$bx, crbitrc:$bx, crbitrc:$bx)>;
 def : InstAlias<"crclr $bx", (CRXOR crbitrc:$bx, crbitrc:$bx, crbitrc:$bx)>;
 def : InstAlias<"crmove $bx, $by", (CROR crbitrc:$bx, crbitrc:$by, crbitrc:$by)>;
diff --git a/llvm/test/MC/Disassembler/PowerPC/dcbt.txt b/llvm/test/MC/Disassembler/PowerPC/dcbt.txt
new file mode 100644 (file)
index 0000000..3289637
--- /dev/null
@@ -0,0 +1,20 @@
+# RUN: llvm-mc --disassemble %s -triple powerpc64-unknown-unknown -mcpu=pwr7 | FileCheck %s -check-prefix=SERVER
+# RUN: llvm-mc --disassemble %s -triple powerpc64-unknown-unknown -mcpu=a2 | FileCheck %s -check-prefix=EMBEDDED
+
+# SERVER: dcbt 2, 3
+# EMBEDDED: dcbt 2, 3
+0x7c 0x02 0x1a 0x2c
+
+# SERVER: dcbtst 2, 3
+# EMBEDDED: dcbtst 2, 3
+0x7c 0x02 0x19 0xec
+
+# SERVER: dcbt 2, 3, 10
+# EMBEDDED: dcbt 10, 2, 3
+0x7d 0x42 0x1a 0x2c
+
+# SERVER: dcbtst 2, 3, 10
+# EMBEDDED: dcbtst 10, 2, 3
+0x7d 0x42 0x19 0xec
+
+
index d65963b..8b8d6a4 100644 (file)
 # CHECK: dcbtst 2, 3                     
 0x7c 0x02 0x19 0xec
 
+# CHECK: dcbt 2, 3, 10
+0x7d 0x42 0x1a 0x2c
+
+# CHECK: dcbtst 2, 3, 10
+0x7d 0x42 0x19 0xec
+
 # CHECK: dcbz 2, 3                       
 0x7c 0x02 0x1f 0xec
 
diff --git a/llvm/test/MC/PowerPC/dcbt.s b/llvm/test/MC/PowerPC/dcbt.s
new file mode 100644 (file)
index 0000000..66f7fa0
--- /dev/null
@@ -0,0 +1,13 @@
+# RUN: llvm-mc -triple powerpc64-unknown-unknown --show-encoding %s | FileCheck -check-prefix=SERVER %s
+# RUN: llvm-mc -mcpu=a2 -triple powerpc64-unknown-unknown --show-encoding %s | FileCheck -check-prefix=EMBEDDED %s
+
+# SERVER: dcbt 2, 3, 10                   # encoding: [0x7d,0x42,0x1a,0x2c]
+          dcbt 2, 3, 10
+# SERVER: dcbtst 2, 3, 10                 # encoding: [0x7d,0x42,0x19,0xec]
+          dcbtst 2, 3, 10
+
+# EMBEDDED: dcbt 10, 2, 3                 # encoding: [0x7d,0x42,0x1a,0x2c]
+            dcbt 10, 2, 3
+# EMBEDDED: dcbtst 10, 2, 3               # encoding: [0x7d,0x42,0x19,0xec]
+            dcbtst 10, 2, 3
+
index ab2ec71..453a371 100644 (file)
 # CHECK-LE: icbt 0, 5, 31                   # encoding: [0x2c,0xf8,0x05,0x7c]
             icbt 0, 5, 31
 
-# FIXME:    dcbt 2, 3, 10
+# CHECK-BE: dcbt 2, 3, 10                   # encoding: [0x7d,0x42,0x1a,0x2c]
+# CHECK-LE: dcbt 2, 3, 10                   # encoding: [0x2c,0x1a,0x42,0x7d]
+            dcbt 2, 3, 10
+# CHECK-BE: dcbt 2, 3, 10                   # encoding: [0x7d,0x42,0x1a,0x2c]
+# CHECK-LE: dcbt 2, 3, 10                   # encoding: [0x2c,0x1a,0x42,0x7d]
+            dcbtct 2, 3, 10
+# CHECK-BE: dcbt 2, 3, 10                   # encoding: [0x7d,0x42,0x1a,0x2c]
+# CHECK-LE: dcbt 2, 3, 10                   # encoding: [0x2c,0x1a,0x42,0x7d]
+            dcbtds 2, 3, 10
 # CHECK-BE: dcbt 2, 3                       # encoding: [0x7c,0x02,0x1a,0x2c]
 # CHECK-LE: dcbt 2, 3                       # encoding: [0x2c,0x1a,0x02,0x7c]
             dcbt 2, 3
-# FIXME:    dcbtst 2, 3, 10
+# CHECK-BE: dcbt 2, 3                       # encoding: [0x7c,0x02,0x1a,0x2c]
+# CHECK-LE: dcbt 2, 3                       # encoding: [0x2c,0x1a,0x02,0x7c]
+            dcbt 2, 3, 0
+# CHECK-BE: dcbtt 2, 3                      # encoding: [0x7e,0x02,0x1a,0x2c]
+# CHECK-LE: dcbtt 2, 3                      # encoding: [0x2c,0x1a,0x02,0x7e]
+            dcbtt 2, 3
+# CHECK-BE: dcbtt 2, 3                      # encoding: [0x7e,0x02,0x1a,0x2c]
+# CHECK-LE: dcbtt 2, 3                      # encoding: [0x2c,0x1a,0x02,0x7e]
+            dcbt 2, 3, 16
+# CHECK-BE: dcbtst 2, 3, 10                 # encoding: [0x7d,0x42,0x19,0xec]
+# CHECK-LE: dcbtst 2, 3, 10                 # encoding: [0xec,0x19,0x42,0x7d]
+            dcbtst 2, 3, 10
+# CHECK-BE: dcbtst 2, 3, 10                 # encoding: [0x7d,0x42,0x19,0xec]
+# CHECK-LE: dcbtst 2, 3, 10                 # encoding: [0xec,0x19,0x42,0x7d]
+            dcbtstct 2, 3, 10
+# CHECK-BE: dcbtst 2, 3, 10                 # encoding: [0x7d,0x42,0x19,0xec]
+# CHECK-LE: dcbtst 2, 3, 10                 # encoding: [0xec,0x19,0x42,0x7d]
+            dcbtstds 2, 3, 10
 # CHECK-BE: dcbtst 2, 3                     # encoding: [0x7c,0x02,0x19,0xec]
 # CHECK-LE: dcbtst 2, 3                     # encoding: [0xec,0x19,0x02,0x7c]
             dcbtst 2, 3
+# CHECK-BE: dcbtst 2, 3                     # encoding: [0x7c,0x02,0x19,0xec]
+# CHECK-LE: dcbtst 2, 3                     # encoding: [0xec,0x19,0x02,0x7c]
+            dcbtst 2, 3, 0
+# CHECK-BE: dcbtstt 2, 3                    # encoding: [0x7e,0x02,0x19,0xec]
+# CHECK-LE: dcbtstt 2, 3                    # encoding: [0xec,0x19,0x02,0x7e]
+            dcbtstt 2, 3
+# CHECK-BE: dcbtstt 2, 3                    # encoding: [0x7e,0x02,0x19,0xec]
+# CHECK-LE: dcbtstt 2, 3                    # encoding: [0xec,0x19,0x02,0x7e]
+            dcbtst 2, 3, 16
 # CHECK-BE: dcbz 2, 3                       # encoding: [0x7c,0x02,0x1f,0xec]
 # CHECK-LE: dcbz 2, 3                       # encoding: [0xec,0x1f,0x02,0x7c]
             dcbz 2, 3