Path: blob/main/contrib/llvm-project/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp
35294 views
//===-- SystemZMCCodeEmitter.cpp - Convert SystemZ code to machine code ---===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the SystemZMCCodeEmitter class.9//10//===----------------------------------------------------------------------===//1112#include "MCTargetDesc/SystemZMCFixups.h"13#include "MCTargetDesc/SystemZMCTargetDesc.h"14#include "llvm/ADT/SmallVector.h"15#include "llvm/MC/MCCodeEmitter.h"16#include "llvm/MC/MCContext.h"17#include "llvm/MC/MCExpr.h"18#include "llvm/MC/MCFixup.h"19#include "llvm/MC/MCInst.h"20#include "llvm/MC/MCInstrInfo.h"21#include "llvm/MC/MCRegisterInfo.h"22#include "llvm/MC/MCSubtargetInfo.h"23#include "llvm/Support/ErrorHandling.h"24#include <cassert>25#include <cstdint>2627using namespace llvm;2829#define DEBUG_TYPE "mccodeemitter"3031namespace {3233class SystemZMCCodeEmitter : public MCCodeEmitter {34const MCInstrInfo &MCII;35MCContext &Ctx;3637public:38SystemZMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)39: MCII(MCII), Ctx(Ctx) {}4041~SystemZMCCodeEmitter() override = default;4243// OVerride MCCodeEmitter.44void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,45SmallVectorImpl<MCFixup> &Fixups,46const MCSubtargetInfo &STI) const override;4748private:49// Automatically generated by TableGen.50uint64_t getBinaryCodeForInstr(const MCInst &MI,51SmallVectorImpl<MCFixup> &Fixups,52const MCSubtargetInfo &STI) const;53uint32_t getOperandBitOffset(const MCInst &MI, unsigned OpNum,54const MCSubtargetInfo &STI) const;5556// Called by the TableGen code to get the binary encoding of operand57// MO in MI. Fixups is the list of fixups against MI.58uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,59SmallVectorImpl<MCFixup> &Fixups,60const MCSubtargetInfo &STI) const;6162// Return the encoded immediate value for the OpNum operand. If it is a63// symbol, add a fixup for it and return 0.64template <SystemZ::FixupKind Kind>65uint64_t getImmOpValue(const MCInst &MI, unsigned OpNum,66SmallVectorImpl<MCFixup> &Fixups,67const MCSubtargetInfo &STI) const;6869// 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.71template <SystemZ::FixupKind Kind>72uint64_t getLenEncoding(const MCInst &MI, unsigned OpNum,73SmallVectorImpl<MCFixup> &Fixups,74const MCSubtargetInfo &STI) const;7576// 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.81uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,82SmallVectorImpl<MCFixup> &Fixups,83unsigned Kind, int64_t Offset,84bool AllowTLS) const;8586uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,87SmallVectorImpl<MCFixup> &Fixups,88const MCSubtargetInfo &STI) const {89return getPCRelEncoding(MI, OpNum, Fixups,90SystemZ::FK_390_PC16DBL, 2, false);91}92uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,93SmallVectorImpl<MCFixup> &Fixups,94const MCSubtargetInfo &STI) const {95return getPCRelEncoding(MI, OpNum, Fixups,96SystemZ::FK_390_PC32DBL, 2, false);97}98uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum,99SmallVectorImpl<MCFixup> &Fixups,100const MCSubtargetInfo &STI) const {101return getPCRelEncoding(MI, OpNum, Fixups,102SystemZ::FK_390_PC16DBL, 2, true);103}104uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum,105SmallVectorImpl<MCFixup> &Fixups,106const MCSubtargetInfo &STI) const {107return getPCRelEncoding(MI, OpNum, Fixups,108SystemZ::FK_390_PC32DBL, 2, true);109}110uint64_t getPC12DBLBPPEncoding(const MCInst &MI, unsigned OpNum,111SmallVectorImpl<MCFixup> &Fixups,112const MCSubtargetInfo &STI) const {113return getPCRelEncoding(MI, OpNum, Fixups,114SystemZ::FK_390_PC12DBL, 1, false);115}116uint64_t getPC16DBLBPPEncoding(const MCInst &MI, unsigned OpNum,117SmallVectorImpl<MCFixup> &Fixups,118const MCSubtargetInfo &STI) const {119return getPCRelEncoding(MI, OpNum, Fixups,120SystemZ::FK_390_PC16DBL, 4, false);121}122uint64_t getPC24DBLBPPEncoding(const MCInst &MI, unsigned OpNum,123SmallVectorImpl<MCFixup> &Fixups,124const MCSubtargetInfo &STI) const {125return getPCRelEncoding(MI, OpNum, Fixups,126SystemZ::FK_390_PC24DBL, 3, false);127}128};129130} // end anonymous namespace131132void SystemZMCCodeEmitter::encodeInstruction(const MCInst &MI,133SmallVectorImpl<char> &CB,134SmallVectorImpl<MCFixup> &Fixups,135const MCSubtargetInfo &STI) const {136uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);137unsigned Size = MCII.get(MI.getOpcode()).getSize();138// Big-endian insertion of Size bytes.139unsigned ShiftValue = (Size * 8) - 8;140for (unsigned I = 0; I != Size; ++I) {141CB.push_back(uint8_t(Bits >> ShiftValue));142ShiftValue -= 8;143}144}145146uint64_t SystemZMCCodeEmitter::147getMachineOpValue(const MCInst &MI, const MCOperand &MO,148SmallVectorImpl<MCFixup> &Fixups,149const MCSubtargetInfo &STI) const {150if (MO.isReg())151return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());152// SystemZAsmParser::parseAnyRegister() produces KindImm when registers are153// specified as integers.154if (MO.isImm())155return static_cast<uint64_t>(MO.getImm());156llvm_unreachable("Unexpected operand type!");157}158159template <SystemZ::FixupKind Kind>160uint64_t SystemZMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNum,161SmallVectorImpl<MCFixup> &Fixups,162const MCSubtargetInfo &STI) const {163const MCOperand &MO = MI.getOperand(OpNum);164if (MO.isImm())165return static_cast<uint64_t>(MO.getImm());166if (MO.isExpr()) {167unsigned MIBitSize = MCII.get(MI.getOpcode()).getSize() * 8;168uint32_t RawBitOffset = getOperandBitOffset(MI, OpNum, STI);169unsigned OpBitSize =170SystemZ::MCFixupKindInfos[Kind - FirstTargetFixupKind].TargetSize;171uint32_t BitOffset = MIBitSize - RawBitOffset - OpBitSize;172Fixups.push_back(MCFixup::create(BitOffset >> 3, MO.getExpr(),173(MCFixupKind)Kind, MI.getLoc()));174return 0;175}176llvm_unreachable("Unexpected operand type!");177}178179template <SystemZ::FixupKind Kind>180uint64_t181SystemZMCCodeEmitter::getLenEncoding(const MCInst &MI, unsigned OpNum,182SmallVectorImpl<MCFixup> &Fixups,183const MCSubtargetInfo &STI) const {184return getImmOpValue<Kind>(MI, OpNum, Fixups, STI) - 1;185}186187uint64_t188SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,189SmallVectorImpl<MCFixup> &Fixups,190unsigned Kind, int64_t Offset,191bool AllowTLS) const {192SMLoc Loc = MI.getLoc();193const MCOperand &MO = MI.getOperand(OpNum);194const MCExpr *Expr;195if (MO.isImm())196Expr = MCConstantExpr::create(MO.getImm() + Offset, Ctx);197else {198Expr = MO.getExpr();199if (Offset) {200// The operand value is relative to the start of MI, but the fixup201// is relative to the operand field itself, which is Offset bytes202// into MI. Add Offset to the relocation value to cancel out203// this difference.204const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);205Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);206}207}208Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind, Loc));209210// Output the fixup for the TLS marker if present.211if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {212const MCOperand &MOTLS = MI.getOperand(OpNum + 1);213Fixups.push_back(MCFixup::create(2140, MOTLS.getExpr(), (MCFixupKind)SystemZ::FK_390_TLS_CALL, Loc));215}216return 0;217}218219#define GET_OPERAND_BIT_OFFSET220#include "SystemZGenMCCodeEmitter.inc"221222MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,223MCContext &Ctx) {224return new SystemZMCCodeEmitter(MCII, Ctx);225}226227228