10b57cec5SDimitry Andric //===-- PPCMCCodeEmitter.cpp - Convert PPC code to machine code -----------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the PPCMCCodeEmitter class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 1306c3fb27SDimitry Andric #include "PPCMCCodeEmitter.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/PPCFixupKinds.h" 15*5f757f3fSDimitry Andric #include "PPCMCTargetDesc.h" 160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 170b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 18*5f757f3fSDimitry Andric #include "llvm/MC/MCExpr.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h" 200b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 22*5f757f3fSDimitry Andric #include "llvm/Support/Casting.h" 230b57cec5SDimitry Andric #include "llvm/Support/Endian.h" 240b57cec5SDimitry Andric #include "llvm/Support/EndianStream.h" 250b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 260b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 270b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 2806c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 290b57cec5SDimitry Andric #include <cassert> 300b57cec5SDimitry Andric #include <cstdint> 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric using namespace llvm; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric #define DEBUG_TYPE "mccodeemitter" 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII, 390b57cec5SDimitry Andric MCContext &Ctx) { 400b57cec5SDimitry Andric return new PPCMCCodeEmitter(MCII, Ctx); 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric unsigned PPCMCCodeEmitter:: 440b57cec5SDimitry Andric getDirectBrEncoding(const MCInst &MI, unsigned OpNo, 450b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 460b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 470b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 480b57cec5SDimitry Andric 49e8d8bef9SDimitry Andric if (MO.isReg() || MO.isImm()) 50e8d8bef9SDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI); 5181ad6265SDimitry Andric 520b57cec5SDimitry Andric // Add a fixup for the branch target. 530b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(), 54*5f757f3fSDimitry Andric (isNoTOCCallInstr(MI) 555ffd83dbSDimitry Andric ? (MCFixupKind)PPC::fixup_ppc_br24_notoc 565ffd83dbSDimitry Andric : (MCFixupKind)PPC::fixup_ppc_br24))); 570b57cec5SDimitry Andric return 0; 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 60*5f757f3fSDimitry Andric /// Check if Opcode corresponds to a call instruction that should be marked 61*5f757f3fSDimitry Andric /// with the NOTOC relocation. 62*5f757f3fSDimitry Andric bool PPCMCCodeEmitter::isNoTOCCallInstr(const MCInst &MI) const { 63*5f757f3fSDimitry Andric unsigned Opcode = MI.getOpcode(); 64*5f757f3fSDimitry Andric if (!MCII.get(Opcode).isCall()) 65*5f757f3fSDimitry Andric return false; 66*5f757f3fSDimitry Andric 67*5f757f3fSDimitry Andric switch (Opcode) { 68*5f757f3fSDimitry Andric default: 69*5f757f3fSDimitry Andric #ifndef NDEBUG 70*5f757f3fSDimitry Andric llvm_unreachable("Unknown call opcode"); 71*5f757f3fSDimitry Andric #endif 72*5f757f3fSDimitry Andric return false; 73*5f757f3fSDimitry Andric case PPC::BL8_NOTOC: 74*5f757f3fSDimitry Andric case PPC::BL8_NOTOC_TLS: 75*5f757f3fSDimitry Andric case PPC::BL8_NOTOC_RM: 76*5f757f3fSDimitry Andric return true; 77*5f757f3fSDimitry Andric #ifndef NDEBUG 78*5f757f3fSDimitry Andric case PPC::BL8: 79*5f757f3fSDimitry Andric case PPC::BL: 80*5f757f3fSDimitry Andric case PPC::BL8_TLS: 81*5f757f3fSDimitry Andric case PPC::BL_TLS: 82*5f757f3fSDimitry Andric case PPC::BLA8: 83*5f757f3fSDimitry Andric case PPC::BLA: 84*5f757f3fSDimitry Andric case PPC::BCCL: 85*5f757f3fSDimitry Andric case PPC::BCCLA: 86*5f757f3fSDimitry Andric case PPC::BCL: 87*5f757f3fSDimitry Andric case PPC::BCLn: 88*5f757f3fSDimitry Andric case PPC::BL8_NOP: 89*5f757f3fSDimitry Andric case PPC::BL_NOP: 90*5f757f3fSDimitry Andric case PPC::BL8_NOP_TLS: 91*5f757f3fSDimitry Andric case PPC::BLA8_NOP: 92*5f757f3fSDimitry Andric case PPC::BCTRL8: 93*5f757f3fSDimitry Andric case PPC::BCTRL: 94*5f757f3fSDimitry Andric case PPC::BCCCTRL8: 95*5f757f3fSDimitry Andric case PPC::BCCCTRL: 96*5f757f3fSDimitry Andric case PPC::BCCTRL8: 97*5f757f3fSDimitry Andric case PPC::BCCTRL: 98*5f757f3fSDimitry Andric case PPC::BCCTRL8n: 99*5f757f3fSDimitry Andric case PPC::BCCTRLn: 100*5f757f3fSDimitry Andric case PPC::BL8_RM: 101*5f757f3fSDimitry Andric case PPC::BLA8_RM: 102*5f757f3fSDimitry Andric case PPC::BL8_NOP_RM: 103*5f757f3fSDimitry Andric case PPC::BLA8_NOP_RM: 104*5f757f3fSDimitry Andric case PPC::BCTRL8_RM: 105*5f757f3fSDimitry Andric case PPC::BCTRL8_LDinto_toc: 106*5f757f3fSDimitry Andric case PPC::BCTRL8_LDinto_toc_RM: 107*5f757f3fSDimitry Andric case PPC::BL8_TLS_: 108*5f757f3fSDimitry Andric case PPC::TCRETURNdi8: 109*5f757f3fSDimitry Andric case PPC::TCRETURNai8: 110*5f757f3fSDimitry Andric case PPC::TCRETURNri8: 111*5f757f3fSDimitry Andric case PPC::TAILBCTR8: 112*5f757f3fSDimitry Andric case PPC::TAILB8: 113*5f757f3fSDimitry Andric case PPC::TAILBA8: 114*5f757f3fSDimitry Andric case PPC::BCLalways: 115*5f757f3fSDimitry Andric case PPC::BLRL: 116*5f757f3fSDimitry Andric case PPC::BCCLRL: 117*5f757f3fSDimitry Andric case PPC::BCLRL: 118*5f757f3fSDimitry Andric case PPC::BCLRLn: 119*5f757f3fSDimitry Andric case PPC::BDZL: 120*5f757f3fSDimitry Andric case PPC::BDNZL: 121*5f757f3fSDimitry Andric case PPC::BDZLA: 122*5f757f3fSDimitry Andric case PPC::BDNZLA: 123*5f757f3fSDimitry Andric case PPC::BDZLp: 124*5f757f3fSDimitry Andric case PPC::BDNZLp: 125*5f757f3fSDimitry Andric case PPC::BDZLAp: 126*5f757f3fSDimitry Andric case PPC::BDNZLAp: 127*5f757f3fSDimitry Andric case PPC::BDZLm: 128*5f757f3fSDimitry Andric case PPC::BDNZLm: 129*5f757f3fSDimitry Andric case PPC::BDZLAm: 130*5f757f3fSDimitry Andric case PPC::BDNZLAm: 131*5f757f3fSDimitry Andric case PPC::BDZLRL: 132*5f757f3fSDimitry Andric case PPC::BDNZLRL: 133*5f757f3fSDimitry Andric case PPC::BDZLRLp: 134*5f757f3fSDimitry Andric case PPC::BDNZLRLp: 135*5f757f3fSDimitry Andric case PPC::BDZLRLm: 136*5f757f3fSDimitry Andric case PPC::BDNZLRLm: 137*5f757f3fSDimitry Andric case PPC::BL_RM: 138*5f757f3fSDimitry Andric case PPC::BLA_RM: 139*5f757f3fSDimitry Andric case PPC::BL_NOP_RM: 140*5f757f3fSDimitry Andric case PPC::BCTRL_RM: 141*5f757f3fSDimitry Andric case PPC::TCRETURNdi: 142*5f757f3fSDimitry Andric case PPC::TCRETURNai: 143*5f757f3fSDimitry Andric case PPC::TCRETURNri: 144*5f757f3fSDimitry Andric case PPC::BCTRL_LWZinto_toc: 145*5f757f3fSDimitry Andric case PPC::BCTRL_LWZinto_toc_RM: 146*5f757f3fSDimitry Andric case PPC::TAILBCTR: 147*5f757f3fSDimitry Andric case PPC::TAILB: 148*5f757f3fSDimitry Andric case PPC::TAILBA: 149*5f757f3fSDimitry Andric return false; 150*5f757f3fSDimitry Andric #endif 151*5f757f3fSDimitry Andric } 152*5f757f3fSDimitry Andric } 153*5f757f3fSDimitry Andric 1540b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo, 1550b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1560b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1570b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 1580b57cec5SDimitry Andric if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric // Add a fixup for the branch target. 1610b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(), 1620b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_brcond14)); 1630b57cec5SDimitry Andric return 0; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric unsigned PPCMCCodeEmitter:: 1670b57cec5SDimitry Andric getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo, 1680b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1690b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1700b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 1710b57cec5SDimitry Andric if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric // Add a fixup for the branch target. 1740b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(), 1750b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_br24abs)); 1760b57cec5SDimitry Andric return 0; 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric unsigned PPCMCCodeEmitter:: 1800b57cec5SDimitry Andric getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo, 1810b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1820b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1830b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 1840b57cec5SDimitry Andric if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric // Add a fixup for the branch target. 1870b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(), 1880b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_brcond14abs)); 1890b57cec5SDimitry Andric return 0; 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric 192e8d8bef9SDimitry Andric unsigned 193e8d8bef9SDimitry Andric PPCMCCodeEmitter::getVSRpEvenEncoding(const MCInst &MI, unsigned OpNo, 194e8d8bef9SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 195e8d8bef9SDimitry Andric const MCSubtargetInfo &STI) const { 196e8d8bef9SDimitry Andric assert(MI.getOperand(OpNo).isReg() && "Operand should be a register"); 197e8d8bef9SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) 198e8d8bef9SDimitry Andric << 1; 199e8d8bef9SDimitry Andric return RegBits; 200e8d8bef9SDimitry Andric } 201e8d8bef9SDimitry Andric 2020b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo, 2030b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2040b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 2050b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 2060b57cec5SDimitry Andric if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric // Add a fixup for the immediate field. 2090b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(), 2100b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_half16)); 2110b57cec5SDimitry Andric return 0; 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 214e8d8bef9SDimitry Andric uint64_t PPCMCCodeEmitter::getImm34Encoding(const MCInst &MI, unsigned OpNo, 2155ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 216e8d8bef9SDimitry Andric const MCSubtargetInfo &STI, 217e8d8bef9SDimitry Andric MCFixupKind Fixup) const { 2185ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 219e8d8bef9SDimitry Andric assert(!MO.isReg() && "Not expecting a register for this operand."); 220e8d8bef9SDimitry Andric if (MO.isImm()) 2215ffd83dbSDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI); 2225ffd83dbSDimitry Andric 2235ffd83dbSDimitry Andric // Add a fixup for the immediate field. 224e8d8bef9SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(), Fixup)); 2255ffd83dbSDimitry Andric return 0; 2265ffd83dbSDimitry Andric } 2275ffd83dbSDimitry Andric 228e8d8bef9SDimitry Andric uint64_t 229e8d8bef9SDimitry Andric PPCMCCodeEmitter::getImm34EncodingNoPCRel(const MCInst &MI, unsigned OpNo, 230e8d8bef9SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 231e8d8bef9SDimitry Andric const MCSubtargetInfo &STI) const { 232e8d8bef9SDimitry Andric return getImm34Encoding(MI, OpNo, Fixups, STI, 233e8d8bef9SDimitry Andric (MCFixupKind)PPC::fixup_ppc_imm34); 234e8d8bef9SDimitry Andric } 235e8d8bef9SDimitry Andric 236e8d8bef9SDimitry Andric uint64_t 237e8d8bef9SDimitry Andric PPCMCCodeEmitter::getImm34EncodingPCRel(const MCInst &MI, unsigned OpNo, 238e8d8bef9SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 239e8d8bef9SDimitry Andric const MCSubtargetInfo &STI) const { 240e8d8bef9SDimitry Andric return getImm34Encoding(MI, OpNo, Fixups, STI, 241e8d8bef9SDimitry Andric (MCFixupKind)PPC::fixup_ppc_pcrel34); 242e8d8bef9SDimitry Andric } 243e8d8bef9SDimitry Andric 24406c3fb27SDimitry Andric unsigned PPCMCCodeEmitter::getDispRIEncoding(const MCInst &MI, unsigned OpNo, 2450b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2460b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 2470b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 2480b57cec5SDimitry Andric if (MO.isImm()) 24906c3fb27SDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF; 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric // Add a fixup for the displacement field. 2520b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(), 2530b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_half16)); 25406c3fb27SDimitry Andric return 0; 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric 25706c3fb27SDimitry Andric unsigned 25806c3fb27SDimitry Andric PPCMCCodeEmitter::getDispRIXEncoding(const MCInst &MI, unsigned OpNo, 2590b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2600b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 2610b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 2620b57cec5SDimitry Andric if (MO.isImm()) 26306c3fb27SDimitry Andric return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF); 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric // Add a fixup for the displacement field. 2660b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(), 2670b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_half16ds)); 26806c3fb27SDimitry Andric return 0; 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric 27106c3fb27SDimitry Andric unsigned 27206c3fb27SDimitry Andric PPCMCCodeEmitter::getDispRIX16Encoding(const MCInst &MI, unsigned OpNo, 2730b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2740b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 2750b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 2760b57cec5SDimitry Andric if (MO.isImm()) { 2770b57cec5SDimitry Andric assert(!(MO.getImm() % 16) && 2780b57cec5SDimitry Andric "Expecting an immediate that is a multiple of 16"); 27906c3fb27SDimitry Andric return ((getMachineOpValue(MI, MO, Fixups, STI) >> 4) & 0xFFF); 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric // Otherwise add a fixup for the displacement field. 2830b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(IsLittleEndian ? 0 : 2, MO.getExpr(), 2843a9a9c0cSDimitry Andric (MCFixupKind)PPC::fixup_ppc_half16dq)); 28506c3fb27SDimitry Andric return 0; 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 288fe6060f1SDimitry Andric unsigned 28906c3fb27SDimitry Andric PPCMCCodeEmitter::getDispRIHashEncoding(const MCInst &MI, unsigned OpNo, 290fe6060f1SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 291fe6060f1SDimitry Andric const MCSubtargetInfo &STI) const { 29206c3fb27SDimitry Andric // Encode imm for the hash load/store to stack for the ROP Protection 293fe6060f1SDimitry Andric // instructions. 294fe6060f1SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 295fe6060f1SDimitry Andric 296fe6060f1SDimitry Andric assert(MO.isImm() && "Expecting an immediate operand."); 297fe6060f1SDimitry Andric assert(!(MO.getImm() % 8) && "Expecting offset to be 8 byte aligned."); 298fe6060f1SDimitry Andric 299fe6060f1SDimitry Andric unsigned DX = (MO.getImm() >> 3) & 0x3F; 30006c3fb27SDimitry Andric return DX; 301fe6060f1SDimitry Andric } 302fe6060f1SDimitry Andric 3035ffd83dbSDimitry Andric uint64_t 30406c3fb27SDimitry Andric PPCMCCodeEmitter::getDispRI34PCRelEncoding(const MCInst &MI, unsigned OpNo, 3055ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3065ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 30706c3fb27SDimitry Andric // Encode the displacement part of pc-relative memri34, which is an imm34. 3085ffd83dbSDimitry Andric // The 34 bit immediate can fall into one of three cases: 3095ffd83dbSDimitry Andric // 1) It is a relocation to be filled in by the linker represented as: 3105ffd83dbSDimitry Andric // (MCExpr::SymbolRef) 3115ffd83dbSDimitry Andric // 2) It is a relocation + SignedOffset represented as: 3125ffd83dbSDimitry Andric // (MCExpr::Binary(MCExpr::SymbolRef + MCExpr::Constant)) 3135ffd83dbSDimitry Andric // 3) It is a known value at compile time. 3145ffd83dbSDimitry Andric 3155ffd83dbSDimitry Andric // If this is not a MCExpr then we are in case 3) and we are dealing with 3165ffd83dbSDimitry Andric // a value known at compile time, not a relocation. 3175ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 3185ffd83dbSDimitry Andric if (!MO.isExpr()) 31906c3fb27SDimitry Andric return (getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL; 3205ffd83dbSDimitry Andric 3215ffd83dbSDimitry Andric // At this point in the function it is known that MO is of type MCExpr. 3225ffd83dbSDimitry Andric // Therefore we are dealing with either case 1) a symbol ref or 3235ffd83dbSDimitry Andric // case 2) a symbol ref plus a constant. 3245ffd83dbSDimitry Andric const MCExpr *Expr = MO.getExpr(); 3255ffd83dbSDimitry Andric switch (Expr->getKind()) { 3265ffd83dbSDimitry Andric default: 3275ffd83dbSDimitry Andric llvm_unreachable("Unsupported MCExpr for getMemRI34PCRelEncoding."); 3285ffd83dbSDimitry Andric case MCExpr::SymbolRef: { 3295ffd83dbSDimitry Andric // Relocation alone. 3305ffd83dbSDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr); 3315ffd83dbSDimitry Andric (void)SRE; 3325ffd83dbSDimitry Andric // Currently these are the only valid PCRelative Relocations. 3335ffd83dbSDimitry Andric assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL || 334e8d8bef9SDimitry Andric SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL || 335e8d8bef9SDimitry Andric SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL || 336e8d8bef9SDimitry Andric SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL || 337e8d8bef9SDimitry Andric SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL) && 338e8d8bef9SDimitry Andric "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL or " 339e8d8bef9SDimitry Andric "VK_PPC_GOT_TLSGD_PCREL or VK_PPC_GOT_TLSLD_PCREL or " 340e8d8bef9SDimitry Andric "VK_PPC_GOT_TPREL_PCREL."); 3415ffd83dbSDimitry Andric // Generate the fixup for the relocation. 3425ffd83dbSDimitry Andric Fixups.push_back( 3435ffd83dbSDimitry Andric MCFixup::create(0, Expr, 3445ffd83dbSDimitry Andric static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34))); 3455ffd83dbSDimitry Andric // Put zero in the location of the immediate. The linker will fill in the 3465ffd83dbSDimitry Andric // correct value based on the relocation. 3475ffd83dbSDimitry Andric return 0; 3485ffd83dbSDimitry Andric } 3495ffd83dbSDimitry Andric case MCExpr::Binary: { 3505ffd83dbSDimitry Andric // Relocation plus some offset. 3515ffd83dbSDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); 3525ffd83dbSDimitry Andric assert(BE->getOpcode() == MCBinaryExpr::Add && 3535ffd83dbSDimitry Andric "Binary expression opcode must be an add."); 3545ffd83dbSDimitry Andric 3555ffd83dbSDimitry Andric const MCExpr *LHS = BE->getLHS(); 3565ffd83dbSDimitry Andric const MCExpr *RHS = BE->getRHS(); 3575ffd83dbSDimitry Andric 3585ffd83dbSDimitry Andric // Need to check in both directions. Reloc+Offset and Offset+Reloc. 3595ffd83dbSDimitry Andric if (LHS->getKind() != MCExpr::SymbolRef) 3605ffd83dbSDimitry Andric std::swap(LHS, RHS); 3615ffd83dbSDimitry Andric 3625ffd83dbSDimitry Andric if (LHS->getKind() != MCExpr::SymbolRef || 3635ffd83dbSDimitry Andric RHS->getKind() != MCExpr::Constant) 3645ffd83dbSDimitry Andric llvm_unreachable("Expecting to have one constant and one relocation."); 3655ffd83dbSDimitry Andric 3665ffd83dbSDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(LHS); 3675ffd83dbSDimitry Andric (void)SRE; 3685ffd83dbSDimitry Andric assert(isInt<34>(cast<MCConstantExpr>(RHS)->getValue()) && 3695ffd83dbSDimitry Andric "Value must fit in 34 bits."); 3705ffd83dbSDimitry Andric 3715ffd83dbSDimitry Andric // Currently these are the only valid PCRelative Relocations. 3725ffd83dbSDimitry Andric assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL || 3735ffd83dbSDimitry Andric SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL) && 3745ffd83dbSDimitry Andric "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL"); 3755ffd83dbSDimitry Andric // Generate the fixup for the relocation. 3765ffd83dbSDimitry Andric Fixups.push_back( 3775ffd83dbSDimitry Andric MCFixup::create(0, Expr, 3785ffd83dbSDimitry Andric static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34))); 3795ffd83dbSDimitry Andric // Put zero in the location of the immediate. The linker will fill in the 3805ffd83dbSDimitry Andric // correct value based on the relocation. 3815ffd83dbSDimitry Andric return 0; 3825ffd83dbSDimitry Andric } 3835ffd83dbSDimitry Andric } 3845ffd83dbSDimitry Andric } 3855ffd83dbSDimitry Andric 3865ffd83dbSDimitry Andric uint64_t 38706c3fb27SDimitry Andric PPCMCCodeEmitter::getDispRI34Encoding(const MCInst &MI, unsigned OpNo, 3885ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3895ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 39006c3fb27SDimitry Andric // Encode the displacement part of a memri34. 3915ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 39206c3fb27SDimitry Andric return (getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL; 3935ffd83dbSDimitry Andric } 3945ffd83dbSDimitry Andric 39506c3fb27SDimitry Andric unsigned 39606c3fb27SDimitry Andric PPCMCCodeEmitter::getDispSPE8Encoding(const MCInst &MI, unsigned OpNo, 3970b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 39806c3fb27SDimitry Andric const MCSubtargetInfo &STI) const { 39906c3fb27SDimitry Andric // Encode imm as a dispSPE8, which has the low 5-bits of (imm / 8). 4000b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 4010b57cec5SDimitry Andric assert(MO.isImm()); 40206c3fb27SDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI) >> 3; 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 40506c3fb27SDimitry Andric unsigned 40606c3fb27SDimitry Andric PPCMCCodeEmitter::getDispSPE4Encoding(const MCInst &MI, unsigned OpNo, 4070b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 40806c3fb27SDimitry Andric const MCSubtargetInfo &STI) const { 40906c3fb27SDimitry Andric // Encode imm as a dispSPE8, which has the low 5-bits of (imm / 4). 4100b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 4110b57cec5SDimitry Andric assert(MO.isImm()); 41206c3fb27SDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI) >> 2; 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric 41506c3fb27SDimitry Andric unsigned 41606c3fb27SDimitry Andric PPCMCCodeEmitter::getDispSPE2Encoding(const MCInst &MI, unsigned OpNo, 4170b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 41806c3fb27SDimitry Andric const MCSubtargetInfo &STI) const { 41906c3fb27SDimitry Andric // Encode imm as a dispSPE8, which has the low 5-bits of (imm / 2). 4200b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 4210b57cec5SDimitry Andric assert(MO.isImm()); 42206c3fb27SDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI) >> 1; 4230b57cec5SDimitry Andric } 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo, 4260b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4270b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 4280b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 4290b57cec5SDimitry Andric if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI); 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric // Add a fixup for the TLS register, which simply provides a relocation 4320b57cec5SDimitry Andric // hint to the linker that this statement is part of a relocation sequence. 433e8d8bef9SDimitry Andric // Return the thread-pointer register's encoding. Add a one byte displacement 434e8d8bef9SDimitry Andric // if using PC relative memops. 435e8d8bef9SDimitry Andric const MCExpr *Expr = MO.getExpr(); 436e8d8bef9SDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr); 437e8d8bef9SDimitry Andric bool IsPCRel = SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS_PCREL; 438e8d8bef9SDimitry Andric Fixups.push_back(MCFixup::create(IsPCRel ? 1 : 0, Expr, 4390b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_nofixup)); 4400b57cec5SDimitry Andric const Triple &TT = STI.getTargetTriple(); 4410b57cec5SDimitry Andric bool isPPC64 = TT.isPPC64(); 4420b57cec5SDimitry Andric return CTX.getRegisterInfo()->getEncodingValue(isPPC64 ? PPC::X13 : PPC::R2); 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo, 4460b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4470b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 4480b57cec5SDimitry Andric // For special TLS calls, we need two fixups; one for the branch target 4490b57cec5SDimitry Andric // (__tls_get_addr), which we create via getDirectBrEncoding as usual, 4500b57cec5SDimitry Andric // and one for the TLSGD or TLSLD symbol, which is emitted here. 4510b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo+1); 4520b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(), 4530b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_nofixup)); 4540b57cec5SDimitry Andric return getDirectBrEncoding(MI, OpNo, Fixups, STI); 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric unsigned PPCMCCodeEmitter:: 4580b57cec5SDimitry Andric get_crbitm_encoding(const MCInst &MI, unsigned OpNo, 4590b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4600b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 4610b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 4620b57cec5SDimitry Andric assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 || 4630b57cec5SDimitry Andric MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) && 4640b57cec5SDimitry Andric (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)); 4650b57cec5SDimitry Andric return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric // Get the index for this operand in this instruction. This is needed for 469*5f757f3fSDimitry Andric // computing the register number in PPC::getRegNumForOperand() for 4700b57cec5SDimitry Andric // any instructions that use a different numbering scheme for registers in 4710b57cec5SDimitry Andric // different operands. 4720b57cec5SDimitry Andric static unsigned getOpIdxForMO(const MCInst &MI, const MCOperand &MO) { 4730b57cec5SDimitry Andric for (unsigned i = 0; i < MI.getNumOperands(); i++) { 4740b57cec5SDimitry Andric const MCOperand &Op = MI.getOperand(i); 4750b57cec5SDimitry Andric if (&Op == &MO) 4760b57cec5SDimitry Andric return i; 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric llvm_unreachable("This operand is not part of this instruction"); 4790b57cec5SDimitry Andric return ~0U; // Silence any warnings about no return. 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric 4825ffd83dbSDimitry Andric uint64_t PPCMCCodeEmitter:: 4830b57cec5SDimitry Andric getMachineOpValue(const MCInst &MI, const MCOperand &MO, 4840b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4850b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 4860b57cec5SDimitry Andric if (MO.isReg()) { 4870b57cec5SDimitry Andric // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand. 4880b57cec5SDimitry Andric // The GPR operand should come through here though. 4890b57cec5SDimitry Andric assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 && 4900b57cec5SDimitry Andric MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) || 4910b57cec5SDimitry Andric MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7); 4920b57cec5SDimitry Andric unsigned OpNo = getOpIdxForMO(MI, MO); 4930b57cec5SDimitry Andric unsigned Reg = 494*5f757f3fSDimitry Andric PPC::getRegNumForOperand(MCII.get(MI.getOpcode()), MO.getReg(), OpNo); 4950b57cec5SDimitry Andric return CTX.getRegisterInfo()->getEncodingValue(Reg); 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric assert(MO.isImm() && 4990b57cec5SDimitry Andric "Relocation required in an instruction that we cannot encode!"); 5000b57cec5SDimitry Andric return MO.getImm(); 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 50306c3fb27SDimitry Andric void PPCMCCodeEmitter::encodeInstruction(const MCInst &MI, 50406c3fb27SDimitry Andric SmallVectorImpl<char> &CB, 505753f127fSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 5060b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 5070b57cec5SDimitry Andric uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric // Output the constant in big/little endian byte order. 5100b57cec5SDimitry Andric unsigned Size = getInstSizeInBytes(MI); 511*5f757f3fSDimitry Andric llvm::endianness E = 512*5f757f3fSDimitry Andric IsLittleEndian ? llvm::endianness::little : llvm::endianness::big; 5130b57cec5SDimitry Andric switch (Size) { 5140b57cec5SDimitry Andric case 0: 5150b57cec5SDimitry Andric break; 5160b57cec5SDimitry Andric case 4: 51706c3fb27SDimitry Andric support::endian::write<uint32_t>(CB, Bits, E); 5180b57cec5SDimitry Andric break; 5190b57cec5SDimitry Andric case 8: 5200b57cec5SDimitry Andric // If we emit a pair of instructions, the first one is 5210b57cec5SDimitry Andric // always in the top 32 bits, even on little-endian. 52206c3fb27SDimitry Andric support::endian::write<uint32_t>(CB, Bits >> 32, E); 52306c3fb27SDimitry Andric support::endian::write<uint32_t>(CB, Bits, E); 5240b57cec5SDimitry Andric break; 5250b57cec5SDimitry Andric default: 5260b57cec5SDimitry Andric llvm_unreachable("Invalid instruction size"); 5270b57cec5SDimitry Andric } 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric ++MCNumEmitted; // Keep track of the # of mi's emitted. 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric // Get the number of bytes used to encode the given MCInst. 5330b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getInstSizeInBytes(const MCInst &MI) const { 5340b57cec5SDimitry Andric unsigned Opcode = MI.getOpcode(); 5350b57cec5SDimitry Andric const MCInstrDesc &Desc = MCII.get(Opcode); 5360b57cec5SDimitry Andric return Desc.getSize(); 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric 5395ffd83dbSDimitry Andric bool PPCMCCodeEmitter::isPrefixedInstruction(const MCInst &MI) const { 540*5f757f3fSDimitry Andric return MCII.get(MI.getOpcode()).TSFlags & PPCII::Prefixed; 5415ffd83dbSDimitry Andric } 5425ffd83dbSDimitry Andric 5430b57cec5SDimitry Andric #include "PPCGenMCCodeEmitter.inc" 544