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