xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
1 //===-- PPCMCCodeEmitter.cpp - Convert PPC code to machine code -----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the PPCMCCodeEmitter class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "PPCMCCodeEmitter.h"
14 #include "MCTargetDesc/PPCFixupKinds.h"
15 #include "PPCInstrInfo.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/Statistic.h"
18 #include "llvm/MC/MCFixup.h"
19 #include "llvm/MC/MCInstrDesc.h"
20 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/Support/Endian.h"
22 #include "llvm/Support/EndianStream.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/MathExtras.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/TargetParser/Triple.h"
27 #include <cassert>
28 #include <cstdint>
29 
30 using namespace llvm;
31 
32 #define DEBUG_TYPE "mccodeemitter"
33 
34 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
35 
36 MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
37                                             MCContext &Ctx) {
38   return new PPCMCCodeEmitter(MCII, Ctx);
39 }
40 
41 unsigned PPCMCCodeEmitter::
42 getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
43                     SmallVectorImpl<MCFixup> &Fixups,
44                     const MCSubtargetInfo &STI) const {
45   const MCOperand &MO = MI.getOperand(OpNo);
46 
47   if (MO.isReg() || MO.isImm())
48     return getMachineOpValue(MI, MO, Fixups, STI);
49 
50   const PPCInstrInfo *InstrInfo = static_cast<const PPCInstrInfo *>(&MCII);
51   unsigned Opcode = MI.getOpcode();
52   // Add a fixup for the branch target.
53   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
54                                    (InstrInfo->isNoTOCCallInstr(Opcode)
55                                         ? (MCFixupKind)PPC::fixup_ppc_br24_notoc
56                                         : (MCFixupKind)PPC::fixup_ppc_br24)));
57   return 0;
58 }
59 
60 unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
61                                      SmallVectorImpl<MCFixup> &Fixups,
62                                      const MCSubtargetInfo &STI) const {
63   const MCOperand &MO = MI.getOperand(OpNo);
64   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
65 
66   // Add a fixup for the branch target.
67   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
68                                    (MCFixupKind)PPC::fixup_ppc_brcond14));
69   return 0;
70 }
71 
72 unsigned PPCMCCodeEmitter::
73 getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
74                        SmallVectorImpl<MCFixup> &Fixups,
75                        const MCSubtargetInfo &STI) const {
76   const MCOperand &MO = MI.getOperand(OpNo);
77   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
78 
79   // Add a fixup for the branch target.
80   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
81                                    (MCFixupKind)PPC::fixup_ppc_br24abs));
82   return 0;
83 }
84 
85 unsigned PPCMCCodeEmitter::
86 getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
87                      SmallVectorImpl<MCFixup> &Fixups,
88                      const MCSubtargetInfo &STI) const {
89   const MCOperand &MO = MI.getOperand(OpNo);
90   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
91 
92   // Add a fixup for the branch target.
93   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
94                                    (MCFixupKind)PPC::fixup_ppc_brcond14abs));
95   return 0;
96 }
97 
98 unsigned
99 PPCMCCodeEmitter::getVSRpEvenEncoding(const MCInst &MI, unsigned OpNo,
100                                       SmallVectorImpl<MCFixup> &Fixups,
101                                       const MCSubtargetInfo &STI) const {
102   assert(MI.getOperand(OpNo).isReg() && "Operand should be a register");
103   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI)
104                      << 1;
105   return RegBits;
106 }
107 
108 unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo,
109                                        SmallVectorImpl<MCFixup> &Fixups,
110                                        const MCSubtargetInfo &STI) const {
111   const MCOperand &MO = MI.getOperand(OpNo);
112   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
113 
114   // Add a fixup for the immediate field.
115   Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
116                                    (MCFixupKind)PPC::fixup_ppc_half16));
117   return 0;
118 }
119 
120 uint64_t PPCMCCodeEmitter::getImm34Encoding(const MCInst &MI, unsigned OpNo,
121                                             SmallVectorImpl<MCFixup> &Fixups,
122                                             const MCSubtargetInfo &STI,
123                                             MCFixupKind Fixup) const {
124   const MCOperand &MO = MI.getOperand(OpNo);
125   assert(!MO.isReg() && "Not expecting a register for this operand.");
126   if (MO.isImm())
127     return getMachineOpValue(MI, MO, Fixups, STI);
128 
129   // Add a fixup for the immediate field.
130   Fixups.push_back(MCFixup::create(0, MO.getExpr(), Fixup));
131   return 0;
132 }
133 
134 uint64_t
135 PPCMCCodeEmitter::getImm34EncodingNoPCRel(const MCInst &MI, unsigned OpNo,
136                                           SmallVectorImpl<MCFixup> &Fixups,
137                                           const MCSubtargetInfo &STI) const {
138   return getImm34Encoding(MI, OpNo, Fixups, STI,
139                           (MCFixupKind)PPC::fixup_ppc_imm34);
140 }
141 
142 uint64_t
143 PPCMCCodeEmitter::getImm34EncodingPCRel(const MCInst &MI, unsigned OpNo,
144                                         SmallVectorImpl<MCFixup> &Fixups,
145                                         const MCSubtargetInfo &STI) const {
146   return getImm34Encoding(MI, OpNo, Fixups, STI,
147                           (MCFixupKind)PPC::fixup_ppc_pcrel34);
148 }
149 
150 unsigned PPCMCCodeEmitter::getDispRIEncoding(const MCInst &MI, unsigned OpNo,
151                                              SmallVectorImpl<MCFixup> &Fixups,
152                                              const MCSubtargetInfo &STI) const {
153   const MCOperand &MO = MI.getOperand(OpNo);
154   if (MO.isImm())
155     return getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF;
156 
157   // Add a fixup for the displacement field.
158   Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
159                                    (MCFixupKind)PPC::fixup_ppc_half16));
160   return 0;
161 }
162 
163 unsigned
164 PPCMCCodeEmitter::getDispRIXEncoding(const MCInst &MI, unsigned OpNo,
165                                      SmallVectorImpl<MCFixup> &Fixups,
166                                      const MCSubtargetInfo &STI) const {
167   const MCOperand &MO = MI.getOperand(OpNo);
168   if (MO.isImm())
169     return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF);
170 
171   // Add a fixup for the displacement field.
172   Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
173                                    (MCFixupKind)PPC::fixup_ppc_half16ds));
174   return 0;
175 }
176 
177 unsigned
178 PPCMCCodeEmitter::getDispRIX16Encoding(const MCInst &MI, unsigned OpNo,
179                                        SmallVectorImpl<MCFixup> &Fixups,
180                                        const MCSubtargetInfo &STI) const {
181   const MCOperand &MO = MI.getOperand(OpNo);
182   if (MO.isImm()) {
183     assert(!(MO.getImm() % 16) &&
184            "Expecting an immediate that is a multiple of 16");
185     return ((getMachineOpValue(MI, MO, Fixups, STI) >> 4) & 0xFFF);
186   }
187 
188   // Otherwise add a fixup for the displacement field.
189   Fixups.push_back(MCFixup::create(IsLittleEndian ? 0 : 2, MO.getExpr(),
190                                    (MCFixupKind)PPC::fixup_ppc_half16dq));
191   return 0;
192 }
193 
194 unsigned
195 PPCMCCodeEmitter::getDispRIHashEncoding(const MCInst &MI, unsigned OpNo,
196                                         SmallVectorImpl<MCFixup> &Fixups,
197                                         const MCSubtargetInfo &STI) const {
198   // Encode imm for the hash load/store to stack for the ROP Protection
199   // instructions.
200   const MCOperand &MO = MI.getOperand(OpNo);
201 
202   assert(MO.isImm() && "Expecting an immediate operand.");
203   assert(!(MO.getImm() % 8) && "Expecting offset to be 8 byte aligned.");
204 
205   unsigned DX = (MO.getImm() >> 3) & 0x3F;
206   return DX;
207 }
208 
209 uint64_t
210 PPCMCCodeEmitter::getDispRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
211                                            SmallVectorImpl<MCFixup> &Fixups,
212                                            const MCSubtargetInfo &STI) const {
213   // Encode the displacement part of pc-relative memri34, which is an imm34.
214   // The 34 bit immediate can fall into one of three cases:
215   // 1) It is a relocation to be filled in by the linker represented as:
216   //    (MCExpr::SymbolRef)
217   // 2) It is a relocation + SignedOffset represented as:
218   //    (MCExpr::Binary(MCExpr::SymbolRef + MCExpr::Constant))
219   // 3) It is a known value at compile time.
220 
221   // If this is not a MCExpr then we are in case 3) and we are dealing with
222   // a value known at compile time, not a relocation.
223   const MCOperand &MO = MI.getOperand(OpNo);
224   if (!MO.isExpr())
225     return (getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL;
226 
227   // At this point in the function it is known that MO is of type MCExpr.
228   // Therefore we are dealing with either case 1) a symbol ref or
229   // case 2) a symbol ref plus a constant.
230   const MCExpr *Expr = MO.getExpr();
231   switch (Expr->getKind()) {
232   default:
233     llvm_unreachable("Unsupported MCExpr for getMemRI34PCRelEncoding.");
234   case MCExpr::SymbolRef: {
235     // Relocation alone.
236     const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr);
237     (void)SRE;
238     // Currently these are the only valid PCRelative Relocations.
239     assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL ||
240             SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL ||
241             SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL ||
242             SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL ||
243             SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL) &&
244            "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL or "
245            "VK_PPC_GOT_TLSGD_PCREL or VK_PPC_GOT_TLSLD_PCREL or "
246            "VK_PPC_GOT_TPREL_PCREL.");
247     // Generate the fixup for the relocation.
248     Fixups.push_back(
249         MCFixup::create(0, Expr,
250                         static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34)));
251     // Put zero in the location of the immediate. The linker will fill in the
252     // correct value based on the relocation.
253     return 0;
254   }
255   case MCExpr::Binary: {
256     // Relocation plus some offset.
257     const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
258     assert(BE->getOpcode() == MCBinaryExpr::Add &&
259            "Binary expression opcode must be an add.");
260 
261     const MCExpr *LHS = BE->getLHS();
262     const MCExpr *RHS = BE->getRHS();
263 
264     // Need to check in both directions. Reloc+Offset and Offset+Reloc.
265     if (LHS->getKind() != MCExpr::SymbolRef)
266       std::swap(LHS, RHS);
267 
268     if (LHS->getKind() != MCExpr::SymbolRef ||
269         RHS->getKind() != MCExpr::Constant)
270       llvm_unreachable("Expecting to have one constant and one relocation.");
271 
272     const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(LHS);
273     (void)SRE;
274     assert(isInt<34>(cast<MCConstantExpr>(RHS)->getValue()) &&
275            "Value must fit in 34 bits.");
276 
277     // Currently these are the only valid PCRelative Relocations.
278     assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL ||
279             SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL) &&
280            "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL");
281     // Generate the fixup for the relocation.
282     Fixups.push_back(
283         MCFixup::create(0, Expr,
284                         static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34)));
285     // Put zero in the location of the immediate. The linker will fill in the
286     // correct value based on the relocation.
287     return 0;
288     }
289   }
290 }
291 
292 uint64_t
293 PPCMCCodeEmitter::getDispRI34Encoding(const MCInst &MI, unsigned OpNo,
294                                       SmallVectorImpl<MCFixup> &Fixups,
295                                       const MCSubtargetInfo &STI) const {
296   // Encode the displacement part of a memri34.
297   const MCOperand &MO = MI.getOperand(OpNo);
298   return (getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL;
299 }
300 
301 unsigned
302 PPCMCCodeEmitter::getDispSPE8Encoding(const MCInst &MI, unsigned OpNo,
303                                       SmallVectorImpl<MCFixup> &Fixups,
304                                       const MCSubtargetInfo &STI) const {
305   // Encode imm as a dispSPE8, which has the low 5-bits of (imm / 8).
306   const MCOperand &MO = MI.getOperand(OpNo);
307   assert(MO.isImm());
308   return getMachineOpValue(MI, MO, Fixups, STI) >> 3;
309 }
310 
311 unsigned
312 PPCMCCodeEmitter::getDispSPE4Encoding(const MCInst &MI, unsigned OpNo,
313                                       SmallVectorImpl<MCFixup> &Fixups,
314                                       const MCSubtargetInfo &STI) const {
315   // Encode imm as a dispSPE8, which has the low 5-bits of (imm / 4).
316   const MCOperand &MO = MI.getOperand(OpNo);
317   assert(MO.isImm());
318   return getMachineOpValue(MI, MO, Fixups, STI) >> 2;
319 }
320 
321 unsigned
322 PPCMCCodeEmitter::getDispSPE2Encoding(const MCInst &MI, unsigned OpNo,
323                                       SmallVectorImpl<MCFixup> &Fixups,
324                                       const MCSubtargetInfo &STI) const {
325   // Encode imm as a dispSPE8, which has the low 5-bits of (imm / 2).
326   const MCOperand &MO = MI.getOperand(OpNo);
327   assert(MO.isImm());
328   return getMachineOpValue(MI, MO, Fixups, STI) >> 1;
329 }
330 
331 unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
332                                        SmallVectorImpl<MCFixup> &Fixups,
333                                        const MCSubtargetInfo &STI) const {
334   const MCOperand &MO = MI.getOperand(OpNo);
335   if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI);
336 
337   // Add a fixup for the TLS register, which simply provides a relocation
338   // hint to the linker that this statement is part of a relocation sequence.
339   // Return the thread-pointer register's encoding. Add a one byte displacement
340   // if using PC relative memops.
341   const MCExpr *Expr = MO.getExpr();
342   const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr);
343   bool IsPCRel = SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS_PCREL;
344   Fixups.push_back(MCFixup::create(IsPCRel ? 1 : 0, Expr,
345                                    (MCFixupKind)PPC::fixup_ppc_nofixup));
346   const Triple &TT = STI.getTargetTriple();
347   bool isPPC64 = TT.isPPC64();
348   return CTX.getRegisterInfo()->getEncodingValue(isPPC64 ? PPC::X13 : PPC::R2);
349 }
350 
351 unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
352                                        SmallVectorImpl<MCFixup> &Fixups,
353                                        const MCSubtargetInfo &STI) const {
354   // For special TLS calls, we need two fixups; one for the branch target
355   // (__tls_get_addr), which we create via getDirectBrEncoding as usual,
356   // and one for the TLSGD or TLSLD symbol, which is emitted here.
357   const MCOperand &MO = MI.getOperand(OpNo+1);
358   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
359                                    (MCFixupKind)PPC::fixup_ppc_nofixup));
360   return getDirectBrEncoding(MI, OpNo, Fixups, STI);
361 }
362 
363 unsigned PPCMCCodeEmitter::
364 get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
365                     SmallVectorImpl<MCFixup> &Fixups,
366                     const MCSubtargetInfo &STI) const {
367   const MCOperand &MO = MI.getOperand(OpNo);
368   assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||
369           MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&
370          (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
371   return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
372 }
373 
374 // Get the index for this operand in this instruction. This is needed for
375 // computing the register number in PPCInstrInfo::getRegNumForOperand() for
376 // any instructions that use a different numbering scheme for registers in
377 // different operands.
378 static unsigned getOpIdxForMO(const MCInst &MI, const MCOperand &MO) {
379   for (unsigned i = 0; i < MI.getNumOperands(); i++) {
380     const MCOperand &Op = MI.getOperand(i);
381     if (&Op == &MO)
382       return i;
383   }
384   llvm_unreachable("This operand is not part of this instruction");
385   return ~0U; // Silence any warnings about no return.
386 }
387 
388 uint64_t PPCMCCodeEmitter::
389 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
390                   SmallVectorImpl<MCFixup> &Fixups,
391                   const MCSubtargetInfo &STI) const {
392   if (MO.isReg()) {
393     // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
394     // The GPR operand should come through here though.
395     assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
396             MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
397            MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
398     unsigned OpNo = getOpIdxForMO(MI, MO);
399     unsigned Reg =
400       PPCInstrInfo::getRegNumForOperand(MCII.get(MI.getOpcode()),
401                                         MO.getReg(), OpNo);
402     return CTX.getRegisterInfo()->getEncodingValue(Reg);
403   }
404 
405   assert(MO.isImm() &&
406          "Relocation required in an instruction that we cannot encode!");
407   return MO.getImm();
408 }
409 
410 void PPCMCCodeEmitter::encodeInstruction(const MCInst &MI,
411                                          SmallVectorImpl<char> &CB,
412                                          SmallVectorImpl<MCFixup> &Fixups,
413                                          const MCSubtargetInfo &STI) const {
414   uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
415 
416   // Output the constant in big/little endian byte order.
417   unsigned Size = getInstSizeInBytes(MI);
418   support::endianness E = IsLittleEndian ? support::little : support::big;
419   switch (Size) {
420   case 0:
421     break;
422   case 4:
423     support::endian::write<uint32_t>(CB, Bits, E);
424     break;
425   case 8:
426     // If we emit a pair of instructions, the first one is
427     // always in the top 32 bits, even on little-endian.
428     support::endian::write<uint32_t>(CB, Bits >> 32, E);
429     support::endian::write<uint32_t>(CB, Bits, E);
430     break;
431   default:
432     llvm_unreachable("Invalid instruction size");
433   }
434 
435   ++MCNumEmitted; // Keep track of the # of mi's emitted.
436 }
437 
438 // Get the number of bytes used to encode the given MCInst.
439 unsigned PPCMCCodeEmitter::getInstSizeInBytes(const MCInst &MI) const {
440   unsigned Opcode = MI.getOpcode();
441   const MCInstrDesc &Desc = MCII.get(Opcode);
442   return Desc.getSize();
443 }
444 
445 bool PPCMCCodeEmitter::isPrefixedInstruction(const MCInst &MI) const {
446   unsigned Opcode = MI.getOpcode();
447   const PPCInstrInfo *InstrInfo = static_cast<const PPCInstrInfo*>(&MCII);
448   return InstrInfo->isPrefixed(Opcode);
449 }
450 
451 #include "PPCGenMCCodeEmitter.inc"
452