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