/src/llvm-project/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- HexagonAsmPrinter.cpp - Print machine instrs to Hexagon assembly ---===// |
2 | | // |
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 |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
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'. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #include "HexagonAsmPrinter.h" |
16 | | #include "Hexagon.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/MC/TargetRegistry.h" |
45 | | #include "llvm/Support/Casting.h" |
46 | | #include "llvm/Support/CommandLine.h" |
47 | | #include "llvm/Support/ErrorHandling.h" |
48 | | #include "llvm/Support/raw_ostream.h" |
49 | | #include <algorithm> |
50 | | #include <cassert> |
51 | | #include <cstdint> |
52 | | #include <string> |
53 | | |
54 | | using namespace llvm; |
55 | | |
56 | | namespace llvm { |
57 | | |
58 | | void HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI, |
59 | | MCInst &MCB, HexagonAsmPrinter &AP); |
60 | | |
61 | | } // end namespace llvm |
62 | | |
63 | | #define DEBUG_TYPE "asm-printer" |
64 | | |
65 | | // Given a scalar register return its pair. |
66 | | inline static unsigned getHexagonRegisterPair(unsigned Reg, |
67 | 0 | const MCRegisterInfo *RI) { |
68 | 0 | assert(Hexagon::IntRegsRegClass.contains(Reg)); |
69 | 0 | unsigned Pair = *RI->superregs(Reg).begin(); |
70 | 0 | assert(Hexagon::DoubleRegsRegClass.contains(Pair)); |
71 | 0 | return Pair; |
72 | 0 | } |
73 | | |
74 | | void HexagonAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, |
75 | 0 | raw_ostream &O) { |
76 | 0 | const MachineOperand &MO = MI->getOperand(OpNo); |
77 | |
|
78 | 0 | switch (MO.getType()) { |
79 | 0 | default: |
80 | 0 | llvm_unreachable ("<unknown operand type>"); |
81 | 0 | case MachineOperand::MO_Register: |
82 | 0 | O << HexagonInstPrinter::getRegisterName(MO.getReg()); |
83 | 0 | return; |
84 | 0 | case MachineOperand::MO_Immediate: |
85 | 0 | O << MO.getImm(); |
86 | 0 | return; |
87 | 0 | case MachineOperand::MO_MachineBasicBlock: |
88 | 0 | MO.getMBB()->getSymbol()->print(O, MAI); |
89 | 0 | return; |
90 | 0 | case MachineOperand::MO_ConstantPoolIndex: |
91 | 0 | GetCPISymbol(MO.getIndex())->print(O, MAI); |
92 | 0 | return; |
93 | 0 | case MachineOperand::MO_GlobalAddress: |
94 | 0 | PrintSymbolOperand(MO, O); |
95 | 0 | return; |
96 | 0 | } |
97 | 0 | } |
98 | | |
99 | | // isBlockOnlyReachableByFallthrough - We need to override this since the |
100 | | // default AsmPrinter does not print labels for any basic block that |
101 | | // is only reachable by a fall through. That works for all cases except |
102 | | // for the case in which the basic block is reachable by a fall through but |
103 | | // through an indirect from a jump table. In this case, the jump table |
104 | | // will contain a label not defined by AsmPrinter. |
105 | | bool HexagonAsmPrinter::isBlockOnlyReachableByFallthrough( |
106 | 3.16k | const MachineBasicBlock *MBB) const { |
107 | 3.16k | if (MBB->hasAddressTaken()) |
108 | 0 | return false; |
109 | 3.16k | return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); |
110 | 3.16k | } |
111 | | |
112 | | /// PrintAsmOperand - Print out an operand for an inline asm expression. |
113 | | bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, |
114 | | const char *ExtraCode, |
115 | 0 | raw_ostream &OS) { |
116 | | // Does this asm operand have a single letter operand modifier? |
117 | 0 | if (ExtraCode && ExtraCode[0]) { |
118 | 0 | if (ExtraCode[1] != 0) |
119 | 0 | return true; // Unknown modifier. |
120 | | |
121 | 0 | switch (ExtraCode[0]) { |
122 | 0 | default: |
123 | | // See if this is a generic print operand |
124 | 0 | return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); |
125 | 0 | case 'L': |
126 | 0 | case 'H': { // The highest-numbered register of a pair. |
127 | 0 | const MachineOperand &MO = MI->getOperand(OpNo); |
128 | 0 | const MachineFunction &MF = *MI->getParent()->getParent(); |
129 | 0 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); |
130 | 0 | if (!MO.isReg()) |
131 | 0 | return true; |
132 | 0 | Register RegNumber = MO.getReg(); |
133 | | // This should be an assert in the frontend. |
134 | 0 | if (Hexagon::DoubleRegsRegClass.contains(RegNumber)) |
135 | 0 | RegNumber = TRI->getSubReg(RegNumber, ExtraCode[0] == 'L' ? |
136 | 0 | Hexagon::isub_lo : |
137 | 0 | Hexagon::isub_hi); |
138 | 0 | OS << HexagonInstPrinter::getRegisterName(RegNumber); |
139 | 0 | return false; |
140 | 0 | } |
141 | 0 | case 'I': |
142 | | // Write 'i' if an integer constant, otherwise nothing. Used to print |
143 | | // addi vs add, etc. |
144 | 0 | if (MI->getOperand(OpNo).isImm()) |
145 | 0 | OS << "i"; |
146 | 0 | return false; |
147 | 0 | } |
148 | 0 | } |
149 | | |
150 | 0 | printOperand(MI, OpNo, OS); |
151 | 0 | return false; |
152 | 0 | } |
153 | | |
154 | | bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, |
155 | | unsigned OpNo, |
156 | | const char *ExtraCode, |
157 | 0 | raw_ostream &O) { |
158 | 0 | if (ExtraCode && ExtraCode[0]) |
159 | 0 | return true; // Unknown modifier. |
160 | | |
161 | 0 | const MachineOperand &Base = MI->getOperand(OpNo); |
162 | 0 | const MachineOperand &Offset = MI->getOperand(OpNo+1); |
163 | |
|
164 | 0 | if (Base.isReg()) |
165 | 0 | printOperand(MI, OpNo, O); |
166 | 0 | else |
167 | 0 | llvm_unreachable("Unimplemented"); |
168 | |
|
169 | 0 | if (Offset.isImm()) { |
170 | 0 | if (Offset.getImm()) |
171 | 0 | O << "+#" << Offset.getImm(); |
172 | 0 | } else { |
173 | 0 | llvm_unreachable("Unimplemented"); |
174 | 0 | } |
175 | |
|
176 | 0 | return false; |
177 | 0 | } |
178 | | |
179 | | static MCSymbol *smallData(AsmPrinter &AP, const MachineInstr &MI, |
180 | | MCStreamer &OutStreamer, const MCOperand &Imm, |
181 | 0 | int AlignSize, const MCSubtargetInfo& STI) { |
182 | 0 | MCSymbol *Sym; |
183 | 0 | int64_t Value; |
184 | 0 | if (Imm.getExpr()->evaluateAsAbsolute(Value)) { |
185 | 0 | StringRef sectionPrefix; |
186 | 0 | std::string ImmString; |
187 | 0 | StringRef Name; |
188 | 0 | if (AlignSize == 8) { |
189 | 0 | Name = ".CONST_0000000000000000"; |
190 | 0 | sectionPrefix = ".gnu.linkonce.l8"; |
191 | 0 | ImmString = utohexstr(Value); |
192 | 0 | } else { |
193 | 0 | Name = ".CONST_00000000"; |
194 | 0 | sectionPrefix = ".gnu.linkonce.l4"; |
195 | 0 | ImmString = utohexstr(static_cast<uint32_t>(Value)); |
196 | 0 | } |
197 | |
|
198 | 0 | std::string symbolName = // Yes, leading zeros are kept. |
199 | 0 | Name.drop_back(ImmString.size()).str() + ImmString; |
200 | 0 | std::string sectionName = sectionPrefix.str() + symbolName; |
201 | |
|
202 | 0 | MCSectionELF *Section = OutStreamer.getContext().getELFSection( |
203 | 0 | sectionName, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); |
204 | 0 | OutStreamer.switchSection(Section); |
205 | |
|
206 | 0 | Sym = AP.OutContext.getOrCreateSymbol(Twine(symbolName)); |
207 | 0 | if (Sym->isUndefined()) { |
208 | 0 | OutStreamer.emitLabel(Sym); |
209 | 0 | OutStreamer.emitSymbolAttribute(Sym, MCSA_Global); |
210 | 0 | OutStreamer.emitIntValue(Value, AlignSize); |
211 | 0 | OutStreamer.emitCodeAlignment(Align(AlignSize), &STI); |
212 | 0 | } |
213 | 0 | } else { |
214 | 0 | assert(Imm.isExpr() && "Expected expression and found none"); |
215 | 0 | const MachineOperand &MO = MI.getOperand(1); |
216 | 0 | assert(MO.isGlobal() || MO.isCPI() || MO.isJTI()); |
217 | 0 | MCSymbol *MOSymbol = nullptr; |
218 | 0 | if (MO.isGlobal()) |
219 | 0 | MOSymbol = AP.getSymbol(MO.getGlobal()); |
220 | 0 | else if (MO.isCPI()) |
221 | 0 | MOSymbol = AP.GetCPISymbol(MO.getIndex()); |
222 | 0 | else if (MO.isJTI()) |
223 | 0 | MOSymbol = AP.GetJTISymbol(MO.getIndex()); |
224 | 0 | else |
225 | 0 | llvm_unreachable("Unknown operand type!"); |
226 | |
|
227 | 0 | StringRef SymbolName = MOSymbol->getName(); |
228 | 0 | std::string LitaName = ".CONST_" + SymbolName.str(); |
229 | |
|
230 | 0 | MCSectionELF *Section = OutStreamer.getContext().getELFSection( |
231 | 0 | ".lita", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); |
232 | |
|
233 | 0 | OutStreamer.switchSection(Section); |
234 | 0 | Sym = AP.OutContext.getOrCreateSymbol(Twine(LitaName)); |
235 | 0 | if (Sym->isUndefined()) { |
236 | 0 | OutStreamer.emitLabel(Sym); |
237 | 0 | OutStreamer.emitSymbolAttribute(Sym, MCSA_Local); |
238 | 0 | OutStreamer.emitValue(Imm.getExpr(), AlignSize); |
239 | 0 | OutStreamer.emitCodeAlignment(Align(AlignSize), &STI); |
240 | 0 | } |
241 | 0 | } |
242 | 0 | return Sym; |
243 | 0 | } |
244 | | |
245 | | static MCInst ScaleVectorOffset(MCInst &Inst, unsigned OpNo, |
246 | 0 | unsigned VectorSize, MCContext &Ctx) { |
247 | 0 | MCInst T; |
248 | 0 | T.setOpcode(Inst.getOpcode()); |
249 | 0 | for (unsigned i = 0, n = Inst.getNumOperands(); i != n; ++i) { |
250 | 0 | if (i != OpNo) { |
251 | 0 | T.addOperand(Inst.getOperand(i)); |
252 | 0 | continue; |
253 | 0 | } |
254 | 0 | MCOperand &ImmOp = Inst.getOperand(i); |
255 | 0 | const auto *HE = static_cast<const HexagonMCExpr*>(ImmOp.getExpr()); |
256 | 0 | int32_t V = cast<MCConstantExpr>(HE->getExpr())->getValue(); |
257 | 0 | auto *NewCE = MCConstantExpr::create(V / int32_t(VectorSize), Ctx); |
258 | 0 | auto *NewHE = HexagonMCExpr::create(NewCE, Ctx); |
259 | 0 | T.addOperand(MCOperand::createExpr(NewHE)); |
260 | 0 | } |
261 | 0 | return T; |
262 | 0 | } |
263 | | |
264 | | void HexagonAsmPrinter::HexagonProcessInstruction(MCInst &Inst, |
265 | 671k | const MachineInstr &MI) { |
266 | 671k | MCInst &MappedInst = static_cast <MCInst &>(Inst); |
267 | 671k | const MCRegisterInfo *RI = OutStreamer->getContext().getRegisterInfo(); |
268 | 671k | const MachineFunction &MF = *MI.getParent()->getParent(); |
269 | 671k | auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo(); |
270 | 671k | unsigned VectorSize = HRI.getRegSizeInBits(Hexagon::HvxVRRegClass) / 8; |
271 | | |
272 | 671k | switch (Inst.getOpcode()) { |
273 | 642k | default: |
274 | 642k | return; |
275 | | |
276 | 642k | case Hexagon::A2_iconst: { |
277 | 0 | Inst.setOpcode(Hexagon::A2_addi); |
278 | 0 | MCOperand Reg = Inst.getOperand(0); |
279 | 0 | MCOperand S16 = Inst.getOperand(1); |
280 | 0 | HexagonMCInstrInfo::setMustNotExtend(*S16.getExpr()); |
281 | 0 | HexagonMCInstrInfo::setS27_2_reloc(*S16.getExpr()); |
282 | 0 | Inst.clear(); |
283 | 0 | Inst.addOperand(Reg); |
284 | 0 | Inst.addOperand(MCOperand::createReg(Hexagon::R0)); |
285 | 0 | Inst.addOperand(S16); |
286 | 0 | break; |
287 | 0 | } |
288 | | |
289 | 88 | case Hexagon::A2_tfrf: { |
290 | 88 | const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext); |
291 | 88 | Inst.setOpcode(Hexagon::A2_paddif); |
292 | 88 | Inst.addOperand(MCOperand::createExpr(Zero)); |
293 | 88 | break; |
294 | 0 | } |
295 | | |
296 | 2 | case Hexagon::A2_tfrt: { |
297 | 2 | const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext); |
298 | 2 | Inst.setOpcode(Hexagon::A2_paddit); |
299 | 2 | Inst.addOperand(MCOperand::createExpr(Zero)); |
300 | 2 | break; |
301 | 0 | } |
302 | | |
303 | 6 | case Hexagon::A2_tfrfnew: { |
304 | 6 | const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext); |
305 | 6 | Inst.setOpcode(Hexagon::A2_paddifnew); |
306 | 6 | Inst.addOperand(MCOperand::createExpr(Zero)); |
307 | 6 | break; |
308 | 0 | } |
309 | | |
310 | 0 | case Hexagon::A2_tfrtnew: { |
311 | 0 | const MCConstantExpr *Zero = MCConstantExpr::create(0, OutContext); |
312 | 0 | Inst.setOpcode(Hexagon::A2_padditnew); |
313 | 0 | Inst.addOperand(MCOperand::createExpr(Zero)); |
314 | 0 | break; |
315 | 0 | } |
316 | | |
317 | 1.22k | case Hexagon::A2_zxtb: { |
318 | 1.22k | const MCConstantExpr *C255 = MCConstantExpr::create(255, OutContext); |
319 | 1.22k | Inst.setOpcode(Hexagon::A2_andir); |
320 | 1.22k | Inst.addOperand(MCOperand::createExpr(C255)); |
321 | 1.22k | break; |
322 | 0 | } |
323 | | |
324 | | // "$dst = CONST64(#$src1)", |
325 | 6.41k | case Hexagon::CONST64: |
326 | 6.41k | if (!OutStreamer->hasRawTextSupport()) { |
327 | 0 | const MCOperand &Imm = MappedInst.getOperand(1); |
328 | 0 | MCSectionSubPair Current = OutStreamer->getCurrentSection(); |
329 | |
|
330 | 0 | MCSymbol *Sym = |
331 | 0 | smallData(*this, MI, *OutStreamer, Imm, 8, getSubtargetInfo()); |
332 | |
|
333 | 0 | OutStreamer->switchSection(Current.first, Current.second); |
334 | 0 | MCInst TmpInst; |
335 | 0 | MCOperand &Reg = MappedInst.getOperand(0); |
336 | 0 | TmpInst.setOpcode(Hexagon::L2_loadrdgp); |
337 | 0 | TmpInst.addOperand(Reg); |
338 | 0 | TmpInst.addOperand(MCOperand::createExpr( |
339 | 0 | MCSymbolRefExpr::create(Sym, OutContext))); |
340 | 0 | MappedInst = TmpInst; |
341 | |
|
342 | 0 | } |
343 | 6.41k | break; |
344 | 0 | case Hexagon::CONST32: |
345 | 0 | if (!OutStreamer->hasRawTextSupport()) { |
346 | 0 | MCOperand &Imm = MappedInst.getOperand(1); |
347 | 0 | MCSectionSubPair Current = OutStreamer->getCurrentSection(); |
348 | 0 | MCSymbol *Sym = |
349 | 0 | smallData(*this, MI, *OutStreamer, Imm, 4, getSubtargetInfo()); |
350 | 0 | OutStreamer->switchSection(Current.first, Current.second); |
351 | 0 | MCInst TmpInst; |
352 | 0 | MCOperand &Reg = MappedInst.getOperand(0); |
353 | 0 | TmpInst.setOpcode(Hexagon::L2_loadrigp); |
354 | 0 | TmpInst.addOperand(Reg); |
355 | 0 | TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create( |
356 | 0 | MCSymbolRefExpr::create(Sym, OutContext), OutContext))); |
357 | 0 | MappedInst = TmpInst; |
358 | 0 | } |
359 | 0 | break; |
360 | | |
361 | | // C2_pxfer_map maps to C2_or instruction. Though, it's possible to use |
362 | | // C2_or during instruction selection itself but it results |
363 | | // into suboptimal code. |
364 | 0 | case Hexagon::C2_pxfer_map: { |
365 | 0 | MCOperand &Ps = Inst.getOperand(1); |
366 | 0 | MappedInst.setOpcode(Hexagon::C2_or); |
367 | 0 | MappedInst.addOperand(Ps); |
368 | 0 | return; |
369 | 0 | } |
370 | | |
371 | | // Vector reduce complex multiply by scalar, Rt & 1 map to :hi else :lo |
372 | | // The insn is mapped from the 4 operand to the 3 operand raw form taking |
373 | | // 3 register pairs. |
374 | 0 | case Hexagon::M2_vrcmpys_acc_s1: { |
375 | 0 | MCOperand &Rt = Inst.getOperand(3); |
376 | 0 | assert(Rt.isReg() && "Expected register and none was found"); |
377 | 0 | unsigned Reg = RI->getEncodingValue(Rt.getReg()); |
378 | 0 | if (Reg & 1) |
379 | 0 | MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h); |
380 | 0 | else |
381 | 0 | MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l); |
382 | 0 | Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); |
383 | 0 | return; |
384 | 0 | } |
385 | 0 | case Hexagon::M2_vrcmpys_s1: { |
386 | 0 | MCOperand &Rt = Inst.getOperand(2); |
387 | 0 | assert(Rt.isReg() && "Expected register and none was found"); |
388 | 0 | unsigned Reg = RI->getEncodingValue(Rt.getReg()); |
389 | 0 | if (Reg & 1) |
390 | 0 | MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_h); |
391 | 0 | else |
392 | 0 | MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_l); |
393 | 0 | Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); |
394 | 0 | return; |
395 | 0 | } |
396 | | |
397 | 0 | case Hexagon::M2_vrcmpys_s1rp: { |
398 | 0 | MCOperand &Rt = Inst.getOperand(2); |
399 | 0 | assert(Rt.isReg() && "Expected register and none was found"); |
400 | 0 | unsigned Reg = RI->getEncodingValue(Rt.getReg()); |
401 | 0 | if (Reg & 1) |
402 | 0 | MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h); |
403 | 0 | else |
404 | 0 | MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l); |
405 | 0 | Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); |
406 | 0 | return; |
407 | 0 | } |
408 | | |
409 | 0 | case Hexagon::A4_boundscheck: { |
410 | 0 | MCOperand &Rs = Inst.getOperand(1); |
411 | 0 | assert(Rs.isReg() && "Expected register and none was found"); |
412 | 0 | unsigned Reg = RI->getEncodingValue(Rs.getReg()); |
413 | 0 | if (Reg & 1) // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2 |
414 | 0 | MappedInst.setOpcode(Hexagon::A4_boundscheck_hi); |
415 | 0 | else // raw:lo |
416 | 0 | MappedInst.setOpcode(Hexagon::A4_boundscheck_lo); |
417 | 0 | Rs.setReg(getHexagonRegisterPair(Rs.getReg(), RI)); |
418 | 0 | return; |
419 | 0 | } |
420 | | |
421 | 0 | case Hexagon::PS_call_nr: |
422 | 0 | Inst.setOpcode(Hexagon::J2_call); |
423 | 0 | break; |
424 | | |
425 | 0 | case Hexagon::S5_asrhub_rnd_sat_goodsyntax: { |
426 | 0 | MCOperand &MO = MappedInst.getOperand(2); |
427 | 0 | int64_t Imm; |
428 | 0 | MCExpr const *Expr = MO.getExpr(); |
429 | 0 | bool Success = Expr->evaluateAsAbsolute(Imm); |
430 | 0 | assert(Success && "Expected immediate and none was found"); |
431 | 0 | (void)Success; |
432 | 0 | MCInst TmpInst; |
433 | 0 | if (Imm == 0) { |
434 | 0 | TmpInst.setOpcode(Hexagon::S2_vsathub); |
435 | 0 | TmpInst.addOperand(MappedInst.getOperand(0)); |
436 | 0 | TmpInst.addOperand(MappedInst.getOperand(1)); |
437 | 0 | MappedInst = TmpInst; |
438 | 0 | return; |
439 | 0 | } |
440 | 0 | TmpInst.setOpcode(Hexagon::S5_asrhub_rnd_sat); |
441 | 0 | TmpInst.addOperand(MappedInst.getOperand(0)); |
442 | 0 | TmpInst.addOperand(MappedInst.getOperand(1)); |
443 | 0 | const MCExpr *One = MCConstantExpr::create(1, OutContext); |
444 | 0 | const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext); |
445 | 0 | TmpInst.addOperand( |
446 | 0 | MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext))); |
447 | 0 | MappedInst = TmpInst; |
448 | 0 | return; |
449 | 0 | } |
450 | | |
451 | 0 | case Hexagon::S5_vasrhrnd_goodsyntax: |
452 | 0 | case Hexagon::S2_asr_i_p_rnd_goodsyntax: { |
453 | 0 | MCOperand &MO2 = MappedInst.getOperand(2); |
454 | 0 | MCExpr const *Expr = MO2.getExpr(); |
455 | 0 | int64_t Imm; |
456 | 0 | bool Success = Expr->evaluateAsAbsolute(Imm); |
457 | 0 | assert(Success && "Expected immediate and none was found"); |
458 | 0 | (void)Success; |
459 | 0 | MCInst TmpInst; |
460 | 0 | if (Imm == 0) { |
461 | 0 | TmpInst.setOpcode(Hexagon::A2_combinew); |
462 | 0 | TmpInst.addOperand(MappedInst.getOperand(0)); |
463 | 0 | MCOperand &MO1 = MappedInst.getOperand(1); |
464 | 0 | unsigned High = RI->getSubReg(MO1.getReg(), Hexagon::isub_hi); |
465 | 0 | unsigned Low = RI->getSubReg(MO1.getReg(), Hexagon::isub_lo); |
466 | | // Add a new operand for the second register in the pair. |
467 | 0 | TmpInst.addOperand(MCOperand::createReg(High)); |
468 | 0 | TmpInst.addOperand(MCOperand::createReg(Low)); |
469 | 0 | MappedInst = TmpInst; |
470 | 0 | return; |
471 | 0 | } |
472 | | |
473 | 0 | if (Inst.getOpcode() == Hexagon::S2_asr_i_p_rnd_goodsyntax) |
474 | 0 | TmpInst.setOpcode(Hexagon::S2_asr_i_p_rnd); |
475 | 0 | else |
476 | 0 | TmpInst.setOpcode(Hexagon::S5_vasrhrnd); |
477 | 0 | TmpInst.addOperand(MappedInst.getOperand(0)); |
478 | 0 | TmpInst.addOperand(MappedInst.getOperand(1)); |
479 | 0 | const MCExpr *One = MCConstantExpr::create(1, OutContext); |
480 | 0 | const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext); |
481 | 0 | TmpInst.addOperand( |
482 | 0 | MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext))); |
483 | 0 | MappedInst = TmpInst; |
484 | 0 | return; |
485 | 0 | } |
486 | | |
487 | | // if ("#u5==0") Assembler mapped to: "Rd=Rs"; else Rd=asr(Rs,#u5-1):rnd |
488 | 0 | case Hexagon::S2_asr_i_r_rnd_goodsyntax: { |
489 | 0 | MCOperand &MO = Inst.getOperand(2); |
490 | 0 | MCExpr const *Expr = MO.getExpr(); |
491 | 0 | int64_t Imm; |
492 | 0 | bool Success = Expr->evaluateAsAbsolute(Imm); |
493 | 0 | assert(Success && "Expected immediate and none was found"); |
494 | 0 | (void)Success; |
495 | 0 | MCInst TmpInst; |
496 | 0 | if (Imm == 0) { |
497 | 0 | TmpInst.setOpcode(Hexagon::A2_tfr); |
498 | 0 | TmpInst.addOperand(MappedInst.getOperand(0)); |
499 | 0 | TmpInst.addOperand(MappedInst.getOperand(1)); |
500 | 0 | MappedInst = TmpInst; |
501 | 0 | return; |
502 | 0 | } |
503 | 0 | TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd); |
504 | 0 | TmpInst.addOperand(MappedInst.getOperand(0)); |
505 | 0 | TmpInst.addOperand(MappedInst.getOperand(1)); |
506 | 0 | const MCExpr *One = MCConstantExpr::create(1, OutContext); |
507 | 0 | const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext); |
508 | 0 | TmpInst.addOperand( |
509 | 0 | MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext))); |
510 | 0 | MappedInst = TmpInst; |
511 | 0 | return; |
512 | 0 | } |
513 | | |
514 | | // Translate a "$Rdd = #imm" to "$Rdd = combine(#[-1,0], #imm)" |
515 | 4.75k | case Hexagon::A2_tfrpi: { |
516 | 4.75k | MCInst TmpInst; |
517 | 4.75k | MCOperand &Rdd = MappedInst.getOperand(0); |
518 | 4.75k | MCOperand &MO = MappedInst.getOperand(1); |
519 | | |
520 | 4.75k | TmpInst.setOpcode(Hexagon::A2_combineii); |
521 | 4.75k | TmpInst.addOperand(Rdd); |
522 | 4.75k | int64_t Imm; |
523 | 4.75k | bool Success = MO.getExpr()->evaluateAsAbsolute(Imm); |
524 | 4.75k | if (Success && Imm < 0) { |
525 | 588 | const MCExpr *MOne = MCConstantExpr::create(-1, OutContext); |
526 | 588 | const HexagonMCExpr *E = HexagonMCExpr::create(MOne, OutContext); |
527 | 588 | TmpInst.addOperand(MCOperand::createExpr(E)); |
528 | 4.17k | } else { |
529 | 4.17k | const MCExpr *Zero = MCConstantExpr::create(0, OutContext); |
530 | 4.17k | const HexagonMCExpr *E = HexagonMCExpr::create(Zero, OutContext); |
531 | 4.17k | TmpInst.addOperand(MCOperand::createExpr(E)); |
532 | 4.17k | } |
533 | 4.75k | TmpInst.addOperand(MO); |
534 | 4.75k | MappedInst = TmpInst; |
535 | 4.75k | return; |
536 | 0 | } |
537 | | |
538 | | // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)" |
539 | 16.1k | case Hexagon::A2_tfrp: { |
540 | 16.1k | MCOperand &MO = MappedInst.getOperand(1); |
541 | 16.1k | unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi); |
542 | 16.1k | unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo); |
543 | 16.1k | MO.setReg(High); |
544 | | // Add a new operand for the second register in the pair. |
545 | 16.1k | MappedInst.addOperand(MCOperand::createReg(Low)); |
546 | 16.1k | MappedInst.setOpcode(Hexagon::A2_combinew); |
547 | 16.1k | return; |
548 | 0 | } |
549 | | |
550 | 0 | case Hexagon::A2_tfrpt: |
551 | 0 | case Hexagon::A2_tfrpf: { |
552 | 0 | MCOperand &MO = MappedInst.getOperand(2); |
553 | 0 | unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi); |
554 | 0 | unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo); |
555 | 0 | MO.setReg(High); |
556 | | // Add a new operand for the second register in the pair. |
557 | 0 | MappedInst.addOperand(MCOperand::createReg(Low)); |
558 | 0 | MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt) |
559 | 0 | ? Hexagon::C2_ccombinewt |
560 | 0 | : Hexagon::C2_ccombinewf); |
561 | 0 | return; |
562 | 0 | } |
563 | | |
564 | 0 | case Hexagon::A2_tfrptnew: |
565 | 0 | case Hexagon::A2_tfrpfnew: { |
566 | 0 | MCOperand &MO = MappedInst.getOperand(2); |
567 | 0 | unsigned High = RI->getSubReg(MO.getReg(), Hexagon::isub_hi); |
568 | 0 | unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::isub_lo); |
569 | 0 | MO.setReg(High); |
570 | | // Add a new operand for the second register in the pair. |
571 | 0 | MappedInst.addOperand(MCOperand::createReg(Low)); |
572 | 0 | MappedInst.setOpcode(Inst.getOpcode() == Hexagon::A2_tfrptnew |
573 | 0 | ? Hexagon::C2_ccombinewnewt |
574 | 0 | : Hexagon::C2_ccombinewnewf); |
575 | 0 | return; |
576 | 0 | } |
577 | | |
578 | 26 | case Hexagon::M2_mpysmi: { |
579 | 26 | MCOperand &Imm = MappedInst.getOperand(2); |
580 | 26 | MCExpr const *Expr = Imm.getExpr(); |
581 | 26 | int64_t Value; |
582 | 26 | bool Success = Expr->evaluateAsAbsolute(Value); |
583 | 26 | assert(Success); |
584 | 0 | (void)Success; |
585 | 26 | if (Value < 0 && Value > -256) { |
586 | 2 | MappedInst.setOpcode(Hexagon::M2_mpysin); |
587 | 2 | Imm.setExpr(HexagonMCExpr::create( |
588 | 2 | MCUnaryExpr::createMinus(Expr, OutContext), OutContext)); |
589 | 2 | } else |
590 | 24 | MappedInst.setOpcode(Hexagon::M2_mpysip); |
591 | 26 | return; |
592 | 0 | } |
593 | | |
594 | 0 | case Hexagon::A2_addsp: { |
595 | 0 | MCOperand &Rt = Inst.getOperand(1); |
596 | 0 | assert(Rt.isReg() && "Expected register and none was found"); |
597 | 0 | unsigned Reg = RI->getEncodingValue(Rt.getReg()); |
598 | 0 | if (Reg & 1) |
599 | 0 | MappedInst.setOpcode(Hexagon::A2_addsph); |
600 | 0 | else |
601 | 0 | MappedInst.setOpcode(Hexagon::A2_addspl); |
602 | 0 | Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI)); |
603 | 0 | return; |
604 | 0 | } |
605 | | |
606 | 0 | case Hexagon::V6_vd0: { |
607 | 0 | MCInst TmpInst; |
608 | 0 | assert(Inst.getOperand(0).isReg() && |
609 | 0 | "Expected register and none was found"); |
610 | | |
611 | 0 | TmpInst.setOpcode(Hexagon::V6_vxor); |
612 | 0 | TmpInst.addOperand(Inst.getOperand(0)); |
613 | 0 | TmpInst.addOperand(Inst.getOperand(0)); |
614 | 0 | TmpInst.addOperand(Inst.getOperand(0)); |
615 | 0 | MappedInst = TmpInst; |
616 | 0 | return; |
617 | 0 | } |
618 | | |
619 | 0 | case Hexagon::V6_vdd0: { |
620 | 0 | MCInst TmpInst; |
621 | 0 | assert (Inst.getOperand(0).isReg() && |
622 | 0 | "Expected register and none was found"); |
623 | | |
624 | 0 | TmpInst.setOpcode(Hexagon::V6_vsubw_dv); |
625 | 0 | TmpInst.addOperand(Inst.getOperand(0)); |
626 | 0 | TmpInst.addOperand(Inst.getOperand(0)); |
627 | 0 | TmpInst.addOperand(Inst.getOperand(0)); |
628 | 0 | MappedInst = TmpInst; |
629 | 0 | return; |
630 | 0 | } |
631 | | |
632 | 0 | case Hexagon::V6_vL32Ub_pi: |
633 | 0 | case Hexagon::V6_vL32b_cur_pi: |
634 | 0 | case Hexagon::V6_vL32b_nt_cur_pi: |
635 | 0 | case Hexagon::V6_vL32b_pi: |
636 | 0 | case Hexagon::V6_vL32b_nt_pi: |
637 | 0 | case Hexagon::V6_vL32b_nt_tmp_pi: |
638 | 0 | case Hexagon::V6_vL32b_tmp_pi: |
639 | 0 | MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext); |
640 | 0 | return; |
641 | | |
642 | 0 | case Hexagon::V6_vL32Ub_ai: |
643 | 0 | case Hexagon::V6_vL32b_ai: |
644 | 0 | case Hexagon::V6_vL32b_cur_ai: |
645 | 0 | case Hexagon::V6_vL32b_nt_ai: |
646 | 0 | case Hexagon::V6_vL32b_nt_cur_ai: |
647 | 0 | case Hexagon::V6_vL32b_nt_tmp_ai: |
648 | 0 | case Hexagon::V6_vL32b_tmp_ai: |
649 | 0 | MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext); |
650 | 0 | return; |
651 | | |
652 | 0 | case Hexagon::V6_vS32Ub_pi: |
653 | 0 | case Hexagon::V6_vS32b_new_pi: |
654 | 0 | case Hexagon::V6_vS32b_nt_new_pi: |
655 | 0 | case Hexagon::V6_vS32b_nt_pi: |
656 | 0 | case Hexagon::V6_vS32b_pi: |
657 | 0 | MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext); |
658 | 0 | return; |
659 | | |
660 | 0 | case Hexagon::V6_vS32Ub_ai: |
661 | 0 | case Hexagon::V6_vS32b_ai: |
662 | 0 | case Hexagon::V6_vS32b_new_ai: |
663 | 0 | case Hexagon::V6_vS32b_nt_ai: |
664 | 0 | case Hexagon::V6_vS32b_nt_new_ai: |
665 | 0 | MappedInst = ScaleVectorOffset(Inst, 1, VectorSize, OutContext); |
666 | 0 | return; |
667 | | |
668 | 0 | case Hexagon::V6_vL32b_cur_npred_pi: |
669 | 0 | case Hexagon::V6_vL32b_cur_pred_pi: |
670 | 0 | case Hexagon::V6_vL32b_npred_pi: |
671 | 0 | case Hexagon::V6_vL32b_nt_cur_npred_pi: |
672 | 0 | case Hexagon::V6_vL32b_nt_cur_pred_pi: |
673 | 0 | case Hexagon::V6_vL32b_nt_npred_pi: |
674 | 0 | case Hexagon::V6_vL32b_nt_pred_pi: |
675 | 0 | case Hexagon::V6_vL32b_nt_tmp_npred_pi: |
676 | 0 | case Hexagon::V6_vL32b_nt_tmp_pred_pi: |
677 | 0 | case Hexagon::V6_vL32b_pred_pi: |
678 | 0 | case Hexagon::V6_vL32b_tmp_npred_pi: |
679 | 0 | case Hexagon::V6_vL32b_tmp_pred_pi: |
680 | 0 | MappedInst = ScaleVectorOffset(Inst, 4, VectorSize, OutContext); |
681 | 0 | return; |
682 | | |
683 | 0 | case Hexagon::V6_vL32b_cur_npred_ai: |
684 | 0 | case Hexagon::V6_vL32b_cur_pred_ai: |
685 | 0 | case Hexagon::V6_vL32b_npred_ai: |
686 | 0 | case Hexagon::V6_vL32b_nt_cur_npred_ai: |
687 | 0 | case Hexagon::V6_vL32b_nt_cur_pred_ai: |
688 | 0 | case Hexagon::V6_vL32b_nt_npred_ai: |
689 | 0 | case Hexagon::V6_vL32b_nt_pred_ai: |
690 | 0 | case Hexagon::V6_vL32b_nt_tmp_npred_ai: |
691 | 0 | case Hexagon::V6_vL32b_nt_tmp_pred_ai: |
692 | 0 | case Hexagon::V6_vL32b_pred_ai: |
693 | 0 | case Hexagon::V6_vL32b_tmp_npred_ai: |
694 | 0 | case Hexagon::V6_vL32b_tmp_pred_ai: |
695 | 0 | MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext); |
696 | 0 | return; |
697 | | |
698 | 0 | case Hexagon::V6_vS32Ub_npred_pi: |
699 | 0 | case Hexagon::V6_vS32Ub_pred_pi: |
700 | 0 | case Hexagon::V6_vS32b_new_npred_pi: |
701 | 0 | case Hexagon::V6_vS32b_new_pred_pi: |
702 | 0 | case Hexagon::V6_vS32b_npred_pi: |
703 | 0 | case Hexagon::V6_vS32b_nqpred_pi: |
704 | 0 | case Hexagon::V6_vS32b_nt_new_npred_pi: |
705 | 0 | case Hexagon::V6_vS32b_nt_new_pred_pi: |
706 | 0 | case Hexagon::V6_vS32b_nt_npred_pi: |
707 | 0 | case Hexagon::V6_vS32b_nt_nqpred_pi: |
708 | 0 | case Hexagon::V6_vS32b_nt_pred_pi: |
709 | 0 | case Hexagon::V6_vS32b_nt_qpred_pi: |
710 | 0 | case Hexagon::V6_vS32b_pred_pi: |
711 | 0 | case Hexagon::V6_vS32b_qpred_pi: |
712 | 0 | MappedInst = ScaleVectorOffset(Inst, 3, VectorSize, OutContext); |
713 | 0 | return; |
714 | | |
715 | 0 | case Hexagon::V6_vS32Ub_npred_ai: |
716 | 0 | case Hexagon::V6_vS32Ub_pred_ai: |
717 | 0 | case Hexagon::V6_vS32b_new_npred_ai: |
718 | 0 | case Hexagon::V6_vS32b_new_pred_ai: |
719 | 0 | case Hexagon::V6_vS32b_npred_ai: |
720 | 0 | case Hexagon::V6_vS32b_nqpred_ai: |
721 | 0 | case Hexagon::V6_vS32b_nt_new_npred_ai: |
722 | 0 | case Hexagon::V6_vS32b_nt_new_pred_ai: |
723 | 0 | case Hexagon::V6_vS32b_nt_npred_ai: |
724 | 0 | case Hexagon::V6_vS32b_nt_nqpred_ai: |
725 | 0 | case Hexagon::V6_vS32b_nt_pred_ai: |
726 | 0 | case Hexagon::V6_vS32b_nt_qpred_ai: |
727 | 0 | case Hexagon::V6_vS32b_pred_ai: |
728 | 0 | case Hexagon::V6_vS32b_qpred_ai: |
729 | 0 | MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext); |
730 | 0 | return; |
731 | | |
732 | | // V65+ |
733 | 0 | case Hexagon::V6_vS32b_srls_ai: |
734 | 0 | MappedInst = ScaleVectorOffset(Inst, 1, VectorSize, OutContext); |
735 | 0 | return; |
736 | | |
737 | 0 | case Hexagon::V6_vS32b_srls_pi: |
738 | 0 | MappedInst = ScaleVectorOffset(Inst, 2, VectorSize, OutContext); |
739 | 0 | return; |
740 | 671k | } |
741 | 671k | } |
742 | | |
743 | | /// Print out a single Hexagon MI to the current output stream. |
744 | 229k | void HexagonAsmPrinter::emitInstruction(const MachineInstr *MI) { |
745 | 229k | Hexagon_MC::verifyInstructionPredicates(MI->getOpcode(), |
746 | 229k | getSubtargetInfo().getFeatureBits()); |
747 | | |
748 | 229k | MCInst MCB; |
749 | 229k | MCB.setOpcode(Hexagon::BUNDLE); |
750 | 229k | MCB.addOperand(MCOperand::createImm(0)); |
751 | 229k | const MCInstrInfo &MCII = *Subtarget->getInstrInfo(); |
752 | | |
753 | 229k | if (MI->isBundle()) { |
754 | 212k | const MachineBasicBlock* MBB = MI->getParent(); |
755 | 212k | MachineBasicBlock::const_instr_iterator MII = MI->getIterator(); |
756 | | |
757 | 866k | for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII) |
758 | 654k | if (!MII->isDebugInstr() && !MII->isImplicitDef()) |
759 | 654k | HexagonLowerToMC(MCII, &*MII, MCB, *this); |
760 | 212k | } else { |
761 | 16.8k | HexagonLowerToMC(MCII, MI, MCB, *this); |
762 | 16.8k | } |
763 | | |
764 | 229k | const MachineFunction &MF = *MI->getParent()->getParent(); |
765 | 229k | const auto &HII = *MF.getSubtarget<HexagonSubtarget>().getInstrInfo(); |
766 | 229k | if (MI->isBundle() && HII.getBundleNoShuf(*MI)) |
767 | 0 | HexagonMCInstrInfo::setMemReorderDisabled(MCB); |
768 | | |
769 | 229k | MCContext &Ctx = OutStreamer->getContext(); |
770 | 229k | bool Ok = HexagonMCInstrInfo::canonicalizePacket(MCII, *Subtarget, Ctx, |
771 | 229k | MCB, nullptr); |
772 | 229k | assert(Ok); (void)Ok; |
773 | 229k | if (HexagonMCInstrInfo::bundleSize(MCB) == 0) |
774 | 0 | return; |
775 | 229k | OutStreamer->emitInstruction(MCB, getSubtargetInfo()); |
776 | 229k | } |
777 | | |
778 | 0 | void HexagonAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) { |
779 | 0 | static const int8_t NoopsInSledCount = 4; |
780 | | // We want to emit the following pattern: |
781 | | // |
782 | | // .L_xray_sled_N: |
783 | | // <xray_sled_base>: |
784 | | // { jump .Ltmp0 } |
785 | | // { nop |
786 | | // nop |
787 | | // nop |
788 | | // nop } |
789 | | // .Ltmp0: |
790 | | // |
791 | | // We need the 4 nop words because at runtime, we'd be patching over the |
792 | | // full 5 words with the following pattern: |
793 | | // |
794 | | // <xray_sled_n>: |
795 | | // { immext(#...) // upper 26-bits of trampoline |
796 | | // r6 = ##... // lower 6-bits of trampoline |
797 | | // immext(#...) // upper 26-bits of func id |
798 | | // r7 = ##... } // lower 6 bits of func id |
799 | | // { callr r6 } |
800 | | // |
801 | | // |
802 | 0 | auto CurSled = OutContext.createTempSymbol("xray_sled_", true); |
803 | 0 | OutStreamer->emitLabel(CurSled); |
804 | |
|
805 | 0 | MCInst *SledJump = new (OutContext) MCInst(); |
806 | 0 | SledJump->setOpcode(Hexagon::J2_jump); |
807 | 0 | auto PostSled = OutContext.createTempSymbol(); |
808 | 0 | SledJump->addOperand(MCOperand::createExpr(HexagonMCExpr::create( |
809 | 0 | MCSymbolRefExpr::create(PostSled, OutContext), OutContext))); |
810 | | |
811 | | // Emit "jump PostSled" instruction, which jumps over the nop series. |
812 | 0 | MCInst SledJumpPacket; |
813 | 0 | SledJumpPacket.setOpcode(Hexagon::BUNDLE); |
814 | 0 | SledJumpPacket.addOperand(MCOperand::createImm(0)); |
815 | 0 | SledJumpPacket.addOperand(MCOperand::createInst(SledJump)); |
816 | |
|
817 | 0 | EmitToStreamer(*OutStreamer, SledJumpPacket); |
818 | | |
819 | | // FIXME: this will emit individual packets, we should |
820 | | // special-case this and combine them into a single packet. |
821 | 0 | emitNops(NoopsInSledCount); |
822 | |
|
823 | 0 | OutStreamer->emitLabel(PostSled); |
824 | 0 | recordSled(CurSled, MI, Kind, 2); |
825 | 0 | } |
826 | | |
827 | 0 | void HexagonAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) { |
828 | 0 | EmitSled(MI, SledKind::FUNCTION_ENTER); |
829 | 0 | } |
830 | | |
831 | 0 | void HexagonAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) { |
832 | 0 | EmitSled(MI, SledKind::FUNCTION_EXIT); |
833 | 0 | } |
834 | | |
835 | 0 | void HexagonAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) { |
836 | 0 | EmitSled(MI, SledKind::TAIL_CALL); |
837 | 0 | } |
838 | | |
839 | 24 | extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonAsmPrinter() { |
840 | 24 | RegisterAsmPrinter<HexagonAsmPrinter> X(getTheHexagonTarget()); |
841 | 24 | } |