From c2d91820e1695c24563441f25112b2b740ced87a Mon Sep 17 00:00:00 2001 From: Victor Huang Date: Tue, 28 Jan 2020 08:22:53 -0600 Subject: [PATCH] [PowerPC][Future] Add pld and pstd to future CPU Add the prefixed instructions pld and pstd to future CPU. These are load and store instructions that require new operand types that are 34 bits. This patch adds the two instructions as well as the operand types required. Note that this patch also makes a minor change to tablegen to account for the fact that some instructions are going to require shifts greater than 31 bits for the new 34 bit instructions. Differential Revision: https://reviews.llvm.org/D72574 --- lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 3 ++ .../PowerPC/Disassembler/PPCDisassembler.cpp | 29 +++++++++++++ .../PowerPC/MCTargetDesc/PPCInstPrinter.cpp | 16 +++++++ .../PowerPC/MCTargetDesc/PPCInstPrinter.h | 2 + .../PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp | 31 ++++++++++++++ .../PowerPC/MCTargetDesc/PPCMCCodeEmitter.h | 6 +++ lib/Target/PowerPC/PPC.td | 7 +++- lib/Target/PowerPC/PPCInstrInfo.td | 24 +++++++++++ lib/Target/PowerPC/PPCInstrPrefix.td | 42 +++++++++++++++++++ lib/Target/PowerPC/PPCSubtarget.cpp | 1 + lib/Target/PowerPC/PPCSubtarget.h | 2 + test/CodeGen/PowerPC/future-check-features.ll | 4 +- .../Disassembler/PowerPC/future-invalid.txt | 7 +++- test/MC/Disassembler/PowerPC/futureinsts.txt | 6 +++ test/MC/PowerPC/future-errors.s | 11 +++++ test/MC/PowerPC/future.s | 11 ++++- 16 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 test/MC/PowerPC/future-errors.s diff --git a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index 41f4bb61ccc..2d9ba02b35b 100644 --- a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -356,6 +356,9 @@ public: bool isS16ImmX16() const { return Kind == Expression || (Kind == Immediate && isInt<16>(getImm()) && (getImm() & 15) == 0); } + bool isS34ImmX16() const { return Kind == Expression || + (Kind == Immediate && isInt<34>(getImm()) && + (getImm() & 15) == 0); } bool isS34Imm() const { // Once the PC-Rel ABI is finalized, evaluate whether a 34-bit // ContextImmediate is needed. diff --git a/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp b/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp index 872fe4ba25c..49c2790d7ca 100644 --- a/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp +++ b/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp @@ -270,6 +270,35 @@ static DecodeStatus decodeMemRIX16Operands(MCInst &Inst, uint64_t Imm, return MCDisassembler::Success; } +static DecodeStatus decodeMemRI34PCRelOperands(MCInst &Inst, uint64_t Imm, + int64_t Address, + const void *Decoder) { + // Decode the memri34_pcrel field (imm, reg), which has the low 34-bits as the + // displacement, and the next 5 bits as an immediate 0. + uint64_t Base = Imm >> 34; + uint64_t Disp = Imm & 0x3FFFFFFFFUL; + + assert(Base < 32 && "Invalid base register"); + + Inst.addOperand(MCOperand::createImm(SignExtend64<34>(Disp))); + return decodeImmZeroOperand(Inst, Base, Address, Decoder); +} + +static DecodeStatus decodeMemRI34Operands(MCInst &Inst, uint64_t Imm, + int64_t Address, + const void *Decoder) { + // Decode the memri34 field (imm, reg), which has the low 34-bits as the + // displacement, and the next 5 bits as the register #. + uint64_t Base = Imm >> 34; + uint64_t Disp = Imm & 0x3FFFFFFFFUL; + + assert(Base < 32 && "Invalid base register"); + + Inst.addOperand(MCOperand::createImm(SignExtend64<34>(Disp))); + Inst.addOperand(MCOperand::createReg(RRegsNoR0[Base])); + return MCDisassembler::Success; +} + static DecodeStatus decodeSPE8Operands(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder) { // Decode the spe8disp field (imm, reg), which has the low 5-bits as the diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp index bae5c942da4..911359264bd 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp @@ -465,6 +465,22 @@ void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo, O << ')'; } +void PPCInstPrinter::printMemRegImm34PCRel(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + printS34ImmOperand(MI, OpNo, O); + O << '('; + printImmZeroOperand(MI, OpNo+1, O); + O << ')'; +} + +void PPCInstPrinter::printMemRegImm34(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + printS34ImmOperand(MI, OpNo, O); + O << '('; + printOperand(MI, OpNo+1, O); + O << ')'; +} + void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo, raw_ostream &O) { // When used as the base register, r0 reads constant zero rather than diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h b/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h index 841eab9fdd8..15d9c70db5f 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h @@ -71,6 +71,8 @@ public: void printcrbitm(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printMemRegImm(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printMemRegImm34PCRel(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printMemRegImm34(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printMemRegReg(const MCInst *MI, unsigned OpNo, raw_ostream &O); }; } // end namespace llvm diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp index b68f8216562..b9b705d5230 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -159,6 +159,37 @@ unsigned PPCMCCodeEmitter::getMemRIX16Encoding(const MCInst &MI, unsigned OpNo, return RegBits; } +uint64_t +PPCMCCodeEmitter::getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Encode (imm, reg) as a memri34, which has the low 34-bits as the + // displacement and the next 5 bits as an immediate 0. + assert(MI.getOperand(OpNo + 1).isImm() && "Expecting an immediate."); + uint64_t RegBits = + getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI) << 34; + + if (RegBits != 0) + report_fatal_error("Operand must be 0"); + + const MCOperand &MO = MI.getOperand(OpNo); + return ((getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL) | RegBits; +} + +uint64_t +PPCMCCodeEmitter::getMemRI34Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Encode (imm, reg) as a memri34, which has the low 34-bits as the + // displacement and the next 5 bits as the register #. + assert(MI.getOperand(OpNo + 1).isReg() && "Expecting a register."); + uint64_t RegBits = + getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI) << 34; + + const MCOperand &MO = MI.getOperand(OpNo); + return ((getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL) | RegBits; +} + unsigned PPCMCCodeEmitter::getSPE8DisEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h index 3bc9f200ec3..9acdd941178 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h @@ -59,6 +59,12 @@ public: unsigned getMemRIX16Encoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + uint64_t getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + uint64_t getMemRI34Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; unsigned getSPE8DisEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; diff --git a/lib/Target/PowerPC/PPC.td b/lib/Target/PowerPC/PPC.td index a5577a4148c..bd6b9dd0418 100644 --- a/lib/Target/PowerPC/PPC.td +++ b/lib/Target/PowerPC/PPC.td @@ -214,6 +214,10 @@ def FeaturePrefixInstrs : SubtargetFeature<"prefix-instrs", "HasPrefixInstrs", "Enable prefixed instructions", [FeatureISA3_0, FeatureP8Vector, FeatureP9Altivec]>; +def FeaturePCRelativeMemops : + SubtargetFeature<"pcrelative-memops", "HasPCRelativeMemops", "true", + "Enable PC relative Memory Ops", + [FeatureISA3_0]>; // Since new processors generally contain a superset of features of those that // came before them, the idea is to make implementations of new processors @@ -303,7 +307,8 @@ def ProcessorFeatures { // For future CPU we assume that all of the existing features from Power 9 // still exist with the exception of those we know are Power 9 specific. list FutureAdditionalFeatures = []; - list FutureSpecificFeatures = [FeaturePrefixInstrs]; + list FutureSpecificFeatures = + [FeaturePrefixInstrs, FeaturePCRelativeMemops]; list FutureInheritableFeatures = !listconcat(P9InheritableFeatures, FutureAdditionalFeatures); list FutureFeatures = diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 137a2f3fb16..4571f284f5f 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -803,6 +803,30 @@ def PPCRegGxRCNoR0Operand : AsmOperandClass { def ptr_rc_nor0 : Operand, PointerLikeRegClass<1> { let ParserMatchClass = PPCRegGxRCNoR0Operand; } + +// New addressing modes with 34 bit immediates. +def PPCDispRI34Operand : AsmOperandClass { + let Name = "DispRI34"; let PredicateMethod = "isS34Imm"; + let RenderMethod = "addImmOperands"; +} +def dispRI34 : Operand { + let ParserMatchClass = PPCDispRI34Operand; +} +def memri34 : Operand { // memri, imm is a 34-bit value. + let PrintMethod = "printMemRegImm34"; + let MIOperandInfo = (ops dispRI34:$imm, ptr_rc_nor0:$reg); + let EncoderMethod = "getMemRI34Encoding"; + let DecoderMethod = "decodeMemRI34Operands"; +} +// memri, imm is a 34-bit value for pc-relative instructions where +// base register is set to zero. +def memri34_pcrel : Operand { // memri, imm is a 34-bit value. + let PrintMethod = "printMemRegImm34PCRel"; + let MIOperandInfo = (ops dispRI34:$imm, immZero:$reg); + let EncoderMethod = "getMemRI34PCRelEncoding"; + let DecoderMethod = "decodeMemRI34PCRelOperands"; +} + // A version of ptr_rc usable with the asm parser. def PPCRegGxRCOperand : AsmOperandClass { let Name = "RegGxRC"; let PredicateMethod = "isRegNumber"; diff --git a/lib/Target/PowerPC/PPCInstrPrefix.td b/lib/Target/PowerPC/PPCInstrPrefix.td index 46c8608b35f..418aef96609 100644 --- a/lib/Target/PowerPC/PPCInstrPrefix.td +++ b/lib/Target/PowerPC/PPCInstrPrefix.td @@ -95,6 +95,34 @@ multiclass MLS_DForm_R_SI34_RTA5_p opcode, dag OOL, dag IOL, !strconcat(asmstr, ", 1"), itin, []>, isPCRel; } +class 8LS_DForm_R_D34_RTA5 opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : PI<1, opcode, OOL, IOL, asmstr, itin> { + bits<5> RT; + bits<39> D_RA; + + let Pattern = pattern; + + // The prefix. + let Inst{6-10} = 0; + let Inst{11} = PCRel; + let Inst{12-13} = 0; + let Inst{14-31} = D_RA{33-16}; // d0 + + // The instruction. + let Inst{38-42} = RT{4-0}; + let Inst{43-47} = D_RA{38-34}; // RA + let Inst{48-63} = D_RA{15-0}; // d1 +} + +multiclass 8LS_DForm_R_D34_RTA5_p opcode, dag OOL, dag IOL, + dag PCRel_IOL, string asmstr, + InstrItinClass itin> { + def NAME : 8LS_DForm_R_D34_RTA5; + def pc : 8LS_DForm_R_D34_RTA5, isPCRel; +} def PrefixInstrs : Predicate<"PPCSubTarget->hasPrefixInstrs()">; @@ -119,5 +147,19 @@ let Predicates = [PrefixInstrs] in { (ins s34imm:$SI), "pli $RT, $SI", IIC_IntSimple, []>; } + + let mayLoad = 1, mayStore = 0 in { + defm PLD : + 8LS_DForm_R_D34_RTA5_p<57, (outs g8rc:$RT), (ins memri34:$D_RA), + (ins memri34_pcrel:$D_RA), "pld $RT, $D_RA", + IIC_LdStLFD>; + } + + let mayStore = 1, mayLoad = 0 in { + defm PSTD : + 8LS_DForm_R_D34_RTA5_p<61, (outs), (ins g8rc:$RS, memri34:$D_RA), + (ins g8rc:$RS, memri34_pcrel:$D_RA), + "pstd $RS, $D_RA", IIC_LdStLFD>; + } } diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp b/lib/Target/PowerPC/PPCSubtarget.cpp index 07e20dfb255..1d0ed7e5357 100644 --- a/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/lib/Target/PowerPC/PPCSubtarget.cpp @@ -79,6 +79,7 @@ void PPCSubtarget::initializeEnvironment() { HasP9Vector = false; HasP9Altivec = false; HasPrefixInstrs = false; + HasPCRelativeMemops = false; HasFCPSGN = false; HasFSQRT = false; HasFRE = false; diff --git a/lib/Target/PowerPC/PPCSubtarget.h b/lib/Target/PowerPC/PPCSubtarget.h index 4e1d65e5007..8ff713f7d71 100644 --- a/lib/Target/PowerPC/PPCSubtarget.h +++ b/lib/Target/PowerPC/PPCSubtarget.h @@ -106,6 +106,7 @@ protected: bool HasP9Vector; bool HasP9Altivec; bool HasPrefixInstrs; + bool HasPCRelativeMemops; bool HasFCPSGN; bool HasFSQRT; bool HasFRE, HasFRES, HasFRSQRTE, HasFRSQRTES; @@ -257,6 +258,7 @@ public: bool hasP9Vector() const { return HasP9Vector; } bool hasP9Altivec() const { return HasP9Altivec; } bool hasPrefixInstrs() const { return HasPrefixInstrs; } + bool hasPCRelativeMemops() const { return HasPCRelativeMemops; } bool hasMFOCRF() const { return HasMFOCRF; } bool hasISEL() const { return HasISEL; } bool hasBPERMD() const { return HasBPERMD; } diff --git a/test/CodeGen/PowerPC/future-check-features.ll b/test/CodeGen/PowerPC/future-check-features.ll index c4d48282579..cfaf4eab93c 100644 --- a/test/CodeGen/PowerPC/future-check-features.ll +++ b/test/CodeGen/PowerPC/future-check-features.ll @@ -1,7 +1,7 @@ -; RUN: llc -mattr=prefix-instrs -verify-machineinstrs \ +; RUN: llc -mattr=pcrelative-memops,prefix-instrs -verify-machineinstrs \ ; RUN: -mtriple=powerpc64le-unknown-unknown -ppc-asm-full-reg-names \ ; RUN: %s -o - 2>&1 | FileCheck %s -; RUN: llc -mattr=prefix-instrs -verify-machineinstrs \ +; RUN: llc -mattr=pcrelative-memops,prefix-instrs -verify-machineinstrs \ ; RUN: -mtriple=powerpc64-unknown-unknown -ppc-asm-full-reg-names \ ; RUN: %s -o - 2>&1 | FileCheck %s diff --git a/test/MC/Disassembler/PowerPC/future-invalid.txt b/test/MC/Disassembler/PowerPC/future-invalid.txt index 263fb7facb0..7f295c3c9d1 100644 --- a/test/MC/Disassembler/PowerPC/future-invalid.txt +++ b/test/MC/Disassembler/PowerPC/future-invalid.txt @@ -1,5 +1,10 @@ -# RUN: llvm-mc --disassemble %s -mcpu=future -triple powerpc64-unknown-linux-gnu < %s 2>&1 | FileCheck %s +# RUN: llvm-mc --disassemble %s -mcpu=future -triple \ +# RUN: powerpc64-unknown-linux-gnu < %s 2>&1 | FileCheck %s # paddi 1, 2, 8589934591, 1. However, RA is not zero with R=1 # CHECK: warning: invalid instruction encoding 0x06 0x11 0xff 0xff 0x38 0x22 0xff 0xff + +# pld 1, -8589934592(3), 1. However, RA is not zero with R=1 +# CHECK: warning: invalid instruction encoding +0x04 0x12 0x00 0x00 0xe0 0x23 0x00 0x00 diff --git a/test/MC/Disassembler/PowerPC/futureinsts.txt b/test/MC/Disassembler/PowerPC/futureinsts.txt index 9ff8bff939c..482a6f92770 100644 --- a/test/MC/Disassembler/PowerPC/futureinsts.txt +++ b/test/MC/Disassembler/PowerPC/futureinsts.txt @@ -7,3 +7,9 @@ # CHECK: paddi 1, 0, -8589934592, 1 0x06 0x12 0x00 0x00 0x38 0x20 0x00 0x00 +# CHECK: pld 1, -8589934592(3), 0 +0x04 0x02 0x00 0x00 0xe4 0x23 0x00 0x00 + +# CHECK: pld 1, 8589934591(0), 1 +0x04 0x11 0xff 0xff 0xe4 0x20 0xff 0xff + diff --git a/test/MC/PowerPC/future-errors.s b/test/MC/PowerPC/future-errors.s new file mode 100644 index 00000000000..d5b6c6f06ba --- /dev/null +++ b/test/MC/PowerPC/future-errors.s @@ -0,0 +1,11 @@ +# RUN: not llvm-mc -triple powerpc64-unknown-unknown < %s 2> %t +# RUN: FileCheck < %t %s +# RUN: not llvm-mc -triple powerpc64le-unknown-unknown < %s 2> %t +# RUN: FileCheck < %t %s + + # CHECK: error: invalid operand for instruction +paddi 1, 1, 32, 1 + +# CHECK: error: invalid operand for instruction +pld 1, 32(1), 1 + diff --git a/test/MC/PowerPC/future.s b/test/MC/PowerPC/future.s index afffee1c0be..a16965a6d20 100644 --- a/test/MC/PowerPC/future.s +++ b/test/MC/PowerPC/future.s @@ -23,5 +23,14 @@ # CHECK-LE: pli 1, 8589934591 # encoding: [0xff,0xff,0x01,0x06 # CHECK-LE-SAME: 0xff,0xff,0x20,0x38] pli 1, 8589934591 - +# CHECK-BE: pld 1, -8589934592(3), 0 # encoding: [0x04,0x02,0x00,0x00, +# CHECK-BE-SAME: 0xe4,0x23,0x00,0x00] +# CHECK-LE: pld 1, -8589934592(3), 0 # encoding: [0x00,0x00,0x02,0x04 +# CHECK-LE-SAME: 0x00,0x00,0x23,0xe4] + pld 1, -8589934592(3), 0 +# CHECK-BE: pld 1, 8589934591(0), 1 # encoding: [0x04,0x11,0xff,0xff +# CHECK-BE-SAME: 0xe4,0x20,0xff,0xff] +# CHECK-LE: pld 1, 8589934591(0), 1 # encoding: [0xff,0xff,0x11,0x04, +# CHECK-LE-SAME: 0xff,0xff,0x20,0xe4] + pld 1, 8589934591(0), 1