Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
35294 views
//===-- PPCMCCodeEmitter.cpp - Convert PPC 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 PPCMCCodeEmitter class.9//10//===----------------------------------------------------------------------===//1112#include "PPCMCCodeEmitter.h"13#include "MCTargetDesc/PPCFixupKinds.h"14#include "PPCMCTargetDesc.h"15#include "llvm/ADT/SmallVector.h"16#include "llvm/ADT/Statistic.h"17#include "llvm/MC/MCExpr.h"18#include "llvm/MC/MCFixup.h"19#include "llvm/MC/MCInstrDesc.h"20#include "llvm/MC/MCRegisterInfo.h"21#include "llvm/Support/Casting.h"22#include "llvm/Support/Endian.h"23#include "llvm/Support/EndianStream.h"24#include "llvm/Support/ErrorHandling.h"25#include "llvm/Support/MathExtras.h"26#include "llvm/Support/raw_ostream.h"27#include "llvm/TargetParser/Triple.h"28#include <cassert>29#include <cstdint>3031using namespace llvm;3233#define DEBUG_TYPE "mccodeemitter"3435STATISTIC(MCNumEmitted, "Number of MC instructions emitted");3637MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,38MCContext &Ctx) {39return new PPCMCCodeEmitter(MCII, Ctx);40}4142unsigned PPCMCCodeEmitter::43getDirectBrEncoding(const MCInst &MI, unsigned OpNo,44SmallVectorImpl<MCFixup> &Fixups,45const MCSubtargetInfo &STI) const {46const MCOperand &MO = MI.getOperand(OpNo);4748if (MO.isReg() || MO.isImm())49return getMachineOpValue(MI, MO, Fixups, STI);5051// Add a fixup for the branch target.52Fixups.push_back(MCFixup::create(0, MO.getExpr(),53(isNoTOCCallInstr(MI)54? (MCFixupKind)PPC::fixup_ppc_br24_notoc55: (MCFixupKind)PPC::fixup_ppc_br24)));56return 0;57}5859/// Check if Opcode corresponds to a call instruction that should be marked60/// with the NOTOC relocation.61bool PPCMCCodeEmitter::isNoTOCCallInstr(const MCInst &MI) const {62unsigned Opcode = MI.getOpcode();63if (!MCII.get(Opcode).isCall())64return false;6566switch (Opcode) {67default:68#ifndef NDEBUG69llvm_unreachable("Unknown call opcode");70#endif71return false;72case PPC::BL8_NOTOC:73case PPC::BL8_NOTOC_TLS:74case PPC::BL8_NOTOC_RM:75return true;76#ifndef NDEBUG77case PPC::BL8:78case PPC::BL:79case PPC::BL8_TLS:80case PPC::BL_TLS:81case PPC::BLA8:82case PPC::BLA:83case PPC::BCCL:84case PPC::BCCLA:85case PPC::BCL:86case PPC::BCLn:87case PPC::BL8_NOP:88case PPC::BL_NOP:89case PPC::BL8_NOP_TLS:90case PPC::BLA8_NOP:91case PPC::BCTRL8:92case PPC::BCTRL:93case PPC::BCCCTRL8:94case PPC::BCCCTRL:95case PPC::BCCTRL8:96case PPC::BCCTRL:97case PPC::BCCTRL8n:98case PPC::BCCTRLn:99case PPC::BL8_RM:100case PPC::BLA8_RM:101case PPC::BL8_NOP_RM:102case PPC::BLA8_NOP_RM:103case PPC::BCTRL8_RM:104case PPC::BCTRL8_LDinto_toc:105case PPC::BCTRL8_LDinto_toc_RM:106case PPC::BL8_TLS_:107case PPC::TCRETURNdi8:108case PPC::TCRETURNai8:109case PPC::TCRETURNri8:110case PPC::TAILBCTR8:111case PPC::TAILB8:112case PPC::TAILBA8:113case PPC::BCLalways:114case PPC::BLRL:115case PPC::BCCLRL:116case PPC::BCLRL:117case PPC::BCLRLn:118case PPC::BDZL:119case PPC::BDNZL:120case PPC::BDZLA:121case PPC::BDNZLA:122case PPC::BDZLp:123case PPC::BDNZLp:124case PPC::BDZLAp:125case PPC::BDNZLAp:126case PPC::BDZLm:127case PPC::BDNZLm:128case PPC::BDZLAm:129case PPC::BDNZLAm:130case PPC::BDZLRL:131case PPC::BDNZLRL:132case PPC::BDZLRLp:133case PPC::BDNZLRLp:134case PPC::BDZLRLm:135case PPC::BDNZLRLm:136case PPC::BL_RM:137case PPC::BLA_RM:138case PPC::BL_NOP_RM:139case PPC::BCTRL_RM:140case PPC::TCRETURNdi:141case PPC::TCRETURNai:142case PPC::TCRETURNri:143case PPC::BCTRL_LWZinto_toc:144case PPC::BCTRL_LWZinto_toc_RM:145case PPC::TAILBCTR:146case PPC::TAILB:147case PPC::TAILBA:148return false;149#endif150}151}152153unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,154SmallVectorImpl<MCFixup> &Fixups,155const MCSubtargetInfo &STI) const {156const MCOperand &MO = MI.getOperand(OpNo);157if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);158159// Add a fixup for the branch target.160Fixups.push_back(MCFixup::create(0, MO.getExpr(),161(MCFixupKind)PPC::fixup_ppc_brcond14));162return 0;163}164165unsigned PPCMCCodeEmitter::166getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,167SmallVectorImpl<MCFixup> &Fixups,168const MCSubtargetInfo &STI) const {169const MCOperand &MO = MI.getOperand(OpNo);170if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);171172// Add a fixup for the branch target.173Fixups.push_back(MCFixup::create(0, MO.getExpr(),174(MCFixupKind)PPC::fixup_ppc_br24abs));175return 0;176}177178unsigned PPCMCCodeEmitter::179getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,180SmallVectorImpl<MCFixup> &Fixups,181const MCSubtargetInfo &STI) const {182const MCOperand &MO = MI.getOperand(OpNo);183if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);184185// Add a fixup for the branch target.186Fixups.push_back(MCFixup::create(0, MO.getExpr(),187(MCFixupKind)PPC::fixup_ppc_brcond14abs));188return 0;189}190191unsigned192PPCMCCodeEmitter::getVSRpEvenEncoding(const MCInst &MI, unsigned OpNo,193SmallVectorImpl<MCFixup> &Fixups,194const MCSubtargetInfo &STI) const {195assert(MI.getOperand(OpNo).isReg() && "Operand should be a register");196unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI)197<< 1;198return RegBits;199}200201unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo,202SmallVectorImpl<MCFixup> &Fixups,203const MCSubtargetInfo &STI) const {204const MCOperand &MO = MI.getOperand(OpNo);205if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);206207// Add a fixup for the immediate field.208Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),209(MCFixupKind)PPC::fixup_ppc_half16));210return 0;211}212213uint64_t PPCMCCodeEmitter::getImm34Encoding(const MCInst &MI, unsigned OpNo,214SmallVectorImpl<MCFixup> &Fixups,215const MCSubtargetInfo &STI,216MCFixupKind Fixup) const {217const MCOperand &MO = MI.getOperand(OpNo);218assert(!MO.isReg() && "Not expecting a register for this operand.");219if (MO.isImm())220return getMachineOpValue(MI, MO, Fixups, STI);221222// Add a fixup for the immediate field.223Fixups.push_back(MCFixup::create(0, MO.getExpr(), Fixup));224return 0;225}226227uint64_t228PPCMCCodeEmitter::getImm34EncodingNoPCRel(const MCInst &MI, unsigned OpNo,229SmallVectorImpl<MCFixup> &Fixups,230const MCSubtargetInfo &STI) const {231return getImm34Encoding(MI, OpNo, Fixups, STI,232(MCFixupKind)PPC::fixup_ppc_imm34);233}234235uint64_t236PPCMCCodeEmitter::getImm34EncodingPCRel(const MCInst &MI, unsigned OpNo,237SmallVectorImpl<MCFixup> &Fixups,238const MCSubtargetInfo &STI) const {239return getImm34Encoding(MI, OpNo, Fixups, STI,240(MCFixupKind)PPC::fixup_ppc_pcrel34);241}242243unsigned PPCMCCodeEmitter::getDispRIEncoding(const MCInst &MI, unsigned OpNo,244SmallVectorImpl<MCFixup> &Fixups,245const MCSubtargetInfo &STI) const {246const MCOperand &MO = MI.getOperand(OpNo);247if (MO.isImm())248return getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF;249250// Add a fixup for the displacement field.251Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),252(MCFixupKind)PPC::fixup_ppc_half16));253return 0;254}255256unsigned257PPCMCCodeEmitter::getDispRIXEncoding(const MCInst &MI, unsigned OpNo,258SmallVectorImpl<MCFixup> &Fixups,259const MCSubtargetInfo &STI) const {260const MCOperand &MO = MI.getOperand(OpNo);261if (MO.isImm())262return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF);263264// Add a fixup for the displacement field.265Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),266(MCFixupKind)PPC::fixup_ppc_half16ds));267return 0;268}269270unsigned271PPCMCCodeEmitter::getDispRIX16Encoding(const MCInst &MI, unsigned OpNo,272SmallVectorImpl<MCFixup> &Fixups,273const MCSubtargetInfo &STI) const {274const MCOperand &MO = MI.getOperand(OpNo);275if (MO.isImm()) {276assert(!(MO.getImm() % 16) &&277"Expecting an immediate that is a multiple of 16");278return ((getMachineOpValue(MI, MO, Fixups, STI) >> 4) & 0xFFF);279}280281// Otherwise add a fixup for the displacement field.282Fixups.push_back(MCFixup::create(IsLittleEndian ? 0 : 2, MO.getExpr(),283(MCFixupKind)PPC::fixup_ppc_half16dq));284return 0;285}286287unsigned288PPCMCCodeEmitter::getDispRIHashEncoding(const MCInst &MI, unsigned OpNo,289SmallVectorImpl<MCFixup> &Fixups,290const MCSubtargetInfo &STI) const {291// Encode imm for the hash load/store to stack for the ROP Protection292// instructions.293const MCOperand &MO = MI.getOperand(OpNo);294295assert(MO.isImm() && "Expecting an immediate operand.");296assert(!(MO.getImm() % 8) && "Expecting offset to be 8 byte aligned.");297298unsigned DX = (MO.getImm() >> 3) & 0x3F;299return DX;300}301302uint64_t303PPCMCCodeEmitter::getDispRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,304SmallVectorImpl<MCFixup> &Fixups,305const MCSubtargetInfo &STI) const {306// Encode the displacement part of pc-relative memri34, which is an imm34.307// The 34 bit immediate can fall into one of three cases:308// 1) It is a relocation to be filled in by the linker represented as:309// (MCExpr::SymbolRef)310// 2) It is a relocation + SignedOffset represented as:311// (MCExpr::Binary(MCExpr::SymbolRef + MCExpr::Constant))312// 3) It is a known value at compile time.313314// If this is not a MCExpr then we are in case 3) and we are dealing with315// a value known at compile time, not a relocation.316const MCOperand &MO = MI.getOperand(OpNo);317if (!MO.isExpr())318return (getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL;319320// At this point in the function it is known that MO is of type MCExpr.321// Therefore we are dealing with either case 1) a symbol ref or322// case 2) a symbol ref plus a constant.323const MCExpr *Expr = MO.getExpr();324switch (Expr->getKind()) {325default:326llvm_unreachable("Unsupported MCExpr for getMemRI34PCRelEncoding.");327case MCExpr::SymbolRef: {328// Relocation alone.329const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr);330(void)SRE;331// Currently these are the only valid PCRelative Relocations.332assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL ||333SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL ||334SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL ||335SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL ||336SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL) &&337"VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL or "338"VK_PPC_GOT_TLSGD_PCREL or VK_PPC_GOT_TLSLD_PCREL or "339"VK_PPC_GOT_TPREL_PCREL.");340// Generate the fixup for the relocation.341Fixups.push_back(342MCFixup::create(0, Expr,343static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34)));344// Put zero in the location of the immediate. The linker will fill in the345// correct value based on the relocation.346return 0;347}348case MCExpr::Binary: {349// Relocation plus some offset.350const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);351assert(BE->getOpcode() == MCBinaryExpr::Add &&352"Binary expression opcode must be an add.");353354const MCExpr *LHS = BE->getLHS();355const MCExpr *RHS = BE->getRHS();356357// Need to check in both directions. Reloc+Offset and Offset+Reloc.358if (LHS->getKind() != MCExpr::SymbolRef)359std::swap(LHS, RHS);360361if (LHS->getKind() != MCExpr::SymbolRef ||362RHS->getKind() != MCExpr::Constant)363llvm_unreachable("Expecting to have one constant and one relocation.");364365const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(LHS);366(void)SRE;367assert(isInt<34>(cast<MCConstantExpr>(RHS)->getValue()) &&368"Value must fit in 34 bits.");369370// Currently these are the only valid PCRelative Relocations.371assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL ||372SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL) &&373"VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL");374// Generate the fixup for the relocation.375Fixups.push_back(376MCFixup::create(0, Expr,377static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34)));378// Put zero in the location of the immediate. The linker will fill in the379// correct value based on the relocation.380return 0;381}382}383}384385uint64_t386PPCMCCodeEmitter::getDispRI34Encoding(const MCInst &MI, unsigned OpNo,387SmallVectorImpl<MCFixup> &Fixups,388const MCSubtargetInfo &STI) const {389// Encode the displacement part of a memri34.390const MCOperand &MO = MI.getOperand(OpNo);391return (getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL;392}393394unsigned395PPCMCCodeEmitter::getDispSPE8Encoding(const MCInst &MI, unsigned OpNo,396SmallVectorImpl<MCFixup> &Fixups,397const MCSubtargetInfo &STI) const {398// Encode imm as a dispSPE8, which has the low 5-bits of (imm / 8).399const MCOperand &MO = MI.getOperand(OpNo);400assert(MO.isImm());401return getMachineOpValue(MI, MO, Fixups, STI) >> 3;402}403404unsigned405PPCMCCodeEmitter::getDispSPE4Encoding(const MCInst &MI, unsigned OpNo,406SmallVectorImpl<MCFixup> &Fixups,407const MCSubtargetInfo &STI) const {408// Encode imm as a dispSPE8, which has the low 5-bits of (imm / 4).409const MCOperand &MO = MI.getOperand(OpNo);410assert(MO.isImm());411return getMachineOpValue(MI, MO, Fixups, STI) >> 2;412}413414unsigned415PPCMCCodeEmitter::getDispSPE2Encoding(const MCInst &MI, unsigned OpNo,416SmallVectorImpl<MCFixup> &Fixups,417const MCSubtargetInfo &STI) const {418// Encode imm as a dispSPE8, which has the low 5-bits of (imm / 2).419const MCOperand &MO = MI.getOperand(OpNo);420assert(MO.isImm());421return getMachineOpValue(MI, MO, Fixups, STI) >> 1;422}423424unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,425SmallVectorImpl<MCFixup> &Fixups,426const MCSubtargetInfo &STI) const {427const MCOperand &MO = MI.getOperand(OpNo);428if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI);429430// Add a fixup for the TLS register, which simply provides a relocation431// hint to the linker that this statement is part of a relocation sequence.432// Return the thread-pointer register's encoding. Add a one byte displacement433// if using PC relative memops.434const MCExpr *Expr = MO.getExpr();435const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr);436bool IsPCRel = SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS_PCREL;437Fixups.push_back(MCFixup::create(IsPCRel ? 1 : 0, Expr,438(MCFixupKind)PPC::fixup_ppc_nofixup));439const Triple &TT = STI.getTargetTriple();440bool isPPC64 = TT.isPPC64();441return CTX.getRegisterInfo()->getEncodingValue(isPPC64 ? PPC::X13 : PPC::R2);442}443444unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo,445SmallVectorImpl<MCFixup> &Fixups,446const MCSubtargetInfo &STI) const {447// For special TLS calls, we need two fixups; one for the branch target448// (__tls_get_addr), which we create via getDirectBrEncoding as usual,449// and one for the TLSGD or TLSLD symbol, which is emitted here.450const MCOperand &MO = MI.getOperand(OpNo+1);451Fixups.push_back(MCFixup::create(0, MO.getExpr(),452(MCFixupKind)PPC::fixup_ppc_nofixup));453return getDirectBrEncoding(MI, OpNo, Fixups, STI);454}455456unsigned PPCMCCodeEmitter::457get_crbitm_encoding(const MCInst &MI, unsigned OpNo,458SmallVectorImpl<MCFixup> &Fixups,459const MCSubtargetInfo &STI) const {460const MCOperand &MO = MI.getOperand(OpNo);461assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||462MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&463(MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));464return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());465}466467// Get the index for this operand in this instruction. This is needed for468// computing the register number in PPC::getRegNumForOperand() for469// any instructions that use a different numbering scheme for registers in470// different operands.471static unsigned getOpIdxForMO(const MCInst &MI, const MCOperand &MO) {472for (unsigned i = 0; i < MI.getNumOperands(); i++) {473const MCOperand &Op = MI.getOperand(i);474if (&Op == &MO)475return i;476}477llvm_unreachable("This operand is not part of this instruction");478return ~0U; // Silence any warnings about no return.479}480481uint64_t PPCMCCodeEmitter::482getMachineOpValue(const MCInst &MI, const MCOperand &MO,483SmallVectorImpl<MCFixup> &Fixups,484const MCSubtargetInfo &STI) const {485if (MO.isReg()) {486// MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.487// The GPR operand should come through here though.488assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&489MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||490MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);491unsigned OpNo = getOpIdxForMO(MI, MO);492unsigned Reg =493PPC::getRegNumForOperand(MCII.get(MI.getOpcode()), MO.getReg(), OpNo);494return CTX.getRegisterInfo()->getEncodingValue(Reg);495}496497assert(MO.isImm() &&498"Relocation required in an instruction that we cannot encode!");499return MO.getImm();500}501502void PPCMCCodeEmitter::encodeInstruction(const MCInst &MI,503SmallVectorImpl<char> &CB,504SmallVectorImpl<MCFixup> &Fixups,505const MCSubtargetInfo &STI) const {506uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);507508// Output the constant in big/little endian byte order.509unsigned Size = getInstSizeInBytes(MI);510llvm::endianness E =511IsLittleEndian ? llvm::endianness::little : llvm::endianness::big;512switch (Size) {513case 0:514break;515case 4:516support::endian::write<uint32_t>(CB, Bits, E);517break;518case 8:519// If we emit a pair of instructions, the first one is520// always in the top 32 bits, even on little-endian.521support::endian::write<uint32_t>(CB, Bits >> 32, E);522support::endian::write<uint32_t>(CB, Bits, E);523break;524default:525llvm_unreachable("Invalid instruction size");526}527528++MCNumEmitted; // Keep track of the # of mi's emitted.529}530531// Get the number of bytes used to encode the given MCInst.532unsigned PPCMCCodeEmitter::getInstSizeInBytes(const MCInst &MI) const {533unsigned Opcode = MI.getOpcode();534const MCInstrDesc &Desc = MCII.get(Opcode);535return Desc.getSize();536}537538bool PPCMCCodeEmitter::isPrefixedInstruction(const MCInst &MI) const {539return MCII.get(MI.getOpcode()).TSFlags & PPCII::Prefixed;540}541542#include "PPCGenMCCodeEmitter.inc"543544545