brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.2 KiB · 0e576fa Raw
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