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