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. 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: 29 ExegesisPowerPCTarget() : ExegesisTarget(PPCCpuPfmCounters) {} 30 31 private: 32 std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg, 33 const APInt &Value) const override; 34 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 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. 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 67 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 73 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 91 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 130 static ExegesisTarget *getTheExegesisPowerPCTarget() { 131 static ExegesisPowerPCTarget Target; 132 return &Target; 133 } 134 135 void InitializePowerPCExegesisTarget() { 136 ExegesisTarget::registerTarget(getTheExegesisPowerPCTarget()); 137 } 138 139 } // namespace exegesis 140 } // namespace llvm 141