LLVM 17.0.0git
VEAsmParser.cpp
Go to the documentation of this file.
1//===-- VEAsmParser.cpp - Parse VE 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
12#include "VE.h"
13#include "llvm/ADT/STLExtras.h"
15#include "llvm/ADT/StringRef.h"
16#include "llvm/ADT/Twine.h"
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/MC/MCInstrInfo.h"
26#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCSymbol.h"
31#include <algorithm>
32#include <memory>
33
34using namespace llvm;
35
36#define DEBUG_TYPE "ve-asmparser"
37
38namespace {
39
40class VEOperand;
41
42class VEAsmParser : public MCTargetAsmParser {
43 MCAsmParser &Parser;
44
45 /// @name Auto-generated Match Functions
46 /// {
47
48#define GET_ASSEMBLER_HEADER
49#include "VEGenAsmMatcher.inc"
50
51 /// }
52
53 // public interface of the MCTargetAsmParser.
54 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
57 bool MatchingInlineAsm) override;
58 bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
59 SMLoc &EndLoc) override;
60 int parseRegisterName(unsigned (*matchFn)(StringRef));
62 SMLoc &EndLoc) override;
64 SMLoc NameLoc, OperandVector &Operands) override;
65 bool ParseDirective(AsmToken DirectiveID) override;
66
68 unsigned Kind) override;
69
70 // Custom parse functions for VE specific operands.
77 OperandMatchResultTy parseVEAsmOperand(std::unique_ptr<VEOperand> &Operand);
78
79 // Helper function to parse expression with a symbol.
80 const MCExpr *extractModifierFromExpr(const MCExpr *E,
81 VEMCExpr::VariantKind &Variant);
82 const MCExpr *fixupVariantKind(const MCExpr *E);
83 bool parseExpression(const MCExpr *&EVal);
84
85 // Split the mnemonic stripping conditional code and quantifiers
86 StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
88
89 bool parseLiteralValues(unsigned Size, SMLoc L);
90
91public:
92 VEAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
93 const MCInstrInfo &MII, const MCTargetOptions &Options)
94 : MCTargetAsmParser(Options, sti, MII), Parser(parser) {
95 // Initialize the set of available features.
96 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
97 }
98};
99
100} // end anonymous namespace
101
102static const MCPhysReg I32Regs[64] = {
103 VE::SW0, VE::SW1, VE::SW2, VE::SW3, VE::SW4, VE::SW5, VE::SW6,
104 VE::SW7, VE::SW8, VE::SW9, VE::SW10, VE::SW11, VE::SW12, VE::SW13,
105 VE::SW14, VE::SW15, VE::SW16, VE::SW17, VE::SW18, VE::SW19, VE::SW20,
106 VE::SW21, VE::SW22, VE::SW23, VE::SW24, VE::SW25, VE::SW26, VE::SW27,
107 VE::SW28, VE::SW29, VE::SW30, VE::SW31, VE::SW32, VE::SW33, VE::SW34,
108 VE::SW35, VE::SW36, VE::SW37, VE::SW38, VE::SW39, VE::SW40, VE::SW41,
109 VE::SW42, VE::SW43, VE::SW44, VE::SW45, VE::SW46, VE::SW47, VE::SW48,
110 VE::SW49, VE::SW50, VE::SW51, VE::SW52, VE::SW53, VE::SW54, VE::SW55,
111 VE::SW56, VE::SW57, VE::SW58, VE::SW59, VE::SW60, VE::SW61, VE::SW62,
112 VE::SW63};
113
114static const MCPhysReg F32Regs[64] = {
115 VE::SF0, VE::SF1, VE::SF2, VE::SF3, VE::SF4, VE::SF5, VE::SF6,
116 VE::SF7, VE::SF8, VE::SF9, VE::SF10, VE::SF11, VE::SF12, VE::SF13,
117 VE::SF14, VE::SF15, VE::SF16, VE::SF17, VE::SF18, VE::SF19, VE::SF20,
118 VE::SF21, VE::SF22, VE::SF23, VE::SF24, VE::SF25, VE::SF26, VE::SF27,
119 VE::SF28, VE::SF29, VE::SF30, VE::SF31, VE::SF32, VE::SF33, VE::SF34,
120 VE::SF35, VE::SF36, VE::SF37, VE::SF38, VE::SF39, VE::SF40, VE::SF41,
121 VE::SF42, VE::SF43, VE::SF44, VE::SF45, VE::SF46, VE::SF47, VE::SF48,
122 VE::SF49, VE::SF50, VE::SF51, VE::SF52, VE::SF53, VE::SF54, VE::SF55,
123 VE::SF56, VE::SF57, VE::SF58, VE::SF59, VE::SF60, VE::SF61, VE::SF62,
124 VE::SF63};
125
126static const MCPhysReg F128Regs[32] = {
127 VE::Q0, VE::Q1, VE::Q2, VE::Q3, VE::Q4, VE::Q5, VE::Q6, VE::Q7,
128 VE::Q8, VE::Q9, VE::Q10, VE::Q11, VE::Q12, VE::Q13, VE::Q14, VE::Q15,
129 VE::Q16, VE::Q17, VE::Q18, VE::Q19, VE::Q20, VE::Q21, VE::Q22, VE::Q23,
130 VE::Q24, VE::Q25, VE::Q26, VE::Q27, VE::Q28, VE::Q29, VE::Q30, VE::Q31};
131
132static const MCPhysReg VM512Regs[8] = {VE::VMP0, VE::VMP1, VE::VMP2, VE::VMP3,
133 VE::VMP4, VE::VMP5, VE::VMP6, VE::VMP7};
134
135static const MCPhysReg MISCRegs[31] = {
136 VE::USRCC, VE::PSW, VE::SAR, VE::NoRegister,
137 VE::NoRegister, VE::NoRegister, VE::NoRegister, VE::PMMR,
138 VE::PMCR0, VE::PMCR1, VE::PMCR2, VE::PMCR3,
139 VE::NoRegister, VE::NoRegister, VE::NoRegister, VE::NoRegister,
140 VE::PMC0, VE::PMC1, VE::PMC2, VE::PMC3,
141 VE::PMC4, VE::PMC5, VE::PMC6, VE::PMC7,
142 VE::PMC8, VE::PMC9, VE::PMC10, VE::PMC11,
143 VE::PMC12, VE::PMC13, VE::PMC14};
144
145namespace {
146
147/// VEOperand - Instances of this class represent a parsed VE machine
148/// instruction.
149class VEOperand : public MCParsedAsmOperand {
150private:
151 enum KindTy {
152 k_Token,
153 k_Register,
154 k_Immediate,
155 // SX-Aurora ASX form is disp(index, base).
156 k_MemoryRegRegImm, // base=reg, index=reg, disp=imm
157 k_MemoryRegImmImm, // base=reg, index=imm, disp=imm
158 k_MemoryZeroRegImm, // base=0, index=reg, disp=imm
159 k_MemoryZeroImmImm, // base=0, index=imm, disp=imm
160 // SX-Aurora AS form is disp(base).
161 k_MemoryRegImm, // base=reg, disp=imm
162 k_MemoryZeroImm, // base=0, disp=imm
163 // Other special cases for Aurora VE
164 k_CCOp, // condition code
165 k_RDOp, // rounding mode
166 k_MImmOp, // Special immediate value of sequential bit stream of 0 or 1.
167 } Kind;
168
169 SMLoc StartLoc, EndLoc;
170
171 struct Token {
172 const char *Data;
173 unsigned Length;
174 };
175
176 struct RegOp {
177 unsigned RegNum;
178 };
179
180 struct ImmOp {
181 const MCExpr *Val;
182 };
183
184 struct MemOp {
185 unsigned Base;
186 unsigned IndexReg;
187 const MCExpr *Index;
188 const MCExpr *Offset;
189 };
190
191 struct CCOp {
192 unsigned CCVal;
193 };
194
195 struct RDOp {
196 unsigned RDVal;
197 };
198
199 struct MImmOp {
200 const MCExpr *Val;
201 bool M0Flag;
202 };
203
204 union {
205 struct Token Tok;
206 struct RegOp Reg;
207 struct ImmOp Imm;
208 struct MemOp Mem;
209 struct CCOp CC;
210 struct RDOp RD;
211 struct MImmOp MImm;
212 };
213
214public:
215 VEOperand(KindTy K) : Kind(K) {}
216
217 bool isToken() const override { return Kind == k_Token; }
218 bool isReg() const override { return Kind == k_Register; }
219 bool isImm() const override { return Kind == k_Immediate; }
220 bool isMem() const override {
221 return isMEMrri() || isMEMrii() || isMEMzri() || isMEMzii() || isMEMri() ||
222 isMEMzi();
223 }
224 bool isMEMrri() const { return Kind == k_MemoryRegRegImm; }
225 bool isMEMrii() const { return Kind == k_MemoryRegImmImm; }
226 bool isMEMzri() const { return Kind == k_MemoryZeroRegImm; }
227 bool isMEMzii() const { return Kind == k_MemoryZeroImmImm; }
228 bool isMEMri() const { return Kind == k_MemoryRegImm; }
229 bool isMEMzi() const { return Kind == k_MemoryZeroImm; }
230 bool isCCOp() const { return Kind == k_CCOp; }
231 bool isRDOp() const { return Kind == k_RDOp; }
232 bool isZero() {
233 if (!isImm())
234 return false;
235
236 // Constant case
237 if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {
238 int64_t Value = ConstExpr->getValue();
239 return Value == 0;
240 }
241 return false;
242 }
243 bool isUImm0to2() {
244 if (!isImm())
245 return false;
246
247 // Constant case
248 if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {
249 int64_t Value = ConstExpr->getValue();
250 return Value >= 0 && Value < 3;
251 }
252 return false;
253 }
254 bool isUImm1() {
255 if (!isImm())
256 return false;
257
258 // Constant case
259 if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {
260 int64_t Value = ConstExpr->getValue();
261 return isUInt<1>(Value);
262 }
263 return false;
264 }
265 bool isUImm2() {
266 if (!isImm())
267 return false;
268
269 // Constant case
270 if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {
271 int64_t Value = ConstExpr->getValue();
272 return isUInt<2>(Value);
273 }
274 return false;
275 }
276 bool isUImm3() {
277 if (!isImm())
278 return false;
279
280 // Constant case
281 if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {
282 int64_t Value = ConstExpr->getValue();
283 return isUInt<3>(Value);
284 }
285 return false;
286 }
287 bool isUImm4() {
288 if (!isImm())
289 return false;
290
291 // Constant case
292 if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {
293 int64_t Value = ConstExpr->getValue();
294 return isUInt<4>(Value);
295 }
296 return false;
297 }
298 bool isUImm6() {
299 if (!isImm())
300 return false;
301
302 // Constant case
303 if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {
304 int64_t Value = ConstExpr->getValue();
305 return isUInt<6>(Value);
306 }
307 return false;
308 }
309 bool isUImm7() {
310 if (!isImm())
311 return false;
312
313 // Constant case
314 if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {
315 int64_t Value = ConstExpr->getValue();
316 return isUInt<7>(Value);
317 }
318 return false;
319 }
320 bool isSImm7() {
321 if (!isImm())
322 return false;
323
324 // Constant case
325 if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {
326 int64_t Value = ConstExpr->getValue();
327 return isInt<7>(Value);
328 }
329 return false;
330 }
331 bool isMImm() const {
332 if (Kind != k_MImmOp)
333 return false;
334
335 // Constant case
336 if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(MImm.Val)) {
337 int64_t Value = ConstExpr->getValue();
338 return isUInt<6>(Value);
339 }
340 return false;
341 }
342
343 StringRef getToken() const {
344 assert(Kind == k_Token && "Invalid access!");
345 return StringRef(Tok.Data, Tok.Length);
346 }
347
348 unsigned getReg() const override {
349 assert((Kind == k_Register) && "Invalid access!");
350 return Reg.RegNum;
351 }
352
353 const MCExpr *getImm() const {
354 assert((Kind == k_Immediate) && "Invalid access!");
355 return Imm.Val;
356 }
357
358 unsigned getMemBase() const {
359 assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
360 Kind == k_MemoryRegImm) &&
361 "Invalid access!");
362 return Mem.Base;
363 }
364
365 unsigned getMemIndexReg() const {
366 assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryZeroRegImm) &&
367 "Invalid access!");
368 return Mem.IndexReg;
369 }
370
371 const MCExpr *getMemIndex() const {
372 assert((Kind == k_MemoryRegImmImm || Kind == k_MemoryZeroImmImm) &&
373 "Invalid access!");
374 return Mem.Index;
375 }
376
377 const MCExpr *getMemOffset() const {
378 assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
379 Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm ||
380 Kind == k_MemoryRegImm || Kind == k_MemoryZeroImm) &&
381 "Invalid access!");
382 return Mem.Offset;
383 }
384
385 void setMemOffset(const MCExpr *off) {
386 assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
387 Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm ||
388 Kind == k_MemoryRegImm || Kind == k_MemoryZeroImm) &&
389 "Invalid access!");
390 Mem.Offset = off;
391 }
392
393 unsigned getCCVal() const {
394 assert((Kind == k_CCOp) && "Invalid access!");
395 return CC.CCVal;
396 }
397
398 unsigned getRDVal() const {
399 assert((Kind == k_RDOp) && "Invalid access!");
400 return RD.RDVal;
401 }
402
403 const MCExpr *getMImmVal() const {
404 assert((Kind == k_MImmOp) && "Invalid access!");
405 return MImm.Val;
406 }
407 bool getM0Flag() const {
408 assert((Kind == k_MImmOp) && "Invalid access!");
409 return MImm.M0Flag;
410 }
411
412 /// getStartLoc - Get the location of the first token of this operand.
413 SMLoc getStartLoc() const override { return StartLoc; }
414 /// getEndLoc - Get the location of the last token of this operand.
415 SMLoc getEndLoc() const override { return EndLoc; }
416
417 void print(raw_ostream &OS) const override {
418 switch (Kind) {
419 case k_Token:
420 OS << "Token: " << getToken() << "\n";
421 break;
422 case k_Register:
423 OS << "Reg: #" << getReg() << "\n";
424 break;
425 case k_Immediate:
426 OS << "Imm: " << getImm() << "\n";
427 break;
428 case k_MemoryRegRegImm:
429 assert(getMemOffset() != nullptr);
430 OS << "Mem: #" << getMemBase() << "+#" << getMemIndexReg() << "+"
431 << *getMemOffset() << "\n";
432 break;
433 case k_MemoryRegImmImm:
434 assert(getMemIndex() != nullptr && getMemOffset() != nullptr);
435 OS << "Mem: #" << getMemBase() << "+" << *getMemIndex() << "+"
436 << *getMemOffset() << "\n";
437 break;
438 case k_MemoryZeroRegImm:
439 assert(getMemOffset() != nullptr);
440 OS << "Mem: 0+#" << getMemIndexReg() << "+" << *getMemOffset() << "\n";
441 break;
442 case k_MemoryZeroImmImm:
443 assert(getMemIndex() != nullptr && getMemOffset() != nullptr);
444 OS << "Mem: 0+" << *getMemIndex() << "+" << *getMemOffset() << "\n";
445 break;
446 case k_MemoryRegImm:
447 assert(getMemOffset() != nullptr);
448 OS << "Mem: #" << getMemBase() << "+" << *getMemOffset() << "\n";
449 break;
450 case k_MemoryZeroImm:
451 assert(getMemOffset() != nullptr);
452 OS << "Mem: 0+" << *getMemOffset() << "\n";
453 break;
454 case k_CCOp:
455 OS << "CCOp: " << getCCVal() << "\n";
456 break;
457 case k_RDOp:
458 OS << "RDOp: " << getRDVal() << "\n";
459 break;
460 case k_MImmOp:
461 OS << "MImm: (" << getMImmVal() << (getM0Flag() ? ")0" : ")1") << "\n";
462 break;
463 }
464 }
465
466 void addRegOperands(MCInst &Inst, unsigned N) const {
467 assert(N == 1 && "Invalid number of operands!");
469 }
470
471 void addImmOperands(MCInst &Inst, unsigned N) const {
472 assert(N == 1 && "Invalid number of operands!");
473 const MCExpr *Expr = getImm();
474 addExpr(Inst, Expr);
475 }
476
477 void addZeroOperands(MCInst &Inst, unsigned N) const {
478 addImmOperands(Inst, N);
479 }
480
481 void addUImm0to2Operands(MCInst &Inst, unsigned N) const {
482 addImmOperands(Inst, N);
483 }
484
485 void addUImm1Operands(MCInst &Inst, unsigned N) const {
486 addImmOperands(Inst, N);
487 }
488
489 void addUImm2Operands(MCInst &Inst, unsigned N) const {
490 addImmOperands(Inst, N);
491 }
492
493 void addUImm3Operands(MCInst &Inst, unsigned N) const {
494 addImmOperands(Inst, N);
495 }
496
497 void addUImm4Operands(MCInst &Inst, unsigned N) const {
498 addImmOperands(Inst, N);
499 }
500
501 void addUImm6Operands(MCInst &Inst, unsigned N) const {
502 addImmOperands(Inst, N);
503 }
504
505 void addUImm7Operands(MCInst &Inst, unsigned N) const {
506 addImmOperands(Inst, N);
507 }
508
509 void addSImm7Operands(MCInst &Inst, unsigned N) const {
510 addImmOperands(Inst, N);
511 }
512
513 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
514 // Add as immediate when possible. Null MCExpr = 0.
515 if (!Expr)
517 else if (const auto *CE = dyn_cast<MCConstantExpr>(Expr))
518 Inst.addOperand(MCOperand::createImm(CE->getValue()));
519 else
521 }
522
523 void addMEMrriOperands(MCInst &Inst, unsigned N) const {
524 assert(N == 3 && "Invalid number of operands!");
525
526 Inst.addOperand(MCOperand::createReg(getMemBase()));
527 Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
528 addExpr(Inst, getMemOffset());
529 }
530
531 void addMEMriiOperands(MCInst &Inst, unsigned N) const {
532 assert(N == 3 && "Invalid number of operands!");
533
534 Inst.addOperand(MCOperand::createReg(getMemBase()));
535 addExpr(Inst, getMemIndex());
536 addExpr(Inst, getMemOffset());
537 }
538
539 void addMEMzriOperands(MCInst &Inst, unsigned N) const {
540 assert(N == 3 && "Invalid number of operands!");
541
543 Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
544 addExpr(Inst, getMemOffset());
545 }
546
547 void addMEMziiOperands(MCInst &Inst, unsigned N) const {
548 assert(N == 3 && "Invalid number of operands!");
549
551 addExpr(Inst, getMemIndex());
552 addExpr(Inst, getMemOffset());
553 }
554
555 void addMEMriOperands(MCInst &Inst, unsigned N) const {
556 assert(N == 2 && "Invalid number of operands!");
557
558 Inst.addOperand(MCOperand::createReg(getMemBase()));
559 addExpr(Inst, getMemOffset());
560 }
561
562 void addMEMziOperands(MCInst &Inst, unsigned N) const {
563 assert(N == 2 && "Invalid number of operands!");
564
566 addExpr(Inst, getMemOffset());
567 }
568
569 void addCCOpOperands(MCInst &Inst, unsigned N) const {
570 assert(N == 1 && "Invalid number of operands!");
571
572 Inst.addOperand(MCOperand::createImm(getCCVal()));
573 }
574
575 void addRDOpOperands(MCInst &Inst, unsigned N) const {
576 assert(N == 1 && "Invalid number of operands!");
577
578 Inst.addOperand(MCOperand::createImm(getRDVal()));
579 }
580
581 void addMImmOperands(MCInst &Inst, unsigned N) const {
582 assert(N == 1 && "Invalid number of operands!");
583 const auto *ConstExpr = dyn_cast<MCConstantExpr>(getMImmVal());
584 assert(ConstExpr && "Null operands!");
585 int64_t Value = ConstExpr->getValue();
586 if (getM0Flag())
587 Value += 64;
589 }
590
591 static std::unique_ptr<VEOperand> CreateToken(StringRef Str, SMLoc S) {
592 auto Op = std::make_unique<VEOperand>(k_Token);
593 Op->Tok.Data = Str.data();
594 Op->Tok.Length = Str.size();
595 Op->StartLoc = S;
596 Op->EndLoc = S;
597 return Op;
598 }
599
600 static std::unique_ptr<VEOperand> CreateReg(unsigned RegNum, SMLoc S,
601 SMLoc E) {
602 auto Op = std::make_unique<VEOperand>(k_Register);
603 Op->Reg.RegNum = RegNum;
604 Op->StartLoc = S;
605 Op->EndLoc = E;
606 return Op;
607 }
608
609 static std::unique_ptr<VEOperand> CreateImm(const MCExpr *Val, SMLoc S,
610 SMLoc E) {
611 auto Op = std::make_unique<VEOperand>(k_Immediate);
612 Op->Imm.Val = Val;
613 Op->StartLoc = S;
614 Op->EndLoc = E;
615 return Op;
616 }
617
618 static std::unique_ptr<VEOperand> CreateCCOp(unsigned CCVal, SMLoc S,
619 SMLoc E) {
620 auto Op = std::make_unique<VEOperand>(k_CCOp);
621 Op->CC.CCVal = CCVal;
622 Op->StartLoc = S;
623 Op->EndLoc = E;
624 return Op;
625 }
626
627 static std::unique_ptr<VEOperand> CreateRDOp(unsigned RDVal, SMLoc S,
628 SMLoc E) {
629 auto Op = std::make_unique<VEOperand>(k_RDOp);
630 Op->RD.RDVal = RDVal;
631 Op->StartLoc = S;
632 Op->EndLoc = E;
633 return Op;
634 }
635
636 static std::unique_ptr<VEOperand> CreateMImm(const MCExpr *Val, bool Flag,
637 SMLoc S, SMLoc E) {
638 auto Op = std::make_unique<VEOperand>(k_MImmOp);
639 Op->MImm.Val = Val;
640 Op->MImm.M0Flag = Flag;
641 Op->StartLoc = S;
642 Op->EndLoc = E;
643 return Op;
644 }
645
646 static bool MorphToI32Reg(VEOperand &Op) {
647 unsigned Reg = Op.getReg();
648 unsigned regIdx = Reg - VE::SX0;
649 if (regIdx > 63)
650 return false;
651 Op.Reg.RegNum = I32Regs[regIdx];
652 return true;
653 }
654
655 static bool MorphToF32Reg(VEOperand &Op) {
656 unsigned Reg = Op.getReg();
657 unsigned regIdx = Reg - VE::SX0;
658 if (regIdx > 63)
659 return false;
660 Op.Reg.RegNum = F32Regs[regIdx];
661 return true;
662 }
663
664 static bool MorphToF128Reg(VEOperand &Op) {
665 unsigned Reg = Op.getReg();
666 unsigned regIdx = Reg - VE::SX0;
667 if (regIdx % 2 || regIdx > 63)
668 return false;
669 Op.Reg.RegNum = F128Regs[regIdx / 2];
670 return true;
671 }
672
673 static bool MorphToVM512Reg(VEOperand &Op) {
674 unsigned Reg = Op.getReg();
675 unsigned regIdx = Reg - VE::VM0;
676 if (regIdx % 2 || regIdx > 15)
677 return false;
678 Op.Reg.RegNum = VM512Regs[regIdx / 2];
679 return true;
680 }
681
682 static bool MorphToMISCReg(VEOperand &Op) {
683 const auto *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm());
684 if (!ConstExpr)
685 return false;
686 unsigned regIdx = ConstExpr->getValue();
687 if (regIdx > 31 || MISCRegs[regIdx] == VE::NoRegister)
688 return false;
689 Op.Kind = k_Register;
690 Op.Reg.RegNum = MISCRegs[regIdx];
691 return true;
692 }
693
694 static std::unique_ptr<VEOperand>
695 MorphToMEMri(unsigned Base, std::unique_ptr<VEOperand> Op) {
696 const MCExpr *Imm = Op->getImm();
697 Op->Kind = k_MemoryRegImm;
698 Op->Mem.Base = Base;
699 Op->Mem.IndexReg = 0;
700 Op->Mem.Index = nullptr;
701 Op->Mem.Offset = Imm;
702 return Op;
703 }
704
705 static std::unique_ptr<VEOperand>
706 MorphToMEMzi(std::unique_ptr<VEOperand> Op) {
707 const MCExpr *Imm = Op->getImm();
708 Op->Kind = k_MemoryZeroImm;
709 Op->Mem.Base = 0;
710 Op->Mem.IndexReg = 0;
711 Op->Mem.Index = nullptr;
712 Op->Mem.Offset = Imm;
713 return Op;
714 }
715
716 static std::unique_ptr<VEOperand>
717 MorphToMEMrri(unsigned Base, unsigned Index, std::unique_ptr<VEOperand> Op) {
718 const MCExpr *Imm = Op->getImm();
719 Op->Kind = k_MemoryRegRegImm;
720 Op->Mem.Base = Base;
721 Op->Mem.IndexReg = Index;
722 Op->Mem.Index = nullptr;
723 Op->Mem.Offset = Imm;
724 return Op;
725 }
726
727 static std::unique_ptr<VEOperand>
728 MorphToMEMrii(unsigned Base, const MCExpr *Index,
729 std::unique_ptr<VEOperand> Op) {
730 const MCExpr *Imm = Op->getImm();
731 Op->Kind = k_MemoryRegImmImm;
732 Op->Mem.Base = Base;
733 Op->Mem.IndexReg = 0;
734 Op->Mem.Index = Index;
735 Op->Mem.Offset = Imm;
736 return Op;
737 }
738
739 static std::unique_ptr<VEOperand>
740 MorphToMEMzri(unsigned Index, std::unique_ptr<VEOperand> Op) {
741 const MCExpr *Imm = Op->getImm();
742 Op->Kind = k_MemoryZeroRegImm;
743 Op->Mem.Base = 0;
744 Op->Mem.IndexReg = Index;
745 Op->Mem.Index = nullptr;
746 Op->Mem.Offset = Imm;
747 return Op;
748 }
749
750 static std::unique_ptr<VEOperand>
751 MorphToMEMzii(const MCExpr *Index, std::unique_ptr<VEOperand> Op) {
752 const MCExpr *Imm = Op->getImm();
753 Op->Kind = k_MemoryZeroImmImm;
754 Op->Mem.Base = 0;
755 Op->Mem.IndexReg = 0;
756 Op->Mem.Index = Index;
757 Op->Mem.Offset = Imm;
758 return Op;
759 }
760};
761
762} // end anonymous namespace
763
764bool VEAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
767 bool MatchingInlineAsm) {
768 MCInst Inst;
769 unsigned MatchResult =
770 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
771 switch (MatchResult) {
772 case Match_Success:
773 Inst.setLoc(IDLoc);
774 Out.emitInstruction(Inst, getSTI());
775 return false;
776
777 case Match_MissingFeature:
778 return Error(IDLoc,
779 "instruction requires a CPU feature not currently enabled");
780
781 case Match_InvalidOperand: {
782 SMLoc ErrorLoc = IDLoc;
783 if (ErrorInfo != ~0ULL) {
784 if (ErrorInfo >= Operands.size())
785 return Error(IDLoc, "too few operands for instruction");
786
787 ErrorLoc = ((VEOperand &)*Operands[ErrorInfo]).getStartLoc();
788 if (ErrorLoc == SMLoc())
789 ErrorLoc = IDLoc;
790 }
791
792 return Error(ErrorLoc, "invalid operand for instruction");
793 }
794 case Match_MnemonicFail:
795 return Error(IDLoc, "invalid instruction mnemonic");
796 }
797 llvm_unreachable("Implement any new match types added!");
798}
799
800bool VEAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
801 SMLoc &EndLoc) {
802 if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
803 return Error(StartLoc, "invalid register name");
804 return false;
805}
806
807/// Parses a register name using a given matching function.
808/// Checks for lowercase or uppercase if necessary.
809int VEAsmParser::parseRegisterName(unsigned (*matchFn)(StringRef)) {
810 StringRef Name = Parser.getTok().getString();
811
812 int RegNum = matchFn(Name);
813
814 // GCC supports case insensitive register names. All of the VE registers
815 // are all lower case.
816 if (RegNum == VE::NoRegister) {
817 RegNum = matchFn(Name.lower());
818 }
819
820 return RegNum;
821}
822
823/// Maps from the set of all register names to a register number.
824/// \note Generated by TableGen.
826
827/// Maps from the set of all alternative registernames to a register number.
828/// \note Generated by TableGen.
830
831OperandMatchResultTy VEAsmParser::tryParseRegister(MCRegister &RegNo,
832 SMLoc &StartLoc,
833 SMLoc &EndLoc) {
834 const AsmToken Tok = Parser.getTok();
835 StartLoc = Tok.getLoc();
836 EndLoc = Tok.getEndLoc();
837 RegNo = 0;
838 if (getLexer().getKind() != AsmToken::Percent)
840 Parser.Lex();
841
842 RegNo = parseRegisterName(&MatchRegisterName);
843 if (RegNo == VE::NoRegister)
844 RegNo = parseRegisterName(&MatchRegisterAltName);
845
846 if (RegNo != VE::NoRegister) {
847 Parser.Lex();
849 }
850
851 getLexer().UnLex(Tok);
853}
854
855static StringRef parseCC(StringRef Name, unsigned Prefix, unsigned Suffix,
856 bool IntegerCC, bool OmitCC, SMLoc NameLoc,
858 // Parse instructions with a conditional code. For example, 'bne' is
859 // converted into two operands 'b' and 'ne'.
860 StringRef Cond = Name.slice(Prefix, Suffix);
861 VECC::CondCode CondCode =
863
864 // If OmitCC is enabled, CC_AT and CC_AF is treated as a part of mnemonic.
865 if (CondCode != VECC::UNKNOWN &&
866 (!OmitCC || (CondCode != VECC::CC_AT && CondCode != VECC::CC_AF))) {
867 StringRef SuffixStr = Name.substr(Suffix);
868 // Push "b".
869 Name = Name.slice(0, Prefix);
870 Operands->push_back(VEOperand::CreateToken(Name, NameLoc));
871 // Push $cond part.
872 SMLoc CondLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Prefix);
873 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Suffix);
874 Operands->push_back(VEOperand::CreateCCOp(CondCode, CondLoc, SuffixLoc));
875 // push suffix like ".l.t"
876 if (!SuffixStr.empty())
877 Operands->push_back(VEOperand::CreateToken(SuffixStr, SuffixLoc));
878 } else {
879 Operands->push_back(VEOperand::CreateToken(Name, NameLoc));
880 }
881 return Name;
882}
883
884static StringRef parseRD(StringRef Name, unsigned Prefix, SMLoc NameLoc,
886 // Parse instructions with a conditional code. For example, 'cvt.w.d.sx.rz'
887 // is converted into two operands 'cvt.w.d.sx' and '.rz'.
888 StringRef RD = Name.substr(Prefix);
890
892 Name = Name.slice(0, Prefix);
893 // push 1st like `cvt.w.d.sx`
894 Operands->push_back(VEOperand::CreateToken(Name, NameLoc));
895 SMLoc SuffixLoc =
896 SMLoc::getFromPointer(NameLoc.getPointer() + (RD.data() - Name.data()));
898 SMLoc::getFromPointer(NameLoc.getPointer() + (RD.end() - Name.data()));
899 // push $round if it has rounding mode
900 Operands->push_back(
901 VEOperand::CreateRDOp(RoundingMode, SuffixLoc, SuffixEnd));
902 } else {
903 Operands->push_back(VEOperand::CreateToken(Name, NameLoc));
904 }
905 return Name;
906}
907
908// Split the mnemonic into ASM operand, conditional code and instruction
909// qualifier (half-word, byte).
910StringRef VEAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
912 // Create the leading tokens for the mnemonic
913 StringRef Mnemonic = Name;
914
915 if (Name[0] == 'b') {
916 // Match b?? or br??.
917 size_t Start = 1;
918 size_t Next = Name.find('.');
919 // Adjust position of CondCode.
920 if (Name.size() > 1 && Name[1] == 'r')
921 Start = 2;
922 // Check suffix.
923 bool ICC = true;
924 if (Next + 1 < Name.size() &&
925 (Name[Next + 1] == 'd' || Name[Next + 1] == 's'))
926 ICC = false;
927 Mnemonic = parseCC(Name, Start, Next, ICC, true, NameLoc, Operands);
928 } else if (Name.startswith("cmov.l.") || Name.startswith("cmov.w.") ||
929 Name.startswith("cmov.d.") || Name.startswith("cmov.s.")) {
930 bool ICC = Name[5] == 'l' || Name[5] == 'w';
931 Mnemonic = parseCC(Name, 7, Name.size(), ICC, false, NameLoc, Operands);
932 } else if (Name.startswith("cvt.w.d.sx") || Name.startswith("cvt.w.d.zx") ||
933 Name.startswith("cvt.w.s.sx") || Name.startswith("cvt.w.s.zx")) {
934 Mnemonic = parseRD(Name, 10, NameLoc, Operands);
935 } else if (Name.startswith("cvt.l.d")) {
936 Mnemonic = parseRD(Name, 7, NameLoc, Operands);
937 } else if (Name.startswith("vcvt.w.d.sx") || Name.startswith("vcvt.w.d.zx") ||
938 Name.startswith("vcvt.w.s.sx") || Name.startswith("vcvt.w.s.zx")) {
939 Mnemonic = parseRD(Name, 11, NameLoc, Operands);
940 } else if (Name.startswith("vcvt.l.d")) {
941 Mnemonic = parseRD(Name, 8, NameLoc, Operands);
942 } else if (Name.startswith("pvcvt.w.s.lo") ||
943 Name.startswith("pvcvt.w.s.up")) {
944 Mnemonic = parseRD(Name, 12, NameLoc, Operands);
945 } else if (Name.startswith("pvcvt.w.s")) {
946 Mnemonic = parseRD(Name, 9, NameLoc, Operands);
947 } else if (Name.startswith("vfmk.l.") || Name.startswith("vfmk.w.") ||
948 Name.startswith("vfmk.d.") || Name.startswith("vfmk.s.")) {
949 bool ICC = Name[5] == 'l' || Name[5] == 'w' ? true : false;
950 Mnemonic = parseCC(Name, 7, Name.size(), ICC, true, NameLoc, Operands);
951 } else if (Name.startswith("pvfmk.w.lo.") || Name.startswith("pvfmk.w.up.") ||
952 Name.startswith("pvfmk.s.lo.") || Name.startswith("pvfmk.s.up.")) {
953 bool ICC = Name[6] == 'l' || Name[6] == 'w' ? true : false;
954 Mnemonic = parseCC(Name, 11, Name.size(), ICC, true, NameLoc, Operands);
955 } else {
956 Operands->push_back(VEOperand::CreateToken(Mnemonic, NameLoc));
957 }
958
959 return Mnemonic;
960}
961
962static void applyMnemonicAliases(StringRef &Mnemonic,
963 const FeatureBitset &Features,
964 unsigned VariantID);
965
966bool VEAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
967 SMLoc NameLoc, OperandVector &Operands) {
968 // If the target architecture uses MnemonicAlias, call it here to parse
969 // operands correctly.
970 applyMnemonicAliases(Name, getAvailableFeatures(), 0);
971
972 // Split name to first token and the rest, e.g. "bgt.l.t" to "b", "gt", and
973 // ".l.t". We treat "b" as a mnemonic, "gt" as first operand, and ".l.t"
974 // as second operand.
975 StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
976
977 if (getLexer().isNot(AsmToken::EndOfStatement)) {
978 // Read the first operand.
979 if (parseOperand(Operands, Mnemonic) != MatchOperand_Success) {
980 SMLoc Loc = getLexer().getLoc();
981 return Error(Loc, "unexpected token");
982 }
983
984 while (getLexer().is(AsmToken::Comma)) {
985 Parser.Lex(); // Eat the comma.
986 // Parse and remember the operand.
987 if (parseOperand(Operands, Mnemonic) != MatchOperand_Success) {
988 SMLoc Loc = getLexer().getLoc();
989 return Error(Loc, "unexpected token");
990 }
991 }
992 }
993 if (getLexer().isNot(AsmToken::EndOfStatement)) {
994 SMLoc Loc = getLexer().getLoc();
995 return Error(Loc, "unexpected token");
996 }
997 Parser.Lex(); // Consume the EndOfStatement.
998 return false;
999}
1000
1001bool VEAsmParser::ParseDirective(AsmToken DirectiveID) {
1002 std::string IDVal = DirectiveID.getIdentifier().lower();
1003
1004 // Defines VE specific directives. Reference is "Vector Engine Assembly
1005 // Language Reference Manual":
1006 // https://www.hpc.nec/documents/sdk/pdfs/VectorEngine-as-manual-v1.3.pdf
1007
1008 // The .word is 4 bytes long on VE.
1009 if (IDVal == ".word")
1010 return parseLiteralValues(4, DirectiveID.getLoc());
1011
1012 // The .long is 8 bytes long on VE.
1013 if (IDVal == ".long")
1014 return parseLiteralValues(8, DirectiveID.getLoc());
1015
1016 // The .llong is 8 bytes long on VE.
1017 if (IDVal == ".llong")
1018 return parseLiteralValues(8, DirectiveID.getLoc());
1019
1020 // Let the MC layer to handle other directives.
1021 return true;
1022}
1023
1024/// parseLiteralValues
1025/// ::= .word expression [, expression]*
1026/// ::= .long expression [, expression]*
1027/// ::= .llong expression [, expression]*
1028bool VEAsmParser::parseLiteralValues(unsigned Size, SMLoc L) {
1029 auto parseOne = [&]() -> bool {
1030 const MCExpr *Value;
1031 if (getParser().parseExpression(Value))
1032 return true;
1033 getParser().getStreamer().emitValue(Value, Size, L);
1034 return false;
1035 };
1036 return (parseMany(parseOne));
1037}
1038
1039/// Extract \code @lo32/@hi32/etc \endcode modifier from expression.
1040/// Recursively scan the expression and check for VK_VE_HI32/LO32/etc
1041/// symbol variants. If all symbols with modifier use the same
1042/// variant, return the corresponding VEMCExpr::VariantKind,
1043/// and a modified expression using the default symbol variant.
1044/// Otherwise, return NULL.
1045const MCExpr *
1046VEAsmParser::extractModifierFromExpr(const MCExpr *E,
1047 VEMCExpr::VariantKind &Variant) {
1048 MCContext &Context = getParser().getContext();
1050
1051 switch (E->getKind()) {
1052 case MCExpr::Target:
1053 case MCExpr::Constant:
1054 return nullptr;
1055
1056 case MCExpr::SymbolRef: {
1057 const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
1058
1059 switch (SRE->getKind()) {
1061 // Use VK_VE_REFLONG to a symbol without modifiers.
1063 break;
1066 break;
1069 break;
1072 break;
1075 break;
1078 break;
1081 break;
1084 break;
1087 break;
1090 break;
1093 break;
1096 break;
1099 break;
1102 break;
1105 break;
1106 default:
1107 return nullptr;
1108 }
1109
1110 return MCSymbolRefExpr::create(&SRE->getSymbol(), Context);
1111 }
1112
1113 case MCExpr::Unary: {
1114 const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
1115 const MCExpr *Sub = extractModifierFromExpr(UE->getSubExpr(), Variant);
1116 if (!Sub)
1117 return nullptr;
1118 return MCUnaryExpr::create(UE->getOpcode(), Sub, Context);
1119 }
1120
1121 case MCExpr::Binary: {
1122 const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
1123 VEMCExpr::VariantKind LHSVariant, RHSVariant;
1124 const MCExpr *LHS = extractModifierFromExpr(BE->getLHS(), LHSVariant);
1125 const MCExpr *RHS = extractModifierFromExpr(BE->getRHS(), RHSVariant);
1126
1127 if (!LHS && !RHS)
1128 return nullptr;
1129
1130 if (!LHS)
1131 LHS = BE->getLHS();
1132 if (!RHS)
1133 RHS = BE->getRHS();
1134
1135 if (LHSVariant == VEMCExpr::VK_VE_None)
1136 Variant = RHSVariant;
1137 else if (RHSVariant == VEMCExpr::VK_VE_None)
1138 Variant = LHSVariant;
1139 else if (LHSVariant == RHSVariant)
1140 Variant = LHSVariant;
1141 else
1142 return nullptr;
1143
1144 return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);
1145 }
1146 }
1147
1148 llvm_unreachable("Invalid expression kind!");
1149}
1150
1151const MCExpr *VEAsmParser::fixupVariantKind(const MCExpr *E) {
1152 MCContext &Context = getParser().getContext();
1153
1154 switch (E->getKind()) {
1155 case MCExpr::Target:
1156 case MCExpr::Constant:
1157 case MCExpr::SymbolRef:
1158 return E;
1159
1160 case MCExpr::Unary: {
1161 const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
1162 const MCExpr *Sub = fixupVariantKind(UE->getSubExpr());
1163 if (Sub == UE->getSubExpr())
1164 return E;
1165 return MCUnaryExpr::create(UE->getOpcode(), Sub, Context);
1166 }
1167
1168 case MCExpr::Binary: {
1169 const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
1170 const MCExpr *LHS = fixupVariantKind(BE->getLHS());
1171 const MCExpr *RHS = fixupVariantKind(BE->getRHS());
1172 if (LHS == BE->getLHS() && RHS == BE->getRHS())
1173 return E;
1174 return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);
1175 }
1176 }
1177
1178 llvm_unreachable("Invalid expression kind!");
1179}
1180
1181/// ParseExpression. This differs from the default "parseExpression" in that
1182/// it handles modifiers.
1183bool VEAsmParser::parseExpression(const MCExpr *&EVal) {
1184 // Handle \code symbol @lo32/@hi32/etc \endcode.
1185 if (getParser().parseExpression(EVal))
1186 return true;
1187
1188 // Convert MCSymbolRefExpr with VK_* to MCExpr with VK_*.
1189 EVal = fixupVariantKind(EVal);
1191 const MCExpr *E = extractModifierFromExpr(EVal, Variant);
1192 if (E)
1193 EVal = VEMCExpr::create(Variant, E, getParser().getContext());
1194
1195 return false;
1196}
1197
1198OperandMatchResultTy VEAsmParser::parseMEMOperand(OperandVector &Operands) {
1199 LLVM_DEBUG(dbgs() << "parseMEMOperand\n");
1200 const AsmToken &Tok = Parser.getTok();
1201 SMLoc S = Tok.getLoc();
1202 SMLoc E = Tok.getEndLoc();
1203 // Parse ASX format
1204 // disp
1205 // disp(, base)
1206 // disp(index)
1207 // disp(index, base)
1208 // (, base)
1209 // (index)
1210 // (index, base)
1211
1212 std::unique_ptr<VEOperand> Offset;
1213 switch (getLexer().getKind()) {
1214 default:
1215 return MatchOperand_NoMatch;
1216
1217 case AsmToken::Minus:
1218 case AsmToken::Integer:
1219 case AsmToken::Dot:
1220 case AsmToken::Identifier: {
1221 const MCExpr *EVal;
1222 if (!parseExpression(EVal))
1223 Offset = VEOperand::CreateImm(EVal, S, E);
1224 else
1225 return MatchOperand_NoMatch;
1226 break;
1227 }
1228
1229 case AsmToken::LParen:
1230 // empty disp (= 0)
1231 Offset =
1232 VEOperand::CreateImm(MCConstantExpr::create(0, getContext()), S, E);
1233 break;
1234 }
1235
1236 switch (getLexer().getKind()) {
1237 default:
1239
1241 Operands.push_back(VEOperand::MorphToMEMzii(
1242 MCConstantExpr::create(0, getContext()), std::move(Offset)));
1243 return MatchOperand_Success;
1244
1245 case AsmToken::LParen:
1246 Parser.Lex(); // Eat the (
1247 break;
1248 }
1249
1250 const MCExpr *IndexValue = nullptr;
1251 MCRegister IndexReg;
1252
1253 switch (getLexer().getKind()) {
1254 default:
1255 if (parseRegister(IndexReg, S, E))
1257 break;
1258
1259 case AsmToken::Minus:
1260 case AsmToken::Integer:
1261 case AsmToken::Dot:
1262 if (getParser().parseExpression(IndexValue, E))
1264 break;
1265
1266 case AsmToken::Comma:
1267 // empty index
1268 IndexValue = MCConstantExpr::create(0, getContext());
1269 break;
1270 }
1271
1272 switch (getLexer().getKind()) {
1273 default:
1275
1276 case AsmToken::RParen:
1277 Parser.Lex(); // Eat the )
1278 Operands.push_back(
1279 IndexValue ? VEOperand::MorphToMEMzii(IndexValue, std::move(Offset))
1280 : VEOperand::MorphToMEMzri(IndexReg, std::move(Offset)));
1281 return MatchOperand_Success;
1282
1283 case AsmToken::Comma:
1284 Parser.Lex(); // Eat the ,
1285 break;
1286 }
1287
1288 MCRegister BaseReg;
1289 if (parseRegister(BaseReg, S, E))
1291
1292 if (!Parser.getTok().is(AsmToken::RParen))
1294
1295 Parser.Lex(); // Eat the )
1296 Operands.push_back(
1297 IndexValue
1298 ? VEOperand::MorphToMEMrii(BaseReg, IndexValue, std::move(Offset))
1299 : VEOperand::MorphToMEMrri(BaseReg, IndexReg, std::move(Offset)));
1300
1301 return MatchOperand_Success;
1302}
1303
1304OperandMatchResultTy VEAsmParser::parseMEMAsOperand(OperandVector &Operands) {
1305 LLVM_DEBUG(dbgs() << "parseMEMAsOperand\n");
1306 const AsmToken &Tok = Parser.getTok();
1307 SMLoc S = Tok.getLoc();
1308 SMLoc E = Tok.getEndLoc();
1309 // Parse AS format
1310 // disp
1311 // disp(, base)
1312 // disp(base)
1313 // disp()
1314 // (, base)
1315 // (base)
1316 // base
1317
1318 MCRegister BaseReg;
1319 std::unique_ptr<VEOperand> Offset;
1320 switch (getLexer().getKind()) {
1321 default:
1322 return MatchOperand_NoMatch;
1323
1324 case AsmToken::Minus:
1325 case AsmToken::Integer:
1326 case AsmToken::Dot:
1327 case AsmToken::Identifier: {
1328 const MCExpr *EVal;
1329 if (!parseExpression(EVal))
1330 Offset = VEOperand::CreateImm(EVal, S, E);
1331 else
1332 return MatchOperand_NoMatch;
1333 break;
1334 }
1335
1336 case AsmToken::Percent:
1337 if (parseRegister(BaseReg, S, E))
1338 return MatchOperand_NoMatch;
1339 Offset =
1340 VEOperand::CreateImm(MCConstantExpr::create(0, getContext()), S, E);
1341 break;
1342
1343 case AsmToken::LParen:
1344 // empty disp (= 0)
1345 Offset =
1346 VEOperand::CreateImm(MCConstantExpr::create(0, getContext()), S, E);
1347 break;
1348 }
1349
1350 switch (getLexer().getKind()) {
1351 default:
1353
1355 case AsmToken::Comma:
1356 Operands.push_back(BaseReg != VE::NoRegister
1357 ? VEOperand::MorphToMEMri(BaseReg, std::move(Offset))
1358 : VEOperand::MorphToMEMzi(std::move(Offset)));
1359 return MatchOperand_Success;
1360
1361 case AsmToken::LParen:
1362 if (BaseReg != VE::NoRegister)
1364 Parser.Lex(); // Eat the (
1365 break;
1366 }
1367
1368 switch (getLexer().getKind()) {
1369 default:
1370 if (parseRegister(BaseReg, S, E))
1372 break;
1373
1374 case AsmToken::Comma:
1375 Parser.Lex(); // Eat the ,
1376 if (parseRegister(BaseReg, S, E))
1378 break;
1379
1380 case AsmToken::RParen:
1381 break;
1382 }
1383
1384 if (!Parser.getTok().is(AsmToken::RParen))
1386
1387 Parser.Lex(); // Eat the )
1388 Operands.push_back(BaseReg != VE::NoRegister
1389 ? VEOperand::MorphToMEMri(BaseReg, std::move(Offset))
1390 : VEOperand::MorphToMEMzi(std::move(Offset)));
1391
1392 return MatchOperand_Success;
1393}
1394
1395OperandMatchResultTy VEAsmParser::parseMImmOperand(OperandVector &Operands) {
1396 LLVM_DEBUG(dbgs() << "parseMImmOperand\n");
1397
1398 // Parsing "(" + number + ")0/1"
1399 const AsmToken Tok1 = Parser.getTok();
1400 if (!Tok1.is(AsmToken::LParen))
1401 return MatchOperand_NoMatch;
1402
1403 Parser.Lex(); // Eat the '('.
1404
1405 const AsmToken Tok2 = Parser.getTok();
1406 SMLoc E;
1407 const MCExpr *EVal;
1408 if (!Tok2.is(AsmToken::Integer) || getParser().parseExpression(EVal, E)) {
1409 getLexer().UnLex(Tok1);
1410 return MatchOperand_NoMatch;
1411 }
1412
1413 const AsmToken Tok3 = Parser.getTok();
1414 if (!Tok3.is(AsmToken::RParen)) {
1415 getLexer().UnLex(Tok2);
1416 getLexer().UnLex(Tok1);
1417 return MatchOperand_NoMatch;
1418 }
1419 Parser.Lex(); // Eat the ')'.
1420
1421 const AsmToken &Tok4 = Parser.getTok();
1422 StringRef Suffix = Tok4.getString();
1423 if (Suffix != "1" && Suffix != "0") {
1424 getLexer().UnLex(Tok3);
1425 getLexer().UnLex(Tok2);
1426 getLexer().UnLex(Tok1);
1427 return MatchOperand_NoMatch;
1428 }
1429 Parser.Lex(); // Eat the value.
1430 SMLoc EndLoc = SMLoc::getFromPointer(Suffix.end());
1431 Operands.push_back(
1432 VEOperand::CreateMImm(EVal, Suffix == "0", Tok1.getLoc(), EndLoc));
1433 return MatchOperand_Success;
1434}
1435
1436OperandMatchResultTy VEAsmParser::parseOperand(OperandVector &Operands,
1437 StringRef Mnemonic) {
1438 LLVM_DEBUG(dbgs() << "parseOperand\n");
1439 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1440
1441 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1442 // there was a match, but an error occurred, in which case, just return that
1443 // the operand parsing failed.
1444 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
1445 return ResTy;
1446
1447 switch (getLexer().getKind()) {
1448 case AsmToken::LParen: {
1449 // Parsing "(" + %vreg + ", " + %vreg + ")"
1450 const AsmToken Tok1 = Parser.getTok();
1451 Parser.Lex(); // Eat the '('.
1452
1453 MCRegister RegNo1;
1454 SMLoc S1, E1;
1455 if (tryParseRegister(RegNo1, S1, E1) != MatchOperand_Success) {
1456 getLexer().UnLex(Tok1);
1457 return MatchOperand_NoMatch;
1458 }
1459
1460 if (!Parser.getTok().is(AsmToken::Comma))
1462 Parser.Lex(); // Eat the ','.
1463
1464 MCRegister RegNo2;
1465 SMLoc S2, E2;
1466 if (tryParseRegister(RegNo2, S2, E2) != MatchOperand_Success)
1468
1469 if (!Parser.getTok().is(AsmToken::RParen))
1471
1472 Operands.push_back(VEOperand::CreateToken(Tok1.getString(), Tok1.getLoc()));
1473 Operands.push_back(VEOperand::CreateReg(RegNo1, S1, E1));
1474 Operands.push_back(VEOperand::CreateReg(RegNo2, S2, E2));
1475 Operands.push_back(VEOperand::CreateToken(Parser.getTok().getString(),
1476 Parser.getTok().getLoc()));
1477 Parser.Lex(); // Eat the ')'.
1478 break;
1479 }
1480 default: {
1481 std::unique_ptr<VEOperand> Op;
1482 ResTy = parseVEAsmOperand(Op);
1483 if (ResTy != MatchOperand_Success || !Op)
1485
1486 // Push the parsed operand into the list of operands
1487 Operands.push_back(std::move(Op));
1488
1489 if (!Parser.getTok().is(AsmToken::LParen))
1490 break;
1491
1492 // Parsing %vec-reg + "(" + %sclar-reg/number + ")"
1493 std::unique_ptr<VEOperand> Op1 = VEOperand::CreateToken(
1494 Parser.getTok().getString(), Parser.getTok().getLoc());
1495 Parser.Lex(); // Eat the '('.
1496
1497 std::unique_ptr<VEOperand> Op2;
1498 ResTy = parseVEAsmOperand(Op2);
1499 if (ResTy != MatchOperand_Success || !Op2)
1501
1502 if (!Parser.getTok().is(AsmToken::RParen))
1504
1505 Operands.push_back(std::move(Op1));
1506 Operands.push_back(std::move(Op2));
1507 Operands.push_back(VEOperand::CreateToken(Parser.getTok().getString(),
1508 Parser.getTok().getLoc()));
1509 Parser.Lex(); // Eat the ')'.
1510 break;
1511 }
1512 }
1513
1514 return MatchOperand_Success;
1515}
1516
1518VEAsmParser::parseVEAsmOperand(std::unique_ptr<VEOperand> &Op) {
1519 LLVM_DEBUG(dbgs() << "parseVEAsmOperand\n");
1520 SMLoc S = Parser.getTok().getLoc();
1522 const MCExpr *EVal;
1523
1524 Op = nullptr;
1525 switch (getLexer().getKind()) {
1526 default:
1527 break;
1528
1529 case AsmToken::Percent: {
1530 MCRegister RegNo;
1531 if (tryParseRegister(RegNo, S, E) == MatchOperand_Success)
1532 Op = VEOperand::CreateReg(RegNo, S, E);
1533 break;
1534 }
1535 case AsmToken::Minus:
1536 case AsmToken::Integer:
1537 case AsmToken::Dot:
1539 if (!parseExpression(EVal))
1540 Op = VEOperand::CreateImm(EVal, S, E);
1541 break;
1542 }
1544}
1545
1546// Force static initialization.
1549}
1550
1551#define GET_REGISTER_MATCHER
1552#define GET_MATCHER_IMPLEMENTATION
1553#include "VEGenAsmMatcher.inc"
1554
1555unsigned VEAsmParser::validateTargetOperandClass(MCParsedAsmOperand &GOp,
1556 unsigned Kind) {
1557 VEOperand &Op = (VEOperand &)GOp;
1558
1559 // VE uses identical register name for all registers like both
1560 // F32 and I32 uses "%s23". Need to convert the name of them
1561 // for validation.
1562 switch (Kind) {
1563 default:
1564 break;
1565 case MCK_F32:
1566 if (Op.isReg() && VEOperand::MorphToF32Reg(Op))
1568 break;
1569 case MCK_I32:
1570 if (Op.isReg() && VEOperand::MorphToI32Reg(Op))
1572 break;
1573 case MCK_F128:
1574 if (Op.isReg() && VEOperand::MorphToF128Reg(Op))
1576 break;
1577 case MCK_VM512:
1578 if (Op.isReg() && VEOperand::MorphToVM512Reg(Op))
1580 break;
1581 case MCK_MISC:
1582 if (Op.isImm() && VEOperand::MorphToMISCReg(Op))
1584 break;
1585 }
1586 return Match_InvalidOperand;
1587}
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
basic Basic Alias true
SmallVector< MachineOperand, 4 > Cond
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:127
#define LLVM_DEBUG(X)
Definition: Debug.h:101
constexpr char SuffixEnd
Definition: ELFEmitter.cpp:686
std::string Name
uint64_t Size
static LVOptions Options
Definition: LVOptions.cpp:25
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
Definition: Lint.cpp:522
mir Rename Register Operands
unsigned Reg
LLVMContext & Context
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
This file defines the SmallVector class.
static const MCPhysReg MISCRegs[31]
static const MCPhysReg F128Regs[32]
static const MCPhysReg F32Regs[64]
static unsigned MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
static void applyMnemonicAliases(StringRef &Mnemonic, const FeatureBitset &Features, unsigned VariantID)
static StringRef parseCC(StringRef Name, unsigned Prefix, unsigned Suffix, bool IntegerCC, bool OmitCC, SMLoc NameLoc, OperandVector *Operands)
static const MCPhysReg VM512Regs[8]
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmParser()
static unsigned MatchRegisterName(StringRef Name)
Maps from the set of all register names to a register number.
static const MCPhysReg I32Regs[64]
static StringRef parseRD(StringRef Name, unsigned Prefix, SMLoc NameLoc, OperandVector *Operands)
static bool isMImm(SDValue V)
Value * RHS
Value * LHS
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:26
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmMacro.h:110
bool is(TokenKind K) const
Definition: MCAsmMacro.h:82
SMLoc getEndLoc() const
Definition: MCAsmLexer.cpp:30
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition: MCAsmMacro.h:99
Base class for user error types.
Definition: Error.h:348
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
Container class for subtarget features.
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:123
const AsmToken & getTok() const
Get the current AsmToken from the stream.
Definition: MCAsmParser.cpp:40
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
Binary assembler expressions.
Definition: MCExpr.h:481
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
Definition: MCExpr.h:628
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Definition: MCExpr.h:631
Opcode getOpcode() const
Get the kind of this binary expression.
Definition: MCExpr.h:625
static const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:183
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:76
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
@ Unary
Unary expressions.
Definition: MCExpr.h:41
@ Constant
Constant expressions.
Definition: MCExpr.h:39
@ SymbolRef
References to labels and assigned expressions.
Definition: MCExpr.h:40
@ Target
Target specific expression.
Definition: MCExpr.h:42
@ Binary
Binary expressions.
Definition: MCExpr.h:38
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
void setLoc(SMLoc loc)
Definition: MCInst.h:203
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:162
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
virtual unsigned getReg() const =0
virtual SMLoc getStartLoc() const =0
getStartLoc - Get the location of the first token of this operand.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool isMem() const =0
isMem - Is this a memory operand?
virtual void print(raw_ostream &OS) const =0
print - Print a debug representation of the operand to the given stream.
virtual bool isToken() const =0
isToken - Is this a token operand?
virtual bool isImm() const =0
isImm - Is this an immediate operand?
virtual SMLoc getEndLoc() const =0
getEndLoc - Get the location of the last token of this operand.
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:24
Streaming machine code generation interface.
Definition: MCStreamer.h:212
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
const MCSymbol & getSymbol() const
Definition: MCExpr.h:399
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:386
VariantKind getKind() const
Definition: MCExpr.h:401
MCTargetAsmParser - Generic interface to target specific assembly parsers.
virtual bool ParseDirective(AsmToken DirectiveID)=0
ParseDirective - Parse a target specific assembler directive.
virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
void setAvailableFeatures(const FeatureBitset &Value)
const MCSubtargetInfo & getSTI() const
virtual unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind)
Allow a target to add special case operand matching for things that tblgen doesn't/can't handle effec...
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands)=0
ParseInstruction - Parse one assembly instruction.
virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm)=0
MatchAndEmitInstruction - Recognize a series of operands of a parsed instruction as an actual MCInst ...
virtual OperandMatchResultTy tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
tryParseRegister - parse one register if possible
Unary assembler expressions.
Definition: MCExpr.h:425
Opcode getOpcode() const
Get the kind of this unary expression.
Definition: MCExpr.h:468
static const MCUnaryExpr * create(Opcode Op, const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:189
const MCExpr * getSubExpr() const
Get the child of this unary expression.
Definition: MCExpr.h:471
Represents a location in source code.
Definition: SMLoc.h:23
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:36
const char * getPointer() const
Definition: SMLoc.h:34
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
iterator end() const
Definition: StringRef.h:113
std::string lower() const
Definition: StringRef.cpp:111
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
static const VEMCExpr * create(VariantKind Kind, const MCExpr *Expr, MCContext &Ctx)
Definition: VEMCExpr.cpp:27
@ VK_VE_TLS_GD_HI32
Definition: VEMCExpr.h:38
@ VK_VE_TPOFF_HI32
Definition: VEMCExpr.h:40
@ VK_VE_TPOFF_LO32
Definition: VEMCExpr.h:41
@ VK_VE_TLS_GD_LO32
Definition: VEMCExpr.h:39
@ VK_VE_GOTOFF_HI32
Definition: VEMCExpr.h:34
@ VK_VE_GOTOFF_LO32
Definition: VEMCExpr.h:35
LLVM Value Representation.
Definition: Value.h:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:148
CondCode
Definition: VE.h:44
@ CC_AF
Definition: VE.h:54
@ UNKNOWN
Definition: VE.h:70
@ CC_AT
Definition: VE.h:69
RoundingMode
Definition: VE.h:76
@ UNKNOWN
Definition: VE.h:83
@ CE
Windows NT (Windows on ARM)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:440
@ Length
Definition: DWP.cpp:440
@ MatchOperand_NoMatch
@ MatchOperand_ParseFail
@ MatchOperand_Success
Target & getTheVETarget()
static VECC::CondCode stringToVEFCondCode(StringRef S)
Definition: VE.h:130
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
RoundingMode
Rounding mode.
static VERD::RoundingMode stringToVERD(StringRef S)
Definition: VE.h:359
static VECC::CondCode stringToVEICondCode(StringRef S)
Definition: VE.h:116
#define N
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...