LLVM 22.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
59 const MCSubtargetInfo &STI) const override;
60
62 uint64_t Value) const override;
63
64 void relaxInstruction(MCInst &Inst,
65 const MCSubtargetInfo &STI) const override;
66
67 /// Returns the minimum size of a nop in bytes on this target. The assembler
68 /// will use this to emit excess padding in situations where the padding
69 /// required for simple alignment would be less than the minimum nop size.
70 unsigned getMinimumNopSize() const override { return 2; }
71
72 /// Write a sequence of optimal nops to the output, covering \p Count bytes.
73 /// \return - true on success, false on failure
75 const MCSubtargetInfo *STI) const override;
76};
77} // end anonymous namespace
78
79void M68kAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
80 const MCValue &Target, uint8_t *Data,
81 uint64_t Value, bool IsResolved) {
82 if (!IsResolved)
83 Asm->getWriter().recordRelocation(F, Fixup, Target, Value);
84
85 unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind());
86 assert(Fixup.getOffset() + Size <= F.getSize() && "Invalid fixup offset!");
87 // Check that uppper bits are either all zeros or all ones.
88 // Specifically ignore overflow/underflow as long as the leakage is
89 // limited to the lower bits. This is to remain compatible with
90 // other assemblers.
91 assert(isIntN(Size * 8 + 1, static_cast<int64_t>(Value)) &&
92 "Value does not fit in the Fixup field");
93
94 // Write in Big Endian
95 for (unsigned i = 0; i != Size; ++i)
96 Data[i] = uint8_t(static_cast<int64_t>(Value) >> ((Size - i - 1) * 8));
97}
98
99/// cc—Carry clear GE—Greater than or equal
100/// LS—Lower or same PL—Plus
101/// CS—Carry set GT—Greater than
102/// LT—Less than
103/// EQ—Equal HI—Higher
104/// MI—Minus VC—Overflow clear
105/// LE—Less than or equal
106/// NE—Not equal VS—Overflow set
107static unsigned getRelaxedOpcodeBranch(unsigned Op) {
108 switch (Op) {
109 default:
110 return Op;
111
112 // 8 -> 16
113 case M68k::BRA8:
114 return M68k::BRA16;
115 case M68k::Bcc8:
116 return M68k::Bcc16;
117 case M68k::Bls8:
118 return M68k::Bls16;
119 case M68k::Blt8:
120 return M68k::Blt16;
121 case M68k::Beq8:
122 return M68k::Beq16;
123 case M68k::Bmi8:
124 return M68k::Bmi16;
125 case M68k::Bne8:
126 return M68k::Bne16;
127 case M68k::Bge8:
128 return M68k::Bge16;
129 case M68k::Bcs8:
130 return M68k::Bcs16;
131 case M68k::Bpl8:
132 return M68k::Bpl16;
133 case M68k::Bgt8:
134 return M68k::Bgt16;
135 case M68k::Bhi8:
136 return M68k::Bhi16;
137 case M68k::Bvc8:
138 return M68k::Bvc16;
139 case M68k::Ble8:
140 return M68k::Ble16;
141 case M68k::Bvs8:
142 return M68k::Bvs16;
143
144 // 16 -> 32
145 case M68k::BRA16:
146 return M68k::BRA32;
147 case M68k::Bcc16:
148 return M68k::Bcc32;
149 case M68k::Bls16:
150 return M68k::Bls32;
151 case M68k::Blt16:
152 return M68k::Blt32;
153 case M68k::Beq16:
154 return M68k::Beq32;
155 case M68k::Bmi16:
156 return M68k::Bmi32;
157 case M68k::Bne16:
158 return M68k::Bne32;
159 case M68k::Bge16:
160 return M68k::Bge32;
161 case M68k::Bcs16:
162 return M68k::Bcs32;
163 case M68k::Bpl16:
164 return M68k::Bpl32;
165 case M68k::Bgt16:
166 return M68k::Bgt32;
167 case M68k::Bhi16:
168 return M68k::Bhi32;
169 case M68k::Bvc16:
170 return M68k::Bvc32;
171 case M68k::Ble16:
172 return M68k::Ble32;
173 case M68k::Bvs16:
174 return M68k::Bvs32;
175 }
176}
177
178static unsigned getRelaxedOpcode(unsigned Opcode) {
179 // NOTE there will be some relaxations for PCD and ARD mem for x20
180 return getRelaxedOpcodeBranch(Opcode);
181}
182
183bool M68kAsmBackend::mayNeedRelaxation(unsigned Opcode, ArrayRef<MCOperand>,
184 const MCSubtargetInfo &STI) const {
185 // Branches can always be relaxed in either mode.
186 return getRelaxedOpcode(Opcode) != Opcode;
187
188 // NOTE will change for x20 mem
189}
190
191bool M68kAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
192 uint64_t UnsignedValue) const {
193 int64_t Value = static_cast<int64_t>(UnsignedValue);
194
195 if (!isInt<32>(Value) || (!Allows32BitBranch && !isInt<16>(Value)))
196 llvm_unreachable("Cannot relax the instruction, value does not fit");
197
198 // Relax if the value is too big for a (signed) i8
199 // (or signed i16 if 32 bit branches can be used). This means
200 // that byte-wide instructions have to matched by default
201 unsigned KindLog2Size = getFixupKindLog2Size(Fixup.getKind());
202 bool FixupFieldTooSmall = false;
203 if (!isInt<8>(Value) && KindLog2Size == 0)
204 FixupFieldTooSmall = true;
205 else if (!isInt<16>(Value) && KindLog2Size <= 1)
206 FixupFieldTooSmall = true;
207
208 // NOTE
209 // A branch to the immediately following instruction automatically
210 // uses the 16-bit displacement format because the 8-bit
211 // displacement field contains $00 (zero offset).
212 bool ZeroDisplacementNeedsFixup = Value == 0 && KindLog2Size == 0;
213
214 return ZeroDisplacementNeedsFixup || FixupFieldTooSmall;
215}
216
217// NOTE Can tblgen help at all here to verify there aren't other instructions
218// we can relax?
219void M68kAsmBackend::relaxInstruction(MCInst &Inst,
220 const MCSubtargetInfo &STI) const {
221 unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode());
222 assert(RelaxedOp != Inst.getOpcode());
223 Inst.setOpcode(RelaxedOp);
224}
225
226bool M68kAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
227 const MCSubtargetInfo *STI) const {
228 // Cannot emit NOP with size being not multiple of 16 bits.
229 if (Count % 2 != 0)
230 return false;
231
232 uint64_t NumNops = Count / 2;
233 for (uint64_t i = 0; i != NumNops; ++i) {
234 OS << "\x4E\x71";
235 }
236
237 return true;
238}
239
240namespace {
241
242class M68kELFAsmBackend : public M68kAsmBackend {
243public:
244 uint8_t OSABI;
245 M68kELFAsmBackend(const Target &T, const MCSubtargetInfo &STI, uint8_t OSABI)
246 : M68kAsmBackend(T, STI), OSABI(OSABI) {}
247
248 std::unique_ptr<MCObjectTargetWriter>
249 createObjectTargetWriter() const override {
250 return createM68kELFObjectWriter(OSABI);
251 }
252};
253
254} // end anonymous namespace
255
257 const MCSubtargetInfo &STI,
258 const MCRegisterInfo &MRI,
259 const MCTargetOptions &Options) {
260 const Triple &TheTriple = STI.getTargetTriple();
262 return new M68kELFAsmBackend(T, STI, OSABI);
263}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t Size
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:55
mir Rename Register Operands
PowerPC TLS Dynamic Call Fixup
raw_pwrite_stream & OS
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:41
This class represents an Operation in the Expression.
Generic interface to target specific assembler backends.
Definition: MCAsmBackend.h:55
virtual unsigned getMinimumNopSize() const
Returns the minimum size of a nop in bytes on this target.
Definition: MCAsmBackend.h:185
virtual bool writeNopData(raw_ostream &OS, uint64_t Count, const MCSubtargetInfo *STI) const =0
Write an (optimal) nop sequence of Count bytes to the given output.
virtual void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const
Relax the instruction in the given fragment to the next wider instruction.
Definition: MCAsmBackend.h:157
virtual bool mayNeedRelaxation(unsigned Opcode, ArrayRef< MCOperand > Operands, const MCSubtargetInfo &STI) const
Check whether the given instruction (encoded as Opcode+Operands) may need relaxation.
Definition: MCAsmBackend.h:135
virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value) const
Simple predicate for targets where !Resolved implies requiring relaxation.
Definition: MCAsmBackend.h:147
virtual void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target, uint8_t *Data, uint64_t Value, bool IsResolved)=0
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.
Definition: StringSwitch.h:43
StringSwitch & CasesLower(StringLiteral S0, StringLiteral S1, T Value)
Definition: StringSwitch.h:158
R Default(T Value)
Definition: StringSwitch.h:177
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:417
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: AddressRanges.h:18
static unsigned getFixupKindLog2Size(unsigned Kind)
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)
DWARFExpression::Operation Op
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:257