| 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 | |