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