1*9880d681SAndroid Build Coastguard Worker //===-- PPCAsmBackend.cpp - PPC Assembler Backend -------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/PPCMCTargetDesc.h"
11*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/PPCFixupKinds.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmBackend.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAssembler.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCELFObjectWriter.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCFixupKindInfo.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCMachObjectWriter.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectWriter.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSectionMachO.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbolELF.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCValue.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ELF.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MachO.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
25*9880d681SAndroid Build Coastguard Worker using namespace llvm;
26*9880d681SAndroid Build Coastguard Worker
adjustFixupValue(unsigned Kind,uint64_t Value)27*9880d681SAndroid Build Coastguard Worker static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
28*9880d681SAndroid Build Coastguard Worker switch (Kind) {
29*9880d681SAndroid Build Coastguard Worker default:
30*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown fixup kind!");
31*9880d681SAndroid Build Coastguard Worker case FK_Data_1:
32*9880d681SAndroid Build Coastguard Worker case FK_Data_2:
33*9880d681SAndroid Build Coastguard Worker case FK_Data_4:
34*9880d681SAndroid Build Coastguard Worker case FK_Data_8:
35*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_nofixup:
36*9880d681SAndroid Build Coastguard Worker return Value;
37*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_brcond14:
38*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_brcond14abs:
39*9880d681SAndroid Build Coastguard Worker return Value & 0xfffc;
40*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_br24:
41*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_br24abs:
42*9880d681SAndroid Build Coastguard Worker return Value & 0x3fffffc;
43*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_half16:
44*9880d681SAndroid Build Coastguard Worker return Value & 0xffff;
45*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_half16ds:
46*9880d681SAndroid Build Coastguard Worker return Value & 0xfffc;
47*9880d681SAndroid Build Coastguard Worker }
48*9880d681SAndroid Build Coastguard Worker }
49*9880d681SAndroid Build Coastguard Worker
getFixupKindNumBytes(unsigned Kind)50*9880d681SAndroid Build Coastguard Worker static unsigned getFixupKindNumBytes(unsigned Kind) {
51*9880d681SAndroid Build Coastguard Worker switch (Kind) {
52*9880d681SAndroid Build Coastguard Worker default:
53*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown fixup kind!");
54*9880d681SAndroid Build Coastguard Worker case FK_Data_1:
55*9880d681SAndroid Build Coastguard Worker return 1;
56*9880d681SAndroid Build Coastguard Worker case FK_Data_2:
57*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_half16:
58*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_half16ds:
59*9880d681SAndroid Build Coastguard Worker return 2;
60*9880d681SAndroid Build Coastguard Worker case FK_Data_4:
61*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_brcond14:
62*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_brcond14abs:
63*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_br24:
64*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_br24abs:
65*9880d681SAndroid Build Coastguard Worker return 4;
66*9880d681SAndroid Build Coastguard Worker case FK_Data_8:
67*9880d681SAndroid Build Coastguard Worker return 8;
68*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_nofixup:
69*9880d681SAndroid Build Coastguard Worker return 0;
70*9880d681SAndroid Build Coastguard Worker }
71*9880d681SAndroid Build Coastguard Worker }
72*9880d681SAndroid Build Coastguard Worker
73*9880d681SAndroid Build Coastguard Worker namespace {
74*9880d681SAndroid Build Coastguard Worker
75*9880d681SAndroid Build Coastguard Worker class PPCAsmBackend : public MCAsmBackend {
76*9880d681SAndroid Build Coastguard Worker const Target &TheTarget;
77*9880d681SAndroid Build Coastguard Worker bool IsLittleEndian;
78*9880d681SAndroid Build Coastguard Worker public:
PPCAsmBackend(const Target & T,bool isLittle)79*9880d681SAndroid Build Coastguard Worker PPCAsmBackend(const Target &T, bool isLittle) : MCAsmBackend(), TheTarget(T),
80*9880d681SAndroid Build Coastguard Worker IsLittleEndian(isLittle) {}
81*9880d681SAndroid Build Coastguard Worker
getNumFixupKinds() const82*9880d681SAndroid Build Coastguard Worker unsigned getNumFixupKinds() const override {
83*9880d681SAndroid Build Coastguard Worker return PPC::NumTargetFixupKinds;
84*9880d681SAndroid Build Coastguard Worker }
85*9880d681SAndroid Build Coastguard Worker
getFixupKindInfo(MCFixupKind Kind) const86*9880d681SAndroid Build Coastguard Worker const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
87*9880d681SAndroid Build Coastguard Worker const static MCFixupKindInfo InfosBE[PPC::NumTargetFixupKinds] = {
88*9880d681SAndroid Build Coastguard Worker // name offset bits flags
89*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_br24", 6, 24, MCFixupKindInfo::FKF_IsPCRel },
90*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_brcond14", 16, 14, MCFixupKindInfo::FKF_IsPCRel },
91*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_br24abs", 6, 24, 0 },
92*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_brcond14abs", 16, 14, 0 },
93*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_half16", 0, 16, 0 },
94*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_half16ds", 0, 14, 0 },
95*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_nofixup", 0, 0, 0 }
96*9880d681SAndroid Build Coastguard Worker };
97*9880d681SAndroid Build Coastguard Worker const static MCFixupKindInfo InfosLE[PPC::NumTargetFixupKinds] = {
98*9880d681SAndroid Build Coastguard Worker // name offset bits flags
99*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_br24", 2, 24, MCFixupKindInfo::FKF_IsPCRel },
100*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_brcond14", 2, 14, MCFixupKindInfo::FKF_IsPCRel },
101*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_br24abs", 2, 24, 0 },
102*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_brcond14abs", 2, 14, 0 },
103*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_half16", 0, 16, 0 },
104*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_half16ds", 2, 14, 0 },
105*9880d681SAndroid Build Coastguard Worker { "fixup_ppc_nofixup", 0, 0, 0 }
106*9880d681SAndroid Build Coastguard Worker };
107*9880d681SAndroid Build Coastguard Worker
108*9880d681SAndroid Build Coastguard Worker if (Kind < FirstTargetFixupKind)
109*9880d681SAndroid Build Coastguard Worker return MCAsmBackend::getFixupKindInfo(Kind);
110*9880d681SAndroid Build Coastguard Worker
111*9880d681SAndroid Build Coastguard Worker assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
112*9880d681SAndroid Build Coastguard Worker "Invalid kind!");
113*9880d681SAndroid Build Coastguard Worker return (IsLittleEndian? InfosLE : InfosBE)[Kind - FirstTargetFixupKind];
114*9880d681SAndroid Build Coastguard Worker }
115*9880d681SAndroid Build Coastguard Worker
applyFixup(const MCFixup & Fixup,char * Data,unsigned DataSize,uint64_t Value,bool IsPCRel) const116*9880d681SAndroid Build Coastguard Worker void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
117*9880d681SAndroid Build Coastguard Worker uint64_t Value, bool IsPCRel) const override {
118*9880d681SAndroid Build Coastguard Worker Value = adjustFixupValue(Fixup.getKind(), Value);
119*9880d681SAndroid Build Coastguard Worker if (!Value) return; // Doesn't change encoding.
120*9880d681SAndroid Build Coastguard Worker
121*9880d681SAndroid Build Coastguard Worker unsigned Offset = Fixup.getOffset();
122*9880d681SAndroid Build Coastguard Worker unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
123*9880d681SAndroid Build Coastguard Worker
124*9880d681SAndroid Build Coastguard Worker // For each byte of the fragment that the fixup touches, mask in the bits
125*9880d681SAndroid Build Coastguard Worker // from the fixup value. The Value has been "split up" into the appropriate
126*9880d681SAndroid Build Coastguard Worker // bitfields above.
127*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i != NumBytes; ++i) {
128*9880d681SAndroid Build Coastguard Worker unsigned Idx = IsLittleEndian ? i : (NumBytes - 1 - i);
129*9880d681SAndroid Build Coastguard Worker Data[Offset + i] |= uint8_t((Value >> (Idx * 8)) & 0xff);
130*9880d681SAndroid Build Coastguard Worker }
131*9880d681SAndroid Build Coastguard Worker }
132*9880d681SAndroid Build Coastguard Worker
processFixupValue(const MCAssembler & Asm,const MCAsmLayout & Layout,const MCFixup & Fixup,const MCFragment * DF,const MCValue & Target,uint64_t & Value,bool & IsResolved)133*9880d681SAndroid Build Coastguard Worker void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout,
134*9880d681SAndroid Build Coastguard Worker const MCFixup &Fixup, const MCFragment *DF,
135*9880d681SAndroid Build Coastguard Worker const MCValue &Target, uint64_t &Value,
136*9880d681SAndroid Build Coastguard Worker bool &IsResolved) override {
137*9880d681SAndroid Build Coastguard Worker switch ((PPC::Fixups)Fixup.getKind()) {
138*9880d681SAndroid Build Coastguard Worker default: break;
139*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_br24:
140*9880d681SAndroid Build Coastguard Worker case PPC::fixup_ppc_br24abs:
141*9880d681SAndroid Build Coastguard Worker // If the target symbol has a local entry point we must not attempt
142*9880d681SAndroid Build Coastguard Worker // to resolve the fixup directly. Emit a relocation and leave
143*9880d681SAndroid Build Coastguard Worker // resolution of the final target address to the linker.
144*9880d681SAndroid Build Coastguard Worker if (const MCSymbolRefExpr *A = Target.getSymA()) {
145*9880d681SAndroid Build Coastguard Worker if (const auto *S = dyn_cast<MCSymbolELF>(&A->getSymbol())) {
146*9880d681SAndroid Build Coastguard Worker // The "other" values are stored in the last 6 bits of the second
147*9880d681SAndroid Build Coastguard Worker // byte. The traditional defines for STO values assume the full byte
148*9880d681SAndroid Build Coastguard Worker // and thus the shift to pack it.
149*9880d681SAndroid Build Coastguard Worker unsigned Other = S->getOther() << 2;
150*9880d681SAndroid Build Coastguard Worker if ((Other & ELF::STO_PPC64_LOCAL_MASK) != 0)
151*9880d681SAndroid Build Coastguard Worker IsResolved = false;
152*9880d681SAndroid Build Coastguard Worker }
153*9880d681SAndroid Build Coastguard Worker }
154*9880d681SAndroid Build Coastguard Worker break;
155*9880d681SAndroid Build Coastguard Worker }
156*9880d681SAndroid Build Coastguard Worker }
157*9880d681SAndroid Build Coastguard Worker
mayNeedRelaxation(const MCInst & Inst) const158*9880d681SAndroid Build Coastguard Worker bool mayNeedRelaxation(const MCInst &Inst) const override {
159*9880d681SAndroid Build Coastguard Worker // FIXME.
160*9880d681SAndroid Build Coastguard Worker return false;
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker
fixupNeedsRelaxation(const MCFixup & Fixup,uint64_t Value,const MCRelaxableFragment * DF,const MCAsmLayout & Layout) const163*9880d681SAndroid Build Coastguard Worker bool fixupNeedsRelaxation(const MCFixup &Fixup,
164*9880d681SAndroid Build Coastguard Worker uint64_t Value,
165*9880d681SAndroid Build Coastguard Worker const MCRelaxableFragment *DF,
166*9880d681SAndroid Build Coastguard Worker const MCAsmLayout &Layout) const override {
167*9880d681SAndroid Build Coastguard Worker // FIXME.
168*9880d681SAndroid Build Coastguard Worker llvm_unreachable("relaxInstruction() unimplemented");
169*9880d681SAndroid Build Coastguard Worker }
170*9880d681SAndroid Build Coastguard Worker
relaxInstruction(const MCInst & Inst,const MCSubtargetInfo & STI,MCInst & Res) const171*9880d681SAndroid Build Coastguard Worker void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
172*9880d681SAndroid Build Coastguard Worker MCInst &Res) const override {
173*9880d681SAndroid Build Coastguard Worker // FIXME.
174*9880d681SAndroid Build Coastguard Worker llvm_unreachable("relaxInstruction() unimplemented");
175*9880d681SAndroid Build Coastguard Worker }
176*9880d681SAndroid Build Coastguard Worker
writeNopData(uint64_t Count,MCObjectWriter * OW) const177*9880d681SAndroid Build Coastguard Worker bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override {
178*9880d681SAndroid Build Coastguard Worker uint64_t NumNops = Count / 4;
179*9880d681SAndroid Build Coastguard Worker for (uint64_t i = 0; i != NumNops; ++i)
180*9880d681SAndroid Build Coastguard Worker OW->write32(0x60000000);
181*9880d681SAndroid Build Coastguard Worker
182*9880d681SAndroid Build Coastguard Worker OW->WriteZeros(Count % 4);
183*9880d681SAndroid Build Coastguard Worker
184*9880d681SAndroid Build Coastguard Worker return true;
185*9880d681SAndroid Build Coastguard Worker }
186*9880d681SAndroid Build Coastguard Worker
getPointerSize() const187*9880d681SAndroid Build Coastguard Worker unsigned getPointerSize() const {
188*9880d681SAndroid Build Coastguard Worker StringRef Name = TheTarget.getName();
189*9880d681SAndroid Build Coastguard Worker if (Name == "ppc64" || Name == "ppc64le") return 8;
190*9880d681SAndroid Build Coastguard Worker assert(Name == "ppc32" && "Unknown target name!");
191*9880d681SAndroid Build Coastguard Worker return 4;
192*9880d681SAndroid Build Coastguard Worker }
193*9880d681SAndroid Build Coastguard Worker
isLittleEndian() const194*9880d681SAndroid Build Coastguard Worker bool isLittleEndian() const {
195*9880d681SAndroid Build Coastguard Worker return IsLittleEndian;
196*9880d681SAndroid Build Coastguard Worker }
197*9880d681SAndroid Build Coastguard Worker };
198*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
199*9880d681SAndroid Build Coastguard Worker
200*9880d681SAndroid Build Coastguard Worker
201*9880d681SAndroid Build Coastguard Worker // FIXME: This should be in a separate file.
202*9880d681SAndroid Build Coastguard Worker namespace {
203*9880d681SAndroid Build Coastguard Worker class DarwinPPCAsmBackend : public PPCAsmBackend {
204*9880d681SAndroid Build Coastguard Worker public:
DarwinPPCAsmBackend(const Target & T)205*9880d681SAndroid Build Coastguard Worker DarwinPPCAsmBackend(const Target &T) : PPCAsmBackend(T, false) { }
206*9880d681SAndroid Build Coastguard Worker
createObjectWriter(raw_pwrite_stream & OS) const207*9880d681SAndroid Build Coastguard Worker MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
208*9880d681SAndroid Build Coastguard Worker bool is64 = getPointerSize() == 8;
209*9880d681SAndroid Build Coastguard Worker return createPPCMachObjectWriter(
210*9880d681SAndroid Build Coastguard Worker OS,
211*9880d681SAndroid Build Coastguard Worker /*Is64Bit=*/is64,
212*9880d681SAndroid Build Coastguard Worker (is64 ? MachO::CPU_TYPE_POWERPC64 : MachO::CPU_TYPE_POWERPC),
213*9880d681SAndroid Build Coastguard Worker MachO::CPU_SUBTYPE_POWERPC_ALL);
214*9880d681SAndroid Build Coastguard Worker }
215*9880d681SAndroid Build Coastguard Worker };
216*9880d681SAndroid Build Coastguard Worker
217*9880d681SAndroid Build Coastguard Worker class ELFPPCAsmBackend : public PPCAsmBackend {
218*9880d681SAndroid Build Coastguard Worker uint8_t OSABI;
219*9880d681SAndroid Build Coastguard Worker public:
ELFPPCAsmBackend(const Target & T,bool IsLittleEndian,uint8_t OSABI)220*9880d681SAndroid Build Coastguard Worker ELFPPCAsmBackend(const Target &T, bool IsLittleEndian, uint8_t OSABI) :
221*9880d681SAndroid Build Coastguard Worker PPCAsmBackend(T, IsLittleEndian), OSABI(OSABI) { }
222*9880d681SAndroid Build Coastguard Worker
createObjectWriter(raw_pwrite_stream & OS) const223*9880d681SAndroid Build Coastguard Worker MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
224*9880d681SAndroid Build Coastguard Worker bool is64 = getPointerSize() == 8;
225*9880d681SAndroid Build Coastguard Worker return createPPCELFObjectWriter(OS, is64, isLittleEndian(), OSABI);
226*9880d681SAndroid Build Coastguard Worker }
227*9880d681SAndroid Build Coastguard Worker };
228*9880d681SAndroid Build Coastguard Worker
229*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
230*9880d681SAndroid Build Coastguard Worker
createPPCAsmBackend(const Target & T,const MCRegisterInfo & MRI,const Triple & TT,StringRef CPU)231*9880d681SAndroid Build Coastguard Worker MCAsmBackend *llvm::createPPCAsmBackend(const Target &T,
232*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo &MRI,
233*9880d681SAndroid Build Coastguard Worker const Triple &TT, StringRef CPU) {
234*9880d681SAndroid Build Coastguard Worker if (TT.isOSDarwin())
235*9880d681SAndroid Build Coastguard Worker return new DarwinPPCAsmBackend(T);
236*9880d681SAndroid Build Coastguard Worker
237*9880d681SAndroid Build Coastguard Worker uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
238*9880d681SAndroid Build Coastguard Worker bool IsLittleEndian = TT.getArch() == Triple::ppc64le;
239*9880d681SAndroid Build Coastguard Worker return new ELFPPCAsmBackend(T, IsLittleEndian, OSABI);
240*9880d681SAndroid Build Coastguard Worker }
241