From 79f43b27368e6b8ac0eb3a143a03d61f4e2b1209 Mon Sep 17 00:00:00 2001 From: Hal Finkel Date: Thu, 23 Apr 2015 22:47:57 +0000 Subject: [PATCH] [PowerPC] Add asm/disasm support for dcbt with hint 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 | 3 +- lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 49 +++++++++++++++++++ .../PowerPC/InstPrinter/PPCInstPrinter.cpp | 32 ++++++++++++ lib/Target/PowerPC/PPCInstrFormats.td | 15 ++++++ lib/Target/PowerPC/PPCInstrInfo.td | 35 ++++++++++--- test/MC/Disassembler/PowerPC/dcbt.txt | 20 ++++++++ .../PowerPC/ppc64-encoding-bookII.txt | 6 +++ test/MC/PowerPC/dcbt.s | 13 +++++ test/MC/PowerPC/ppc64-encoding-bookII.s | 38 +++++++++++++- 9 files changed, 200 insertions(+), 11 deletions(-) create mode 100644 test/MC/Disassembler/PowerPC/dcbt.txt create mode 100644 test/MC/PowerPC/dcbt.s diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 74c017234f5..947a7636a0e 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -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], []>; diff --git a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index 90ab7a558f8..9492e1d3f66 100644 --- a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -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; } diff --git a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp index 046682ddfc3..c87499ffeae 100644 --- a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +++ b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp @@ -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 diff --git a/lib/Target/PowerPC/PPCInstrFormats.td b/lib/Target/PowerPC/PPCInstrFormats.td index 43c2158d713..57ac0784bd7 100644 --- a/lib/Target/PowerPC/PPCInstrFormats.td +++ b/lib/Target/PowerPC/PPCInstrFormats.td @@ -936,6 +936,21 @@ class DCB_Form xo, bits<5> immfield, dag OOL, dag IOL, string asmstr, let Inst{31} = 0; } +class DCB_Form_hint xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list 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 T, bits<10> xo, dag OOL, dag IOL, string asmstr, diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 8aecb65b3fb..b2457b33828 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -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 index 00000000000..3289637ca60 --- /dev/null +++ b/test/MC/Disassembler/PowerPC/dcbt.txt @@ -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 + + diff --git a/test/MC/Disassembler/PowerPC/ppc64-encoding-bookII.txt b/test/MC/Disassembler/PowerPC/ppc64-encoding-bookII.txt index d65963bdb0b..8b8d6a4b8ac 100644 --- a/test/MC/Disassembler/PowerPC/ppc64-encoding-bookII.txt +++ b/test/MC/Disassembler/PowerPC/ppc64-encoding-bookII.txt @@ -12,6 +12,12 @@ # 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 index 00000000000..66f7fa07b03 --- /dev/null +++ b/test/MC/PowerPC/dcbt.s @@ -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 + diff --git a/test/MC/PowerPC/ppc64-encoding-bookII.s b/test/MC/PowerPC/ppc64-encoding-bookII.s index ab2ec7160d4..453a371f127 100644 --- a/test/MC/PowerPC/ppc64-encoding-bookII.s +++ b/test/MC/PowerPC/ppc64-encoding-bookII.s @@ -12,14 +12,48 @@ # 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