LLVM 20.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
22#include "llvm/MC/MCExpr.h"
24#include "llvm/MC/MCInst.h"
36
37using namespace llvm;
38
39namespace {
40
41class M68kAsmBackend : public MCAsmBackend {
42
43public:
44 M68kAsmBackend(const Target &T) : MCAsmBackend(llvm::endianness::big) {}
45
46 unsigned getNumFixupKinds() const override { return 0; }
47
48 void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
50 uint64_t Value, bool IsResolved,
51 const MCSubtargetInfo *STI) const override {
52 unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind());
53
54 assert(Fixup.getOffset() + Size <= Data.size() && "Invalid fixup offset!");
55
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");
62
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));
66 }
67
68 bool mayNeedRelaxation(const MCInst &Inst,
69 const MCSubtargetInfo &STI) const override;
70
72 uint64_t Value) const override;
73
74 void relaxInstruction(MCInst &Inst,
75 const MCSubtargetInfo &STI) const override;
76
77 /// Returns the minimum size of a nop in bytes on this target. The assembler
78 /// will use this to emit excess padding in situations where the padding
79 /// required for simple alignment would be less than the minimum nop size.
80 unsigned getMinimumNopSize() const override { return 2; }
81
82 /// Write a sequence of optimal nops to the output, covering \p Count bytes.
83 /// \return - true on success, false on failure
85 const MCSubtargetInfo *STI) const override;
86};
87} // end anonymous namespace
88
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
97static 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;
132 }
133}
134
135static 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;
139}
140
141static unsigned getRelaxedOpcode(const MCInst &Inst) {
142 unsigned R = getRelaxedOpcodeArith(Inst);
143 if (R != Inst.getOpcode())
144 return R;
145 return getRelaxedOpcodeBranch(Inst);
146}
147
148bool 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;
153
154 // Check if this instruction is ever relaxable.
155 if (getRelaxedOpcodeArith(Inst) == Inst.getOpcode())
156 return false;
157
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;
164
165 return false;
166}
167
168bool M68kAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
169 uint64_t Value) const {
170 // TODO Newer CPU can use 32 bit offsets, so check for this when ready
171 if (!isInt<16>(Value)) {
172 llvm_unreachable("Cannot relax the instruction, value does not fit");
173 }
174 // Relax if the value is too big for a (signed) i8. This means that byte-wide
175 // instructions have to matched by default
176 //
177 // NOTE
178 // A branch to the immediately following instruction automatically
179 // uses the 16-bit displacement format because the 8-bit
180 // displacement field contains $00 (zero offset).
181 return Value == 0 || !isInt<8>(Value);
182}
183
184// NOTE Can tblgen help at all here to verify there aren't other instructions
185// we can relax?
186void M68kAsmBackend::relaxInstruction(MCInst &Inst,
187 const MCSubtargetInfo &STI) const {
188 // The only relaxations M68k does is from a 1byte pcrel to a 2byte PCRel.
189 unsigned RelaxedOp = getRelaxedOpcode(Inst);
190
191 if (RelaxedOp == Inst.getOpcode()) {
194 Inst.dump_pretty(OS);
195 OS << "\n";
196 report_fatal_error("unexpected instruction to relax: " + OS.str());
197 }
198
199 Inst.setOpcode(RelaxedOp);
200}
201
202bool M68kAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
203 const MCSubtargetInfo *STI) const {
204 // Cannot emit NOP with size being not multiple of 16 bits.
205 if (Count % 2 != 0)
206 return false;
207
208 uint64_t NumNops = Count / 2;
209 for (uint64_t i = 0; i != NumNops; ++i) {
210 OS << "\x4E\x71";
211 }
212
213 return true;
214}
215
216namespace {
217
218class M68kELFAsmBackend : public M68kAsmBackend {
219public:
220 uint8_t OSABI;
221 M68kELFAsmBackend(const Target &T, uint8_t OSABI)
222 : M68kAsmBackend(T), OSABI(OSABI) {}
223
224 std::unique_ptr<MCObjectTargetWriter>
225 createObjectTargetWriter() const override {
226 return createM68kELFObjectWriter(OSABI);
227 }
228};
229
230} // end anonymous namespace
231
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);
239}
unsigned const MachineRegisterInfo * MRI
uint64_t Size
static LVOptions Options
Definition: LVOptions.cpp:25
static unsigned getRelaxedOpcodeBranch(const MCInst &Inst)
cc—Carry clear GE—Greater than or equal LS—Lower or same PL—Plus CS—Carry set GT—Greater than LT—Less...
static unsigned getRelaxedOpcodeArith(const MCInst &Inst)
static unsigned getRelaxedOpcode(const MCInst &Inst)
This file contains small standalone helper functions and enum definitions for the M68k target useful ...
This file contains M68k specific fixup entries.
PowerPC TLS Dynamic Call Fixup
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
This class represents an Operation in the Expression.
Generic interface to target specific assembler backends.
Definition: MCAsmBackend.h:42
virtual unsigned getMinimumNopSize() const
Returns the minimum size of a nop in bytes on this target.
Definition: MCAsmBackend.h:207
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:179
virtual bool mayNeedRelaxation(const MCInst &Inst, const MCSubtargetInfo &STI) const
Check whether the given instruction may need relaxation.
Definition: MCAsmBackend.h:155
virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value) const
Simple predicate for targets where !Resolved implies requiring relaxation.
Definition: MCAsmBackend.h:169
virtual unsigned getNumFixupKinds() const =0
Get the number of target specific fixup kinds.
virtual void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef< char > Data, uint64_t Value, bool IsResolved, const MCSubtargetInfo *STI) const =0
Apply the Value for given Fixup into the provided data fragment, at the offset specified by the fixup...
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer=nullptr, StringRef Separator=" ", const MCRegisterInfo *RegInfo=nullptr) const
Dump the MCInst as prettily as possible using the additional MC structures, if given.
Definition: MCInst.cpp:84
unsigned getNumOperands() const
Definition: MCInst.h:208
unsigned getOpcode() const
Definition: MCInst.h:198
void setOpcode(unsigned Op)
Definition: MCInst.h:197
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:206
bool isExpr() const
Definition: MCInst.h:65
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
This represents an "assembler immediate".
Definition: MCValue.h:36
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:307
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
OSType getOS() const
Get the parsed operating system type of this triple.
Definition: Triple.h:382
LLVM Value Representation.
Definition: Value.h:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:691
#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)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:260
DWARFExpression::Operation Op
endianness
Definition: bit.h:70