1 //===- HexagonAsmPrinter.cpp - Print machine instrs to Hexagon assembly ---===// 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 // This file contains a printer that converts from our internal representation 10 // of machine-dependent LLVM code to Hexagon assembly language. This printer is 11 // the output mechanism used by `llc'. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "HexagonAsmPrinter.h" 16 #include "Hexagon.h" 17 #include "HexagonInstrInfo.h" 18 #include "HexagonRegisterInfo.h" 19 #include "HexagonSubtarget.h" 20 #include "MCTargetDesc/HexagonInstPrinter.h" 21 #include "MCTargetDesc/HexagonMCExpr.h" 22 #include "MCTargetDesc/HexagonMCInstrInfo.h" 23 #include "MCTargetDesc/HexagonMCTargetDesc.h" 24 #include "TargetInfo/HexagonTargetInfo.h" 25 #include "llvm/ADT/StringExtras.h" 26 #include "llvm/ADT/StringRef.h" 27 #include "llvm/ADT/Twine.h" 28 #include "llvm/BinaryFormat/ELF.h" 29 #include "llvm/CodeGen/AsmPrinter.h" 30 #include "llvm/CodeGen/MachineBasicBlock.h" 31 #include "llvm/CodeGen/MachineFunction.h" 32 #include "llvm/CodeGen/MachineInstr.h" 33 #include "llvm/CodeGen/MachineOperand.h" 34 #include "llvm/CodeGen/TargetRegisterInfo.h" 35 #include "llvm/CodeGen/TargetSubtargetInfo.h" 36 #include "llvm/MC/MCContext.h" 37 #include "llvm/MC/MCDirectives.h" 38 #include "llvm/MC/MCExpr.h" 39 #include "llvm/MC/MCInst.h" 40 #include "llvm/MC/MCRegisterInfo.h" 41 #include "llvm/MC/MCSectionELF.h" 42 #include "llvm/MC/MCStreamer.h" 43 #include "llvm/MC/MCSymbol.h" 44 #include "llvm/MC/TargetRegistry.h" 45 #include "llvm/Support/Casting.h" 46 #include "llvm/Support/CommandLine.h" 47 #include "llvm/Support/ErrorHandling.h" 48 #include "llvm/Support/raw_ostream.h" 49 #include <algorithm> 50 #include <cassert> 51 #include <cstdint> 52 #include <string> 53 54 using namespace llvm; 55 56 namespace llvm { 57 58 void HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI, 59 MCInst &MCB, HexagonAsmPrinter &AP); 60 61 } // end namespace llvm 62 63 #define DEBUG_TYPE "asm-printer" 64 65 // Given a scalar register return its pair. 66 inline static unsigned getHexagonRegisterPair(unsigned Reg, 67 const MCRegisterInfo *RI) { 68 assert(Hexagon::IntRegsRegClass.contains(Reg)); 69 MCSuperRegIterator SR(Reg, RI, false); 70 unsigned Pair = *SR; 71 assert(Hexagon::DoubleRegsRegClass.contains(Pair)); 72 return Pair; 73 } 74 75 void HexagonAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, 76 raw_ostream &O) { 77 const MachineOperand &MO = MI->getOperand(OpNo); 78 79 switch (MO.getType()) { 80 default: 81 llvm_unreachable ("<unknown operand type>"); 82 case MachineOperand::MO_Register: 83 O << HexagonInstPrinter::getRegisterName(MO.getReg()); 84 return; 85 case MachineOperand::MO_Immediate: 86 O << MO.getImm(); 87 return; 88 case MachineOperand::MO_MachineBasicBlock: 89 MO.getMBB()->getSymbol()->print(O, MAI); 90 return; 91 case MachineOperand::MO_ConstantPoolIndex: 92 GetCPISymbol(MO.getIndex())->print(O, MAI); 93 return; 94 case MachineOperand::MO_GlobalAddress: 95 PrintSymbolOperand(MO, O); 96 return; 97 } 98 } 99 100 // isBlockOnlyReachableByFallthrough - We need to override this since the 101 // default AsmPrinter does not print labels for any basic block that 102 // is only reachable by a fall through. That works for all cases except 103 // for the case in which the basic block is reachable by a fall through but 104 // through an indirect from a jump table. In this case, the jump table 105 // will contain a label not defined by AsmPrinter. 106 bool HexagonAsmPrinter::isBlockOnlyReachableByFallthrough( 107 const MachineBasicBlock *MBB) const { 108 if (MBB->hasAddressTaken()) 109 return false; 110 return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); 111 } 112 113 /// PrintAsmOperand - Print out an operand for an inline asm expression. 114 bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 115 const char *ExtraCode, 116 raw_ostream &OS) { 117 // Does this asm operand have a single letter operand modifier? 118 if (ExtraCode && ExtraCode[0]) { 119 if (ExtraCode[1] != 0) 120 return true; // Unknown modifier. 121 122 switch (ExtraCode[0]) { 123 default: 124 // See if this is a generic print operand 125 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); 126 case 'L': 127 case 'H': { // The highest-numbered register of a pair. 128 const MachineOperand &MO = MI->getOperand(OpNo); 129 const MachineFunction &MF = *MI->getParent()->getParent(); 130 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 131 if (!MO.isReg()) 132 return true; 133 Register RegNumber = MO.getReg(); 134 // This should be an assert in the frontend. 135 if (Hexagon::DoubleRegsRegClass.contains(RegNumber)) 136 RegNumber = TRI->getSubReg(RegNumber, ExtraCode[0] == 'L' ? 137 Hexagon::isub_lo : 138 Hexagon::isub_hi); 139 OS << HexagonInstPrinter::getRegisterName(RegNumber); 140 return false; 141 } 142 case 'I': 143 // Write 'i' if an integer constant, otherwise nothing. Used to print 144 // addi vs add, etc. 145 if (MI->getOperand(OpNo).isImm()) 146 OS << "i"; 147 return false; 148 } 149 } 150 151 printOperand(MI, OpNo, OS); 152 return false; 153 } 154 155 bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 156 unsigned OpNo, 157 const char *ExtraCode, 158 raw_ostream &O) { 159 if (ExtraCode && ExtraCode[0]) 160 return true; // Unknown modifier. 161 162 const MachineOperand &Base = MI->getOperand(OpNo); 163 const MachineOperand &Offset = MI->getOperand(OpNo+1); 164 165 if (Base.isReg()) 166 printOperand(MI, OpNo, O); 167 else 168 llvm_unreachable("Unimplemented"); 169 170 if (Offset.isImm()) { 171 if (Offset.getImm()) 172 O << "+#" << Offset.getImm(); 173 } else { 174 llvm_unreachable("Unimplemented"); 175 } 176 177 return false; 178 } 179 180 static MCSymbol *smallData(AsmPrinter &AP, const MachineInstr &MI, 181 MCStreamer &OutStreamer, const MCOperand &Imm, 182 int AlignSize, const MCSubtargetInfo& STI) { 183 MCSymbol *Sym; 184 int64_t Value; 185 if (Imm.getExpr()->evaluateAsAbsolute(Value)) { 186 StringRef sectionPrefix; 187 std::string ImmString; 188 StringRef Name; 189 if (AlignSize == 8) { 190 Name = ".CONST_0000000000000000"; 191 sectionPrefix = ".gnu.linkonce.l8"; 192 ImmString = utohexstr(Value); 193 } else { 194 Name = ".CONST_00000000"; 195 sectionPrefix = ".gnu.linkonce.l4"; 196 ImmString = utohexstr(static_cast<uint32_t>(Value)); 197 } 198 199 std::string symbolName = // Yes, leading zeros are kept. 200 Name.drop_back(ImmString.size()).str() + ImmString; 201 std::string sectionName = sectionPrefix.str() + symbolName; 202 203 MCSectionELF *Section = OutStreamer.getContext().getELFSection( 204 sectionName, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); 205 OutStreamer.switchSection(Section); 206 207 Sym = AP.OutContext.getOrCreateSymbol(Twine(symbolName)); 208 if (Sym->isUndefined()) { 209 OutStreamer.emitLabel(Sym); 210 OutStreamer.emitSymbolAttribute(Sym, MCSA_Global); 211 OutStreamer.emitIntValue(Value, AlignSize); 212 OutStreamer.emitCodeAlignment(AlignSize, &STI); 213 } 214 } else { 215 assert(Imm.isExpr() && "Expected expression and found none"); 216 const MachineOperand &MO = MI.getOperand(1); 217 assert(MO.isGlobal() || MO.isCPI() || MO.isJTI()); 218 MCSymbol *MOSymbol = nullptr; 219 if (MO.isGlobal()) 220 MOSymbol = AP.getSymbol(MO.getGlobal()); 221 else if (MO.isCPI()) 222 MOSymbol = AP.GetCPISymbol(MO.getIndex()); 223 else if (MO.isJTI()) 224 MOSymbol = AP.GetJTISymbol(MO.getIndex()); 225 else 226 llvm_unreachable("Unknown operand type!"); 227 228 StringRef SymbolName = MOSymbol->getName(); 229 std::string LitaName = ".CONST_" + SymbolName.str(); 230 231 MCSectionELF *Section = OutStreamer.getContext().getELFSection( 232 ".lita", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); 233 234 OutStreamer.switchSection(Section); 235 Sym = AP.OutContext.getOrCreateSymbol(Twine(LitaName)); 236 if (Sym->isUndefined()) { 237 OutStreamer.emitLabel(Sym); 238 OutStreamer.emitSymbolAttribute(Sym, MCSA_Local); 239 OutStreamer.emitValue(Imm.getExpr(), AlignSize); 240 OutStreamer.emitCodeAlignment(AlignSize, &STI); 241 } 242 } 243 return Sym; 244 } 245 246 static MCInst ScaleVectorOffset(MCInst &Inst, unsigned OpNo, 247 unsigned VectorSize, MCContext &Ctx) { 248 MCInst T; 249 T.setOpcode(Inst.getOpcode()); 250 for (unsigned i = 0, n = Inst.getNumOperands(); i != n; ++i) { 251 if (i != OpNo) { 252 T.addOperand(Inst.getOperand(i)); 253 continue; 254 } 255 MCOperand &ImmOp = Inst.getOperand(i); 256 const auto *HE = static_cast<const HexagonMCExpr*>(ImmOp.getExpr()); 257 int32_t V = cast<MCConstantExpr>(HE->getExpr())->getValue(); 258 auto *NewCE = MCConstantExpr::create(V / int32_t(VectorSize), Ctx); 259 auto *NewHE = HexagonMCExpr::create(NewCE, Ctx); 260 T.addOperand(MCOperand::createExpr(NewHE)); 261 } 262 return T; 263 } 264 265 void HexagonAsmPrinter::HexagonProcessInstruction(MCInst &Inst, 266 const MachineInstr &MI) { 267 MCInst &MappedInst = static_cast <MCInst &>(Inst); 268 const MCRegisterInfo *RI = OutStreamer->getContext().getRegisterInfo(); 269 const MachineFunction &MF = *MI.getParent()->getParent(); 270 auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo(); 271 unsigned VectorSize = HRI.getRegSizeInBits(Hexagon::HvxVRRegClass) / 8; 272 273 switch (Inst.getOpcode()) { 274 default: 275 return; 276 277 case Hexagon::A2_iconst: { 278 Inst.setOpcode(Hexagon::A2_addi); 279 MCOperand Reg = Inst.getOperand(0); 280 MCOperand S16 = Inst.getOperand(1); 281 HexagonMCInstrInfo::setMustNotExtend(*S16.getExpr()); 282 HexagonMCInstrInfo::setS27_2_reloc(*S16.getExpr()); 283 Inst.clear(); 284 Inst.addOperand(Reg); 285 Inst.addOperand(MCOperand::createReg(Hexagon::R0)); 286 Inst.addOperand(S16); 287 break; 288 } 289 290 case Hexagon::A2_tfrf: { 291 const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext); 292 Inst.setOpcode(Hexagon::A2_paddif); 293 Inst.addOperand(MCOperand::createExpr(Zero)); 294 break; 295 } 296 297 case Hexagon::A2_tfrt: { 298 const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext); 299 Inst.setOpcode(Hexagon::A2_paddit); 300 Inst.addOperand(MCOperand::createExpr(Zero)); 301 break; 302 } 303 304 case Hexagon::A2_tfrfnew: { 305 const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext); 306 Inst.setOpcode(Hexagon::A2_paddifnew); 307 Inst.addOperand(MCOperand::createExpr(Zero)); 308 break; 309 } 310 311 case Hexagon::A2_tfrtnew: { 312 const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext); 313 Inst.setOpcode(Hexagon::A2_padditnew); 314 Inst.addOperand(MCOperand::createExpr(Zero)); 315 break; 316 } 317 318 case Hexagon::A2_zxtb: { 319 const MCConstantExpr *C255 = MCConstantExpr::create(255, OutContext); 320 Inst.setOpcode(Hexagon::A2_andir); 321 Inst.addOperand(MCOperand::createExpr(C255)); 322 break; 323 } 324 325 // "$dst = CONST64(#$src1)", 326 case Hexagon::CONST64: 327 if (!OutStreamer->hasRawTextSupport()) { 328 const MCOperand &Imm = MappedInst.getOperand(1); 329 MCSectionSubPair Current = OutStreamer->getCurrentSection(); 330 331 MCSymbol *Sym = 332 smallData(*this, MI, *OutStreamer, Imm, 8, getSubtargetInfo()); 333 334 OutStreamer->switchSection(Current.first, Current.second); 335 MCInst TmpInst; 336 MCOperand &Reg = MappedInst.getOperand(0); 337 TmpInst.setOpcode(Hexagon::L2_loadrdgp); 338 TmpInst.addOperand(Reg); 339 TmpInst.addOperand(MCOperand::createExpr( 340 MCSymbolRefExpr::create(Sym, OutContext))); 341 MappedInst = TmpInst; 342 343 } 344 break; 345 case Hexagon::CONST32: 346 if (!OutStreamer->hasRawTextSupport()) { 347 MCOperand &Imm = MappedInst.getOperand(1); 348 MCSectionSubPair Current = OutStreamer->getCurrentSection(); 349 MCSymbol *Sym = 350 smallData(*this, MI, *OutStreamer, Imm, 4, getSubtargetInfo()); 351 OutStreamer->switchSection(Current.first, Current.second); 352 MCInst TmpInst; 353 MCOperand &Reg = MappedInst.getOperand(0); 354 TmpInst.setOpcode(Hexagon::L2_loadrigp); 355 TmpInst.addOperand(Reg); 356 TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create( 357 MCSymbolRefExpr::create(Sym, OutContext), OutContext))); 358 MappedInst = TmpInst; 359 } 360 break; 361 362 // C2_pxfer_map maps to C2_or instruction. Though, it's possible to use 363 // C2_or during instruction selection itself but it results 364 // into suboptimal code. 365 case Hexagon::C2_pxfer_map: { 366 MCOperand &Ps = Inst.getOperand(1); 367 MappedInst.setOpcode(Hexagon::C2_or); 368 MappedInst.addOperand(Ps); 369 return; 370 } 371 372 // Vector reduce complex multiply by scalar, Rt & 1 map to :hi else :lo 373 // The insn is mapped from the 4 operand to the 3 operand raw form taking 374 // 3 register pairs. 375 case Hexagon::M2_vrcmpys_acc_s1: { 376 MCOperand &Rt = Inst.getOperand(3); 377 assert(Rt.isReg() && "Expected register and none was found"); 378 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 379 if (Reg & 1) 380 MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h); 381 else 382 MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l); 383 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 384 return; 385 } 386 case Hexagon::M2_vrcmpys_s1: { 387 MCOperand &Rt = Inst.getOperand(2); 388 assert(Rt.isReg() && "Expected register and none was found"); 389 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 390 if (Reg & 1) 391 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_h); 392 else 393 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_l); 394 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 395 return; 396 } 397 398 case Hexagon::M2_vrcmpys_s1rp: { 399 MCOperand &Rt = Inst.getOperand(2); 400 assert(Rt.isReg() && "Expected register and none was found"); 401 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 402 if (Reg & 1) 403 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h); 404 else 405 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l); 406 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 407 return; 408 } 409 410 case Hexagon::A4_boundscheck: { 411 MCOperand &Rs = Inst.getOperand(1); 412 assert(Rs.isReg() && "Expected register and none was found"); 413 unsigned Reg = RI->getEncodingValue(Rs.getReg()); 414 if (Reg & 1) // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2 415 MappedInst.setOpcode(Hexagon::A4_boundscheck_hi); 416 else // raw:lo 417 MappedInst.setOpcode(Hexagon::A4_boundscheck_lo); 418 Rs.setReg(getHexagonRegisterPair(Rs.getReg(), RI)); 419 return; 420 } 421 422 case Hexagon::PS_call_nr: 423 Inst.setOpcode(Hexagon::J2_call); 424 break; 425 426 case Hexagon::S5_asrhub_rnd_sat_goodsyntax: { 427 MCOperand &MO = MappedInst.getOperand(2); 428 int64_t Imm; 429 MCExpr const *Expr = MO.getExpr(); 430 bool Success = Expr->evaluateAsAbsolute(Imm); 431 assert(Success && "Expected immediate and none was found"); 432 (void)Success; 433 MCInst TmpInst; 434 if (Imm == 0) { 435 TmpInst.setOpcode(Hexagon::S2_vsathub); 436 TmpInst.addOperand(MappedInst.getOperand(0)); 437 TmpInst.addOperand(MappedInst.getOperand(1)); 438 MappedInst = TmpInst; 439 return; 440 } 441 TmpInst.setOpcode(Hexagon::S5_asrhub_rnd_sat); 442 TmpInst.addOperand(MappedInst.getOperand(0)); 443 TmpInst.addOperand(MappedInst.getOperand(1)); 444 const MCExpr *One = MCConstantExpr::create(1, OutContext); 445 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext); 446 TmpInst.addOperand( 447 MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext))); 448 MappedInst = TmpInst; 449 return; 450 } 451 452 case Hexagon::S5_vasrhrnd_goodsyntax: 453 case Hexagon::S2_asr_i_p_rnd_goodsyntax: { 454 MCOperand &MO2 = MappedInst.getOperand(2); 455 MCExpr const *Expr = MO2.getExpr(); 456 int64_t Imm; 457 bool Success = Expr->evaluateAsAbsolute(Imm); 458 assert(Success && "Expected immediate and none was found"); 459 (void)Success; 460 MCInst TmpInst; 461 if (Imm == 0) { 462 TmpInst.setOpcode(Hexagon::A2_combinew); 463 TmpInst.addOperand(MappedInst.getOperand(0)); 464 MCOperand &MO1 = MappedInst.getOperand(1); 465 unsigned High = RI->getSubReg(MO1.getReg(), Hexagon::isub_hi); 466 unsigned Low = RI->getSubReg(MO1.getReg(), Hexagon::isub_lo); 467 // Add a new operand for the second register in the pair. 468 TmpInst.addOperand(MCOperand::createReg(High)); 469 TmpInst.addOperand(MCOperand::createReg(Low)); 470 MappedInst = TmpInst; 471 return; 472 } 473 474 if (Inst.getOpcode() == Hexagon::S2_asr_i_p_rnd_goodsyntax) 475 TmpInst.setOpcode(Hexagon::S2_asr_i_p_rnd); 476 else 477 TmpInst.setOpcode(Hexagon::S5_vasrhrnd); 478 TmpInst.addOperand(MappedInst.getOperand(0)); 479 TmpInst.addOperand(MappedInst.getOperand(1)); 480 const MCExpr *One = MCConstantExpr::create(1, OutContext); 481 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext); 482 TmpInst.addOperand( 483 MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext))); 484 MappedInst = TmpInst; 485 return; 486 } 487 488 // if ("#u5==0") Assembler mapped to: "Rd=Rs"; else Rd=asr(Rs,#u5-1):rnd 489 case Hexagon::S2_asr_i_r_rnd_goodsyntax: { 490 MCOperand &MO = Inst.getOperand(2); 491 MCExpr const *Expr = MO.getExpr(); 492 int64_t Imm; 493 bool Success = Expr->evaluateAsAbsolute(Imm); 494 assert(Success && "Expected immediate and none was found"); 495 (void)Success; 496 MCInst TmpInst; 497 if (Imm == 0) { 498 TmpInst.setOpcode(Hexagon::A2_tfr); 499 TmpInst.addOperand(MappedInst.getOperand(0)); 500 TmpInst.addOperand(MappedInst.getOperand(1)); 501 MappedInst = TmpInst; 502 return; 503 } 504 TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd); 505 TmpInst.addOperand(MappedInst.getOperand(0)); 506 TmpInst.addOperand(MappedInst.getOperand(1)); 507 const MCExpr *One = MCConstantExpr::create(1, OutContext); 508 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext); 509 TmpInst.addOperand( 510 MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext))); 511 MappedInst = TmpInst; 512 return; 513 } 514 515 // Translate a "$Rdd = #imm" to "$Rdd = combine(#[-1,0], #imm)" 516 case Hexagon::A2_tfrpi: { 517 MCInst TmpInst; 518 MCOperand &Rdd = MappedInst.getOperand(0); 519 MCOperand &MO = MappedInst.getOperand(1); 520 521 TmpInst.setOpcode(Hexagon::A2_combineii); 522 TmpInst.addOperand(Rdd); 523 int64_t Imm; 524 bool Success = MO.getExpr()->evaluateAsAbsolute(Imm); 525 if (Success && Imm < 0) { 526 const MCExpr *MOne = MCConstantExpr::create(-1, OutContext); 527 const HexagonMCExpr *E = HexagonMCExpr::create(MOne, OutContext); 528 TmpInst.addOperand(MCOperand::createExpr(E)); 529 } else { 530 const MCExpr *Zero = MCConstantExpr::create(0, OutContext); 531 const HexagonMCExpr *E = HexagonMCExpr::create(Zero, OutContext); 532 TmpInst.addOperand(MCOperand::createExpr(E)); 533 } 534 TmpInst.addOperand(MO); 535 MappedInst = TmpInst; 536 return; 537 } 538 539 // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)" 540 case Hexagon::A2_tfrp: { 541 MCOperand &MO = MappedInst.getOperand(1); 542 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi); 543 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo); 544 MO.setReg(High); 545 // Add a new operand for the second register in the pair. 546 MappedInst.addOperand(MCOperand::createReg(Low)); 547 MappedInst.setOpcode(Hexagon::A2_combinew); 548 return; 549 } 550 551 case Hexagon::A2_tfrpt: 552 case Hexagon::A2_tfrpf: { 553 MCOperand &MO = MappedInst.getOperand(2); 554 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi); 555 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo); 556 MO.setReg(High); 557 // Add a new operand for the second register in the pair. 558 MappedInst.addOperand(MCOperand::createReg(Low)); 559 MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt) 560 ? Hexagon::C2_ccombinewt 561 : Hexagon::C2_ccombinewf); 562 return; 563 } 564 565 case Hexagon::A2_tfrptnew: 566 case Hexagon::A2_tfrpfnew: { 567 MCOperand &MO = MappedInst.getOperand(2); 568 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi); 569 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo); 570 MO.setReg(High); 571 // Add a new operand for the second register in the pair. 572 MappedInst.addOperand(MCOperand::createReg(Low)); 573 MappedInst.setOpcode(Inst.getOpcode() == Hexagon::A2_tfrptnew 574 ? Hexagon::C2_ccombinewnewt 575 : Hexagon::C2_ccombinewnewf); 576 return; 577 } 578 579 case Hexagon::M2_mpysmi: { 580 MCOperand &Imm = MappedInst.getOperand(2); 581 MCExpr const *Expr = Imm.getExpr(); 582 int64_t Value; 583 bool Success = Expr->evaluateAsAbsolute(Value); 584 assert(Success); 585 (void)Success; 586 if (Value < 0 && Value > -256) { 587 MappedInst.setOpcode(Hexagon::M2_mpysin); 588 Imm.setExpr(HexagonMCExpr::create( 589 MCUnaryExpr::createMinus(Expr, OutContext), OutContext)); 590 } else 591 MappedInst.setOpcode(Hexagon::M2_mpysip); 592 return; 593 } 594 595 case Hexagon::A2_addsp: { 596 MCOperand &Rt = Inst.getOperand(1); 597 assert(Rt.isReg() && "Expected register and none was found"); 598 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 599 if (Reg & 1) 600 MappedInst.setOpcode(Hexagon::A2_addsph); 601 else 602 MappedInst.setOpcode(Hexagon::A2_addspl); 603 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 604 return; 605 } 606 607 case Hexagon::V6_vd0: { 608 MCInst TmpInst; 609 assert(Inst.getOperand(0).isReg() && 610 "Expected register and none was found"); 611 612 TmpInst.setOpcode(Hexagon::V6_vxor); 613 TmpInst.addOperand(Inst.getOperand(0)); 614 TmpInst.addOperand(Inst.getOperand(0)); 615 TmpInst.addOperand(Inst.getOperand(0)); 616 MappedInst = TmpInst; 617 return; 618 } 619 620 case Hexagon::V6_vdd0: { 621 MCInst TmpInst; 622 assert (Inst.getOperand(0).isReg() && 623 "Expected register and none was found"); 624 625 TmpInst.setOpcode(Hexagon::V6_vsubw_dv); 626 TmpInst.addOperand(Inst.getOperand(0)); 627 TmpInst.addOperand(Inst.getOperand(0)); 628 TmpInst.addOperand(Inst.getOperand(0)); 629 MappedInst = TmpInst; 630 return; 631 } 632 633 case Hexagon::V6_vL32Ub_pi: 634 case Hexagon::V6_vL32b_cur_pi: 635 case Hexagon::V6_vL32b_nt_cur_pi: 636 case Hexagon::V6_vL32b_pi: 637 case Hexagon::V6_vL32b_nt_pi: 638 case Hexagon::V6_vL32b_nt_tmp_pi: 639 case Hexagon::V6_vL32b_tmp_pi: 640 MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext); 641 return; 642 643 case Hexagon::V6_vL32Ub_ai: 644 case Hexagon::V6_vL32b_ai: 645 case Hexagon::V6_vL32b_cur_ai: 646 case Hexagon::V6_vL32b_nt_ai: 647 case Hexagon::V6_vL32b_nt_cur_ai: 648 case Hexagon::V6_vL32b_nt_tmp_ai: 649 case Hexagon::V6_vL32b_tmp_ai: 650 MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext); 651 return; 652 653 case Hexagon::V6_vS32Ub_pi: 654 case Hexagon::V6_vS32b_new_pi: 655 case Hexagon::V6_vS32b_nt_new_pi: 656 case Hexagon::V6_vS32b_nt_pi: 657 case Hexagon::V6_vS32b_pi: 658 MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext); 659 return; 660 661 case Hexagon::V6_vS32Ub_ai: 662 case Hexagon::V6_vS32b_ai: 663 case Hexagon::V6_vS32b_new_ai: 664 case Hexagon::V6_vS32b_nt_ai: 665 case Hexagon::V6_vS32b_nt_new_ai: 666 MappedInst = ScaleVectorOffset(Inst, 1, VectorSize, OutContext); 667 return; 668 669 case Hexagon::V6_vL32b_cur_npred_pi: 670 case Hexagon::V6_vL32b_cur_pred_pi: 671 case Hexagon::V6_vL32b_npred_pi: 672 case Hexagon::V6_vL32b_nt_cur_npred_pi: 673 case Hexagon::V6_vL32b_nt_cur_pred_pi: 674 case Hexagon::V6_vL32b_nt_npred_pi: 675 case Hexagon::V6_vL32b_nt_pred_pi: 676 case Hexagon::V6_vL32b_nt_tmp_npred_pi: 677 case Hexagon::V6_vL32b_nt_tmp_pred_pi: 678 case Hexagon::V6_vL32b_pred_pi: 679 case Hexagon::V6_vL32b_tmp_npred_pi: 680 case Hexagon::V6_vL32b_tmp_pred_pi: 681 MappedInst = ScaleVectorOffset(Inst, 4, VectorSize, OutContext); 682 return; 683 684 case Hexagon::V6_vL32b_cur_npred_ai: 685 case Hexagon::V6_vL32b_cur_pred_ai: 686 case Hexagon::V6_vL32b_npred_ai: 687 case Hexagon::V6_vL32b_nt_cur_npred_ai: 688 case Hexagon::V6_vL32b_nt_cur_pred_ai: 689 case Hexagon::V6_vL32b_nt_npred_ai: 690 case Hexagon::V6_vL32b_nt_pred_ai: 691 case Hexagon::V6_vL32b_nt_tmp_npred_ai: 692 case Hexagon::V6_vL32b_nt_tmp_pred_ai: 693 case Hexagon::V6_vL32b_pred_ai: 694 case Hexagon::V6_vL32b_tmp_npred_ai: 695 case Hexagon::V6_vL32b_tmp_pred_ai: 696 MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext); 697 return; 698 699 case Hexagon::V6_vS32Ub_npred_pi: 700 case Hexagon::V6_vS32Ub_pred_pi: 701 case Hexagon::V6_vS32b_new_npred_pi: 702 case Hexagon::V6_vS32b_new_pred_pi: 703 case Hexagon::V6_vS32b_npred_pi: 704 case Hexagon::V6_vS32b_nqpred_pi: 705 case Hexagon::V6_vS32b_nt_new_npred_pi: 706 case Hexagon::V6_vS32b_nt_new_pred_pi: 707 case Hexagon::V6_vS32b_nt_npred_pi: 708 case Hexagon::V6_vS32b_nt_nqpred_pi: 709 case Hexagon::V6_vS32b_nt_pred_pi: 710 case Hexagon::V6_vS32b_nt_qpred_pi: 711 case Hexagon::V6_vS32b_pred_pi: 712 case Hexagon::V6_vS32b_qpred_pi: 713 MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext); 714 return; 715 716 case Hexagon::V6_vS32Ub_npred_ai: 717 case Hexagon::V6_vS32Ub_pred_ai: 718 case Hexagon::V6_vS32b_new_npred_ai: 719 case Hexagon::V6_vS32b_new_pred_ai: 720 case Hexagon::V6_vS32b_npred_ai: 721 case Hexagon::V6_vS32b_nqpred_ai: 722 case Hexagon::V6_vS32b_nt_new_npred_ai: 723 case Hexagon::V6_vS32b_nt_new_pred_ai: 724 case Hexagon::V6_vS32b_nt_npred_ai: 725 case Hexagon::V6_vS32b_nt_nqpred_ai: 726 case Hexagon::V6_vS32b_nt_pred_ai: 727 case Hexagon::V6_vS32b_nt_qpred_ai: 728 case Hexagon::V6_vS32b_pred_ai: 729 case Hexagon::V6_vS32b_qpred_ai: 730 MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext); 731 return; 732 733 // V65+ 734 case Hexagon::V6_vS32b_srls_ai: 735 MappedInst = ScaleVectorOffset(Inst, 1, VectorSize, OutContext); 736 return; 737 738 case Hexagon::V6_vS32b_srls_pi: 739 MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext); 740 return; 741 } 742 } 743 744 /// Print out a single Hexagon MI to the current output stream. 745 void HexagonAsmPrinter::emitInstruction(const MachineInstr *MI) { 746 Hexagon_MC::verifyInstructionPredicates(MI->getOpcode(), 747 getSubtargetInfo().getFeatureBits()); 748 749 MCInst MCB; 750 MCB.setOpcode(Hexagon::BUNDLE); 751 MCB.addOperand(MCOperand::createImm(0)); 752 const MCInstrInfo &MCII = *Subtarget->getInstrInfo(); 753 754 if (MI->isBundle()) { 755 const MachineBasicBlock* MBB = MI->getParent(); 756 MachineBasicBlock::const_instr_iterator MII = MI->getIterator(); 757 758 for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII) 759 if (!MII->isDebugInstr() && !MII->isImplicitDef()) 760 HexagonLowerToMC(MCII, &*MII, MCB, *this); 761 } else { 762 HexagonLowerToMC(MCII, MI, MCB, *this); 763 } 764 765 const MachineFunction &MF = *MI->getParent()->getParent(); 766 const auto &HII = *MF.getSubtarget<HexagonSubtarget>().getInstrInfo(); 767 if (MI->isBundle() && HII.getBundleNoShuf(*MI)) 768 HexagonMCInstrInfo::setMemReorderDisabled(MCB); 769 770 MCContext &Ctx = OutStreamer->getContext(); 771 bool Ok = HexagonMCInstrInfo::canonicalizePacket(MCII, *Subtarget, Ctx, 772 MCB, nullptr); 773 assert(Ok); (void)Ok; 774 if (HexagonMCInstrInfo::bundleSize(MCB) == 0) 775 return; 776 OutStreamer->emitInstruction(MCB, getSubtargetInfo()); 777 } 778 779 void HexagonAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) { 780 static const int8_t NoopsInSledCount = 4; 781 // We want to emit the following pattern: 782 // 783 // .L_xray_sled_N: 784 // <xray_sled_base>: 785 // { jump .Ltmp0 } 786 // { nop 787 // nop 788 // nop 789 // nop } 790 // .Ltmp0: 791 // 792 // We need the 4 nop words because at runtime, we'd be patching over the 793 // full 5 words with the following pattern: 794 // 795 // <xray_sled_n>: 796 // { immext(#...) // upper 26-bits of trampoline 797 // r6 = ##... // lower 6-bits of trampoline 798 // immext(#...) // upper 26-bits of func id 799 // r7 = ##... } // lower 6 bits of func id 800 // { callr r6 } 801 // 802 // 803 auto CurSled = OutContext.createTempSymbol("xray_sled_", true); 804 OutStreamer->emitLabel(CurSled); 805 806 MCInst *SledJump = new (OutContext) MCInst(); 807 SledJump->setOpcode(Hexagon::J2_jump); 808 auto PostSled = OutContext.createTempSymbol(); 809 SledJump->addOperand(MCOperand::createExpr(HexagonMCExpr::create( 810 MCSymbolRefExpr::create(PostSled, OutContext), OutContext))); 811 812 // Emit "jump PostSled" instruction, which jumps over the nop series. 813 MCInst SledJumpPacket; 814 SledJumpPacket.setOpcode(Hexagon::BUNDLE); 815 SledJumpPacket.addOperand(MCOperand::createImm(0)); 816 SledJumpPacket.addOperand(MCOperand::createInst(SledJump)); 817 818 EmitToStreamer(*OutStreamer, SledJumpPacket); 819 820 // FIXME: this will emit individual packets, we should 821 // special-case this and combine them into a single packet. 822 emitNops(NoopsInSledCount); 823 824 OutStreamer->emitLabel(PostSled); 825 recordSled(CurSled, MI, Kind, 0); 826 } 827 828 void HexagonAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) { 829 EmitSled(MI, SledKind::FUNCTION_ENTER); 830 } 831 832 void HexagonAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) { 833 EmitSled(MI, SledKind::FUNCTION_EXIT); 834 } 835 836 void HexagonAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) { 837 EmitSled(MI, SledKind::TAIL_CALL); 838 } 839 840 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonAsmPrinter() { 841 RegisterAsmPrinter<HexagonAsmPrinter> X(getTheHexagonTarget()); 842 } 843