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/Support/Casting.h" 45 #include "llvm/Support/CommandLine.h" 46 #include "llvm/Support/ErrorHandling.h" 47 #include "llvm/Support/TargetRegistry.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) { 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); 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); 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 = smallData(*this, MI, *OutStreamer, Imm, 8); 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 = smallData(*this, MI, *OutStreamer, Imm, 4); 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 MCInst MCB; 745 MCB.setOpcode(Hexagon::BUNDLE); 746 MCB.addOperand(MCOperand::createImm(0)); 747 const MCInstrInfo &MCII = *Subtarget->getInstrInfo(); 748 749 if (MI->isBundle()) { 750 const MachineBasicBlock* MBB = MI->getParent(); 751 MachineBasicBlock::const_instr_iterator MII = MI->getIterator(); 752 753 for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII) 754 if (!MII->isDebugInstr() && !MII->isImplicitDef()) 755 HexagonLowerToMC(MCII, &*MII, MCB, *this); 756 } else { 757 HexagonLowerToMC(MCII, MI, MCB, *this); 758 } 759 760 const MachineFunction &MF = *MI->getParent()->getParent(); 761 const auto &HII = *MF.getSubtarget<HexagonSubtarget>().getInstrInfo(); 762 if (MI->isBundle() && HII.getBundleNoShuf(*MI)) 763 HexagonMCInstrInfo::setMemReorderDisabled(MCB); 764 765 MCContext &Ctx = OutStreamer->getContext(); 766 bool Ok = HexagonMCInstrInfo::canonicalizePacket(MCII, *Subtarget, Ctx, 767 MCB, nullptr); 768 assert(Ok); (void)Ok; 769 if (HexagonMCInstrInfo::bundleSize(MCB) == 0) 770 return; 771 OutStreamer->emitInstruction(MCB, getSubtargetInfo()); 772 } 773 774 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonAsmPrinter() { 775 RegisterAsmPrinter<HexagonAsmPrinter> X(getTheHexagonTarget()); 776 } 777