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