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.
getHexagonRegisterPair(unsigned Reg,const MCRegisterInfo * RI)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
HexagonAsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)82 HexagonAsmPrinter::HexagonAsmPrinter(TargetMachine &TM,
83 std::unique_ptr<MCStreamer> Streamer)
84 : AsmPrinter(TM, std::move(Streamer)), Subtarget(nullptr) {}
85
printOperand(const MachineInstr * MI,unsigned OpNo,raw_ostream & O)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::
isBlockOnlyReachableByFallthrough(const MachineBasicBlock * MBB) const121 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 ///
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & OS)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
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & O)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
smallData(AsmPrinter & AP,const MachineInstr & MI,MCStreamer & OutStreamer,const MCOperand & Imm,int AlignSize)193 MCSymbol *smallData(AsmPrinter &AP, const MachineInstr &MI,
194 MCStreamer &OutStreamer,
195 const MCOperand &Imm, 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
HexagonProcessInstruction(MCInst & Inst,const MachineInstr & MI)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 // "$dst = CONST64(#$src1)",
268 case Hexagon::CONST64_Float_Real:
269 case Hexagon::CONST64_Int_Real:
270 if (!OutStreamer->hasRawTextSupport()) {
271 const MCOperand &Imm = MappedInst.getOperand(1);
272 MCSectionSubPair Current = OutStreamer->getCurrentSection();
273
274 MCSymbol *Sym = smallData(*this, MI, *OutStreamer, Imm, 8);
275
276 OutStreamer->SwitchSection(Current.first, Current.second);
277 MCInst TmpInst;
278 MCOperand &Reg = MappedInst.getOperand(0);
279 TmpInst.setOpcode(Hexagon::L2_loadrdgp);
280 TmpInst.addOperand(Reg);
281 TmpInst.addOperand(MCOperand::createExpr(
282 MCSymbolRefExpr::create(Sym, OutContext)));
283 MappedInst = TmpInst;
284
285 }
286 break;
287 case Hexagon::CONST32:
288 case Hexagon::CONST32_Float_Real:
289 case Hexagon::CONST32_Int_Real:
290 case Hexagon::FCONST32_nsdata:
291 if (!OutStreamer->hasRawTextSupport()) {
292 MCOperand &Imm = MappedInst.getOperand(1);
293 MCSectionSubPair Current = OutStreamer->getCurrentSection();
294 MCSymbol *Sym = smallData(*this, MI, *OutStreamer, Imm, 4);
295 OutStreamer->SwitchSection(Current.first, Current.second);
296 MCInst TmpInst;
297 MCOperand &Reg = MappedInst.getOperand(0);
298 TmpInst.setOpcode(Hexagon::L2_loadrigp);
299 TmpInst.addOperand(Reg);
300 TmpInst.addOperand(MCOperand::createExpr(
301 MCSymbolRefExpr::create(Sym, OutContext)));
302 MappedInst = TmpInst;
303 }
304 break;
305
306 // C2_pxfer_map maps to C2_or instruction. Though, it's possible to use
307 // C2_or during instruction selection itself but it results
308 // into suboptimal code.
309 case Hexagon::C2_pxfer_map: {
310 MCOperand &Ps = Inst.getOperand(1);
311 MappedInst.setOpcode(Hexagon::C2_or);
312 MappedInst.addOperand(Ps);
313 return;
314 }
315
316 // Vector reduce complex multiply by scalar, Rt & 1 map to :hi else :lo
317 // The insn is mapped from the 4 operand to the 3 operand raw form taking
318 // 3 register pairs.
319 case Hexagon::M2_vrcmpys_acc_s1: {
320 MCOperand &Rt = Inst.getOperand(3);
321 assert (Rt.isReg() && "Expected register and none was found");
322 unsigned Reg = RI->getEncodingValue(Rt.getReg());
323 if (Reg & 1)
324 MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h);
325 else
326 MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l);
327 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));
328 return;
329 }
330 case Hexagon::M2_vrcmpys_s1: {
331 MCOperand &Rt = Inst.getOperand(2);
332 assert (Rt.isReg() && "Expected register and none was found");
333 unsigned Reg = RI->getEncodingValue(Rt.getReg());
334 if (Reg & 1)
335 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_h);
336 else
337 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_l);
338 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));
339 return;
340 }
341
342 case Hexagon::M2_vrcmpys_s1rp: {
343 MCOperand &Rt = Inst.getOperand(2);
344 assert (Rt.isReg() && "Expected register and none was found");
345 unsigned Reg = RI->getEncodingValue(Rt.getReg());
346 if (Reg & 1)
347 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h);
348 else
349 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l);
350 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));
351 return;
352 }
353
354 case Hexagon::A4_boundscheck: {
355 MCOperand &Rs = Inst.getOperand(1);
356 assert (Rs.isReg() && "Expected register and none was found");
357 unsigned Reg = RI->getEncodingValue(Rs.getReg());
358 if (Reg & 1) // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2
359 MappedInst.setOpcode(Hexagon::A4_boundscheck_hi);
360 else // raw:lo
361 MappedInst.setOpcode(Hexagon::A4_boundscheck_lo);
362 Rs.setReg(getHexagonRegisterPair(Rs.getReg(), RI));
363 return;
364 }
365 case Hexagon::S5_asrhub_rnd_sat_goodsyntax: {
366 MCOperand &MO = MappedInst.getOperand(2);
367 int64_t Imm;
368 MCExpr const *Expr = MO.getExpr();
369 bool Success = Expr->evaluateAsAbsolute(Imm);
370 assert (Success && "Expected immediate and none was found");(void)Success;
371 MCInst TmpInst;
372 if (Imm == 0) {
373 TmpInst.setOpcode(Hexagon::S2_vsathub);
374 TmpInst.addOperand(MappedInst.getOperand(0));
375 TmpInst.addOperand(MappedInst.getOperand(1));
376 MappedInst = TmpInst;
377 return;
378 }
379 TmpInst.setOpcode(Hexagon::S5_asrhub_rnd_sat);
380 TmpInst.addOperand(MappedInst.getOperand(0));
381 TmpInst.addOperand(MappedInst.getOperand(1));
382 const MCExpr *One = MCConstantExpr::create(1, OutContext);
383 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);
384 TmpInst.addOperand(MCOperand::createExpr(Sub));
385 MappedInst = TmpInst;
386 return;
387 }
388 case Hexagon::S5_vasrhrnd_goodsyntax:
389 case Hexagon::S2_asr_i_p_rnd_goodsyntax: {
390 MCOperand &MO2 = MappedInst.getOperand(2);
391 MCExpr const *Expr = MO2.getExpr();
392 int64_t Imm;
393 bool Success = Expr->evaluateAsAbsolute(Imm);
394 assert (Success && "Expected immediate and none was found");(void)Success;
395 MCInst TmpInst;
396 if (Imm == 0) {
397 TmpInst.setOpcode(Hexagon::A2_combinew);
398 TmpInst.addOperand(MappedInst.getOperand(0));
399 MCOperand &MO1 = MappedInst.getOperand(1);
400 unsigned High = RI->getSubReg(MO1.getReg(), Hexagon::subreg_hireg);
401 unsigned Low = RI->getSubReg(MO1.getReg(), Hexagon::subreg_loreg);
402 // Add a new operand for the second register in the pair.
403 TmpInst.addOperand(MCOperand::createReg(High));
404 TmpInst.addOperand(MCOperand::createReg(Low));
405 MappedInst = TmpInst;
406 return;
407 }
408
409 if (Inst.getOpcode() == Hexagon::S2_asr_i_p_rnd_goodsyntax)
410 TmpInst.setOpcode(Hexagon::S2_asr_i_p_rnd);
411 else
412 TmpInst.setOpcode(Hexagon::S5_vasrhrnd);
413 TmpInst.addOperand(MappedInst.getOperand(0));
414 TmpInst.addOperand(MappedInst.getOperand(1));
415 const MCExpr *One = MCConstantExpr::create(1, OutContext);
416 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);
417 TmpInst.addOperand(MCOperand::createExpr(Sub));
418 MappedInst = TmpInst;
419 return;
420 }
421 // if ("#u5==0") Assembler mapped to: "Rd=Rs"; else Rd=asr(Rs,#u5-1):rnd
422 case Hexagon::S2_asr_i_r_rnd_goodsyntax: {
423 MCOperand &MO = Inst.getOperand(2);
424 MCExpr const *Expr = MO.getExpr();
425 int64_t Imm;
426 bool Success = Expr->evaluateAsAbsolute(Imm);
427 assert (Success && "Expected immediate and none was found");(void)Success;
428 MCInst TmpInst;
429 if (Imm == 0) {
430 TmpInst.setOpcode(Hexagon::A2_tfr);
431 TmpInst.addOperand(MappedInst.getOperand(0));
432 TmpInst.addOperand(MappedInst.getOperand(1));
433 MappedInst = TmpInst;
434 return;
435 }
436 TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd);
437 TmpInst.addOperand(MappedInst.getOperand(0));
438 TmpInst.addOperand(MappedInst.getOperand(1));
439 const MCExpr *One = MCConstantExpr::create(1, OutContext);
440 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);
441 TmpInst.addOperand(MCOperand::createExpr(Sub));
442 MappedInst = TmpInst;
443 return;
444 }
445 case Hexagon::TFRI_f:
446 MappedInst.setOpcode(Hexagon::A2_tfrsi);
447 return;
448 case Hexagon::TFRI_cPt_f:
449 MappedInst.setOpcode(Hexagon::C2_cmoveit);
450 return;
451 case Hexagon::TFRI_cNotPt_f:
452 MappedInst.setOpcode(Hexagon::C2_cmoveif);
453 return;
454 case Hexagon::MUX_ri_f:
455 MappedInst.setOpcode(Hexagon::C2_muxri);
456 return;
457 case Hexagon::MUX_ir_f:
458 MappedInst.setOpcode(Hexagon::C2_muxir);
459 return;
460
461 // Translate a "$Rdd = #imm" to "$Rdd = combine(#[-1,0], #imm)"
462 case Hexagon::A2_tfrpi: {
463 MCInst TmpInst;
464 MCOperand &Rdd = MappedInst.getOperand(0);
465 MCOperand &MO = MappedInst.getOperand(1);
466
467 TmpInst.setOpcode(Hexagon::A2_combineii);
468 TmpInst.addOperand(Rdd);
469 int64_t Imm;
470 bool Success = MO.getExpr()->evaluateAsAbsolute(Imm);
471 if (Success && Imm < 0) {
472 const MCExpr *MOne = MCConstantExpr::create(-1, OutContext);
473 TmpInst.addOperand(MCOperand::createExpr(MOne));
474 } else {
475 const MCExpr *Zero = MCConstantExpr::create(0, OutContext);
476 TmpInst.addOperand(MCOperand::createExpr(Zero));
477 }
478 TmpInst.addOperand(MO);
479 MappedInst = TmpInst;
480 return;
481 }
482 // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)"
483 case Hexagon::A2_tfrp: {
484 MCOperand &MO = MappedInst.getOperand(1);
485 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::subreg_hireg);
486 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::subreg_loreg);
487 MO.setReg(High);
488 // Add a new operand for the second register in the pair.
489 MappedInst.addOperand(MCOperand::createReg(Low));
490 MappedInst.setOpcode(Hexagon::A2_combinew);
491 return;
492 }
493
494 case Hexagon::A2_tfrpt:
495 case Hexagon::A2_tfrpf: {
496 MCOperand &MO = MappedInst.getOperand(2);
497 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::subreg_hireg);
498 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::subreg_loreg);
499 MO.setReg(High);
500 // Add a new operand for the second register in the pair.
501 MappedInst.addOperand(MCOperand::createReg(Low));
502 MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt)
503 ? Hexagon::C2_ccombinewt
504 : Hexagon::C2_ccombinewf);
505 return;
506 }
507 case Hexagon::A2_tfrptnew:
508 case Hexagon::A2_tfrpfnew: {
509 MCOperand &MO = MappedInst.getOperand(2);
510 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::subreg_hireg);
511 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::subreg_loreg);
512 MO.setReg(High);
513 // Add a new operand for the second register in the pair.
514 MappedInst.addOperand(MCOperand::createReg(Low));
515 MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrptnew)
516 ? Hexagon::C2_ccombinewnewt
517 : Hexagon::C2_ccombinewnewf);
518 return;
519 }
520
521 case Hexagon::M2_mpysmi: {
522 MCOperand &Imm = MappedInst.getOperand(2);
523 MCExpr const *Expr = Imm.getExpr();
524 int64_t Value;
525 bool Success = Expr->evaluateAsAbsolute(Value);
526 assert(Success);(void)Success;
527 if (Value < 0 && Value > -256) {
528 MappedInst.setOpcode(Hexagon::M2_mpysin);
529 Imm.setExpr(MCUnaryExpr::createMinus(Expr, OutContext));
530 }
531 else
532 MappedInst.setOpcode(Hexagon::M2_mpysip);
533 return;
534 }
535
536 case Hexagon::A2_addsp: {
537 MCOperand &Rt = Inst.getOperand(1);
538 assert (Rt.isReg() && "Expected register and none was found");
539 unsigned Reg = RI->getEncodingValue(Rt.getReg());
540 if (Reg & 1)
541 MappedInst.setOpcode(Hexagon::A2_addsph);
542 else
543 MappedInst.setOpcode(Hexagon::A2_addspl);
544 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));
545 return;
546 }
547 case Hexagon::HEXAGON_V6_vd0_pseudo:
548 case Hexagon::HEXAGON_V6_vd0_pseudo_128B: {
549 MCInst TmpInst;
550 assert (Inst.getOperand(0).isReg() &&
551 "Expected register and none was found");
552
553 TmpInst.setOpcode(Hexagon::V6_vxor);
554 TmpInst.addOperand(Inst.getOperand(0));
555 TmpInst.addOperand(Inst.getOperand(0));
556 TmpInst.addOperand(Inst.getOperand(0));
557 MappedInst = TmpInst;
558 return;
559 }
560
561 }
562 }
563
564
565 /// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to
566 /// the current output stream.
567 ///
EmitInstruction(const MachineInstr * MI)568 void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
569 MCInst MCB = HexagonMCInstrInfo::createBundle();
570 const MCInstrInfo &MCII = *Subtarget->getInstrInfo();
571
572 if (MI->isBundle()) {
573 const MachineBasicBlock* MBB = MI->getParent();
574 MachineBasicBlock::const_instr_iterator MII = MI->getIterator();
575 unsigned IgnoreCount = 0;
576
577 for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII)
578 if (MII->getOpcode() == TargetOpcode::DBG_VALUE ||
579 MII->getOpcode() == TargetOpcode::IMPLICIT_DEF)
580 ++IgnoreCount;
581 else
582 HexagonLowerToMC(MCII, &*MII, MCB, *this);
583 }
584 else
585 HexagonLowerToMC(MCII, MI, MCB, *this);
586
587 bool Ok = HexagonMCInstrInfo::canonicalizePacket(
588 MCII, *Subtarget, OutStreamer->getContext(), MCB, nullptr);
589 assert(Ok);
590 (void)Ok;
591 if(HexagonMCInstrInfo::bundleSize(MCB) == 0)
592 return;
593 OutStreamer->EmitInstruction(MCB, getSubtargetInfo());
594 }
595
LLVMInitializeHexagonAsmPrinter()596 extern "C" void LLVMInitializeHexagonAsmPrinter() {
597 RegisterAsmPrinter<HexagonAsmPrinter> X(TheHexagonTarget);
598 }
599