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, SmallVectorImpl<char> &CB, 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, 126 SmallVectorImpl<char> &CB, 127 SmallVectorImpl<MCFixup> &Fixups, 128 const MCSubtargetInfo &STI) const { 129 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 130 unsigned Size = MCII.get(MI.getOpcode()).getSize(); 131 132 if (IsLittleEndian) { 133 // Little-endian insertion of Size bytes. 134 unsigned ShiftValue = 0; 135 for (unsigned I = 0; I != Size; ++I) { 136 CB.push_back(char(Bits >> ShiftValue)); 137 ShiftValue += 8; 138 } 139 } else { 140 // TODO Big-endian insertion of Size bytes. 141 report_fatal_error("Big-endian mode currently is not supported!"); 142 } 143 } 144 145 uint32_t 146 XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 147 SmallVectorImpl<MCFixup> &Fixups, 148 const MCSubtargetInfo &STI) const { 149 if (MO.isReg()) 150 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 151 if (MO.isImm()) { 152 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 153 return Res; 154 } 155 156 report_fatal_error("Unhandled expression!"); 157 return 0; 158 } 159 160 uint32_t 161 XtensaMCCodeEmitter::getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum, 162 SmallVectorImpl<MCFixup> &Fixups, 163 const MCSubtargetInfo &STI) const { 164 const MCOperand &MO = MI.getOperand(OpNum); 165 166 if (MO.isImm()) 167 return MO.getImm(); 168 169 const MCExpr *Expr = MO.getExpr(); 170 Fixups.push_back(MCFixup::create( 171 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_jump_18), MI.getLoc())); 172 return 0; 173 } 174 175 uint32_t XtensaMCCodeEmitter::getBranchTargetEncoding( 176 const MCInst &MI, unsigned int OpNum, SmallVectorImpl<MCFixup> &Fixups, 177 const MCSubtargetInfo &STI) const { 178 const MCOperand &MO = MI.getOperand(OpNum); 179 if (MO.isImm()) 180 return static_cast<uint32_t>(MO.getImm()); 181 182 const MCExpr *Expr = MO.getExpr(); 183 switch (MI.getOpcode()) { 184 case Xtensa::BEQZ: 185 case Xtensa::BGEZ: 186 case Xtensa::BLTZ: 187 case Xtensa::BNEZ: 188 Fixups.push_back(MCFixup::create( 189 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_12), MI.getLoc())); 190 return 0; 191 default: 192 Fixups.push_back(MCFixup::create( 193 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_8), MI.getLoc())); 194 return 0; 195 } 196 } 197 198 uint32_t 199 XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum, 200 SmallVectorImpl<MCFixup> &Fixups, 201 const MCSubtargetInfo &STI) const { 202 const MCOperand &MO = MI.getOperand(OpNum); 203 if (MO.isImm()) { 204 int32_t Res = MO.getImm(); 205 if (Res & 0x3) { 206 llvm_unreachable("Unexpected operand value!"); 207 } 208 Res >>= 2; 209 return Res; 210 } 211 212 assert((MO.isExpr()) && "Unexpected operand value!"); 213 const MCExpr *Expr = MO.getExpr(); 214 Fixups.push_back(MCFixup::create( 215 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_call_18), MI.getLoc())); 216 return 0; 217 } 218 219 uint32_t 220 XtensaMCCodeEmitter::getL32RTargetEncoding(const MCInst &MI, unsigned OpNum, 221 SmallVectorImpl<MCFixup> &Fixups, 222 const MCSubtargetInfo &STI) const { 223 const MCOperand &MO = MI.getOperand(OpNum); 224 if (MO.isImm()) { 225 int32_t Res = MO.getImm(); 226 // We don't check first 2 bits, because in these bits we could store first 2 227 // bits of instruction address 228 Res >>= 2; 229 return Res; 230 } 231 232 assert((MO.isExpr()) && "Unexpected operand value!"); 233 234 Fixups.push_back(MCFixup::create( 235 0, MO.getExpr(), MCFixupKind(Xtensa::fixup_xtensa_l32r_16), MI.getLoc())); 236 return 0; 237 } 238 239 uint32_t 240 XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo, 241 SmallVectorImpl<MCFixup> &Fixups, 242 const MCSubtargetInfo &STI) const { 243 assert(MI.getOperand(OpNo + 1).isImm()); 244 245 uint32_t Res = static_cast<uint32_t>(MI.getOperand(OpNo + 1).getImm()); 246 247 switch (MI.getOpcode()) { 248 case Xtensa::S16I: 249 case Xtensa::L16SI: 250 case Xtensa::L16UI: 251 if (Res & 0x1) { 252 report_fatal_error("Unexpected operand value!"); 253 } 254 Res >>= 1; 255 break; 256 case Xtensa::S32I: 257 case Xtensa::L32I: 258 if (Res & 0x3) { 259 report_fatal_error("Unexpected operand value!"); 260 } 261 Res >>= 2; 262 break; 263 } 264 265 assert((isUInt<8>(Res)) && "Unexpected operand value!"); 266 267 uint32_t OffBits = Res << 4; 268 uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); 269 270 return ((OffBits & 0xFF0) | RegBits); 271 } 272 273 uint32_t XtensaMCCodeEmitter::getImm8OpValue(const MCInst &MI, unsigned OpNo, 274 SmallVectorImpl<MCFixup> &Fixups, 275 const MCSubtargetInfo &STI) const { 276 const MCOperand &MO = MI.getOperand(OpNo); 277 int32_t Res = MO.getImm(); 278 279 assert(((Res >= -128) && (Res <= 127)) && "Unexpected operand value!"); 280 281 return (Res & 0xff); 282 } 283 284 uint32_t 285 XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo, 286 SmallVectorImpl<MCFixup> &Fixups, 287 const MCSubtargetInfo &STI) const { 288 const MCOperand &MO = MI.getOperand(OpNo); 289 int32_t Res = MO.getImm(); 290 291 assert(((Res >= -32768) && (Res <= 32512) && ((Res & 0xff) == 0)) && 292 "Unexpected operand value!"); 293 294 return (Res & 0xffff); 295 } 296 297 uint32_t 298 XtensaMCCodeEmitter::getImm12OpValue(const MCInst &MI, unsigned OpNo, 299 SmallVectorImpl<MCFixup> &Fixups, 300 const MCSubtargetInfo &STI) const { 301 const MCOperand &MO = MI.getOperand(OpNo); 302 int32_t Res = MO.getImm(); 303 304 assert(((Res >= -2048) && (Res <= 2047)) && "Unexpected operand value!"); 305 306 return (Res & 0xfff); 307 } 308 309 uint32_t 310 XtensaMCCodeEmitter::getUimm4OpValue(const MCInst &MI, unsigned OpNo, 311 SmallVectorImpl<MCFixup> &Fixups, 312 const MCSubtargetInfo &STI) const { 313 const MCOperand &MO = MI.getOperand(OpNo); 314 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 315 316 assert((Res <= 15) && "Unexpected operand value!"); 317 318 return Res & 0xf; 319 } 320 321 uint32_t 322 XtensaMCCodeEmitter::getUimm5OpValue(const MCInst &MI, unsigned OpNo, 323 SmallVectorImpl<MCFixup> &Fixups, 324 const MCSubtargetInfo &STI) const { 325 const MCOperand &MO = MI.getOperand(OpNo); 326 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 327 328 assert((Res <= 31) && "Unexpected operand value!"); 329 330 return (Res & 0x1f); 331 } 332 333 uint32_t 334 XtensaMCCodeEmitter::getShimm1_31OpValue(const MCInst &MI, unsigned OpNo, 335 SmallVectorImpl<MCFixup> &Fixups, 336 const MCSubtargetInfo &STI) const { 337 const MCOperand &MO = MI.getOperand(OpNo); 338 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 339 340 assert(((Res >= 1) && (Res <= 31)) && "Unexpected operand value!"); 341 342 return ((32 - Res) & 0x1f); 343 } 344 345 uint32_t 346 XtensaMCCodeEmitter::getImm1_16OpValue(const MCInst &MI, unsigned OpNo, 347 SmallVectorImpl<MCFixup> &Fixups, 348 const MCSubtargetInfo &STI) const { 349 const MCOperand &MO = MI.getOperand(OpNo); 350 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 351 352 assert(((Res >= 1) && (Res <= 16)) && "Unexpected operand value!"); 353 354 return (Res - 1); 355 } 356 357 uint32_t 358 XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo, 359 SmallVectorImpl<MCFixup> &Fixups, 360 const MCSubtargetInfo &STI) const { 361 const MCOperand &MO = MI.getOperand(OpNo); 362 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 363 364 switch (Res) { 365 case 0xffffffff: 366 Res = 0; 367 break; 368 case 1: 369 case 2: 370 case 3: 371 case 4: 372 case 5: 373 case 6: 374 case 7: 375 case 8: 376 break; 377 case 10: 378 Res = 9; 379 break; 380 case 12: 381 Res = 10; 382 break; 383 case 16: 384 Res = 11; 385 break; 386 case 32: 387 Res = 12; 388 break; 389 case 64: 390 Res = 13; 391 break; 392 case 128: 393 Res = 14; 394 break; 395 case 256: 396 Res = 15; 397 break; 398 default: 399 llvm_unreachable("Unexpected operand value!"); 400 } 401 402 return Res; 403 } 404 405 uint32_t 406 XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo, 407 SmallVectorImpl<MCFixup> &Fixups, 408 const MCSubtargetInfo &STI) const { 409 const MCOperand &MO = MI.getOperand(OpNo); 410 uint32_t Res = static_cast<uint32_t>(MO.getImm()); 411 412 switch (Res) { 413 case 32768: 414 Res = 0; 415 break; 416 case 65536: 417 Res = 1; 418 break; 419 case 2: 420 case 3: 421 case 4: 422 case 5: 423 case 6: 424 case 7: 425 case 8: 426 break; 427 case 10: 428 Res = 9; 429 break; 430 case 12: 431 Res = 10; 432 break; 433 case 16: 434 Res = 11; 435 break; 436 case 32: 437 Res = 12; 438 break; 439 case 64: 440 Res = 13; 441 break; 442 case 128: 443 Res = 14; 444 break; 445 case 256: 446 Res = 15; 447 break; 448 default: 449 llvm_unreachable("Unexpected operand value!"); 450 } 451 452 return Res; 453 } 454 #include "XtensaGenMCCodeEmitter.inc" 455