LLVM 23.0.0git
M68kAsmBackend.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
13
16
21#include "llvm/MC/MCAssembler.h"
23#include "llvm/MC/MCExpr.h"
24#include "llvm/MC/MCInst.h"
32#include "llvm/MC/MCValue.h"
34#include "llvm/Support/Debug.h"
38
39using namespace llvm;
40
41#define DEBUG_TYPE "M68k-asm-backend"
42
43namespace {
44
45class M68kAsmBackend : public MCAsmBackend {
46 bool Allows32BitBranch;
47
48public:
49 M68kAsmBackend(const Target &T, const MCSubtargetInfo &STI)
51 Allows32BitBranch(llvm::StringSwitch<bool>(STI.getCPU())
52 .CasesLower({"m68020", "m68030", "m68040"}, true)
53 .Default(false)) {}
54
55 void applyFixup(const MCFragment &, const MCFixup &, const MCValue &,
56 uint8_t *Data, uint64_t Value, bool IsResolved) override;
57
58 bool mayNeedRelaxation(unsigned Opcode, ArrayRef<MCOperand> Operands,
59 const MCSubtargetInfo &STI) const override;
60
61 bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &,
62 const MCValue &, uint64_t,
63 bool) const override;
64
65 void relaxInstruction(MCInst &Inst,
66 const MCSubtargetInfo &STI) const override;
67
68 /// Returns the minimum size of a nop in bytes on this target. The assembler
69 /// will use this to emit excess padding in situations where the padding
70 /// required for simple alignment would be less than the minimum nop size.
71 unsigned getMinimumNopSize() const override { return 2; }
72
73 /// Write a sequence of optimal nops to the output, covering \p Count bytes.
74 /// \return - true on success, false on failure
75 bool writeNopData(raw_ostream &OS, uint64_t Count,
76 const MCSubtargetInfo *STI) const override;
77};
78} // end anonymous namespace
79
80void M68kAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
81 const MCValue &Target, uint8_t *Data,
82 uint64_t Value, bool IsResolved) {
83 if (!IsResolved)
84 Asm->getWriter().recordRelocation(F, Fixup, Target, Value);
85
86 unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind());
87 assert(Fixup.getOffset() + Size <= F.getSize() && "Invalid fixup offset!");
88 // Check that uppper bits are either all zeros or all ones.
89 // Specifically ignore overflow/underflow as long as the leakage is
90 // limited to the lower bits. This is to remain compatible with
91 // other assemblers.
92 assert(isIntN(Size * 8 + 1, static_cast<int64_t>(Value)) &&
93 "Value does not fit in the Fixup field");
94
95 // Write in Big Endian
96 for (unsigned i = 0; i != Size; ++i)
97 Data[i] = uint8_t(static_cast<int64_t>(Value) >> ((Size - i - 1) * 8));
98}
99
100/// cc—Carry clear GE—Greater than or equal
101/// LS—Lower or same PL—Plus
102/// CS—Carry set GT—Greater than
103/// LT—Less than
104/// EQ—Equal HI—Higher
105/// MI—Minus VC—Overflow clear
106/// LE—Less than or equal
107/// NE—Not equal VS—Overflow set
108static unsigned getRelaxedOpcodeBranch(unsigned Op) {
109 switch (Op) {
110 default:
111 return Op;
112
113 // 8 -> 16
114 case M68k::BRA8:
115 return M68k::BRA16;
116 case M68k::Bcc8:
117 return M68k::Bcc16;
118 case M68k::Bls8:
119 return M68k::Bls16;
120 case M68k::Blt8:
121 return M68k::Blt16;
122 case M68k::Beq8:
123 return M68k::Beq16;
124 case M68k::Bmi8:
125 return M68k::Bmi16;
126 case M68k::Bne8:
127 return M68k::Bne16;
128 case M68k::Bge8:
129 return M68k::Bge16;
130 case M68k::Bcs8:
131 return M68k::Bcs16;
132 case M68k::Bpl8:
133 return M68k::Bpl16;
134 case M68k::Bgt8:
135 return M68k::Bgt16;
136 case M68k::Bhi8:
137 return M68k::Bhi16;
138 case M68k::Bvc8:
139 return M68k::Bvc16;
140 case M68k::Ble8:
141 return M68k::Ble16;
142 case M68k::Bvs8:
143 return M68k::Bvs16;
144
145 // 16 -> 32
146 case M68k::BRA16:
147 return M68k::BRA32;
148 case M68k::Bcc16:
149 return M68k::Bcc32;
150 case M68k::Bls16:
151 return M68k::Bls32;
152 case M68k::Blt16:
153 return M68k::Blt32;
154 case M68k::Beq16:
155 return M68k::Beq32;
156 case M68k::Bmi16:
157 return M68k::Bmi32;
158 case M68k::Bne16:
159 return M68k::Bne32;
160 case M68k::Bge16:
161 return M68k::Bge32;
162 case M68k::Bcs16:
163 return M68k::Bcs32;
164 case M68k::Bpl16:
165 return M68k::Bpl32;
166 case M68k::Bgt16:
167 return M68k::Bgt32;
168 case M68k::Bhi16:
169 return M68k::Bhi32;
170 case M68k::Bvc16:
171 return M68k::Bvc32;
172 case M68k::Ble16:
173 return M68k::Ble32;
174 case M68k::Bvs16:
175 return M68k::Bvs32;
176 }
177}
178
179static unsigned getRelaxedOpcode(unsigned Opcode) {
180 // NOTE there will be some relaxations for PCD and ARD mem for x20
181 return getRelaxedOpcodeBranch(Opcode);
182}
183
184bool M68kAsmBackend::mayNeedRelaxation(unsigned Opcode, ArrayRef<MCOperand>,
185 const MCSubtargetInfo &STI) const {
186 // Branches can always be relaxed in either mode.
187 return getRelaxedOpcode(Opcode) != Opcode;
188
189 // NOTE will change for x20 mem
190}
191
192bool M68kAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &,
193 const MCFixup &Fixup,
194 const MCValue &,
195 uint64_t UnsignedValue,
196 bool Resolved) const {
197 if (!Resolved)
198 return true;
199 int64_t Value = static_cast<int64_t>(UnsignedValue);
200
201 if (!isInt<32>(Value) || (!Allows32BitBranch && !isInt<16>(Value)))
202 llvm_unreachable("Cannot relax the instruction, value does not fit");
203
204 // Relax if the value is too big for a (signed) i8
205 // (or signed i16 if 32 bit branches can be used). This means
206 // that byte-wide instructions have to matched by default
207 unsigned KindLog2Size = getFixupKindLog2Size(Fixup.getKind());
208 bool FixupFieldTooSmall = false;
209 if (!isInt<8>(Value) && KindLog2Size == 0)
210 FixupFieldTooSmall = true;
211 else if (!isInt<16>(Value) && KindLog2Size <= 1)
212 FixupFieldTooSmall = true;
213
214 // NOTE
215 // A branch to the immediately following instruction automatically
216 // uses the 16-bit displacement format because the 8-bit
217 // displacement field contains $00 (zero offset).
218 bool ZeroDisplacementNeedsFixup = Value == 0 && KindLog2Size == 0;
219
220 return ZeroDisplacementNeedsFixup || FixupFieldTooSmall;
221}
222
223// NOTE Can tblgen help at all here to verify there aren't other instructions
224// we can relax?
225void M68kAsmBackend::relaxInstruction(MCInst &Inst,
226 const MCSubtargetInfo &STI) const {
227 unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode());
228 assert(RelaxedOp != Inst.getOpcode());
229 Inst.setOpcode(RelaxedOp);
230}
231
232bool M68kAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
233 const MCSubtargetInfo *STI) const {
234 // Cannot emit NOP with size being not multiple of 16 bits.
235 if (Count % 2 != 0)
236 return false;
237
238 uint64_t NumNops = Count / 2;
239 for (uint64_t i = 0; i != NumNops; ++i) {
240 OS << "\x4E\x71";
241 }
242
243 return true;
244}
245
246namespace {
247
248class M68kELFAsmBackend : public M68kAsmBackend {
249public:
250 uint8_t OSABI;
251 M68kELFAsmBackend(const Target &T, const MCSubtargetInfo &STI, uint8_t OSABI)
252 : M68kAsmBackend(T, STI), OSABI(OSABI) {}
253
254 std::unique_ptr<MCObjectTargetWriter>
255 createObjectTargetWriter() const override {
256 return createM68kELFObjectWriter(OSABI);
257 }
258};
259
260} // end anonymous namespace
261
263 const MCSubtargetInfo &STI,
264 const MCRegisterInfo &MRI,
265 const MCTargetOptions &Options) {
266 const Triple &TheTriple = STI.getTargetTriple();
268 return new M68kELFAsmBackend(T, STI, OSABI);
269}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static LVOptions Options
Definition LVOptions.cpp:25
static unsigned getRelaxedOpcodeBranch(unsigned Op)
cc—Carry clear GE—Greater than or equal LS—Lower or same PL—Plus CS—Carry set GT—Greater than LT—Less...
static unsigned getRelaxedOpcode(unsigned Opcode)
This file contains small standalone helper functions and enum definitions for the M68k target useful ...
This file contains M68k specific fixup entries.
#define F(x, y, z)
Definition MD5.cpp:54
#define T
PowerPC TLS Dynamic Call Fixup
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Generic interface to target specific assembler backends.
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition MCFixup.h:61
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getOpcode() const
Definition MCInst.h:202
void setOpcode(unsigned Op)
Definition MCInst.h:201
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
StringRef getCPU() const
A switch()-like statement whose cases are string literals.
StringSwitch & CasesLower(std::initializer_list< StringLiteral > CaseStrings, T Value)
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
OSType getOS() const
Get the parsed operating system type of this triple.
Definition Triple.h:429
LLVM Value Representation.
Definition Value.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
static unsigned getFixupKindLog2Size(unsigned Kind)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
std::unique_ptr< MCObjectTargetWriter > createM68kELFObjectWriter(uint8_t OSABI)
Construct an M68k ELF object writer.
MCAsmBackend * createM68kAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:248