Path: blob/main/contrib/llvm-project/llvm/lib/Target/Lanai/MCTargetDesc/LanaiMCCodeEmitter.cpp
35295 views
//===-- LanaiMCCodeEmitter.cpp - Convert Lanai 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 LanaiMCCodeEmitter class.9//10//===----------------------------------------------------------------------===//1112#include "LanaiAluCode.h"13#include "MCTargetDesc/LanaiBaseInfo.h"14#include "MCTargetDesc/LanaiFixupKinds.h"15#include "MCTargetDesc/LanaiMCExpr.h"16#include "llvm/ADT/SmallVector.h"17#include "llvm/ADT/Statistic.h"18#include "llvm/MC/MCCodeEmitter.h"19#include "llvm/MC/MCExpr.h"20#include "llvm/MC/MCFixup.h"21#include "llvm/MC/MCInst.h"22#include "llvm/MC/MCInstrInfo.h"23#include "llvm/MC/MCRegisterInfo.h"24#include "llvm/MC/MCSubtargetInfo.h"25#include "llvm/Support/Casting.h"26#include "llvm/Support/EndianStream.h"27#include "llvm/Support/raw_ostream.h"28#include <cassert>29#include <cstdint>3031#define DEBUG_TYPE "mccodeemitter"3233STATISTIC(MCNumEmitted, "Number of MC instructions emitted");3435namespace llvm {3637namespace {3839class LanaiMCCodeEmitter : public MCCodeEmitter {40public:41LanaiMCCodeEmitter(const MCInstrInfo &MCII, MCContext &C) {}42LanaiMCCodeEmitter(const LanaiMCCodeEmitter &) = delete;43void operator=(const LanaiMCCodeEmitter &) = delete;44~LanaiMCCodeEmitter() override = default;4546// The functions below are called by TableGen generated functions for getting47// the binary encoding of instructions/opereands.4849// getBinaryCodeForInstr - TableGen'erated function for getting the50// binary encoding for an instruction.51uint64_t getBinaryCodeForInstr(const MCInst &Inst,52SmallVectorImpl<MCFixup> &Fixups,53const MCSubtargetInfo &SubtargetInfo) const;5455// getMachineOpValue - Return binary encoding of operand. If the machine56// operand requires relocation, record the relocation and return zero.57unsigned getMachineOpValue(const MCInst &Inst, const MCOperand &MCOp,58SmallVectorImpl<MCFixup> &Fixups,59const MCSubtargetInfo &SubtargetInfo) const;6061unsigned getRiMemoryOpValue(const MCInst &Inst, unsigned OpNo,62SmallVectorImpl<MCFixup> &Fixups,63const MCSubtargetInfo &SubtargetInfo) const;6465unsigned getRrMemoryOpValue(const MCInst &Inst, unsigned OpNo,66SmallVectorImpl<MCFixup> &Fixups,67const MCSubtargetInfo &SubtargetInfo) const;6869unsigned getSplsOpValue(const MCInst &Inst, unsigned OpNo,70SmallVectorImpl<MCFixup> &Fixups,71const MCSubtargetInfo &SubtargetInfo) const;7273unsigned getBranchTargetOpValue(const MCInst &Inst, unsigned OpNo,74SmallVectorImpl<MCFixup> &Fixups,75const MCSubtargetInfo &SubtargetInfo) const;7677void encodeInstruction(const MCInst &Inst, SmallVectorImpl<char> &CB,78SmallVectorImpl<MCFixup> &Fixups,79const MCSubtargetInfo &SubtargetInfo) const override;8081unsigned adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value,82const MCSubtargetInfo &STI) const;8384unsigned adjustPqBitsSpls(const MCInst &Inst, unsigned Value,85const MCSubtargetInfo &STI) const;86};8788} // end anonymous namespace8990static Lanai::Fixups FixupKind(const MCExpr *Expr) {91if (isa<MCSymbolRefExpr>(Expr))92return Lanai::FIXUP_LANAI_21;93if (const LanaiMCExpr *McExpr = dyn_cast<LanaiMCExpr>(Expr)) {94LanaiMCExpr::VariantKind ExprKind = McExpr->getKind();95switch (ExprKind) {96case LanaiMCExpr::VK_Lanai_None:97return Lanai::FIXUP_LANAI_21;98case LanaiMCExpr::VK_Lanai_ABS_HI:99return Lanai::FIXUP_LANAI_HI16;100case LanaiMCExpr::VK_Lanai_ABS_LO:101return Lanai::FIXUP_LANAI_LO16;102}103}104return Lanai::Fixups(0);105}106107// getMachineOpValue - Return binary encoding of operand. If the machine108// operand requires relocation, record the relocation and return zero.109unsigned LanaiMCCodeEmitter::getMachineOpValue(110const MCInst &Inst, const MCOperand &MCOp, SmallVectorImpl<MCFixup> &Fixups,111const MCSubtargetInfo &SubtargetInfo) const {112if (MCOp.isReg())113return getLanaiRegisterNumbering(MCOp.getReg());114if (MCOp.isImm())115return static_cast<unsigned>(MCOp.getImm());116117// MCOp must be an expression118assert(MCOp.isExpr());119const MCExpr *Expr = MCOp.getExpr();120121// Extract the symbolic reference side of a binary expression.122if (Expr->getKind() == MCExpr::Binary) {123const MCBinaryExpr *BinaryExpr = static_cast<const MCBinaryExpr *>(Expr);124Expr = BinaryExpr->getLHS();125}126127assert(isa<LanaiMCExpr>(Expr) || Expr->getKind() == MCExpr::SymbolRef);128// Push fixup (all info is contained within)129Fixups.push_back(130MCFixup::create(0, MCOp.getExpr(), MCFixupKind(FixupKind(Expr))));131return 0;132}133134// Helper function to adjust P and Q bits on load and store instructions.135static unsigned adjustPqBits(const MCInst &Inst, unsigned Value,136unsigned PBitShift, unsigned QBitShift) {137const MCOperand AluOp = Inst.getOperand(3);138unsigned AluCode = AluOp.getImm();139140// Set the P bit to one iff the immediate is nonzero and not a post-op141// instruction.142const MCOperand Op2 = Inst.getOperand(2);143Value &= ~(1 << PBitShift);144if (!LPAC::isPostOp(AluCode) &&145((Op2.isImm() && Op2.getImm() != 0) ||146(Op2.isReg() && Op2.getReg() != Lanai::R0) || (Op2.isExpr())))147Value |= (1 << PBitShift);148149// Set the Q bit to one iff it is a post- or pre-op instruction.150assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&151"Expected register operand.");152Value &= ~(1 << QBitShift);153if (LPAC::modifiesOp(AluCode) && ((Op2.isImm() && Op2.getImm() != 0) ||154(Op2.isReg() && Op2.getReg() != Lanai::R0)))155Value |= (1 << QBitShift);156157return Value;158}159160unsigned161LanaiMCCodeEmitter::adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value,162const MCSubtargetInfo &STI) const {163return adjustPqBits(Inst, Value, 17, 16);164}165166unsigned167LanaiMCCodeEmitter::adjustPqBitsSpls(const MCInst &Inst, unsigned Value,168const MCSubtargetInfo &STI) const {169return adjustPqBits(Inst, Value, 11, 10);170}171172void LanaiMCCodeEmitter::encodeInstruction(173const MCInst &Inst, SmallVectorImpl<char> &CB,174SmallVectorImpl<MCFixup> &Fixups,175const MCSubtargetInfo &SubtargetInfo) const {176// Get instruction encoding and emit it177unsigned Value = getBinaryCodeForInstr(Inst, Fixups, SubtargetInfo);178++MCNumEmitted; // Keep track of the number of emitted insns.179180support::endian::write<uint32_t>(CB, Value, llvm::endianness::big);181}182183// Encode Lanai Memory Operand184unsigned LanaiMCCodeEmitter::getRiMemoryOpValue(185const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,186const MCSubtargetInfo &SubtargetInfo) const {187unsigned Encoding;188const MCOperand Op1 = Inst.getOperand(OpNo + 0);189const MCOperand Op2 = Inst.getOperand(OpNo + 1);190const MCOperand AluOp = Inst.getOperand(OpNo + 2);191192assert(Op1.isReg() && "First operand is not register.");193assert((Op2.isImm() || Op2.isExpr()) &&194"Second operand is neither an immediate nor an expression.");195assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) &&196"Register immediate only supports addition operator");197198Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 18);199if (Op2.isImm()) {200assert(isInt<16>(Op2.getImm()) &&201"Constant value truncated (limited to 16-bit)");202203Encoding |= (Op2.getImm() & 0xffff);204if (Op2.getImm() != 0) {205if (LPAC::isPreOp(AluOp.getImm()))206Encoding |= (0x3 << 16);207if (LPAC::isPostOp(AluOp.getImm()))208Encoding |= (0x1 << 16);209}210} else211getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo);212213return Encoding;214}215216unsigned LanaiMCCodeEmitter::getRrMemoryOpValue(217const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,218const MCSubtargetInfo &SubtargetInfo) const {219unsigned Encoding;220const MCOperand Op1 = Inst.getOperand(OpNo + 0);221const MCOperand Op2 = Inst.getOperand(OpNo + 1);222const MCOperand AluMCOp = Inst.getOperand(OpNo + 2);223224assert(Op1.isReg() && "First operand is not register.");225Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 15);226assert(Op2.isReg() && "Second operand is not register.");227Encoding |= (getLanaiRegisterNumbering(Op2.getReg()) << 10);228229assert(AluMCOp.isImm() && "Third operator is not immediate.");230// Set BBB231unsigned AluOp = AluMCOp.getImm();232Encoding |= LPAC::encodeLanaiAluCode(AluOp) << 5;233// Set P and Q234if (LPAC::isPreOp(AluOp))235Encoding |= (0x3 << 8);236if (LPAC::isPostOp(AluOp))237Encoding |= (0x1 << 8);238// Set JJJJ239switch (LPAC::getAluOp(AluOp)) {240case LPAC::SHL:241case LPAC::SRL:242Encoding |= 0x10;243break;244case LPAC::SRA:245Encoding |= 0x18;246break;247default:248break;249}250251return Encoding;252}253254unsigned255LanaiMCCodeEmitter::getSplsOpValue(const MCInst &Inst, unsigned OpNo,256SmallVectorImpl<MCFixup> &Fixups,257const MCSubtargetInfo &SubtargetInfo) const {258unsigned Encoding;259const MCOperand Op1 = Inst.getOperand(OpNo + 0);260const MCOperand Op2 = Inst.getOperand(OpNo + 1);261const MCOperand AluOp = Inst.getOperand(OpNo + 2);262263assert(Op1.isReg() && "First operand is not register.");264assert((Op2.isImm() || Op2.isExpr()) &&265"Second operand is neither an immediate nor an expression.");266assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) &&267"Register immediate only supports addition operator");268269Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 12);270if (Op2.isImm()) {271assert(isInt<10>(Op2.getImm()) &&272"Constant value truncated (limited to 10-bit)");273274Encoding |= (Op2.getImm() & 0x3ff);275if (Op2.getImm() != 0) {276if (LPAC::isPreOp(AluOp.getImm()))277Encoding |= (0x3 << 10);278if (LPAC::isPostOp(AluOp.getImm()))279Encoding |= (0x1 << 10);280}281} else282getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo);283284return Encoding;285}286287unsigned LanaiMCCodeEmitter::getBranchTargetOpValue(288const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,289const MCSubtargetInfo &SubtargetInfo) const {290const MCOperand &MCOp = Inst.getOperand(OpNo);291if (MCOp.isReg() || MCOp.isImm())292return getMachineOpValue(Inst, MCOp, Fixups, SubtargetInfo);293294Fixups.push_back(MCFixup::create(2950, MCOp.getExpr(), static_cast<MCFixupKind>(Lanai::FIXUP_LANAI_25)));296297return 0;298}299300#include "LanaiGenMCCodeEmitter.inc"301302} // end namespace llvm303304llvm::MCCodeEmitter *305llvm::createLanaiMCCodeEmitter(const MCInstrInfo &InstrInfo,306MCContext &context) {307return new LanaiMCCodeEmitter(InstrInfo, context);308}309310311