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" 24*81ad6265SDimitry 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 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 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. 49349cc55cSDimitry Andric emitCodeAlignment(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 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 * 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