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 "PPCMCTargetDesc.h" |
16 | #include "llvm/ADT/SmallVector.h" |
17 | #include "llvm/ADT/Statistic.h" |
18 | #include "llvm/MC/MCExpr.h" |
19 | #include "llvm/MC/MCFixup.h" |
20 | #include "llvm/MC/MCInstrDesc.h" |
21 | #include "llvm/MC/MCRegisterInfo.h" |
22 | #include "llvm/Support/Casting.h" |
23 | #include "llvm/Support/Endian.h" |
24 | #include "llvm/Support/EndianStream.h" |
25 | #include "llvm/Support/ErrorHandling.h" |
26 | #include "llvm/Support/MathExtras.h" |
27 | #include "llvm/Support/raw_ostream.h" |
28 | #include "llvm/TargetParser/Triple.h" |
29 | #include <cassert> |
30 | #include <cstdint> |
31 | |
32 | using namespace llvm; |
33 | |
34 | #define DEBUG_TYPE "mccodeemitter" |
35 | |
36 | STATISTIC(MCNumEmitted, "Number of MC instructions emitted" ); |
37 | |
38 | MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII, |
39 | MCContext &Ctx) { |
40 | return new PPCMCCodeEmitter(MCII, Ctx); |
41 | } |
42 | |
43 | unsigned PPCMCCodeEmitter:: |
44 | getDirectBrEncoding(const MCInst &MI, unsigned OpNo, |
45 | SmallVectorImpl<MCFixup> &Fixups, |
46 | const MCSubtargetInfo &STI) const { |
47 | const MCOperand &MO = MI.getOperand(i: OpNo); |
48 | |
49 | if (MO.isReg() || MO.isImm()) |
50 | return getMachineOpValue(MI, MO, Fixups, STI); |
51 | |
52 | // Add a fixup for the branch target. |
53 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MO.getExpr(), |
54 | Kind: (isNoTOCCallInstr(MI) |
55 | ? (MCFixupKind)PPC::fixup_ppc_br24_notoc |
56 | : (MCFixupKind)PPC::fixup_ppc_br24))); |
57 | return 0; |
58 | } |
59 | |
60 | /// Check if Opcode corresponds to a call instruction that should be marked |
61 | /// with the NOTOC relocation. |
62 | bool PPCMCCodeEmitter::isNoTOCCallInstr(const MCInst &MI) const { |
63 | unsigned Opcode = MI.getOpcode(); |
64 | if (!MCII.get(Opcode).isCall()) |
65 | return false; |
66 | |
67 | switch (Opcode) { |
68 | default: |
69 | #ifndef NDEBUG |
70 | llvm_unreachable("Unknown call opcode" ); |
71 | #endif |
72 | return false; |
73 | case PPC::BL8_NOTOC: |
74 | case PPC::BL8_NOTOC_TLS: |
75 | case PPC::BL8_NOTOC_RM: |
76 | return true; |
77 | #ifndef NDEBUG |
78 | case PPC::BL8: |
79 | case PPC::BL: |
80 | case PPC::BL8_TLS: |
81 | case PPC::BL_TLS: |
82 | case PPC::BLA8: |
83 | case PPC::BLA: |
84 | case PPC::BCCL: |
85 | case PPC::BCCLA: |
86 | case PPC::BCL: |
87 | case PPC::BCLn: |
88 | case PPC::BL8_NOP: |
89 | case PPC::BL_NOP: |
90 | case PPC::BL8_NOP_TLS: |
91 | case PPC::BLA8_NOP: |
92 | case PPC::BCTRL8: |
93 | case PPC::BCTRL: |
94 | case PPC::BCCCTRL8: |
95 | case PPC::BCCCTRL: |
96 | case PPC::BCCTRL8: |
97 | case PPC::BCCTRL: |
98 | case PPC::BCCTRL8n: |
99 | case PPC::BCCTRLn: |
100 | case PPC::BL8_RM: |
101 | case PPC::BLA8_RM: |
102 | case PPC::BL8_NOP_RM: |
103 | case PPC::BLA8_NOP_RM: |
104 | case PPC::BCTRL8_RM: |
105 | case PPC::BCTRL8_LDinto_toc: |
106 | case PPC::BCTRL8_LDinto_toc_RM: |
107 | case PPC::BL8_TLS_: |
108 | case PPC::TCRETURNdi8: |
109 | case PPC::TCRETURNai8: |
110 | case PPC::TCRETURNri8: |
111 | case PPC::TAILBCTR8: |
112 | case PPC::TAILB8: |
113 | case PPC::TAILBA8: |
114 | case PPC::BCLalways: |
115 | case PPC::BLRL: |
116 | case PPC::BCCLRL: |
117 | case PPC::BCLRL: |
118 | case PPC::BCLRLn: |
119 | case PPC::BDZL: |
120 | case PPC::BDNZL: |
121 | case PPC::BDZLA: |
122 | case PPC::BDNZLA: |
123 | case PPC::BDZLp: |
124 | case PPC::BDNZLp: |
125 | case PPC::BDZLAp: |
126 | case PPC::BDNZLAp: |
127 | case PPC::BDZLm: |
128 | case PPC::BDNZLm: |
129 | case PPC::BDZLAm: |
130 | case PPC::BDNZLAm: |
131 | case PPC::BDZLRL: |
132 | case PPC::BDNZLRL: |
133 | case PPC::BDZLRLp: |
134 | case PPC::BDNZLRLp: |
135 | case PPC::BDZLRLm: |
136 | case PPC::BDNZLRLm: |
137 | case PPC::BL_RM: |
138 | case PPC::BLA_RM: |
139 | case PPC::BL_NOP_RM: |
140 | case PPC::BCTRL_RM: |
141 | case PPC::TCRETURNdi: |
142 | case PPC::TCRETURNai: |
143 | case PPC::TCRETURNri: |
144 | case PPC::BCTRL_LWZinto_toc: |
145 | case PPC::BCTRL_LWZinto_toc_RM: |
146 | case PPC::TAILBCTR: |
147 | case PPC::TAILB: |
148 | case PPC::TAILBA: |
149 | return false; |
150 | #endif |
151 | } |
152 | } |
153 | |
154 | unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo, |
155 | SmallVectorImpl<MCFixup> &Fixups, |
156 | const MCSubtargetInfo &STI) const { |
157 | const MCOperand &MO = MI.getOperand(i: OpNo); |
158 | if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); |
159 | |
160 | // Add a fixup for the branch target. |
161 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MO.getExpr(), |
162 | Kind: (MCFixupKind)PPC::fixup_ppc_brcond14)); |
163 | return 0; |
164 | } |
165 | |
166 | unsigned PPCMCCodeEmitter:: |
167 | getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo, |
168 | SmallVectorImpl<MCFixup> &Fixups, |
169 | const MCSubtargetInfo &STI) const { |
170 | const MCOperand &MO = MI.getOperand(i: OpNo); |
171 | if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); |
172 | |
173 | // Add a fixup for the branch target. |
174 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MO.getExpr(), |
175 | Kind: (MCFixupKind)PPC::fixup_ppc_br24abs)); |
176 | return 0; |
177 | } |
178 | |
179 | unsigned PPCMCCodeEmitter:: |
180 | getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo, |
181 | SmallVectorImpl<MCFixup> &Fixups, |
182 | const MCSubtargetInfo &STI) const { |
183 | const MCOperand &MO = MI.getOperand(i: OpNo); |
184 | if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); |
185 | |
186 | // Add a fixup for the branch target. |
187 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MO.getExpr(), |
188 | Kind: (MCFixupKind)PPC::fixup_ppc_brcond14abs)); |
189 | return 0; |
190 | } |
191 | |
192 | unsigned |
193 | PPCMCCodeEmitter::getVSRpEvenEncoding(const MCInst &MI, unsigned OpNo, |
194 | SmallVectorImpl<MCFixup> &Fixups, |
195 | const MCSubtargetInfo &STI) const { |
196 | assert(MI.getOperand(OpNo).isReg() && "Operand should be a register" ); |
197 | unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI) |
198 | << 1; |
199 | return RegBits; |
200 | } |
201 | |
202 | unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo, |
203 | SmallVectorImpl<MCFixup> &Fixups, |
204 | const MCSubtargetInfo &STI) const { |
205 | const MCOperand &MO = MI.getOperand(i: OpNo); |
206 | if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); |
207 | |
208 | // Add a fixup for the immediate field. |
209 | Fixups.push_back(Elt: MCFixup::create(Offset: IsLittleEndian? 0 : 2, Value: MO.getExpr(), |
210 | Kind: (MCFixupKind)PPC::fixup_ppc_half16)); |
211 | return 0; |
212 | } |
213 | |
214 | uint64_t PPCMCCodeEmitter::getImm34Encoding(const MCInst &MI, unsigned OpNo, |
215 | SmallVectorImpl<MCFixup> &Fixups, |
216 | const MCSubtargetInfo &STI, |
217 | MCFixupKind Fixup) const { |
218 | const MCOperand &MO = MI.getOperand(i: OpNo); |
219 | assert(!MO.isReg() && "Not expecting a register for this operand." ); |
220 | if (MO.isImm()) |
221 | return getMachineOpValue(MI, MO, Fixups, STI); |
222 | |
223 | // Add a fixup for the immediate field. |
224 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MO.getExpr(), Kind: Fixup)); |
225 | return 0; |
226 | } |
227 | |
228 | uint64_t |
229 | PPCMCCodeEmitter::getImm34EncodingNoPCRel(const MCInst &MI, unsigned OpNo, |
230 | SmallVectorImpl<MCFixup> &Fixups, |
231 | const MCSubtargetInfo &STI) const { |
232 | return getImm34Encoding(MI, OpNo, Fixups, STI, |
233 | Fixup: (MCFixupKind)PPC::fixup_ppc_imm34); |
234 | } |
235 | |
236 | uint64_t |
237 | PPCMCCodeEmitter::getImm34EncodingPCRel(const MCInst &MI, unsigned OpNo, |
238 | SmallVectorImpl<MCFixup> &Fixups, |
239 | const MCSubtargetInfo &STI) const { |
240 | return getImm34Encoding(MI, OpNo, Fixups, STI, |
241 | Fixup: (MCFixupKind)PPC::fixup_ppc_pcrel34); |
242 | } |
243 | |
244 | unsigned PPCMCCodeEmitter::getDispRIEncoding(const MCInst &MI, unsigned OpNo, |
245 | SmallVectorImpl<MCFixup> &Fixups, |
246 | const MCSubtargetInfo &STI) const { |
247 | const MCOperand &MO = MI.getOperand(i: OpNo); |
248 | if (MO.isImm()) |
249 | return getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF; |
250 | |
251 | // Add a fixup for the displacement field. |
252 | Fixups.push_back(Elt: MCFixup::create(Offset: IsLittleEndian? 0 : 2, Value: MO.getExpr(), |
253 | Kind: (MCFixupKind)PPC::fixup_ppc_half16)); |
254 | return 0; |
255 | } |
256 | |
257 | unsigned |
258 | PPCMCCodeEmitter::getDispRIXEncoding(const MCInst &MI, unsigned OpNo, |
259 | SmallVectorImpl<MCFixup> &Fixups, |
260 | const MCSubtargetInfo &STI) const { |
261 | const MCOperand &MO = MI.getOperand(i: OpNo); |
262 | if (MO.isImm()) |
263 | return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF); |
264 | |
265 | // Add a fixup for the displacement field. |
266 | Fixups.push_back(Elt: MCFixup::create(Offset: IsLittleEndian? 0 : 2, Value: MO.getExpr(), |
267 | Kind: (MCFixupKind)PPC::fixup_ppc_half16ds)); |
268 | return 0; |
269 | } |
270 | |
271 | unsigned |
272 | PPCMCCodeEmitter::getDispRIX16Encoding(const MCInst &MI, unsigned OpNo, |
273 | SmallVectorImpl<MCFixup> &Fixups, |
274 | const MCSubtargetInfo &STI) const { |
275 | const MCOperand &MO = MI.getOperand(i: OpNo); |
276 | if (MO.isImm()) { |
277 | assert(!(MO.getImm() % 16) && |
278 | "Expecting an immediate that is a multiple of 16" ); |
279 | return ((getMachineOpValue(MI, MO, Fixups, STI) >> 4) & 0xFFF); |
280 | } |
281 | |
282 | // Otherwise add a fixup for the displacement field. |
283 | Fixups.push_back(Elt: MCFixup::create(Offset: IsLittleEndian ? 0 : 2, Value: MO.getExpr(), |
284 | Kind: (MCFixupKind)PPC::fixup_ppc_half16dq)); |
285 | return 0; |
286 | } |
287 | |
288 | unsigned |
289 | PPCMCCodeEmitter::getDispRIHashEncoding(const MCInst &MI, unsigned OpNo, |
290 | SmallVectorImpl<MCFixup> &Fixups, |
291 | const MCSubtargetInfo &STI) const { |
292 | // Encode imm for the hash load/store to stack for the ROP Protection |
293 | // instructions. |
294 | const MCOperand &MO = MI.getOperand(i: OpNo); |
295 | |
296 | assert(MO.isImm() && "Expecting an immediate operand." ); |
297 | assert(!(MO.getImm() % 8) && "Expecting offset to be 8 byte aligned." ); |
298 | |
299 | unsigned DX = (MO.getImm() >> 3) & 0x3F; |
300 | return DX; |
301 | } |
302 | |
303 | uint64_t |
304 | PPCMCCodeEmitter::getDispRI34PCRelEncoding(const MCInst &MI, unsigned OpNo, |
305 | SmallVectorImpl<MCFixup> &Fixups, |
306 | const MCSubtargetInfo &STI) const { |
307 | // Encode the displacement part of pc-relative memri34, which is an imm34. |
308 | // The 34 bit immediate can fall into one of three cases: |
309 | // 1) It is a relocation to be filled in by the linker represented as: |
310 | // (MCExpr::SymbolRef) |
311 | // 2) It is a relocation + SignedOffset represented as: |
312 | // (MCExpr::Binary(MCExpr::SymbolRef + MCExpr::Constant)) |
313 | // 3) It is a known value at compile time. |
314 | |
315 | // If this is not a MCExpr then we are in case 3) and we are dealing with |
316 | // a value known at compile time, not a relocation. |
317 | const MCOperand &MO = MI.getOperand(i: OpNo); |
318 | if (!MO.isExpr()) |
319 | return (getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL; |
320 | |
321 | // At this point in the function it is known that MO is of type MCExpr. |
322 | // Therefore we are dealing with either case 1) a symbol ref or |
323 | // case 2) a symbol ref plus a constant. |
324 | const MCExpr *Expr = MO.getExpr(); |
325 | switch (Expr->getKind()) { |
326 | default: |
327 | llvm_unreachable("Unsupported MCExpr for getMemRI34PCRelEncoding." ); |
328 | case MCExpr::SymbolRef: { |
329 | // Relocation alone. |
330 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Val: Expr); |
331 | (void)SRE; |
332 | // Currently these are the only valid PCRelative Relocations. |
333 | assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL || |
334 | SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL || |
335 | SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL || |
336 | SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL || |
337 | SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL) && |
338 | "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL or " |
339 | "VK_PPC_GOT_TLSGD_PCREL or VK_PPC_GOT_TLSLD_PCREL or " |
340 | "VK_PPC_GOT_TPREL_PCREL." ); |
341 | // Generate the fixup for the relocation. |
342 | Fixups.push_back( |
343 | Elt: MCFixup::create(Offset: 0, Value: Expr, |
344 | Kind: static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34))); |
345 | // Put zero in the location of the immediate. The linker will fill in the |
346 | // correct value based on the relocation. |
347 | return 0; |
348 | } |
349 | case MCExpr::Binary: { |
350 | // Relocation plus some offset. |
351 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(Val: Expr); |
352 | assert(BE->getOpcode() == MCBinaryExpr::Add && |
353 | "Binary expression opcode must be an add." ); |
354 | |
355 | const MCExpr *LHS = BE->getLHS(); |
356 | const MCExpr *RHS = BE->getRHS(); |
357 | |
358 | // Need to check in both directions. Reloc+Offset and Offset+Reloc. |
359 | if (LHS->getKind() != MCExpr::SymbolRef) |
360 | std::swap(a&: LHS, b&: RHS); |
361 | |
362 | if (LHS->getKind() != MCExpr::SymbolRef || |
363 | RHS->getKind() != MCExpr::Constant) |
364 | llvm_unreachable("Expecting to have one constant and one relocation." ); |
365 | |
366 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Val: LHS); |
367 | (void)SRE; |
368 | assert(isInt<34>(cast<MCConstantExpr>(RHS)->getValue()) && |
369 | "Value must fit in 34 bits." ); |
370 | |
371 | // Currently these are the only valid PCRelative Relocations. |
372 | assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL || |
373 | SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL) && |
374 | "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL" ); |
375 | // Generate the fixup for the relocation. |
376 | Fixups.push_back( |
377 | Elt: MCFixup::create(Offset: 0, Value: Expr, |
378 | Kind: static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34))); |
379 | // Put zero in the location of the immediate. The linker will fill in the |
380 | // correct value based on the relocation. |
381 | return 0; |
382 | } |
383 | } |
384 | } |
385 | |
386 | uint64_t |
387 | PPCMCCodeEmitter::getDispRI34Encoding(const MCInst &MI, unsigned OpNo, |
388 | SmallVectorImpl<MCFixup> &Fixups, |
389 | const MCSubtargetInfo &STI) const { |
390 | // Encode the displacement part of a memri34. |
391 | const MCOperand &MO = MI.getOperand(i: OpNo); |
392 | return (getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL; |
393 | } |
394 | |
395 | unsigned |
396 | PPCMCCodeEmitter::getDispSPE8Encoding(const MCInst &MI, unsigned OpNo, |
397 | SmallVectorImpl<MCFixup> &Fixups, |
398 | const MCSubtargetInfo &STI) const { |
399 | // Encode imm as a dispSPE8, which has the low 5-bits of (imm / 8). |
400 | const MCOperand &MO = MI.getOperand(i: OpNo); |
401 | assert(MO.isImm()); |
402 | return getMachineOpValue(MI, MO, Fixups, STI) >> 3; |
403 | } |
404 | |
405 | unsigned |
406 | PPCMCCodeEmitter::getDispSPE4Encoding(const MCInst &MI, unsigned OpNo, |
407 | SmallVectorImpl<MCFixup> &Fixups, |
408 | const MCSubtargetInfo &STI) const { |
409 | // Encode imm as a dispSPE8, which has the low 5-bits of (imm / 4). |
410 | const MCOperand &MO = MI.getOperand(i: OpNo); |
411 | assert(MO.isImm()); |
412 | return getMachineOpValue(MI, MO, Fixups, STI) >> 2; |
413 | } |
414 | |
415 | unsigned |
416 | PPCMCCodeEmitter::getDispSPE2Encoding(const MCInst &MI, unsigned OpNo, |
417 | SmallVectorImpl<MCFixup> &Fixups, |
418 | const MCSubtargetInfo &STI) const { |
419 | // Encode imm as a dispSPE8, which has the low 5-bits of (imm / 2). |
420 | const MCOperand &MO = MI.getOperand(i: OpNo); |
421 | assert(MO.isImm()); |
422 | return getMachineOpValue(MI, MO, Fixups, STI) >> 1; |
423 | } |
424 | |
425 | unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo, |
426 | SmallVectorImpl<MCFixup> &Fixups, |
427 | const MCSubtargetInfo &STI) const { |
428 | const MCOperand &MO = MI.getOperand(i: OpNo); |
429 | if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI); |
430 | |
431 | // Add a fixup for the TLS register, which simply provides a relocation |
432 | // hint to the linker that this statement is part of a relocation sequence. |
433 | // Return the thread-pointer register's encoding. Add a one byte displacement |
434 | // if using PC relative memops. |
435 | const MCExpr *Expr = MO.getExpr(); |
436 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Val: Expr); |
437 | bool IsPCRel = SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS_PCREL; |
438 | Fixups.push_back(Elt: MCFixup::create(Offset: IsPCRel ? 1 : 0, Value: Expr, |
439 | Kind: (MCFixupKind)PPC::fixup_ppc_nofixup)); |
440 | const Triple &TT = STI.getTargetTriple(); |
441 | bool isPPC64 = TT.isPPC64(); |
442 | return CTX.getRegisterInfo()->getEncodingValue(RegNo: isPPC64 ? PPC::X13 : PPC::R2); |
443 | } |
444 | |
445 | unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo, |
446 | SmallVectorImpl<MCFixup> &Fixups, |
447 | const MCSubtargetInfo &STI) const { |
448 | // For special TLS calls, we need two fixups; one for the branch target |
449 | // (__tls_get_addr), which we create via getDirectBrEncoding as usual, |
450 | // and one for the TLSGD or TLSLD symbol, which is emitted here. |
451 | const MCOperand &MO = MI.getOperand(i: OpNo+1); |
452 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MO.getExpr(), |
453 | Kind: (MCFixupKind)PPC::fixup_ppc_nofixup)); |
454 | return getDirectBrEncoding(MI, OpNo, Fixups, STI); |
455 | } |
456 | |
457 | unsigned PPCMCCodeEmitter:: |
458 | get_crbitm_encoding(const MCInst &MI, unsigned OpNo, |
459 | SmallVectorImpl<MCFixup> &Fixups, |
460 | const MCSubtargetInfo &STI) const { |
461 | const MCOperand &MO = MI.getOperand(i: OpNo); |
462 | assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 || |
463 | MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) && |
464 | (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)); |
465 | return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(RegNo: MO.getReg()); |
466 | } |
467 | |
468 | // Get the index for this operand in this instruction. This is needed for |
469 | // computing the register number in PPC::getRegNumForOperand() for |
470 | // any instructions that use a different numbering scheme for registers in |
471 | // different operands. |
472 | static unsigned getOpIdxForMO(const MCInst &MI, const MCOperand &MO) { |
473 | for (unsigned i = 0; i < MI.getNumOperands(); i++) { |
474 | const MCOperand &Op = MI.getOperand(i); |
475 | if (&Op == &MO) |
476 | return i; |
477 | } |
478 | llvm_unreachable("This operand is not part of this instruction" ); |
479 | return ~0U; // Silence any warnings about no return. |
480 | } |
481 | |
482 | uint64_t PPCMCCodeEmitter:: |
483 | getMachineOpValue(const MCInst &MI, const MCOperand &MO, |
484 | SmallVectorImpl<MCFixup> &Fixups, |
485 | const MCSubtargetInfo &STI) const { |
486 | if (MO.isReg()) { |
487 | // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand. |
488 | // The GPR operand should come through here though. |
489 | assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 && |
490 | MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) || |
491 | MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7); |
492 | unsigned OpNo = getOpIdxForMO(MI, MO); |
493 | unsigned Reg = |
494 | PPC::getRegNumForOperand(Desc: MCII.get(Opcode: MI.getOpcode()), Reg: MO.getReg(), OpNo); |
495 | return CTX.getRegisterInfo()->getEncodingValue(RegNo: Reg); |
496 | } |
497 | |
498 | assert(MO.isImm() && |
499 | "Relocation required in an instruction that we cannot encode!" ); |
500 | return MO.getImm(); |
501 | } |
502 | |
503 | void PPCMCCodeEmitter::encodeInstruction(const MCInst &MI, |
504 | SmallVectorImpl<char> &CB, |
505 | SmallVectorImpl<MCFixup> &Fixups, |
506 | const MCSubtargetInfo &STI) const { |
507 | uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); |
508 | |
509 | // Output the constant in big/little endian byte order. |
510 | unsigned Size = getInstSizeInBytes(MI); |
511 | llvm::endianness E = |
512 | IsLittleEndian ? llvm::endianness::little : llvm::endianness::big; |
513 | switch (Size) { |
514 | case 0: |
515 | break; |
516 | case 4: |
517 | support::endian::write<uint32_t>(Out&: CB, V: Bits, E); |
518 | break; |
519 | case 8: |
520 | // If we emit a pair of instructions, the first one is |
521 | // always in the top 32 bits, even on little-endian. |
522 | support::endian::write<uint32_t>(Out&: CB, V: Bits >> 32, E); |
523 | support::endian::write<uint32_t>(Out&: CB, V: Bits, E); |
524 | break; |
525 | default: |
526 | llvm_unreachable("Invalid instruction size" ); |
527 | } |
528 | |
529 | ++MCNumEmitted; // Keep track of the # of mi's emitted. |
530 | } |
531 | |
532 | // Get the number of bytes used to encode the given MCInst. |
533 | unsigned PPCMCCodeEmitter::getInstSizeInBytes(const MCInst &MI) const { |
534 | unsigned Opcode = MI.getOpcode(); |
535 | const MCInstrDesc &Desc = MCII.get(Opcode); |
536 | return Desc.getSize(); |
537 | } |
538 | |
539 | bool PPCMCCodeEmitter::isPrefixedInstruction(const MCInst &MI) const { |
540 | return MCII.get(Opcode: MI.getOpcode()).TSFlags & PPCII::Prefixed; |
541 | } |
542 | |
543 | #include "PPCGenMCCodeEmitter.inc" |
544 | |