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