[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
This commit is contained in:
Hal Finkel 2015-04-23 22:47:57 +00:00
parent 3ad4bc1445
commit 79f43b2736
9 changed files with 200 additions and 11 deletions

View 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], []>;

View 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;
}

View 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

View 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,

View 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)>;

View File

@ -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

View File

@ -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

13
test/MC/PowerPC/dcbt.s Normal file
View File

@ -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

View File

@ -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