Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
35294 views
1
// LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions -=//
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
#include "MCTargetDesc/LoongArchInstPrinter.h"
10
#include "MCTargetDesc/LoongArchMCExpr.h"
11
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
12
#include "MCTargetDesc/LoongArchMatInt.h"
13
#include "TargetInfo/LoongArchTargetInfo.h"
14
#include "llvm/MC/MCContext.h"
15
#include "llvm/MC/MCInstBuilder.h"
16
#include "llvm/MC/MCInstrInfo.h"
17
#include "llvm/MC/MCParser/MCAsmLexer.h"
18
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
19
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
20
#include "llvm/MC/MCRegisterInfo.h"
21
#include "llvm/MC/MCStreamer.h"
22
#include "llvm/MC/MCSubtargetInfo.h"
23
#include "llvm/MC/MCValue.h"
24
#include "llvm/MC/TargetRegistry.h"
25
#include "llvm/Support/Casting.h"
26
27
using namespace llvm;
28
29
#define DEBUG_TYPE "loongarch-asm-parser"
30
31
namespace {
32
class LoongArchAsmParser : public MCTargetAsmParser {
33
SMLoc getLoc() const { return getParser().getTok().getLoc(); }
34
bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); }
35
36
struct Inst {
37
unsigned Opc;
38
LoongArchMCExpr::VariantKind VK;
39
Inst(unsigned Opc,
40
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None)
41
: Opc(Opc), VK(VK) {}
42
};
43
using InstSeq = SmallVector<Inst>;
44
45
/// Parse a register as used in CFI directives.
46
bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
47
ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
48
SMLoc &EndLoc) override;
49
50
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
51
SMLoc NameLoc, OperandVector &Operands) override;
52
53
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
54
OperandVector &Operands, MCStreamer &Out,
55
uint64_t &ErrorInfo,
56
bool MatchingInlineAsm) override;
57
58
unsigned checkTargetMatchPredicate(MCInst &Inst) override;
59
60
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
61
unsigned Kind) override;
62
63
bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
64
int64_t Lower, int64_t Upper,
65
const Twine &Msg);
66
67
/// Helper for processing MC instructions that have been successfully matched
68
/// by MatchAndEmitInstruction.
69
bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
70
MCStreamer &Out);
71
72
// Auto-generated instruction matching functions.
73
#define GET_ASSEMBLER_HEADER
74
#include "LoongArchGenAsmMatcher.inc"
75
76
ParseStatus parseRegister(OperandVector &Operands);
77
ParseStatus parseImmediate(OperandVector &Operands);
78
ParseStatus parseOperandWithModifier(OperandVector &Operands);
79
ParseStatus parseSImm26Operand(OperandVector &Operands);
80
ParseStatus parseAtomicMemOp(OperandVector &Operands);
81
82
bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
83
84
// Helper to emit the sequence of instructions generated by the
85
// "emitLoadAddress*" functions.
86
void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
87
const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts,
88
SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false);
89
90
// Helper to emit pseudo instruction "la.abs $rd, sym".
91
void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
92
93
// Helper to emit pseudo instruction "la.pcrel $rd, sym".
94
void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
95
// Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym".
96
void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
97
98
// Helper to emit pseudo instruction "la.got $rd, sym".
99
void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
100
// Helper to emit pseudo instruction "la.got $rd, $rj, sym".
101
void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
102
103
// Helper to emit pseudo instruction "la.tls.le $rd, sym".
104
void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
105
106
// Helper to emit pseudo instruction "la.tls.ie $rd, sym".
107
void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
108
// Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym".
109
void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
110
111
// Helper to emit pseudo instruction "la.tls.ld $rd, sym".
112
void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
113
// Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym".
114
void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
115
116
// Helper to emit pseudo instruction "la.tls.gd $rd, sym".
117
void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
118
// Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym".
119
void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
120
121
// Helper to emit pseudo instruction "la.tls.desc $rd, sym".
122
void emitLoadAddressTLSDescAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
123
void emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
124
// Helper to emit pseudo instruction "la.tls.desc $rd, $rj, sym".
125
void emitLoadAddressTLSDescPcrelLarge(MCInst &Inst, SMLoc IDLoc,
126
MCStreamer &Out);
127
128
// Helper to emit pseudo instruction "li.w/d $rd, $imm".
129
void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
130
131
// Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".
132
void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
133
bool IsTailCall);
134
135
public:
136
enum LoongArchMatchResultTy {
137
Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
138
Match_RequiresMsbNotLessThanLsb,
139
Match_RequiresOpnd2NotR0R1,
140
Match_RequiresAMORdDifferRkRj,
141
Match_RequiresLAORdDifferRj,
142
Match_RequiresLAORdR4,
143
#define GET_OPERAND_DIAGNOSTIC_TYPES
144
#include "LoongArchGenAsmMatcher.inc"
145
#undef GET_OPERAND_DIAGNOSTIC_TYPES
146
};
147
148
static bool classifySymbolRef(const MCExpr *Expr,
149
LoongArchMCExpr::VariantKind &Kind);
150
151
LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
152
const MCInstrInfo &MII, const MCTargetOptions &Options)
153
: MCTargetAsmParser(Options, STI, MII) {
154
Parser.addAliasForDirective(".half", ".2byte");
155
Parser.addAliasForDirective(".hword", ".2byte");
156
Parser.addAliasForDirective(".word", ".4byte");
157
Parser.addAliasForDirective(".dword", ".8byte");
158
159
// Initialize the set of available features.
160
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
161
}
162
};
163
164
// Instances of this class represent a parsed LoongArch machine instruction.
165
class LoongArchOperand : public MCParsedAsmOperand {
166
enum class KindTy {
167
Token,
168
Register,
169
Immediate,
170
} Kind;
171
172
struct RegOp {
173
MCRegister RegNum;
174
};
175
176
struct ImmOp {
177
const MCExpr *Val;
178
};
179
180
SMLoc StartLoc, EndLoc;
181
union {
182
StringRef Tok;
183
struct RegOp Reg;
184
struct ImmOp Imm;
185
};
186
187
public:
188
LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
189
190
bool isToken() const override { return Kind == KindTy::Token; }
191
bool isReg() const override { return Kind == KindTy::Register; }
192
bool isImm() const override { return Kind == KindTy::Immediate; }
193
bool isMem() const override { return false; }
194
void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; }
195
bool isGPR() const {
196
return Kind == KindTy::Register &&
197
LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(
198
Reg.RegNum);
199
}
200
201
static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
202
LoongArchMCExpr::VariantKind &VK) {
203
if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) {
204
VK = LE->getKind();
205
return false;
206
}
207
208
if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
209
Imm = CE->getValue();
210
return true;
211
}
212
213
return false;
214
}
215
216
template <unsigned N, int P = 0> bool isUImm() const {
217
if (!isImm())
218
return false;
219
220
int64_t Imm;
221
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
222
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
223
return IsConstantImm && isUInt<N>(Imm - P) &&
224
VK == LoongArchMCExpr::VK_LoongArch_None;
225
}
226
227
template <unsigned N, unsigned S = 0> bool isSImm() const {
228
if (!isImm())
229
return false;
230
231
int64_t Imm;
232
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
233
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
234
return IsConstantImm && isShiftedInt<N, S>(Imm) &&
235
VK == LoongArchMCExpr::VK_LoongArch_None;
236
}
237
238
bool isBareSymbol() const {
239
int64_t Imm;
240
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
241
// Must be of 'immediate' type but not a constant.
242
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
243
return false;
244
return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
245
VK == LoongArchMCExpr::VK_LoongArch_None;
246
}
247
248
bool isTPRelAddSymbol() const {
249
int64_t Imm;
250
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
251
// Must be of 'immediate' type but not a constant.
252
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
253
return false;
254
return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
255
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R;
256
}
257
258
bool isUImm1() const { return isUImm<1>(); }
259
bool isUImm2() const { return isUImm<2>(); }
260
bool isUImm2plus1() const { return isUImm<2, 1>(); }
261
bool isUImm3() const { return isUImm<3>(); }
262
bool isUImm4() const { return isUImm<4>(); }
263
bool isSImm5() const { return isSImm<5>(); }
264
bool isUImm5() const { return isUImm<5>(); }
265
bool isUImm6() const { return isUImm<6>(); }
266
bool isUImm7() const { return isUImm<7>(); }
267
bool isSImm8() const { return isSImm<8>(); }
268
bool isSImm8lsl1() const { return isSImm<8, 1>(); }
269
bool isSImm8lsl2() const { return isSImm<8, 2>(); }
270
bool isSImm8lsl3() const { return isSImm<8, 3>(); }
271
bool isUImm8() const { return isUImm<8>(); }
272
bool isSImm9lsl3() const { return isSImm<9, 3>(); }
273
bool isSImm10() const { return isSImm<10>(); }
274
bool isSImm10lsl2() const { return isSImm<10, 2>(); }
275
bool isSImm11lsl1() const { return isSImm<11, 1>(); }
276
bool isSImm12() const { return isSImm<12>(); }
277
278
bool isSImm12addlike() const {
279
if (!isImm())
280
return false;
281
282
int64_t Imm;
283
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
284
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
285
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
286
VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
287
VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
288
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 ||
289
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R ||
290
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12 ||
291
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD;
292
return IsConstantImm
293
? isInt<12>(Imm) && IsValidKind
294
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
295
IsValidKind;
296
}
297
298
bool isSImm12lu52id() const {
299
if (!isImm())
300
return false;
301
302
int64_t Imm;
303
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
304
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
305
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
306
VK == LoongArchMCExpr::VK_LoongArch_ABS64_HI12 ||
307
VK == LoongArchMCExpr::VK_LoongArch_PCALA64_HI12 ||
308
VK == LoongArchMCExpr::VK_LoongArch_GOT64_HI12 ||
309
VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 ||
310
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 ||
311
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 ||
312
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12 ||
313
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12 ||
314
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12;
315
return IsConstantImm
316
? isInt<12>(Imm) && IsValidKind
317
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
318
IsValidKind;
319
}
320
321
bool isUImm12() const { return isUImm<12>(); }
322
323
bool isUImm12ori() const {
324
if (!isImm())
325
return false;
326
327
int64_t Imm;
328
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
329
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
330
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
331
VK == LoongArchMCExpr::VK_LoongArch_ABS_LO12 ||
332
VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
333
VK == LoongArchMCExpr::VK_LoongArch_GOT_LO12 ||
334
VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
335
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 ||
336
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 ||
337
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 ||
338
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12;
339
return IsConstantImm
340
? isUInt<12>(Imm) && IsValidKind
341
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
342
IsValidKind;
343
}
344
345
bool isSImm13() const { return isSImm<13>(); }
346
bool isUImm14() const { return isUImm<14>(); }
347
bool isUImm15() const { return isUImm<15>(); }
348
349
bool isSImm14lsl2() const { return isSImm<14, 2>(); }
350
bool isSImm16() const { return isSImm<16>(); }
351
352
bool isSImm16lsl2() const {
353
if (!isImm())
354
return false;
355
356
int64_t Imm;
357
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
358
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
359
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
360
VK == LoongArchMCExpr::VK_LoongArch_B16 ||
361
VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
362
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL;
363
return IsConstantImm
364
? isShiftedInt<16, 2>(Imm) && IsValidKind
365
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
366
IsValidKind;
367
}
368
369
bool isSImm20() const { return isSImm<20>(); }
370
371
bool isSImm20pcalau12i() const {
372
if (!isImm())
373
return false;
374
375
int64_t Imm;
376
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
377
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
378
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
379
VK == LoongArchMCExpr::VK_LoongArch_PCALA_HI20 ||
380
VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 ||
381
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 ||
382
VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 ||
383
VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20 ||
384
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20;
385
return IsConstantImm
386
? isInt<20>(Imm) && IsValidKind
387
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
388
IsValidKind;
389
}
390
391
bool isSImm20lu12iw() const {
392
if (!isImm())
393
return false;
394
395
int64_t Imm;
396
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
397
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
398
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
399
VK == LoongArchMCExpr::VK_LoongArch_ABS_HI20 ||
400
VK == LoongArchMCExpr::VK_LoongArch_GOT_HI20 ||
401
VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 ||
402
VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 ||
403
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 ||
404
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20 ||
405
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R ||
406
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20;
407
return IsConstantImm
408
? isInt<20>(Imm) && IsValidKind
409
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
410
IsValidKind;
411
}
412
413
bool isSImm20lu32id() const {
414
if (!isImm())
415
return false;
416
417
int64_t Imm;
418
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
419
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
420
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
421
VK == LoongArchMCExpr::VK_LoongArch_ABS64_LO20 ||
422
VK == LoongArchMCExpr::VK_LoongArch_PCALA64_LO20 ||
423
VK == LoongArchMCExpr::VK_LoongArch_GOT64_LO20 ||
424
VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 ||
425
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 ||
426
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 ||
427
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20 ||
428
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20 ||
429
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20;
430
431
return IsConstantImm
432
? isInt<20>(Imm) && IsValidKind
433
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
434
IsValidKind;
435
}
436
437
bool isSImm20pcaddu18i() const {
438
if (!isImm())
439
return false;
440
441
int64_t Imm;
442
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
443
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
444
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
445
VK == LoongArchMCExpr::VK_LoongArch_CALL36;
446
447
return IsConstantImm
448
? isInt<20>(Imm) && IsValidKind
449
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
450
IsValidKind;
451
}
452
453
bool isSImm20pcaddi() const {
454
if (!isImm())
455
return false;
456
457
int64_t Imm;
458
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
459
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
460
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
461
VK == LoongArchMCExpr::VK_LoongArch_PCREL20_S2 ||
462
VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PCREL20_S2 ||
463
VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PCREL20_S2 ||
464
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PCREL20_S2;
465
return IsConstantImm
466
? isInt<20>(Imm) && IsValidKind
467
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
468
IsValidKind;
469
}
470
471
bool isSImm21lsl2() const {
472
if (!isImm())
473
return false;
474
475
int64_t Imm;
476
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
477
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
478
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
479
VK == LoongArchMCExpr::VK_LoongArch_B21;
480
return IsConstantImm
481
? isShiftedInt<21, 2>(Imm) && IsValidKind
482
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
483
IsValidKind;
484
}
485
486
bool isSImm26Operand() const {
487
if (!isImm())
488
return false;
489
490
int64_t Imm;
491
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
492
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
493
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
494
VK == LoongArchMCExpr::VK_LoongArch_CALL ||
495
VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT ||
496
VK == LoongArchMCExpr::VK_LoongArch_B26;
497
return IsConstantImm
498
? isShiftedInt<26, 2>(Imm) && IsValidKind
499
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
500
IsValidKind;
501
}
502
503
bool isImm32() const { return isSImm<32>() || isUImm<32>(); }
504
bool isImm64() const {
505
if (!isImm())
506
return false;
507
int64_t Imm;
508
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
509
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
510
return IsConstantImm && VK == LoongArchMCExpr::VK_LoongArch_None;
511
}
512
513
/// Gets location of the first token of this operand.
514
SMLoc getStartLoc() const override { return StartLoc; }
515
/// Gets location of the last token of this operand.
516
SMLoc getEndLoc() const override { return EndLoc; }
517
518
MCRegister getReg() const override {
519
assert(Kind == KindTy::Register && "Invalid type access!");
520
return Reg.RegNum;
521
}
522
523
const MCExpr *getImm() const {
524
assert(Kind == KindTy::Immediate && "Invalid type access!");
525
return Imm.Val;
526
}
527
528
StringRef getToken() const {
529
assert(Kind == KindTy::Token && "Invalid type access!");
530
return Tok;
531
}
532
533
void print(raw_ostream &OS) const override {
534
auto RegName = [](MCRegister Reg) {
535
if (Reg)
536
return LoongArchInstPrinter::getRegisterName(Reg);
537
else
538
return "noreg";
539
};
540
541
switch (Kind) {
542
case KindTy::Immediate:
543
OS << *getImm();
544
break;
545
case KindTy::Register:
546
OS << "<register " << RegName(getReg()) << ">";
547
break;
548
case KindTy::Token:
549
OS << "'" << getToken() << "'";
550
break;
551
}
552
}
553
554
static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) {
555
auto Op = std::make_unique<LoongArchOperand>(KindTy::Token);
556
Op->Tok = Str;
557
Op->StartLoc = S;
558
Op->EndLoc = S;
559
return Op;
560
}
561
562
static std::unique_ptr<LoongArchOperand> createReg(unsigned RegNo, SMLoc S,
563
SMLoc E) {
564
auto Op = std::make_unique<LoongArchOperand>(KindTy::Register);
565
Op->Reg.RegNum = RegNo;
566
Op->StartLoc = S;
567
Op->EndLoc = E;
568
return Op;
569
}
570
571
static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S,
572
SMLoc E) {
573
auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate);
574
Op->Imm.Val = Val;
575
Op->StartLoc = S;
576
Op->EndLoc = E;
577
return Op;
578
}
579
580
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
581
if (auto CE = dyn_cast<MCConstantExpr>(Expr))
582
Inst.addOperand(MCOperand::createImm(CE->getValue()));
583
else
584
Inst.addOperand(MCOperand::createExpr(Expr));
585
}
586
587
// Used by the TableGen Code.
588
void addRegOperands(MCInst &Inst, unsigned N) const {
589
assert(N == 1 && "Invalid number of operands!");
590
Inst.addOperand(MCOperand::createReg(getReg()));
591
}
592
void addImmOperands(MCInst &Inst, unsigned N) const {
593
assert(N == 1 && "Invalid number of operands!");
594
addExpr(Inst, getImm());
595
}
596
};
597
} // end namespace
598
599
#define GET_REGISTER_MATCHER
600
#define GET_SUBTARGET_FEATURE_NAME
601
#define GET_MATCHER_IMPLEMENTATION
602
#define GET_MNEMONIC_SPELL_CHECKER
603
#include "LoongArchGenAsmMatcher.inc"
604
605
static MCRegister convertFPR32ToFPR64(MCRegister Reg) {
606
assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register");
607
return Reg - LoongArch::F0 + LoongArch::F0_64;
608
}
609
610
// Attempts to match Name as a register (either using the default name or
611
// alternative ABI names), setting RegNo to the matching register. Upon
612
// failure, returns true and sets RegNo to 0.
613
static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {
614
RegNo = MatchRegisterName(Name);
615
// The 32-bit and 64-bit FPRs have the same asm name. Check that the initial
616
// match always matches the 32-bit variant, and not the 64-bit one.
617
assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64));
618
// The default FPR register class is based on the tablegen enum ordering.
619
static_assert(LoongArch::F0 < LoongArch::F0_64,
620
"FPR matching must be updated");
621
if (RegNo == LoongArch::NoRegister)
622
RegNo = MatchRegisterAltName(Name);
623
624
return RegNo == LoongArch::NoRegister;
625
}
626
627
bool LoongArchAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
628
SMLoc &EndLoc) {
629
return Error(getLoc(), "invalid register number");
630
}
631
632
ParseStatus LoongArchAsmParser::tryParseRegister(MCRegister &Reg,
633
SMLoc &StartLoc,
634
SMLoc &EndLoc) {
635
llvm_unreachable("Unimplemented function.");
636
}
637
638
bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr,
639
LoongArchMCExpr::VariantKind &Kind) {
640
Kind = LoongArchMCExpr::VK_LoongArch_None;
641
642
if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) {
643
Kind = RE->getKind();
644
Expr = RE->getSubExpr();
645
}
646
647
MCValue Res;
648
if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr))
649
return Res.getRefKind() == LoongArchMCExpr::VK_LoongArch_None;
650
return false;
651
}
652
653
ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) {
654
if (!parseOptionalToken(AsmToken::Dollar))
655
return ParseStatus::NoMatch;
656
if (getLexer().getKind() != AsmToken::Identifier)
657
return ParseStatus::NoMatch;
658
659
StringRef Name = getLexer().getTok().getIdentifier();
660
MCRegister RegNo;
661
matchRegisterNameHelper(RegNo, Name);
662
if (RegNo == LoongArch::NoRegister)
663
return ParseStatus::NoMatch;
664
665
SMLoc S = getLoc();
666
SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
667
getLexer().Lex();
668
Operands.push_back(LoongArchOperand::createReg(RegNo, S, E));
669
670
return ParseStatus::Success;
671
}
672
673
ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) {
674
SMLoc S = getLoc();
675
SMLoc E;
676
const MCExpr *Res;
677
678
switch (getLexer().getKind()) {
679
default:
680
return ParseStatus::NoMatch;
681
case AsmToken::LParen:
682
case AsmToken::Dot:
683
case AsmToken::Minus:
684
case AsmToken::Plus:
685
case AsmToken::Exclaim:
686
case AsmToken::Tilde:
687
case AsmToken::Integer:
688
case AsmToken::String:
689
case AsmToken::Identifier:
690
if (getParser().parseExpression(Res, E))
691
return ParseStatus::Failure;
692
break;
693
case AsmToken::Percent:
694
return parseOperandWithModifier(Operands);
695
}
696
697
Operands.push_back(LoongArchOperand::createImm(Res, S, E));
698
return ParseStatus::Success;
699
}
700
701
ParseStatus
702
LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) {
703
SMLoc S = getLoc();
704
SMLoc E;
705
706
if (getLexer().getKind() != AsmToken::Percent)
707
return Error(getLoc(), "expected '%' for operand modifier");
708
709
getParser().Lex(); // Eat '%'
710
711
if (getLexer().getKind() != AsmToken::Identifier)
712
return Error(getLoc(), "expected valid identifier for operand modifier");
713
StringRef Identifier = getParser().getTok().getIdentifier();
714
LoongArchMCExpr::VariantKind VK =
715
LoongArchMCExpr::getVariantKindForName(Identifier);
716
if (VK == LoongArchMCExpr::VK_LoongArch_Invalid)
717
return Error(getLoc(), "unrecognized operand modifier");
718
719
getParser().Lex(); // Eat the identifier
720
if (getLexer().getKind() != AsmToken::LParen)
721
return Error(getLoc(), "expected '('");
722
getParser().Lex(); // Eat '('
723
724
const MCExpr *SubExpr;
725
if (getParser().parseParenExpression(SubExpr, E))
726
return ParseStatus::Failure;
727
728
const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext());
729
Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E));
730
return ParseStatus::Success;
731
}
732
733
ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) {
734
SMLoc S = getLoc();
735
const MCExpr *Res;
736
737
if (getLexer().getKind() == AsmToken::Percent)
738
return parseOperandWithModifier(Operands);
739
740
if (getLexer().getKind() != AsmToken::Identifier)
741
return ParseStatus::NoMatch;
742
743
StringRef Identifier;
744
if (getParser().parseIdentifier(Identifier))
745
return ParseStatus::Failure;
746
747
SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
748
749
MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
750
Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
751
Res = LoongArchMCExpr::create(Res, LoongArchMCExpr::VK_LoongArch_CALL,
752
getContext());
753
Operands.push_back(LoongArchOperand::createImm(Res, S, E));
754
return ParseStatus::Success;
755
}
756
757
ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) {
758
// Parse "$r*".
759
if (!parseRegister(Operands).isSuccess())
760
return ParseStatus::NoMatch;
761
762
// If there is a next operand and it is 0, ignore it. Otherwise print a
763
// diagnostic message.
764
if (parseOptionalToken(AsmToken::Comma)) {
765
int64_t ImmVal;
766
SMLoc ImmStart = getLoc();
767
if (getParser().parseIntToken(ImmVal, "expected optional integer offset"))
768
return ParseStatus::Failure;
769
if (ImmVal)
770
return Error(ImmStart, "optional integer offset must be 0");
771
}
772
773
return ParseStatus::Success;
774
}
775
/// Looks at a token type and creates the relevant operand from this
776
/// information, adding to Operands. Return true upon an error.
777
bool LoongArchAsmParser::parseOperand(OperandVector &Operands,
778
StringRef Mnemonic) {
779
// Check if the current operand has a custom associated parser, if so, try to
780
// custom parse the operand, or fallback to the general approach.
781
ParseStatus Result =
782
MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
783
if (Result.isSuccess())
784
return false;
785
if (Result.isFailure())
786
return true;
787
788
if (parseRegister(Operands).isSuccess() ||
789
parseImmediate(Operands).isSuccess())
790
return false;
791
792
// Finally we have exhausted all options and must declare defeat.
793
return Error(getLoc(), "unknown operand");
794
}
795
796
bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info,
797
StringRef Name, SMLoc NameLoc,
798
OperandVector &Operands) {
799
// First operand in MCInst is instruction mnemonic.
800
Operands.push_back(LoongArchOperand::createToken(Name, NameLoc));
801
802
// If there are no more operands, then finish.
803
if (parseOptionalToken(AsmToken::EndOfStatement))
804
return false;
805
806
// Parse first operand.
807
if (parseOperand(Operands, Name))
808
return true;
809
810
// Parse until end of statement, consuming commas between operands.
811
while (parseOptionalToken(AsmToken::Comma))
812
if (parseOperand(Operands, Name))
813
return true;
814
815
// Parse end of statement and return successfully.
816
if (parseOptionalToken(AsmToken::EndOfStatement))
817
return false;
818
819
SMLoc Loc = getLexer().getLoc();
820
getParser().eatToEndOfStatement();
821
return Error(Loc, "unexpected token");
822
}
823
824
void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
825
const MCExpr *Symbol,
826
SmallVectorImpl<Inst> &Insts,
827
SMLoc IDLoc, MCStreamer &Out,
828
bool RelaxHint) {
829
MCContext &Ctx = getContext();
830
for (LoongArchAsmParser::Inst &Inst : Insts) {
831
unsigned Opc = Inst.Opc;
832
LoongArchMCExpr::VariantKind VK = Inst.VK;
833
const LoongArchMCExpr *LE =
834
LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint);
835
switch (Opc) {
836
default:
837
llvm_unreachable("unexpected opcode");
838
case LoongArch::PCALAU12I:
839
case LoongArch::LU12I_W:
840
Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE),
841
getSTI());
842
break;
843
case LoongArch::ORI:
844
case LoongArch::ADDI_W:
845
case LoongArch::LD_W:
846
case LoongArch::LD_D: {
847
if (VK == LoongArchMCExpr::VK_LoongArch_None) {
848
Out.emitInstruction(
849
MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0),
850
getSTI());
851
continue;
852
} else if (VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD) {
853
Out.emitInstruction(MCInstBuilder(Opc)
854
.addReg(LoongArch::R1)
855
.addReg(DestReg)
856
.addExpr(LE),
857
getSTI());
858
continue;
859
}
860
Out.emitInstruction(
861
MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE),
862
getSTI());
863
break;
864
}
865
case LoongArch::LU32I_D:
866
Out.emitInstruction(MCInstBuilder(Opc)
867
.addReg(DestReg == TmpReg ? DestReg : TmpReg)
868
.addReg(DestReg == TmpReg ? DestReg : TmpReg)
869
.addExpr(LE),
870
getSTI());
871
break;
872
case LoongArch::LU52I_D:
873
Out.emitInstruction(
874
MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE),
875
getSTI());
876
break;
877
case LoongArch::ADDI_D:
878
Out.emitInstruction(
879
MCInstBuilder(Opc)
880
.addReg(TmpReg)
881
.addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0)
882
.addExpr(LE),
883
getSTI());
884
break;
885
case LoongArch::ADD_D:
886
case LoongArch::LDX_D:
887
Out.emitInstruction(
888
MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg),
889
getSTI());
890
break;
891
case LoongArch::JIRL:
892
Out.emitInstruction(MCInstBuilder(Opc)
893
.addReg(LoongArch::R1)
894
.addReg(LoongArch::R1)
895
.addExpr(LE),
896
getSTI());
897
break;
898
}
899
}
900
}
901
902
void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc,
903
MCStreamer &Out) {
904
// la.abs $rd, sym
905
// expands to:
906
// lu12i.w $rd, %abs_hi20(sym)
907
// ori $rd, $rd, %abs_lo12(sym)
908
//
909
// for 64bit appends:
910
// lu32i.d $rd, %abs64_lo20(sym)
911
// lu52i.d $rd, $rd, %abs64_hi12(sym)
912
MCRegister DestReg = Inst.getOperand(0).getReg();
913
const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS
914
? Inst.getOperand(1).getExpr()
915
: Inst.getOperand(2).getExpr();
916
InstSeq Insts;
917
918
Insts.push_back(LoongArchAsmParser::Inst(
919
LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_ABS_HI20));
920
Insts.push_back(LoongArchAsmParser::Inst(
921
LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_ABS_LO12));
922
923
if (is64Bit()) {
924
Insts.push_back(LoongArchAsmParser::Inst(
925
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_ABS64_LO20));
926
Insts.push_back(LoongArchAsmParser::Inst(
927
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_ABS64_HI12));
928
}
929
930
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
931
}
932
933
void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc,
934
MCStreamer &Out) {
935
// la.pcrel $rd, sym
936
// expands to:
937
// pcalau12i $rd, %pc_hi20(sym)
938
// addi.w/d $rd, rd, %pc_lo12(sym)
939
MCRegister DestReg = Inst.getOperand(0).getReg();
940
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
941
InstSeq Insts;
942
unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
943
944
Insts.push_back(LoongArchAsmParser::Inst(
945
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));
946
Insts.push_back(
947
LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));
948
949
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true);
950
}
951
952
void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,
953
MCStreamer &Out) {
954
// la.pcrel $rd, $rj, sym
955
// expands to:
956
// pcalau12i $rd, %pc_hi20(sym)
957
// addi.d $rj, $r0, %pc_lo12(sym)
958
// lu32i.d $rj, %pc64_lo20(sym)
959
// lu52i.d $rj, $rj, %pc64_hi12(sym)
960
// add.d $rd, $rd, $rj
961
MCRegister DestReg = Inst.getOperand(0).getReg();
962
MCRegister TmpReg = Inst.getOperand(1).getReg();
963
const MCExpr *Symbol = Inst.getOperand(2).getExpr();
964
InstSeq Insts;
965
966
Insts.push_back(LoongArchAsmParser::Inst(
967
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));
968
Insts.push_back(LoongArchAsmParser::Inst(
969
LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));
970
Insts.push_back(LoongArchAsmParser::Inst(
971
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20));
972
Insts.push_back(LoongArchAsmParser::Inst(
973
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12));
974
Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
975
976
emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
977
}
978
979
void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,
980
MCStreamer &Out) {
981
// la.got $rd, sym
982
// expands to:
983
// pcalau12i $rd, %got_pc_hi20(sym)
984
// ld.w/d $rd, $rd, %got_pc_lo12(sym)
985
MCRegister DestReg = Inst.getOperand(0).getReg();
986
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
987
InstSeq Insts;
988
unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
989
990
Insts.push_back(LoongArchAsmParser::Inst(
991
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
992
Insts.push_back(
993
LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
994
995
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true);
996
}
997
998
void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc,
999
MCStreamer &Out) {
1000
// la.got $rd, $rj, sym
1001
// expands to:
1002
// pcalau12i $rd, %got_pc_hi20(sym)
1003
// addi.d $rj, $r0, %got_pc_lo12(sym)
1004
// lu32i.d $rj, %got64_pc_lo20(sym)
1005
// lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1006
// ldx.d $rd, $rd, $rj
1007
MCRegister DestReg = Inst.getOperand(0).getReg();
1008
MCRegister TmpReg = Inst.getOperand(1).getReg();
1009
const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1010
InstSeq Insts;
1011
1012
Insts.push_back(LoongArchAsmParser::Inst(
1013
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
1014
Insts.push_back(LoongArchAsmParser::Inst(
1015
LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1016
Insts.push_back(LoongArchAsmParser::Inst(
1017
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1018
Insts.push_back(LoongArchAsmParser::Inst(
1019
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1020
Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));
1021
1022
emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1023
}
1024
1025
void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc,
1026
MCStreamer &Out) {
1027
// la.tls.le $rd, sym
1028
// expands to:
1029
// lu12i.w $rd, %le_hi20(sym)
1030
// ori $rd, $rd, %le_lo12(sym)
1031
MCRegister DestReg = Inst.getOperand(0).getReg();
1032
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1033
InstSeq Insts;
1034
1035
Insts.push_back(LoongArchAsmParser::Inst(
1036
LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20));
1037
Insts.push_back(LoongArchAsmParser::Inst(
1038
LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12));
1039
1040
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1041
}
1042
1043
void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,
1044
MCStreamer &Out) {
1045
// la.tls.ie $rd, sym
1046
// expands to:
1047
// pcalau12i $rd, %ie_pc_hi20(sym)
1048
// ld.w/d $rd, $rd, %ie_pc_lo12(sym)
1049
MCRegister DestReg = Inst.getOperand(0).getReg();
1050
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1051
InstSeq Insts;
1052
unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1053
1054
Insts.push_back(LoongArchAsmParser::Inst(
1055
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
1056
Insts.push_back(LoongArchAsmParser::Inst(
1057
LD, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12));
1058
1059
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1060
}
1061
1062
void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc,
1063
MCStreamer &Out) {
1064
// la.tls.ie $rd, $rj, sym
1065
// expands to:
1066
// pcalau12i $rd, %ie_pc_hi20(sym)
1067
// addi.d $rj, $r0, %ie_pc_lo12(sym)
1068
// lu32i.d $rj, %ie64_pc_lo20(sym)
1069
// lu52i.d $rj, $rj, %ie64_pc_hi12(sym)
1070
// ldx.d $rd, $rd, $rj
1071
MCRegister DestReg = Inst.getOperand(0).getReg();
1072
MCRegister TmpReg = Inst.getOperand(1).getReg();
1073
const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1074
InstSeq Insts;
1075
1076
Insts.push_back(LoongArchAsmParser::Inst(
1077
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
1078
Insts.push_back(LoongArchAsmParser::Inst(
1079
LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12));
1080
Insts.push_back(LoongArchAsmParser::Inst(
1081
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20));
1082
Insts.push_back(LoongArchAsmParser::Inst(
1083
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12));
1084
Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));
1085
1086
emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1087
}
1088
1089
void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,
1090
MCStreamer &Out) {
1091
// la.tls.ld $rd, sym
1092
// expands to:
1093
// pcalau12i $rd, %ld_pc_hi20(sym)
1094
// addi.w/d $rd, $rd, %got_pc_lo12(sym)
1095
MCRegister DestReg = Inst.getOperand(0).getReg();
1096
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1097
InstSeq Insts;
1098
unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1099
1100
Insts.push_back(LoongArchAsmParser::Inst(
1101
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
1102
Insts.push_back(LoongArchAsmParser::Inst(
1103
ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1104
1105
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1106
}
1107
1108
void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc,
1109
MCStreamer &Out) {
1110
// la.tls.ld $rd, $rj, sym
1111
// expands to:
1112
// pcalau12i $rd, %ld_pc_hi20(sym)
1113
// addi.d $rj, $r0, %got_pc_lo12(sym)
1114
// lu32i.d $rj, %got64_pc_lo20(sym)
1115
// lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1116
// add.d $rd, $rd, $rj
1117
MCRegister DestReg = Inst.getOperand(0).getReg();
1118
MCRegister TmpReg = Inst.getOperand(1).getReg();
1119
const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1120
InstSeq Insts;
1121
1122
Insts.push_back(LoongArchAsmParser::Inst(
1123
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
1124
Insts.push_back(LoongArchAsmParser::Inst(
1125
LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1126
Insts.push_back(LoongArchAsmParser::Inst(
1127
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1128
Insts.push_back(LoongArchAsmParser::Inst(
1129
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1130
Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1131
1132
emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1133
}
1134
1135
void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,
1136
MCStreamer &Out) {
1137
// la.tls.gd $rd, sym
1138
// expands to:
1139
// pcalau12i $rd, %gd_pc_hi20(sym)
1140
// addi.w/d $rd, $rd, %got_pc_lo12(sym)
1141
MCRegister DestReg = Inst.getOperand(0).getReg();
1142
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1143
InstSeq Insts;
1144
unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1145
1146
Insts.push_back(LoongArchAsmParser::Inst(
1147
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
1148
Insts.push_back(LoongArchAsmParser::Inst(
1149
ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1150
1151
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1152
}
1153
1154
void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,
1155
MCStreamer &Out) {
1156
// la.tls.gd $rd, $rj, sym
1157
// expands to:
1158
// pcalau12i $rd, %gd_pc_hi20(sym)
1159
// addi.d $rj, $r0, %got_pc_lo12(sym)
1160
// lu32i.d $rj, %got64_pc_lo20(sym)
1161
// lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1162
// add.d $rd, $rd, $rj
1163
MCRegister DestReg = Inst.getOperand(0).getReg();
1164
MCRegister TmpReg = Inst.getOperand(1).getReg();
1165
const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1166
InstSeq Insts;
1167
1168
Insts.push_back(LoongArchAsmParser::Inst(
1169
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
1170
Insts.push_back(LoongArchAsmParser::Inst(
1171
LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1172
Insts.push_back(LoongArchAsmParser::Inst(
1173
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1174
Insts.push_back(LoongArchAsmParser::Inst(
1175
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1176
Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1177
1178
emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1179
}
1180
1181
void LoongArchAsmParser::emitLoadAddressTLSDescAbs(MCInst &Inst, SMLoc IDLoc,
1182
MCStreamer &Out) {
1183
// `la.tls.desc $rd, sym` with `la-global-with-abs` feature
1184
// for la32 expands to:
1185
// lu12i.w $rd, %desc_hi20(sym)
1186
// ori $rd, $rd, %desc_lo12(sym)
1187
// ld.w $ra, $rd, %desc_ld(sym)
1188
// jirl $ra, $ra, %desc_call(sym)
1189
//
1190
// for la64 expands to:
1191
// lu12i.w $rd, %desc_hi20(sym)
1192
// ori $rd, $rd, %desc_lo12(sym)
1193
// lu32i.d $rd, %desc64_lo20(sym)
1194
// lu52i.d $rd, $rd, %desc64_hi12(sym)
1195
// ld.d $ra, $rd, %desc_ld(sym)
1196
// jirl $ra, $ra, %desc_call(sym)
1197
MCRegister DestReg = Inst.getOperand(0).getReg();
1198
const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_TLS_DESC_ABS
1199
? Inst.getOperand(1).getExpr()
1200
: Inst.getOperand(2).getExpr();
1201
unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1202
InstSeq Insts;
1203
1204
Insts.push_back(LoongArchAsmParser::Inst(
1205
LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20));
1206
Insts.push_back(LoongArchAsmParser::Inst(
1207
LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12));
1208
1209
if (is64Bit()) {
1210
Insts.push_back(LoongArchAsmParser::Inst(
1211
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20));
1212
Insts.push_back(LoongArchAsmParser::Inst(
1213
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12));
1214
}
1215
1216
Insts.push_back(
1217
LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
1218
Insts.push_back(LoongArchAsmParser::Inst(
1219
LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));
1220
1221
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1222
}
1223
1224
void LoongArchAsmParser::emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc,
1225
MCStreamer &Out) {
1226
// la.tls.desc $rd, sym
1227
// expands to:
1228
// pcalau12i $rd, %desc_pc_hi20(sym)
1229
// addi.w/d $rd, $rd, %desc_pc_lo12(sym)
1230
// ld.w/d $ra, $rd, %desc_ld(sym)
1231
// jirl $ra, $ra, %desc_call(sym)
1232
MCRegister DestReg = Inst.getOperand(0).getReg();
1233
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1234
unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1235
unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1236
InstSeq Insts;
1237
1238
Insts.push_back(LoongArchAsmParser::Inst(
1239
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
1240
Insts.push_back(LoongArchAsmParser::Inst(
1241
ADDI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12));
1242
Insts.push_back(
1243
LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
1244
Insts.push_back(LoongArchAsmParser::Inst(
1245
LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));
1246
1247
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1248
}
1249
1250
void LoongArchAsmParser::emitLoadAddressTLSDescPcrelLarge(MCInst &Inst,
1251
SMLoc IDLoc,
1252
MCStreamer &Out) {
1253
// la.tls.desc $rd, $rj, sym
1254
// expands to:
1255
// pcalau12i $rd, %desc_pc_hi20(sym)
1256
// addi.d $rj, $r0, %desc_pc_lo12(sym)
1257
// lu32i.d $rj, %desc64_pc_lo20(sym)
1258
// lu52i.d $rj, $rj, %desc64_pc_hi12(sym)
1259
// add.d $rd, $rd, $rj
1260
// ld.w/d $ra, $rd, %desc_ld(sym)
1261
// jirl $ra, $ra, %desc_call(sym)
1262
MCRegister DestReg = Inst.getOperand(0).getReg();
1263
MCRegister TmpReg = Inst.getOperand(1).getReg();
1264
const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1265
InstSeq Insts;
1266
1267
Insts.push_back(LoongArchAsmParser::Inst(
1268
LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
1269
Insts.push_back(LoongArchAsmParser::Inst(
1270
LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12));
1271
Insts.push_back(LoongArchAsmParser::Inst(
1272
LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20));
1273
Insts.push_back(LoongArchAsmParser::Inst(
1274
LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12));
1275
Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1276
Insts.push_back(LoongArchAsmParser::Inst(
1277
LoongArch::LD_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
1278
Insts.push_back(LoongArchAsmParser::Inst(
1279
LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));
1280
1281
emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1282
}
1283
1284
void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
1285
MCStreamer &Out) {
1286
MCRegister DestReg = Inst.getOperand(0).getReg();
1287
int64_t Imm = Inst.getOperand(1).getImm();
1288
MCRegister SrcReg = LoongArch::R0;
1289
1290
if (Inst.getOpcode() == LoongArch::PseudoLI_W)
1291
Imm = SignExtend64<32>(Imm);
1292
1293
for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) {
1294
unsigned Opc = Inst.Opc;
1295
if (Opc == LoongArch::LU12I_W)
1296
Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addImm(Inst.Imm),
1297
getSTI());
1298
else
1299
Out.emitInstruction(
1300
MCInstBuilder(Opc).addReg(DestReg).addReg(SrcReg).addImm(Inst.Imm),
1301
getSTI());
1302
SrcReg = DestReg;
1303
}
1304
}
1305
1306
void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,
1307
MCStreamer &Out, bool IsTailCall) {
1308
// call36 sym
1309
// expands to:
1310
// pcaddu18i $ra, %call36(sym)
1311
// jirl $ra, $ra, 0
1312
//
1313
// tail36 $rj, sym
1314
// expands to:
1315
// pcaddu18i $rj, %call36(sym)
1316
// jirl $r0, $rj, 0
1317
unsigned ScratchReg =
1318
IsTailCall ? Inst.getOperand(0).getReg() : (unsigned)LoongArch::R1;
1319
const MCExpr *Sym =
1320
IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr();
1321
const LoongArchMCExpr *LE = LoongArchMCExpr::create(
1322
Sym, llvm::LoongArchMCExpr::VK_LoongArch_CALL36, getContext());
1323
1324
Out.emitInstruction(
1325
MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE),
1326
getSTI());
1327
Out.emitInstruction(
1328
MCInstBuilder(LoongArch::JIRL)
1329
.addReg(IsTailCall ? (unsigned)LoongArch::R0 : ScratchReg)
1330
.addReg(ScratchReg)
1331
.addImm(0),
1332
getSTI());
1333
}
1334
1335
bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1336
OperandVector &Operands,
1337
MCStreamer &Out) {
1338
Inst.setLoc(IDLoc);
1339
switch (Inst.getOpcode()) {
1340
default:
1341
break;
1342
case LoongArch::PseudoLA_ABS:
1343
case LoongArch::PseudoLA_ABS_LARGE:
1344
emitLoadAddressAbs(Inst, IDLoc, Out);
1345
return false;
1346
case LoongArch::PseudoLA_PCREL:
1347
emitLoadAddressPcrel(Inst, IDLoc, Out);
1348
return false;
1349
case LoongArch::PseudoLA_PCREL_LARGE:
1350
emitLoadAddressPcrelLarge(Inst, IDLoc, Out);
1351
return false;
1352
case LoongArch::PseudoLA_GOT:
1353
emitLoadAddressGot(Inst, IDLoc, Out);
1354
return false;
1355
case LoongArch::PseudoLA_GOT_LARGE:
1356
emitLoadAddressGotLarge(Inst, IDLoc, Out);
1357
return false;
1358
case LoongArch::PseudoLA_TLS_LE:
1359
emitLoadAddressTLSLE(Inst, IDLoc, Out);
1360
return false;
1361
case LoongArch::PseudoLA_TLS_IE:
1362
emitLoadAddressTLSIE(Inst, IDLoc, Out);
1363
return false;
1364
case LoongArch::PseudoLA_TLS_IE_LARGE:
1365
emitLoadAddressTLSIELarge(Inst, IDLoc, Out);
1366
return false;
1367
case LoongArch::PseudoLA_TLS_LD:
1368
emitLoadAddressTLSLD(Inst, IDLoc, Out);
1369
return false;
1370
case LoongArch::PseudoLA_TLS_LD_LARGE:
1371
emitLoadAddressTLSLDLarge(Inst, IDLoc, Out);
1372
return false;
1373
case LoongArch::PseudoLA_TLS_GD:
1374
emitLoadAddressTLSGD(Inst, IDLoc, Out);
1375
return false;
1376
case LoongArch::PseudoLA_TLS_GD_LARGE:
1377
emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);
1378
return false;
1379
case LoongArch::PseudoLA_TLS_DESC_ABS:
1380
case LoongArch::PseudoLA_TLS_DESC_ABS_LARGE:
1381
emitLoadAddressTLSDescAbs(Inst, IDLoc, Out);
1382
return false;
1383
case LoongArch::PseudoLA_TLS_DESC_PC:
1384
emitLoadAddressTLSDescPcrel(Inst, IDLoc, Out);
1385
return false;
1386
case LoongArch::PseudoLA_TLS_DESC_PC_LARGE:
1387
emitLoadAddressTLSDescPcrelLarge(Inst, IDLoc, Out);
1388
return false;
1389
case LoongArch::PseudoLI_W:
1390
case LoongArch::PseudoLI_D:
1391
emitLoadImm(Inst, IDLoc, Out);
1392
return false;
1393
case LoongArch::PseudoCALL36:
1394
emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);
1395
return false;
1396
case LoongArch::PseudoTAIL36:
1397
emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true);
1398
return false;
1399
}
1400
Out.emitInstruction(Inst, getSTI());
1401
return false;
1402
}
1403
1404
unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1405
unsigned Opc = Inst.getOpcode();
1406
switch (Opc) {
1407
default:
1408
if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W) {
1409
unsigned Rd = Inst.getOperand(0).getReg();
1410
unsigned Rk = Inst.getOperand(1).getReg();
1411
unsigned Rj = Inst.getOperand(2).getReg();
1412
if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0)
1413
return Match_RequiresAMORdDifferRkRj;
1414
}
1415
break;
1416
case LoongArch::PseudoLA_TLS_DESC_ABS:
1417
case LoongArch::PseudoLA_TLS_DESC_ABS_LARGE:
1418
case LoongArch::PseudoLA_TLS_DESC_PC:
1419
case LoongArch::PseudoLA_TLS_DESC_PC_LARGE: {
1420
unsigned Rd = Inst.getOperand(0).getReg();
1421
if (Rd != LoongArch::R4)
1422
return Match_RequiresLAORdR4;
1423
break;
1424
}
1425
case LoongArch::PseudoLA_PCREL_LARGE:
1426
case LoongArch::PseudoLA_GOT_LARGE:
1427
case LoongArch::PseudoLA_TLS_IE_LARGE:
1428
case LoongArch::PseudoLA_TLS_LD_LARGE:
1429
case LoongArch::PseudoLA_TLS_GD_LARGE: {
1430
unsigned Rd = Inst.getOperand(0).getReg();
1431
unsigned Rj = Inst.getOperand(1).getReg();
1432
if (Rd == Rj)
1433
return Match_RequiresLAORdDifferRj;
1434
break;
1435
}
1436
case LoongArch::CSRXCHG:
1437
case LoongArch::GCSRXCHG: {
1438
unsigned Rj = Inst.getOperand(2).getReg();
1439
if (Rj == LoongArch::R0 || Rj == LoongArch::R1)
1440
return Match_RequiresOpnd2NotR0R1;
1441
return Match_Success;
1442
}
1443
case LoongArch::BSTRINS_W:
1444
case LoongArch::BSTRINS_D:
1445
case LoongArch::BSTRPICK_W:
1446
case LoongArch::BSTRPICK_D: {
1447
unsigned Opc = Inst.getOpcode();
1448
const signed Msb =
1449
(Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
1450
? Inst.getOperand(3).getImm()
1451
: Inst.getOperand(2).getImm();
1452
const signed Lsb =
1453
(Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
1454
? Inst.getOperand(4).getImm()
1455
: Inst.getOperand(3).getImm();
1456
if (Msb < Lsb)
1457
return Match_RequiresMsbNotLessThanLsb;
1458
return Match_Success;
1459
}
1460
}
1461
1462
return Match_Success;
1463
}
1464
1465
unsigned
1466
LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1467
unsigned Kind) {
1468
LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp);
1469
if (!Op.isReg())
1470
return Match_InvalidOperand;
1471
1472
MCRegister Reg = Op.getReg();
1473
// As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1474
// register from FPR32 to FPR64 if necessary.
1475
if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) &&
1476
Kind == MCK_FPR64) {
1477
Op.setReg(convertFPR32ToFPR64(Reg));
1478
return Match_Success;
1479
}
1480
1481
return Match_InvalidOperand;
1482
}
1483
1484
bool LoongArchAsmParser::generateImmOutOfRangeError(
1485
OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1486
const Twine &Msg = "immediate must be an integer in the range") {
1487
SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1488
return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1489
}
1490
1491
bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1492
OperandVector &Operands,
1493
MCStreamer &Out,
1494
uint64_t &ErrorInfo,
1495
bool MatchingInlineAsm) {
1496
MCInst Inst;
1497
FeatureBitset MissingFeatures;
1498
1499
auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1500
MatchingInlineAsm);
1501
switch (Result) {
1502
default:
1503
break;
1504
case Match_Success:
1505
return processInstruction(Inst, IDLoc, Operands, Out);
1506
case Match_MissingFeature: {
1507
assert(MissingFeatures.any() && "Unknown missing features!");
1508
bool FirstFeature = true;
1509
std::string Msg = "instruction requires the following:";
1510
for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1511
if (MissingFeatures[i]) {
1512
Msg += FirstFeature ? " " : ", ";
1513
Msg += getSubtargetFeatureName(i);
1514
FirstFeature = false;
1515
}
1516
}
1517
return Error(IDLoc, Msg);
1518
}
1519
case Match_MnemonicFail: {
1520
FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1521
std::string Suggestion = LoongArchMnemonicSpellCheck(
1522
((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0);
1523
return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1524
}
1525
case Match_InvalidOperand: {
1526
SMLoc ErrorLoc = IDLoc;
1527
if (ErrorInfo != ~0ULL) {
1528
if (ErrorInfo >= Operands.size())
1529
return Error(ErrorLoc, "too few operands for instruction");
1530
1531
ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1532
if (ErrorLoc == SMLoc())
1533
ErrorLoc = IDLoc;
1534
}
1535
return Error(ErrorLoc, "invalid operand for instruction");
1536
}
1537
}
1538
1539
// Handle the case when the error message is of specific type
1540
// other than the generic Match_InvalidOperand, and the
1541
// corresponding operand is missing.
1542
if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1543
SMLoc ErrorLoc = IDLoc;
1544
if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1545
return Error(ErrorLoc, "too few operands for instruction");
1546
}
1547
1548
switch (Result) {
1549
default:
1550
break;
1551
case Match_RequiresMsbNotLessThanLsb: {
1552
SMLoc ErrorStart = Operands[3]->getStartLoc();
1553
return Error(ErrorStart, "msb is less than lsb",
1554
SMRange(ErrorStart, Operands[4]->getEndLoc()));
1555
}
1556
case Match_RequiresOpnd2NotR0R1:
1557
return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1");
1558
case Match_RequiresAMORdDifferRkRj:
1559
return Error(Operands[1]->getStartLoc(),
1560
"$rd must be different from both $rk and $rj");
1561
case Match_RequiresLAORdDifferRj:
1562
return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj");
1563
case Match_RequiresLAORdR4:
1564
return Error(Operands[1]->getStartLoc(), "$rd must be $r4");
1565
case Match_InvalidUImm1:
1566
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1567
/*Upper=*/(1 << 1) - 1);
1568
case Match_InvalidUImm2:
1569
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1570
/*Upper=*/(1 << 2) - 1);
1571
case Match_InvalidUImm2plus1:
1572
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1,
1573
/*Upper=*/(1 << 2));
1574
case Match_InvalidUImm3:
1575
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1576
/*Upper=*/(1 << 3) - 1);
1577
case Match_InvalidUImm4:
1578
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1579
/*Upper=*/(1 << 4) - 1);
1580
case Match_InvalidUImm5:
1581
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1582
/*Upper=*/(1 << 5) - 1);
1583
case Match_InvalidUImm6:
1584
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1585
/*Upper=*/(1 << 6) - 1);
1586
case Match_InvalidUImm7:
1587
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1588
/*Upper=*/(1 << 7) - 1);
1589
case Match_InvalidUImm8:
1590
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1591
/*Upper=*/(1 << 8) - 1);
1592
case Match_InvalidUImm12:
1593
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1594
/*Upper=*/(1 << 12) - 1);
1595
case Match_InvalidUImm12ori:
1596
return generateImmOutOfRangeError(
1597
Operands, ErrorInfo, /*Lower=*/0,
1598
/*Upper=*/(1 << 12) - 1,
1599
"operand must be a symbol with modifier (e.g. %abs_lo12) or an "
1600
"integer in the range");
1601
case Match_InvalidUImm14:
1602
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1603
/*Upper=*/(1 << 14) - 1);
1604
case Match_InvalidUImm15:
1605
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1606
/*Upper=*/(1 << 15) - 1);
1607
case Match_InvalidSImm5:
1608
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4),
1609
/*Upper=*/(1 << 4) - 1);
1610
case Match_InvalidSImm8:
1611
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7),
1612
/*Upper=*/(1 << 7) - 1);
1613
case Match_InvalidSImm8lsl1:
1614
return generateImmOutOfRangeError(
1615
Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2,
1616
"immediate must be a multiple of 2 in the range");
1617
case Match_InvalidSImm8lsl2:
1618
return generateImmOutOfRangeError(
1619
Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4,
1620
"immediate must be a multiple of 4 in the range");
1621
case Match_InvalidSImm10:
1622
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9),
1623
/*Upper=*/(1 << 9) - 1);
1624
case Match_InvalidSImm8lsl3:
1625
return generateImmOutOfRangeError(
1626
Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8,
1627
"immediate must be a multiple of 8 in the range");
1628
case Match_InvalidSImm9lsl3:
1629
return generateImmOutOfRangeError(
1630
Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8,
1631
"immediate must be a multiple of 8 in the range");
1632
case Match_InvalidSImm10lsl2:
1633
return generateImmOutOfRangeError(
1634
Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4,
1635
"immediate must be a multiple of 4 in the range");
1636
case Match_InvalidSImm11lsl1:
1637
return generateImmOutOfRangeError(
1638
Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2,
1639
"immediate must be a multiple of 2 in the range");
1640
case Match_InvalidSImm12:
1641
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1642
/*Upper=*/(1 << 11) - 1);
1643
case Match_InvalidSImm12addlike:
1644
return generateImmOutOfRangeError(
1645
Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1646
/*Upper=*/(1 << 11) - 1,
1647
"operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "
1648
"in the range");
1649
case Match_InvalidSImm12lu52id:
1650
return generateImmOutOfRangeError(
1651
Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1652
/*Upper=*/(1 << 11) - 1,
1653
"operand must be a symbol with modifier (e.g. %pc64_hi12) or an "
1654
"integer in the range");
1655
case Match_InvalidSImm13:
1656
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12),
1657
/*Upper=*/(1 << 12) - 1);
1658
case Match_InvalidSImm14lsl2:
1659
return generateImmOutOfRangeError(
1660
Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,
1661
"immediate must be a multiple of 4 in the range");
1662
case Match_InvalidSImm16:
1663
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15),
1664
/*Upper=*/(1 << 15) - 1);
1665
case Match_InvalidSImm16lsl2:
1666
return generateImmOutOfRangeError(
1667
Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,
1668
"operand must be a symbol with modifier (e.g. %b16) or an integer "
1669
"in the range");
1670
case Match_InvalidSImm20:
1671
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1672
/*Upper=*/(1 << 19) - 1);
1673
case Match_InvalidSImm20lu12iw:
1674
return generateImmOutOfRangeError(
1675
Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1676
/*Upper=*/(1 << 19) - 1,
1677
"operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "
1678
"in the range");
1679
case Match_InvalidSImm20lu32id:
1680
return generateImmOutOfRangeError(
1681
Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1682
/*Upper=*/(1 << 19) - 1,
1683
"operand must be a symbol with modifier (e.g. %abs64_lo20) or an "
1684
"integer in the range");
1685
case Match_InvalidSImm20pcalau12i:
1686
return generateImmOutOfRangeError(
1687
Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1688
/*Upper=*/(1 << 19) - 1,
1689
"operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "
1690
"in the range");
1691
case Match_InvalidSImm20pcaddu18i:
1692
return generateImmOutOfRangeError(
1693
Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1694
/*Upper=*/(1 << 19) - 1,
1695
"operand must be a symbol with modifier (e.g. %call36) or an integer "
1696
"in the range");
1697
case Match_InvalidSImm20pcaddi:
1698
return generateImmOutOfRangeError(
1699
Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1700
/*Upper=*/(1 << 19) - 1,
1701
"operand must be a symbol with modifier (e.g. %pcrel_20) or an integer "
1702
"in the range");
1703
case Match_InvalidSImm21lsl2:
1704
return generateImmOutOfRangeError(
1705
Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
1706
"operand must be a symbol with modifier (e.g. %b21) or an integer "
1707
"in the range");
1708
case Match_InvalidSImm26Operand:
1709
return generateImmOutOfRangeError(
1710
Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,
1711
"operand must be a bare symbol name or an immediate must be a multiple "
1712
"of 4 in the range");
1713
case Match_InvalidImm32: {
1714
SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1715
return Error(ErrorLoc, "operand must be a 32 bit immediate");
1716
}
1717
case Match_InvalidImm64: {
1718
SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1719
return Error(ErrorLoc, "operand must be a 64 bit immediate");
1720
}
1721
case Match_InvalidBareSymbol: {
1722
SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1723
return Error(ErrorLoc, "operand must be a bare symbol name");
1724
}
1725
case Match_InvalidTPRelAddSymbol: {
1726
SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1727
return Error(ErrorLoc, "operand must be a symbol with %le_add_r modifier");
1728
}
1729
}
1730
llvm_unreachable("Unknown match type detected!");
1731
}
1732
1733
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() {
1734
RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target());
1735
RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target());
1736
}
1737
1738