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
56using namespace llvm;
57
58namespace llvm {
59  void HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI,
60                        MCInst &MCB, HexagonAsmPrinter &AP);
61}
62
63#define DEBUG_TYPE "asm-printer"
64
65static 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.
70inline 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
79HexagonAsmPrinter::HexagonAsmPrinter(TargetMachine &TM,
80                                     std::unique_ptr<MCStreamer> Streamer)
81    : AsmPrinter(TM, std::move(Streamer)), Subtarget(nullptr) {}
82
83void 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//
117bool HexagonAsmPrinter::
118isBlockOnlyReachableByFallthrough(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///
127bool 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
165bool 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
190static 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
256void 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///
585void 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
613extern "C" void LLVMInitializeHexagonAsmPrinter() {
614  RegisterAsmPrinter<HexagonAsmPrinter> X(TheHexagonTarget);
615}
616