1 //===-- XtensaMCCodeEmitter.cpp - Convert Xtensa Code to Machine Code -----===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6 // See https://llvm.org/LICENSE.txt for license information. 7 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8 // 9 //===----------------------------------------------------------------------===// 10 // 11 // This file implements the XtensaMCCodeEmitter class. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "MCTargetDesc/XtensaFixupKinds.h" 16 #include "MCTargetDesc/XtensaMCExpr.h" 17 #include "MCTargetDesc/XtensaMCTargetDesc.h" 18 #include "llvm/MC/MCCodeEmitter.h" 19 #include "llvm/MC/MCContext.h" 20 #include "llvm/MC/MCExpr.h" 21 #include "llvm/MC/MCInst.h" 22 #include "llvm/MC/MCInstrInfo.h" 23 #include "llvm/MC/MCRegisterInfo.h" 24 25 #define GET_INSTRMAP_INFO 26 #include "XtensaGenInstrInfo.inc" 27 #undef GET_INSTRMAP_INFO 28 29 using namespace llvm; 30 31 #define DEBUG_TYPE "mccodeemitter" 32 33 namespace { 34 class XtensaMCCodeEmitter : public MCCodeEmitter { 35 const MCInstrInfo &MCII; 36 MCContext &Ctx; 37 bool IsLittleEndian; 38 39 public: 40 XtensaMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx, bool isLE) 41 : MCII(mcii), Ctx(ctx), IsLittleEndian(isLE) {} 42 43 ~XtensaMCCodeEmitter() {} 44 45 // OVerride MCCodeEmitter. 46 void encodeInstruction(const MCInst &MI, raw_ostream &OS, 47 SmallVectorImpl<MCFixup> &Fixups, 48 const MCSubtargetInfo &STI) const override; 49 50 private: 51 // Automatically generated by TableGen. 52 uint64_t getBinaryCodeForInstr(const MCInst &MI, 53 SmallVectorImpl<MCFixup> &Fixups, 54 const MCSubtargetInfo &STI) const; 55 56 // Called by the TableGen code to get the binary encoding of operand 57 // MO in MI. Fixups is the list of fixups against MI. 58 uint32_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, 59 SmallVectorImpl<MCFixup> &Fixups, 60 const MCSubtargetInfo &STI) const; 61 62 uint32_t getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum, 63 SmallVectorImpl<MCFixup> &Fixups, 64 const MCSubtargetInfo &STI) const; 65 66 uint32_t getBranchTargetEncoding(const MCInst &MI, unsigned int OpNum, 67 SmallVectorImpl<MCFixup> &Fixups, 68 const MCSubtargetInfo &STI) const; 69 70 uint32_t getCallEncoding(const MCInst &MI, unsigned int OpNum, 71 SmallVectorImpl<MCFixup> &Fixups, 72 const MCSubtargetInfo &STI) const; 73 74 uint32_t getL32RTargetEncoding(const MCInst &MI, unsigned OpNum, 75 SmallVectorImpl<MCFixup> &Fixups, 76 const MCSubtargetInfo &STI) const; 77 78 uint32_t getMemRegEncoding(const MCInst &MI, unsigned OpNo, 79 SmallVectorImpl<MCFixup> &Fixups, 80 const MCSubtargetInfo &STI) const; 81 82 uint32_t getImm8OpValue(const MCInst &MI, unsigned OpNo, 83 SmallVectorImpl<MCFixup> &Fixups, 84 const MCSubtargetInfo &STI) const; 85 86 uint32_t getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo, 87 SmallVectorImpl<MCFixup> &Fixups, 88 const MCSubtargetInfo &STI) const; 89 90 uint32_t getImm12OpValue(const MCInst &MI, unsigned OpNo, 91 SmallVectorImpl<MCFixup> &Fixups, 92 const MCSubtargetInfo &STI) const; 93 94 uint32_t getUimm4OpValue(const MCInst &MI, unsigned OpNo, 95 SmallVectorImpl<MCFixup> &Fixups, 96 const MCSubtargetInfo &STI) const; 97 98 uint32_t getUimm5OpValue(const MCInst &MI, unsigned OpNo, 99 SmallVectorImpl<MCFixup> &Fixups, 100 const MCSubtargetInfo &STI) const; 101 102 uint32_t getImm1_16OpValue(const MCInst &MI, unsigned OpNo, 103 SmallVectorImpl<MCFixup> &Fixups, 104 const MCSubtargetInfo &STI) const; 105 106 uint32_t getShimm1_31OpValue(const MCInst &MI, unsigned OpNo, 107 SmallVectorImpl<MCFixup> &Fixups, 108 const MCSubtargetInfo &STI) const; 109 110 uint32_t getB4constOpValue(const MCInst &MI, unsigned OpNo, 111 SmallVectorImpl<MCFixup> &Fixups, 112 const MCSubtargetInfo &STI) const; 113 114 uint32_t getB4constuOpValue(const MCInst &MI, unsigned OpNo, 115 SmallVectorImpl<MCFixup> &Fixups, 116 const MCSubtargetInfo &STI) const; 117 }; 118 } // namespace 119 120 MCCodeEmitter *llvm::createXtensaMCCodeEmitter(const MCInstrInfo &MCII, 121 MCContext &Ctx) { 122 return new XtensaMCCodeEmitter(MCII, Ctx, true); 123 } 124 125 void XtensaMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 126 SmallVectorImpl<MCFixup> &Fixups, 127 const MCSubtargetInfo &STI) const { 128 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 129 unsigned Size = MCII.get(MI.getOpcode()).getSize(); 130 131 if (IsLittleEndian) { 132 // Little-endian insertion of Size bytes. 133 unsigned ShiftValue = 0; 134 for (unsigned I = 0; I != Size; ++I) { 135 OS << uint8_t(Bits >> ShiftValue); 136 ShiftValue += 8; 137 } 138 } else { 139 // TODO Big-endian insertion of Size bytes. 140 report_fatal_error("Big-endian mode currently is not supported!"); 141 } 142 } 143 144 uint32_t 145 XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 146 SmallVectorImpl<MCFixup> &Fixups, 147 const MCSubtargetInfo &STI) const { 148 if (MO.isReg()) 149 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 150 if (MO.isImm()) { 151 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 152 return Res; 153 } 154 155 report_fatal_error("Unhandled expression!"); 156 return 0; 157 } 158 159 uint32_t 160 XtensaMCCodeEmitter::getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum, 161 SmallVectorImpl<MCFixup> &Fixups, 162 const MCSubtargetInfo &STI) const { 163 const MCOperand &MO = MI.getOperand(OpNum); 164 165 if (MO.isImm()) 166 return MO.getImm(); 167 168 const MCExpr *Expr = MO.getExpr(); 169 Fixups.push_back(MCFixup::create( 170 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_jump_18), MI.getLoc())); 171 return 0; 172 } 173 174 uint32_t XtensaMCCodeEmitter::getBranchTargetEncoding( 175 const MCInst &MI, unsigned int OpNum, SmallVectorImpl<MCFixup> &Fixups, 176 const MCSubtargetInfo &STI) const { 177 const MCOperand &MO = MI.getOperand(OpNum); 178 if (MO.isImm()) 179 return static_cast<uint32_t>(MO.getImm()); 180 181 const MCExpr *Expr = MO.getExpr(); 182 switch (MI.getOpcode()) { 183 case Xtensa::BEQZ: 184 case Xtensa::BGEZ: 185 case Xtensa::BLTZ: 186 case Xtensa::BNEZ: 187 Fixups.push_back(MCFixup::create( 188 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_12), MI.getLoc())); 189 return 0; 190 default: 191 Fixups.push_back(MCFixup::create( 192 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_8), MI.getLoc())); 193 return 0; 194 } 195 } 196 197 uint32_t 198 XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum, 199 SmallVectorImpl<MCFixup> &Fixups, 200 const MCSubtargetInfo &STI) const { 201 const MCOperand &MO = MI.getOperand(OpNum); 202 if (MO.isImm()) { 203 int32_t Res = MO.getImm(); 204 if (Res & 0x3) { 205 llvm_unreachable("Unexpected operand value!"); 206 } 207 Res >>= 2; 208 return Res; 209 } 210 211 assert((MO.isExpr()) && "Unexpected operand value!"); 212 const MCExpr *Expr = MO.getExpr(); 213 Fixups.push_back(MCFixup::create( 214 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_call_18), MI.getLoc())); 215 return 0; 216 } 217 218 uint32_t 219 XtensaMCCodeEmitter::getL32RTargetEncoding(const MCInst &MI, unsigned OpNum, 220 SmallVectorImpl<MCFixup> &Fixups, 221 const MCSubtargetInfo &STI) const { 222 const MCOperand &MO = MI.getOperand(OpNum); 223 if (MO.isImm()) { 224 int32_t Res = MO.getImm(); 225 // We don't check first 2 bits, because in these bits we could store first 2 226 // bits of instruction address 227 Res >>= 2; 228 return Res; 229 } 230 231 assert((MO.isExpr()) && "Unexpected operand value!"); 232 233 Fixups.push_back(MCFixup::create( 234 0, MO.getExpr(), MCFixupKind(Xtensa::fixup_xtensa_l32r_16), MI.getLoc())); 235 return 0; 236 } 237 238 uint32_t 239 XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo, 240 SmallVectorImpl<MCFixup> &Fixups, 241 const MCSubtargetInfo &STI) const { 242 assert(MI.getOperand(OpNo + 1).isImm()); 243 244 uint32_t Res = static_cast<uint32_t>(MI.getOperand(OpNo + 1).getImm()); 245 246 switch (MI.getOpcode()) { 247 case Xtensa::S16I: 248 case Xtensa::L16SI: 249 case Xtensa::L16UI: 250 if (Res & 0x1) { 251 report_fatal_error("Unexpected operand value!"); 252 } 253 Res >>= 1; 254 break; 255 case Xtensa::S32I: 256 case Xtensa::L32I: 257 if (Res & 0x3) { 258 report_fatal_error("Unexpected operand value!"); 259 } 260 Res >>= 2; 261 break; 262 } 263 264 assert((isUInt<8>(Res)) && "Unexpected operand value!"); 265 266 uint32_t OffBits = Res << 4; 267 uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); 268 269 return ((OffBits & 0xFF0) | RegBits); 270 } 271 272 uint32_t XtensaMCCodeEmitter::getImm8OpValue(const MCInst &MI, unsigned OpNo, 273 SmallVectorImpl<MCFixup> &Fixups, 274 const MCSubtargetInfo &STI) const { 275 const MCOperand &MO = MI.getOperand(OpNo); 276 int32_t Res = MO.getImm(); 277 278 assert(((Res >= -128) && (Res <= 127)) && "Unexpected operand value!"); 279 280 return (Res & 0xff); 281 } 282 283 uint32_t 284 XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo, 285 SmallVectorImpl<MCFixup> &Fixups, 286 const MCSubtargetInfo &STI) const { 287 const MCOperand &MO = MI.getOperand(OpNo); 288 int32_t Res = MO.getImm(); 289 290 assert(((Res >= -32768) && (Res <= 32512) && ((Res & 0xff) == 0)) && 291 "Unexpected operand value!"); 292 293 return (Res & 0xffff); 294 } 295 296 uint32_t 297 XtensaMCCodeEmitter::getImm12OpValue(const MCInst &MI, unsigned OpNo, 298 SmallVectorImpl<MCFixup> &Fixups, 299 const MCSubtargetInfo &STI) const { 300 const MCOperand &MO = MI.getOperand(OpNo); 301 int32_t Res = MO.getImm(); 302 303 assert(((Res >= -2048) && (Res <= 2047)) && "Unexpected operand value!"); 304 305 return (Res & 0xfff); 306 } 307 308 uint32_t 309 XtensaMCCodeEmitter::getUimm4OpValue(const MCInst &MI, unsigned OpNo, 310 SmallVectorImpl<MCFixup> &Fixups, 311 const MCSubtargetInfo &STI) const { 312 const MCOperand &MO = MI.getOperand(OpNo); 313 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 314 315 assert((Res <= 15) && "Unexpected operand value!"); 316 317 return Res & 0xf; 318 } 319 320 uint32_t 321 XtensaMCCodeEmitter::getUimm5OpValue(const MCInst &MI, unsigned OpNo, 322 SmallVectorImpl<MCFixup> &Fixups, 323 const MCSubtargetInfo &STI) const { 324 const MCOperand &MO = MI.getOperand(OpNo); 325 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 326 327 assert((Res <= 31) && "Unexpected operand value!"); 328 329 return (Res & 0x1f); 330 } 331 332 uint32_t 333 XtensaMCCodeEmitter::getShimm1_31OpValue(const MCInst &MI, unsigned OpNo, 334 SmallVectorImpl<MCFixup> &Fixups, 335 const MCSubtargetInfo &STI) const { 336 const MCOperand &MO = MI.getOperand(OpNo); 337 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 338 339 assert(((Res >= 1) && (Res <= 31)) && "Unexpected operand value!"); 340 341 return ((32 - Res) & 0x1f); 342 } 343 344 uint32_t 345 XtensaMCCodeEmitter::getImm1_16OpValue(const MCInst &MI, unsigned OpNo, 346 SmallVectorImpl<MCFixup> &Fixups, 347 const MCSubtargetInfo &STI) const { 348 const MCOperand &MO = MI.getOperand(OpNo); 349 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 350 351 assert(((Res >= 1) && (Res <= 16)) && "Unexpected operand value!"); 352 353 return (Res - 1); 354 } 355 356 uint32_t 357 XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo, 358 SmallVectorImpl<MCFixup> &Fixups, 359 const MCSubtargetInfo &STI) const { 360 const MCOperand &MO = MI.getOperand(OpNo); 361 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 362 363 switch (Res) { 364 case 0xffffffff: 365 Res = 0; 366 break; 367 case 1: 368 case 2: 369 case 3: 370 case 4: 371 case 5: 372 case 6: 373 case 7: 374 case 8: 375 break; 376 case 10: 377 Res = 9; 378 break; 379 case 12: 380 Res = 10; 381 break; 382 case 16: 383 Res = 11; 384 break; 385 case 32: 386 Res = 12; 387 break; 388 case 64: 389 Res = 13; 390 break; 391 case 128: 392 Res = 14; 393 break; 394 case 256: 395 Res = 15; 396 break; 397 default: 398 llvm_unreachable("Unexpected operand value!"); 399 } 400 401 return Res; 402 } 403 404 uint32_t 405 XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo, 406 SmallVectorImpl<MCFixup> &Fixups, 407 const MCSubtargetInfo &STI) const { 408 const MCOperand &MO = MI.getOperand(OpNo); 409 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 410 411 switch (Res) { 412 case 32768: 413 Res = 0; 414 break; 415 case 65536: 416 Res = 1; 417 break; 418 case 2: 419 case 3: 420 case 4: 421 case 5: 422 case 6: 423 case 7: 424 case 8: 425 break; 426 case 10: 427 Res = 9; 428 break; 429 case 12: 430 Res = 10; 431 break; 432 case 16: 433 Res = 11; 434 break; 435 case 32: 436 Res = 12; 437 break; 438 case 64: 439 Res = 13; 440 break; 441 case 128: 442 Res = 14; 443 break; 444 case 256: 445 Res = 15; 446 break; 447 default: 448 llvm_unreachable("Unexpected operand value!"); 449 } 450 451 return Res; 452 } 453 #include "XtensaGenMCCodeEmitter.inc" 454