brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.4 KiB · 383c96e Raw
229 lines · cpp
1//===-- SystemZMCCodeEmitter.cpp - Convert SystemZ code to machine code ---===//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//9// This file implements the SystemZMCCodeEmitter class.10//11//===----------------------------------------------------------------------===//12 13#include "MCTargetDesc/SystemZMCFixups.h"14#include "MCTargetDesc/SystemZMCTargetDesc.h"15#include "llvm/ADT/SmallVector.h"16#include "llvm/MC/MCCodeEmitter.h"17#include "llvm/MC/MCContext.h"18#include "llvm/MC/MCExpr.h"19#include "llvm/MC/MCFixup.h"20#include "llvm/MC/MCInst.h"21#include "llvm/MC/MCInstrInfo.h"22#include "llvm/MC/MCRegisterInfo.h"23#include "llvm/MC/MCSubtargetInfo.h"24#include <cassert>25#include <cstdint>26 27using namespace llvm;28 29#define DEBUG_TYPE "mccodeemitter"30 31namespace {32 33class SystemZMCCodeEmitter : public MCCodeEmitter {34  const MCInstrInfo &MCII;35  MCContext &Ctx;36 37public:38  SystemZMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)39      : MCII(MCII), Ctx(Ctx) {}40 41  ~SystemZMCCodeEmitter() override = default;42 43  // OVerride MCCodeEmitter.44  void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,45                         SmallVectorImpl<MCFixup> &Fixups,46                         const MCSubtargetInfo &STI) const override;47 48private:49  // Automatically generated by TableGen.50  uint64_t getBinaryCodeForInstr(const MCInst &MI,51                                 SmallVectorImpl<MCFixup> &Fixups,52                                 const MCSubtargetInfo &STI) const;53  uint32_t getOperandBitOffset(const MCInst &MI, unsigned OpNum,54                               const MCSubtargetInfo &STI) const;55 56  // Called by the TableGen code to get the binary encoding of operand57  // MO in MI.  Fixups is the list of fixups against MI.58  uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,59                             SmallVectorImpl<MCFixup> &Fixups,60                             const MCSubtargetInfo &STI) const;61 62  // Return the encoded immediate value for the OpNum operand. If it is a63  // symbol, add a fixup for it and return 0.64  template <SystemZ::FixupKind Kind>65  uint64_t getImmOpValue(const MCInst &MI, unsigned OpNum,66                         SmallVectorImpl<MCFixup> &Fixups,67                         const MCSubtargetInfo &STI) const;68 69  // Called by the TableGen code to get the binary encoding of a length value.70  // Length values are encoded by subtracting 1 from the actual value.71  template <SystemZ::FixupKind Kind>72  uint64_t getLenEncoding(const MCInst &MI, unsigned OpNum,73                          SmallVectorImpl<MCFixup> &Fixups,74                          const MCSubtargetInfo &STI) const;75 76  // Operand OpNum of MI needs a PC-relative fixup of kind Kind at77  // Offset bytes from the start of MI.  Add the fixup to Fixups78  // and return the in-place addend, which since we're a RELA target79  // is always 0.  If AllowTLS is true and optional operand OpNum + 180  // is present, also emit a TLS call fixup for it.81  uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,82                            SmallVectorImpl<MCFixup> &Fixups,83                            unsigned Kind, int64_t Offset,84                            bool AllowTLS) const;85 86  uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,87                              SmallVectorImpl<MCFixup> &Fixups,88                              const MCSubtargetInfo &STI) const {89    return getPCRelEncoding(MI, OpNum, Fixups,90                            SystemZ::FK_390_PC16DBL, 2, false);91  }92  uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,93                              SmallVectorImpl<MCFixup> &Fixups,94                              const MCSubtargetInfo &STI) const {95    return getPCRelEncoding(MI, OpNum, Fixups,96                            SystemZ::FK_390_PC32DBL, 2, false);97  }98  uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum,99                                 SmallVectorImpl<MCFixup> &Fixups,100                                 const MCSubtargetInfo &STI) const {101    return getPCRelEncoding(MI, OpNum, Fixups,102                            SystemZ::FK_390_PC16DBL, 2, true);103  }104  uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum,105                                 SmallVectorImpl<MCFixup> &Fixups,106                                 const MCSubtargetInfo &STI) const {107    return getPCRelEncoding(MI, OpNum, Fixups,108                            SystemZ::FK_390_PC32DBL, 2, true);109  }110  uint64_t getPC12DBLBPPEncoding(const MCInst &MI, unsigned OpNum,111                                 SmallVectorImpl<MCFixup> &Fixups,112                                 const MCSubtargetInfo &STI) const {113    return getPCRelEncoding(MI, OpNum, Fixups,114                            SystemZ::FK_390_PC12DBL, 1, false);115  }116  uint64_t getPC16DBLBPPEncoding(const MCInst &MI, unsigned OpNum,117                                 SmallVectorImpl<MCFixup> &Fixups,118                                 const MCSubtargetInfo &STI) const {119    return getPCRelEncoding(MI, OpNum, Fixups,120                            SystemZ::FK_390_PC16DBL, 4, false);121  }122  uint64_t getPC24DBLBPPEncoding(const MCInst &MI, unsigned OpNum,123                                 SmallVectorImpl<MCFixup> &Fixups,124                                 const MCSubtargetInfo &STI) const {125    return getPCRelEncoding(MI, OpNum, Fixups,126                            SystemZ::FK_390_PC24DBL, 3, false);127  }128};129 130} // end anonymous namespace131  //132static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,133                     const MCExpr *Value, uint16_t Kind, bool PCRel = false) {134  Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));135}136 137void SystemZMCCodeEmitter::encodeInstruction(const MCInst &MI,138                                             SmallVectorImpl<char> &CB,139                                             SmallVectorImpl<MCFixup> &Fixups,140                                             const MCSubtargetInfo &STI) const {141  uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);142  unsigned Size = MCII.get(MI.getOpcode()).getSize();143  // Big-endian insertion of Size bytes.144  unsigned ShiftValue = (Size * 8) - 8;145  for (unsigned I = 0; I != Size; ++I) {146    CB.push_back(uint8_t(Bits >> ShiftValue));147    ShiftValue -= 8;148  }149}150 151uint64_t SystemZMCCodeEmitter::152getMachineOpValue(const MCInst &MI, const MCOperand &MO,153                  SmallVectorImpl<MCFixup> &Fixups,154                  const MCSubtargetInfo &STI) const {155  if (MO.isReg())156    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());157  // SystemZAsmParser::parseAnyRegister() produces KindImm when registers are158  // specified as integers.159  if (MO.isImm())160    return static_cast<uint64_t>(MO.getImm());161  llvm_unreachable("Unexpected operand type!");162}163 164template <SystemZ::FixupKind Kind>165uint64_t SystemZMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNum,166                                             SmallVectorImpl<MCFixup> &Fixups,167                                             const MCSubtargetInfo &STI) const {168  const MCOperand &MO = MI.getOperand(OpNum);169  if (MO.isImm())170    return static_cast<uint64_t>(MO.getImm());171  if (MO.isExpr()) {172    unsigned MIBitSize = MCII.get(MI.getOpcode()).getSize() * 8;173    uint32_t RawBitOffset = getOperandBitOffset(MI, OpNum, STI);174    unsigned OpBitSize =175        SystemZ::MCFixupKindInfos[Kind - FirstTargetFixupKind].TargetSize;176    uint32_t BitOffset = MIBitSize - RawBitOffset - OpBitSize;177    addFixup(Fixups, BitOffset >> 3, MO.getExpr(), Kind);178    return 0;179  }180  llvm_unreachable("Unexpected operand type!");181}182 183template <SystemZ::FixupKind Kind>184uint64_t185SystemZMCCodeEmitter::getLenEncoding(const MCInst &MI, unsigned OpNum,186                                     SmallVectorImpl<MCFixup> &Fixups,187                                     const MCSubtargetInfo &STI) const {188  return getImmOpValue<Kind>(MI, OpNum, Fixups, STI) - 1;189}190 191uint64_t192SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,193                                       SmallVectorImpl<MCFixup> &Fixups,194                                       unsigned Kind, int64_t Offset,195                                       bool AllowTLS) const {196  SMLoc Loc = MI.getLoc();197  const MCOperand &MO = MI.getOperand(OpNum);198  const MCExpr *Expr;199  if (MO.isImm())200    Expr = MCConstantExpr::create(MO.getImm() + Offset, Ctx);201  else {202    Expr = MO.getExpr();203    if (Offset) {204      // The operand value is relative to the start of MI, but the fixup205      // is relative to the operand field itself, which is Offset bytes206      // into MI.  Add Offset to the relocation value to cancel out207      // this difference.208      const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);209      Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx, Loc);210    }211  }212  addFixup(Fixups, Offset, Expr, Kind, true);213 214  // Output the fixup for the TLS marker if present.215  if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {216    const MCOperand &MOTLS = MI.getOperand(OpNum + 1);217    addFixup(Fixups, 0, MOTLS.getExpr(), SystemZ::FK_390_TLS_CALL);218  }219  return 0;220}221 222#define GET_OPERAND_BIT_OFFSET223#include "SystemZGenMCCodeEmitter.inc"224 225MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,226                                                MCContext &Ctx) {227  return new SystemZMCCodeEmitter(MCII, Ctx);228}229