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 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, 55 unsigned Offset, SmallVectorImpl<MCFixup> &Fixups, 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, 60 SmallVectorImpl<MCFixup> &Fixups, 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, 65 SmallVectorImpl<MCFixup> &Fixups, 66 const MCSubtargetInfo &STI) const; 67 68 void encodeInstruction(const MCInst &MI, raw_ostream &OS, 69 SmallVectorImpl<MCFixup> &Fixups, 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, 79 SmallVectorImpl<MCFixup> &Fixups, 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, 110 SmallVectorImpl<MCFixup> &Fixups, 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, 185 SmallVectorImpl<MCFixup> &Fixups, 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) { 263 Expr = MCBinaryExpr::createAdd( 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) { 280 Expr = MCBinaryExpr::createAdd( 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, 316 SmallVectorImpl<MCFixup> &Fixups, 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 383 MCCodeEmitter *llvm::createM68kMCCodeEmitter(const MCInstrInfo &MCII, 384 const MCRegisterInfo &MRI, 385 MCContext &Ctx) { 386 return new M68kMCCodeEmitter(MCII, Ctx); 387 } 388