145 lines · cpp
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-exception6//7// The PowerPC ExegesisTarget.8//===----------------------------------------------------------------------===//9#include "../Target.h"10#include "PPC.h"11#include "PPCRegisterInfo.h"12 13#define GET_AVAILABLE_OPCODE_CHECKER14#include "PPCGenInstrInfo.inc"15 16namespace llvm {17namespace exegesis {18 19// Helper to fill a memory operand with a value.20static 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 29namespace {30class ExegesisPowerPCTarget : public ExegesisTarget {31public:32 ExegesisPowerPCTarget()33 : ExegesisTarget(PPCCpuPfmCounters, PPC_MC::isOpcodeAvailable) {}34 35private: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 namespace46 47static 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.58static 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 bit63 // 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 70MCRegister71ExegesisPowerPCTarget::getScratchMemoryRegister(const Triple &TT) const {72 // R13 is reserved as Thread Pointer, we won't use threading in benchmark, so73 // use it as scratch memory register74 return TT.isArch64Bit() ? PPC::X13 : PPC::R13;75}76 77void 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 reggister89 setMemOp(IT, DispOpIdx, MCOperand::createReg(PPC::X1));90 else91 setMemOp(IT, DispOpIdx, MCOperand::createImm(Offset)); // Disp92 setMemOp(IT, MemOpIdx + 2, MCOperand::createReg(Reg)); // BaseReg93}94 95std::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 one99 // 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 bits110 // 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 yet125 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:" << Reg130 << "\n";131 return {};132}133 134static ExegesisTarget *getTheExegesisPowerPCTarget() {135 static ExegesisPowerPCTarget Target;136 return &Target;137}138 139void InitializePowerPCExegesisTarget() {140 ExegesisTarget::registerTarget(getTheExegesisPowerPCTarget());141}142 143} // namespace exegesis144} // namespace llvm145