Home | History | Annotate | Download | only in Hexagon
      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