LLVM  14.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 
19 #include "llvm/MC/MCCodeEmitter.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCInstrInfo.h"
24 #include "llvm/MC/MCRegisterInfo.h"
26 #include "llvm/MC/MCSymbol.h"
27 #include "llvm/Support/Debug.h"
30 
31 using namespace llvm;
32 
33 #define DEBUG_TYPE "m68k-mccodeemitter"
34 
35 namespace {
36 class M68kMCCodeEmitter : public MCCodeEmitter {
37  M68kMCCodeEmitter(const M68kMCCodeEmitter &) = delete;
38  void operator=(const M68kMCCodeEmitter &) = delete;
39  const MCInstrInfo &MCII;
40  MCContext &Ctx;
41 
42 public:
43  M68kMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
44  : MCII(mcii), Ctx(ctx) {}
45 
46  ~M68kMCCodeEmitter() override {}
47 
48  // TableGen'erated function
49  const uint8_t *getGenInstrBeads(const MCInst &MI) const {
50  return M68k::getMCInstrBeads(MI.getOpcode());
51  }
52 
53  unsigned encodeBits(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
54  const MCInstrDesc &Desc, uint64_t &Buffer,
56  const MCSubtargetInfo &STI) const;
57 
58  unsigned encodeReg(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
59  const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset,
61  const MCSubtargetInfo &STI) const;
62 
63  unsigned encodeImm(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
64  const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset,
66  const MCSubtargetInfo &STI) const;
67 
68  void encodeInstruction(const MCInst &MI, raw_ostream &OS,
70  const MCSubtargetInfo &STI) const override;
71 };
72 
73 } // end anonymous namespace
74 
75 unsigned M68kMCCodeEmitter::encodeBits(unsigned ThisByte, uint8_t Bead,
76  const MCInst &MI,
77  const MCInstrDesc &Desc,
78  uint64_t &Buffer, unsigned Offset,
80  const MCSubtargetInfo &STI) const {
81  unsigned Num = 0;
82  switch (Bead & 0xF) {
83  case M68kBeads::Bits1:
84  Num = 1;
85  break;
86  case M68kBeads::Bits2:
87  Num = 2;
88  break;
89  case M68kBeads::Bits3:
90  Num = 3;
91  break;
92  case M68kBeads::Bits4:
93  Num = 4;
94  break;
95  }
96  unsigned char Val = (Bead & 0xF0) >> 4;
97 
98  LLVM_DEBUG(dbgs() << "\tEncodeBits"
99  << " Num: " << Num << " Val: 0x");
100  LLVM_DEBUG(dbgs().write_hex(Val) << "\n");
101 
102  Buffer |= (Val << Offset);
103 
104  return Num;
105 }
106 
107 unsigned M68kMCCodeEmitter::encodeReg(unsigned ThisByte, uint8_t Bead,
108  const MCInst &MI, const MCInstrDesc &Desc,
109  uint64_t &Buffer, unsigned Offset,
111  const MCSubtargetInfo &STI) const {
112  bool DA, Reg;
113  switch (Bead & 0xF) {
114  default:
115  llvm_unreachable("Unrecognized Bead code for register type");
116  case M68kBeads::DAReg:
117  Reg = true;
118  DA = true;
119  break;
120  case M68kBeads::DA:
121  Reg = false;
122  DA = true;
123  break;
124  case M68kBeads::DReg:
125  case M68kBeads::Reg:
126  Reg = true;
127  DA = false;
128  break;
129  }
130 
131  unsigned Op = (Bead & 0x70) >> 4;
132  bool Alt = (Bead & 0x80);
133  LLVM_DEBUG(dbgs() << "\tEncodeReg"
134  << " Op: " << Op << ", DA: " << DA << ", Reg: " << Reg
135  << ", Alt: " << Alt << "\n");
136 
137  auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op);
138  bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
139 
140  MCOperand MCO;
141  if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) {
142  if (IsPCRel) {
143  assert(Alt &&
144  "PCRel addresses use Alt bead register encoding by default");
145  MCO = MI.getOperand(MIOpIdx + M68k::PCRelIndex);
146  } else {
147  MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemIndex : M68k::MemBase));
148  }
149  } else {
150  assert(!Alt && "You cannot use Alt register with a simple operand");
151  MCO = MI.getOperand(MIOpIdx);
152  }
153 
154  unsigned RegNum = MCO.getReg();
155  auto RI = Ctx.getRegisterInfo();
156 
157  unsigned Written = 0;
158  if (Reg) {
159  uint32_t Val = RI->getEncodingValue(RegNum);
160  Buffer |= (Val & 7) << Offset;
161  Offset += 3;
162  Written += 3;
163  }
164 
165  if (DA) {
166  Buffer |= (uint64_t)M68kII::isAddressRegister(RegNum) << Offset;
167  Written++;
168  }
169 
170  return Written;
171 }
172 
173 static unsigned EmitConstant(uint64_t Val, unsigned Size, unsigned Pad,
174  uint64_t &Buffer, unsigned Offset) {
175  assert(Size + Offset <= 64 && isUIntN(Size, Val) && "Value does not fit");
176 
177  // Writing Value in host's endianness
178  Buffer |= (Val & ((1ULL << Size) - 1)) << Offset;
179  return Size + Pad;
180 }
181 
182 unsigned M68kMCCodeEmitter::encodeImm(unsigned ThisByte, uint8_t Bead,
183  const MCInst &MI, const MCInstrDesc &Desc,
184  uint64_t &Buffer, unsigned Offset,
186  const MCSubtargetInfo &STI) const {
187  unsigned ThisWord = ThisByte / 2;
188  unsigned Size = 0;
189  unsigned Pad = 0;
190  unsigned FixOffset = 0;
191  int64_t Addendum = 0;
192  bool NoExpr = false;
193 
194  unsigned Type = Bead & 0xF;
195  unsigned Op = (Bead & 0x70) >> 4;
196  bool Alt = (Bead & 0x80);
197 
198  auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op);
199  bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
200 
201  // The PC value upon instruction reading of a short jump will point to the
202  // next instruction, thus we need to compensate 2 bytes, which is the diff
203  // between the patch point and the PC.
204  if (IsPCRel && ThisWord == 0)
205  Addendum -= 2;
206 
207  switch (Type) {
208  // ??? what happens if it is not byte aligned
209  // ??? is it even possible
210  case M68kBeads::Disp8:
211  Size = 8;
212  Pad = 0;
213  FixOffset = ThisByte + 1;
214  Addendum += 1;
215  break;
216  case M68kBeads::Imm8:
217  Size = 8;
218  Pad = 8;
219  FixOffset = ThisByte;
220  break;
221  case M68kBeads::Imm16:
222  Size = 16;
223  Pad = 0;
224  FixOffset = ThisByte;
225  break;
226  case M68kBeads::Imm32:
227  Size = 32;
228  Pad = 0;
229  FixOffset = ThisByte;
230  break;
231  case M68kBeads::Imm3:
232  Size = 3;
233  Pad = 0;
234  NoExpr = true;
235  break;
236  }
237 
238  LLVM_DEBUG(dbgs() << "\tEncodeImm"
239  << " Op: " << Op << ", Size: " << Size << ", Alt: " << Alt
240  << "\n");
241 
242  MCOperand MCO;
243  if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) {
244 
245  if (IsPCRel) {
246  assert(!Alt && "You cannot use ALT operand with PCRel");
247  MCO = MI.getOperand(MIOpIdx + M68k::PCRelDisp);
248  } else {
249  MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemOuter : M68k::MemDisp));
250  }
251 
252  if (MCO.isExpr()) {
253  assert(!NoExpr && "Cannot use expression here");
254  const MCExpr *Expr = MCO.getExpr();
255 
256  // This only makes sense for PCRel instructions since PC points to the
257  // extension word and Disp8 for example is right justified and requires
258  // correction. E.g. R_68K_PC32 is calculated as S + A - P, P for Disp8
259  // will be EXTENSION_WORD + 1 thus we need to have A equal to 1 to
260  // compensate.
261  // TODO count extension words
262  if (IsPCRel && Addendum != 0) {
264  Expr, MCConstantExpr::create(Addendum, Ctx), Ctx);
265  }
266 
267  Fixups.push_back(MCFixup::create(
268  FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc()));
269  // Write zeros
270  return EmitConstant(0, Size, Pad, Buffer, Offset);
271  }
272 
273  } else {
274  MCO = MI.getOperand(MIOpIdx);
275  if (MCO.isExpr()) {
276  assert(!NoExpr && "Cannot use expression here");
277  const MCExpr *Expr = MCO.getExpr();
278 
279  if (Addendum != 0) {
281  Expr, MCConstantExpr::create(Addendum, Ctx), Ctx);
282  }
283 
284  Fixups.push_back(MCFixup::create(
285  FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc()));
286  // Write zeros
287  return EmitConstant(0, Size, Pad, Buffer, Offset);
288  }
289  }
290 
291  int64_t I = MCO.getImm();
292 
293  // Store 8 as 0, thus making range 1-8
294  if (Type == M68kBeads::Imm3 && Alt) {
295  assert(I && "Cannot encode Alt Imm3 zero value");
296  I %= 8;
297  } else {
298  assert(isIntN(Size, I));
299  }
300 
301  uint64_t Imm = I;
302 
303  // 32 bit Imm requires HI16 first then LO16
304  if (Size == 32) {
305  Offset += EmitConstant((Imm >> 16) & 0xFFFF, 16, Pad, Buffer, Offset);
306  EmitConstant(Imm & 0xFFFF, 16, Pad, Buffer, Offset);
307  return Size;
308  }
309 
310  return EmitConstant(Imm & ((1ULL << Size) - 1), Size, Pad, Buffer, Offset);
311 }
312 
313 #include "M68kGenMCCodeBeads.inc"
314 
315 void M68kMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
317  const MCSubtargetInfo &STI) const {
318  unsigned Opcode = MI.getOpcode();
319  const MCInstrDesc &Desc = MCII.get(Opcode);
320 
321  LLVM_DEBUG(dbgs() << "EncodeInstruction: " << MCII.getName(Opcode) << "("
322  << Opcode << ")\n");
323 
324  const uint8_t *Beads = getGenInstrBeads(MI);
325  if (!Beads || !*Beads) {
326  llvm_unreachable("*** Instruction does not have Beads defined");
327  }
328 
329  uint64_t Buffer = 0;
330  unsigned Offset = 0;
331  unsigned ThisByte = 0;
332 
333  for (uint8_t Bead = *Beads; Bead; Bead = *++Beads) {
334  // Check for control beads
335  if (!(Bead & 0xF)) {
336  switch (Bead >> 4) {
337  case M68kBeads::Ignore:
338  continue;
339  }
340  }
341 
342  switch (Bead & 0xF) {
343  default:
344  llvm_unreachable("Unknown Bead code");
345  break;
346  case M68kBeads::Bits1:
347  case M68kBeads::Bits2:
348  case M68kBeads::Bits3:
349  case M68kBeads::Bits4:
350  Offset +=
351  encodeBits(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
352  break;
353  case M68kBeads::DAReg:
354  case M68kBeads::DA:
355  case M68kBeads::DReg:
356  case M68kBeads::Reg:
357  Offset +=
358  encodeReg(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
359  break;
360  case M68kBeads::Disp8:
361  case M68kBeads::Imm8:
362  case M68kBeads::Imm16:
363  case M68kBeads::Imm32:
364  case M68kBeads::Imm3:
365  Offset +=
366  encodeImm(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
367  break;
368  }
369 
370  // Since M68k is Big Endian we need to rotate each instruction word
371  while (Offset / 16) {
372  support::endian::write<uint16_t>(OS, Buffer, support::big);
373  Buffer >>= 16;
374  Offset -= 16;
375  ThisByte += 2;
376  }
377  }
378 
379  assert(Offset == 0 && "M68k Instructions are % 2 bytes");
380  assert((ThisByte && !(ThisByte % 2)) && "M68k Instructions are % 2 bytes");
381 }
382 
384  const MCRegisterInfo &MRI,
385  MCContext &Ctx) {
386  return new M68kMCCodeEmitter(MCII, Ctx);
387 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:105
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
Reg
unsigned Reg
Definition: MachineSink.cpp:1566
llvm::M68kBeads::Imm3
@ Imm3
Definition: M68kBaseInfo.h:66
llvm::M68kBeads::Reg
@ Reg
Definition: M68kBaseInfo.h:60
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:72
MCCodeEmitter.h
llvm::MCConstantExpr::create
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
llvm::MCFixup::create
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:87
llvm::M68k::MemDisp
@ MemDisp
Definition: M68kBaseInfo.h:41
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::M68k::MemBase
@ MemBase
Definition: M68kBaseInfo.h:41
llvm::M68kBeads::DReg
@ DReg
Definition: M68kBaseInfo.h:61
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::M68kBeads::DAReg
@ DAReg
Definition: M68kBaseInfo.h:58
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
MCContext.h
MCInstrInfo.h
llvm::MCOperand::getImm
int64_t getImm() const
Definition: MCInst.h:80
MCSymbol.h
llvm::M68kBeads::Imm8
@ Imm8
Definition: M68kBaseInfo.h:63
MCInst.h
llvm::MCInstrDesc
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:195
llvm::isUIntN
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:455
llvm::AArch64::Fixups
Fixups
Definition: AArch64FixupKinds.h:17
MCSubtargetInfo.h
llvm::M68k::PCRelDisp
@ PCRelDisp
Definition: M68kBaseInfo.h:48
llvm::M68kBeads::Bits1
@ Bits1
Definition: M68kBaseInfo.h:54
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::MCOI::OPERAND_PCREL
@ OPERAND_PCREL
Definition: MCInstrDesc.h:61
llvm::M68kBeads::Bits3
@ Bits3
Definition: M68kBaseInfo.h:56
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
M68kMCCodeEmitter.h
llvm::M68k::getMCInstrBeads
const uint8_t * getMCInstrBeads(unsigned)
llvm::M68kBeads::Bits4
@ Bits4
Definition: M68kBaseInfo.h:57
llvm::getFixupForSize
static MCFixupKind getFixupForSize(unsigned Size, bool isPCRel)
Definition: M68kFixupKinds.h:38
M68kMCTargetDesc.h
uint64_t
EmitConstant
static unsigned EmitConstant(uint64_t Val, unsigned Size, unsigned Pad, uint64_t &Buffer, unsigned Offset)
Definition: M68kMCCodeEmitter.cpp:173
llvm::M68kII::hasMultiMIOperands
static bool hasMultiMIOperands(unsigned Op, unsigned LogicalOpIdx)
Definition: M68kBaseInfo.h:200
llvm::MCOperandInfo::OperandType
uint8_t OperandType
Information about the type of the operand.
Definition: MCInstrDesc.h:95
M68kFixupKinds.h
I
#define I(x, y, z)
Definition: MD5.cpp:59
MCRegisterInfo.h
llvm::M68k::PCRelIndex
@ PCRelIndex
Definition: M68kBaseInfo.h:48
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MCInstrDesc::OpInfo
const MCOperandInfo * OpInfo
Definition: MCInstrDesc.h:206
llvm::write_hex
void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, Optional< size_t > Width=None)
Definition: NativeFormatting.cpp:133
llvm::MCBinaryExpr::createAdd
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:524
llvm::M68kBeads::DA
@ DA
Definition: M68kBaseInfo.h:59
llvm::M68kBeads::Bits2
@ Bits2
Definition: M68kBaseInfo.h:55
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
uint32_t
llvm::MCRegisterInfo
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Definition: MCRegisterInfo.h:135
llvm::M68kBeads::Disp8
@ Disp8
Definition: M68kBaseInfo.h:62
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::M68kBeads::Imm16
@ Imm16
Definition: M68kBaseInfo.h:64
llvm::MCInstrInfo
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:25
EndianStream.h
llvm::MCCodeEmitter
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
llvm::createM68kMCCodeEmitter
MCCodeEmitter * createM68kMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx)
Definition: M68kMCCodeEmitter.cpp:383
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:324
llvm::MCOperand::getExpr
const MCExpr * getExpr() const
Definition: MCInst.h:114
llvm::MCOperand::isExpr
bool isExpr() const
Definition: MCInst.h:65
M68kBaseInfo.h
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:43
llvm::M68kII::isAddressRegister
static bool isAddressRegister(unsigned RegNo)
Definition: M68kBaseInfo.h:176
llvm::MCOperand
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
Alt
bool Alt
Definition: README.txt:468
raw_ostream.h
llvm::M68kBeads::Imm32
@ Imm32
Definition: M68kBaseInfo.h:65
MCExpr.h
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:75
llvm::MCExpr
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
Debug.h
llvm::support::big
@ big
Definition: Endian.h:27
llvm::MCOperand::getReg
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
llvm::M68k::MemOuter
@ MemOuter
Definition: M68kBaseInfo.h:41
llvm::M68k::MemIndex
@ MemIndex
Definition: M68kBaseInfo.h:41
llvm::M68kBeads::Ignore
@ Ignore
Definition: M68kBaseInfo.h:72