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 "Hexagon.h" 17 #include "HexagonAsmPrinter.h" 18 #include "HexagonMachineFunctionInfo.h" 19 #include "HexagonSubtarget.h" 20 #include "HexagonTargetMachine.h" 21 #include "MCTargetDesc/HexagonInstPrinter.h" 22 #include "MCTargetDesc/HexagonMCInstrInfo.h" 23 #include "MCTargetDesc/HexagonMCShuffler.h" 24 #include "llvm/ADT/StringExtras.h" 25 #include "llvm/Analysis/ConstantFolding.h" 26 #include "llvm/CodeGen/AsmPrinter.h" 27 #include "llvm/CodeGen/MachineFunctionPass.h" 28 #include "llvm/CodeGen/MachineInstr.h" 29 #include "llvm/CodeGen/MachineInstrBuilder.h" 30 #include "llvm/CodeGen/MachineModuleInfo.h" 31 #include "llvm/IR/Constants.h" 32 #include "llvm/IR/DataLayout.h" 33 #include "llvm/IR/DerivedTypes.h" 34 #include "llvm/IR/Mangler.h" 35 #include "llvm/IR/Module.h" 36 #include "llvm/MC/MCAsmInfo.h" 37 #include "llvm/MC/MCContext.h" 38 #include "llvm/MC/MCExpr.h" 39 #include "llvm/MC/MCInst.h" 40 #include "llvm/MC/MCSection.h" 41 #include "llvm/MC/MCSectionELF.h" 42 #include "llvm/MC/MCStreamer.h" 43 #include "llvm/MC/MCSymbol.h" 44 #include "llvm/Support/CommandLine.h" 45 #include "llvm/Support/Debug.h" 46 #include "llvm/Support/ELF.h" 47 #include "llvm/Support/Format.h" 48 #include "llvm/Support/MathExtras.h" 49 #include "llvm/Support/TargetRegistry.h" 50 #include "llvm/Support/raw_ostream.h" 51 #include "llvm/Target/TargetInstrInfo.h" 52 #include "llvm/Target/TargetLoweringObjectFile.h" 53 #include "llvm/Target/TargetOptions.h" 54 #include "llvm/Target/TargetRegisterInfo.h" 55 56 using namespace llvm; 57 58 namespace llvm { 59 void HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI, 60 MCInst &MCB, HexagonAsmPrinter &AP); 61 } 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)), Subtarget(nullptr) {} 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 // 110 // isBlockOnlyReachableByFallthrough - We need to override this since the 111 // default AsmPrinter does not print labels for any basic block that 112 // is only reachable by a fall through. That works for all cases except 113 // for the case in which the basic block is reachable by a fall through but 114 // through an indirect from a jump table. In this case, the jump table 115 // will contain a label not defined by AsmPrinter. 116 // 117 bool HexagonAsmPrinter:: 118 isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { 119 if (MBB->hasAddressTaken()) 120 return false; 121 return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); 122 } 123 124 125 /// PrintAsmOperand - Print out an operand for an inline asm expression. 126 /// 127 bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 128 unsigned AsmVariant, 129 const char *ExtraCode, 130 raw_ostream &OS) { 131 // Does this asm operand have a single letter operand modifier? 132 if (ExtraCode && ExtraCode[0]) { 133 if (ExtraCode[1] != 0) 134 return true; // Unknown modifier. 135 136 switch (ExtraCode[0]) { 137 default: 138 // See if this is a generic print operand 139 return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, OS); 140 case 'c': // Don't print "$" before a global var name or constant. 141 // Hexagon never has a prefix. 142 printOperand(MI, OpNo, OS); 143 return false; 144 case 'L': // Write second word of DImode reference. 145 // Verify that this operand has two consecutive registers. 146 if (!MI->getOperand(OpNo).isReg() || 147 OpNo+1 == MI->getNumOperands() || 148 !MI->getOperand(OpNo+1).isReg()) 149 return true; 150 ++OpNo; // Return the high-part. 151 break; 152 case 'I': 153 // Write 'i' if an integer constant, otherwise nothing. Used to print 154 // addi vs add, etc. 155 if (MI->getOperand(OpNo).isImm()) 156 OS << "i"; 157 return false; 158 } 159 } 160 161 printOperand(MI, OpNo, OS); 162 return false; 163 } 164 165 bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 166 unsigned OpNo, unsigned AsmVariant, 167 const char *ExtraCode, 168 raw_ostream &O) { 169 if (ExtraCode && ExtraCode[0]) 170 return true; // Unknown modifier. 171 172 const MachineOperand &Base = MI->getOperand(OpNo); 173 const MachineOperand &Offset = MI->getOperand(OpNo+1); 174 175 if (Base.isReg()) 176 printOperand(MI, OpNo, O); 177 else 178 llvm_unreachable("Unimplemented"); 179 180 if (Offset.isImm()) { 181 if (Offset.getImm()) 182 O << " + #" << Offset.getImm(); 183 } 184 else 185 llvm_unreachable("Unimplemented"); 186 187 return false; 188 } 189 190 static MCSymbol *smallData(AsmPrinter &AP, const MachineInstr &MI, 191 MCStreamer &OutStreamer, const MCOperand &Imm, 192 int AlignSize) { 193 MCSymbol *Sym; 194 int64_t Value; 195 if (Imm.getExpr()->evaluateAsAbsolute(Value)) { 196 StringRef sectionPrefix; 197 std::string ImmString; 198 StringRef Name; 199 if (AlignSize == 8) { 200 Name = ".CONST_0000000000000000"; 201 sectionPrefix = ".gnu.linkonce.l8"; 202 ImmString = utohexstr(Value); 203 } else { 204 Name = ".CONST_00000000"; 205 sectionPrefix = ".gnu.linkonce.l4"; 206 ImmString = utohexstr(static_cast<uint32_t>(Value)); 207 } 208 209 std::string symbolName = // Yes, leading zeros are kept. 210 Name.drop_back(ImmString.size()).str() + ImmString; 211 std::string sectionName = sectionPrefix.str() + symbolName; 212 213 MCSectionELF *Section = OutStreamer.getContext().getELFSection( 214 sectionName, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); 215 OutStreamer.SwitchSection(Section); 216 217 Sym = AP.OutContext.getOrCreateSymbol(Twine(symbolName)); 218 if (Sym->isUndefined()) { 219 OutStreamer.EmitLabel(Sym); 220 OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global); 221 OutStreamer.EmitIntValue(Value, AlignSize); 222 OutStreamer.EmitCodeAlignment(AlignSize); 223 } 224 } else { 225 assert(Imm.isExpr() && "Expected expression and found none"); 226 const MachineOperand &MO = MI.getOperand(1); 227 assert(MO.isGlobal() || MO.isCPI() || MO.isJTI()); 228 MCSymbol *MOSymbol = nullptr; 229 if (MO.isGlobal()) 230 MOSymbol = AP.getSymbol(MO.getGlobal()); 231 else if (MO.isCPI()) 232 MOSymbol = AP.GetCPISymbol(MO.getIndex()); 233 else if (MO.isJTI()) 234 MOSymbol = AP.GetJTISymbol(MO.getIndex()); 235 else 236 llvm_unreachable("Unknown operand type!"); 237 238 StringRef SymbolName = MOSymbol->getName(); 239 std::string LitaName = ".CONST_" + SymbolName.str(); 240 241 MCSectionELF *Section = OutStreamer.getContext().getELFSection( 242 ".lita", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); 243 244 OutStreamer.SwitchSection(Section); 245 Sym = AP.OutContext.getOrCreateSymbol(Twine(LitaName)); 246 if (Sym->isUndefined()) { 247 OutStreamer.EmitLabel(Sym); 248 OutStreamer.EmitSymbolAttribute(Sym, MCSA_Local); 249 OutStreamer.EmitValue(Imm.getExpr(), AlignSize); 250 OutStreamer.EmitCodeAlignment(AlignSize); 251 } 252 } 253 return Sym; 254 } 255 256 void HexagonAsmPrinter::HexagonProcessInstruction(MCInst &Inst, 257 const MachineInstr &MI) { 258 MCInst &MappedInst = static_cast <MCInst &>(Inst); 259 const MCRegisterInfo *RI = OutStreamer->getContext().getRegisterInfo(); 260 261 switch (Inst.getOpcode()) { 262 default: return; 263 264 case Hexagon::A2_iconst: { 265 Inst.setOpcode(Hexagon::A2_addi); 266 MCOperand Reg = Inst.getOperand(0); 267 MCOperand S16 = Inst.getOperand(1); 268 HexagonMCInstrInfo::setMustNotExtend(*S16.getExpr()); 269 HexagonMCInstrInfo::setS23_2_reloc(*S16.getExpr()); 270 Inst.clear(); 271 Inst.addOperand(Reg); 272 Inst.addOperand(MCOperand::createReg(Hexagon::R0)); 273 Inst.addOperand(S16); 274 break; 275 } 276 277 // "$dst = CONST64(#$src1)", 278 case Hexagon::CONST64_Float_Real: 279 case Hexagon::CONST64_Int_Real: 280 if (!OutStreamer->hasRawTextSupport()) { 281 const MCOperand &Imm = MappedInst.getOperand(1); 282 MCSectionSubPair Current = OutStreamer->getCurrentSection(); 283 284 MCSymbol *Sym = smallData(*this, MI, *OutStreamer, Imm, 8); 285 286 OutStreamer->SwitchSection(Current.first, Current.second); 287 MCInst TmpInst; 288 MCOperand &Reg = MappedInst.getOperand(0); 289 TmpInst.setOpcode(Hexagon::L2_loadrdgp); 290 TmpInst.addOperand(Reg); 291 TmpInst.addOperand(MCOperand::createExpr( 292 MCSymbolRefExpr::create(Sym, OutContext))); 293 MappedInst = TmpInst; 294 295 } 296 break; 297 case Hexagon::CONST32: 298 case Hexagon::CONST32_Float_Real: 299 case Hexagon::CONST32_Int_Real: 300 case Hexagon::FCONST32_nsdata: 301 if (!OutStreamer->hasRawTextSupport()) { 302 MCOperand &Imm = MappedInst.getOperand(1); 303 MCSectionSubPair Current = OutStreamer->getCurrentSection(); 304 MCSymbol *Sym = smallData(*this, MI, *OutStreamer, Imm, 4); 305 OutStreamer->SwitchSection(Current.first, Current.second); 306 MCInst TmpInst; 307 MCOperand &Reg = MappedInst.getOperand(0); 308 TmpInst.setOpcode(Hexagon::L2_loadrigp); 309 TmpInst.addOperand(Reg); 310 TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create( 311 MCSymbolRefExpr::create(Sym, OutContext), OutContext))); 312 MappedInst = TmpInst; 313 } 314 break; 315 316 // C2_pxfer_map maps to C2_or instruction. Though, it's possible to use 317 // C2_or during instruction selection itself but it results 318 // into suboptimal code. 319 case Hexagon::C2_pxfer_map: { 320 MCOperand &Ps = Inst.getOperand(1); 321 MappedInst.setOpcode(Hexagon::C2_or); 322 MappedInst.addOperand(Ps); 323 return; 324 } 325 326 // Vector reduce complex multiply by scalar, Rt & 1 map to :hi else :lo 327 // The insn is mapped from the 4 operand to the 3 operand raw form taking 328 // 3 register pairs. 329 case Hexagon::M2_vrcmpys_acc_s1: { 330 MCOperand &Rt = Inst.getOperand(3); 331 assert (Rt.isReg() && "Expected register and none was found"); 332 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 333 if (Reg & 1) 334 MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h); 335 else 336 MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l); 337 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 338 return; 339 } 340 case Hexagon::M2_vrcmpys_s1: { 341 MCOperand &Rt = Inst.getOperand(2); 342 assert (Rt.isReg() && "Expected register and none was found"); 343 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 344 if (Reg & 1) 345 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_h); 346 else 347 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_l); 348 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 349 return; 350 } 351 352 case Hexagon::M2_vrcmpys_s1rp: { 353 MCOperand &Rt = Inst.getOperand(2); 354 assert (Rt.isReg() && "Expected register and none was found"); 355 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 356 if (Reg & 1) 357 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h); 358 else 359 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l); 360 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 361 return; 362 } 363 364 case Hexagon::A4_boundscheck: { 365 MCOperand &Rs = Inst.getOperand(1); 366 assert (Rs.isReg() && "Expected register and none was found"); 367 unsigned Reg = RI->getEncodingValue(Rs.getReg()); 368 if (Reg & 1) // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2 369 MappedInst.setOpcode(Hexagon::A4_boundscheck_hi); 370 else // raw:lo 371 MappedInst.setOpcode(Hexagon::A4_boundscheck_lo); 372 Rs.setReg(getHexagonRegisterPair(Rs.getReg(), RI)); 373 return; 374 } 375 case Hexagon::S5_asrhub_rnd_sat_goodsyntax: { 376 MCOperand &MO = MappedInst.getOperand(2); 377 int64_t Imm; 378 MCExpr const *Expr = MO.getExpr(); 379 bool Success = Expr->evaluateAsAbsolute(Imm); 380 assert (Success && "Expected immediate and none was found"); 381 (void)Success; 382 MCInst TmpInst; 383 if (Imm == 0) { 384 TmpInst.setOpcode(Hexagon::S2_vsathub); 385 TmpInst.addOperand(MappedInst.getOperand(0)); 386 TmpInst.addOperand(MappedInst.getOperand(1)); 387 MappedInst = TmpInst; 388 return; 389 } 390 TmpInst.setOpcode(Hexagon::S5_asrhub_rnd_sat); 391 TmpInst.addOperand(MappedInst.getOperand(0)); 392 TmpInst.addOperand(MappedInst.getOperand(1)); 393 const MCExpr *One = MCConstantExpr::create(1, OutContext); 394 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext); 395 TmpInst.addOperand( 396 MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext))); 397 MappedInst = TmpInst; 398 return; 399 } 400 case Hexagon::S5_vasrhrnd_goodsyntax: 401 case Hexagon::S2_asr_i_p_rnd_goodsyntax: { 402 MCOperand &MO2 = MappedInst.getOperand(2); 403 MCExpr const *Expr = MO2.getExpr(); 404 int64_t Imm; 405 bool Success = Expr->evaluateAsAbsolute(Imm); 406 assert (Success && "Expected immediate and none was found"); 407 (void)Success; 408 MCInst TmpInst; 409 if (Imm == 0) { 410 TmpInst.setOpcode(Hexagon::A2_combinew); 411 TmpInst.addOperand(MappedInst.getOperand(0)); 412 MCOperand &MO1 = MappedInst.getOperand(1); 413 unsigned High = RI->getSubReg(MO1.getReg(), Hexagon::subreg_hireg); 414 unsigned Low = RI->getSubReg(MO1.getReg(), Hexagon::subreg_loreg); 415 // Add a new operand for the second register in the pair. 416 TmpInst.addOperand(MCOperand::createReg(High)); 417 TmpInst.addOperand(MCOperand::createReg(Low)); 418 MappedInst = TmpInst; 419 return; 420 } 421 422 if (Inst.getOpcode() == Hexagon::S2_asr_i_p_rnd_goodsyntax) 423 TmpInst.setOpcode(Hexagon::S2_asr_i_p_rnd); 424 else 425 TmpInst.setOpcode(Hexagon::S5_vasrhrnd); 426 TmpInst.addOperand(MappedInst.getOperand(0)); 427 TmpInst.addOperand(MappedInst.getOperand(1)); 428 const MCExpr *One = MCConstantExpr::create(1, OutContext); 429 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext); 430 TmpInst.addOperand( 431 MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext))); 432 MappedInst = TmpInst; 433 return; 434 } 435 // if ("#u5==0") Assembler mapped to: "Rd=Rs"; else Rd=asr(Rs,#u5-1):rnd 436 case Hexagon::S2_asr_i_r_rnd_goodsyntax: { 437 MCOperand &MO = Inst.getOperand(2); 438 MCExpr const *Expr = MO.getExpr(); 439 int64_t Imm; 440 bool Success = Expr->evaluateAsAbsolute(Imm); 441 assert (Success && "Expected immediate and none was found"); 442 (void)Success; 443 MCInst TmpInst; 444 if (Imm == 0) { 445 TmpInst.setOpcode(Hexagon::A2_tfr); 446 TmpInst.addOperand(MappedInst.getOperand(0)); 447 TmpInst.addOperand(MappedInst.getOperand(1)); 448 MappedInst = TmpInst; 449 return; 450 } 451 TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd); 452 TmpInst.addOperand(MappedInst.getOperand(0)); 453 TmpInst.addOperand(MappedInst.getOperand(1)); 454 const MCExpr *One = MCConstantExpr::create(1, OutContext); 455 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext); 456 TmpInst.addOperand( 457 MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext))); 458 MappedInst = TmpInst; 459 return; 460 } 461 case Hexagon::TFRI_f: 462 MappedInst.setOpcode(Hexagon::A2_tfrsi); 463 return; 464 case Hexagon::TFRI_cPt_f: 465 MappedInst.setOpcode(Hexagon::C2_cmoveit); 466 return; 467 case Hexagon::TFRI_cNotPt_f: 468 MappedInst.setOpcode(Hexagon::C2_cmoveif); 469 return; 470 case Hexagon::MUX_ri_f: 471 MappedInst.setOpcode(Hexagon::C2_muxri); 472 return; 473 case Hexagon::MUX_ir_f: 474 MappedInst.setOpcode(Hexagon::C2_muxir); 475 return; 476 477 // Translate a "$Rdd = #imm" to "$Rdd = combine(#[-1,0], #imm)" 478 case Hexagon::A2_tfrpi: { 479 MCInst TmpInst; 480 MCOperand &Rdd = MappedInst.getOperand(0); 481 MCOperand &MO = MappedInst.getOperand(1); 482 483 TmpInst.setOpcode(Hexagon::A2_combineii); 484 TmpInst.addOperand(Rdd); 485 int64_t Imm; 486 bool Success = MO.getExpr()->evaluateAsAbsolute(Imm); 487 if (Success && Imm < 0) { 488 const MCExpr *MOne = MCConstantExpr::create(-1, OutContext); 489 TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(MOne, OutContext))); 490 } else { 491 const MCExpr *Zero = MCConstantExpr::create(0, OutContext); 492 TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(Zero, OutContext))); 493 } 494 TmpInst.addOperand(MO); 495 MappedInst = TmpInst; 496 return; 497 } 498 // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)" 499 case Hexagon::A2_tfrp: { 500 MCOperand &MO = MappedInst.getOperand(1); 501 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::subreg_hireg); 502 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::subreg_loreg); 503 MO.setReg(High); 504 // Add a new operand for the second register in the pair. 505 MappedInst.addOperand(MCOperand::createReg(Low)); 506 MappedInst.setOpcode(Hexagon::A2_combinew); 507 return; 508 } 509 510 case Hexagon::A2_tfrpt: 511 case Hexagon::A2_tfrpf: { 512 MCOperand &MO = MappedInst.getOperand(2); 513 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::subreg_hireg); 514 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::subreg_loreg); 515 MO.setReg(High); 516 // Add a new operand for the second register in the pair. 517 MappedInst.addOperand(MCOperand::createReg(Low)); 518 MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt) 519 ? Hexagon::C2_ccombinewt 520 : Hexagon::C2_ccombinewf); 521 return; 522 } 523 case Hexagon::A2_tfrptnew: 524 case Hexagon::A2_tfrpfnew: { 525 MCOperand &MO = MappedInst.getOperand(2); 526 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::subreg_hireg); 527 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::subreg_loreg); 528 MO.setReg(High); 529 // Add a new operand for the second register in the pair. 530 MappedInst.addOperand(MCOperand::createReg(Low)); 531 MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrptnew) 532 ? Hexagon::C2_ccombinewnewt 533 : Hexagon::C2_ccombinewnewf); 534 return; 535 } 536 537 case Hexagon::M2_mpysmi: { 538 MCOperand &Imm = MappedInst.getOperand(2); 539 MCExpr const *Expr = Imm.getExpr(); 540 int64_t Value; 541 bool Success = Expr->evaluateAsAbsolute(Value); 542 assert(Success); 543 (void)Success; 544 if (Value < 0 && Value > -256) { 545 MappedInst.setOpcode(Hexagon::M2_mpysin); 546 Imm.setExpr(HexagonMCExpr::create( 547 MCUnaryExpr::createMinus(Expr, OutContext), OutContext)); 548 } else 549 MappedInst.setOpcode(Hexagon::M2_mpysip); 550 return; 551 } 552 553 case Hexagon::A2_addsp: { 554 MCOperand &Rt = Inst.getOperand(1); 555 assert (Rt.isReg() && "Expected register and none was found"); 556 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 557 if (Reg & 1) 558 MappedInst.setOpcode(Hexagon::A2_addsph); 559 else 560 MappedInst.setOpcode(Hexagon::A2_addspl); 561 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 562 return; 563 } 564 case Hexagon::HEXAGON_V6_vd0_pseudo: 565 case Hexagon::HEXAGON_V6_vd0_pseudo_128B: { 566 MCInst TmpInst; 567 assert (Inst.getOperand(0).isReg() && 568 "Expected register and none was found"); 569 570 TmpInst.setOpcode(Hexagon::V6_vxor); 571 TmpInst.addOperand(Inst.getOperand(0)); 572 TmpInst.addOperand(Inst.getOperand(0)); 573 TmpInst.addOperand(Inst.getOperand(0)); 574 MappedInst = TmpInst; 575 return; 576 } 577 578 } 579 } 580 581 582 /// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to 583 /// the current output stream. 584 /// 585 void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { 586 MCInst MCB = HexagonMCInstrInfo::createBundle(); 587 const MCInstrInfo &MCII = *Subtarget->getInstrInfo(); 588 589 if (MI->isBundle()) { 590 const MachineBasicBlock* MBB = MI->getParent(); 591 MachineBasicBlock::const_instr_iterator MII = MI->getIterator(); 592 unsigned IgnoreCount = 0; 593 594 for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII) 595 if (MII->getOpcode() == TargetOpcode::DBG_VALUE || 596 MII->getOpcode() == TargetOpcode::IMPLICIT_DEF) 597 ++IgnoreCount; 598 else 599 HexagonLowerToMC(MCII, &*MII, MCB, *this); 600 } 601 else 602 HexagonLowerToMC(MCII, MI, MCB, *this); 603 604 bool Ok = HexagonMCInstrInfo::canonicalizePacket( 605 MCII, *Subtarget, OutStreamer->getContext(), MCB, nullptr); 606 assert(Ok); 607 (void)Ok; 608 if(HexagonMCInstrInfo::bundleSize(MCB) == 0) 609 return; 610 OutStreamer->EmitInstruction(MCB, getSubtargetInfo()); 611 } 612 613 extern "C" void LLVMInitializeHexagonAsmPrinter() { 614 RegisterAsmPrinter<HexagonAsmPrinter> X(TheHexagonTarget); 615 } 616