520 lines · cpp
1//===-- PPCMCTargetDesc.cpp - PowerPC Target Descriptions -----------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file provides PowerPC specific target descriptions.10//11//===----------------------------------------------------------------------===//12 13#include "MCTargetDesc/PPCMCTargetDesc.h"14#include "MCTargetDesc/PPCInstPrinter.h"15#include "MCTargetDesc/PPCMCAsmInfo.h"16#include "PPCELFStreamer.h"17#include "PPCMCAsmInfo.h"18#include "PPCTargetStreamer.h"19#include "PPCXCOFFStreamer.h"20#include "TargetInfo/PowerPCTargetInfo.h"21#include "llvm/ADT/SmallPtrSet.h"22#include "llvm/ADT/StringRef.h"23#include "llvm/BinaryFormat/ELF.h"24#include "llvm/MC/MCAsmBackend.h"25#include "llvm/MC/MCAssembler.h"26#include "llvm/MC/MCCodeEmitter.h"27#include "llvm/MC/MCContext.h"28#include "llvm/MC/MCDwarf.h"29#include "llvm/MC/MCELFObjectWriter.h"30#include "llvm/MC/MCELFStreamer.h"31#include "llvm/MC/MCExpr.h"32#include "llvm/MC/MCInstrAnalysis.h"33#include "llvm/MC/MCInstrInfo.h"34#include "llvm/MC/MCRegisterInfo.h"35#include "llvm/MC/MCSectionXCOFF.h"36#include "llvm/MC/MCStreamer.h"37#include "llvm/MC/MCSubtargetInfo.h"38#include "llvm/MC/MCSymbol.h"39#include "llvm/MC/MCSymbolELF.h"40#include "llvm/MC/MCSymbolXCOFF.h"41#include "llvm/MC/MCXCOFFObjectWriter.h"42#include "llvm/MC/TargetRegistry.h"43#include "llvm/Support/Casting.h"44#include "llvm/Support/Compiler.h"45#include "llvm/Support/ErrorHandling.h"46#include "llvm/Support/FormattedStream.h"47#include "llvm/Support/raw_ostream.h"48#include "llvm/TargetParser/Triple.h"49 50using namespace llvm;51 52#define GET_INSTRINFO_MC_DESC53#define ENABLE_INSTR_PREDICATE_VERIFIER54#include "PPCGenInstrInfo.inc"55 56#define GET_SUBTARGETINFO_MC_DESC57#include "PPCGenSubtargetInfo.inc"58 59#define GET_REGINFO_MC_DESC60#include "PPCGenRegisterInfo.inc"61 62/// stripRegisterPrefix - This method strips the character prefix from a63/// register name so that only the number is left. Used by for linux asm.64const char *PPC::stripRegisterPrefix(const char *RegName) {65 switch (RegName[0]) {66 case 'a':67 if (RegName[1] == 'c' && RegName[2] == 'c')68 return RegName + 3;69 break;70 case 'f':71 if (RegName[1] == 'p')72 return RegName + 2;73 [[fallthrough]];74 case 'r':75 case 'v':76 if (RegName[1] == 's') {77 if (RegName[2] == 'p')78 return RegName + 3;79 return RegName + 2;80 }81 return RegName + 1;82 case 'c':83 if (RegName[1] == 'r')84 return RegName + 2;85 break;86 case 'w':87 // For wacc and wacc_hi88 if (RegName[1] == 'a' && RegName[2] == 'c' && RegName[3] == 'c') {89 if (RegName[4] == '_')90 return RegName + 7;91 else92 return RegName + 4;93 }94 break;95 case 'd':96 // For dmr, dmrp, dmrrow, dmrrowp97 if (RegName[1] == 'm' && RegName[2] == 'r') {98 if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w' &&99 RegName[6] == 'p')100 return RegName + 7;101 else if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w')102 return RegName + 6;103 else if (RegName[3] == 'p')104 return RegName + 4;105 else106 return RegName + 3;107 }108 break;109 }110 111 return RegName;112}113 114/// getRegNumForOperand - some operands use different numbering schemes115/// for the same registers. For example, a VSX instruction may have any of116/// vs0-vs63 allocated whereas an Altivec instruction could only have117/// vs32-vs63 allocated (numbered as v0-v31). This function returns the actual118/// register number needed for the opcode/operand number combination.119/// The operand number argument will be useful when we need to extend this120/// to instructions that use both Altivec and VSX numbering (for different121/// operands).122MCRegister PPC::getRegNumForOperand(const MCInstrDesc &Desc, MCRegister Reg,123 unsigned OpNo) {124 int16_t regClass = Desc.operands()[OpNo].RegClass;125 switch (regClass) {126 // We store F0-F31, VF0-VF31 in MCOperand and it should be F0-F31,127 // VSX32-VSX63 during encoding/disassembling128 case PPC::VSSRCRegClassID:129 case PPC::VSFRCRegClassID:130 if (PPC::isVFRegister(Reg))131 return PPC::VSX32 + (Reg - PPC::VF0);132 break;133 // We store VSL0-VSL31, V0-V31 in MCOperand and it should be VSL0-VSL31,134 // VSX32-VSX63 during encoding/disassembling135 case PPC::VSRCRegClassID:136 if (PPC::isVRRegister(Reg))137 return PPC::VSX32 + (Reg - PPC::V0);138 break;139 // Other RegClass doesn't need mapping140 default:141 break;142 }143 return Reg;144}145 146PPCTargetStreamer::PPCTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}147 148// Pin the vtable to this file.149PPCTargetStreamer::~PPCTargetStreamer() = default;150 151static MCInstrInfo *createPPCMCInstrInfo() {152 MCInstrInfo *X = new MCInstrInfo();153 InitPPCMCInstrInfo(X);154 return X;155}156 157static MCRegisterInfo *createPPCMCRegisterInfo(const Triple &TT) {158 bool isPPC64 =159 (TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le);160 unsigned Flavour = isPPC64 ? 0 : 1;161 unsigned RA = isPPC64 ? PPC::LR8 : PPC::LR;162 163 MCRegisterInfo *X = new MCRegisterInfo();164 InitPPCMCRegisterInfo(X, RA, Flavour, Flavour);165 return X;166}167 168static MCSubtargetInfo *createPPCMCSubtargetInfo(const Triple &TT,169 StringRef CPU, StringRef FS) {170 // Set some default feature to MC layer.171 std::string FullFS = std::string(FS);172 173 if (TT.isOSAIX()) {174 if (!FullFS.empty())175 FullFS = "+aix," + FullFS;176 else177 FullFS = "+aix";178 }179 180 return createPPCMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FullFS);181}182 183static MCAsmInfo *createPPCMCAsmInfo(const MCRegisterInfo &MRI,184 const Triple &TheTriple,185 const MCTargetOptions &Options) {186 bool isPPC64 = (TheTriple.getArch() == Triple::ppc64 ||187 TheTriple.getArch() == Triple::ppc64le);188 189 MCAsmInfo *MAI;190 if (TheTriple.isOSBinFormatXCOFF())191 MAI = new PPCXCOFFMCAsmInfo(isPPC64, TheTriple);192 else193 MAI = new PPCELFMCAsmInfo(isPPC64, TheTriple);194 195 // Initial state of the frame pointer is R1.196 unsigned Reg = isPPC64 ? PPC::X1 : PPC::R1;197 MCCFIInstruction Inst =198 MCCFIInstruction::cfiDefCfa(nullptr, MRI.getDwarfRegNum(Reg, true), 0);199 MAI->addInitialFrameState(Inst);200 201 return MAI;202}203 204namespace {205 206class PPCTargetAsmStreamer : public PPCTargetStreamer {207 formatted_raw_ostream &OS;208 209public:210 PPCTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS)211 : PPCTargetStreamer(S), OS(OS) {}212 213 void emitTCEntry(const MCSymbol &S, PPCMCExpr::Specifier Kind) override {214 if (getContext().isXCOFF()) {215 MCSymbolXCOFF *TCSym =216 static_cast<const MCSectionXCOFF *>(Streamer.getCurrentSectionOnly())217 ->getQualNameSymbol();218 // On AIX, we have TLS variable offsets (symbol@({gd|ie|le|ld}) depending219 // on the TLS access method (or model). For the general-dynamic access220 // method, we also have region handle (symbol@m) for each variable. For221 // local-dynamic, there is a module handle (_$TLSML[TC]@ml) for all222 // variables. Finally for local-exec and initial-exec, we have a thread223 // pointer, in r13 for 64-bit mode and returned by .__get_tpointer for224 // 32-bit mode.225 if (Kind == PPC::S_AIX_TLSGD || Kind == PPC::S_AIX_TLSGDM ||226 Kind == PPC::S_AIX_TLSIE || Kind == PPC::S_AIX_TLSLE ||227 Kind == PPC::S_AIX_TLSLD || Kind == PPC::S_AIX_TLSML)228 OS << "\t.tc " << TCSym->getName() << "," << S.getName() << "@"229 << getContext().getAsmInfo()->getSpecifierName(Kind) << '\n';230 else231 OS << "\t.tc " << TCSym->getName() << "," << S.getName() << '\n';232 233 if (TCSym->hasRename())234 Streamer.emitXCOFFRenameDirective(TCSym, TCSym->getSymbolTableName());235 return;236 }237 238 OS << "\t.tc " << S.getName() << "[TC]," << S.getName() << '\n';239 }240 241 void emitMachine(StringRef CPU) override {242 const Triple &TT = Streamer.getContext().getTargetTriple();243 if (TT.isOSBinFormatXCOFF())244 OS << "\t.machine\t" << '\"' << CPU << '\"' << '\n';245 else246 OS << "\t.machine " << CPU << '\n';247 }248 249 void emitAbiVersion(int AbiVersion) override {250 OS << "\t.abiversion " << AbiVersion << '\n';251 }252 253 void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {254 const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();255 256 OS << "\t.localentry\t";257 S->print(OS, MAI);258 OS << ", ";259 MAI->printExpr(OS, *LocalOffset);260 OS << '\n';261 }262};263 264class PPCTargetELFStreamer : public PPCTargetStreamer {265public:266 PPCTargetELFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}267 268 MCELFStreamer &getStreamer() {269 return static_cast<MCELFStreamer &>(Streamer);270 }271 272 void emitTCEntry(const MCSymbol &S, PPCMCExpr::Specifier Kind) override {273 // Creates a R_PPC64_TOC relocation274 Streamer.emitValueToAlignment(Align(8));275 Streamer.emitSymbolValue(&S, 8);276 }277 278 void emitMachine(StringRef CPU) override {279 // FIXME: Is there anything to do in here or does this directive only280 // limit the parser?281 }282 283 void emitAbiVersion(int AbiVersion) override {284 ELFObjectWriter &W = getStreamer().getWriter();285 unsigned Flags = W.getELFHeaderEFlags();286 Flags &= ~ELF::EF_PPC64_ABI;287 Flags |= (AbiVersion & ELF::EF_PPC64_ABI);288 W.setELFHeaderEFlags(Flags);289 }290 291 void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {292 293 // encodePPC64LocalEntryOffset will report an error if it cannot294 // encode LocalOffset.295 unsigned Encoded = encodePPC64LocalEntryOffset(LocalOffset);296 297 unsigned Other = S->getOther();298 Other &= ~ELF::STO_PPC64_LOCAL_MASK;299 Other |= Encoded;300 S->setOther(Other);301 302 // For GAS compatibility, unless we already saw a .abiversion directive,303 // set e_flags to indicate ELFv2 ABI.304 ELFObjectWriter &W = getStreamer().getWriter();305 unsigned Flags = W.getELFHeaderEFlags();306 if ((Flags & ELF::EF_PPC64_ABI) == 0)307 W.setELFHeaderEFlags(Flags | 2);308 }309 310 void emitAssignment(MCSymbol *S, const MCExpr *Value) override {311 auto *Symbol = static_cast<MCSymbolELF *>(S);312 313 // When encoding an assignment to set symbol A to symbol B, also copy314 // the st_other bits encoding the local entry point offset.315 if (copyLocalEntry(Symbol, Value))316 UpdateOther.insert(Symbol);317 else318 UpdateOther.erase(Symbol);319 }320 321 void finish() override {322 for (auto *Sym : UpdateOther)323 if (Sym->isVariable())324 copyLocalEntry(Sym, Sym->getVariableValue());325 326 // Clear the set of symbols that needs to be updated so the streamer can327 // be reused without issues.328 UpdateOther.clear();329 }330 331private:332 SmallPtrSet<MCSymbolELF *, 32> UpdateOther;333 334 bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) {335 auto *Ref = dyn_cast<const MCSymbolRefExpr>(S);336 if (!Ref)337 return false;338 auto &RhsSym = static_cast<const MCSymbolELF &>(Ref->getSymbol());339 unsigned Other = D->getOther();340 Other &= ~ELF::STO_PPC64_LOCAL_MASK;341 Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK;342 D->setOther(Other);343 return true;344 }345 346 unsigned encodePPC64LocalEntryOffset(const MCExpr *LocalOffset) {347 MCAssembler &MCA = getStreamer().getAssembler();348 int64_t Offset;349 if (!LocalOffset->evaluateAsAbsolute(Offset, MCA))350 MCA.getContext().reportError(LocalOffset->getLoc(),351 ".localentry expression must be absolute");352 353 switch (Offset) {354 default:355 MCA.getContext().reportError(356 LocalOffset->getLoc(), ".localentry expression must be a power of 2");357 return 0;358 case 0:359 return 0;360 case 1:361 return 1 << ELF::STO_PPC64_LOCAL_BIT;362 case 4:363 case 8:364 case 16:365 case 32:366 case 64:367 return Log2_32(Offset) << ELF::STO_PPC64_LOCAL_BIT;368 }369 }370};371 372class PPCTargetMachOStreamer : public PPCTargetStreamer {373public:374 PPCTargetMachOStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}375 376 void emitTCEntry(const MCSymbol &S, PPCMCExpr::Specifier Kind) override {377 llvm_unreachable("Unknown pseudo-op: .tc");378 }379 380 void emitMachine(StringRef CPU) override {381 // FIXME: We should update the CPUType, CPUSubType in the Object file if382 // the new values are different from the defaults.383 }384 385 void emitAbiVersion(int AbiVersion) override {386 llvm_unreachable("Unknown pseudo-op: .abiversion");387 }388 389 void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {390 llvm_unreachable("Unknown pseudo-op: .localentry");391 }392};393 394class PPCTargetXCOFFStreamer : public PPCTargetStreamer {395public:396 PPCTargetXCOFFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}397 398 void emitTCEntry(const MCSymbol &S, PPCMCExpr::Specifier Kind) override {399 const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();400 const unsigned PointerSize = MAI->getCodePointerSize();401 Streamer.emitValueToAlignment(Align(PointerSize));402 Streamer.emitValue(MCSymbolRefExpr::create(&S, Kind, Streamer.getContext()),403 PointerSize);404 }405 406 void emitMachine(StringRef CPU) override {407 static_cast<XCOFFObjectWriter &>(Streamer.getAssemblerPtr()->getWriter())408 .setCPU(CPU);409 }410 411 void emitAbiVersion(int AbiVersion) override {412 llvm_unreachable("ABI-version pseudo-ops are invalid for XCOFF.");413 }414 415 void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {416 llvm_unreachable("Local-entry pseudo-ops are invalid for XCOFF.");417 }418};419 420} // end anonymous namespace421 422static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S,423 formatted_raw_ostream &OS,424 MCInstPrinter *InstPrint) {425 return new PPCTargetAsmStreamer(S, OS);426}427 428static MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) {429 return new PPCTargetStreamer(S);430}431 432static MCTargetStreamer *433createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {434 const Triple &TT = STI.getTargetTriple();435 if (TT.isOSBinFormatELF())436 return new PPCTargetELFStreamer(S);437 if (TT.isOSBinFormatXCOFF())438 return new PPCTargetXCOFFStreamer(S);439 return new PPCTargetMachOStreamer(S);440}441 442static MCInstPrinter *createPPCMCInstPrinter(const Triple &T,443 unsigned SyntaxVariant,444 const MCAsmInfo &MAI,445 const MCInstrInfo &MII,446 const MCRegisterInfo &MRI) {447 return new PPCInstPrinter(MAI, MII, MRI, T);448}449 450namespace {451 452class PPCMCInstrAnalysis : public MCInstrAnalysis {453public:454 explicit PPCMCInstrAnalysis(const MCInstrInfo *Info)455 : MCInstrAnalysis(Info) {}456 457 bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,458 uint64_t &Target) const override {459 unsigned NumOps = Inst.getNumOperands();460 if (NumOps == 0 ||461 Info->get(Inst.getOpcode()).operands()[NumOps - 1].OperandType !=462 MCOI::OPERAND_PCREL)463 return false;464 Target = Addr + Inst.getOperand(NumOps - 1).getImm() * Size;465 return true;466 }467};468 469} // end anonymous namespace470 471static MCInstrAnalysis *createPPCMCInstrAnalysis(const MCInstrInfo *Info) {472 return new PPCMCInstrAnalysis(Info);473}474 475extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void476LLVMInitializePowerPCTargetMC() {477 for (Target *T : {&getThePPC32Target(), &getThePPC32LETarget(),478 &getThePPC64Target(), &getThePPC64LETarget()}) {479 // Register the MC asm info.480 RegisterMCAsmInfoFn C(*T, createPPCMCAsmInfo);481 482 // Register the MC instruction info.483 TargetRegistry::RegisterMCInstrInfo(*T, createPPCMCInstrInfo);484 485 // Register the MC register info.486 TargetRegistry::RegisterMCRegInfo(*T, createPPCMCRegisterInfo);487 488 // Register the MC subtarget info.489 TargetRegistry::RegisterMCSubtargetInfo(*T, createPPCMCSubtargetInfo);490 491 // Register the MC instruction analyzer.492 TargetRegistry::RegisterMCInstrAnalysis(*T, createPPCMCInstrAnalysis);493 494 // Register the MC Code Emitter495 TargetRegistry::RegisterMCCodeEmitter(*T, createPPCMCCodeEmitter);496 497 // Register the asm backend.498 TargetRegistry::RegisterMCAsmBackend(*T, createPPCAsmBackend);499 500 // Register the elf streamer.501 TargetRegistry::RegisterELFStreamer(*T, createPPCELFStreamer);502 503 // Register the XCOFF streamer.504 TargetRegistry::RegisterXCOFFStreamer(*T, createPPCXCOFFStreamer);505 506 // Register the object target streamer.507 TargetRegistry::RegisterObjectTargetStreamer(*T,508 createObjectTargetStreamer);509 510 // Register the asm target streamer.511 TargetRegistry::RegisterAsmTargetStreamer(*T, createAsmTargetStreamer);512 513 // Register the null target streamer.514 TargetRegistry::RegisterNullTargetStreamer(*T, createNullTargetStreamer);515 516 // Register the MCInstPrinter.517 TargetRegistry::RegisterMCInstPrinter(*T, createPPCMCInstPrinter);518 }519}520