[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / M68k / MCTargetDesc / M68kAsmBackend.cpp
blob8a0f32b58da421d7e5c9334b20f2a957377dca05
1 //===-- M68kAsmBackend.cpp - M68k Assembler Backend ---------*- C++ -*-===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file contains definitions for M68k assembler backend.
11 ///
12 //===----------------------------------------------------------------------===//
14 #include "MCTargetDesc/M68kBaseInfo.h"
15 #include "MCTargetDesc/M68kFixupKinds.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/BinaryFormat/ELF.h"
19 #include "llvm/BinaryFormat/MachO.h"
20 #include "llvm/MC/MCAsmBackend.h"
21 #include "llvm/MC/MCELFObjectWriter.h"
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCFixupKindInfo.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/MCMachObjectWriter.h"
26 #include "llvm/MC/MCObjectWriter.h"
27 #include "llvm/MC/MCRegisterInfo.h"
28 #include "llvm/MC/MCSectionCOFF.h"
29 #include "llvm/MC/MCSectionELF.h"
30 #include "llvm/MC/MCSectionMachO.h"
31 #include "llvm/MC/MCSubtargetInfo.h"
32 #include "llvm/Support/ErrorHandling.h"
33 #include "llvm/Support/MathExtras.h"
34 #include "llvm/Support/TargetRegistry.h"
35 #include "llvm/Support/raw_ostream.h"
37 using namespace llvm;
39 namespace {
41 class M68kAsmBackend : public MCAsmBackend {
43 public:
44 M68kAsmBackend(const Target &T) : MCAsmBackend(support::big) {}
46 unsigned getNumFixupKinds() const override { return 0; }
48 void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
49 const MCValue &Target, MutableArrayRef<char> Data,
50 uint64_t Value, bool IsResolved,
51 const MCSubtargetInfo *STI) const override {
52 unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind());
54 assert(Fixup.getOffset() + Size <= Data.size() && "Invalid fixup offset!");
56 // Check that uppper bits are either all zeros or all ones.
57 // Specifically ignore overflow/underflow as long as the leakage is
58 // limited to the lower bits. This is to remain compatible with
59 // other assemblers.
60 assert(isIntN(Size * 8 + 1, Value) &&
61 "Value does not fit in the Fixup field");
63 // Write in Big Endian
64 for (unsigned i = 0; i != Size; ++i)
65 Data[Fixup.getOffset() + i] = uint8_t(Value >> ((Size - i - 1) * 8));
68 bool mayNeedRelaxation(const MCInst &Inst,
69 const MCSubtargetInfo &STI) const override;
71 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
72 const MCRelaxableFragment *DF,
73 const MCAsmLayout &Layout) const override;
75 void relaxInstruction(MCInst &Inst,
76 const MCSubtargetInfo &STI) const override;
78 /// Returns the minimum size of a nop in bytes on this target. The assembler
79 /// will use this to emit excess padding in situations where the padding
80 /// required for simple alignment would be less than the minimum nop size.
81 unsigned getMinimumNopSize() const override { return 2; }
83 /// Write a sequence of optimal nops to the output, covering \p Count bytes.
84 /// \return - true on success, false on failure
85 bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
87 } // end anonymous namespace
89 /// cc—Carry clear GE—Greater than or equal
90 /// LS—Lower or same PL—Plus
91 /// CS—Carry set GT—Greater than
92 /// LT—Less than
93 /// EQ—Equal HI—Higher
94 /// MI—Minus VC—Overflow clear
95 /// LE—Less than or equal
96 /// NE—Not equal VS—Overflow set
97 static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
98 unsigned Op = Inst.getOpcode();
99 switch (Op) {
100 default:
101 return Op;
102 case M68k::BRA8:
103 return M68k::BRA16;
104 case M68k::Bcc8:
105 return M68k::Bcc16;
106 case M68k::Bls8:
107 return M68k::Bls16;
108 case M68k::Blt8:
109 return M68k::Blt16;
110 case M68k::Beq8:
111 return M68k::Beq16;
112 case M68k::Bmi8:
113 return M68k::Bmi16;
114 case M68k::Bne8:
115 return M68k::Bne16;
116 case M68k::Bge8:
117 return M68k::Bge16;
118 case M68k::Bcs8:
119 return M68k::Bcs16;
120 case M68k::Bpl8:
121 return M68k::Bpl16;
122 case M68k::Bgt8:
123 return M68k::Bgt16;
124 case M68k::Bhi8:
125 return M68k::Bhi16;
126 case M68k::Bvc8:
127 return M68k::Bvc16;
128 case M68k::Ble8:
129 return M68k::Ble16;
130 case M68k::Bvs8:
131 return M68k::Bvs16;
135 static unsigned getRelaxedOpcodeArith(const MCInst &Inst) {
136 unsigned Op = Inst.getOpcode();
137 // NOTE there will be some relaxations for PCD and ARD mem for x20
138 return Op;
141 static unsigned getRelaxedOpcode(const MCInst &Inst) {
142 unsigned R = getRelaxedOpcodeArith(Inst);
143 if (R != Inst.getOpcode())
144 return R;
145 return getRelaxedOpcodeBranch(Inst);
148 bool M68kAsmBackend::mayNeedRelaxation(const MCInst &Inst,
149 const MCSubtargetInfo &STI) const {
150 // Branches can always be relaxed in either mode.
151 if (getRelaxedOpcodeBranch(Inst) != Inst.getOpcode())
152 return true;
154 // Check if this instruction is ever relaxable.
155 if (getRelaxedOpcodeArith(Inst) == Inst.getOpcode())
156 return false;
158 // Check if the relaxable operand has an expression. For the current set of
159 // relaxable instructions, the relaxable operand is always the last operand.
160 // NOTE will change for x20 mem
161 unsigned RelaxableOp = Inst.getNumOperands() - 1;
162 if (Inst.getOperand(RelaxableOp).isExpr())
163 return true;
165 return false;
168 bool M68kAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
169 const MCRelaxableFragment *DF,
170 const MCAsmLayout &Layout) const {
171 // TODO Newer CPU can use 32 bit offsets, so check for this when ready
172 if (!isInt<16>(Value)) {
173 llvm_unreachable("Cannot relax the instruction, value does not fit");
175 // Relax if the value is too big for a (signed) i8. This means that byte-wide
176 // instructions have to matched by default
178 // NOTE
179 // A branch to the immediately following instruction automatically
180 // uses the 16-bit displacement format because the 8-bit
181 // displacement field contains $00 (zero offset).
182 return Value == 0 || !isInt<8>(Value);
185 // NOTE Can tblgen help at all here to verify there aren't other instructions
186 // we can relax?
187 void M68kAsmBackend::relaxInstruction(MCInst &Inst,
188 const MCSubtargetInfo &STI) const {
189 // The only relaxations M68k does is from a 1byte pcrel to a 2byte PCRel.
190 unsigned RelaxedOp = getRelaxedOpcode(Inst);
192 if (RelaxedOp == Inst.getOpcode()) {
193 SmallString<256> Tmp;
194 raw_svector_ostream OS(Tmp);
195 Inst.dump_pretty(OS);
196 OS << "\n";
197 report_fatal_error("unexpected instruction to relax: " + OS.str());
200 Inst.setOpcode(RelaxedOp);
203 bool M68kAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const {
204 // Cannot emit NOP with size being not multiple of 16 bits.
205 if (Count % 2 != 0)
206 return false;
208 uint64_t NumNops = Count / 2;
209 for (uint64_t i = 0; i != NumNops; ++i) {
210 OS << "\x4E\x71";
213 return true;
216 namespace {
218 class M68kELFAsmBackend : public M68kAsmBackend {
219 public:
220 uint8_t OSABI;
221 M68kELFAsmBackend(const Target &T, uint8_t OSABI)
222 : M68kAsmBackend(T), OSABI(OSABI) {}
224 std::unique_ptr<MCObjectTargetWriter>
225 createObjectTargetWriter() const override {
226 return createM68kELFObjectWriter(OSABI);
230 } // end anonymous namespace
232 MCAsmBackend *llvm::createM68kAsmBackend(const Target &T,
233 const MCSubtargetInfo &STI,
234 const MCRegisterInfo &MRI,
235 const MCTargetOptions &Options) {
236 const Triple &TheTriple = STI.getTargetTriple();
237 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
238 return new M68kELFAsmBackend(T, OSABI);