1 //===-- Target.cpp ----------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 // The PowerPC ExegesisTarget.
8 //===----------------------------------------------------------------------===//
9 #include "../Target.h"
10 #include "PPC.h"
11 #include "PPCRegisterInfo.h"
12
13 namespace llvm {
14 namespace exegesis {
15
16 // Helper to fill a memory operand with a value.
setMemOp(InstructionTemplate & IT,int OpIdx,const MCOperand & OpVal)17 static void setMemOp(InstructionTemplate &IT, int OpIdx,
18 const MCOperand &OpVal) {
19 const auto Op = IT.getInstr().Operands[OpIdx];
20 assert(Op.isExplicit() && "invalid memory pattern");
21 IT.getValueFor(Op) = OpVal;
22 }
23
24 #include "PPCGenExegesis.inc"
25
26 namespace {
27 class ExegesisPowerPCTarget : public ExegesisTarget {
28 public:
ExegesisPowerPCTarget()29 ExegesisPowerPCTarget() : ExegesisTarget(PPCCpuPfmCounters) {}
30
31 private:
32 std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
33 const APInt &Value) const override;
matchesArch(Triple::ArchType Arch) const34 bool matchesArch(Triple::ArchType Arch) const override {
35 return Arch == Triple::ppc64le;
36 }
37 unsigned getScratchMemoryRegister(const Triple &) const override;
38 void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
39 unsigned Offset) const override;
40 };
41 } // end anonymous namespace
42
getLoadImmediateOpcode(unsigned RegBitWidth)43 static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) {
44 switch (RegBitWidth) {
45 case 32:
46 return PPC::LI;
47 case 64:
48 return PPC::LI8;
49 }
50 llvm_unreachable("Invalid Value Width");
51 }
52
53 // Generates instruction to load an immediate value into a register.
loadImmediate(unsigned Reg,unsigned RegBitWidth,const APInt & Value)54 static MCInst loadImmediate(unsigned Reg, unsigned RegBitWidth,
55 const APInt &Value) {
56 if (Value.getBitWidth() > RegBitWidth)
57 llvm_unreachable("Value must fit in the Register");
58 // We don't really care the value in reg, ignore the 16 bit
59 // restriction for now.
60 // TODO: make sure we get the exact value in reg if needed.
61 return MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
62 .addReg(Reg)
63 .addImm(Value.getZExtValue());
64 }
65
66 unsigned
getScratchMemoryRegister(const Triple & TT) const67 ExegesisPowerPCTarget::getScratchMemoryRegister(const Triple &TT) const {
68 // R13 is reserved as Thread Pointer, we won't use threading in benchmark, so
69 // use it as scratch memory register
70 return TT.isArch64Bit() ? PPC::X13 : PPC::R13;
71 }
72
fillMemoryOperands(InstructionTemplate & IT,unsigned Reg,unsigned Offset) const73 void ExegesisPowerPCTarget::fillMemoryOperands(InstructionTemplate &IT,
74 unsigned Reg,
75 unsigned Offset) const {
76 int MemOpIdx = 0;
77 if (IT.getInstr().hasTiedRegisters())
78 MemOpIdx = 1;
79 int DispOpIdx = MemOpIdx + 1;
80 const auto DispOp = IT.getInstr().Operands[DispOpIdx];
81 if (DispOp.isReg())
82 // We don't really care about the real address in snippets,
83 // So hardcode X1 for X-form Memory Operations for simplicity.
84 // TODO: materialize the offset into a reggister
85 setMemOp(IT, DispOpIdx, MCOperand::createReg(PPC::X1));
86 else
87 setMemOp(IT, DispOpIdx, MCOperand::createImm(Offset)); // Disp
88 setMemOp(IT, MemOpIdx + 2, MCOperand::createReg(Reg)); // BaseReg
89 }
90
setRegTo(const MCSubtargetInfo & STI,unsigned Reg,const APInt & Value) const91 std::vector<MCInst> ExegesisPowerPCTarget::setRegTo(const MCSubtargetInfo &STI,
92 unsigned Reg,
93 const APInt &Value) const {
94 // X11 is optional use in function linkage, should be the least used one
95 // Use it as scratch reg to load immediate.
96 unsigned ScratchImmReg = PPC::X11;
97
98 if (PPC::GPRCRegClass.contains(Reg))
99 return {loadImmediate(Reg, 32, Value)};
100 if (PPC::G8RCRegClass.contains(Reg))
101 return {loadImmediate(Reg, 64, Value)};
102 if (PPC::F4RCRegClass.contains(Reg))
103 return {loadImmediate(ScratchImmReg, 64, Value),
104 MCInstBuilder(PPC::MTVSRD).addReg(Reg).addReg(ScratchImmReg)};
105 // We don't care the real value in reg, so set 64 bits or duplicate 64 bits
106 // for simplicity.
107 // TODO: update these if we need a accurate 128 values in registers.
108 if (PPC::VRRCRegClass.contains(Reg))
109 return {loadImmediate(ScratchImmReg, 64, Value),
110 MCInstBuilder(PPC::MTVRD).addReg(Reg).addReg(ScratchImmReg)};
111 if (PPC::VSRCRegClass.contains(Reg))
112 return {loadImmediate(ScratchImmReg, 64, Value),
113 MCInstBuilder(PPC::MTVSRDD)
114 .addReg(Reg)
115 .addReg(ScratchImmReg)
116 .addReg(ScratchImmReg)};
117 if (PPC::VFRCRegClass.contains(Reg))
118 return {loadImmediate(ScratchImmReg, 64, Value),
119 MCInstBuilder(PPC::MTVSRD).addReg(Reg).addReg(ScratchImmReg)};
120 // SPE not supported yet
121 if (PPC::SPERCRegClass.contains(Reg)) {
122 errs() << "Unsupported SPE Reg:" << Reg << "\n";
123 return {};
124 }
125 errs() << "setRegTo is not implemented, results will be unreliable:" << Reg
126 << "\n";
127 return {};
128 }
129
getTheExegesisPowerPCTarget()130 static ExegesisTarget *getTheExegesisPowerPCTarget() {
131 static ExegesisPowerPCTarget Target;
132 return &Target;
133 }
134
InitializePowerPCExegesisTarget()135 void InitializePowerPCExegesisTarget() {
136 ExegesisTarget::registerTarget(getTheExegesisPowerPCTarget());
137 }
138
139 } // namespace exegesis
140 } // namespace llvm
141