1 //===-- M68kAsmBackend.cpp - M68k Assembler Backend ---------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file contains definitions for M68k assembler backend.
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"
41 class M68kAsmBackend
: public MCAsmBackend
{
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
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
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();
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
141 static unsigned getRelaxedOpcode(const MCInst
&Inst
) {
142 unsigned R
= getRelaxedOpcodeArith(Inst
);
143 if (R
!= Inst
.getOpcode())
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())
154 // Check if this instruction is ever relaxable.
155 if (getRelaxedOpcodeArith(Inst
) == Inst
.getOpcode())
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())
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
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
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
);
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.
208 uint64_t NumNops
= Count
/ 2;
209 for (uint64_t i
= 0; i
!= NumNops
; ++i
) {
218 class M68kELFAsmBackend
: public M68kAsmBackend
{
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
);