LLVM 22.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
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
71public:
72 M68kMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
73 : MCII(mcii), Ctx(ctx) {}
74
75 ~M68kMCCodeEmitter() override {}
76
79 const MCSubtargetInfo &STI) const override;
80};
81
82} // end anonymous namespace
83
84#include "M68kGenMCCodeEmitter.inc"
85
86// Select the proper unsigned integer type from a bit size.
87template <unsigned Size> struct select_uint_t {
88 using type = typename std::conditional<
89 Size == 8, uint8_t,
90 typename std::conditional<
91 Size == 16, uint16_t,
92 typename std::conditional<Size == 32, uint32_t,
94};
95
96// Figure out which byte we're at in big endian mode.
97template <unsigned Size> static unsigned getBytePosition(unsigned BitPos) {
98 if (Size % 16) {
99 return static_cast<unsigned>(BitPos / 8 + ((BitPos & 0b1111) < 8 ? 1 : -1));
100 } else {
101 assert(!(BitPos & 0b1111) && "Not aligned to word boundary?");
102 return BitPos / 8;
103 }
104}
105
107 const MCExpr *Value, uint16_t Kind, bool PCRel = false) {
108 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));
109}
110
111// We need special handlings for relocatable & pc-relative operands that are
112// larger than a word.
113// A M68k instruction is aligned by word (16 bits). That means, 32-bit
114// (& 64-bit) immediate values are separated into hi & lo words and placed
115// at lower & higher addresses, respectively. For immediate values that can
116// be easily expressed in TG, we explicitly rotate the word ordering like
117// this:
118// ```
119// (ascend (slice "$imm", 31, 16), (slice "$imm", 15, 0))
120// ```
121// For operands that call into encoder functions, we need to use the `swapWord`
122// function to assure the correct word ordering on LE host. Note that
123// M68kMCCodeEmitter does massage _byte_ ordering of the final encoded
124// instruction but it assumes everything aligns on word boundaries. So things
125// will go wrong if we don't take care of the _word_ ordering here.
126template <unsigned Size>
127void M68kMCCodeEmitter::encodeRelocImm(const MCInst &MI, unsigned OpIdx,
128 unsigned InsertPos, APInt &Value,
130 const MCSubtargetInfo &STI) const {
131 using value_t = typename select_uint_t<Size>::type;
132 const MCOperand &MCO = MI.getOperand(OpIdx);
133 if (MCO.isImm()) {
134 Value |= M68k::swapWord<value_t>(static_cast<value_t>(MCO.getImm()));
135 } else if (MCO.isExpr()) {
136 const MCExpr *Expr = MCO.getExpr();
137
138 // Absolute address
139 int64_t Addr;
140 if (Expr->evaluateAsAbsolute(Addr)) {
141 Value |= M68k::swapWord<value_t>(static_cast<value_t>(Addr));
142 return;
143 }
144
145 // Relocatable address
146 unsigned InsertByte = getBytePosition<Size>(InsertPos);
147 addFixup(Fixups, InsertByte, Expr, MCFixup::getDataKindForSize(Size / 8));
148 }
149}
150
151template <unsigned Size>
152void M68kMCCodeEmitter::encodePCRelImm(const MCInst &MI, unsigned OpIdx,
153 unsigned InsertPos, APInt &Value,
155 const MCSubtargetInfo &STI) const {
156 const MCOperand &MCO = MI.getOperand(OpIdx);
157 if (MCO.isImm()) {
158 using value_t = typename select_uint_t<Size>::type;
159 Value |= M68k::swapWord<value_t>(static_cast<value_t>(MCO.getImm()));
160 } else if (MCO.isExpr()) {
161 const MCExpr *Expr = MCO.getExpr();
162 unsigned InsertByte = getBytePosition<Size>(InsertPos);
163
164 // Special handlings for sizes smaller than a word.
165 if (Size < 16) {
166 int LabelOffset = 0;
167 if (InsertPos < 16)
168 // If the patch point is at the first word, PC is pointing at the
169 // next word.
170 LabelOffset = InsertByte - 2;
171 else if (InsertByte % 2)
172 // Otherwise the PC is pointing at the first byte of this word.
173 // So we need to consider the offset between PC and the fixup byte.
174 LabelOffset = 1;
175
176 if (LabelOffset)
178 Expr, MCConstantExpr::create(LabelOffset, Ctx), Ctx);
179 }
180
181 addFixup(Fixups, InsertByte, Expr, MCFixup::getDataKindForSize(Size / 8),
182 true);
183 }
184}
185
186void M68kMCCodeEmitter::encodeFPSYSSelect(const MCInst &MI, unsigned OpIdx,
187 unsigned InsertPos, APInt &Value,
189 const MCSubtargetInfo &STI) const {
190 MCRegister FPSysReg = MI.getOperand(OpIdx).getReg();
191 switch (FPSysReg) {
192 case M68k::FPC:
193 Value = 0b100;
194 break;
195 case M68k::FPS:
196 Value = 0b010;
197 break;
198 case M68k::FPIAR:
199 Value = 0b001;
200 break;
201 default:
202 llvm_unreachable("Unrecognized FPSYS register");
203 }
204}
205
206void M68kMCCodeEmitter::encodeInverseMoveMask(
207 const MCInst &MI, unsigned OpIdx, unsigned InsertPos, APInt &Value,
208 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
209 const MCOperand &Op = MI.getOperand(OpIdx);
210 Value = llvm::reverseBits<uint16_t>((uint16_t)Op.getImm());
211}
212
213void M68kMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &Op,
214 unsigned InsertPos, APInt &Value,
216 const MCSubtargetInfo &STI) const {
217 // Register
218 if (Op.isReg()) {
219 unsigned RegNum = Op.getReg();
220 const auto *RI = Ctx.getRegisterInfo();
221 Value |= RI->getEncodingValue(RegNum);
222 // Setup the D/A bit
223 if (M68kII::isAddressRegister(RegNum))
224 Value |= 0b1000;
225 } else if (Op.isImm()) {
226 // Immediate
227 Value |= static_cast<uint64_t>(Op.getImm());
228 } else if (Op.isExpr()) {
229 // Absolute address
230 int64_t Addr;
231 if (!Op.getExpr()->evaluateAsAbsolute(Addr))
232 report_fatal_error("Unsupported asm expression. Only absolute address "
233 "can be placed here.");
234 Value |= static_cast<uint64_t>(Addr);
235 } else {
236 llvm_unreachable("Unsupported operand type");
237 }
238}
239
240void M68kMCCodeEmitter::encodeInstruction(const MCInst &MI,
243 const MCSubtargetInfo &STI) const {
244 LLVM_DEBUG(dbgs() << "EncodeInstruction: " << MCII.getName(MI.getOpcode())
245 << "(" << MI.getOpcode() << ")\n");
246 (void)MCII;
247
248 // Try using the new method first.
249 APInt EncodedInst(16, 0U);
250 APInt Scratch(64, 0U); // One APInt word is enough.
251 getBinaryCodeForInstr(MI, Fixups, EncodedInst, Scratch, STI);
252
253 unsigned InstSize = EncodedInst.getBitWidth();
254 for (unsigned i = 0; i != InstSize; i += 16)
255 support::endian::write<uint16_t>(
256 CB, static_cast<uint16_t>(EncodedInst.extractBitsAsZExtValue(16, i)),
258}
259
261 MCContext &Ctx) {
262 return new M68kMCCodeEmitter(MCII, Ctx);
263}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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)
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind, bool PCRel=false)
This file contains the declarations for the code emitter which are useful outside of the emitter itse...
This file provides M68k specific target descriptions.
MachineInstr unsigned OpIdx
#define LLVM_DEBUG(...)
Definition: Debug.h:119
Class for arbitrary precision integers.
Definition: APInt.h:78
This class represents an Operation in the Expression.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:343
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:23
virtual void encodeInstruction(const MCInst &Inst, SmallVectorImpl< char > &CB, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
Encode the given Inst to bytes and append to CB.
MCCodeEmitter & operator=(const MCCodeEmitter &)=delete
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
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
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
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
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:574
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)
Definition: M68kBaseInfo.h:252
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
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