xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- PPCMCTargetDesc.cpp - PowerPC Target Descriptions -----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file provides PowerPC specific target descriptions.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h"
140b57cec5SDimitry Andric #include "MCTargetDesc/PPCInstPrinter.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/PPCMCAsmInfo.h"
165ffd83dbSDimitry Andric #include "PPCELFStreamer.h"
170b57cec5SDimitry Andric #include "PPCTargetStreamer.h"
18fe6060f1SDimitry Andric #include "PPCXCOFFStreamer.h"
190b57cec5SDimitry Andric #include "TargetInfo/PowerPCTargetInfo.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
210b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
220b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
235ffd83dbSDimitry Andric #include "llvm/MC/MCAsmBackend.h"
24e8d8bef9SDimitry Andric #include "llvm/MC/MCAssembler.h"
255ffd83dbSDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCDwarf.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCELFStreamer.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
300eae32dcSDimitry Andric #include "llvm/MC/MCInstrAnalysis.h"
310b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
325ffd83dbSDimitry Andric #include "llvm/MC/MCObjectWriter.h"
330b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
34e8d8bef9SDimitry Andric #include "llvm/MC/MCSectionXCOFF.h"
350b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
360b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
370b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
380b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
39480093f4SDimitry Andric #include "llvm/MC/MCSymbolXCOFF.h"
40349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
410b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
420b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h"
430b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
440b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h"
450b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
4606c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric using namespace llvm;
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric #define GET_INSTRINFO_MC_DESC
51753f127fSDimitry Andric #define ENABLE_INSTR_PREDICATE_VERIFIER
520b57cec5SDimitry Andric #include "PPCGenInstrInfo.inc"
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric #define GET_SUBTARGETINFO_MC_DESC
550b57cec5SDimitry Andric #include "PPCGenSubtargetInfo.inc"
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric #define GET_REGINFO_MC_DESC
580b57cec5SDimitry Andric #include "PPCGenRegisterInfo.inc"
590b57cec5SDimitry Andric 
605f757f3fSDimitry Andric /// stripRegisterPrefix - This method strips the character prefix from a
615f757f3fSDimitry Andric /// register name so that only the number is left.  Used by for linux asm.
625f757f3fSDimitry Andric const char *PPC::stripRegisterPrefix(const char *RegName) {
635f757f3fSDimitry Andric   switch (RegName[0]) {
645f757f3fSDimitry Andric     case 'a':
655f757f3fSDimitry Andric       if (RegName[1] == 'c' && RegName[2] == 'c')
665f757f3fSDimitry Andric         return RegName + 3;
675f757f3fSDimitry Andric       break;
685f757f3fSDimitry Andric     case 'f':
695f757f3fSDimitry Andric       if (RegName[1] == 'p')
705f757f3fSDimitry Andric         return RegName + 2;
715f757f3fSDimitry Andric       [[fallthrough]];
725f757f3fSDimitry Andric     case 'r':
735f757f3fSDimitry Andric     case 'v':
745f757f3fSDimitry Andric       if (RegName[1] == 's') {
755f757f3fSDimitry Andric         if (RegName[2] == 'p')
765f757f3fSDimitry Andric           return RegName + 3;
775f757f3fSDimitry Andric         return RegName + 2;
785f757f3fSDimitry Andric       }
795f757f3fSDimitry Andric       return RegName + 1;
805f757f3fSDimitry Andric     case 'c':
815f757f3fSDimitry Andric       if (RegName[1] == 'r')
825f757f3fSDimitry Andric         return RegName + 2;
835f757f3fSDimitry Andric       break;
845f757f3fSDimitry Andric     case 'w':
855f757f3fSDimitry Andric       // For wacc and wacc_hi
865f757f3fSDimitry Andric       if (RegName[1] == 'a' && RegName[2] == 'c' && RegName[3] == 'c') {
875f757f3fSDimitry Andric         if (RegName[4] == '_')
885f757f3fSDimitry Andric           return RegName + 7;
895f757f3fSDimitry Andric         else
905f757f3fSDimitry Andric           return RegName + 4;
915f757f3fSDimitry Andric       }
925f757f3fSDimitry Andric       break;
935f757f3fSDimitry Andric     case 'd':
945f757f3fSDimitry Andric       // For dmr, dmrp, dmrrow, dmrrowp
955f757f3fSDimitry Andric       if (RegName[1] == 'm' && RegName[2] == 'r') {
965f757f3fSDimitry Andric         if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w' &&
975f757f3fSDimitry Andric             RegName[6] == 'p')
985f757f3fSDimitry Andric           return RegName + 7;
995f757f3fSDimitry Andric         else if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w')
1005f757f3fSDimitry Andric           return RegName + 6;
1015f757f3fSDimitry Andric         else if (RegName[3] == 'p')
1025f757f3fSDimitry Andric           return RegName + 4;
1035f757f3fSDimitry Andric         else
1045f757f3fSDimitry Andric           return RegName + 3;
1055f757f3fSDimitry Andric       }
1065f757f3fSDimitry Andric       break;
1075f757f3fSDimitry Andric   }
1085f757f3fSDimitry Andric 
1095f757f3fSDimitry Andric   return RegName;
1105f757f3fSDimitry Andric }
1115f757f3fSDimitry Andric 
1125f757f3fSDimitry Andric /// getRegNumForOperand - some operands use different numbering schemes
1135f757f3fSDimitry Andric /// for the same registers. For example, a VSX instruction may have any of
1145f757f3fSDimitry Andric /// vs0-vs63 allocated whereas an Altivec instruction could only have
1155f757f3fSDimitry Andric /// vs32-vs63 allocated (numbered as v0-v31). This function returns the actual
1165f757f3fSDimitry Andric /// register number needed for the opcode/operand number combination.
1175f757f3fSDimitry Andric /// The operand number argument will be useful when we need to extend this
1185f757f3fSDimitry Andric /// to instructions that use both Altivec and VSX numbering (for different
1195f757f3fSDimitry Andric /// operands).
1205f757f3fSDimitry Andric unsigned PPC::getRegNumForOperand(const MCInstrDesc &Desc, unsigned Reg,
1215f757f3fSDimitry Andric                                   unsigned OpNo) {
1225f757f3fSDimitry Andric   int16_t regClass = Desc.operands()[OpNo].RegClass;
1235f757f3fSDimitry Andric   switch (regClass) {
1245f757f3fSDimitry Andric     // We store F0-F31, VF0-VF31 in MCOperand and it should be F0-F31,
1255f757f3fSDimitry Andric     // VSX32-VSX63 during encoding/disassembling
1265f757f3fSDimitry Andric     case PPC::VSSRCRegClassID:
1275f757f3fSDimitry Andric     case PPC::VSFRCRegClassID:
1285f757f3fSDimitry Andric       if (PPC::isVFRegister(Reg))
1295f757f3fSDimitry Andric 	return PPC::VSX32 + (Reg - PPC::VF0);
1305f757f3fSDimitry Andric       break;
1315f757f3fSDimitry Andric     // We store VSL0-VSL31, V0-V31 in MCOperand and it should be VSL0-VSL31,
1325f757f3fSDimitry Andric     // VSX32-VSX63 during encoding/disassembling
1335f757f3fSDimitry Andric     case PPC::VSRCRegClassID:
1345f757f3fSDimitry Andric       if (PPC::isVRRegister(Reg))
1355f757f3fSDimitry Andric 	return PPC::VSX32 + (Reg - PPC::V0);
1365f757f3fSDimitry Andric       break;
1375f757f3fSDimitry Andric     // Other RegClass doesn't need mapping
1385f757f3fSDimitry Andric     default:
1395f757f3fSDimitry Andric       break;
1405f757f3fSDimitry Andric   }
1415f757f3fSDimitry Andric   return Reg;
1425f757f3fSDimitry Andric }
1435f757f3fSDimitry Andric 
1440b57cec5SDimitry Andric PPCTargetStreamer::PPCTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric // Pin the vtable to this file.
1470b57cec5SDimitry Andric PPCTargetStreamer::~PPCTargetStreamer() = default;
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric static MCInstrInfo *createPPCMCInstrInfo() {
1500b57cec5SDimitry Andric   MCInstrInfo *X = new MCInstrInfo();
1510b57cec5SDimitry Andric   InitPPCMCInstrInfo(X);
1520b57cec5SDimitry Andric   return X;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric static MCRegisterInfo *createPPCMCRegisterInfo(const Triple &TT) {
1560b57cec5SDimitry Andric   bool isPPC64 =
1570b57cec5SDimitry Andric       (TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le);
1580b57cec5SDimitry Andric   unsigned Flavour = isPPC64 ? 0 : 1;
1590b57cec5SDimitry Andric   unsigned RA = isPPC64 ? PPC::LR8 : PPC::LR;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   MCRegisterInfo *X = new MCRegisterInfo();
1620b57cec5SDimitry Andric   InitPPCMCRegisterInfo(X, RA, Flavour, Flavour);
1630b57cec5SDimitry Andric   return X;
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric static MCSubtargetInfo *createPPCMCSubtargetInfo(const Triple &TT,
1670b57cec5SDimitry Andric                                                  StringRef CPU, StringRef FS) {
168e8d8bef9SDimitry Andric   // Set some default feature to MC layer.
169e8d8bef9SDimitry Andric   std::string FullFS = std::string(FS);
170e8d8bef9SDimitry Andric 
171e8d8bef9SDimitry Andric   if (TT.isOSAIX()) {
172e8d8bef9SDimitry Andric     if (!FullFS.empty())
173e8d8bef9SDimitry Andric       FullFS = "+aix," + FullFS;
174e8d8bef9SDimitry Andric     else
175e8d8bef9SDimitry Andric       FullFS = "+aix";
176e8d8bef9SDimitry Andric   }
177e8d8bef9SDimitry Andric 
178e8d8bef9SDimitry Andric   return createPPCMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FullFS);
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric static MCAsmInfo *createPPCMCAsmInfo(const MCRegisterInfo &MRI,
182480093f4SDimitry Andric                                      const Triple &TheTriple,
183480093f4SDimitry Andric                                      const MCTargetOptions &Options) {
1840b57cec5SDimitry Andric   bool isPPC64 = (TheTriple.getArch() == Triple::ppc64 ||
1850b57cec5SDimitry Andric                   TheTriple.getArch() == Triple::ppc64le);
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   MCAsmInfo *MAI;
188480093f4SDimitry Andric   if (TheTriple.isOSBinFormatXCOFF())
1890b57cec5SDimitry Andric     MAI = new PPCXCOFFMCAsmInfo(isPPC64, TheTriple);
1900b57cec5SDimitry Andric   else
1910b57cec5SDimitry Andric     MAI = new PPCELFMCAsmInfo(isPPC64, TheTriple);
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   // Initial state of the frame pointer is R1.
1940b57cec5SDimitry Andric   unsigned Reg = isPPC64 ? PPC::X1 : PPC::R1;
1950b57cec5SDimitry Andric   MCCFIInstruction Inst =
1965ffd83dbSDimitry Andric       MCCFIInstruction::cfiDefCfa(nullptr, MRI.getDwarfRegNum(Reg, true), 0);
1970b57cec5SDimitry Andric   MAI->addInitialFrameState(Inst);
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   return MAI;
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
202fe6060f1SDimitry Andric static MCStreamer *
203fe6060f1SDimitry Andric createPPCELFStreamer(const Triple &T, MCContext &Context,
2045ffd83dbSDimitry Andric                      std::unique_ptr<MCAsmBackend> &&MAB,
2055ffd83dbSDimitry Andric                      std::unique_ptr<MCObjectWriter> &&OW,
206*0fca6ea1SDimitry Andric                      std::unique_ptr<MCCodeEmitter> &&Emitter) {
2075ffd83dbSDimitry Andric   return createPPCELFStreamer(Context, std::move(MAB), std::move(OW),
2085ffd83dbSDimitry Andric                               std::move(Emitter));
2095ffd83dbSDimitry Andric }
2105ffd83dbSDimitry Andric 
211*0fca6ea1SDimitry Andric static MCStreamer *
212*0fca6ea1SDimitry Andric createPPCXCOFFStreamer(const Triple &T, MCContext &Context,
213*0fca6ea1SDimitry Andric                        std::unique_ptr<MCAsmBackend> &&MAB,
214fe6060f1SDimitry Andric                        std::unique_ptr<MCObjectWriter> &&OW,
215*0fca6ea1SDimitry Andric                        std::unique_ptr<MCCodeEmitter> &&Emitter) {
216fe6060f1SDimitry Andric   return createPPCXCOFFStreamer(Context, std::move(MAB), std::move(OW),
217fe6060f1SDimitry Andric                                 std::move(Emitter));
218fe6060f1SDimitry Andric }
219fe6060f1SDimitry Andric 
2200b57cec5SDimitry Andric namespace {
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric class PPCTargetAsmStreamer : public PPCTargetStreamer {
2230b57cec5SDimitry Andric   formatted_raw_ostream &OS;
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric public:
2260b57cec5SDimitry Andric   PPCTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS)
2270b57cec5SDimitry Andric       : PPCTargetStreamer(S), OS(OS) {}
2280b57cec5SDimitry Andric 
229fe6060f1SDimitry Andric   void emitTCEntry(const MCSymbol &S,
230fe6060f1SDimitry Andric                    MCSymbolRefExpr::VariantKind Kind) override {
2315ffd83dbSDimitry Andric     if (const MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(&S)) {
2325ffd83dbSDimitry Andric       MCSymbolXCOFF *TCSym =
233e8d8bef9SDimitry Andric           cast<MCSectionXCOFF>(Streamer.getCurrentSectionOnly())
234e8d8bef9SDimitry Andric               ->getQualNameSymbol();
235*0fca6ea1SDimitry Andric       // On AIX, we have TLS variable offsets (symbol@({gd|ie|le|ld}) depending
236*0fca6ea1SDimitry Andric       // on the TLS access method (or model). For the general-dynamic access
237*0fca6ea1SDimitry Andric       // method, we also have region handle (symbol@m) for each variable. For
238*0fca6ea1SDimitry Andric       // local-dynamic, there is a module handle (_$TLSML[TC]@ml) for all
239*0fca6ea1SDimitry Andric       // variables. Finally for local-exec and initial-exec, we have a thread
240*0fca6ea1SDimitry Andric       // pointer, in r13 for 64-bit mode and returned by .__get_tpointer for
241*0fca6ea1SDimitry Andric       // 32-bit mode.
242fe6060f1SDimitry Andric       if (Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD ||
24306c3fb27SDimitry Andric           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM ||
2445f757f3fSDimitry Andric           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE ||
245*0fca6ea1SDimitry Andric           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE ||
246*0fca6ea1SDimitry Andric           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD ||
247*0fca6ea1SDimitry Andric           Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSML)
248fe6060f1SDimitry Andric         OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@"
249fe6060f1SDimitry Andric            << MCSymbolRefExpr::getVariantKindName(Kind) << '\n';
250fe6060f1SDimitry Andric       else
251e8d8bef9SDimitry Andric         OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << '\n';
252e8d8bef9SDimitry Andric 
2535ffd83dbSDimitry Andric       if (TCSym->hasRename())
2545ffd83dbSDimitry Andric         Streamer.emitXCOFFRenameDirective(TCSym, TCSym->getSymbolTableName());
2555ffd83dbSDimitry Andric       return;
2565ffd83dbSDimitry Andric     }
2575ffd83dbSDimitry Andric 
2585ffd83dbSDimitry Andric     OS << "\t.tc " << S.getName() << "[TC]," << S.getName() << '\n';
2590b57cec5SDimitry Andric   }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   void emitMachine(StringRef CPU) override {
2620b57cec5SDimitry Andric     OS << "\t.machine " << CPU << '\n';
2630b57cec5SDimitry Andric   }
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   void emitAbiVersion(int AbiVersion) override {
2660b57cec5SDimitry Andric     OS << "\t.abiversion " << AbiVersion << '\n';
2670b57cec5SDimitry Andric   }
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {
2700b57cec5SDimitry Andric     const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric     OS << "\t.localentry\t";
2730b57cec5SDimitry Andric     S->print(OS, MAI);
2740b57cec5SDimitry Andric     OS << ", ";
2750b57cec5SDimitry Andric     LocalOffset->print(OS, MAI);
2760b57cec5SDimitry Andric     OS << '\n';
2770b57cec5SDimitry Andric   }
2780b57cec5SDimitry Andric };
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric class PPCTargetELFStreamer : public PPCTargetStreamer {
2810b57cec5SDimitry Andric public:
2820b57cec5SDimitry Andric   PPCTargetELFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   MCELFStreamer &getStreamer() {
2850b57cec5SDimitry Andric     return static_cast<MCELFStreamer &>(Streamer);
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric 
288fe6060f1SDimitry Andric   void emitTCEntry(const MCSymbol &S,
289fe6060f1SDimitry Andric                    MCSymbolRefExpr::VariantKind Kind) override {
2900b57cec5SDimitry Andric     // Creates a R_PPC64_TOC relocation
291bdd1243dSDimitry Andric     Streamer.emitValueToAlignment(Align(8));
2925ffd83dbSDimitry Andric     Streamer.emitSymbolValue(&S, 8);
2930b57cec5SDimitry Andric   }
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   void emitMachine(StringRef CPU) override {
2960b57cec5SDimitry Andric     // FIXME: Is there anything to do in here or does this directive only
2970b57cec5SDimitry Andric     // limit the parser?
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   void emitAbiVersion(int AbiVersion) override {
301*0fca6ea1SDimitry Andric     ELFObjectWriter &W = getStreamer().getWriter();
302*0fca6ea1SDimitry Andric     unsigned Flags = W.getELFHeaderEFlags();
3030b57cec5SDimitry Andric     Flags &= ~ELF::EF_PPC64_ABI;
3040b57cec5SDimitry Andric     Flags |= (AbiVersion & ELF::EF_PPC64_ABI);
305*0fca6ea1SDimitry Andric     W.setELFHeaderEFlags(Flags);
3060b57cec5SDimitry Andric   }
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {
3090b57cec5SDimitry Andric 
3105ffd83dbSDimitry Andric     // encodePPC64LocalEntryOffset will report an error if it cannot
3115ffd83dbSDimitry Andric     // encode LocalOffset.
3125ffd83dbSDimitry Andric     unsigned Encoded = encodePPC64LocalEntryOffset(LocalOffset);
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric     unsigned Other = S->getOther();
3150b57cec5SDimitry Andric     Other &= ~ELF::STO_PPC64_LOCAL_MASK;
3160b57cec5SDimitry Andric     Other |= Encoded;
3170b57cec5SDimitry Andric     S->setOther(Other);
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric     // For GAS compatibility, unless we already saw a .abiversion directive,
3200b57cec5SDimitry Andric     // set e_flags to indicate ELFv2 ABI.
321*0fca6ea1SDimitry Andric     ELFObjectWriter &W = getStreamer().getWriter();
322*0fca6ea1SDimitry Andric     unsigned Flags = W.getELFHeaderEFlags();
3230b57cec5SDimitry Andric     if ((Flags & ELF::EF_PPC64_ABI) == 0)
324*0fca6ea1SDimitry Andric       W.setELFHeaderEFlags(Flags | 2);
3250b57cec5SDimitry Andric   }
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   void emitAssignment(MCSymbol *S, const MCExpr *Value) override {
3280b57cec5SDimitry Andric     auto *Symbol = cast<MCSymbolELF>(S);
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric     // When encoding an assignment to set symbol A to symbol B, also copy
3310b57cec5SDimitry Andric     // the st_other bits encoding the local entry point offset.
3320b57cec5SDimitry Andric     if (copyLocalEntry(Symbol, Value))
3330b57cec5SDimitry Andric       UpdateOther.insert(Symbol);
3340b57cec5SDimitry Andric     else
3350b57cec5SDimitry Andric       UpdateOther.erase(Symbol);
3360b57cec5SDimitry Andric   }
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   void finish() override {
3390b57cec5SDimitry Andric     for (auto *Sym : UpdateOther)
340480093f4SDimitry Andric       if (Sym->isVariable())
3410b57cec5SDimitry Andric         copyLocalEntry(Sym, Sym->getVariableValue());
3425ffd83dbSDimitry Andric 
3435ffd83dbSDimitry Andric     // Clear the set of symbols that needs to be updated so the streamer can
3445ffd83dbSDimitry Andric     // be reused without issues.
3455ffd83dbSDimitry Andric     UpdateOther.clear();
3460b57cec5SDimitry Andric   }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric private:
3490b57cec5SDimitry Andric   SmallPtrSet<MCSymbolELF *, 32> UpdateOther;
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric   bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) {
3520b57cec5SDimitry Andric     auto *Ref = dyn_cast<const MCSymbolRefExpr>(S);
3530b57cec5SDimitry Andric     if (!Ref)
3540b57cec5SDimitry Andric       return false;
3550b57cec5SDimitry Andric     const auto &RhsSym = cast<MCSymbolELF>(Ref->getSymbol());
3560b57cec5SDimitry Andric     unsigned Other = D->getOther();
3570b57cec5SDimitry Andric     Other &= ~ELF::STO_PPC64_LOCAL_MASK;
3580b57cec5SDimitry Andric     Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK;
3590b57cec5SDimitry Andric     D->setOther(Other);
3600b57cec5SDimitry Andric     return true;
3610b57cec5SDimitry Andric   }
3625ffd83dbSDimitry Andric 
3635ffd83dbSDimitry Andric   unsigned encodePPC64LocalEntryOffset(const MCExpr *LocalOffset) {
3645ffd83dbSDimitry Andric     MCAssembler &MCA = getStreamer().getAssembler();
3655ffd83dbSDimitry Andric     int64_t Offset;
3665ffd83dbSDimitry Andric     if (!LocalOffset->evaluateAsAbsolute(Offset, MCA))
36704eeddc0SDimitry Andric       MCA.getContext().reportError(LocalOffset->getLoc(),
36804eeddc0SDimitry Andric                                    ".localentry expression must be absolute");
3695ffd83dbSDimitry Andric 
3705ffd83dbSDimitry Andric     switch (Offset) {
3715ffd83dbSDimitry Andric     default:
37204eeddc0SDimitry Andric       MCA.getContext().reportError(
37304eeddc0SDimitry Andric           LocalOffset->getLoc(), ".localentry expression must be a power of 2");
37404eeddc0SDimitry Andric       return 0;
3755ffd83dbSDimitry Andric     case 0:
3765ffd83dbSDimitry Andric       return 0;
3775ffd83dbSDimitry Andric     case 1:
3785ffd83dbSDimitry Andric       return 1 << ELF::STO_PPC64_LOCAL_BIT;
3795ffd83dbSDimitry Andric     case 4:
3805ffd83dbSDimitry Andric     case 8:
3815ffd83dbSDimitry Andric     case 16:
3825ffd83dbSDimitry Andric     case 32:
3835ffd83dbSDimitry Andric     case 64:
384bdd1243dSDimitry Andric       return Log2_32(Offset) << ELF::STO_PPC64_LOCAL_BIT;
3855ffd83dbSDimitry Andric     }
3865ffd83dbSDimitry Andric   }
3870b57cec5SDimitry Andric };
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric class PPCTargetMachOStreamer : public PPCTargetStreamer {
3900b57cec5SDimitry Andric public:
3910b57cec5SDimitry Andric   PPCTargetMachOStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
3920b57cec5SDimitry Andric 
393fe6060f1SDimitry Andric   void emitTCEntry(const MCSymbol &S,
394fe6060f1SDimitry Andric                    MCSymbolRefExpr::VariantKind Kind) override {
3950b57cec5SDimitry Andric     llvm_unreachable("Unknown pseudo-op: .tc");
3960b57cec5SDimitry Andric   }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   void emitMachine(StringRef CPU) override {
3990b57cec5SDimitry Andric     // FIXME: We should update the CPUType, CPUSubType in the Object file if
4000b57cec5SDimitry Andric     // the new values are different from the defaults.
4010b57cec5SDimitry Andric   }
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   void emitAbiVersion(int AbiVersion) override {
4040b57cec5SDimitry Andric     llvm_unreachable("Unknown pseudo-op: .abiversion");
4050b57cec5SDimitry Andric   }
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {
4080b57cec5SDimitry Andric     llvm_unreachable("Unknown pseudo-op: .localentry");
4090b57cec5SDimitry Andric   }
4100b57cec5SDimitry Andric };
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric class PPCTargetXCOFFStreamer : public PPCTargetStreamer {
4130b57cec5SDimitry Andric public:
4140b57cec5SDimitry Andric   PPCTargetXCOFFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
4150b57cec5SDimitry Andric 
416fe6060f1SDimitry Andric   void emitTCEntry(const MCSymbol &S,
417fe6060f1SDimitry Andric                    MCSymbolRefExpr::VariantKind Kind) override {
418480093f4SDimitry Andric     const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
419480093f4SDimitry Andric     const unsigned PointerSize = MAI->getCodePointerSize();
420bdd1243dSDimitry Andric     Streamer.emitValueToAlignment(Align(PointerSize));
421fe6060f1SDimitry Andric     Streamer.emitValue(MCSymbolRefExpr::create(&S, Kind, Streamer.getContext()),
422fe6060f1SDimitry Andric                        PointerSize);
4230b57cec5SDimitry Andric   }
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   void emitMachine(StringRef CPU) override {
4260b57cec5SDimitry Andric     llvm_unreachable("Machine pseudo-ops are invalid for XCOFF.");
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   void emitAbiVersion(int AbiVersion) override {
4300b57cec5SDimitry Andric     llvm_unreachable("ABI-version pseudo-ops are invalid for XCOFF.");
4310b57cec5SDimitry Andric   }
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric   void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {
4340b57cec5SDimitry Andric     llvm_unreachable("Local-entry pseudo-ops are invalid for XCOFF.");
4350b57cec5SDimitry Andric   }
4360b57cec5SDimitry Andric };
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric } // end anonymous namespace
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S,
4410b57cec5SDimitry Andric                                                  formatted_raw_ostream &OS,
442*0fca6ea1SDimitry Andric                                                  MCInstPrinter *InstPrint) {
4430b57cec5SDimitry Andric   return new PPCTargetAsmStreamer(S, OS);
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric 
446bdd1243dSDimitry Andric static MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) {
447bdd1243dSDimitry Andric   return new PPCTargetStreamer(S);
448bdd1243dSDimitry Andric }
449bdd1243dSDimitry Andric 
4500b57cec5SDimitry Andric static MCTargetStreamer *
4510b57cec5SDimitry Andric createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
4520b57cec5SDimitry Andric   const Triple &TT = STI.getTargetTriple();
4530b57cec5SDimitry Andric   if (TT.isOSBinFormatELF())
4540b57cec5SDimitry Andric     return new PPCTargetELFStreamer(S);
4550b57cec5SDimitry Andric   if (TT.isOSBinFormatXCOFF())
4560b57cec5SDimitry Andric     return new PPCTargetXCOFFStreamer(S);
4570b57cec5SDimitry Andric   return new PPCTargetMachOStreamer(S);
4580b57cec5SDimitry Andric }
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric static MCInstPrinter *createPPCMCInstPrinter(const Triple &T,
4610b57cec5SDimitry Andric                                              unsigned SyntaxVariant,
4620b57cec5SDimitry Andric                                              const MCAsmInfo &MAI,
4630b57cec5SDimitry Andric                                              const MCInstrInfo &MII,
4640b57cec5SDimitry Andric                                              const MCRegisterInfo &MRI) {
4650b57cec5SDimitry Andric   return new PPCInstPrinter(MAI, MII, MRI, T);
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric 
4680eae32dcSDimitry Andric namespace {
4690eae32dcSDimitry Andric 
4700eae32dcSDimitry Andric class PPCMCInstrAnalysis : public MCInstrAnalysis {
4710eae32dcSDimitry Andric public:
4720eae32dcSDimitry Andric   explicit PPCMCInstrAnalysis(const MCInstrInfo *Info)
4730eae32dcSDimitry Andric       : MCInstrAnalysis(Info) {}
4740eae32dcSDimitry Andric 
4750eae32dcSDimitry Andric   bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
4760eae32dcSDimitry Andric                       uint64_t &Target) const override {
4770eae32dcSDimitry Andric     unsigned NumOps = Inst.getNumOperands();
4780eae32dcSDimitry Andric     if (NumOps == 0 ||
479bdd1243dSDimitry Andric         Info->get(Inst.getOpcode()).operands()[NumOps - 1].OperandType !=
4800eae32dcSDimitry Andric             MCOI::OPERAND_PCREL)
4810eae32dcSDimitry Andric       return false;
4820eae32dcSDimitry Andric     Target = Addr + Inst.getOperand(NumOps - 1).getImm() * Size;
4830eae32dcSDimitry Andric     return true;
4840eae32dcSDimitry Andric   }
4850eae32dcSDimitry Andric };
4860eae32dcSDimitry Andric 
4870eae32dcSDimitry Andric } // end anonymous namespace
4880eae32dcSDimitry Andric 
4890eae32dcSDimitry Andric static MCInstrAnalysis *createPPCMCInstrAnalysis(const MCInstrInfo *Info) {
4900eae32dcSDimitry Andric   return new PPCMCInstrAnalysis(Info);
4910eae32dcSDimitry Andric }
4920eae32dcSDimitry Andric 
493480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() {
494e8d8bef9SDimitry Andric   for (Target *T : {&getThePPC32Target(), &getThePPC32LETarget(),
495e8d8bef9SDimitry Andric                     &getThePPC64Target(), &getThePPC64LETarget()}) {
4960b57cec5SDimitry Andric     // Register the MC asm info.
4970b57cec5SDimitry Andric     RegisterMCAsmInfoFn C(*T, createPPCMCAsmInfo);
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric     // Register the MC instruction info.
5000b57cec5SDimitry Andric     TargetRegistry::RegisterMCInstrInfo(*T, createPPCMCInstrInfo);
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric     // Register the MC register info.
5030b57cec5SDimitry Andric     TargetRegistry::RegisterMCRegInfo(*T, createPPCMCRegisterInfo);
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric     // Register the MC subtarget info.
5060b57cec5SDimitry Andric     TargetRegistry::RegisterMCSubtargetInfo(*T, createPPCMCSubtargetInfo);
5070b57cec5SDimitry Andric 
5080eae32dcSDimitry Andric     // Register the MC instruction analyzer.
5090eae32dcSDimitry Andric     TargetRegistry::RegisterMCInstrAnalysis(*T, createPPCMCInstrAnalysis);
5100eae32dcSDimitry Andric 
5110b57cec5SDimitry Andric     // Register the MC Code Emitter
5120b57cec5SDimitry Andric     TargetRegistry::RegisterMCCodeEmitter(*T, createPPCMCCodeEmitter);
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric     // Register the asm backend.
5150b57cec5SDimitry Andric     TargetRegistry::RegisterMCAsmBackend(*T, createPPCAsmBackend);
5160b57cec5SDimitry Andric 
5175ffd83dbSDimitry Andric     // Register the elf streamer.
518fe6060f1SDimitry Andric     TargetRegistry::RegisterELFStreamer(*T, createPPCELFStreamer);
519fe6060f1SDimitry Andric 
520fe6060f1SDimitry Andric     // Register the XCOFF streamer.
521fe6060f1SDimitry Andric     TargetRegistry::RegisterXCOFFStreamer(*T, createPPCXCOFFStreamer);
5225ffd83dbSDimitry Andric 
5230b57cec5SDimitry Andric     // Register the object target streamer.
5240b57cec5SDimitry Andric     TargetRegistry::RegisterObjectTargetStreamer(*T,
5250b57cec5SDimitry Andric                                                  createObjectTargetStreamer);
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric     // Register the asm target streamer.
5280b57cec5SDimitry Andric     TargetRegistry::RegisterAsmTargetStreamer(*T, createAsmTargetStreamer);
5290b57cec5SDimitry Andric 
530bdd1243dSDimitry Andric     // Register the null target streamer.
531bdd1243dSDimitry Andric     TargetRegistry::RegisterNullTargetStreamer(*T, createNullTargetStreamer);
532bdd1243dSDimitry Andric 
5330b57cec5SDimitry Andric     // Register the MCInstPrinter.
5340b57cec5SDimitry Andric     TargetRegistry::RegisterMCInstPrinter(*T, createPPCMCInstPrinter);
5350b57cec5SDimitry Andric   }
5360b57cec5SDimitry Andric }
537