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
130b57cec5SDimitry Andric #include "MCTargetDesc/PPCFixupKinds.h"
140b57cec5SDimitry Andric #include "PPCInstrInfo.h"
150b57cec5SDimitry Andric #include "PPCMCCodeEmitter.h"
160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
170b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
180b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
220b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
230b57cec5SDimitry Andric #include "llvm/Support/EndianStream.h"
240b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
250b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
260b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
270b57cec5SDimitry Andric #include <cassert>
280b57cec5SDimitry Andric #include <cstdint>
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric using namespace llvm;
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric #define DEBUG_TYPE "mccodeemitter"
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
350b57cec5SDimitry Andric
createPPCMCCodeEmitter(const MCInstrInfo & MCII,const MCRegisterInfo & MRI,MCContext & Ctx)360b57cec5SDimitry Andric MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
370b57cec5SDimitry Andric const MCRegisterInfo &MRI,
380b57cec5SDimitry Andric MCContext &Ctx) {
390b57cec5SDimitry Andric return new PPCMCCodeEmitter(MCII, Ctx);
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::
getDirectBrEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const430b57cec5SDimitry Andric getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
440b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
450b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
460b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
470b57cec5SDimitry Andric
48af732203SDimitry Andric if (MO.isReg() || MO.isImm())
49af732203SDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI);
500b57cec5SDimitry Andric // Add a fixup for the branch target.
510b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(),
52af732203SDimitry Andric ((MI.getOpcode() == PPC::BL8_NOTOC ||
53af732203SDimitry Andric MI.getOpcode() == PPC::BL8_NOTOC_TLS)
545ffd83dbSDimitry Andric ? (MCFixupKind)PPC::fixup_ppc_br24_notoc
555ffd83dbSDimitry Andric : (MCFixupKind)PPC::fixup_ppc_br24)));
560b57cec5SDimitry Andric return 0;
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric
getCondBrEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const590b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
600b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
610b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
620b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
630b57cec5SDimitry Andric if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric // Add a fixup for the branch target.
660b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(),
670b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_brcond14));
680b57cec5SDimitry Andric return 0;
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::
getAbsDirectBrEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const720b57cec5SDimitry Andric getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
730b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
740b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
750b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
760b57cec5SDimitry Andric if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric // Add a fixup for the branch target.
790b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(),
800b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_br24abs));
810b57cec5SDimitry Andric return 0;
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::
getAbsCondBrEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const850b57cec5SDimitry Andric getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
860b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
870b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
880b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
890b57cec5SDimitry Andric if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric // Add a fixup for the branch target.
920b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(),
930b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_brcond14abs));
940b57cec5SDimitry Andric return 0;
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric
97af732203SDimitry Andric unsigned
getVSRpEvenEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const98af732203SDimitry Andric PPCMCCodeEmitter::getVSRpEvenEncoding(const MCInst &MI, unsigned OpNo,
99af732203SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
100af732203SDimitry Andric const MCSubtargetInfo &STI) const {
101af732203SDimitry Andric assert(MI.getOperand(OpNo).isReg() && "Operand should be a register");
102af732203SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI)
103af732203SDimitry Andric << 1;
104af732203SDimitry Andric return RegBits;
105af732203SDimitry Andric }
106af732203SDimitry Andric
getImm16Encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const1070b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo,
1080b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
1090b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
1100b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
1110b57cec5SDimitry Andric if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
1120b57cec5SDimitry Andric
1130b57cec5SDimitry Andric // Add a fixup for the immediate field.
1140b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
1150b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_half16));
1160b57cec5SDimitry Andric return 0;
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric
getImm34Encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI,MCFixupKind Fixup) const119af732203SDimitry Andric uint64_t PPCMCCodeEmitter::getImm34Encoding(const MCInst &MI, unsigned OpNo,
1205ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
121af732203SDimitry Andric const MCSubtargetInfo &STI,
122af732203SDimitry Andric MCFixupKind Fixup) const {
1235ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
124af732203SDimitry Andric assert(!MO.isReg() && "Not expecting a register for this operand.");
125af732203SDimitry Andric if (MO.isImm())
1265ffd83dbSDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI);
1275ffd83dbSDimitry Andric
1285ffd83dbSDimitry Andric // Add a fixup for the immediate field.
129af732203SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(), Fixup));
1305ffd83dbSDimitry Andric return 0;
1315ffd83dbSDimitry Andric }
1325ffd83dbSDimitry Andric
133af732203SDimitry Andric uint64_t
getImm34EncodingNoPCRel(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const134af732203SDimitry Andric PPCMCCodeEmitter::getImm34EncodingNoPCRel(const MCInst &MI, unsigned OpNo,
135af732203SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
136af732203SDimitry Andric const MCSubtargetInfo &STI) const {
137af732203SDimitry Andric return getImm34Encoding(MI, OpNo, Fixups, STI,
138af732203SDimitry Andric (MCFixupKind)PPC::fixup_ppc_imm34);
139af732203SDimitry Andric }
140af732203SDimitry Andric
141af732203SDimitry Andric uint64_t
getImm34EncodingPCRel(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const142af732203SDimitry Andric PPCMCCodeEmitter::getImm34EncodingPCRel(const MCInst &MI, unsigned OpNo,
143af732203SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
144af732203SDimitry Andric const MCSubtargetInfo &STI) const {
145af732203SDimitry Andric return getImm34Encoding(MI, OpNo, Fixups, STI,
146af732203SDimitry Andric (MCFixupKind)PPC::fixup_ppc_pcrel34);
147af732203SDimitry Andric }
148af732203SDimitry Andric
getMemRIEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const1490b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
1500b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
1510b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
1520b57cec5SDimitry Andric // Encode (imm, reg) as a memri, which has the low 16-bits as the
1530b57cec5SDimitry Andric // displacement and the next 5 bits as the register #.
1540b57cec5SDimitry Andric assert(MI.getOperand(OpNo+1).isReg());
1550b57cec5SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 16;
1560b57cec5SDimitry Andric
1570b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
1580b57cec5SDimitry Andric if (MO.isImm())
1590b57cec5SDimitry Andric return (getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF) | RegBits;
1600b57cec5SDimitry Andric
1610b57cec5SDimitry Andric // Add a fixup for the displacement field.
1620b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
1630b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_half16));
1640b57cec5SDimitry Andric return RegBits;
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric
getMemRIXEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const1670b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
1680b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
1690b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
1700b57cec5SDimitry Andric // Encode (imm, reg) as a memrix, which has the low 14-bits as the
1710b57cec5SDimitry Andric // displacement and the next 5 bits as the register #.
1720b57cec5SDimitry Andric assert(MI.getOperand(OpNo+1).isReg());
1730b57cec5SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 14;
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
1760b57cec5SDimitry Andric if (MO.isImm())
1770b57cec5SDimitry Andric return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF) | RegBits;
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric // Add a fixup for the displacement field.
1800b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
1810b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_half16ds));
1820b57cec5SDimitry Andric return RegBits;
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric
getMemRIX16Encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const1850b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
1860b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
1870b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
1880b57cec5SDimitry Andric // Encode (imm, reg) as a memrix16, which has the low 12-bits as the
1890b57cec5SDimitry Andric // displacement and the next 5 bits as the register #.
1900b57cec5SDimitry Andric assert(MI.getOperand(OpNo+1).isReg());
1910b57cec5SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 12;
1920b57cec5SDimitry Andric
1930b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
1940b57cec5SDimitry Andric if (MO.isImm()) {
1950b57cec5SDimitry Andric assert(!(MO.getImm() % 16) &&
1960b57cec5SDimitry Andric "Expecting an immediate that is a multiple of 16");
1970b57cec5SDimitry Andric return ((getMachineOpValue(MI, MO, Fixups, STI) >> 4) & 0xFFF) | RegBits;
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric
2000b57cec5SDimitry Andric // Otherwise add a fixup for the displacement field.
2010b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
2020b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_half16ds));
2030b57cec5SDimitry Andric return RegBits;
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric
206*5f7ddb14SDimitry Andric unsigned
getMemRIHashEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const207*5f7ddb14SDimitry Andric PPCMCCodeEmitter::getMemRIHashEncoding(const MCInst &MI, unsigned OpNo,
208*5f7ddb14SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
209*5f7ddb14SDimitry Andric const MCSubtargetInfo &STI) const {
210*5f7ddb14SDimitry Andric // Encode (imm, reg) for the hash load/store to stack for the ROP Protection
211*5f7ddb14SDimitry Andric // instructions.
212*5f7ddb14SDimitry Andric const MCOperand &RegMO = MI.getOperand(OpNo + 1);
213*5f7ddb14SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
214*5f7ddb14SDimitry Andric
215*5f7ddb14SDimitry Andric assert(RegMO.isReg() && "Base address must be a register.");
216*5f7ddb14SDimitry Andric assert(MO.isImm() && "Expecting an immediate operand.");
217*5f7ddb14SDimitry Andric assert(!(MO.getImm() % 8) && "Expecting offset to be 8 byte aligned.");
218*5f7ddb14SDimitry Andric
219*5f7ddb14SDimitry Andric unsigned RegBits = getMachineOpValue(MI, RegMO, Fixups, STI) << 6;
220*5f7ddb14SDimitry Andric unsigned DX = (MO.getImm() >> 3) & 0x3F;
221*5f7ddb14SDimitry Andric return RegBits | DX;
222*5f7ddb14SDimitry Andric }
223*5f7ddb14SDimitry Andric
2245ffd83dbSDimitry Andric uint64_t
getMemRI34PCRelEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const2255ffd83dbSDimitry Andric PPCMCCodeEmitter::getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
2265ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
2275ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const {
2285ffd83dbSDimitry Andric // Encode the PCRelative version of memri34: imm34(r0).
2295ffd83dbSDimitry Andric // In the PC relative version the register for the address must be zero.
2305ffd83dbSDimitry Andric // The 34 bit immediate can fall into one of three cases:
2315ffd83dbSDimitry Andric // 1) It is a relocation to be filled in by the linker represented as:
2325ffd83dbSDimitry Andric // (MCExpr::SymbolRef)
2335ffd83dbSDimitry Andric // 2) It is a relocation + SignedOffset represented as:
2345ffd83dbSDimitry Andric // (MCExpr::Binary(MCExpr::SymbolRef + MCExpr::Constant))
2355ffd83dbSDimitry Andric // 3) It is a known value at compile time.
2365ffd83dbSDimitry Andric
2375ffd83dbSDimitry Andric // Make sure that the register is a zero as expected.
2385ffd83dbSDimitry Andric assert(MI.getOperand(OpNo + 1).isImm() && "Expecting an immediate.");
2395ffd83dbSDimitry Andric uint64_t RegBits =
2405ffd83dbSDimitry Andric getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI) << 34;
2415ffd83dbSDimitry Andric assert(RegBits == 0 && "Operand must be 0.");
2425ffd83dbSDimitry Andric
2435ffd83dbSDimitry Andric // If this is not a MCExpr then we are in case 3) and we are dealing with
2445ffd83dbSDimitry Andric // a value known at compile time, not a relocation.
2455ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
2465ffd83dbSDimitry Andric if (!MO.isExpr())
2475ffd83dbSDimitry Andric return ((getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL) | RegBits;
2485ffd83dbSDimitry Andric
2495ffd83dbSDimitry Andric // At this point in the function it is known that MO is of type MCExpr.
2505ffd83dbSDimitry Andric // Therefore we are dealing with either case 1) a symbol ref or
2515ffd83dbSDimitry Andric // case 2) a symbol ref plus a constant.
2525ffd83dbSDimitry Andric const MCExpr *Expr = MO.getExpr();
2535ffd83dbSDimitry Andric switch (Expr->getKind()) {
2545ffd83dbSDimitry Andric default:
2555ffd83dbSDimitry Andric llvm_unreachable("Unsupported MCExpr for getMemRI34PCRelEncoding.");
2565ffd83dbSDimitry Andric case MCExpr::SymbolRef: {
2575ffd83dbSDimitry Andric // Relocation alone.
2585ffd83dbSDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr);
2595ffd83dbSDimitry Andric (void)SRE;
2605ffd83dbSDimitry Andric // Currently these are the only valid PCRelative Relocations.
2615ffd83dbSDimitry Andric assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL ||
262af732203SDimitry Andric SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL ||
263af732203SDimitry Andric SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL ||
264af732203SDimitry Andric SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL ||
265af732203SDimitry Andric SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL) &&
266af732203SDimitry Andric "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL or "
267af732203SDimitry Andric "VK_PPC_GOT_TLSGD_PCREL or VK_PPC_GOT_TLSLD_PCREL or "
268af732203SDimitry Andric "VK_PPC_GOT_TPREL_PCREL.");
2695ffd83dbSDimitry Andric // Generate the fixup for the relocation.
2705ffd83dbSDimitry Andric Fixups.push_back(
2715ffd83dbSDimitry Andric MCFixup::create(0, Expr,
2725ffd83dbSDimitry Andric static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34)));
2735ffd83dbSDimitry Andric // Put zero in the location of the immediate. The linker will fill in the
2745ffd83dbSDimitry Andric // correct value based on the relocation.
2755ffd83dbSDimitry Andric return 0;
2765ffd83dbSDimitry Andric }
2775ffd83dbSDimitry Andric case MCExpr::Binary: {
2785ffd83dbSDimitry Andric // Relocation plus some offset.
2795ffd83dbSDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
2805ffd83dbSDimitry Andric assert(BE->getOpcode() == MCBinaryExpr::Add &&
2815ffd83dbSDimitry Andric "Binary expression opcode must be an add.");
2825ffd83dbSDimitry Andric
2835ffd83dbSDimitry Andric const MCExpr *LHS = BE->getLHS();
2845ffd83dbSDimitry Andric const MCExpr *RHS = BE->getRHS();
2855ffd83dbSDimitry Andric
2865ffd83dbSDimitry Andric // Need to check in both directions. Reloc+Offset and Offset+Reloc.
2875ffd83dbSDimitry Andric if (LHS->getKind() != MCExpr::SymbolRef)
2885ffd83dbSDimitry Andric std::swap(LHS, RHS);
2895ffd83dbSDimitry Andric
2905ffd83dbSDimitry Andric if (LHS->getKind() != MCExpr::SymbolRef ||
2915ffd83dbSDimitry Andric RHS->getKind() != MCExpr::Constant)
2925ffd83dbSDimitry Andric llvm_unreachable("Expecting to have one constant and one relocation.");
2935ffd83dbSDimitry Andric
2945ffd83dbSDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(LHS);
2955ffd83dbSDimitry Andric (void)SRE;
2965ffd83dbSDimitry Andric assert(isInt<34>(cast<MCConstantExpr>(RHS)->getValue()) &&
2975ffd83dbSDimitry Andric "Value must fit in 34 bits.");
2985ffd83dbSDimitry Andric
2995ffd83dbSDimitry Andric // Currently these are the only valid PCRelative Relocations.
3005ffd83dbSDimitry Andric assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL ||
3015ffd83dbSDimitry Andric SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL) &&
3025ffd83dbSDimitry Andric "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL");
3035ffd83dbSDimitry Andric // Generate the fixup for the relocation.
3045ffd83dbSDimitry Andric Fixups.push_back(
3055ffd83dbSDimitry Andric MCFixup::create(0, Expr,
3065ffd83dbSDimitry Andric static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34)));
3075ffd83dbSDimitry Andric // Put zero in the location of the immediate. The linker will fill in the
3085ffd83dbSDimitry Andric // correct value based on the relocation.
3095ffd83dbSDimitry Andric return 0;
3105ffd83dbSDimitry Andric }
3115ffd83dbSDimitry Andric }
3125ffd83dbSDimitry Andric }
3135ffd83dbSDimitry Andric
3145ffd83dbSDimitry Andric uint64_t
getMemRI34Encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const3155ffd83dbSDimitry Andric PPCMCCodeEmitter::getMemRI34Encoding(const MCInst &MI, unsigned OpNo,
3165ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
3175ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const {
3185ffd83dbSDimitry Andric // Encode (imm, reg) as a memri34, which has the low 34-bits as the
3195ffd83dbSDimitry Andric // displacement and the next 5 bits as the register #.
3205ffd83dbSDimitry Andric assert(MI.getOperand(OpNo + 1).isReg() && "Expecting a register.");
3215ffd83dbSDimitry Andric uint64_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI)
3225ffd83dbSDimitry Andric << 34;
3235ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
3245ffd83dbSDimitry Andric return ((getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL) | RegBits;
3255ffd83dbSDimitry Andric }
3265ffd83dbSDimitry Andric
getSPE8DisEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const3270b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
3280b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
3290b57cec5SDimitry Andric const MCSubtargetInfo &STI)
3300b57cec5SDimitry Andric const {
3310b57cec5SDimitry Andric // Encode (imm, reg) as a spe8dis, which has the low 5-bits of (imm / 8)
3320b57cec5SDimitry Andric // as the displacement and the next 5 bits as the register #.
3330b57cec5SDimitry Andric assert(MI.getOperand(OpNo+1).isReg());
3340b57cec5SDimitry Andric uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
3350b57cec5SDimitry Andric
3360b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
3370b57cec5SDimitry Andric assert(MO.isImm());
3380b57cec5SDimitry Andric uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 3;
3390b57cec5SDimitry Andric return reverseBits(Imm | RegBits) >> 22;
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric
getSPE4DisEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const3420b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getSPE4DisEncoding(const MCInst &MI, unsigned OpNo,
3430b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
3440b57cec5SDimitry Andric const MCSubtargetInfo &STI)
3450b57cec5SDimitry Andric const {
3460b57cec5SDimitry Andric // Encode (imm, reg) as a spe4dis, which has the low 5-bits of (imm / 4)
3470b57cec5SDimitry Andric // as the displacement and the next 5 bits as the register #.
3480b57cec5SDimitry Andric assert(MI.getOperand(OpNo+1).isReg());
3490b57cec5SDimitry Andric uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
3500b57cec5SDimitry Andric
3510b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
3520b57cec5SDimitry Andric assert(MO.isImm());
3530b57cec5SDimitry Andric uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 2;
3540b57cec5SDimitry Andric return reverseBits(Imm | RegBits) >> 22;
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric
getSPE2DisEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const3570b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getSPE2DisEncoding(const MCInst &MI, unsigned OpNo,
3580b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
3590b57cec5SDimitry Andric const MCSubtargetInfo &STI)
3600b57cec5SDimitry Andric const {
3610b57cec5SDimitry Andric // Encode (imm, reg) as a spe2dis, which has the low 5-bits of (imm / 2)
3620b57cec5SDimitry Andric // as the displacement and the next 5 bits as the register #.
3630b57cec5SDimitry Andric assert(MI.getOperand(OpNo+1).isReg());
3640b57cec5SDimitry Andric uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
3670b57cec5SDimitry Andric assert(MO.isImm());
3680b57cec5SDimitry Andric uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 1;
3690b57cec5SDimitry Andric return reverseBits(Imm | RegBits) >> 22;
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric
getTLSRegEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const3720b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
3730b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
3740b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
3750b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
3760b57cec5SDimitry Andric if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI);
3770b57cec5SDimitry Andric
3780b57cec5SDimitry Andric // Add a fixup for the TLS register, which simply provides a relocation
3790b57cec5SDimitry Andric // hint to the linker that this statement is part of a relocation sequence.
380af732203SDimitry Andric // Return the thread-pointer register's encoding. Add a one byte displacement
381af732203SDimitry Andric // if using PC relative memops.
382af732203SDimitry Andric const MCExpr *Expr = MO.getExpr();
383af732203SDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr);
384af732203SDimitry Andric bool IsPCRel = SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS_PCREL;
385af732203SDimitry Andric Fixups.push_back(MCFixup::create(IsPCRel ? 1 : 0, Expr,
3860b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_nofixup));
3870b57cec5SDimitry Andric const Triple &TT = STI.getTargetTriple();
3880b57cec5SDimitry Andric bool isPPC64 = TT.isPPC64();
3890b57cec5SDimitry Andric return CTX.getRegisterInfo()->getEncodingValue(isPPC64 ? PPC::X13 : PPC::R2);
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric
getTLSCallEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const3920b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
3930b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
3940b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
3950b57cec5SDimitry Andric // For special TLS calls, we need two fixups; one for the branch target
3960b57cec5SDimitry Andric // (__tls_get_addr), which we create via getDirectBrEncoding as usual,
3970b57cec5SDimitry Andric // and one for the TLSGD or TLSLD symbol, which is emitted here.
3980b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo+1);
3990b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(),
4000b57cec5SDimitry Andric (MCFixupKind)PPC::fixup_ppc_nofixup));
4010b57cec5SDimitry Andric return getDirectBrEncoding(MI, OpNo, Fixups, STI);
4020b57cec5SDimitry Andric }
4030b57cec5SDimitry Andric
4040b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::
get_crbitm_encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const4050b57cec5SDimitry Andric get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
4060b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
4070b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
4080b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
4090b57cec5SDimitry Andric assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||
4100b57cec5SDimitry Andric MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&
4110b57cec5SDimitry Andric (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
4120b57cec5SDimitry Andric return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric
4150b57cec5SDimitry Andric // Get the index for this operand in this instruction. This is needed for
4160b57cec5SDimitry Andric // computing the register number in PPCInstrInfo::getRegNumForOperand() for
4170b57cec5SDimitry Andric // any instructions that use a different numbering scheme for registers in
4180b57cec5SDimitry Andric // different operands.
getOpIdxForMO(const MCInst & MI,const MCOperand & MO)4190b57cec5SDimitry Andric static unsigned getOpIdxForMO(const MCInst &MI, const MCOperand &MO) {
4200b57cec5SDimitry Andric for (unsigned i = 0; i < MI.getNumOperands(); i++) {
4210b57cec5SDimitry Andric const MCOperand &Op = MI.getOperand(i);
4220b57cec5SDimitry Andric if (&Op == &MO)
4230b57cec5SDimitry Andric return i;
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric llvm_unreachable("This operand is not part of this instruction");
4260b57cec5SDimitry Andric return ~0U; // Silence any warnings about no return.
4270b57cec5SDimitry Andric }
4280b57cec5SDimitry Andric
4295ffd83dbSDimitry Andric uint64_t PPCMCCodeEmitter::
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const4300b57cec5SDimitry Andric getMachineOpValue(const MCInst &MI, const MCOperand &MO,
4310b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
4320b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
4330b57cec5SDimitry Andric if (MO.isReg()) {
4340b57cec5SDimitry Andric // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
4350b57cec5SDimitry Andric // The GPR operand should come through here though.
4360b57cec5SDimitry Andric assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
4370b57cec5SDimitry Andric MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
4380b57cec5SDimitry Andric MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
4390b57cec5SDimitry Andric unsigned OpNo = getOpIdxForMO(MI, MO);
4400b57cec5SDimitry Andric unsigned Reg =
4410b57cec5SDimitry Andric PPCInstrInfo::getRegNumForOperand(MCII.get(MI.getOpcode()),
4420b57cec5SDimitry Andric MO.getReg(), OpNo);
4430b57cec5SDimitry Andric return CTX.getRegisterInfo()->getEncodingValue(Reg);
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric
4460b57cec5SDimitry Andric assert(MO.isImm() &&
4470b57cec5SDimitry Andric "Relocation required in an instruction that we cannot encode!");
4480b57cec5SDimitry Andric return MO.getImm();
4490b57cec5SDimitry Andric }
4500b57cec5SDimitry Andric
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const4510b57cec5SDimitry Andric void PPCMCCodeEmitter::encodeInstruction(
4520b57cec5SDimitry Andric const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups,
4530b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
4540b57cec5SDimitry Andric verifyInstructionPredicates(MI,
4550b57cec5SDimitry Andric computeAvailableFeatures(STI.getFeatureBits()));
4560b57cec5SDimitry Andric
4570b57cec5SDimitry Andric uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
4580b57cec5SDimitry Andric
4590b57cec5SDimitry Andric // Output the constant in big/little endian byte order.
4600b57cec5SDimitry Andric unsigned Size = getInstSizeInBytes(MI);
4610b57cec5SDimitry Andric support::endianness E = IsLittleEndian ? support::little : support::big;
4620b57cec5SDimitry Andric switch (Size) {
4630b57cec5SDimitry Andric case 0:
4640b57cec5SDimitry Andric break;
4650b57cec5SDimitry Andric case 4:
4660b57cec5SDimitry Andric support::endian::write<uint32_t>(OS, Bits, E);
4670b57cec5SDimitry Andric break;
4680b57cec5SDimitry Andric case 8:
4690b57cec5SDimitry Andric // If we emit a pair of instructions, the first one is
4700b57cec5SDimitry Andric // always in the top 32 bits, even on little-endian.
4710b57cec5SDimitry Andric support::endian::write<uint32_t>(OS, Bits >> 32, E);
4720b57cec5SDimitry Andric support::endian::write<uint32_t>(OS, Bits, E);
4730b57cec5SDimitry Andric break;
4740b57cec5SDimitry Andric default:
4750b57cec5SDimitry Andric llvm_unreachable("Invalid instruction size");
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric
4780b57cec5SDimitry Andric ++MCNumEmitted; // Keep track of the # of mi's emitted.
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric
4810b57cec5SDimitry Andric // Get the number of bytes used to encode the given MCInst.
getInstSizeInBytes(const MCInst & MI) const4820b57cec5SDimitry Andric unsigned PPCMCCodeEmitter::getInstSizeInBytes(const MCInst &MI) const {
4830b57cec5SDimitry Andric unsigned Opcode = MI.getOpcode();
4840b57cec5SDimitry Andric const MCInstrDesc &Desc = MCII.get(Opcode);
4850b57cec5SDimitry Andric return Desc.getSize();
4860b57cec5SDimitry Andric }
4870b57cec5SDimitry Andric
isPrefixedInstruction(const MCInst & MI) const4885ffd83dbSDimitry Andric bool PPCMCCodeEmitter::isPrefixedInstruction(const MCInst &MI) const {
4895ffd83dbSDimitry Andric unsigned Opcode = MI.getOpcode();
4905ffd83dbSDimitry Andric const PPCInstrInfo *InstrInfo = static_cast<const PPCInstrInfo*>(&MCII);
4915ffd83dbSDimitry Andric return InstrInfo->isPrefixed(Opcode);
4925ffd83dbSDimitry Andric }
4935ffd83dbSDimitry Andric
4940b57cec5SDimitry Andric #define ENABLE_INSTR_PREDICATE_VERIFIER
4950b57cec5SDimitry Andric #include "PPCGenMCCodeEmitter.inc"
496