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