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