1fe6060f1SDimitry Andric //===-------- PPCXCOFFStreamer.cpp - XCOFF Object Output ------------------===//
2fe6060f1SDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric //
9fe6060f1SDimitry Andric // This is a custom MCXCOFFStreamer for PowerPC.
10fe6060f1SDimitry Andric //
11fe6060f1SDimitry Andric // The purpose of the custom XCOFF streamer is to allow us to intercept
12fe6060f1SDimitry Andric // instructions as they are being emitted and align all 8 byte instructions
13fe6060f1SDimitry Andric // to a 64 byte boundary if required (by adding a 4 byte nop). This is important
14fe6060f1SDimitry Andric // because 8 byte instructions are not allowed to cross 64 byte boundaries
15fe6060f1SDimitry Andric // and by aligning anything that is within 4 bytes of the boundary we can
16fe6060f1SDimitry Andric // guarantee that the 8 byte instructions do not cross that boundary.
17fe6060f1SDimitry Andric //
18fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
19fe6060f1SDimitry Andric
20fe6060f1SDimitry Andric #include "PPCXCOFFStreamer.h"
21fe6060f1SDimitry Andric #include "PPCMCCodeEmitter.h"
22fe6060f1SDimitry Andric #include "llvm/BinaryFormat/XCOFF.h"
23fe6060f1SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
2481ad6265SDimitry Andric #include "llvm/MC/MCAssembler.h"
25fe6060f1SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
26fe6060f1SDimitry Andric #include "llvm/MC/MCDirectives.h"
27fe6060f1SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
28fe6060f1SDimitry Andric #include "llvm/MC/MCSectionXCOFF.h"
29fe6060f1SDimitry Andric #include "llvm/MC/MCSymbolXCOFF.h"
30349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
31fe6060f1SDimitry Andric
32fe6060f1SDimitry Andric using namespace llvm;
33fe6060f1SDimitry Andric
PPCXCOFFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)34fe6060f1SDimitry Andric PPCXCOFFStreamer::PPCXCOFFStreamer(MCContext &Context,
35fe6060f1SDimitry Andric std::unique_ptr<MCAsmBackend> MAB,
36fe6060f1SDimitry Andric std::unique_ptr<MCObjectWriter> OW,
37fe6060f1SDimitry Andric std::unique_ptr<MCCodeEmitter> Emitter)
38fe6060f1SDimitry Andric : MCXCOFFStreamer(Context, std::move(MAB), std::move(OW),
39fe6060f1SDimitry Andric std::move(Emitter)) {}
40fe6060f1SDimitry Andric
emitPrefixedInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)41fe6060f1SDimitry Andric void PPCXCOFFStreamer::emitPrefixedInstruction(const MCInst &Inst,
42fe6060f1SDimitry Andric const MCSubtargetInfo &STI) {
43fe6060f1SDimitry Andric // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is
44fe6060f1SDimitry Andric // before the boundary and the remaining 4-bytes are after the boundary). In
45fe6060f1SDimitry Andric // order to achieve this, a nop is added prior to any such boundary-crossing
46fe6060f1SDimitry Andric // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4
47fe6060f1SDimitry Andric // bytes when trying to do that. If alignment requires adding more than 4
48fe6060f1SDimitry Andric // bytes then the instruction won't be aligned.
49*bdd1243dSDimitry Andric emitCodeAlignment(Align(64), &STI, 4);
50fe6060f1SDimitry Andric
51fe6060f1SDimitry Andric // Emit the instruction.
52fe6060f1SDimitry Andric // Since the previous emit created a new fragment then adding this instruction
53fe6060f1SDimitry Andric // also forces the addition of a new fragment. Inst is now the first
54fe6060f1SDimitry Andric // instruction in that new fragment.
55fe6060f1SDimitry Andric MCXCOFFStreamer::emitInstruction(Inst, STI);
56fe6060f1SDimitry Andric }
57fe6060f1SDimitry Andric
emitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)58fe6060f1SDimitry Andric void PPCXCOFFStreamer::emitInstruction(const MCInst &Inst,
59fe6060f1SDimitry Andric const MCSubtargetInfo &STI) {
60fe6060f1SDimitry Andric PPCMCCodeEmitter *Emitter =
61fe6060f1SDimitry Andric static_cast<PPCMCCodeEmitter *>(getAssembler().getEmitterPtr());
62fe6060f1SDimitry Andric
63fe6060f1SDimitry Andric // Special handling is only for prefixed instructions.
64fe6060f1SDimitry Andric if (!Emitter->isPrefixedInstruction(Inst)) {
65fe6060f1SDimitry Andric MCXCOFFStreamer::emitInstruction(Inst, STI);
66fe6060f1SDimitry Andric return;
67fe6060f1SDimitry Andric }
68fe6060f1SDimitry Andric emitPrefixedInstruction(Inst, STI);
69fe6060f1SDimitry Andric }
70fe6060f1SDimitry Andric
71fe6060f1SDimitry Andric MCXCOFFStreamer *
createPPCXCOFFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)72fe6060f1SDimitry Andric llvm::createPPCXCOFFStreamer(MCContext &Context,
73fe6060f1SDimitry Andric std::unique_ptr<MCAsmBackend> MAB,
74fe6060f1SDimitry Andric std::unique_ptr<MCObjectWriter> OW,
75fe6060f1SDimitry Andric std::unique_ptr<MCCodeEmitter> Emitter) {
76fe6060f1SDimitry Andric return new PPCXCOFFStreamer(Context, std::move(MAB), std::move(OW),
77fe6060f1SDimitry Andric std::move(Emitter));
78fe6060f1SDimitry Andric }
79