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