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