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 
14 #include "MCTargetDesc/M68kMCCodeEmitter.h"
15 #include "MCTargetDesc/M68kBaseInfo.h"
16 #include "MCTargetDesc/M68kFixupKinds.h"
17 #include "MCTargetDesc/M68kMCTargetDesc.h"
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"
25 #include "llvm/MC/MCSubtargetInfo.h"
26 #include "llvm/MC/MCSymbol.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/EndianStream.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include <type_traits>
31 
32 using namespace llvm;
33 
34 #define DEBUG_TYPE "m68k-mccodeemitter"
35 
36 namespace {
37 class 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,
49                          SmallVectorImpl<MCFixup> &Fixups,
50                          const MCSubtargetInfo &STI) const;
51 
52   template <unsigned Size>
53   void encodeRelocImm(const MCInst &MI, unsigned OpIdx, unsigned InsertPos,
54                       APInt &Value, SmallVectorImpl<MCFixup> &Fixups,
55                       const MCSubtargetInfo &STI) const;
56 
57   template <unsigned Size>
58   void encodePCRelImm(const MCInst &MI, unsigned OpIdx, unsigned InsertPos,
59                       APInt &Value, SmallVectorImpl<MCFixup> &Fixups,
60                       const MCSubtargetInfo &STI) const;
61 
62 public:
63   M68kMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
64       : MCII(mcii), Ctx(ctx) {}
65 
66   ~M68kMCCodeEmitter() override {}
67 
68   // TableGen'erated function
69   const uint8_t *getGenInstrBeads(const MCInst &MI) const {
70     return M68k::getMCInstrBeads(MI.getOpcode());
71   }
72 
73   unsigned encodeBits(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
74                       const MCInstrDesc &Desc, uint64_t &Buffer,
75                       unsigned Offset, SmallVectorImpl<MCFixup> &Fixups,
76                       const MCSubtargetInfo &STI) const;
77 
78   unsigned encodeReg(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
79                      const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset,
80                      SmallVectorImpl<MCFixup> &Fixups,
81                      const MCSubtargetInfo &STI) const;
82 
83   unsigned encodeImm(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
84                      const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset,
85                      SmallVectorImpl<MCFixup> &Fixups,
86                      const MCSubtargetInfo &STI) const;
87 
88   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
89                          SmallVectorImpl<MCFixup> &Fixups,
90                          const MCSubtargetInfo &STI) const override;
91 };
92 
93 } // end anonymous namespace
94 
95 #include "M68kGenMCCodeEmitter.inc"
96 
97 // Select the proper unsigned integer type from a bit size.
98 template <unsigned Size> struct select_uint_t {
99   using type = typename std::conditional<
100       Size == 8, uint8_t,
101       typename std::conditional<
102           Size == 16, uint16_t,
103           typename std::conditional<Size == 32, uint32_t,
104                                     uint64_t>::type>::type>::type;
105 };
106 
107 // On a LE host:
108 // MSB                   LSB    MSB                   LSB
109 // | 0x12 0x34 | 0xAB 0xCD | -> | 0xAB 0xCD | 0x12 0x34 |
110 // (On a BE host nothing changes)
111 template <typename value_t> static value_t swapWord(value_t Val) {
112   const unsigned NumWords = sizeof(Val) / 2;
113   if (NumWords <= 1)
114     return Val;
115   Val = support::endian::byte_swap(Val, support::big);
116   value_t NewVal = 0;
117   for (unsigned i = 0U; i != NumWords; ++i) {
118     uint16_t Part = (Val >> (i * 16)) & 0xFFFF;
119     Part = support::endian::byte_swap(Part, support::big);
120     NewVal |= (Part << (i * 16));
121   }
122   return NewVal;
123 }
124 
125 // Figure out which byte we're at in big endian mode.
126 template <unsigned Size> static unsigned getBytePosition(unsigned BitPos) {
127   if (Size % 16) {
128     return static_cast<unsigned>(BitPos / 8 + ((BitPos & 0b1111) < 8 ? 1 : -1));
129   } else {
130     assert(!(BitPos & 0b1111) && "Not aligned to word boundary?");
131     return BitPos / 8;
132   }
133 }
134 
135 // We need special handlings for relocatable & pc-relative operands that are
136 // larger than a word.
137 // A M68k instruction is aligned by word (16 bits). That means, 32-bit
138 // (& 64-bit) immediate values are separated into hi & lo words and placed
139 // at lower & higher addresses, respectively. For immediate values that can
140 // be easily expressed in TG, we explicitly rotate the word ordering like
141 // this:
142 // ```
143 // (ascend (slice "$imm", 31, 16), (slice "$imm", 15, 0))
144 // ```
145 // For operands that call into encoder functions, we need to use the `swapWord`
146 // function to assure the correct word ordering on LE host. Note that
147 // M68kMCCodeEmitter does massage _byte_ ordering of the final encoded
148 // instruction but it assumes everything aligns on word boundaries. So things
149 // will go wrong if we don't take care of the _word_ ordering here.
150 template <unsigned Size>
151 void M68kMCCodeEmitter::encodeRelocImm(const MCInst &MI, unsigned OpIdx,
152                                        unsigned InsertPos, APInt &Value,
153                                        SmallVectorImpl<MCFixup> &Fixups,
154                                        const MCSubtargetInfo &STI) const {
155   using value_t = typename select_uint_t<Size>::type;
156   const MCOperand &MCO = MI.getOperand(OpIdx);
157   if (MCO.isImm()) {
158     Value |= swapWord<value_t>(static_cast<value_t>(MCO.getImm()));
159   } else if (MCO.isExpr()) {
160     const MCExpr *Expr = MCO.getExpr();
161 
162     // Absolute address
163     int64_t Addr;
164     if (Expr->evaluateAsAbsolute(Addr)) {
165       Value |= swapWord<value_t>(static_cast<value_t>(Addr));
166       return;
167     }
168 
169     // Relocatable address
170     unsigned InsertByte = getBytePosition<Size>(InsertPos);
171     Fixups.push_back(MCFixup::create(InsertByte, Expr,
172                                      getFixupForSize(Size, /*IsPCRel=*/false),
173                                      MI.getLoc()));
174   }
175 }
176 
177 template <unsigned Size>
178 void M68kMCCodeEmitter::encodePCRelImm(const MCInst &MI, unsigned OpIdx,
179                                        unsigned InsertPos, APInt &Value,
180                                        SmallVectorImpl<MCFixup> &Fixups,
181                                        const MCSubtargetInfo &STI) const {
182   const MCOperand &MCO = MI.getOperand(OpIdx);
183   if (MCO.isImm()) {
184     using value_t = typename select_uint_t<Size>::type;
185     Value |= swapWord<value_t>(static_cast<value_t>(MCO.getImm()));
186   } else if (MCO.isExpr()) {
187     const MCExpr *Expr = MCO.getExpr();
188     unsigned InsertByte = getBytePosition<Size>(InsertPos);
189 
190     // Special handlings for sizes smaller than a word.
191     if (Size < 16) {
192       int LabelOffset = 0;
193       if (InsertPos < 16)
194         // If the patch point is at the first word, PC is pointing at the
195         // next word.
196         LabelOffset = InsertByte - 2;
197       else if (InsertByte % 2)
198         // Otherwise the PC is pointing at the first byte of this word.
199         // So we need to consider the offset between PC and the fixup byte.
200         LabelOffset = 1;
201 
202       if (LabelOffset)
203         Expr = MCBinaryExpr::createAdd(
204             Expr, MCConstantExpr::create(LabelOffset, Ctx), Ctx);
205     }
206 
207     Fixups.push_back(MCFixup::create(InsertByte, Expr,
208                                      getFixupForSize(Size, /*IsPCRel=*/true),
209                                      MI.getLoc()));
210   }
211 }
212 
213 void M68kMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &Op,
214                                           unsigned InsertPos, APInt &Value,
215                                           SmallVectorImpl<MCFixup> &Fixups,
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 
240 unsigned M68kMCCodeEmitter::encodeBits(unsigned ThisByte, uint8_t Bead,
241                                        const MCInst &MI,
242                                        const MCInstrDesc &Desc,
243                                        uint64_t &Buffer, unsigned Offset,
244                                        SmallVectorImpl<MCFixup> &Fixups,
245                                        const MCSubtargetInfo &STI) const {
246   unsigned Num = 0;
247   switch (Bead & 0xF) {
248   case M68kBeads::Bits1:
249     Num = 1;
250     break;
251   case M68kBeads::Bits2:
252     Num = 2;
253     break;
254   case M68kBeads::Bits3:
255     Num = 3;
256     break;
257   case M68kBeads::Bits4:
258     Num = 4;
259     break;
260   }
261   unsigned char Val = (Bead & 0xF0) >> 4;
262 
263   LLVM_DEBUG(dbgs() << "\tEncodeBits"
264                     << " Num: " << Num << " Val: 0x");
265   LLVM_DEBUG(dbgs().write_hex(Val) << "\n");
266 
267   Buffer |= (Val << Offset);
268 
269   return Num;
270 }
271 
272 unsigned M68kMCCodeEmitter::encodeReg(unsigned ThisByte, uint8_t Bead,
273                                       const MCInst &MI, const MCInstrDesc &Desc,
274                                       uint64_t &Buffer, unsigned Offset,
275                                       SmallVectorImpl<MCFixup> &Fixups,
276                                       const MCSubtargetInfo &STI) const {
277   bool DA, Reg;
278   switch (Bead & 0xF) {
279   default:
280     llvm_unreachable("Unrecognized Bead code for register type");
281   case M68kBeads::DAReg:
282     Reg = true;
283     DA = true;
284     break;
285   case M68kBeads::DA:
286     Reg = false;
287     DA = true;
288     break;
289   case M68kBeads::DReg:
290   case M68kBeads::Reg:
291     Reg = true;
292     DA = false;
293     break;
294   }
295 
296   unsigned Op = (Bead & 0x70) >> 4;
297   bool Alt = (Bead & 0x80);
298   LLVM_DEBUG(dbgs() << "\tEncodeReg"
299                     << " Op: " << Op << ", DA: " << DA << ", Reg: " << Reg
300                     << ", Alt: " << Alt << "\n");
301 
302   auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op);
303   bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
304 
305   MCOperand MCO;
306   if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) {
307     if (IsPCRel) {
308       assert(Alt &&
309              "PCRel addresses use Alt bead register encoding by default");
310       MCO = MI.getOperand(MIOpIdx + M68k::PCRelIndex);
311     } else {
312       MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemIndex : M68k::MemBase));
313     }
314   } else {
315     assert(!Alt && "You cannot use Alt register with a simple operand");
316     MCO = MI.getOperand(MIOpIdx);
317   }
318 
319   unsigned RegNum = MCO.getReg();
320   auto RI = Ctx.getRegisterInfo();
321 
322   unsigned Written = 0;
323   if (Reg) {
324     uint32_t Val = RI->getEncodingValue(RegNum);
325     Buffer |= (Val & 7) << Offset;
326     Offset += 3;
327     Written += 3;
328   }
329 
330   if (DA) {
331     Buffer |= (uint64_t)M68kII::isAddressRegister(RegNum) << Offset;
332     Written++;
333   }
334 
335   return Written;
336 }
337 
338 static unsigned EmitConstant(uint64_t Val, unsigned Size, unsigned Pad,
339                              uint64_t &Buffer, unsigned Offset) {
340   assert(Size + Offset <= 64 && isUIntN(Size, Val) && "Value does not fit");
341 
342   // Writing Value in host's endianness
343   Buffer |= (Val & ((1ULL << Size) - 1)) << Offset;
344   return Size + Pad;
345 }
346 
347 unsigned M68kMCCodeEmitter::encodeImm(unsigned ThisByte, uint8_t Bead,
348                                       const MCInst &MI, const MCInstrDesc &Desc,
349                                       uint64_t &Buffer, unsigned Offset,
350                                       SmallVectorImpl<MCFixup> &Fixups,
351                                       const MCSubtargetInfo &STI) const {
352   unsigned ThisWord = ThisByte / 2;
353   unsigned Size = 0;
354   unsigned Pad = 0;
355   unsigned FixOffset = 0;
356   int64_t Addendum = 0;
357   bool NoExpr = false;
358 
359   unsigned Type = Bead & 0xF;
360   unsigned Op = (Bead & 0x70) >> 4;
361   bool Alt = (Bead & 0x80);
362 
363   auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op);
364   bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
365 
366   // The PC value upon instruction reading of a short jump will point to the
367   // next instruction, thus we need to compensate 2 bytes, which is the diff
368   // between the patch point and the PC.
369   if (IsPCRel && ThisWord == 0)
370     Addendum -= 2;
371 
372   switch (Type) {
373   // ??? what happens if it is not byte aligned
374   // ??? is it even possible
375   case M68kBeads::Disp8:
376     Size = 8;
377     Pad = 0;
378     FixOffset = ThisByte + 1;
379     Addendum += 1;
380     break;
381   case M68kBeads::Imm8:
382     Size = 8;
383     Pad = 8;
384     FixOffset = ThisByte;
385     break;
386   case M68kBeads::Imm16:
387     Size = 16;
388     Pad = 0;
389     FixOffset = ThisByte;
390     break;
391   case M68kBeads::Imm32:
392     Size = 32;
393     Pad = 0;
394     FixOffset = ThisByte;
395     break;
396   case M68kBeads::Imm3:
397     Size = 3;
398     Pad = 0;
399     NoExpr = true;
400     break;
401   }
402 
403   LLVM_DEBUG(dbgs() << "\tEncodeImm"
404                     << " Op: " << Op << ", Size: " << Size << ", Alt: " << Alt
405                     << "\n");
406 
407   MCOperand MCO;
408   if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) {
409 
410     if (IsPCRel) {
411       assert(!Alt && "You cannot use ALT operand with PCRel");
412       MCO = MI.getOperand(MIOpIdx + M68k::PCRelDisp);
413     } else {
414       MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemOuter : M68k::MemDisp));
415     }
416 
417     if (MCO.isExpr()) {
418       assert(!NoExpr && "Cannot use expression here");
419       const MCExpr *Expr = MCO.getExpr();
420 
421       // This only makes sense for PCRel instructions since PC points to the
422       // extension word and Disp8 for example is right justified and requires
423       // correction. E.g. R_68K_PC32 is calculated as S + A - P, P for Disp8
424       // will be EXTENSION_WORD + 1 thus we need to have A equal to 1 to
425       // compensate.
426       // TODO count extension words
427       if (IsPCRel && Addendum != 0) {
428         Expr = MCBinaryExpr::createAdd(
429             Expr, MCConstantExpr::create(Addendum, Ctx), Ctx);
430       }
431 
432       Fixups.push_back(MCFixup::create(
433           FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc()));
434       // Write zeros
435       return EmitConstant(0, Size, Pad, Buffer, Offset);
436     }
437 
438   } else {
439     MCO = MI.getOperand(MIOpIdx);
440     if (MCO.isExpr()) {
441       assert(!NoExpr && "Cannot use expression here");
442       const MCExpr *Expr = MCO.getExpr();
443 
444       if (Addendum != 0) {
445         Expr = MCBinaryExpr::createAdd(
446             Expr, MCConstantExpr::create(Addendum, Ctx), Ctx);
447       }
448 
449       Fixups.push_back(MCFixup::create(
450           FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc()));
451       // Write zeros
452       return EmitConstant(0, Size, Pad, Buffer, Offset);
453     }
454   }
455 
456   int64_t I = MCO.getImm();
457 
458   // Store 8 as 0, thus making range 1-8
459   if (Type == M68kBeads::Imm3 && Alt) {
460     assert(I && "Cannot encode Alt Imm3 zero value");
461     I %= 8;
462   } else {
463     assert(isIntN(Size, I));
464   }
465 
466   uint64_t Imm = I;
467 
468   // 32 bit Imm requires HI16 first then LO16
469   if (Size == 32) {
470     Offset += EmitConstant((Imm >> 16) & 0xFFFF, 16, Pad, Buffer, Offset);
471     EmitConstant(Imm & 0xFFFF, 16, Pad, Buffer, Offset);
472     return Size;
473   }
474 
475   return EmitConstant(Imm & ((1ULL << Size) - 1), Size, Pad, Buffer, Offset);
476 }
477 
478 #include "M68kGenMCCodeBeads.inc"
479 
480 void M68kMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
481                                           SmallVectorImpl<MCFixup> &Fixups,
482                                           const MCSubtargetInfo &STI) const {
483   unsigned Opcode = MI.getOpcode();
484   const MCInstrDesc &Desc = MCII.get(Opcode);
485 
486   LLVM_DEBUG(dbgs() << "EncodeInstruction: " << MCII.getName(Opcode) << "("
487                     << Opcode << ")\n");
488 
489   // Try using the new method first.
490   APInt EncodedInst(16, 0U);
491   APInt Scratch(16, 0U);
492   getBinaryCodeForInstr(MI, Fixups, EncodedInst, Scratch, STI);
493   if (EncodedInst.getBitWidth()) {
494     LLVM_DEBUG(dbgs() << "Instruction " << MCII.getName(Opcode) << "(" << Opcode
495                       << ") is using the new code emitter\n");
496     ArrayRef<uint64_t> Data(EncodedInst.getRawData(),
497                             EncodedInst.getNumWords());
498     int64_t InstSize = EncodedInst.getBitWidth();
499     for (uint64_t Word : Data) {
500       for (int i = 0; i < 4 && InstSize > 0; ++i, InstSize -= 16) {
501         support::endian::write<uint16_t>(OS, static_cast<uint16_t>(Word),
502                                          support::big);
503         Word >>= 16;
504       }
505     }
506     return;
507   }
508 
509   const uint8_t *Beads = getGenInstrBeads(MI);
510   if (!Beads || !*Beads) {
511     llvm_unreachable("*** Instruction does not have Beads defined");
512   }
513 
514   uint64_t Buffer = 0;
515   unsigned Offset = 0;
516   unsigned ThisByte = 0;
517 
518   for (uint8_t Bead = *Beads; Bead; Bead = *++Beads) {
519     // Check for control beads
520     if (!(Bead & 0xF)) {
521       switch (Bead >> 4) {
522       case M68kBeads::Ignore:
523         continue;
524       }
525     }
526 
527     switch (Bead & 0xF) {
528     default:
529       llvm_unreachable("Unknown Bead code");
530       break;
531     case M68kBeads::Bits1:
532     case M68kBeads::Bits2:
533     case M68kBeads::Bits3:
534     case M68kBeads::Bits4:
535       Offset +=
536           encodeBits(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
537       break;
538     case M68kBeads::DAReg:
539     case M68kBeads::DA:
540     case M68kBeads::DReg:
541     case M68kBeads::Reg:
542       Offset +=
543           encodeReg(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
544       break;
545     case M68kBeads::Disp8:
546     case M68kBeads::Imm8:
547     case M68kBeads::Imm16:
548     case M68kBeads::Imm32:
549     case M68kBeads::Imm3:
550       Offset +=
551           encodeImm(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
552       break;
553     }
554 
555     // Since M68k is Big Endian we need to rotate each instruction word
556     while (Offset / 16) {
557       support::endian::write<uint16_t>(OS, Buffer, support::big);
558       Buffer >>= 16;
559       Offset -= 16;
560       ThisByte += 2;
561     }
562   }
563 
564   assert(Offset == 0 && "M68k Instructions are % 2 bytes");
565   assert((ThisByte && !(ThisByte % 2)) && "M68k Instructions are % 2 bytes");
566 }
567 
568 MCCodeEmitter *llvm::createM68kMCCodeEmitter(const MCInstrInfo &MCII,
569                                              MCContext &Ctx) {
570   return new M68kMCCodeEmitter(MCII, Ctx);
571 }
572