LLVM 17.0.0git
M68kMCCodeEmitter.cpp
Go to the documentation of this file.
1//===-- M68kMCCodeEmitter.cpp - Convert M68k code emitter -------*- 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 defintions for M68k code emitter.
11///
12//===----------------------------------------------------------------------===//
13
18
20#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCExpr.h"
22#include "llvm/MC/MCInst.h"
23#include "llvm/MC/MCInstrInfo.h"
26#include "llvm/MC/MCSymbol.h"
27#include "llvm/Support/Debug.h"
30#include <type_traits>
31
32using namespace llvm;
33
34#define DEBUG_TYPE "m68k-mccodeemitter"
35
36namespace {
37class M68kMCCodeEmitter : public MCCodeEmitter {
38 M68kMCCodeEmitter(const M68kMCCodeEmitter &) = delete;
39 void operator=(const M68kMCCodeEmitter &) = delete;
40 const MCInstrInfo &MCII;
41 MCContext &Ctx;
42
43 void getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl<MCFixup> &Fixups,
44 APInt &Inst, APInt &Scratch,
45 const MCSubtargetInfo &STI) const;
46
47 void getMachineOpValue(const MCInst &MI, const MCOperand &Op,
48 unsigned InsertPos, APInt &Value,
50 const MCSubtargetInfo &STI) const;
51
52 template <unsigned Size>
53 void encodeRelocImm(const MCInst &MI, unsigned OpIdx, unsigned InsertPos,
55 const MCSubtargetInfo &STI) const;
56
57 template <unsigned Size>
58 void encodePCRelImm(const MCInst &MI, unsigned OpIdx, unsigned InsertPos,
60 const MCSubtargetInfo &STI) const;
61
62public:
63 M68kMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
64 : MCII(mcii), Ctx(ctx) {}
65
66 ~M68kMCCodeEmitter() override {}
67
68 void encodeInstruction(const MCInst &MI, raw_ostream &OS,
70 const MCSubtargetInfo &STI) const override;
71};
72
73} // end anonymous namespace
74
75#include "M68kGenMCCodeEmitter.inc"
76
77// Select the proper unsigned integer type from a bit size.
78template <unsigned Size> struct select_uint_t {
79 using type = typename std::conditional<
80 Size == 8, uint8_t,
81 typename std::conditional<
82 Size == 16, uint16_t,
83 typename std::conditional<Size == 32, uint32_t,
85};
86
87// Figure out which byte we're at in big endian mode.
88template <unsigned Size> static unsigned getBytePosition(unsigned BitPos) {
89 if (Size % 16) {
90 return static_cast<unsigned>(BitPos / 8 + ((BitPos & 0b1111) < 8 ? 1 : -1));
91 } else {
92 assert(!(BitPos & 0b1111) && "Not aligned to word boundary?");
93 return BitPos / 8;
94 }
95}
96
97// We need special handlings for relocatable & pc-relative operands that are
98// larger than a word.
99// A M68k instruction is aligned by word (16 bits). That means, 32-bit
100// (& 64-bit) immediate values are separated into hi & lo words and placed
101// at lower & higher addresses, respectively. For immediate values that can
102// be easily expressed in TG, we explicitly rotate the word ordering like
103// this:
104// ```
105// (ascend (slice "$imm", 31, 16), (slice "$imm", 15, 0))
106// ```
107// For operands that call into encoder functions, we need to use the `swapWord`
108// function to assure the correct word ordering on LE host. Note that
109// M68kMCCodeEmitter does massage _byte_ ordering of the final encoded
110// instruction but it assumes everything aligns on word boundaries. So things
111// will go wrong if we don't take care of the _word_ ordering here.
112template <unsigned Size>
113void M68kMCCodeEmitter::encodeRelocImm(const MCInst &MI, unsigned OpIdx,
114 unsigned InsertPos, APInt &Value,
116 const MCSubtargetInfo &STI) const {
117 using value_t = typename select_uint_t<Size>::type;
118 const MCOperand &MCO = MI.getOperand(OpIdx);
119 if (MCO.isImm()) {
120 Value |= M68k::swapWord<value_t>(static_cast<value_t>(MCO.getImm()));
121 } else if (MCO.isExpr()) {
122 const MCExpr *Expr = MCO.getExpr();
123
124 // Absolute address
125 int64_t Addr;
126 if (Expr->evaluateAsAbsolute(Addr)) {
127 Value |= M68k::swapWord<value_t>(static_cast<value_t>(Addr));
128 return;
129 }
130
131 // Relocatable address
132 unsigned InsertByte = getBytePosition<Size>(InsertPos);
133 Fixups.push_back(MCFixup::create(InsertByte, Expr,
134 getFixupForSize(Size, /*IsPCRel=*/false),
135 MI.getLoc()));
136 }
137}
138
139template <unsigned Size>
140void M68kMCCodeEmitter::encodePCRelImm(const MCInst &MI, unsigned OpIdx,
141 unsigned InsertPos, APInt &Value,
143 const MCSubtargetInfo &STI) const {
144 const MCOperand &MCO = MI.getOperand(OpIdx);
145 if (MCO.isImm()) {
146 using value_t = typename select_uint_t<Size>::type;
147 Value |= M68k::swapWord<value_t>(static_cast<value_t>(MCO.getImm()));
148 } else if (MCO.isExpr()) {
149 const MCExpr *Expr = MCO.getExpr();
150 unsigned InsertByte = getBytePosition<Size>(InsertPos);
151
152 // Special handlings for sizes smaller than a word.
153 if (Size < 16) {
154 int LabelOffset = 0;
155 if (InsertPos < 16)
156 // If the patch point is at the first word, PC is pointing at the
157 // next word.
158 LabelOffset = InsertByte - 2;
159 else if (InsertByte % 2)
160 // Otherwise the PC is pointing at the first byte of this word.
161 // So we need to consider the offset between PC and the fixup byte.
162 LabelOffset = 1;
163
164 if (LabelOffset)
166 Expr, MCConstantExpr::create(LabelOffset, Ctx), Ctx);
167 }
168
169 Fixups.push_back(MCFixup::create(InsertByte, Expr,
170 getFixupForSize(Size, /*IsPCRel=*/true),
171 MI.getLoc()));
172 }
173}
174
175void M68kMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &Op,
176 unsigned InsertPos, APInt &Value,
178 const MCSubtargetInfo &STI) const {
179 // Register
180 if (Op.isReg()) {
181 unsigned RegNum = Op.getReg();
182 const auto *RI = Ctx.getRegisterInfo();
183 Value |= RI->getEncodingValue(RegNum);
184 // Setup the D/A bit
185 if (M68kII::isAddressRegister(RegNum))
186 Value |= 0b1000;
187 } else if (Op.isImm()) {
188 // Immediate
189 Value |= static_cast<uint64_t>(Op.getImm());
190 } else if (Op.isExpr()) {
191 // Absolute address
192 int64_t Addr;
193 if (!Op.getExpr()->evaluateAsAbsolute(Addr))
194 report_fatal_error("Unsupported asm expression. Only absolute address "
195 "can be placed here.");
196 Value |= static_cast<uint64_t>(Addr);
197 } else {
198 llvm_unreachable("Unsupported operand type");
199 }
200}
201
202void M68kMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
204 const MCSubtargetInfo &STI) const {
205 unsigned Opcode = MI.getOpcode();
206
207 LLVM_DEBUG(dbgs() << "EncodeInstruction: " << MCII.getName(Opcode) << "("
208 << Opcode << ")\n");
209
210 // Try using the new method first.
211 APInt EncodedInst(16, 0U);
212 APInt Scratch(16, 0U);
213 getBinaryCodeForInstr(MI, Fixups, EncodedInst, Scratch, STI);
214
215 ArrayRef<uint64_t> Data(EncodedInst.getRawData(), EncodedInst.getNumWords());
216 int64_t InstSize = EncodedInst.getBitWidth();
217 for (uint64_t Word : Data) {
218 for (int i = 0; i < 4 && InstSize > 0; ++i, InstSize -= 16) {
219 support::endian::write<uint16_t>(OS, static_cast<uint16_t>(Word),
221 Word >>= 16;
222 }
223 }
224}
225
227 MCContext &Ctx) {
228 return new M68kMCCodeEmitter(MCII, Ctx);
229}
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Addr
uint64_t Size
IRTranslator LLVM IR MI
This file contains small standalone helper functions and enum definitions for the M68k target useful ...
This file contains M68k specific fixup entries.
static unsigned getBytePosition(unsigned BitPos)
This file contains the declarations for the code emitter which are useful outside of the emitter itse...
This file provides M68k specific target descriptions.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Class for arbitrary precision integers.
Definition: APInt.h:75
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:525
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
EncodeInstruction - Encode the given Inst to bytes on the output stream OS.
MCCodeEmitter & operator=(const MCCodeEmitter &)=delete
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:76
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:87
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
int64_t getImm() const
Definition: MCInst.h:80
bool isImm() const
Definition: MCInst.h:62
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
Generic base class for all target subtargets.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
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
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool isAddressRegister(unsigned RegNo)
Definition: M68kBaseInfo.h:195
support::ulittle32_t Word
Definition: IRSymtab.h:52
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
static MCFixupKind getFixupForSize(unsigned Size, bool isPCRel)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
MCCodeEmitter * createM68kMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
typename std::conditional< Size==8, uint8_t, typename std::conditional< Size==16, uint16_t, typename std::conditional< Size==32, uint32_t, uint64_t >::type >::type >::type type