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/MC/MCContext.h" 35 #include "llvm/MC/MCDirectives.h" 36 #include "llvm/MC/MCExpr.h" 37 #include "llvm/MC/MCInst.h" 38 #include "llvm/MC/MCRegisterInfo.h" 39 #include "llvm/MC/MCSectionELF.h" 40 #include "llvm/MC/MCStreamer.h" 41 #include "llvm/MC/MCSymbol.h" 42 #include "llvm/Support/Casting.h" 43 #include "llvm/Support/CommandLine.h" 44 #include "llvm/Support/ErrorHandling.h" 45 #include "llvm/Support/TargetRegistry.h" 46 #include "llvm/Support/raw_ostream.h" 47 #include "llvm/Target/TargetRegisterInfo.h" 48 #include "llvm/Target/TargetSubtargetInfo.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 static cl::opt<bool> AlignCalls( 66 "hexagon-align-calls", cl::Hidden, cl::init(true), 67 cl::desc("Insert falign after call instruction for Hexagon target")); 68 69 // Given a scalar register return its pair. 70 inline static unsigned getHexagonRegisterPair(unsigned Reg, 71 const MCRegisterInfo *RI) { 72 assert(Hexagon::IntRegsRegClass.contains(Reg)); 73 MCSuperRegIterator SR(Reg, RI, false); 74 unsigned Pair = *SR; 75 assert(Hexagon::DoubleRegsRegClass.contains(Pair)); 76 return Pair; 77 } 78 79 HexagonAsmPrinter::HexagonAsmPrinter(TargetMachine &TM, 80 std::unique_ptr<MCStreamer> Streamer) 81 : AsmPrinter(TM, std::move(Streamer)) {} 82 83 void HexagonAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, 84 raw_ostream &O) { 85 const MachineOperand &MO = MI->getOperand(OpNo); 86 87 switch (MO.getType()) { 88 default: llvm_unreachable ("<unknown operand type>"); 89 case MachineOperand::MO_Register: 90 O << HexagonInstPrinter::getRegisterName(MO.getReg()); 91 return; 92 case MachineOperand::MO_Immediate: 93 O << MO.getImm(); 94 return; 95 case MachineOperand::MO_MachineBasicBlock: 96 MO.getMBB()->getSymbol()->print(O, MAI); 97 return; 98 case MachineOperand::MO_ConstantPoolIndex: 99 GetCPISymbol(MO.getIndex())->print(O, MAI); 100 return; 101 case MachineOperand::MO_GlobalAddress: 102 // Computing the address of a global symbol, not calling it. 103 getSymbol(MO.getGlobal())->print(O, MAI); 104 printOffset(MO.getOffset(), O); 105 return; 106 } 107 } 108 109 // isBlockOnlyReachableByFallthrough - We need to override this since the 110 // default AsmPrinter does not print labels for any basic block that 111 // is only reachable by a fall through. That works for all cases except 112 // for the case in which the basic block is reachable by a fall through but 113 // through an indirect from a jump table. In this case, the jump table 114 // will contain a label not defined by AsmPrinter. 115 bool HexagonAsmPrinter:: 116 isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { 117 if (MBB->hasAddressTaken()) 118 return false; 119 return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); 120 } 121 122 /// PrintAsmOperand - Print out an operand for an inline asm expression. 123 bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 124 unsigned AsmVariant, 125 const char *ExtraCode, 126 raw_ostream &OS) { 127 // Does this asm operand have a single letter operand modifier? 128 if (ExtraCode && ExtraCode[0]) { 129 if (ExtraCode[1] != 0) 130 return true; // Unknown modifier. 131 132 switch (ExtraCode[0]) { 133 default: 134 // See if this is a generic print operand 135 return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, OS); 136 case 'c': // Don't print "$" before a global var name or constant. 137 // Hexagon never has a prefix. 138 printOperand(MI, OpNo, OS); 139 return false; 140 case 'L': 141 case 'H': { // The highest-numbered register of a pair. 142 const MachineOperand &MO = MI->getOperand(OpNo); 143 const MachineFunction &MF = *MI->getParent()->getParent(); 144 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 145 if (!MO.isReg()) 146 return true; 147 unsigned RegNumber = MO.getReg(); 148 // This should be an assert in the frontend. 149 if (Hexagon::DoubleRegsRegClass.contains(RegNumber)) 150 RegNumber = TRI->getSubReg(RegNumber, ExtraCode[0] == 'L' ? 151 Hexagon::isub_lo : 152 Hexagon::isub_hi); 153 OS << HexagonInstPrinter::getRegisterName(RegNumber); 154 return false; 155 } 156 case 'I': 157 // Write 'i' if an integer constant, otherwise nothing. Used to print 158 // addi vs add, etc. 159 if (MI->getOperand(OpNo).isImm()) 160 OS << "i"; 161 return false; 162 } 163 } 164 165 printOperand(MI, OpNo, OS); 166 return false; 167 } 168 169 bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 170 unsigned OpNo, unsigned AsmVariant, 171 const char *ExtraCode, 172 raw_ostream &O) { 173 if (ExtraCode && ExtraCode[0]) 174 return true; // Unknown modifier. 175 176 const MachineOperand &Base = MI->getOperand(OpNo); 177 const MachineOperand &Offset = MI->getOperand(OpNo+1); 178 179 if (Base.isReg()) 180 printOperand(MI, OpNo, O); 181 else 182 llvm_unreachable("Unimplemented"); 183 184 if (Offset.isImm()) { 185 if (Offset.getImm()) 186 O << " + #" << Offset.getImm(); 187 } 188 else 189 llvm_unreachable("Unimplemented"); 190 191 return false; 192 } 193 194 static MCSymbol *smallData(AsmPrinter &AP, const MachineInstr &MI, 195 MCStreamer &OutStreamer, const MCOperand &Imm, 196 int AlignSize) { 197 MCSymbol *Sym; 198 int64_t Value; 199 if (Imm.getExpr()->evaluateAsAbsolute(Value)) { 200 StringRef sectionPrefix; 201 std::string ImmString; 202 StringRef Name; 203 if (AlignSize == 8) { 204 Name = ".CONST_0000000000000000"; 205 sectionPrefix = ".gnu.linkonce.l8"; 206 ImmString = utohexstr(Value); 207 } else { 208 Name = ".CONST_00000000"; 209 sectionPrefix = ".gnu.linkonce.l4"; 210 ImmString = utohexstr(static_cast<uint32_t>(Value)); 211 } 212 213 std::string symbolName = // Yes, leading zeros are kept. 214 Name.drop_back(ImmString.size()).str() + ImmString; 215 std::string sectionName = sectionPrefix.str() + symbolName; 216 217 MCSectionELF *Section = OutStreamer.getContext().getELFSection( 218 sectionName, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); 219 OutStreamer.SwitchSection(Section); 220 221 Sym = AP.OutContext.getOrCreateSymbol(Twine(symbolName)); 222 if (Sym->isUndefined()) { 223 OutStreamer.EmitLabel(Sym); 224 OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global); 225 OutStreamer.EmitIntValue(Value, AlignSize); 226 OutStreamer.EmitCodeAlignment(AlignSize); 227 } 228 } else { 229 assert(Imm.isExpr() && "Expected expression and found none"); 230 const MachineOperand &MO = MI.getOperand(1); 231 assert(MO.isGlobal() || MO.isCPI() || MO.isJTI()); 232 MCSymbol *MOSymbol = nullptr; 233 if (MO.isGlobal()) 234 MOSymbol = AP.getSymbol(MO.getGlobal()); 235 else if (MO.isCPI()) 236 MOSymbol = AP.GetCPISymbol(MO.getIndex()); 237 else if (MO.isJTI()) 238 MOSymbol = AP.GetJTISymbol(MO.getIndex()); 239 else 240 llvm_unreachable("Unknown operand type!"); 241 242 StringRef SymbolName = MOSymbol->getName(); 243 std::string LitaName = ".CONST_" + SymbolName.str(); 244 245 MCSectionELF *Section = OutStreamer.getContext().getELFSection( 246 ".lita", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); 247 248 OutStreamer.SwitchSection(Section); 249 Sym = AP.OutContext.getOrCreateSymbol(Twine(LitaName)); 250 if (Sym->isUndefined()) { 251 OutStreamer.EmitLabel(Sym); 252 OutStreamer.EmitSymbolAttribute(Sym, MCSA_Local); 253 OutStreamer.EmitValue(Imm.getExpr(), AlignSize); 254 OutStreamer.EmitCodeAlignment(AlignSize); 255 } 256 } 257 return Sym; 258 } 259 260 static MCInst ScaleVectorOffset(MCInst &Inst, unsigned OpNo, 261 unsigned VectorSize, MCContext &Ctx) { 262 MCInst T; 263 T.setOpcode(Inst.getOpcode()); 264 for (unsigned i = 0, n = Inst.getNumOperands(); i != n; ++i) { 265 if (i != OpNo) { 266 T.addOperand(Inst.getOperand(i)); 267 continue; 268 } 269 MCOperand &ImmOp = Inst.getOperand(i); 270 const auto *HE = static_cast<const HexagonMCExpr*>(ImmOp.getExpr()); 271 int32_t V = cast<MCConstantExpr>(HE->getExpr())->getValue(); 272 auto *NewCE = MCConstantExpr::create(V / int32_t(VectorSize), Ctx); 273 auto *NewHE = HexagonMCExpr::create(NewCE, Ctx); 274 T.addOperand(MCOperand::createExpr(NewHE)); 275 } 276 return T; 277 } 278 279 void HexagonAsmPrinter::HexagonProcessInstruction(MCInst &Inst, 280 const MachineInstr &MI) { 281 MCInst &MappedInst = static_cast <MCInst &>(Inst); 282 const MCRegisterInfo *RI = OutStreamer->getContext().getRegisterInfo(); 283 const MachineFunction &MF = *MI.getParent()->getParent(); 284 auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo(); 285 unsigned VectorSize = HRI.getRegSizeInBits(Hexagon::HvxVRRegClass) / 8; 286 287 switch (Inst.getOpcode()) { 288 default: return; 289 290 case Hexagon::A2_iconst: { 291 Inst.setOpcode(Hexagon::A2_addi); 292 MCOperand Reg = Inst.getOperand(0); 293 MCOperand S16 = Inst.getOperand(1); 294 HexagonMCInstrInfo::setMustNotExtend(*S16.getExpr()); 295 HexagonMCInstrInfo::setS27_2_reloc(*S16.getExpr()); 296 Inst.clear(); 297 Inst.addOperand(Reg); 298 Inst.addOperand(MCOperand::createReg(Hexagon::R0)); 299 Inst.addOperand(S16); 300 break; 301 } 302 303 case Hexagon::A2_tfrf: 304 Inst.setOpcode(Hexagon::A2_paddif); 305 Inst.addOperand(MCOperand::createExpr(MCConstantExpr::create(0, OutContext))); 306 break; 307 308 case Hexagon::A2_tfrt: 309 Inst.setOpcode(Hexagon::A2_paddit); 310 Inst.addOperand(MCOperand::createExpr(MCConstantExpr::create(0, OutContext))); 311 break; 312 313 case Hexagon::A2_tfrfnew: 314 Inst.setOpcode(Hexagon::A2_paddifnew); 315 Inst.addOperand(MCOperand::createExpr(MCConstantExpr::create(0, OutContext))); 316 break; 317 318 case Hexagon::A2_tfrtnew: 319 Inst.setOpcode(Hexagon::A2_padditnew); 320 Inst.addOperand(MCOperand::createExpr(MCConstantExpr::create(0, OutContext))); 321 break; 322 323 case Hexagon::A2_zxtb: 324 Inst.setOpcode(Hexagon::A2_andir); 325 Inst.addOperand(MCOperand::createExpr(MCConstantExpr::create(255, OutContext))); 326 break; 327 328 // "$dst = CONST64(#$src1)", 329 case Hexagon::CONST64: 330 if (!OutStreamer->hasRawTextSupport()) { 331 const MCOperand &Imm = MappedInst.getOperand(1); 332 MCSectionSubPair Current = OutStreamer->getCurrentSection(); 333 334 MCSymbol *Sym = smallData(*this, MI, *OutStreamer, Imm, 8); 335 336 OutStreamer->SwitchSection(Current.first, Current.second); 337 MCInst TmpInst; 338 MCOperand &Reg = MappedInst.getOperand(0); 339 TmpInst.setOpcode(Hexagon::L2_loadrdgp); 340 TmpInst.addOperand(Reg); 341 TmpInst.addOperand(MCOperand::createExpr( 342 MCSymbolRefExpr::create(Sym, OutContext))); 343 MappedInst = TmpInst; 344 345 } 346 break; 347 case Hexagon::CONST32: 348 if (!OutStreamer->hasRawTextSupport()) { 349 MCOperand &Imm = MappedInst.getOperand(1); 350 MCSectionSubPair Current = OutStreamer->getCurrentSection(); 351 MCSymbol *Sym = smallData(*this, MI, *OutStreamer, Imm, 4); 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 TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(MOne, OutContext))); 529 } else { 530 const MCExpr *Zero = MCConstantExpr::create(0, OutContext); 531 TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(Zero, OutContext))); 532 } 533 TmpInst.addOperand(MO); 534 MappedInst = TmpInst; 535 return; 536 } 537 538 // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)" 539 case Hexagon::A2_tfrp: { 540 MCOperand &MO = MappedInst.getOperand(1); 541 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi); 542 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo); 543 MO.setReg(High); 544 // Add a new operand for the second register in the pair. 545 MappedInst.addOperand(MCOperand::createReg(Low)); 546 MappedInst.setOpcode(Hexagon::A2_combinew); 547 return; 548 } 549 550 case Hexagon::A2_tfrpt: 551 case Hexagon::A2_tfrpf: { 552 MCOperand &MO = MappedInst.getOperand(2); 553 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi); 554 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo); 555 MO.setReg(High); 556 // Add a new operand for the second register in the pair. 557 MappedInst.addOperand(MCOperand::createReg(Low)); 558 MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt) 559 ? Hexagon::C2_ccombinewt 560 : Hexagon::C2_ccombinewf); 561 return; 562 } 563 564 case Hexagon::A2_tfrptnew: 565 case Hexagon::A2_tfrpfnew: { 566 MCOperand &MO = MappedInst.getOperand(2); 567 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi); 568 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo); 569 MO.setReg(High); 570 // Add a new operand for the second register in the pair. 571 MappedInst.addOperand(MCOperand::createReg(Low)); 572 MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrptnew) 573 ? Hexagon::C2_ccombinewnewt 574 : Hexagon::C2_ccombinewnewf); 575 return; 576 } 577 578 case Hexagon::M2_mpysmi: { 579 MCOperand &Imm = MappedInst.getOperand(2); 580 MCExpr const *Expr = Imm.getExpr(); 581 int64_t Value; 582 bool Success = Expr->evaluateAsAbsolute(Value); 583 assert(Success); 584 (void)Success; 585 if (Value < 0 && Value > -256) { 586 MappedInst.setOpcode(Hexagon::M2_mpysin); 587 Imm.setExpr(HexagonMCExpr::create( 588 MCUnaryExpr::createMinus(Expr, OutContext), OutContext)); 589 } else 590 MappedInst.setOpcode(Hexagon::M2_mpysip); 591 return; 592 } 593 594 case Hexagon::A2_addsp: { 595 MCOperand &Rt = Inst.getOperand(1); 596 assert(Rt.isReg() && "Expected register and none was found"); 597 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 598 if (Reg & 1) 599 MappedInst.setOpcode(Hexagon::A2_addsph); 600 else 601 MappedInst.setOpcode(Hexagon::A2_addspl); 602 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 603 return; 604 } 605 606 case Hexagon::V6_vd0: { 607 MCInst TmpInst; 608 assert(Inst.getOperand(0).isReg() && 609 "Expected register and none was found"); 610 611 TmpInst.setOpcode(Hexagon::V6_vxor); 612 TmpInst.addOperand(Inst.getOperand(0)); 613 TmpInst.addOperand(Inst.getOperand(0)); 614 TmpInst.addOperand(Inst.getOperand(0)); 615 MappedInst = TmpInst; 616 return; 617 } 618 619 case Hexagon::V6_vL32Ub_pi: 620 case Hexagon::V6_vL32b_cur_pi: 621 case Hexagon::V6_vL32b_nt_cur_pi: 622 case Hexagon::V6_vL32b_pi: 623 case Hexagon::V6_vL32b_nt_pi: 624 case Hexagon::V6_vL32b_nt_tmp_pi: 625 case Hexagon::V6_vL32b_tmp_pi: 626 MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext); 627 return; 628 629 case Hexagon::V6_vL32Ub_ai: 630 case Hexagon::V6_vL32b_ai: 631 case Hexagon::V6_vL32b_cur_ai: 632 case Hexagon::V6_vL32b_nt_ai: 633 case Hexagon::V6_vL32b_nt_cur_ai: 634 case Hexagon::V6_vL32b_nt_tmp_ai: 635 case Hexagon::V6_vL32b_tmp_ai: 636 MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext); 637 return; 638 639 case Hexagon::V6_vS32Ub_pi: 640 case Hexagon::V6_vS32b_new_pi: 641 case Hexagon::V6_vS32b_nt_new_pi: 642 case Hexagon::V6_vS32b_nt_pi: 643 case Hexagon::V6_vS32b_pi: 644 MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext); 645 return; 646 647 case Hexagon::V6_vS32Ub_ai: 648 case Hexagon::V6_vS32b_ai: 649 case Hexagon::V6_vS32b_new_ai: 650 case Hexagon::V6_vS32b_nt_ai: 651 case Hexagon::V6_vS32b_nt_new_ai: 652 MappedInst = ScaleVectorOffset(Inst, 1, VectorSize, OutContext); 653 return; 654 655 case Hexagon::V6_vL32b_cur_npred_pi: 656 case Hexagon::V6_vL32b_cur_pred_pi: 657 case Hexagon::V6_vL32b_npred_pi: 658 case Hexagon::V6_vL32b_nt_cur_npred_pi: 659 case Hexagon::V6_vL32b_nt_cur_pred_pi: 660 case Hexagon::V6_vL32b_nt_npred_pi: 661 case Hexagon::V6_vL32b_nt_pred_pi: 662 case Hexagon::V6_vL32b_nt_tmp_npred_pi: 663 case Hexagon::V6_vL32b_nt_tmp_pred_pi: 664 case Hexagon::V6_vL32b_pred_pi: 665 case Hexagon::V6_vL32b_tmp_npred_pi: 666 case Hexagon::V6_vL32b_tmp_pred_pi: 667 MappedInst = ScaleVectorOffset(Inst, 4, VectorSize, OutContext); 668 return; 669 670 case Hexagon::V6_vL32b_cur_npred_ai: 671 case Hexagon::V6_vL32b_cur_pred_ai: 672 case Hexagon::V6_vL32b_npred_ai: 673 case Hexagon::V6_vL32b_nt_cur_npred_ai: 674 case Hexagon::V6_vL32b_nt_cur_pred_ai: 675 case Hexagon::V6_vL32b_nt_npred_ai: 676 case Hexagon::V6_vL32b_nt_pred_ai: 677 case Hexagon::V6_vL32b_nt_tmp_npred_ai: 678 case Hexagon::V6_vL32b_nt_tmp_pred_ai: 679 case Hexagon::V6_vL32b_pred_ai: 680 case Hexagon::V6_vL32b_tmp_npred_ai: 681 case Hexagon::V6_vL32b_tmp_pred_ai: 682 MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext); 683 return; 684 685 case Hexagon::V6_vS32Ub_npred_pi: 686 case Hexagon::V6_vS32Ub_pred_pi: 687 case Hexagon::V6_vS32b_new_npred_pi: 688 case Hexagon::V6_vS32b_new_pred_pi: 689 case Hexagon::V6_vS32b_npred_pi: 690 case Hexagon::V6_vS32b_nqpred_pi: 691 case Hexagon::V6_vS32b_nt_new_npred_pi: 692 case Hexagon::V6_vS32b_nt_new_pred_pi: 693 case Hexagon::V6_vS32b_nt_npred_pi: 694 case Hexagon::V6_vS32b_nt_nqpred_pi: 695 case Hexagon::V6_vS32b_nt_pred_pi: 696 case Hexagon::V6_vS32b_nt_qpred_pi: 697 case Hexagon::V6_vS32b_pred_pi: 698 case Hexagon::V6_vS32b_qpred_pi: 699 MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext); 700 return; 701 702 case Hexagon::V6_vS32Ub_npred_ai: 703 case Hexagon::V6_vS32Ub_pred_ai: 704 case Hexagon::V6_vS32b_new_npred_ai: 705 case Hexagon::V6_vS32b_new_pred_ai: 706 case Hexagon::V6_vS32b_npred_ai: 707 case Hexagon::V6_vS32b_nqpred_ai: 708 case Hexagon::V6_vS32b_nt_new_npred_ai: 709 case Hexagon::V6_vS32b_nt_new_pred_ai: 710 case Hexagon::V6_vS32b_nt_npred_ai: 711 case Hexagon::V6_vS32b_nt_nqpred_ai: 712 case Hexagon::V6_vS32b_nt_pred_ai: 713 case Hexagon::V6_vS32b_nt_qpred_ai: 714 case Hexagon::V6_vS32b_pred_ai: 715 case Hexagon::V6_vS32b_qpred_ai: 716 MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext); 717 return; 718 } 719 } 720 721 /// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to 722 /// the current output stream. 723 void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { 724 MCInst MCB = HexagonMCInstrInfo::createBundle(); 725 const MCInstrInfo &MCII = *Subtarget->getInstrInfo(); 726 727 if (MI->isBundle()) { 728 const MachineBasicBlock* MBB = MI->getParent(); 729 MachineBasicBlock::const_instr_iterator MII = MI->getIterator(); 730 731 for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII) 732 if (!MII->isDebugValue() && !MII->isImplicitDef()) 733 HexagonLowerToMC(MCII, &*MII, MCB, *this); 734 } 735 else 736 HexagonLowerToMC(MCII, MI, MCB, *this); 737 738 bool Ok = HexagonMCInstrInfo::canonicalizePacket( 739 MCII, *Subtarget, OutStreamer->getContext(), MCB, nullptr); 740 assert(Ok); 741 (void)Ok; 742 if(HexagonMCInstrInfo::bundleSize(MCB) == 0) 743 return; 744 OutStreamer->EmitInstruction(MCB, getSubtargetInfo()); 745 } 746 747 extern "C" void LLVMInitializeHexagonAsmPrinter() { 748 RegisterAsmPrinter<HexagonAsmPrinter> X(getTheHexagonTarget()); 749 } 750