brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · f9666d9 Raw
174 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//===----------------------------------------------------------------------===//8#include "../Error.h"9#include "../Target.h"10#include "MCTargetDesc/MipsBaseInfo.h"11#include "Mips.h"12#include "MipsRegisterInfo.h"13 14#define GET_AVAILABLE_OPCODE_CHECKER15#include "MipsGenInstrInfo.inc"16 17namespace llvm {18namespace exegesis {19 20#ifndef NDEBUG21// Returns an error if we cannot handle the memory references in this22// instruction.23static Error isInvalidMemoryInstr(const Instruction &Instr) {24  switch (Instr.Description.TSFlags & MipsII::FormMask) {25  default:26    llvm_unreachable("Unknown FormMask value");27  // These have no memory access.28  case MipsII::Pseudo:29  case MipsII::FrmR:30  case MipsII::FrmJ:31  case MipsII::FrmFR:32    return Error::success();33  // These access memory and are handled.34  case MipsII::FrmI:35    return Error::success();36  // These access memory and are not handled yet.37  case MipsII::FrmFI:38  case MipsII::FrmOther:39    return make_error<Failure>("unsupported opcode: non uniform memory access");40  }41}42#endif43 44// Helper to fill a memory operand with a value.45static void setMemOp(InstructionTemplate &IT, int OpIdx,46                     const MCOperand &OpVal) {47  const auto Op = IT.getInstr().Operands[OpIdx];48  assert(Op.isExplicit() && "invalid memory pattern");49  IT.getValueFor(Op) = OpVal;50}51 52#include "MipsGenExegesis.inc"53 54namespace {55class ExegesisMipsTarget : public ExegesisTarget {56public:57  ExegesisMipsTarget()58      : ExegesisTarget(MipsCpuPfmCounters, Mips_MC::isOpcodeAvailable) {}59 60private:61  MCRegister getScratchMemoryRegister(const Triple &TT) const override;62  unsigned getMaxMemoryAccessSize() const override { return 64; }63  void fillMemoryOperands(InstructionTemplate &IT, MCRegister Reg,64                          unsigned Offset) const override;65 66  std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, MCRegister Reg,67                               const APInt &Value) const override;68  bool matchesArch(Triple::ArchType Arch) const override {69    return Arch == Triple::mips || Arch == Triple::mipsel ||70           Arch == Triple::mips64 || Arch == Triple::mips64el;71  }72};73} // end anonymous namespace74 75// Generates instructions to load an immediate value into a register.76static std::vector<MCInst> loadImmediate(MCRegister Reg, bool IsGPR32,77                                         const APInt &Value) {78  unsigned ZeroReg;79  unsigned ORi, LUi, SLL;80  if (IsGPR32) {81    ZeroReg = Mips::ZERO;82    ORi = Mips::ORi;83    SLL = Mips::SLL;84    LUi = Mips::LUi;85  } else {86    ZeroReg = Mips::ZERO_64;87    ORi = Mips::ORi64;88    SLL = Mips::SLL64_64;89    LUi = Mips::LUi64;90  }91 92  if (Value.isIntN(16)) {93    return {MCInstBuilder(ORi)94        .addReg(Reg)95        .addReg(ZeroReg)96        .addImm(Value.getZExtValue())};97  }98 99  std::vector<MCInst> Instructions;100  if (Value.isIntN(32)) {101    const uint16_t HiBits = Value.getHiBits(16).getZExtValue();102    if (!IsGPR32 && Value.getActiveBits() == 32) {103      // Expand to an ORi instead of a LUi to avoid sign-extending into the104      // upper 32 bits.105      Instructions.push_back(106          MCInstBuilder(ORi)107              .addReg(Reg)108              .addReg(ZeroReg)109              .addImm(HiBits));110      Instructions.push_back(111          MCInstBuilder(SLL)112              .addReg(Reg)113              .addReg(Reg)114              .addImm(16));115    } else {116      Instructions.push_back(117          MCInstBuilder(LUi)118              .addReg(Reg)119              .addImm(HiBits));120    }121 122    const uint16_t LoBits = Value.getLoBits(16).getZExtValue();123    if (LoBits) {124      Instructions.push_back(125          MCInstBuilder(ORi)126          .addReg(Reg)127          .addReg(ZeroReg)128          .addImm(LoBits));129    }130 131    return Instructions;132  }133 134  llvm_unreachable("Not implemented for values wider than 32 bits");135}136 137MCRegister138ExegesisMipsTarget::getScratchMemoryRegister(const Triple &TT) const {139  return TT.isArch64Bit() ? Mips::A0_64 : Mips::A0;140}141 142void ExegesisMipsTarget::fillMemoryOperands(InstructionTemplate &IT,143                                            MCRegister Reg,144                                            unsigned Offset) const {145  assert(!isInvalidMemoryInstr(IT.getInstr()) &&146         "fillMemoryOperands requires a valid memory instruction");147  setMemOp(IT, 0, MCOperand::createReg(0));      // IndexReg148  setMemOp(IT, 1, MCOperand::createReg(Reg));    // BaseReg149  setMemOp(IT, 2, MCOperand::createImm(Offset)); // Disp150}151 152std::vector<MCInst> ExegesisMipsTarget::setRegTo(const MCSubtargetInfo &STI,153                                                 MCRegister Reg,154                                                 const APInt &Value) const {155  if (Mips::GPR32RegClass.contains(Reg))156    return loadImmediate(Reg, true, Value);157  if (Mips::GPR64RegClass.contains(Reg))158    return loadImmediate(Reg, false, Value);159  errs() << "setRegTo is not implemented, results will be unreliable\n";160  return {};161}162 163static ExegesisTarget *getTheExegesisMipsTarget() {164  static ExegesisMipsTarget Target;165  return &Target;166}167 168void InitializeMipsExegesisTarget() {169  ExegesisTarget::registerTarget(getTheExegesisMipsTarget());170}171 172} // namespace exegesis173} // namespace llvm174