[PowerPC][Future] Add pld and pstd to future CPU
authorVictor Huang <wei.huang@ibm.com>
Tue, 28 Jan 2020 14:22:53 +0000 (08:22 -0600)
committerVictor Huang <wei.huang@ibm.com>
Tue, 28 Jan 2020 14:23:29 +0000 (08:23 -0600)
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

16 files changed:
llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h
llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h
llvm/lib/Target/PowerPC/PPC.td
llvm/lib/Target/PowerPC/PPCInstrInfo.td
llvm/lib/Target/PowerPC/PPCInstrPrefix.td
llvm/lib/Target/PowerPC/PPCSubtarget.cpp
llvm/lib/Target/PowerPC/PPCSubtarget.h
llvm/test/CodeGen/PowerPC/future-check-features.ll
llvm/test/MC/Disassembler/PowerPC/future-invalid.txt
llvm/test/MC/Disassembler/PowerPC/futureinsts.txt
llvm/test/MC/PowerPC/future-errors.s [new file with mode: 0644]
llvm/test/MC/PowerPC/future.s

index 41f4bb6..2d9ba02 100644 (file)
@@ -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.
index 872fe4b..49c2790 100644 (file)
@@ -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
index bae5c94..9113592 100644 (file)
@@ -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
index 841eab9..15d9c70 100644 (file)
@@ -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
index b68f821..b9b705d 100644 (file)
@@ -159,6 +159,37 @@ unsigned PPCMCCodeEmitter::getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
   return RegBits;
 }
 
+uint64_t
+PPCMCCodeEmitter::getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
+                                          SmallVectorImpl<MCFixup> &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<MCFixup> &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<MCFixup> &Fixups,
                                               const MCSubtargetInfo &STI)
index 3bc9f20..9acdd94 100644 (file)
@@ -59,6 +59,12 @@ public:
   unsigned getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
                                SmallVectorImpl<MCFixup> &Fixups,
                                const MCSubtargetInfo &STI) const;
+  uint64_t getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
+                                   SmallVectorImpl<MCFixup> &Fixups,
+                                   const MCSubtargetInfo &STI) const;
+  uint64_t getMemRI34Encoding(const MCInst &MI, unsigned OpNo,
+                              SmallVectorImpl<MCFixup> &Fixups,
+                              const MCSubtargetInfo &STI) const;
   unsigned getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
                               SmallVectorImpl<MCFixup> &Fixups,
                               const MCSubtargetInfo &STI) const;
index a5577a4..bd6b9dd 100644 (file)
@@ -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<SubtargetFeature> FutureAdditionalFeatures = [];
-  list<SubtargetFeature> FutureSpecificFeatures = [FeaturePrefixInstrs];
+  list<SubtargetFeature> FutureSpecificFeatures =
+    [FeaturePrefixInstrs, FeaturePCRelativeMemops];
   list<SubtargetFeature> FutureInheritableFeatures =
     !listconcat(P9InheritableFeatures, FutureAdditionalFeatures);
   list<SubtargetFeature> FutureFeatures =
index 137a2f3..4571f28 100644 (file)
@@ -803,6 +803,30 @@ def PPCRegGxRCNoR0Operand : AsmOperandClass {
 def ptr_rc_nor0 : Operand<iPTR>, 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<iPTR> {
+  let ParserMatchClass = PPCDispRI34Operand;
+}
+def memri34 : Operand<iPTR> { // 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<iPTR> { // 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";
index 46c8608..418aef9 100644 (file)
@@ -95,6 +95,34 @@ multiclass MLS_DForm_R_SI34_RTA5_p<bits<6> opcode, dag OOL, dag IOL,
                                  !strconcat(asmstr, ", 1"), itin, []>, isPCRel;
 }
 
+class 8LS_DForm_R_D34_RTA5<bits<6> opcode, dag OOL, dag IOL, string asmstr,
+                           InstrItinClass itin, list<dag> 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<bits<6> opcode, dag OOL, dag IOL,
+                                  dag PCRel_IOL, string asmstr,
+                                  InstrItinClass itin> {
+  def NAME : 8LS_DForm_R_D34_RTA5<opcode, OOL, IOL,
+                                  !strconcat(asmstr, ", 0"), itin, []>;
+  def pc : 8LS_DForm_R_D34_RTA5<opcode, OOL, PCRel_IOL,
+                                !strconcat(asmstr, ", 1"), itin, []>, 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>;
+  }
 }
 
index 07e20df..1d0ed7e 100644 (file)
@@ -79,6 +79,7 @@ void PPCSubtarget::initializeEnvironment() {
   HasP9Vector = false;
   HasP9Altivec = false;
   HasPrefixInstrs = false;
+  HasPCRelativeMemops = false;
   HasFCPSGN = false;
   HasFSQRT = false;
   HasFRE = false;
index 4e1d65e..8ff713f 100644 (file)
@@ -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; }
index c4d4828..cfaf4ea 100644 (file)
@@ -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
 
index 263fb7f..7f295c3 100644 (file)
@@ -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
index 9ff8bff..482a6f9 100644 (file)
@@ -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/llvm/test/MC/PowerPC/future-errors.s b/llvm/test/MC/PowerPC/future-errors.s
new file mode 100644 (file)
index 0000000..d5b6c6f
--- /dev/null
@@ -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
+
index afffee1..a16965a 100644 (file)
 # 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