xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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 
createPPCMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)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::
getDirectBrEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const440b57cec5SDimitry 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.
isNoTOCCallInstr(const MCInst & MI) const62*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 
getCondBrEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const1540b57cec5SDimitry 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::
getAbsDirectBrEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const1670b57cec5SDimitry 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::
getAbsCondBrEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const1800b57cec5SDimitry 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
getVSRpEvenEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const193e8d8bef9SDimitry 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 
getImm16Encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const2020b57cec5SDimitry 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 
getImm34Encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI,MCFixupKind Fixup) const214e8d8bef9SDimitry 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
getImm34EncodingNoPCRel(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const229e8d8bef9SDimitry 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
getImm34EncodingPCRel(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const237e8d8bef9SDimitry 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 
getDispRIEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const24406c3fb27SDimitry 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
getDispRIXEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const25806c3fb27SDimitry 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
getDispRIX16Encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const27206c3fb27SDimitry 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
getDispRIHashEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const28906c3fb27SDimitry 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
getDispRI34PCRelEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const30406c3fb27SDimitry 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
getDispRI34Encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const38706c3fb27SDimitry 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
getDispSPE8Encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const39606c3fb27SDimitry 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
getDispSPE4Encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const40606c3fb27SDimitry 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
getDispSPE2Encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const41606c3fb27SDimitry 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 
getTLSRegEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const4250b57cec5SDimitry 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 
getTLSCallEncoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const4450b57cec5SDimitry 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::
get_crbitm_encoding(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const4580b57cec5SDimitry 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.
getOpIdxForMO(const MCInst & MI,const MCOperand & MO)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::
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const4830b57cec5SDimitry 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 
encodeInstruction(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const50306c3fb27SDimitry 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.
getInstSizeInBytes(const MCInst & MI) const5330b57cec5SDimitry 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 
isPrefixedInstruction(const MCInst & MI) const5395ffd83dbSDimitry 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