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