[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).

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

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

index 74c017234f51408afb0f1ba7dfc03beb999a10ac..947a7636a0e53f7fbe5961528722c5460406f883 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 90ab7a558f8bf56d55df21d98f58816510e33025..9492e1d3f6606170e8a2c05d760c34618f2cb968 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 046682ddfc3ac7f071c899560009f036b763ed52..c87499ffeaeb7857f186ce290f54fac49342c14e 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 43c2158d713e569198d499af12578b5d858df17a..57ac0784bd749b6f2810c79cb574b45f9da5c9e0 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 8aecb65b3fbed24c5dcaf0b3a8247840b9ffd228..b2457b338281130bfed5fe95a80f803b912163fc 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/test/MC/Disassembler/PowerPC/dcbt.txt b/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 d65963bdb0be94e794872858f4a48f0d0f3de381..8b8d6a4b8ac9814e2de57482d883a5878e9b0e31 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/test/MC/PowerPC/dcbt.s b/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 ab2ec7160d4147b624343fa5f5c2e21aec0f9001..453a371f127f7e5649966c14e19b048caed8de4e 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