106f32e7eSjoerg //===-- Target.cpp ----------------------------------------------*- C++ -*-===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg // The PowerPC ExegesisTarget.
806f32e7eSjoerg //===----------------------------------------------------------------------===//
906f32e7eSjoerg #include "../Target.h"
1006f32e7eSjoerg #include "PPC.h"
1106f32e7eSjoerg #include "PPCRegisterInfo.h"
1206f32e7eSjoerg 
1306f32e7eSjoerg namespace llvm {
1406f32e7eSjoerg namespace exegesis {
1506f32e7eSjoerg 
16*da58b97aSjoerg // Helper to fill a memory operand with a value.
setMemOp(InstructionTemplate & IT,int OpIdx,const MCOperand & OpVal)17*da58b97aSjoerg static void setMemOp(InstructionTemplate &IT, int OpIdx,
18*da58b97aSjoerg                      const MCOperand &OpVal) {
19*da58b97aSjoerg   const auto Op = IT.getInstr().Operands[OpIdx];
20*da58b97aSjoerg   assert(Op.isExplicit() && "invalid memory pattern");
21*da58b97aSjoerg   IT.getValueFor(Op) = OpVal;
22*da58b97aSjoerg }
23*da58b97aSjoerg 
2406f32e7eSjoerg #include "PPCGenExegesis.inc"
2506f32e7eSjoerg 
2606f32e7eSjoerg namespace {
2706f32e7eSjoerg class ExegesisPowerPCTarget : public ExegesisTarget {
2806f32e7eSjoerg public:
ExegesisPowerPCTarget()2906f32e7eSjoerg   ExegesisPowerPCTarget() : ExegesisTarget(PPCCpuPfmCounters) {}
3006f32e7eSjoerg 
3106f32e7eSjoerg private:
3206f32e7eSjoerg   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
3306f32e7eSjoerg                                const APInt &Value) const override;
matchesArch(Triple::ArchType Arch) const3406f32e7eSjoerg   bool matchesArch(Triple::ArchType Arch) const override {
3506f32e7eSjoerg     return Arch == Triple::ppc64le;
3606f32e7eSjoerg   }
37*da58b97aSjoerg   unsigned getScratchMemoryRegister(const Triple &) const override;
38*da58b97aSjoerg   void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
39*da58b97aSjoerg                           unsigned Offset) const override;
4006f32e7eSjoerg };
4106f32e7eSjoerg } // end anonymous namespace
4206f32e7eSjoerg 
getLoadImmediateOpcode(unsigned RegBitWidth)4306f32e7eSjoerg static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) {
4406f32e7eSjoerg   switch (RegBitWidth) {
4506f32e7eSjoerg   case 32:
4606f32e7eSjoerg     return PPC::LI;
4706f32e7eSjoerg   case 64:
4806f32e7eSjoerg     return PPC::LI8;
4906f32e7eSjoerg   }
5006f32e7eSjoerg   llvm_unreachable("Invalid Value Width");
5106f32e7eSjoerg }
5206f32e7eSjoerg 
5306f32e7eSjoerg // Generates instruction to load an immediate value into a register.
loadImmediate(unsigned Reg,unsigned RegBitWidth,const APInt & Value)5406f32e7eSjoerg static MCInst loadImmediate(unsigned Reg, unsigned RegBitWidth,
5506f32e7eSjoerg                             const APInt &Value) {
5606f32e7eSjoerg   if (Value.getBitWidth() > RegBitWidth)
5706f32e7eSjoerg     llvm_unreachable("Value must fit in the Register");
58*da58b97aSjoerg   // We don't really care the value in reg, ignore the 16 bit
59*da58b97aSjoerg   // restriction for now.
60*da58b97aSjoerg   // TODO: make sure we get the exact value in reg if needed.
6106f32e7eSjoerg   return MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
6206f32e7eSjoerg       .addReg(Reg)
6306f32e7eSjoerg       .addImm(Value.getZExtValue());
6406f32e7eSjoerg }
6506f32e7eSjoerg 
66*da58b97aSjoerg unsigned
getScratchMemoryRegister(const Triple & TT) const67*da58b97aSjoerg ExegesisPowerPCTarget::getScratchMemoryRegister(const Triple &TT) const {
68*da58b97aSjoerg   // R13 is reserved as Thread Pointer, we won't use threading in benchmark, so
69*da58b97aSjoerg   // use it as scratch memory register
70*da58b97aSjoerg   return TT.isArch64Bit() ? PPC::X13 : PPC::R13;
71*da58b97aSjoerg }
72*da58b97aSjoerg 
fillMemoryOperands(InstructionTemplate & IT,unsigned Reg,unsigned Offset) const73*da58b97aSjoerg void ExegesisPowerPCTarget::fillMemoryOperands(InstructionTemplate &IT,
74*da58b97aSjoerg                                                unsigned Reg,
75*da58b97aSjoerg                                                unsigned Offset) const {
76*da58b97aSjoerg   int MemOpIdx = 0;
77*da58b97aSjoerg   if (IT.getInstr().hasTiedRegisters())
78*da58b97aSjoerg     MemOpIdx = 1;
79*da58b97aSjoerg   int DispOpIdx = MemOpIdx + 1;
80*da58b97aSjoerg   const auto DispOp = IT.getInstr().Operands[DispOpIdx];
81*da58b97aSjoerg   if (DispOp.isReg())
82*da58b97aSjoerg     // We don't really care about the real address in snippets,
83*da58b97aSjoerg     // So hardcode X1 for X-form Memory Operations for simplicity.
84*da58b97aSjoerg     // TODO: materialize the offset into a reggister
85*da58b97aSjoerg     setMemOp(IT, DispOpIdx, MCOperand::createReg(PPC::X1));
86*da58b97aSjoerg   else
87*da58b97aSjoerg     setMemOp(IT, DispOpIdx, MCOperand::createImm(Offset)); // Disp
88*da58b97aSjoerg   setMemOp(IT, MemOpIdx + 2, MCOperand::createReg(Reg));   // BaseReg
89*da58b97aSjoerg }
90*da58b97aSjoerg 
setRegTo(const MCSubtargetInfo & STI,unsigned Reg,const APInt & Value) const9106f32e7eSjoerg std::vector<MCInst> ExegesisPowerPCTarget::setRegTo(const MCSubtargetInfo &STI,
9206f32e7eSjoerg                                                     unsigned Reg,
9306f32e7eSjoerg                                                     const APInt &Value) const {
94*da58b97aSjoerg   // X11 is optional use in function linkage, should be the least used one
95*da58b97aSjoerg   // Use it as scratch reg to load immediate.
96*da58b97aSjoerg   unsigned ScratchImmReg = PPC::X11;
97*da58b97aSjoerg 
9806f32e7eSjoerg   if (PPC::GPRCRegClass.contains(Reg))
9906f32e7eSjoerg     return {loadImmediate(Reg, 32, Value)};
10006f32e7eSjoerg   if (PPC::G8RCRegClass.contains(Reg))
10106f32e7eSjoerg     return {loadImmediate(Reg, 64, Value)};
102*da58b97aSjoerg   if (PPC::F4RCRegClass.contains(Reg))
103*da58b97aSjoerg     return {loadImmediate(ScratchImmReg, 64, Value),
104*da58b97aSjoerg             MCInstBuilder(PPC::MTVSRD).addReg(Reg).addReg(ScratchImmReg)};
105*da58b97aSjoerg   // We don't care the real value in reg, so set 64 bits or duplicate 64 bits
106*da58b97aSjoerg   // for simplicity.
107*da58b97aSjoerg   // TODO: update these if we need a accurate 128 values in registers.
108*da58b97aSjoerg   if (PPC::VRRCRegClass.contains(Reg))
109*da58b97aSjoerg     return {loadImmediate(ScratchImmReg, 64, Value),
110*da58b97aSjoerg             MCInstBuilder(PPC::MTVRD).addReg(Reg).addReg(ScratchImmReg)};
111*da58b97aSjoerg   if (PPC::VSRCRegClass.contains(Reg))
112*da58b97aSjoerg     return {loadImmediate(ScratchImmReg, 64, Value),
113*da58b97aSjoerg             MCInstBuilder(PPC::MTVSRDD)
114*da58b97aSjoerg                 .addReg(Reg)
115*da58b97aSjoerg                 .addReg(ScratchImmReg)
116*da58b97aSjoerg                 .addReg(ScratchImmReg)};
117*da58b97aSjoerg   if (PPC::VFRCRegClass.contains(Reg))
118*da58b97aSjoerg     return {loadImmediate(ScratchImmReg, 64, Value),
119*da58b97aSjoerg             MCInstBuilder(PPC::MTVSRD).addReg(Reg).addReg(ScratchImmReg)};
120*da58b97aSjoerg   // SPE not supported yet
121*da58b97aSjoerg   if (PPC::SPERCRegClass.contains(Reg)) {
122*da58b97aSjoerg     errs() << "Unsupported SPE Reg:" << Reg << "\n";
123*da58b97aSjoerg     return {};
124*da58b97aSjoerg   }
125*da58b97aSjoerg   errs() << "setRegTo is not implemented, results will be unreliable:" << Reg
126*da58b97aSjoerg          << "\n";
12706f32e7eSjoerg   return {};
12806f32e7eSjoerg }
12906f32e7eSjoerg 
getTheExegesisPowerPCTarget()13006f32e7eSjoerg static ExegesisTarget *getTheExegesisPowerPCTarget() {
13106f32e7eSjoerg   static ExegesisPowerPCTarget Target;
13206f32e7eSjoerg   return &Target;
13306f32e7eSjoerg }
13406f32e7eSjoerg 
InitializePowerPCExegesisTarget()13506f32e7eSjoerg void InitializePowerPCExegesisTarget() {
13606f32e7eSjoerg   ExegesisTarget::registerTarget(getTheExegesisPowerPCTarget());
13706f32e7eSjoerg }
13806f32e7eSjoerg 
13906f32e7eSjoerg } // namespace exegesis
14006f32e7eSjoerg } // namespace llvm
141