1 //===- HexagonAsmPrinter.cpp - Print machine instrs to Hexagon assembly ---===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to Hexagon assembly language. This printer is
11 // the output mechanism used by `llc'.
13 //===----------------------------------------------------------------------===//
15 #include "HexagonAsmPrinter.h"
17 #include "HexagonInstrInfo.h"
18 #include "HexagonRegisterInfo.h"
19 #include "HexagonSubtarget.h"
20 #include "MCTargetDesc/HexagonInstPrinter.h"
21 #include "MCTargetDesc/HexagonMCExpr.h"
22 #include "MCTargetDesc/HexagonMCInstrInfo.h"
23 #include "MCTargetDesc/HexagonMCTargetDesc.h"
24 #include "TargetInfo/HexagonTargetInfo.h"
25 #include "llvm/ADT/StringExtras.h"
26 #include "llvm/ADT/StringRef.h"
27 #include "llvm/ADT/Twine.h"
28 #include "llvm/BinaryFormat/ELF.h"
29 #include "llvm/CodeGen/AsmPrinter.h"
30 #include "llvm/CodeGen/MachineBasicBlock.h"
31 #include "llvm/CodeGen/MachineFunction.h"
32 #include "llvm/CodeGen/MachineInstr.h"
33 #include "llvm/CodeGen/MachineOperand.h"
34 #include "llvm/CodeGen/TargetRegisterInfo.h"
35 #include "llvm/CodeGen/TargetSubtargetInfo.h"
36 #include "llvm/MC/MCContext.h"
37 #include "llvm/MC/MCDirectives.h"
38 #include "llvm/MC/MCExpr.h"
39 #include "llvm/MC/MCInst.h"
40 #include "llvm/MC/MCRegisterInfo.h"
41 #include "llvm/MC/MCSectionELF.h"
42 #include "llvm/MC/MCStreamer.h"
43 #include "llvm/MC/MCSymbol.h"
44 #include "llvm/Support/Casting.h"
45 #include "llvm/Support/CommandLine.h"
46 #include "llvm/Support/ErrorHandling.h"
47 #include "llvm/Support/TargetRegistry.h"
48 #include "llvm/Support/raw_ostream.h"
58 void HexagonLowerToMC(const MCInstrInfo
&MCII
, const MachineInstr
*MI
,
59 MCInst
&MCB
, HexagonAsmPrinter
&AP
);
61 } // end namespace llvm
63 #define DEBUG_TYPE "asm-printer"
65 // Given a scalar register return its pair.
66 inline static unsigned getHexagonRegisterPair(unsigned Reg
,
67 const MCRegisterInfo
*RI
) {
68 assert(Hexagon::IntRegsRegClass
.contains(Reg
));
69 MCSuperRegIterator
SR(Reg
, RI
, false);
71 assert(Hexagon::DoubleRegsRegClass
.contains(Pair
));
75 void HexagonAsmPrinter::printOperand(const MachineInstr
*MI
, unsigned OpNo
,
77 const MachineOperand
&MO
= MI
->getOperand(OpNo
);
79 switch (MO
.getType()) {
81 llvm_unreachable ("<unknown operand type>");
82 case MachineOperand::MO_Register
:
83 O
<< HexagonInstPrinter::getRegisterName(MO
.getReg());
85 case MachineOperand::MO_Immediate
:
88 case MachineOperand::MO_MachineBasicBlock
:
89 MO
.getMBB()->getSymbol()->print(O
, MAI
);
91 case MachineOperand::MO_ConstantPoolIndex
:
92 GetCPISymbol(MO
.getIndex())->print(O
, MAI
);
94 case MachineOperand::MO_GlobalAddress
:
95 PrintSymbolOperand(MO
, O
);
100 // isBlockOnlyReachableByFallthrough - We need to override this since the
101 // default AsmPrinter does not print labels for any basic block that
102 // is only reachable by a fall through. That works for all cases except
103 // for the case in which the basic block is reachable by a fall through but
104 // through an indirect from a jump table. In this case, the jump table
105 // will contain a label not defined by AsmPrinter.
106 bool HexagonAsmPrinter::isBlockOnlyReachableByFallthrough(
107 const MachineBasicBlock
*MBB
) const {
108 if (MBB
->hasAddressTaken())
110 return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB
);
113 /// PrintAsmOperand - Print out an operand for an inline asm expression.
114 bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
115 const char *ExtraCode
,
117 // Does this asm operand have a single letter operand modifier?
118 if (ExtraCode
&& ExtraCode
[0]) {
119 if (ExtraCode
[1] != 0)
120 return true; // Unknown modifier.
122 switch (ExtraCode
[0]) {
124 // See if this is a generic print operand
125 return AsmPrinter::PrintAsmOperand(MI
, OpNo
, ExtraCode
, OS
);
127 case 'H': { // The highest-numbered register of a pair.
128 const MachineOperand
&MO
= MI
->getOperand(OpNo
);
129 const MachineFunction
&MF
= *MI
->getParent()->getParent();
130 const TargetRegisterInfo
*TRI
= MF
.getSubtarget().getRegisterInfo();
133 Register RegNumber
= MO
.getReg();
134 // This should be an assert in the frontend.
135 if (Hexagon::DoubleRegsRegClass
.contains(RegNumber
))
136 RegNumber
= TRI
->getSubReg(RegNumber
, ExtraCode
[0] == 'L' ?
139 OS
<< HexagonInstPrinter::getRegisterName(RegNumber
);
143 // Write 'i' if an integer constant, otherwise nothing. Used to print
145 if (MI
->getOperand(OpNo
).isImm())
151 printOperand(MI
, OpNo
, OS
);
155 bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
,
157 const char *ExtraCode
,
159 if (ExtraCode
&& ExtraCode
[0])
160 return true; // Unknown modifier.
162 const MachineOperand
&Base
= MI
->getOperand(OpNo
);
163 const MachineOperand
&Offset
= MI
->getOperand(OpNo
+1);
166 printOperand(MI
, OpNo
, O
);
168 llvm_unreachable("Unimplemented");
170 if (Offset
.isImm()) {
172 O
<< "+#" << Offset
.getImm();
174 llvm_unreachable("Unimplemented");
180 static MCSymbol
*smallData(AsmPrinter
&AP
, const MachineInstr
&MI
,
181 MCStreamer
&OutStreamer
, const MCOperand
&Imm
,
185 if (Imm
.getExpr()->evaluateAsAbsolute(Value
)) {
186 StringRef sectionPrefix
;
187 std::string ImmString
;
189 if (AlignSize
== 8) {
190 Name
= ".CONST_0000000000000000";
191 sectionPrefix
= ".gnu.linkonce.l8";
192 ImmString
= utohexstr(Value
);
194 Name
= ".CONST_00000000";
195 sectionPrefix
= ".gnu.linkonce.l4";
196 ImmString
= utohexstr(static_cast<uint32_t>(Value
));
199 std::string symbolName
= // Yes, leading zeros are kept.
200 Name
.drop_back(ImmString
.size()).str() + ImmString
;
201 std::string sectionName
= sectionPrefix
.str() + symbolName
;
203 MCSectionELF
*Section
= OutStreamer
.getContext().getELFSection(
204 sectionName
, ELF::SHT_PROGBITS
, ELF::SHF_WRITE
| ELF::SHF_ALLOC
);
205 OutStreamer
.SwitchSection(Section
);
207 Sym
= AP
.OutContext
.getOrCreateSymbol(Twine(symbolName
));
208 if (Sym
->isUndefined()) {
209 OutStreamer
.EmitLabel(Sym
);
210 OutStreamer
.EmitSymbolAttribute(Sym
, MCSA_Global
);
211 OutStreamer
.EmitIntValue(Value
, AlignSize
);
212 OutStreamer
.EmitCodeAlignment(AlignSize
);
215 assert(Imm
.isExpr() && "Expected expression and found none");
216 const MachineOperand
&MO
= MI
.getOperand(1);
217 assert(MO
.isGlobal() || MO
.isCPI() || MO
.isJTI());
218 MCSymbol
*MOSymbol
= nullptr;
220 MOSymbol
= AP
.getSymbol(MO
.getGlobal());
222 MOSymbol
= AP
.GetCPISymbol(MO
.getIndex());
224 MOSymbol
= AP
.GetJTISymbol(MO
.getIndex());
226 llvm_unreachable("Unknown operand type!");
228 StringRef SymbolName
= MOSymbol
->getName();
229 std::string LitaName
= ".CONST_" + SymbolName
.str();
231 MCSectionELF
*Section
= OutStreamer
.getContext().getELFSection(
232 ".lita", ELF::SHT_PROGBITS
, ELF::SHF_WRITE
| ELF::SHF_ALLOC
);
234 OutStreamer
.SwitchSection(Section
);
235 Sym
= AP
.OutContext
.getOrCreateSymbol(Twine(LitaName
));
236 if (Sym
->isUndefined()) {
237 OutStreamer
.EmitLabel(Sym
);
238 OutStreamer
.EmitSymbolAttribute(Sym
, MCSA_Local
);
239 OutStreamer
.EmitValue(Imm
.getExpr(), AlignSize
);
240 OutStreamer
.EmitCodeAlignment(AlignSize
);
246 static MCInst
ScaleVectorOffset(MCInst
&Inst
, unsigned OpNo
,
247 unsigned VectorSize
, MCContext
&Ctx
) {
249 T
.setOpcode(Inst
.getOpcode());
250 for (unsigned i
= 0, n
= Inst
.getNumOperands(); i
!= n
; ++i
) {
252 T
.addOperand(Inst
.getOperand(i
));
255 MCOperand
&ImmOp
= Inst
.getOperand(i
);
256 const auto *HE
= static_cast<const HexagonMCExpr
*>(ImmOp
.getExpr());
257 int32_t V
= cast
<MCConstantExpr
>(HE
->getExpr())->getValue();
258 auto *NewCE
= MCConstantExpr::create(V
/ int32_t(VectorSize
), Ctx
);
259 auto *NewHE
= HexagonMCExpr::create(NewCE
, Ctx
);
260 T
.addOperand(MCOperand::createExpr(NewHE
));
265 void HexagonAsmPrinter::HexagonProcessInstruction(MCInst
&Inst
,
266 const MachineInstr
&MI
) {
267 MCInst
&MappedInst
= static_cast <MCInst
&>(Inst
);
268 const MCRegisterInfo
*RI
= OutStreamer
->getContext().getRegisterInfo();
269 const MachineFunction
&MF
= *MI
.getParent()->getParent();
270 auto &HRI
= *MF
.getSubtarget
<HexagonSubtarget
>().getRegisterInfo();
271 unsigned VectorSize
= HRI
.getRegSizeInBits(Hexagon::HvxVRRegClass
) / 8;
273 switch (Inst
.getOpcode()) {
277 case Hexagon::A2_iconst
: {
278 Inst
.setOpcode(Hexagon::A2_addi
);
279 MCOperand Reg
= Inst
.getOperand(0);
280 MCOperand S16
= Inst
.getOperand(1);
281 HexagonMCInstrInfo::setMustNotExtend(*S16
.getExpr());
282 HexagonMCInstrInfo::setS27_2_reloc(*S16
.getExpr());
284 Inst
.addOperand(Reg
);
285 Inst
.addOperand(MCOperand::createReg(Hexagon::R0
));
286 Inst
.addOperand(S16
);
290 case Hexagon::A2_tfrf
: {
291 const MCConstantExpr
*Zero
= MCConstantExpr::create(0, OutContext
);
292 Inst
.setOpcode(Hexagon::A2_paddif
);
293 Inst
.addOperand(MCOperand::createExpr(Zero
));
297 case Hexagon::A2_tfrt
: {
298 const MCConstantExpr
*Zero
= MCConstantExpr::create(0, OutContext
);
299 Inst
.setOpcode(Hexagon::A2_paddit
);
300 Inst
.addOperand(MCOperand::createExpr(Zero
));
304 case Hexagon::A2_tfrfnew
: {
305 const MCConstantExpr
*Zero
= MCConstantExpr::create(0, OutContext
);
306 Inst
.setOpcode(Hexagon::A2_paddifnew
);
307 Inst
.addOperand(MCOperand::createExpr(Zero
));
311 case Hexagon::A2_tfrtnew
: {
312 const MCConstantExpr
*Zero
= MCConstantExpr::create(0, OutContext
);
313 Inst
.setOpcode(Hexagon::A2_padditnew
);
314 Inst
.addOperand(MCOperand::createExpr(Zero
));
318 case Hexagon::A2_zxtb
: {
319 const MCConstantExpr
*C255
= MCConstantExpr::create(255, OutContext
);
320 Inst
.setOpcode(Hexagon::A2_andir
);
321 Inst
.addOperand(MCOperand::createExpr(C255
));
325 // "$dst = CONST64(#$src1)",
326 case Hexagon::CONST64
:
327 if (!OutStreamer
->hasRawTextSupport()) {
328 const MCOperand
&Imm
= MappedInst
.getOperand(1);
329 MCSectionSubPair Current
= OutStreamer
->getCurrentSection();
331 MCSymbol
*Sym
= smallData(*this, MI
, *OutStreamer
, Imm
, 8);
333 OutStreamer
->SwitchSection(Current
.first
, Current
.second
);
335 MCOperand
&Reg
= MappedInst
.getOperand(0);
336 TmpInst
.setOpcode(Hexagon::L2_loadrdgp
);
337 TmpInst
.addOperand(Reg
);
338 TmpInst
.addOperand(MCOperand::createExpr(
339 MCSymbolRefExpr::create(Sym
, OutContext
)));
340 MappedInst
= TmpInst
;
344 case Hexagon::CONST32
:
345 if (!OutStreamer
->hasRawTextSupport()) {
346 MCOperand
&Imm
= MappedInst
.getOperand(1);
347 MCSectionSubPair Current
= OutStreamer
->getCurrentSection();
348 MCSymbol
*Sym
= smallData(*this, MI
, *OutStreamer
, Imm
, 4);
349 OutStreamer
->SwitchSection(Current
.first
, Current
.second
);
351 MCOperand
&Reg
= MappedInst
.getOperand(0);
352 TmpInst
.setOpcode(Hexagon::L2_loadrigp
);
353 TmpInst
.addOperand(Reg
);
354 TmpInst
.addOperand(MCOperand::createExpr(HexagonMCExpr::create(
355 MCSymbolRefExpr::create(Sym
, OutContext
), OutContext
)));
356 MappedInst
= TmpInst
;
360 // C2_pxfer_map maps to C2_or instruction. Though, it's possible to use
361 // C2_or during instruction selection itself but it results
362 // into suboptimal code.
363 case Hexagon::C2_pxfer_map
: {
364 MCOperand
&Ps
= Inst
.getOperand(1);
365 MappedInst
.setOpcode(Hexagon::C2_or
);
366 MappedInst
.addOperand(Ps
);
370 // Vector reduce complex multiply by scalar, Rt & 1 map to :hi else :lo
371 // The insn is mapped from the 4 operand to the 3 operand raw form taking
373 case Hexagon::M2_vrcmpys_acc_s1
: {
374 MCOperand
&Rt
= Inst
.getOperand(3);
375 assert(Rt
.isReg() && "Expected register and none was found");
376 unsigned Reg
= RI
->getEncodingValue(Rt
.getReg());
378 MappedInst
.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h
);
380 MappedInst
.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l
);
381 Rt
.setReg(getHexagonRegisterPair(Rt
.getReg(), RI
));
384 case Hexagon::M2_vrcmpys_s1
: {
385 MCOperand
&Rt
= Inst
.getOperand(2);
386 assert(Rt
.isReg() && "Expected register and none was found");
387 unsigned Reg
= RI
->getEncodingValue(Rt
.getReg());
389 MappedInst
.setOpcode(Hexagon::M2_vrcmpys_s1_h
);
391 MappedInst
.setOpcode(Hexagon::M2_vrcmpys_s1_l
);
392 Rt
.setReg(getHexagonRegisterPair(Rt
.getReg(), RI
));
396 case Hexagon::M2_vrcmpys_s1rp
: {
397 MCOperand
&Rt
= Inst
.getOperand(2);
398 assert(Rt
.isReg() && "Expected register and none was found");
399 unsigned Reg
= RI
->getEncodingValue(Rt
.getReg());
401 MappedInst
.setOpcode(Hexagon::M2_vrcmpys_s1rp_h
);
403 MappedInst
.setOpcode(Hexagon::M2_vrcmpys_s1rp_l
);
404 Rt
.setReg(getHexagonRegisterPair(Rt
.getReg(), RI
));
408 case Hexagon::A4_boundscheck
: {
409 MCOperand
&Rs
= Inst
.getOperand(1);
410 assert(Rs
.isReg() && "Expected register and none was found");
411 unsigned Reg
= RI
->getEncodingValue(Rs
.getReg());
412 if (Reg
& 1) // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2
413 MappedInst
.setOpcode(Hexagon::A4_boundscheck_hi
);
415 MappedInst
.setOpcode(Hexagon::A4_boundscheck_lo
);
416 Rs
.setReg(getHexagonRegisterPair(Rs
.getReg(), RI
));
420 case Hexagon::PS_call_nr
:
421 Inst
.setOpcode(Hexagon::J2_call
);
424 case Hexagon::S5_asrhub_rnd_sat_goodsyntax
: {
425 MCOperand
&MO
= MappedInst
.getOperand(2);
427 MCExpr
const *Expr
= MO
.getExpr();
428 bool Success
= Expr
->evaluateAsAbsolute(Imm
);
429 assert(Success
&& "Expected immediate and none was found");
433 TmpInst
.setOpcode(Hexagon::S2_vsathub
);
434 TmpInst
.addOperand(MappedInst
.getOperand(0));
435 TmpInst
.addOperand(MappedInst
.getOperand(1));
436 MappedInst
= TmpInst
;
439 TmpInst
.setOpcode(Hexagon::S5_asrhub_rnd_sat
);
440 TmpInst
.addOperand(MappedInst
.getOperand(0));
441 TmpInst
.addOperand(MappedInst
.getOperand(1));
442 const MCExpr
*One
= MCConstantExpr::create(1, OutContext
);
443 const MCExpr
*Sub
= MCBinaryExpr::createSub(Expr
, One
, OutContext
);
445 MCOperand::createExpr(HexagonMCExpr::create(Sub
, OutContext
)));
446 MappedInst
= TmpInst
;
450 case Hexagon::S5_vasrhrnd_goodsyntax
:
451 case Hexagon::S2_asr_i_p_rnd_goodsyntax
: {
452 MCOperand
&MO2
= MappedInst
.getOperand(2);
453 MCExpr
const *Expr
= MO2
.getExpr();
455 bool Success
= Expr
->evaluateAsAbsolute(Imm
);
456 assert(Success
&& "Expected immediate and none was found");
460 TmpInst
.setOpcode(Hexagon::A2_combinew
);
461 TmpInst
.addOperand(MappedInst
.getOperand(0));
462 MCOperand
&MO1
= MappedInst
.getOperand(1);
463 unsigned High
= RI
->getSubReg(MO1
.getReg(), Hexagon::isub_hi
);
464 unsigned Low
= RI
->getSubReg(MO1
.getReg(), Hexagon::isub_lo
);
465 // Add a new operand for the second register in the pair.
466 TmpInst
.addOperand(MCOperand::createReg(High
));
467 TmpInst
.addOperand(MCOperand::createReg(Low
));
468 MappedInst
= TmpInst
;
472 if (Inst
.getOpcode() == Hexagon::S2_asr_i_p_rnd_goodsyntax
)
473 TmpInst
.setOpcode(Hexagon::S2_asr_i_p_rnd
);
475 TmpInst
.setOpcode(Hexagon::S5_vasrhrnd
);
476 TmpInst
.addOperand(MappedInst
.getOperand(0));
477 TmpInst
.addOperand(MappedInst
.getOperand(1));
478 const MCExpr
*One
= MCConstantExpr::create(1, OutContext
);
479 const MCExpr
*Sub
= MCBinaryExpr::createSub(Expr
, One
, OutContext
);
481 MCOperand::createExpr(HexagonMCExpr::create(Sub
, OutContext
)));
482 MappedInst
= TmpInst
;
486 // if ("#u5==0") Assembler mapped to: "Rd=Rs"; else Rd=asr(Rs,#u5-1):rnd
487 case Hexagon::S2_asr_i_r_rnd_goodsyntax
: {
488 MCOperand
&MO
= Inst
.getOperand(2);
489 MCExpr
const *Expr
= MO
.getExpr();
491 bool Success
= Expr
->evaluateAsAbsolute(Imm
);
492 assert(Success
&& "Expected immediate and none was found");
496 TmpInst
.setOpcode(Hexagon::A2_tfr
);
497 TmpInst
.addOperand(MappedInst
.getOperand(0));
498 TmpInst
.addOperand(MappedInst
.getOperand(1));
499 MappedInst
= TmpInst
;
502 TmpInst
.setOpcode(Hexagon::S2_asr_i_r_rnd
);
503 TmpInst
.addOperand(MappedInst
.getOperand(0));
504 TmpInst
.addOperand(MappedInst
.getOperand(1));
505 const MCExpr
*One
= MCConstantExpr::create(1, OutContext
);
506 const MCExpr
*Sub
= MCBinaryExpr::createSub(Expr
, One
, OutContext
);
508 MCOperand::createExpr(HexagonMCExpr::create(Sub
, OutContext
)));
509 MappedInst
= TmpInst
;
513 // Translate a "$Rdd = #imm" to "$Rdd = combine(#[-1,0], #imm)"
514 case Hexagon::A2_tfrpi
: {
516 MCOperand
&Rdd
= MappedInst
.getOperand(0);
517 MCOperand
&MO
= MappedInst
.getOperand(1);
519 TmpInst
.setOpcode(Hexagon::A2_combineii
);
520 TmpInst
.addOperand(Rdd
);
522 bool Success
= MO
.getExpr()->evaluateAsAbsolute(Imm
);
523 if (Success
&& Imm
< 0) {
524 const MCExpr
*MOne
= MCConstantExpr::create(-1, OutContext
);
525 const HexagonMCExpr
*E
= HexagonMCExpr::create(MOne
, OutContext
);
526 TmpInst
.addOperand(MCOperand::createExpr(E
));
528 const MCExpr
*Zero
= MCConstantExpr::create(0, OutContext
);
529 const HexagonMCExpr
*E
= HexagonMCExpr::create(Zero
, OutContext
);
530 TmpInst
.addOperand(MCOperand::createExpr(E
));
532 TmpInst
.addOperand(MO
);
533 MappedInst
= TmpInst
;
537 // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)"
538 case Hexagon::A2_tfrp
: {
539 MCOperand
&MO
= MappedInst
.getOperand(1);
540 unsigned High
= RI
->getSubReg(MO
.getReg(), Hexagon::isub_hi
);
541 unsigned Low
= RI
->getSubReg(MO
.getReg(), Hexagon::isub_lo
);
543 // Add a new operand for the second register in the pair.
544 MappedInst
.addOperand(MCOperand::createReg(Low
));
545 MappedInst
.setOpcode(Hexagon::A2_combinew
);
549 case Hexagon::A2_tfrpt
:
550 case Hexagon::A2_tfrpf
: {
551 MCOperand
&MO
= MappedInst
.getOperand(2);
552 unsigned High
= RI
->getSubReg(MO
.getReg(), Hexagon::isub_hi
);
553 unsigned Low
= RI
->getSubReg(MO
.getReg(), Hexagon::isub_lo
);
555 // Add a new operand for the second register in the pair.
556 MappedInst
.addOperand(MCOperand::createReg(Low
));
557 MappedInst
.setOpcode((Inst
.getOpcode() == Hexagon::A2_tfrpt
)
558 ? Hexagon::C2_ccombinewt
559 : Hexagon::C2_ccombinewf
);
563 case Hexagon::A2_tfrptnew
:
564 case Hexagon::A2_tfrpfnew
: {
565 MCOperand
&MO
= MappedInst
.getOperand(2);
566 unsigned High
= RI
->getSubReg(MO
.getReg(), Hexagon::isub_hi
);
567 unsigned Low
= RI
->getSubReg(MO
.getReg(), Hexagon::isub_lo
);
569 // Add a new operand for the second register in the pair.
570 MappedInst
.addOperand(MCOperand::createReg(Low
));
571 MappedInst
.setOpcode(Inst
.getOpcode() == Hexagon::A2_tfrptnew
572 ? Hexagon::C2_ccombinewnewt
573 : Hexagon::C2_ccombinewnewf
);
577 case Hexagon::M2_mpysmi
: {
578 MCOperand
&Imm
= MappedInst
.getOperand(2);
579 MCExpr
const *Expr
= Imm
.getExpr();
581 bool Success
= Expr
->evaluateAsAbsolute(Value
);
584 if (Value
< 0 && Value
> -256) {
585 MappedInst
.setOpcode(Hexagon::M2_mpysin
);
586 Imm
.setExpr(HexagonMCExpr::create(
587 MCUnaryExpr::createMinus(Expr
, OutContext
), OutContext
));
589 MappedInst
.setOpcode(Hexagon::M2_mpysip
);
593 case Hexagon::A2_addsp
: {
594 MCOperand
&Rt
= Inst
.getOperand(1);
595 assert(Rt
.isReg() && "Expected register and none was found");
596 unsigned Reg
= RI
->getEncodingValue(Rt
.getReg());
598 MappedInst
.setOpcode(Hexagon::A2_addsph
);
600 MappedInst
.setOpcode(Hexagon::A2_addspl
);
601 Rt
.setReg(getHexagonRegisterPair(Rt
.getReg(), RI
));
605 case Hexagon::V6_vd0
: {
607 assert(Inst
.getOperand(0).isReg() &&
608 "Expected register and none was found");
610 TmpInst
.setOpcode(Hexagon::V6_vxor
);
611 TmpInst
.addOperand(Inst
.getOperand(0));
612 TmpInst
.addOperand(Inst
.getOperand(0));
613 TmpInst
.addOperand(Inst
.getOperand(0));
614 MappedInst
= TmpInst
;
618 case Hexagon::V6_vdd0
: {
620 assert (Inst
.getOperand(0).isReg() &&
621 "Expected register and none was found");
623 TmpInst
.setOpcode(Hexagon::V6_vsubw_dv
);
624 TmpInst
.addOperand(Inst
.getOperand(0));
625 TmpInst
.addOperand(Inst
.getOperand(0));
626 TmpInst
.addOperand(Inst
.getOperand(0));
627 MappedInst
= TmpInst
;
631 case Hexagon::V6_vL32Ub_pi
:
632 case Hexagon::V6_vL32b_cur_pi
:
633 case Hexagon::V6_vL32b_nt_cur_pi
:
634 case Hexagon::V6_vL32b_pi
:
635 case Hexagon::V6_vL32b_nt_pi
:
636 case Hexagon::V6_vL32b_nt_tmp_pi
:
637 case Hexagon::V6_vL32b_tmp_pi
:
638 MappedInst
= ScaleVectorOffset(Inst
, 3, VectorSize
, OutContext
);
641 case Hexagon::V6_vL32Ub_ai
:
642 case Hexagon::V6_vL32b_ai
:
643 case Hexagon::V6_vL32b_cur_ai
:
644 case Hexagon::V6_vL32b_nt_ai
:
645 case Hexagon::V6_vL32b_nt_cur_ai
:
646 case Hexagon::V6_vL32b_nt_tmp_ai
:
647 case Hexagon::V6_vL32b_tmp_ai
:
648 MappedInst
= ScaleVectorOffset(Inst
, 2, VectorSize
, OutContext
);
651 case Hexagon::V6_vS32Ub_pi
:
652 case Hexagon::V6_vS32b_new_pi
:
653 case Hexagon::V6_vS32b_nt_new_pi
:
654 case Hexagon::V6_vS32b_nt_pi
:
655 case Hexagon::V6_vS32b_pi
:
656 MappedInst
= ScaleVectorOffset(Inst
, 2, VectorSize
, OutContext
);
659 case Hexagon::V6_vS32Ub_ai
:
660 case Hexagon::V6_vS32b_ai
:
661 case Hexagon::V6_vS32b_new_ai
:
662 case Hexagon::V6_vS32b_nt_ai
:
663 case Hexagon::V6_vS32b_nt_new_ai
:
664 MappedInst
= ScaleVectorOffset(Inst
, 1, VectorSize
, OutContext
);
667 case Hexagon::V6_vL32b_cur_npred_pi
:
668 case Hexagon::V6_vL32b_cur_pred_pi
:
669 case Hexagon::V6_vL32b_npred_pi
:
670 case Hexagon::V6_vL32b_nt_cur_npred_pi
:
671 case Hexagon::V6_vL32b_nt_cur_pred_pi
:
672 case Hexagon::V6_vL32b_nt_npred_pi
:
673 case Hexagon::V6_vL32b_nt_pred_pi
:
674 case Hexagon::V6_vL32b_nt_tmp_npred_pi
:
675 case Hexagon::V6_vL32b_nt_tmp_pred_pi
:
676 case Hexagon::V6_vL32b_pred_pi
:
677 case Hexagon::V6_vL32b_tmp_npred_pi
:
678 case Hexagon::V6_vL32b_tmp_pred_pi
:
679 MappedInst
= ScaleVectorOffset(Inst
, 4, VectorSize
, OutContext
);
682 case Hexagon::V6_vL32b_cur_npred_ai
:
683 case Hexagon::V6_vL32b_cur_pred_ai
:
684 case Hexagon::V6_vL32b_npred_ai
:
685 case Hexagon::V6_vL32b_nt_cur_npred_ai
:
686 case Hexagon::V6_vL32b_nt_cur_pred_ai
:
687 case Hexagon::V6_vL32b_nt_npred_ai
:
688 case Hexagon::V6_vL32b_nt_pred_ai
:
689 case Hexagon::V6_vL32b_nt_tmp_npred_ai
:
690 case Hexagon::V6_vL32b_nt_tmp_pred_ai
:
691 case Hexagon::V6_vL32b_pred_ai
:
692 case Hexagon::V6_vL32b_tmp_npred_ai
:
693 case Hexagon::V6_vL32b_tmp_pred_ai
:
694 MappedInst
= ScaleVectorOffset(Inst
, 3, VectorSize
, OutContext
);
697 case Hexagon::V6_vS32Ub_npred_pi
:
698 case Hexagon::V6_vS32Ub_pred_pi
:
699 case Hexagon::V6_vS32b_new_npred_pi
:
700 case Hexagon::V6_vS32b_new_pred_pi
:
701 case Hexagon::V6_vS32b_npred_pi
:
702 case Hexagon::V6_vS32b_nqpred_pi
:
703 case Hexagon::V6_vS32b_nt_new_npred_pi
:
704 case Hexagon::V6_vS32b_nt_new_pred_pi
:
705 case Hexagon::V6_vS32b_nt_npred_pi
:
706 case Hexagon::V6_vS32b_nt_nqpred_pi
:
707 case Hexagon::V6_vS32b_nt_pred_pi
:
708 case Hexagon::V6_vS32b_nt_qpred_pi
:
709 case Hexagon::V6_vS32b_pred_pi
:
710 case Hexagon::V6_vS32b_qpred_pi
:
711 MappedInst
= ScaleVectorOffset(Inst
, 3, VectorSize
, OutContext
);
714 case Hexagon::V6_vS32Ub_npred_ai
:
715 case Hexagon::V6_vS32Ub_pred_ai
:
716 case Hexagon::V6_vS32b_new_npred_ai
:
717 case Hexagon::V6_vS32b_new_pred_ai
:
718 case Hexagon::V6_vS32b_npred_ai
:
719 case Hexagon::V6_vS32b_nqpred_ai
:
720 case Hexagon::V6_vS32b_nt_new_npred_ai
:
721 case Hexagon::V6_vS32b_nt_new_pred_ai
:
722 case Hexagon::V6_vS32b_nt_npred_ai
:
723 case Hexagon::V6_vS32b_nt_nqpred_ai
:
724 case Hexagon::V6_vS32b_nt_pred_ai
:
725 case Hexagon::V6_vS32b_nt_qpred_ai
:
726 case Hexagon::V6_vS32b_pred_ai
:
727 case Hexagon::V6_vS32b_qpred_ai
:
728 MappedInst
= ScaleVectorOffset(Inst
, 2, VectorSize
, OutContext
);
732 case Hexagon::V6_vS32b_srls_ai
:
733 MappedInst
= ScaleVectorOffset(Inst
, 1, VectorSize
, OutContext
);
736 case Hexagon::V6_vS32b_srls_pi
:
737 MappedInst
= ScaleVectorOffset(Inst
, 2, VectorSize
, OutContext
);
742 /// Print out a single Hexagon MI to the current output stream.
743 void HexagonAsmPrinter::EmitInstruction(const MachineInstr
*MI
) {
745 MCB
.setOpcode(Hexagon::BUNDLE
);
746 MCB
.addOperand(MCOperand::createImm(0));
747 const MCInstrInfo
&MCII
= *Subtarget
->getInstrInfo();
749 if (MI
->isBundle()) {
750 const MachineBasicBlock
* MBB
= MI
->getParent();
751 MachineBasicBlock::const_instr_iterator MII
= MI
->getIterator();
753 for (++MII
; MII
!= MBB
->instr_end() && MII
->isInsideBundle(); ++MII
)
754 if (!MII
->isDebugInstr() && !MII
->isImplicitDef())
755 HexagonLowerToMC(MCII
, &*MII
, MCB
, *this);
757 HexagonLowerToMC(MCII
, MI
, MCB
, *this);
760 const MachineFunction
&MF
= *MI
->getParent()->getParent();
761 const auto &HII
= *MF
.getSubtarget
<HexagonSubtarget
>().getInstrInfo();
762 if (MI
->isBundle() && HII
.getBundleNoShuf(*MI
))
763 HexagonMCInstrInfo::setMemReorderDisabled(MCB
);
765 MCContext
&Ctx
= OutStreamer
->getContext();
766 bool Ok
= HexagonMCInstrInfo::canonicalizePacket(MCII
, *Subtarget
, Ctx
,
768 assert(Ok
); (void)Ok
;
769 if (HexagonMCInstrInfo::bundleSize(MCB
) == 0)
771 OutStreamer
->EmitInstruction(MCB
, getSubtargetInfo());
774 extern "C" void LLVMInitializeHexagonAsmPrinter() {
775 RegisterAsmPrinter
<HexagonAsmPrinter
> X(getTheHexagonTarget());