LLVM 23.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 definitions 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
62 void encodeFPSYSSelect(const MCInst &MI, unsigned OpIdx, unsigned InsertPos,
64 const MCSubtargetInfo &STI) const;
65
66 void encodeInverseMoveMask(const MCInst &MI, unsigned OpIdx,
67 unsigned InsertPos, APInt &Value,
69 const MCSubtargetInfo &STI) const;
70
71 void encodeScale(const MCInst &MI, unsigned OpIdx, unsigned InsertPos,
73 const MCSubtargetInfo &STI) const;
74
75 void encodeIndexSuppress(const MCInst &MI, unsigned OpIdx, unsigned InsertPos,
77 const MCSubtargetInfo &STI) const;
78
79public:
80 M68kMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
81 : MCII(mcii), Ctx(ctx) {}
82
83 ~M68kMCCodeEmitter() override {}
84
85 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
87 const MCSubtargetInfo &STI) const override;
88};
89
90} // end anonymous namespace
91
92#include "M68kGenMCCodeEmitter.inc"
93
94// Select the proper unsigned integer type from a bit size.
95template <unsigned Size> struct select_uint_t {
96 using type = typename std::conditional<
97 Size == 8, uint8_t,
98 typename std::conditional<
99 Size == 16, uint16_t,
100 typename std::conditional<Size == 32, uint32_t,
102};
103
104// Figure out which byte we're at in big endian mode.
105template <unsigned Size> static unsigned getBytePosition(unsigned BitPos) {
106 if (Size % 16) {
107 return static_cast<unsigned>(BitPos / 8 + ((BitPos & 0b1111) < 8 ? 1 : -1));
108 } else {
109 assert(!(BitPos & 0b1111) && "Not aligned to word boundary?");
110 return BitPos / 8;
111 }
112}
113
115 const MCExpr *Value, uint16_t Kind, bool PCRel = false) {
116 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));
117}
118
119// We need special handlings for relocatable & pc-relative operands that are
120// larger than a word.
121// A M68k instruction is aligned by word (16 bits). That means, 32-bit
122// (& 64-bit) immediate values are separated into hi & lo words and placed
123// at lower & higher addresses, respectively. For immediate values that can
124// be easily expressed in TG, we explicitly rotate the word ordering like
125// this:
126// ```
127// (ascend (slice "$imm", 31, 16), (slice "$imm", 15, 0))
128// ```
129// For operands that call into encoder functions, we need to use the `swapWord`
130// function to assure the correct word ordering on LE host. Note that
131// M68kMCCodeEmitter does massage _byte_ ordering of the final encoded
132// instruction but it assumes everything aligns on word boundaries. So things
133// will go wrong if we don't take care of the _word_ ordering here.
134template <unsigned Size>
135void M68kMCCodeEmitter::encodeRelocImm(const MCInst &MI, unsigned OpIdx,
136 unsigned InsertPos, APInt &Value,
138 const MCSubtargetInfo &STI) const {
139 using value_t = typename select_uint_t<Size>::type;
140 const MCOperand &MCO = MI.getOperand(OpIdx);
141 if (MCO.isImm()) {
142 Value |= M68k::swapWord<value_t>(static_cast<value_t>(MCO.getImm()));
143 } else if (MCO.isExpr()) {
144 const MCExpr *Expr = MCO.getExpr();
145
146 // Absolute address
147 int64_t Addr;
148 if (Expr->evaluateAsAbsolute(Addr)) {
149 Value |= M68k::swapWord<value_t>(static_cast<value_t>(Addr));
150 return;
151 }
152
153 // Relocatable address
154 unsigned InsertByte = getBytePosition<Size>(InsertPos);
155 addFixup(Fixups, InsertByte, Expr, MCFixup::getDataKindForSize(Size / 8));
156 }
157}
158
159template <unsigned Size>
160void M68kMCCodeEmitter::encodePCRelImm(const MCInst &MI, unsigned OpIdx,
161 unsigned InsertPos, APInt &Value,
162 SmallVectorImpl<MCFixup> &Fixups,
163 const MCSubtargetInfo &STI) const {
164 const MCOperand &MCO = MI.getOperand(OpIdx);
165 if (MCO.isImm()) {
166 using value_t = typename select_uint_t<Size>::type;
167 Value |= M68k::swapWord<value_t>(static_cast<value_t>(MCO.getImm()));
168 } else if (MCO.isExpr()) {
169 const MCExpr *Expr = MCO.getExpr();
170 unsigned InsertByte = getBytePosition<Size>(InsertPos);
171
172 // Special handlings for sizes smaller than a word.
173 if (Size < 16) {
174 int LabelOffset = 0;
175 if (InsertPos < 16)
176 // If the patch point is at the first word, PC is pointing at the
177 // next word.
178 LabelOffset = InsertByte - 2;
179 else if (InsertByte % 2)
180 // Otherwise the PC is pointing at the first byte of this word.
181 // So we need to consider the offset between PC and the fixup byte.
182 LabelOffset = 1;
183
184 if (LabelOffset)
186 Expr, MCConstantExpr::create(LabelOffset, Ctx), Ctx);
187 }
188
189 addFixup(Fixups, InsertByte, Expr, MCFixup::getDataKindForSize(Size / 8),
190 true);
191 }
192}
193
194void M68kMCCodeEmitter::encodeFPSYSSelect(const MCInst &MI, unsigned OpIdx,
195 unsigned InsertPos, APInt &Value,
196 SmallVectorImpl<MCFixup> &Fixups,
197 const MCSubtargetInfo &STI) const {
198 MCRegister FPSysReg = MI.getOperand(OpIdx).getReg();
199 switch (FPSysReg) {
200 case M68k::FPC:
201 Value = 0b100;
202 break;
203 case M68k::FPS:
204 Value = 0b010;
205 break;
206 case M68k::FPIAR:
207 Value = 0b001;
208 break;
209 default:
210 llvm_unreachable("Unrecognized FPSYS register");
211 }
212}
213
214void M68kMCCodeEmitter::encodeInverseMoveMask(
215 const MCInst &MI, unsigned OpIdx, unsigned InsertPos, APInt &Value,
216 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
217 const MCOperand &Op = MI.getOperand(OpIdx);
218 Value = llvm::reverseBits<uint16_t>((uint16_t)Op.getImm());
219}
220
221void M68kMCCodeEmitter::encodeScale(const MCInst &MI, unsigned OpIdx,
222 unsigned InsertPos, APInt &Value,
223 SmallVectorImpl<MCFixup> &Fixups,
224 const MCSubtargetInfo &STI) const {
225 const MCOperand &Op = MI.getOperand(OpIdx);
226 int64_t ScaleImm = Op.getImm();
227 assert(ScaleImm >= 1 && ScaleImm <= 8 && isPowerOf2_64(ScaleImm));
228 Value.clearAllBits();
229 Value |= Log2_64(ScaleImm);
230}
231
232void M68kMCCodeEmitter::encodeIndexSuppress(const MCInst &MI, unsigned OpIdx,
233 unsigned InsertPos, APInt &Value,
234 SmallVectorImpl<MCFixup> &Fixups,
235 const MCSubtargetInfo &STI) const {
236 // We suppress the index (i.e. IS = 1) if the index register is NoReg.
237 const MCOperand &Op = MI.getOperand(OpIdx);
238 MCRegister IndexReg = Op.getReg();
239 Value.setBitVal(/*Pos=*/0, !IndexReg.isValid());
240}
241
242void M68kMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &Op,
243 unsigned InsertPos, APInt &Value,
244 SmallVectorImpl<MCFixup> &Fixups,
245 const MCSubtargetInfo &STI) const {
246 // Register
247 if (Op.isReg()) {
248 MCRegister Reg = Op.getReg();
249 // NoReg means that we're ignoring it.
250 if (!Reg.isValid())
251 return;
252 const auto *RI = Ctx.getRegisterInfo();
253 Value |= RI->getEncodingValue(Reg);
254 // Setup the D/A bit
256 Value |= 0b1000;
257 } else if (Op.isImm()) {
258 // Immediate
259 Value |= static_cast<uint64_t>(Op.getImm());
260 } else if (Op.isExpr()) {
261 // Absolute address
262 int64_t Addr;
263 if (!Op.getExpr()->evaluateAsAbsolute(Addr))
264 report_fatal_error("Unsupported asm expression. Only absolute address "
265 "can be placed here.");
266 Value |= static_cast<uint64_t>(Addr);
267 } else {
268 llvm_unreachable("Unsupported operand type");
269 }
270}
271
272void M68kMCCodeEmitter::encodeInstruction(const MCInst &MI,
273 SmallVectorImpl<char> &CB,
274 SmallVectorImpl<MCFixup> &Fixups,
275 const MCSubtargetInfo &STI) const {
276 LLVM_DEBUG(dbgs() << "EncodeInstruction: " << MCII.getName(MI.getOpcode())
277 << "(" << MI.getOpcode() << ")\n");
278 (void)MCII;
279
280 // Try using the new method first.
281 APInt EncodedInst(16, 0U);
282 APInt Scratch(64, 0U); // One APInt word is enough.
283 getBinaryCodeForInstr(MI, Fixups, EncodedInst, Scratch, STI);
284
285 unsigned InstSize = EncodedInst.getBitWidth();
286 for (unsigned i = 0; i != InstSize; i += 16)
288 CB, static_cast<uint16_t>(EncodedInst.extractBitsAsZExtValue(16, i)),
290}
291
293 MCContext &Ctx) {
294 return new M68kMCCodeEmitter(MCII, Ctx);
295}
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind, bool PCRel=false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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.
Register Reg
MachineInstr unsigned OpIdx
#define LLVM_DEBUG(...)
Definition Debug.h:119
Class for arbitrary precision integers.
Definition APInt.h:78
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:343
MCCodeEmitter - Generic instruction encoding interface.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
const MCRegisterInfo * getRegisterInfo() const
Definition MCContext.h:411
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
static MCFixupKind getDataKindForSize(unsigned Size)
Return the generic fixup kind for a value with the given size.
Definition MCFixup.h:110
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Definition MCFixup.h:86
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
Definition MCInstrInfo.h:97
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
int64_t getImm() const
Definition MCInst.h:84
bool isImm() const
Definition MCInst.h:66
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
constexpr bool isValid() const
Definition MCRegister.h:84
Generic base class for all target subtargets.
constexpr bool isValid() const
Definition Register.h:112
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
LLVM Value Representation.
Definition Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool isAddressRegister(unsigned RegNo)
value_t swapWord(value_t Val)
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition Endian.h:96
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:558
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:284
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:337
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind)
DWARFExpression::Operation Op
constexpr T reverseBits(T Val)
Reverse the bits in Val.
Definition MathExtras.h:118
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