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': 145 case 'H': { // The highest-numbered register of a pair. 146 const MachineOperand &MO = MI->getOperand(OpNo); 147 const MachineFunction &MF = *MI->getParent()->getParent(); 148 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 149 if (!MO.isReg()) 150 return true; 151 unsigned RegNumber = MO.getReg(); 152 // This should be an assert in the frontend. 153 if (Hexagon::DoubleRegsRegClass.contains(RegNumber)) 154 RegNumber = TRI->getSubReg(RegNumber, ExtraCode[0] == 'L' ? 155 Hexagon::isub_lo : 156 Hexagon::isub_hi); 157 OS << HexagonInstPrinter::getRegisterName(RegNumber); 158 return false; 159 } 160 case 'I': 161 // Write 'i' if an integer constant, otherwise nothing. Used to print 162 // addi vs add, etc. 163 if (MI->getOperand(OpNo).isImm()) 164 OS << "i"; 165 return false; 166 } 167 } 168 169 printOperand(MI, OpNo, OS); 170 return false; 171 } 172 173 bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 174 unsigned OpNo, unsigned AsmVariant, 175 const char *ExtraCode, 176 raw_ostream &O) { 177 if (ExtraCode && ExtraCode[0]) 178 return true; // Unknown modifier. 179 180 const MachineOperand &Base = MI->getOperand(OpNo); 181 const MachineOperand &Offset = MI->getOperand(OpNo+1); 182 183 if (Base.isReg()) 184 printOperand(MI, OpNo, O); 185 else 186 llvm_unreachable("Unimplemented"); 187 188 if (Offset.isImm()) { 189 if (Offset.getImm()) 190 O << " + #" << Offset.getImm(); 191 } 192 else 193 llvm_unreachable("Unimplemented"); 194 195 return false; 196 } 197 198 static MCSymbol *smallData(AsmPrinter &AP, const MachineInstr &MI, 199 MCStreamer &OutStreamer, const MCOperand &Imm, 200 int AlignSize) { 201 MCSymbol *Sym; 202 int64_t Value; 203 if (Imm.getExpr()->evaluateAsAbsolute(Value)) { 204 StringRef sectionPrefix; 205 std::string ImmString; 206 StringRef Name; 207 if (AlignSize == 8) { 208 Name = ".CONST_0000000000000000"; 209 sectionPrefix = ".gnu.linkonce.l8"; 210 ImmString = utohexstr(Value); 211 } else { 212 Name = ".CONST_00000000"; 213 sectionPrefix = ".gnu.linkonce.l4"; 214 ImmString = utohexstr(static_cast<uint32_t>(Value)); 215 } 216 217 std::string symbolName = // Yes, leading zeros are kept. 218 Name.drop_back(ImmString.size()).str() + ImmString; 219 std::string sectionName = sectionPrefix.str() + symbolName; 220 221 MCSectionELF *Section = OutStreamer.getContext().getELFSection( 222 sectionName, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); 223 OutStreamer.SwitchSection(Section); 224 225 Sym = AP.OutContext.getOrCreateSymbol(Twine(symbolName)); 226 if (Sym->isUndefined()) { 227 OutStreamer.EmitLabel(Sym); 228 OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global); 229 OutStreamer.EmitIntValue(Value, AlignSize); 230 OutStreamer.EmitCodeAlignment(AlignSize); 231 } 232 } else { 233 assert(Imm.isExpr() && "Expected expression and found none"); 234 const MachineOperand &MO = MI.getOperand(1); 235 assert(MO.isGlobal() || MO.isCPI() || MO.isJTI()); 236 MCSymbol *MOSymbol = nullptr; 237 if (MO.isGlobal()) 238 MOSymbol = AP.getSymbol(MO.getGlobal()); 239 else if (MO.isCPI()) 240 MOSymbol = AP.GetCPISymbol(MO.getIndex()); 241 else if (MO.isJTI()) 242 MOSymbol = AP.GetJTISymbol(MO.getIndex()); 243 else 244 llvm_unreachable("Unknown operand type!"); 245 246 StringRef SymbolName = MOSymbol->getName(); 247 std::string LitaName = ".CONST_" + SymbolName.str(); 248 249 MCSectionELF *Section = OutStreamer.getContext().getELFSection( 250 ".lita", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); 251 252 OutStreamer.SwitchSection(Section); 253 Sym = AP.OutContext.getOrCreateSymbol(Twine(LitaName)); 254 if (Sym->isUndefined()) { 255 OutStreamer.EmitLabel(Sym); 256 OutStreamer.EmitSymbolAttribute(Sym, MCSA_Local); 257 OutStreamer.EmitValue(Imm.getExpr(), AlignSize); 258 OutStreamer.EmitCodeAlignment(AlignSize); 259 } 260 } 261 return Sym; 262 } 263 264 void HexagonAsmPrinter::HexagonProcessInstruction(MCInst &Inst, 265 const MachineInstr &MI) { 266 MCInst &MappedInst = static_cast <MCInst &>(Inst); 267 const MCRegisterInfo *RI = OutStreamer->getContext().getRegisterInfo(); 268 269 switch (Inst.getOpcode()) { 270 default: return; 271 272 case Hexagon::A2_iconst: { 273 Inst.setOpcode(Hexagon::A2_addi); 274 MCOperand Reg = Inst.getOperand(0); 275 MCOperand S16 = Inst.getOperand(1); 276 HexagonMCInstrInfo::setMustNotExtend(*S16.getExpr()); 277 HexagonMCInstrInfo::setS23_2_reloc(*S16.getExpr()); 278 Inst.clear(); 279 Inst.addOperand(Reg); 280 Inst.addOperand(MCOperand::createReg(Hexagon::R0)); 281 Inst.addOperand(S16); 282 break; 283 } 284 285 // "$dst = CONST64(#$src1)", 286 case Hexagon::CONST64: 287 if (!OutStreamer->hasRawTextSupport()) { 288 const MCOperand &Imm = MappedInst.getOperand(1); 289 MCSectionSubPair Current = OutStreamer->getCurrentSection(); 290 291 MCSymbol *Sym = smallData(*this, MI, *OutStreamer, Imm, 8); 292 293 OutStreamer->SwitchSection(Current.first, Current.second); 294 MCInst TmpInst; 295 MCOperand &Reg = MappedInst.getOperand(0); 296 TmpInst.setOpcode(Hexagon::L2_loadrdgp); 297 TmpInst.addOperand(Reg); 298 TmpInst.addOperand(MCOperand::createExpr( 299 MCSymbolRefExpr::create(Sym, OutContext))); 300 MappedInst = TmpInst; 301 302 } 303 break; 304 case Hexagon::CONST32: 305 if (!OutStreamer->hasRawTextSupport()) { 306 MCOperand &Imm = MappedInst.getOperand(1); 307 MCSectionSubPair Current = OutStreamer->getCurrentSection(); 308 MCSymbol *Sym = smallData(*this, MI, *OutStreamer, Imm, 4); 309 OutStreamer->SwitchSection(Current.first, Current.second); 310 MCInst TmpInst; 311 MCOperand &Reg = MappedInst.getOperand(0); 312 TmpInst.setOpcode(Hexagon::L2_loadrigp); 313 TmpInst.addOperand(Reg); 314 TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create( 315 MCSymbolRefExpr::create(Sym, OutContext), OutContext))); 316 MappedInst = TmpInst; 317 } 318 break; 319 320 // C2_pxfer_map maps to C2_or instruction. Though, it's possible to use 321 // C2_or during instruction selection itself but it results 322 // into suboptimal code. 323 case Hexagon::C2_pxfer_map: { 324 MCOperand &Ps = Inst.getOperand(1); 325 MappedInst.setOpcode(Hexagon::C2_or); 326 MappedInst.addOperand(Ps); 327 return; 328 } 329 330 // Vector reduce complex multiply by scalar, Rt & 1 map to :hi else :lo 331 // The insn is mapped from the 4 operand to the 3 operand raw form taking 332 // 3 register pairs. 333 case Hexagon::M2_vrcmpys_acc_s1: { 334 MCOperand &Rt = Inst.getOperand(3); 335 assert (Rt.isReg() && "Expected register and none was found"); 336 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 337 if (Reg & 1) 338 MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h); 339 else 340 MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l); 341 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 342 return; 343 } 344 case Hexagon::M2_vrcmpys_s1: { 345 MCOperand &Rt = Inst.getOperand(2); 346 assert (Rt.isReg() && "Expected register and none was found"); 347 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 348 if (Reg & 1) 349 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_h); 350 else 351 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_l); 352 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 353 return; 354 } 355 356 case Hexagon::M2_vrcmpys_s1rp: { 357 MCOperand &Rt = Inst.getOperand(2); 358 assert (Rt.isReg() && "Expected register and none was found"); 359 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 360 if (Reg & 1) 361 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h); 362 else 363 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l); 364 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 365 return; 366 } 367 368 case Hexagon::A4_boundscheck: { 369 MCOperand &Rs = Inst.getOperand(1); 370 assert (Rs.isReg() && "Expected register and none was found"); 371 unsigned Reg = RI->getEncodingValue(Rs.getReg()); 372 if (Reg & 1) // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2 373 MappedInst.setOpcode(Hexagon::A4_boundscheck_hi); 374 else // raw:lo 375 MappedInst.setOpcode(Hexagon::A4_boundscheck_lo); 376 Rs.setReg(getHexagonRegisterPair(Rs.getReg(), RI)); 377 return; 378 } 379 case Hexagon::S5_asrhub_rnd_sat_goodsyntax: { 380 MCOperand &MO = MappedInst.getOperand(2); 381 int64_t Imm; 382 MCExpr const *Expr = MO.getExpr(); 383 bool Success = Expr->evaluateAsAbsolute(Imm); 384 assert (Success && "Expected immediate and none was found"); 385 (void)Success; 386 MCInst TmpInst; 387 if (Imm == 0) { 388 TmpInst.setOpcode(Hexagon::S2_vsathub); 389 TmpInst.addOperand(MappedInst.getOperand(0)); 390 TmpInst.addOperand(MappedInst.getOperand(1)); 391 MappedInst = TmpInst; 392 return; 393 } 394 TmpInst.setOpcode(Hexagon::S5_asrhub_rnd_sat); 395 TmpInst.addOperand(MappedInst.getOperand(0)); 396 TmpInst.addOperand(MappedInst.getOperand(1)); 397 const MCExpr *One = MCConstantExpr::create(1, OutContext); 398 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext); 399 TmpInst.addOperand( 400 MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext))); 401 MappedInst = TmpInst; 402 return; 403 } 404 case Hexagon::S5_vasrhrnd_goodsyntax: 405 case Hexagon::S2_asr_i_p_rnd_goodsyntax: { 406 MCOperand &MO2 = MappedInst.getOperand(2); 407 MCExpr const *Expr = MO2.getExpr(); 408 int64_t Imm; 409 bool Success = Expr->evaluateAsAbsolute(Imm); 410 assert (Success && "Expected immediate and none was found"); 411 (void)Success; 412 MCInst TmpInst; 413 if (Imm == 0) { 414 TmpInst.setOpcode(Hexagon::A2_combinew); 415 TmpInst.addOperand(MappedInst.getOperand(0)); 416 MCOperand &MO1 = MappedInst.getOperand(1); 417 unsigned High = RI->getSubReg(MO1.getReg(), Hexagon::isub_hi); 418 unsigned Low = RI->getSubReg(MO1.getReg(), Hexagon::isub_lo); 419 // Add a new operand for the second register in the pair. 420 TmpInst.addOperand(MCOperand::createReg(High)); 421 TmpInst.addOperand(MCOperand::createReg(Low)); 422 MappedInst = TmpInst; 423 return; 424 } 425 426 if (Inst.getOpcode() == Hexagon::S2_asr_i_p_rnd_goodsyntax) 427 TmpInst.setOpcode(Hexagon::S2_asr_i_p_rnd); 428 else 429 TmpInst.setOpcode(Hexagon::S5_vasrhrnd); 430 TmpInst.addOperand(MappedInst.getOperand(0)); 431 TmpInst.addOperand(MappedInst.getOperand(1)); 432 const MCExpr *One = MCConstantExpr::create(1, OutContext); 433 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext); 434 TmpInst.addOperand( 435 MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext))); 436 MappedInst = TmpInst; 437 return; 438 } 439 // if ("#u5==0") Assembler mapped to: "Rd=Rs"; else Rd=asr(Rs,#u5-1):rnd 440 case Hexagon::S2_asr_i_r_rnd_goodsyntax: { 441 MCOperand &MO = Inst.getOperand(2); 442 MCExpr const *Expr = MO.getExpr(); 443 int64_t Imm; 444 bool Success = Expr->evaluateAsAbsolute(Imm); 445 assert (Success && "Expected immediate and none was found"); 446 (void)Success; 447 MCInst TmpInst; 448 if (Imm == 0) { 449 TmpInst.setOpcode(Hexagon::A2_tfr); 450 TmpInst.addOperand(MappedInst.getOperand(0)); 451 TmpInst.addOperand(MappedInst.getOperand(1)); 452 MappedInst = TmpInst; 453 return; 454 } 455 TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd); 456 TmpInst.addOperand(MappedInst.getOperand(0)); 457 TmpInst.addOperand(MappedInst.getOperand(1)); 458 const MCExpr *One = MCConstantExpr::create(1, OutContext); 459 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext); 460 TmpInst.addOperand( 461 MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext))); 462 MappedInst = TmpInst; 463 return; 464 } 465 466 // Translate a "$Rdd = #imm" to "$Rdd = combine(#[-1,0], #imm)" 467 case Hexagon::A2_tfrpi: { 468 MCInst TmpInst; 469 MCOperand &Rdd = MappedInst.getOperand(0); 470 MCOperand &MO = MappedInst.getOperand(1); 471 472 TmpInst.setOpcode(Hexagon::A2_combineii); 473 TmpInst.addOperand(Rdd); 474 int64_t Imm; 475 bool Success = MO.getExpr()->evaluateAsAbsolute(Imm); 476 if (Success && Imm < 0) { 477 const MCExpr *MOne = MCConstantExpr::create(-1, OutContext); 478 TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(MOne, OutContext))); 479 } else { 480 const MCExpr *Zero = MCConstantExpr::create(0, OutContext); 481 TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(Zero, OutContext))); 482 } 483 TmpInst.addOperand(MO); 484 MappedInst = TmpInst; 485 return; 486 } 487 // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)" 488 case Hexagon::A2_tfrp: { 489 MCOperand &MO = MappedInst.getOperand(1); 490 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi); 491 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo); 492 MO.setReg(High); 493 // Add a new operand for the second register in the pair. 494 MappedInst.addOperand(MCOperand::createReg(Low)); 495 MappedInst.setOpcode(Hexagon::A2_combinew); 496 return; 497 } 498 499 case Hexagon::A2_tfrpt: 500 case Hexagon::A2_tfrpf: { 501 MCOperand &MO = MappedInst.getOperand(2); 502 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi); 503 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo); 504 MO.setReg(High); 505 // Add a new operand for the second register in the pair. 506 MappedInst.addOperand(MCOperand::createReg(Low)); 507 MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt) 508 ? Hexagon::C2_ccombinewt 509 : Hexagon::C2_ccombinewf); 510 return; 511 } 512 case Hexagon::A2_tfrptnew: 513 case Hexagon::A2_tfrpfnew: { 514 MCOperand &MO = MappedInst.getOperand(2); 515 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi); 516 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo); 517 MO.setReg(High); 518 // Add a new operand for the second register in the pair. 519 MappedInst.addOperand(MCOperand::createReg(Low)); 520 MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrptnew) 521 ? Hexagon::C2_ccombinewnewt 522 : Hexagon::C2_ccombinewnewf); 523 return; 524 } 525 526 case Hexagon::M2_mpysmi: { 527 MCOperand &Imm = MappedInst.getOperand(2); 528 MCExpr const *Expr = Imm.getExpr(); 529 int64_t Value; 530 bool Success = Expr->evaluateAsAbsolute(Value); 531 assert(Success); 532 (void)Success; 533 if (Value < 0 && Value > -256) { 534 MappedInst.setOpcode(Hexagon::M2_mpysin); 535 Imm.setExpr(HexagonMCExpr::create( 536 MCUnaryExpr::createMinus(Expr, OutContext), OutContext)); 537 } else 538 MappedInst.setOpcode(Hexagon::M2_mpysip); 539 return; 540 } 541 542 case Hexagon::A2_addsp: { 543 MCOperand &Rt = Inst.getOperand(1); 544 assert (Rt.isReg() && "Expected register and none was found"); 545 unsigned Reg = RI->getEncodingValue(Rt.getReg()); 546 if (Reg & 1) 547 MappedInst.setOpcode(Hexagon::A2_addsph); 548 else 549 MappedInst.setOpcode(Hexagon::A2_addspl); 550 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); 551 return; 552 } 553 case Hexagon::V6_vd0: 554 case Hexagon::V6_vd0_128B: { 555 MCInst TmpInst; 556 assert (Inst.getOperand(0).isReg() && 557 "Expected register and none was found"); 558 559 TmpInst.setOpcode(Hexagon::V6_vxor); 560 TmpInst.addOperand(Inst.getOperand(0)); 561 TmpInst.addOperand(Inst.getOperand(0)); 562 TmpInst.addOperand(Inst.getOperand(0)); 563 MappedInst = TmpInst; 564 return; 565 } 566 567 } 568 } 569 570 571 /// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to 572 /// the current output stream. 573 /// 574 void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { 575 MCInst MCB = HexagonMCInstrInfo::createBundle(); 576 const MCInstrInfo &MCII = *Subtarget->getInstrInfo(); 577 578 if (MI->isBundle()) { 579 const MachineBasicBlock* MBB = MI->getParent(); 580 MachineBasicBlock::const_instr_iterator MII = MI->getIterator(); 581 unsigned IgnoreCount = 0; 582 583 for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII) 584 if (MII->getOpcode() == TargetOpcode::DBG_VALUE || 585 MII->getOpcode() == TargetOpcode::IMPLICIT_DEF) 586 ++IgnoreCount; 587 else 588 HexagonLowerToMC(MCII, &*MII, MCB, *this); 589 } 590 else 591 HexagonLowerToMC(MCII, MI, MCB, *this); 592 593 bool Ok = HexagonMCInstrInfo::canonicalizePacket( 594 MCII, *Subtarget, OutStreamer->getContext(), MCB, nullptr); 595 assert(Ok); 596 (void)Ok; 597 if(HexagonMCInstrInfo::bundleSize(MCB) == 0) 598 return; 599 OutStreamer->EmitInstruction(MCB, getSubtargetInfo()); 600 } 601 602 extern "C" void LLVMInitializeHexagonAsmPrinter() { 603 RegisterAsmPrinter<HexagonAsmPrinter> X(getTheHexagonTarget()); 604 } 605