LLVM  14.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 
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/BinaryFormat/ELF.h"
20 #include "llvm/MC/MCAsmBackend.h"
22 #include "llvm/MC/MCExpr.h"
24 #include "llvm/MC/MCInst.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"
32 #include "llvm/MC/TargetRegistry.h"
36 
37 using namespace llvm;
38 
39 namespace {
40 
41 class M68kAsmBackend : public MCAsmBackend {
42 
43 public:
44  M68kAsmBackend(const Target &T) : MCAsmBackend(support::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 
71  bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
72  const MCRelaxableFragment *DF,
73  const MCAsmLayout &Layout) const override;
74 
75  void relaxInstruction(MCInst &Inst,
76  const MCSubtargetInfo &STI) const override;
77 
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; }
82 
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,
86  const MCSubtargetInfo *STI) const override;
87 };
88 } // end anonymous namespace
89 
90 /// cc—Carry clear GE—Greater than or equal
91 /// LS—Lower or same PL—Plus
92 /// CS—Carry set GT—Greater than
93 /// LT—Less than
94 /// EQ—Equal HI—Higher
95 /// MI—Minus VC—Overflow clear
96 /// LE—Less than or equal
97 /// NE—Not equal VS—Overflow set
98 static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
99  unsigned Op = Inst.getOpcode();
100  switch (Op) {
101  default:
102  return Op;
103  case M68k::BRA8:
104  return M68k::BRA16;
105  case M68k::Bcc8:
106  return M68k::Bcc16;
107  case M68k::Bls8:
108  return M68k::Bls16;
109  case M68k::Blt8:
110  return M68k::Blt16;
111  case M68k::Beq8:
112  return M68k::Beq16;
113  case M68k::Bmi8:
114  return M68k::Bmi16;
115  case M68k::Bne8:
116  return M68k::Bne16;
117  case M68k::Bge8:
118  return M68k::Bge16;
119  case M68k::Bcs8:
120  return M68k::Bcs16;
121  case M68k::Bpl8:
122  return M68k::Bpl16;
123  case M68k::Bgt8:
124  return M68k::Bgt16;
125  case M68k::Bhi8:
126  return M68k::Bhi16;
127  case M68k::Bvc8:
128  return M68k::Bvc16;
129  case M68k::Ble8:
130  return M68k::Ble16;
131  case M68k::Bvs8:
132  return M68k::Bvs16;
133  }
134 }
135 
136 static unsigned getRelaxedOpcodeArith(const MCInst &Inst) {
137  unsigned Op = Inst.getOpcode();
138  // NOTE there will be some relaxations for PCD and ARD mem for x20
139  return Op;
140 }
141 
142 static unsigned getRelaxedOpcode(const MCInst &Inst) {
143  unsigned R = getRelaxedOpcodeArith(Inst);
144  if (R != Inst.getOpcode())
145  return R;
146  return getRelaxedOpcodeBranch(Inst);
147 }
148 
149 bool M68kAsmBackend::mayNeedRelaxation(const MCInst &Inst,
150  const MCSubtargetInfo &STI) const {
151  // Branches can always be relaxed in either mode.
152  if (getRelaxedOpcodeBranch(Inst) != Inst.getOpcode())
153  return true;
154 
155  // Check if this instruction is ever relaxable.
156  if (getRelaxedOpcodeArith(Inst) == Inst.getOpcode())
157  return false;
158 
159  // Check if the relaxable operand has an expression. For the current set of
160  // relaxable instructions, the relaxable operand is always the last operand.
161  // NOTE will change for x20 mem
162  unsigned RelaxableOp = Inst.getNumOperands() - 1;
163  if (Inst.getOperand(RelaxableOp).isExpr())
164  return true;
165 
166  return false;
167 }
168 
169 bool M68kAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
170  const MCRelaxableFragment *DF,
171  const MCAsmLayout &Layout) const {
172  // TODO Newer CPU can use 32 bit offsets, so check for this when ready
173  if (!isInt<16>(Value)) {
174  llvm_unreachable("Cannot relax the instruction, value does not fit");
175  }
176  // Relax if the value is too big for a (signed) i8. This means that byte-wide
177  // instructions have to matched by default
178  //
179  // NOTE
180  // A branch to the immediately following instruction automatically
181  // uses the 16-bit displacement format because the 8-bit
182  // displacement field contains $00 (zero offset).
183  return Value == 0 || !isInt<8>(Value);
184 }
185 
186 // NOTE Can tblgen help at all here to verify there aren't other instructions
187 // we can relax?
188 void M68kAsmBackend::relaxInstruction(MCInst &Inst,
189  const MCSubtargetInfo &STI) const {
190  // The only relaxations M68k does is from a 1byte pcrel to a 2byte PCRel.
191  unsigned RelaxedOp = getRelaxedOpcode(Inst);
192 
193  if (RelaxedOp == Inst.getOpcode()) {
194  SmallString<256> Tmp;
195  raw_svector_ostream OS(Tmp);
196  Inst.dump_pretty(OS);
197  OS << "\n";
198  report_fatal_error("unexpected instruction to relax: " + OS.str());
199  }
200 
201  Inst.setOpcode(RelaxedOp);
202 }
203 
204 bool M68kAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
205  const MCSubtargetInfo *STI) const {
206  // Cannot emit NOP with size being not multiple of 16 bits.
207  if (Count % 2 != 0)
208  return false;
209 
210  uint64_t NumNops = Count / 2;
211  for (uint64_t i = 0; i != NumNops; ++i) {
212  OS << "\x4E\x71";
213  }
214 
215  return true;
216 }
217 
218 namespace {
219 
220 class M68kELFAsmBackend : public M68kAsmBackend {
221 public:
222  uint8_t OSABI;
223  M68kELFAsmBackend(const Target &T, uint8_t OSABI)
224  : M68kAsmBackend(T), OSABI(OSABI) {}
225 
226  std::unique_ptr<MCObjectTargetWriter>
227  createObjectTargetWriter() const override {
228  return createM68kELFObjectWriter(OSABI);
229  }
230 };
231 
232 } // end anonymous namespace
233 
235  const MCSubtargetInfo &STI,
236  const MCRegisterInfo &MRI,
237  const MCTargetOptions &Options) {
238  const Triple &TheTriple = STI.getTargetTriple();
239  uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
240  return new M68kELFAsmBackend(T, OSABI);
241 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
i
i
Definition: README.txt:29
MathExtras.h
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
llvm::MCRelaxableFragment
A relaxable fragment holds on to its MCInst, since it may need to be relaxed during the assembler lay...
Definition: MCFragment.h:271
T
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:137
MCSectionELF.h
ErrorHandling.h
MCSectionCOFF.h
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:45
MCFixupKindInfo.h
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
llvm::MCInst::getNumOperands
unsigned getNumOperands() const
Definition: MCInst.h:208
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::MCInst::setOpcode
void setOpcode(unsigned Op)
Definition: MCInst.h:197
llvm::createM68kAsmBackend
MCAsmBackend * createM68kAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
Definition: M68kAsmBackend.cpp:234
llvm::MCAsmBackend
Generic interface to target specific assembler backends.
Definition: MCAsmBackend.h:36
ELF.h
MCAsmBackend.h
llvm::MutableArrayRef< char >
llvm::MCSubtargetInfo::getTargetTriple
const Triple & getTargetTriple() const
Definition: MCSubtargetInfo.h:107
MCSectionMachO.h
MCInst.h
MCSubtargetInfo.h
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
Options
const char LLVMTargetMachineRef LLVMPassBuilderOptionsRef Options
Definition: PassBuilderBindings.cpp:48
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
MCMachObjectWriter.h
llvm::getFixupKindLog2Size
static unsigned getFixupKindLog2Size(unsigned Kind)
Definition: M68kFixupKinds.h:20
llvm::isIntN
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:460
DF
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
llvm::SmallString< 256 >
llvm::isInt< 8 >
constexpr bool isInt< 8 >(int64_t x)
Definition: MathExtras.h:367
llvm::MCAssembler
Definition: MCAssembler.h:60
getRelaxedOpcodeBranch
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...
Definition: M68kAsmBackend.cpp:98
uint64_t
llvm::Triple::getOS
OSType getOS() const
getOS - Get the parsed operating system type of this triple.
Definition: Triple.h:319
MCELFObjectWriter.h
M68kFixupKinds.h
MCRegisterInfo.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MCTargetOptions
Definition: MCTargetOptions.h:36
llvm::MCELFObjectTargetWriter::getOSABI
uint8_t getOSABI() const
Definition: MCELFObjectWriter.h:101
Fixup
PowerPC TLS Dynamic Call Fixup
Definition: PPCTLSDynamicCall.cpp:235
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
getRelaxedOpcodeArith
static unsigned getRelaxedOpcodeArith(const MCInst &Inst)
Definition: M68kAsmBackend.cpp:136
llvm::MCRegisterInfo
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Definition: MCRegisterInfo.h:135
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::isInt< 16 >
constexpr bool isInt< 16 >(int64_t x)
Definition: MathExtras.h:370
MCObjectWriter.h
llvm::MCAsmLayout
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:28
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:324
llvm::createM68kELFObjectWriter
std::unique_ptr< MCObjectTargetWriter > createM68kELFObjectWriter(uint8_t OSABI)
Construct an M68k ELF object writer.
Definition: M68kELFObjectWriter.cpp:118
llvm::MCInst::getOpcode
unsigned getOpcode() const
Definition: MCInst.h:198
StringSwitch.h
llvm::MCOperand::isExpr
bool isExpr() const
Definition: MCInst.h:65
llvm::MCInst::getOperand
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:206
support
Reimplement select in terms of SEL *We would really like to support but we need to prove that the add doesn t need to overflow between the two bit chunks *Implement pre post increment support(e.g. PR935) *Implement smarter const ant generation for binops with large immediates. A few ARMv6T2 ops should be pattern matched
Definition: README.txt:10
llvm::MCInst::dump_pretty
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:81
M68kBaseInfo.h
llvm::raw_svector_ostream
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:658
llvm::HexStyle::Asm
@ Asm
0ffh
Definition: MCInstPrinter.h:34
getRelaxedOpcode
static unsigned getRelaxedOpcode(const MCInst &Inst)
Definition: M68kAsmBackend.cpp:142
llvm::MCValue
This represents an "assembler immediate".
Definition: MCValue.h:37
MachO.h
raw_ostream.h
TargetRegistry.h
MCExpr.h
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:75
llvm::MCFixup
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::support::big
@ big
Definition: Endian.h:27