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