1//===-- SparcAsmParser.cpp - Parse Sparc 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/SparcMCExpr.h"
10#include "MCTargetDesc/SparcMCTargetDesc.h"
11#include "TargetInfo/SparcTargetInfo.h"
12#include "llvm/ADT/STLExtras.h"
13#include "llvm/ADT/SmallVector.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/MC/MCAsmMacro.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
19#include "llvm/MC/MCInstBuilder.h"
20#include "llvm/MC/MCInstrInfo.h"
21#include "llvm/MC/MCObjectFileInfo.h"
22#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCAsmParser.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
25#include "llvm/MC/MCParser/MCTargetAsmParser.h"
26#include "llvm/MC/MCRegisterInfo.h"
27#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCSubtargetInfo.h"
29#include "llvm/MC/MCSymbol.h"
30#include "llvm/MC/TargetRegistry.h"
31#include "llvm/Support/Casting.h"
32#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Support/MathExtras.h"
34#include "llvm/Support/SMLoc.h"
35#include "llvm/Support/raw_ostream.h"
36#include "llvm/TargetParser/Triple.h"
37#include <algorithm>
38#include <cassert>
39#include <cstdint>
40#include <memory>
41
42using namespace llvm;
43
44// The generated AsmMatcher SparcGenAsmMatcher uses "Sparc" as the target
45// namespace. But SPARC backend uses "SP" as its namespace.
46namespace llvm {
47namespace Sparc {
48
49 using namespace SP;
50
51} // end namespace Sparc
52} // end namespace llvm
53
54namespace {
55
56class SparcOperand;
57
58class SparcAsmParser : public MCTargetAsmParser {
59 MCAsmParser &Parser;
60 const MCRegisterInfo &MRI;
61
62 enum class TailRelocKind { Load_GOT, Add_TLS, Load_TLS, Call_TLS };
63
64 /// @name Auto-generated Match Functions
65 /// {
66
67#define GET_ASSEMBLER_HEADER
68#include "SparcGenAsmMatcher.inc"
69
70 /// }
71
72 // public interface of the MCTargetAsmParser.
73 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
74 OperandVector &Operands, MCStreamer &Out,
75 uint64_t &ErrorInfo,
76 bool MatchingInlineAsm) override;
77 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
78 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
79 SMLoc &EndLoc) override;
80 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
81 SMLoc NameLoc, OperandVector &Operands) override;
82 ParseStatus parseDirective(AsmToken DirectiveID) override;
83
84 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
85 unsigned Kind) override;
86
87 // Custom parse functions for Sparc specific operands.
88 ParseStatus parseMEMOperand(OperandVector &Operands);
89
90 ParseStatus parseMembarTag(OperandVector &Operands);
91
92 ParseStatus parseASITag(OperandVector &Operands);
93
94 ParseStatus parsePrefetchTag(OperandVector &Operands);
95
96 template <TailRelocKind Kind>
97 ParseStatus parseTailRelocSym(OperandVector &Operands);
98
99 template <unsigned N> ParseStatus parseShiftAmtImm(OperandVector &Operands);
100
101 ParseStatus parseCallTarget(OperandVector &Operands);
102
103 ParseStatus parseOperand(OperandVector &Operands, StringRef Name);
104
105 ParseStatus parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Operand,
106 bool isCall = false);
107
108 ParseStatus parseBranchModifiers(OperandVector &Operands);
109
110 ParseStatus parseExpression(int64_t &Val);
111
112 // Helper function for dealing with %lo / %hi in PIC mode.
113 const SparcMCExpr *adjustPICRelocation(SparcMCExpr::VariantKind VK,
114 const MCExpr *subExpr);
115
116 // Helper function to see if current token can start an expression.
117 bool isPossibleExpression(const AsmToken &Token);
118
119 // Check if mnemonic is valid.
120 MatchResultTy mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
121
122 // returns true if Tok is matched to a register and returns register in RegNo.
123 MCRegister matchRegisterName(const AsmToken &Tok, unsigned &RegKind);
124
125 bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc);
126
127 bool is64Bit() const {
128 return getSTI().getTargetTriple().getArch() == Triple::sparcv9;
129 }
130
131 bool expandSET(MCInst &Inst, SMLoc IDLoc,
132 SmallVectorImpl<MCInst> &Instructions);
133
134 bool expandSETX(MCInst &Inst, SMLoc IDLoc,
135 SmallVectorImpl<MCInst> &Instructions);
136
137 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
138
139public:
140 SparcAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
141 const MCInstrInfo &MII, const MCTargetOptions &Options)
142 : MCTargetAsmParser(Options, sti, MII), Parser(parser),
143 MRI(*Parser.getContext().getRegisterInfo()) {
144 Parser.addAliasForDirective(Directive: ".half", Alias: ".2byte");
145 Parser.addAliasForDirective(Directive: ".uahalf", Alias: ".2byte");
146 Parser.addAliasForDirective(Directive: ".word", Alias: ".4byte");
147 Parser.addAliasForDirective(Directive: ".uaword", Alias: ".4byte");
148 Parser.addAliasForDirective(Directive: ".nword", Alias: is64Bit() ? ".8byte" : ".4byte");
149 if (is64Bit())
150 Parser.addAliasForDirective(Directive: ".xword", Alias: ".8byte");
151
152 // Initialize the set of available features.
153 setAvailableFeatures(ComputeAvailableFeatures(FB: getSTI().getFeatureBits()));
154 }
155};
156
157} // end anonymous namespace
158
159 static const MCPhysReg IntRegs[32] = {
160 Sparc::G0, Sparc::G1, Sparc::G2, Sparc::G3,
161 Sparc::G4, Sparc::G5, Sparc::G6, Sparc::G7,
162 Sparc::O0, Sparc::O1, Sparc::O2, Sparc::O3,
163 Sparc::O4, Sparc::O5, Sparc::O6, Sparc::O7,
164 Sparc::L0, Sparc::L1, Sparc::L2, Sparc::L3,
165 Sparc::L4, Sparc::L5, Sparc::L6, Sparc::L7,
166 Sparc::I0, Sparc::I1, Sparc::I2, Sparc::I3,
167 Sparc::I4, Sparc::I5, Sparc::I6, Sparc::I7 };
168
169 static const MCPhysReg DoubleRegs[32] = {
170 Sparc::D0, Sparc::D1, Sparc::D2, Sparc::D3,
171 Sparc::D4, Sparc::D5, Sparc::D6, Sparc::D7,
172 Sparc::D8, Sparc::D9, Sparc::D10, Sparc::D11,
173 Sparc::D12, Sparc::D13, Sparc::D14, Sparc::D15,
174 Sparc::D16, Sparc::D17, Sparc::D18, Sparc::D19,
175 Sparc::D20, Sparc::D21, Sparc::D22, Sparc::D23,
176 Sparc::D24, Sparc::D25, Sparc::D26, Sparc::D27,
177 Sparc::D28, Sparc::D29, Sparc::D30, Sparc::D31 };
178
179 static const MCPhysReg QuadFPRegs[32] = {
180 Sparc::Q0, Sparc::Q1, Sparc::Q2, Sparc::Q3,
181 Sparc::Q4, Sparc::Q5, Sparc::Q6, Sparc::Q7,
182 Sparc::Q8, Sparc::Q9, Sparc::Q10, Sparc::Q11,
183 Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 };
184
185 static const MCPhysReg IntPairRegs[] = {
186 Sparc::G0_G1, Sparc::G2_G3, Sparc::G4_G5, Sparc::G6_G7,
187 Sparc::O0_O1, Sparc::O2_O3, Sparc::O4_O5, Sparc::O6_O7,
188 Sparc::L0_L1, Sparc::L2_L3, Sparc::L4_L5, Sparc::L6_L7,
189 Sparc::I0_I1, Sparc::I2_I3, Sparc::I4_I5, Sparc::I6_I7};
190
191 static const MCPhysReg CoprocPairRegs[] = {
192 Sparc::C0_C1, Sparc::C2_C3, Sparc::C4_C5, Sparc::C6_C7,
193 Sparc::C8_C9, Sparc::C10_C11, Sparc::C12_C13, Sparc::C14_C15,
194 Sparc::C16_C17, Sparc::C18_C19, Sparc::C20_C21, Sparc::C22_C23,
195 Sparc::C24_C25, Sparc::C26_C27, Sparc::C28_C29, Sparc::C30_C31};
196
197namespace {
198
199/// SparcOperand - Instances of this class represent a parsed Sparc machine
200/// instruction.
201class SparcOperand : public MCParsedAsmOperand {
202public:
203 enum RegisterKind {
204 rk_None,
205 rk_IntReg,
206 rk_IntPairReg,
207 rk_FloatReg,
208 rk_DoubleReg,
209 rk_QuadReg,
210 rk_CoprocReg,
211 rk_CoprocPairReg,
212 rk_Special,
213 };
214
215private:
216 enum KindTy {
217 k_Token,
218 k_Register,
219 k_Immediate,
220 k_MemoryReg,
221 k_MemoryImm,
222 k_ASITag,
223 k_PrefetchTag,
224 } Kind;
225
226 SMLoc StartLoc, EndLoc;
227
228 struct Token {
229 const char *Data;
230 unsigned Length;
231 };
232
233 struct RegOp {
234 unsigned RegNum;
235 RegisterKind Kind;
236 };
237
238 struct ImmOp {
239 const MCExpr *Val;
240 };
241
242 struct MemOp {
243 unsigned Base;
244 unsigned OffsetReg;
245 const MCExpr *Off;
246 };
247
248 union {
249 struct Token Tok;
250 struct RegOp Reg;
251 struct ImmOp Imm;
252 struct MemOp Mem;
253 unsigned ASI;
254 unsigned Prefetch;
255 };
256
257public:
258 SparcOperand(KindTy K) : Kind(K) {}
259
260 bool isToken() const override { return Kind == k_Token; }
261 bool isReg() const override { return Kind == k_Register; }
262 bool isImm() const override { return Kind == k_Immediate; }
263 bool isMem() const override { return isMEMrr() || isMEMri(); }
264 bool isMEMrr() const { return Kind == k_MemoryReg; }
265 bool isMEMri() const { return Kind == k_MemoryImm; }
266 bool isMembarTag() const { return Kind == k_Immediate; }
267 bool isASITag() const { return Kind == k_ASITag; }
268 bool isPrefetchTag() const { return Kind == k_PrefetchTag; }
269 bool isTailRelocSym() const { return Kind == k_Immediate; }
270
271 bool isCallTarget() const {
272 if (!isImm())
273 return false;
274
275 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Imm.Val))
276 return CE->getValue() % 4 == 0;
277
278 return true;
279 }
280
281 bool isShiftAmtImm5() const {
282 if (!isImm())
283 return false;
284
285 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Imm.Val))
286 return isUInt<5>(x: CE->getValue());
287
288 return false;
289 }
290
291 bool isShiftAmtImm6() const {
292 if (!isImm())
293 return false;
294
295 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Imm.Val))
296 return isUInt<6>(x: CE->getValue());
297
298 return false;
299 }
300
301 bool isIntReg() const {
302 return (Kind == k_Register && Reg.Kind == rk_IntReg);
303 }
304
305 bool isFloatReg() const {
306 return (Kind == k_Register && Reg.Kind == rk_FloatReg);
307 }
308
309 bool isFloatOrDoubleReg() const {
310 return (Kind == k_Register && (Reg.Kind == rk_FloatReg
311 || Reg.Kind == rk_DoubleReg));
312 }
313
314 bool isCoprocReg() const {
315 return (Kind == k_Register && Reg.Kind == rk_CoprocReg);
316 }
317
318 StringRef getToken() const {
319 assert(Kind == k_Token && "Invalid access!");
320 return StringRef(Tok.Data, Tok.Length);
321 }
322
323 MCRegister getReg() const override {
324 assert((Kind == k_Register) && "Invalid access!");
325 return Reg.RegNum;
326 }
327
328 const MCExpr *getImm() const {
329 assert((Kind == k_Immediate) && "Invalid access!");
330 return Imm.Val;
331 }
332
333 unsigned getMemBase() const {
334 assert((Kind == k_MemoryReg || Kind == k_MemoryImm) && "Invalid access!");
335 return Mem.Base;
336 }
337
338 unsigned getMemOffsetReg() const {
339 assert((Kind == k_MemoryReg) && "Invalid access!");
340 return Mem.OffsetReg;
341 }
342
343 const MCExpr *getMemOff() const {
344 assert((Kind == k_MemoryImm) && "Invalid access!");
345 return Mem.Off;
346 }
347
348 unsigned getASITag() const {
349 assert((Kind == k_ASITag) && "Invalid access!");
350 return ASI;
351 }
352
353 unsigned getPrefetchTag() const {
354 assert((Kind == k_PrefetchTag) && "Invalid access!");
355 return Prefetch;
356 }
357
358 /// getStartLoc - Get the location of the first token of this operand.
359 SMLoc getStartLoc() const override {
360 return StartLoc;
361 }
362 /// getEndLoc - Get the location of the last token of this operand.
363 SMLoc getEndLoc() const override {
364 return EndLoc;
365 }
366
367 void print(raw_ostream &OS) const override {
368 switch (Kind) {
369 case k_Token: OS << "Token: " << getToken() << "\n"; break;
370 case k_Register: OS << "Reg: #" << getReg() << "\n"; break;
371 case k_Immediate: OS << "Imm: " << getImm() << "\n"; break;
372 case k_MemoryReg: OS << "Mem: " << getMemBase() << "+"
373 << getMemOffsetReg() << "\n"; break;
374 case k_MemoryImm: assert(getMemOff() != nullptr);
375 OS << "Mem: " << getMemBase()
376 << "+" << *getMemOff()
377 << "\n"; break;
378 case k_ASITag:
379 OS << "ASI tag: " << getASITag() << "\n";
380 break;
381 case k_PrefetchTag:
382 OS << "Prefetch tag: " << getPrefetchTag() << "\n";
383 break;
384 }
385 }
386
387 void addRegOperands(MCInst &Inst, unsigned N) const {
388 assert(N == 1 && "Invalid number of operands!");
389 Inst.addOperand(Op: MCOperand::createReg(Reg: getReg()));
390 }
391
392 void addImmOperands(MCInst &Inst, unsigned N) const {
393 assert(N == 1 && "Invalid number of operands!");
394 const MCExpr *Expr = getImm();
395 addExpr(Inst, Expr);
396 }
397
398 void addShiftAmtImm5Operands(MCInst &Inst, unsigned N) const {
399 assert(N == 1 && "Invalid number of operands!");
400 addExpr(Inst, Expr: getImm());
401 }
402 void addShiftAmtImm6Operands(MCInst &Inst, unsigned N) const {
403 assert(N == 1 && "Invalid number of operands!");
404 addExpr(Inst, Expr: getImm());
405 }
406
407 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
408 // Add as immediate when possible. Null MCExpr = 0.
409 if (!Expr)
410 Inst.addOperand(Op: MCOperand::createImm(Val: 0));
411 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Expr))
412 Inst.addOperand(Op: MCOperand::createImm(Val: CE->getValue()));
413 else
414 Inst.addOperand(Op: MCOperand::createExpr(Val: Expr));
415 }
416
417 void addMEMrrOperands(MCInst &Inst, unsigned N) const {
418 assert(N == 2 && "Invalid number of operands!");
419
420 Inst.addOperand(Op: MCOperand::createReg(Reg: getMemBase()));
421
422 assert(getMemOffsetReg() != 0 && "Invalid offset");
423 Inst.addOperand(Op: MCOperand::createReg(Reg: getMemOffsetReg()));
424 }
425
426 void addMEMriOperands(MCInst &Inst, unsigned N) const {
427 assert(N == 2 && "Invalid number of operands!");
428
429 Inst.addOperand(Op: MCOperand::createReg(Reg: getMemBase()));
430
431 const MCExpr *Expr = getMemOff();
432 addExpr(Inst, Expr);
433 }
434
435 void addASITagOperands(MCInst &Inst, unsigned N) const {
436 assert(N == 1 && "Invalid number of operands!");
437 Inst.addOperand(Op: MCOperand::createImm(Val: getASITag()));
438 }
439
440 void addPrefetchTagOperands(MCInst &Inst, unsigned N) const {
441 assert(N == 1 && "Invalid number of operands!");
442 Inst.addOperand(Op: MCOperand::createImm(Val: getPrefetchTag()));
443 }
444
445 void addMembarTagOperands(MCInst &Inst, unsigned N) const {
446 assert(N == 1 && "Invalid number of operands!");
447 const MCExpr *Expr = getImm();
448 addExpr(Inst, Expr);
449 }
450
451 void addCallTargetOperands(MCInst &Inst, unsigned N) const {
452 assert(N == 1 && "Invalid number of operands!");
453 addExpr(Inst, Expr: getImm());
454 }
455
456 void addTailRelocSymOperands(MCInst &Inst, unsigned N) const {
457 assert(N == 1 && "Invalid number of operands!");
458 addExpr(Inst, Expr: getImm());
459 }
460
461 static std::unique_ptr<SparcOperand> CreateToken(StringRef Str, SMLoc S) {
462 auto Op = std::make_unique<SparcOperand>(args: k_Token);
463 Op->Tok.Data = Str.data();
464 Op->Tok.Length = Str.size();
465 Op->StartLoc = S;
466 Op->EndLoc = S;
467 return Op;
468 }
469
470 static std::unique_ptr<SparcOperand> CreateReg(unsigned RegNum, unsigned Kind,
471 SMLoc S, SMLoc E) {
472 auto Op = std::make_unique<SparcOperand>(args: k_Register);
473 Op->Reg.RegNum = RegNum;
474 Op->Reg.Kind = (SparcOperand::RegisterKind)Kind;
475 Op->StartLoc = S;
476 Op->EndLoc = E;
477 return Op;
478 }
479
480 static std::unique_ptr<SparcOperand> CreateImm(const MCExpr *Val, SMLoc S,
481 SMLoc E) {
482 auto Op = std::make_unique<SparcOperand>(args: k_Immediate);
483 Op->Imm.Val = Val;
484 Op->StartLoc = S;
485 Op->EndLoc = E;
486 return Op;
487 }
488
489 static std::unique_ptr<SparcOperand> CreateASITag(unsigned Val, SMLoc S,
490 SMLoc E) {
491 auto Op = std::make_unique<SparcOperand>(args: k_ASITag);
492 Op->ASI = Val;
493 Op->StartLoc = S;
494 Op->EndLoc = E;
495 return Op;
496 }
497
498 static std::unique_ptr<SparcOperand> CreatePrefetchTag(unsigned Val, SMLoc S,
499 SMLoc E) {
500 auto Op = std::make_unique<SparcOperand>(args: k_PrefetchTag);
501 Op->Prefetch = Val;
502 Op->StartLoc = S;
503 Op->EndLoc = E;
504 return Op;
505 }
506
507 static bool MorphToIntPairReg(SparcOperand &Op) {
508 unsigned Reg = Op.getReg();
509 assert(Op.Reg.Kind == rk_IntReg);
510 unsigned regIdx = 32;
511 if (Reg >= Sparc::G0 && Reg <= Sparc::G7)
512 regIdx = Reg - Sparc::G0;
513 else if (Reg >= Sparc::O0 && Reg <= Sparc::O7)
514 regIdx = Reg - Sparc::O0 + 8;
515 else if (Reg >= Sparc::L0 && Reg <= Sparc::L7)
516 regIdx = Reg - Sparc::L0 + 16;
517 else if (Reg >= Sparc::I0 && Reg <= Sparc::I7)
518 regIdx = Reg - Sparc::I0 + 24;
519 if (regIdx % 2 || regIdx > 31)
520 return false;
521 Op.Reg.RegNum = IntPairRegs[regIdx / 2];
522 Op.Reg.Kind = rk_IntPairReg;
523 return true;
524 }
525
526 static bool MorphToDoubleReg(SparcOperand &Op) {
527 unsigned Reg = Op.getReg();
528 assert(Op.Reg.Kind == rk_FloatReg);
529 unsigned regIdx = Reg - Sparc::F0;
530 if (regIdx % 2 || regIdx > 31)
531 return false;
532 Op.Reg.RegNum = DoubleRegs[regIdx / 2];
533 Op.Reg.Kind = rk_DoubleReg;
534 return true;
535 }
536
537 static bool MorphToQuadReg(SparcOperand &Op) {
538 unsigned Reg = Op.getReg();
539 unsigned regIdx = 0;
540 switch (Op.Reg.Kind) {
541 default: llvm_unreachable("Unexpected register kind!");
542 case rk_FloatReg:
543 regIdx = Reg - Sparc::F0;
544 if (regIdx % 4 || regIdx > 31)
545 return false;
546 Reg = QuadFPRegs[regIdx / 4];
547 break;
548 case rk_DoubleReg:
549 regIdx = Reg - Sparc::D0;
550 if (regIdx % 2 || regIdx > 31)
551 return false;
552 Reg = QuadFPRegs[regIdx / 2];
553 break;
554 }
555 Op.Reg.RegNum = Reg;
556 Op.Reg.Kind = rk_QuadReg;
557 return true;
558 }
559
560 static bool MorphToCoprocPairReg(SparcOperand &Op) {
561 unsigned Reg = Op.getReg();
562 assert(Op.Reg.Kind == rk_CoprocReg);
563 unsigned regIdx = 32;
564 if (Reg >= Sparc::C0 && Reg <= Sparc::C31)
565 regIdx = Reg - Sparc::C0;
566 if (regIdx % 2 || regIdx > 31)
567 return false;
568 Op.Reg.RegNum = CoprocPairRegs[regIdx / 2];
569 Op.Reg.Kind = rk_CoprocPairReg;
570 return true;
571 }
572
573 static std::unique_ptr<SparcOperand>
574 MorphToMEMrr(unsigned Base, std::unique_ptr<SparcOperand> Op) {
575 unsigned offsetReg = Op->getReg();
576 Op->Kind = k_MemoryReg;
577 Op->Mem.Base = Base;
578 Op->Mem.OffsetReg = offsetReg;
579 Op->Mem.Off = nullptr;
580 return Op;
581 }
582
583 static std::unique_ptr<SparcOperand>
584 CreateMEMr(unsigned Base, SMLoc S, SMLoc E) {
585 auto Op = std::make_unique<SparcOperand>(args: k_MemoryReg);
586 Op->Mem.Base = Base;
587 Op->Mem.OffsetReg = Sparc::G0; // always 0
588 Op->Mem.Off = nullptr;
589 Op->StartLoc = S;
590 Op->EndLoc = E;
591 return Op;
592 }
593
594 static std::unique_ptr<SparcOperand>
595 MorphToMEMri(unsigned Base, std::unique_ptr<SparcOperand> Op) {
596 const MCExpr *Imm = Op->getImm();
597 Op->Kind = k_MemoryImm;
598 Op->Mem.Base = Base;
599 Op->Mem.OffsetReg = 0;
600 Op->Mem.Off = Imm;
601 return Op;
602 }
603};
604
605} // end anonymous namespace
606
607#define GET_MATCHER_IMPLEMENTATION
608#define GET_REGISTER_MATCHER
609#define GET_MNEMONIC_SPELL_CHECKER
610#include "SparcGenAsmMatcher.inc"
611
612// Use a custom function instead of the one from SparcGenAsmMatcher
613// so we can differentiate between unavailable and unknown instructions.
614SparcAsmParser::MatchResultTy
615SparcAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
616 // Process all MnemonicAliases to remap the mnemonic.
617 applyMnemonicAliases(Mnemonic, Features: getAvailableFeatures(), VariantID);
618
619 // Find the appropriate table for this asm variant.
620 const MatchEntry *Start, *End;
621 switch (VariantID) {
622 default:
623 llvm_unreachable("invalid variant!");
624 case 0:
625 Start = std::begin(arr: MatchTable0);
626 End = std::end(arr: MatchTable0);
627 break;
628 }
629
630 // Search the table.
631 auto MnemonicRange = std::equal_range(first: Start, last: End, val: Mnemonic, comp: LessOpcode());
632
633 if (MnemonicRange.first == MnemonicRange.second)
634 return Match_MnemonicFail;
635
636 for (const MatchEntry *it = MnemonicRange.first, *ie = MnemonicRange.second;
637 it != ie; ++it) {
638 const FeatureBitset &RequiredFeatures =
639 FeatureBitsets[it->RequiredFeaturesIdx];
640 if ((getAvailableFeatures() & RequiredFeatures) == RequiredFeatures)
641 return Match_Success;
642 }
643 return Match_MissingFeature;
644}
645
646bool SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc,
647 SmallVectorImpl<MCInst> &Instructions) {
648 MCOperand MCRegOp = Inst.getOperand(i: 0);
649 MCOperand MCValOp = Inst.getOperand(i: 1);
650 assert(MCRegOp.isReg());
651 assert(MCValOp.isImm() || MCValOp.isExpr());
652
653 // the imm operand can be either an expression or an immediate.
654 bool IsImm = Inst.getOperand(i: 1).isImm();
655 int64_t RawImmValue = IsImm ? MCValOp.getImm() : 0;
656
657 // Allow either a signed or unsigned 32-bit immediate.
658 if (RawImmValue < -2147483648LL || RawImmValue > 4294967295LL) {
659 return Error(L: IDLoc,
660 Msg: "set: argument must be between -2147483648 and 4294967295");
661 }
662
663 // If the value was expressed as a large unsigned number, that's ok.
664 // We want to see if it "looks like" a small signed number.
665 int32_t ImmValue = RawImmValue;
666 // For 'set' you can't use 'or' with a negative operand on V9 because
667 // that would splat the sign bit across the upper half of the destination
668 // register, whereas 'set' is defined to zero the high 32 bits.
669 bool IsEffectivelyImm13 =
670 IsImm && ((is64Bit() ? 0 : -4096) <= ImmValue && ImmValue < 4096);
671 const MCExpr *ValExpr;
672 if (IsImm)
673 ValExpr = MCConstantExpr::create(Value: ImmValue, Ctx&: getContext());
674 else
675 ValExpr = MCValOp.getExpr();
676
677 MCOperand PrevReg = MCOperand::createReg(Reg: Sparc::G0);
678
679 // If not just a signed imm13 value, then either we use a 'sethi' with a
680 // following 'or', or a 'sethi' by itself if there are no more 1 bits.
681 // In either case, start with the 'sethi'.
682 if (!IsEffectivelyImm13) {
683 MCInst TmpInst;
684 const MCExpr *Expr = adjustPICRelocation(VK: SparcMCExpr::VK_Sparc_HI, subExpr: ValExpr);
685 TmpInst.setLoc(IDLoc);
686 TmpInst.setOpcode(SP::SETHIi);
687 TmpInst.addOperand(Op: MCRegOp);
688 TmpInst.addOperand(Op: MCOperand::createExpr(Val: Expr));
689 Instructions.push_back(Elt: TmpInst);
690 PrevReg = MCRegOp;
691 }
692
693 // The low bits require touching in 3 cases:
694 // * A non-immediate value will always require both instructions.
695 // * An effectively imm13 value needs only an 'or' instruction.
696 // * Otherwise, an immediate that is not effectively imm13 requires the
697 // 'or' only if bits remain after clearing the 22 bits that 'sethi' set.
698 // If the low bits are known zeros, there's nothing to do.
699 // In the second case, and only in that case, must we NOT clear
700 // bits of the immediate value via the %lo() assembler function.
701 // Note also, the 'or' instruction doesn't mind a large value in the case
702 // where the operand to 'set' was 0xFFFFFzzz - it does exactly what you mean.
703 if (!IsImm || IsEffectivelyImm13 || (ImmValue & 0x3ff)) {
704 MCInst TmpInst;
705 const MCExpr *Expr;
706 if (IsEffectivelyImm13)
707 Expr = ValExpr;
708 else
709 Expr = adjustPICRelocation(VK: SparcMCExpr::VK_Sparc_LO, subExpr: ValExpr);
710 TmpInst.setLoc(IDLoc);
711 TmpInst.setOpcode(SP::ORri);
712 TmpInst.addOperand(Op: MCRegOp);
713 TmpInst.addOperand(Op: PrevReg);
714 TmpInst.addOperand(Op: MCOperand::createExpr(Val: Expr));
715 Instructions.push_back(Elt: TmpInst);
716 }
717 return false;
718}
719
720bool SparcAsmParser::expandSETX(MCInst &Inst, SMLoc IDLoc,
721 SmallVectorImpl<MCInst> &Instructions) {
722 MCOperand MCRegOp = Inst.getOperand(i: 0);
723 MCOperand MCValOp = Inst.getOperand(i: 1);
724 MCOperand MCTmpOp = Inst.getOperand(i: 2);
725 assert(MCRegOp.isReg() && MCTmpOp.isReg());
726 assert(MCValOp.isImm() || MCValOp.isExpr());
727
728 // the imm operand can be either an expression or an immediate.
729 bool IsImm = MCValOp.isImm();
730 int64_t ImmValue = IsImm ? MCValOp.getImm() : 0;
731
732 const MCExpr *ValExpr = IsImm ? MCConstantExpr::create(Value: ImmValue, Ctx&: getContext())
733 : MCValOp.getExpr();
734
735 // Very small immediates can be expressed directly as a single `or`.
736 if (IsImm && isInt<13>(x: ImmValue)) {
737 // or rd, val, rd
738 Instructions.push_back(Elt: MCInstBuilder(SP::ORri)
739 .addReg(Reg: MCRegOp.getReg())
740 .addReg(Reg: Sparc::G0)
741 .addExpr(Val: ValExpr));
742 return false;
743 }
744
745 // Otherwise, first we set the lower half of the register.
746
747 // sethi %hi(val), rd
748 Instructions.push_back(
749 Elt: MCInstBuilder(SP::SETHIi)
750 .addReg(Reg: MCRegOp.getReg())
751 .addExpr(Val: adjustPICRelocation(VK: SparcMCExpr::VK_Sparc_HI, subExpr: ValExpr)));
752 // or rd, %lo(val), rd
753 Instructions.push_back(
754 Elt: MCInstBuilder(SP::ORri)
755 .addReg(Reg: MCRegOp.getReg())
756 .addReg(Reg: MCRegOp.getReg())
757 .addExpr(Val: adjustPICRelocation(VK: SparcMCExpr::VK_Sparc_LO, subExpr: ValExpr)));
758
759 // Small positive immediates can be expressed as a single `sethi`+`or`
760 // combination, so we can just return here.
761 if (IsImm && isUInt<32>(x: ImmValue))
762 return false;
763
764 // For bigger immediates, we need to generate the upper half, then shift and
765 // merge it with the lower half that has just been generated above.
766
767 // sethi %hh(val), tmp
768 Instructions.push_back(
769 Elt: MCInstBuilder(SP::SETHIi)
770 .addReg(Reg: MCTmpOp.getReg())
771 .addExpr(Val: adjustPICRelocation(VK: SparcMCExpr::VK_Sparc_HH, subExpr: ValExpr)));
772 // or tmp, %hm(val), tmp
773 Instructions.push_back(
774 Elt: MCInstBuilder(SP::ORri)
775 .addReg(Reg: MCTmpOp.getReg())
776 .addReg(Reg: MCTmpOp.getReg())
777 .addExpr(Val: adjustPICRelocation(VK: SparcMCExpr::VK_Sparc_HM, subExpr: ValExpr)));
778 // sllx tmp, 32, tmp
779 Instructions.push_back(Elt: MCInstBuilder(SP::SLLXri)
780 .addReg(Reg: MCTmpOp.getReg())
781 .addReg(Reg: MCTmpOp.getReg())
782 .addImm(Val: 32));
783 // or tmp, rd, rd
784 Instructions.push_back(Elt: MCInstBuilder(SP::ORrr)
785 .addReg(Reg: MCRegOp.getReg())
786 .addReg(Reg: MCTmpOp.getReg())
787 .addReg(Reg: MCRegOp.getReg()));
788
789 return false;
790}
791
792bool SparcAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
793 OperandVector &Operands,
794 MCStreamer &Out,
795 uint64_t &ErrorInfo,
796 bool MatchingInlineAsm) {
797 MCInst Inst;
798 SmallVector<MCInst, 8> Instructions;
799 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
800 matchingInlineAsm: MatchingInlineAsm);
801 switch (MatchResult) {
802 case Match_Success: {
803 switch (Inst.getOpcode()) {
804 default:
805 Inst.setLoc(IDLoc);
806 Instructions.push_back(Elt: Inst);
807 break;
808 case SP::SET:
809 if (expandSET(Inst, IDLoc, Instructions))
810 return true;
811 break;
812 case SP::SETX:
813 if (expandSETX(Inst, IDLoc, Instructions))
814 return true;
815 break;
816 }
817
818 for (const MCInst &I : Instructions) {
819 Out.emitInstruction(Inst: I, STI: getSTI());
820 }
821 return false;
822 }
823
824 case Match_MissingFeature:
825 return Error(L: IDLoc,
826 Msg: "instruction requires a CPU feature not currently enabled");
827
828 case Match_InvalidOperand: {
829 SMLoc ErrorLoc = IDLoc;
830 if (ErrorInfo != ~0ULL) {
831 if (ErrorInfo >= Operands.size())
832 return Error(L: IDLoc, Msg: "too few operands for instruction");
833
834 ErrorLoc = ((SparcOperand &)*Operands[ErrorInfo]).getStartLoc();
835 if (ErrorLoc == SMLoc())
836 ErrorLoc = IDLoc;
837 }
838
839 return Error(L: ErrorLoc, Msg: "invalid operand for instruction");
840 }
841 case Match_MnemonicFail:
842 return Error(L: IDLoc, Msg: "invalid instruction mnemonic");
843 }
844 llvm_unreachable("Implement any new match types added!");
845}
846
847bool SparcAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
848 SMLoc &EndLoc) {
849 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
850 return Error(L: StartLoc, Msg: "invalid register name");
851 return false;
852}
853
854ParseStatus SparcAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
855 SMLoc &EndLoc) {
856 const AsmToken &Tok = Parser.getTok();
857 StartLoc = Tok.getLoc();
858 EndLoc = Tok.getEndLoc();
859 Reg = Sparc::NoRegister;
860 if (getLexer().getKind() != AsmToken::Percent)
861 return ParseStatus::NoMatch;
862 Parser.Lex();
863 unsigned RegKind = SparcOperand::rk_None;
864 Reg = matchRegisterName(Tok, RegKind);
865 if (Reg) {
866 Parser.Lex();
867 return ParseStatus::Success;
868 }
869
870 getLexer().UnLex(Token: Tok);
871 return ParseStatus::NoMatch;
872}
873
874bool SparcAsmParser::ParseInstruction(ParseInstructionInfo &Info,
875 StringRef Name, SMLoc NameLoc,
876 OperandVector &Operands) {
877 // Validate and reject unavailable mnemonics early before
878 // running any operand parsing.
879 // This is needed because some operands (mainly memory ones)
880 // differ between V8 and V9 ISA and so any operand parsing errors
881 // will cause IAS to bail out before it reaches MatchAndEmitInstruction
882 // (where the instruction as a whole, including the mnemonic, is validated
883 // once again just before emission).
884 // As a nice side effect this also allows us to reject unknown
885 // instructions and suggest replacements.
886 MatchResultTy MS = mnemonicIsValid(Mnemonic: Name, VariantID: 0);
887 switch (MS) {
888 case Match_Success:
889 break;
890 case Match_MissingFeature:
891 return Error(L: NameLoc,
892 Msg: "instruction requires a CPU feature not currently enabled");
893 case Match_MnemonicFail:
894 return Error(L: NameLoc,
895 Msg: "invalid instruction mnemonic" +
896 SparcMnemonicSpellCheck(S: Name, FBS: getAvailableFeatures(), VariantID: 0));
897 default:
898 llvm_unreachable("invalid return status!");
899 }
900
901 // First operand in MCInst is instruction mnemonic.
902 Operands.push_back(Elt: SparcOperand::CreateToken(Str: Name, S: NameLoc));
903
904 // apply mnemonic aliases, if any, so that we can parse operands correctly.
905 applyMnemonicAliases(Mnemonic&: Name, Features: getAvailableFeatures(), VariantID: 0);
906
907 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
908 // Read the first operand.
909 if (getLexer().is(K: AsmToken::Comma)) {
910 if (!parseBranchModifiers(Operands).isSuccess()) {
911 SMLoc Loc = getLexer().getLoc();
912 return Error(L: Loc, Msg: "unexpected token");
913 }
914 }
915 if (!parseOperand(Operands, Name).isSuccess()) {
916 SMLoc Loc = getLexer().getLoc();
917 return Error(L: Loc, Msg: "unexpected token");
918 }
919
920 while (getLexer().is(K: AsmToken::Comma) || getLexer().is(K: AsmToken::Plus)) {
921 if (getLexer().is(K: AsmToken::Plus)) {
922 // Plus tokens are significant in software_traps (p83, sparcv8.pdf). We must capture them.
923 Operands.push_back(Elt: SparcOperand::CreateToken(Str: "+", S: Parser.getTok().getLoc()));
924 }
925 Parser.Lex(); // Eat the comma or plus.
926 // Parse and remember the operand.
927 if (!parseOperand(Operands, Name).isSuccess()) {
928 SMLoc Loc = getLexer().getLoc();
929 return Error(L: Loc, Msg: "unexpected token");
930 }
931 }
932 }
933 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
934 SMLoc Loc = getLexer().getLoc();
935 return Error(L: Loc, Msg: "unexpected token");
936 }
937 Parser.Lex(); // Consume the EndOfStatement.
938 return false;
939}
940
941ParseStatus SparcAsmParser::parseDirective(AsmToken DirectiveID) {
942 StringRef IDVal = DirectiveID.getString();
943
944 if (IDVal == ".register") {
945 // For now, ignore .register directive.
946 Parser.eatToEndOfStatement();
947 return ParseStatus::Success;
948 }
949 if (IDVal == ".proc") {
950 // For compatibility, ignore this directive.
951 // (It's supposed to be an "optimization" in the Sun assembler)
952 Parser.eatToEndOfStatement();
953 return ParseStatus::Success;
954 }
955
956 // Let the MC layer to handle other directives.
957 return ParseStatus::NoMatch;
958}
959
960ParseStatus SparcAsmParser::parseMEMOperand(OperandVector &Operands) {
961 SMLoc S, E;
962
963 std::unique_ptr<SparcOperand> LHS;
964 if (!parseSparcAsmOperand(Operand&: LHS).isSuccess())
965 return ParseStatus::NoMatch;
966
967 // Single immediate operand
968 if (LHS->isImm()) {
969 Operands.push_back(Elt: SparcOperand::MorphToMEMri(Base: Sparc::G0, Op: std::move(LHS)));
970 return ParseStatus::Success;
971 }
972
973 if (!LHS->isIntReg())
974 return Error(L: LHS->getStartLoc(), Msg: "invalid register kind for this operand");
975
976 AsmToken Tok = getLexer().getTok();
977 // The plus token may be followed by a register or an immediate value, the
978 // minus one is always interpreted as sign for the immediate value
979 if (Tok.is(K: AsmToken::Plus) || Tok.is(K: AsmToken::Minus)) {
980 (void)Parser.parseOptionalToken(T: AsmToken::Plus);
981
982 std::unique_ptr<SparcOperand> RHS;
983 if (!parseSparcAsmOperand(Operand&: RHS).isSuccess())
984 return ParseStatus::NoMatch;
985
986 if (RHS->isReg() && !RHS->isIntReg())
987 return Error(L: RHS->getStartLoc(),
988 Msg: "invalid register kind for this operand");
989
990 Operands.push_back(
991 Elt: RHS->isImm()
992 ? SparcOperand::MorphToMEMri(Base: LHS->getReg(), Op: std::move(RHS))
993 : SparcOperand::MorphToMEMrr(Base: LHS->getReg(), Op: std::move(RHS)));
994
995 return ParseStatus::Success;
996 }
997
998 Operands.push_back(Elt: SparcOperand::CreateMEMr(Base: LHS->getReg(), S, E));
999 return ParseStatus::Success;
1000}
1001
1002template <unsigned N>
1003ParseStatus SparcAsmParser::parseShiftAmtImm(OperandVector &Operands) {
1004 SMLoc S = Parser.getTok().getLoc();
1005 SMLoc E = SMLoc::getFromPointer(Ptr: S.getPointer() - 1);
1006
1007 // This is a register, not an immediate
1008 if (getLexer().getKind() == AsmToken::Percent)
1009 return ParseStatus::NoMatch;
1010
1011 const MCExpr *Expr;
1012 if (getParser().parseExpression(Res&: Expr))
1013 return ParseStatus::Failure;
1014
1015 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Expr);
1016 if (!CE)
1017 return Error(L: S, Msg: "constant expression expected");
1018
1019 if (!isUInt<N>(CE->getValue()))
1020 return Error(L: S, Msg: "immediate shift value out of range");
1021
1022 Operands.push_back(Elt: SparcOperand::CreateImm(Val: Expr, S, E));
1023 return ParseStatus::Success;
1024}
1025
1026template <SparcAsmParser::TailRelocKind Kind>
1027ParseStatus SparcAsmParser::parseTailRelocSym(OperandVector &Operands) {
1028 SMLoc S = getLoc();
1029 SMLoc E = SMLoc::getFromPointer(Ptr: S.getPointer() - 1);
1030
1031 auto MatchesKind = [](SparcMCExpr::VariantKind VK) -> bool {
1032 switch (Kind) {
1033 case TailRelocKind::Load_GOT:
1034 // Non-TLS relocations on ld (or ldx).
1035 // ld [%rr + %rr], %rr, %rel(sym)
1036 return VK == SparcMCExpr::VK_Sparc_GOTDATA_OP;
1037 case TailRelocKind::Add_TLS:
1038 // TLS relocations on add.
1039 // add %rr, %rr, %rr, %rel(sym)
1040 switch (VK) {
1041 case SparcMCExpr::VK_Sparc_TLS_GD_ADD:
1042 case SparcMCExpr::VK_Sparc_TLS_IE_ADD:
1043 case SparcMCExpr::VK_Sparc_TLS_LDM_ADD:
1044 case SparcMCExpr::VK_Sparc_TLS_LDO_ADD:
1045 return true;
1046 default:
1047 return false;
1048 }
1049 case TailRelocKind::Load_TLS:
1050 // TLS relocations on ld (or ldx).
1051 // ld[x] %addr, %rr, %rel(sym)
1052 switch (VK) {
1053 case SparcMCExpr::VK_Sparc_TLS_IE_LD:
1054 case SparcMCExpr::VK_Sparc_TLS_IE_LDX:
1055 return true;
1056 default:
1057 return false;
1058 }
1059 case TailRelocKind::Call_TLS:
1060 // TLS relocations on call.
1061 // call sym, %rel(sym)
1062 switch (VK) {
1063 case SparcMCExpr::VK_Sparc_TLS_GD_CALL:
1064 case SparcMCExpr::VK_Sparc_TLS_LDM_CALL:
1065 return true;
1066 default:
1067 return false;
1068 }
1069 }
1070 llvm_unreachable("Unhandled SparcAsmParser::TailRelocKind enum");
1071 };
1072
1073 if (getLexer().getKind() != AsmToken::Percent)
1074 return Error(L: getLoc(), Msg: "expected '%' for operand modifier");
1075
1076 const AsmToken Tok = Parser.getTok();
1077 getParser().Lex(); // Eat '%'
1078
1079 if (getLexer().getKind() != AsmToken::Identifier)
1080 return Error(L: getLoc(), Msg: "expected valid identifier for operand modifier");
1081
1082 StringRef Name = getParser().getTok().getIdentifier();
1083 SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name: Name);
1084 if (VK == SparcMCExpr::VK_Sparc_None)
1085 return Error(L: getLoc(), Msg: "invalid operand modifier");
1086
1087 if (!MatchesKind(VK)) {
1088 // Did not match the specified set of relocation types, put '%' back.
1089 getLexer().UnLex(Token: Tok);
1090 return ParseStatus::NoMatch;
1091 }
1092
1093 Parser.Lex(); // Eat the identifier.
1094 if (getLexer().getKind() != AsmToken::LParen)
1095 return Error(L: getLoc(), Msg: "expected '('");
1096
1097 getParser().Lex(); // Eat '('
1098 const MCExpr *SubExpr;
1099 if (getParser().parseParenExpression(Res&: SubExpr, EndLoc&: E))
1100 return ParseStatus::Failure;
1101
1102 const MCExpr *Val = adjustPICRelocation(VK, subExpr: SubExpr);
1103 Operands.push_back(Elt: SparcOperand::CreateImm(Val, S, E));
1104 return ParseStatus::Success;
1105}
1106
1107ParseStatus SparcAsmParser::parseMembarTag(OperandVector &Operands) {
1108 SMLoc S = Parser.getTok().getLoc();
1109 const MCExpr *EVal;
1110 int64_t ImmVal = 0;
1111
1112 std::unique_ptr<SparcOperand> Mask;
1113 if (parseSparcAsmOperand(Operand&: Mask).isSuccess()) {
1114 if (!Mask->isImm() || !Mask->getImm()->evaluateAsAbsolute(Res&: ImmVal) ||
1115 ImmVal < 0 || ImmVal > 127)
1116 return Error(L: S, Msg: "invalid membar mask number");
1117 }
1118
1119 while (getLexer().getKind() == AsmToken::Hash) {
1120 SMLoc TagStart = getLexer().getLoc();
1121 Parser.Lex(); // Eat the '#'.
1122 unsigned MaskVal = StringSwitch<unsigned>(Parser.getTok().getString())
1123 .Case(S: "LoadLoad", Value: 0x1)
1124 .Case(S: "StoreLoad", Value: 0x2)
1125 .Case(S: "LoadStore", Value: 0x4)
1126 .Case(S: "StoreStore", Value: 0x8)
1127 .Case(S: "Lookaside", Value: 0x10)
1128 .Case(S: "MemIssue", Value: 0x20)
1129 .Case(S: "Sync", Value: 0x40)
1130 .Default(Value: 0);
1131
1132 Parser.Lex(); // Eat the identifier token.
1133
1134 if (!MaskVal)
1135 return Error(L: TagStart, Msg: "unknown membar tag");
1136
1137 ImmVal |= MaskVal;
1138
1139 if (getLexer().getKind() == AsmToken::Pipe)
1140 Parser.Lex(); // Eat the '|'.
1141 }
1142
1143 EVal = MCConstantExpr::create(Value: ImmVal, Ctx&: getContext());
1144 SMLoc E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
1145 Operands.push_back(Elt: SparcOperand::CreateImm(Val: EVal, S, E));
1146 return ParseStatus::Success;
1147}
1148
1149ParseStatus SparcAsmParser::parseASITag(OperandVector &Operands) {
1150 SMLoc S = Parser.getTok().getLoc();
1151 SMLoc E = Parser.getTok().getEndLoc();
1152 int64_t ASIVal = 0;
1153
1154 if (getLexer().getKind() != AsmToken::Hash) {
1155 // If the ASI tag provided is not a named tag, then it
1156 // must be a constant expression.
1157 ParseStatus ParseExprStatus = parseExpression(Val&: ASIVal);
1158 if (!ParseExprStatus.isSuccess())
1159 return ParseExprStatus;
1160
1161 if (!isUInt<8>(x: ASIVal))
1162 return Error(L: S, Msg: "invalid ASI number, must be between 0 and 255");
1163
1164 Operands.push_back(Elt: SparcOperand::CreateASITag(Val: ASIVal, S, E));
1165 return ParseStatus::Success;
1166 }
1167
1168 // For now we only support named tags for 64-bit/V9 systems.
1169 // TODO: add support for 32-bit/V8 systems.
1170 SMLoc TagStart = getLexer().peekTok(ShouldSkipSpace: false).getLoc();
1171 Parser.Lex(); // Eat the '#'.
1172 const StringRef ASIName = Parser.getTok().getString();
1173 const SparcASITag::ASITag *ASITag = SparcASITag::lookupASITagByName(Name: ASIName);
1174 if (!ASITag)
1175 ASITag = SparcASITag::lookupASITagByAltName(AltName: ASIName);
1176 Parser.Lex(); // Eat the identifier token.
1177
1178 if (!ASITag)
1179 return Error(L: TagStart, Msg: "unknown ASI tag");
1180
1181 ASIVal = ASITag->Encoding;
1182
1183 Operands.push_back(Elt: SparcOperand::CreateASITag(Val: ASIVal, S, E));
1184 return ParseStatus::Success;
1185}
1186
1187ParseStatus SparcAsmParser::parsePrefetchTag(OperandVector &Operands) {
1188 SMLoc S = Parser.getTok().getLoc();
1189 SMLoc E = Parser.getTok().getEndLoc();
1190 int64_t PrefetchVal = 0;
1191
1192 if (getLexer().getKind() != AsmToken::Hash) {
1193 // If the prefetch tag provided is not a named tag, then it
1194 // must be a constant expression.
1195 ParseStatus ParseExprStatus = parseExpression(Val&: PrefetchVal);
1196 if (!ParseExprStatus.isSuccess())
1197 return ParseExprStatus;
1198
1199 if (!isUInt<8>(x: PrefetchVal))
1200 return Error(L: S, Msg: "invalid prefetch number, must be between 0 and 31");
1201
1202 Operands.push_back(Elt: SparcOperand::CreatePrefetchTag(Val: PrefetchVal, S, E));
1203 return ParseStatus::Success;
1204 }
1205
1206 SMLoc TagStart = getLexer().peekTok(ShouldSkipSpace: false).getLoc();
1207 Parser.Lex(); // Eat the '#'.
1208 const StringRef PrefetchName = Parser.getTok().getString();
1209 const SparcPrefetchTag::PrefetchTag *PrefetchTag =
1210 SparcPrefetchTag::lookupPrefetchTagByName(Name: PrefetchName);
1211 Parser.Lex(); // Eat the identifier token.
1212
1213 if (!PrefetchTag)
1214 return Error(L: TagStart, Msg: "unknown prefetch tag");
1215
1216 PrefetchVal = PrefetchTag->Encoding;
1217
1218 Operands.push_back(Elt: SparcOperand::CreatePrefetchTag(Val: PrefetchVal, S, E));
1219 return ParseStatus::Success;
1220}
1221
1222ParseStatus SparcAsmParser::parseCallTarget(OperandVector &Operands) {
1223 SMLoc S = Parser.getTok().getLoc();
1224 SMLoc E = SMLoc::getFromPointer(Ptr: S.getPointer() - 1);
1225
1226 switch (getLexer().getKind()) {
1227 default:
1228 return ParseStatus::NoMatch;
1229 case AsmToken::LParen:
1230 case AsmToken::Integer:
1231 case AsmToken::Identifier:
1232 case AsmToken::Dot:
1233 break;
1234 }
1235
1236 const MCExpr *DestValue;
1237 if (getParser().parseExpression(Res&: DestValue))
1238 return ParseStatus::NoMatch;
1239
1240 bool IsPic = getContext().getObjectFileInfo()->isPositionIndependent();
1241 SparcMCExpr::VariantKind Kind =
1242 IsPic ? SparcMCExpr::VK_Sparc_WPLT30 : SparcMCExpr::VK_Sparc_WDISP30;
1243
1244 const MCExpr *DestExpr = SparcMCExpr::create(Kind, Expr: DestValue, Ctx&: getContext());
1245 Operands.push_back(Elt: SparcOperand::CreateImm(Val: DestExpr, S, E));
1246 return ParseStatus::Success;
1247}
1248
1249ParseStatus SparcAsmParser::parseOperand(OperandVector &Operands,
1250 StringRef Mnemonic) {
1251
1252 ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
1253
1254 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1255 // there was a match, but an error occurred, in which case, just return that
1256 // the operand parsing failed.
1257 if (Res.isSuccess() || Res.isFailure())
1258 return Res;
1259
1260 if (getLexer().is(K: AsmToken::LBrac)) {
1261 // Memory operand
1262 Operands.push_back(Elt: SparcOperand::CreateToken(Str: "[",
1263 S: Parser.getTok().getLoc()));
1264 Parser.Lex(); // Eat the [
1265
1266 if (Mnemonic == "cas" || Mnemonic == "casl" || Mnemonic == "casa" ||
1267 Mnemonic == "casx" || Mnemonic == "casxl" || Mnemonic == "casxa") {
1268 SMLoc S = Parser.getTok().getLoc();
1269 if (getLexer().getKind() != AsmToken::Percent)
1270 return ParseStatus::NoMatch;
1271 Parser.Lex(); // eat %
1272
1273 unsigned RegKind;
1274 MCRegister Reg = matchRegisterName(Tok: Parser.getTok(), RegKind);
1275 if (!Reg)
1276 return ParseStatus::NoMatch;
1277
1278 Parser.Lex(); // Eat the identifier token.
1279 SMLoc E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer()-1);
1280 Operands.push_back(Elt: SparcOperand::CreateReg(RegNum: Reg, Kind: RegKind, S, E));
1281 Res = ParseStatus::Success;
1282 } else {
1283 Res = parseMEMOperand(Operands);
1284 }
1285
1286 if (!Res.isSuccess())
1287 return Res;
1288
1289 if (!getLexer().is(K: AsmToken::RBrac))
1290 return ParseStatus::Failure;
1291
1292 Operands.push_back(Elt: SparcOperand::CreateToken(Str: "]",
1293 S: Parser.getTok().getLoc()));
1294 Parser.Lex(); // Eat the ]
1295
1296 // Parse an optional address-space identifier after the address.
1297 // This will be either an immediate constant expression, or, on 64-bit
1298 // processors, the %asi register.
1299 if (getLexer().is(K: AsmToken::Percent)) {
1300 SMLoc S = Parser.getTok().getLoc();
1301 if (!is64Bit())
1302 return Error(
1303 L: S, Msg: "malformed ASI tag, must be a constant integer expression");
1304
1305 Parser.Lex(); // Eat the %.
1306 const AsmToken Tok = Parser.getTok();
1307 if (Tok.is(K: AsmToken::Identifier) && Tok.getString() == "asi") {
1308 // Here we patch the MEM operand from [base + %g0] into [base + 0]
1309 // as memory operations with ASI tag stored in %asi register needs
1310 // to use immediate offset. We need to do this because Reg addressing
1311 // will be parsed as Reg+G0 initially.
1312 // This allows forms such as `ldxa [%o0] %asi, %o0` to parse correctly.
1313 SparcOperand &OldMemOp = (SparcOperand &)*Operands[Operands.size() - 2];
1314 if (OldMemOp.isMEMrr()) {
1315 if (OldMemOp.getMemOffsetReg() != Sparc::G0) {
1316 return Error(L: S, Msg: "invalid operand for instruction");
1317 }
1318 Operands[Operands.size() - 2] = SparcOperand::MorphToMEMri(
1319 Base: OldMemOp.getMemBase(),
1320 Op: SparcOperand::CreateImm(Val: MCConstantExpr::create(Value: 0, Ctx&: getContext()),
1321 S: OldMemOp.getStartLoc(),
1322 E: OldMemOp.getEndLoc()));
1323 }
1324 Parser.Lex(); // Eat the identifier.
1325 // In this context, we convert the register operand into
1326 // a plain "%asi" token since the register access is already
1327 // implicit in the instruction definition and encoding.
1328 // See LoadASI/StoreASI in SparcInstrInfo.td.
1329 Operands.push_back(Elt: SparcOperand::CreateToken(Str: "%asi", S));
1330 return ParseStatus::Success;
1331 }
1332
1333 return Error(L: S, Msg: "malformed ASI tag, must be %asi, a constant integer "
1334 "expression, or a named tag");
1335 }
1336
1337 // If we're not at the end of statement and the next token is not a comma,
1338 // then it is an immediate ASI value.
1339 if (getLexer().isNot(K: AsmToken::EndOfStatement) &&
1340 getLexer().isNot(K: AsmToken::Comma))
1341 return parseASITag(Operands);
1342 return ParseStatus::Success;
1343 }
1344
1345 std::unique_ptr<SparcOperand> Op;
1346
1347 Res = parseSparcAsmOperand(Operand&: Op, isCall: (Mnemonic == "call"));
1348 if (!Res.isSuccess() || !Op)
1349 return ParseStatus::Failure;
1350
1351 // Push the parsed operand into the list of operands
1352 Operands.push_back(Elt: std::move(Op));
1353
1354 return ParseStatus::Success;
1355}
1356
1357ParseStatus
1358SparcAsmParser::parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Op,
1359 bool isCall) {
1360 SMLoc S = Parser.getTok().getLoc();
1361 SMLoc E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
1362 const MCExpr *EVal;
1363
1364 Op = nullptr;
1365 switch (getLexer().getKind()) {
1366 default: break;
1367
1368 case AsmToken::Percent: {
1369 Parser.Lex(); // Eat the '%'.
1370 unsigned RegKind;
1371 if (MCRegister Reg = matchRegisterName(Tok: Parser.getTok(), RegKind)) {
1372 StringRef Name = Parser.getTok().getString();
1373 Parser.Lex(); // Eat the identifier token.
1374 E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
1375 if (Reg == Sparc::ICC && Name == "xcc")
1376 Op = SparcOperand::CreateToken(Str: "%xcc", S);
1377 else
1378 Op = SparcOperand::CreateReg(RegNum: Reg, Kind: RegKind, S, E);
1379 break;
1380 }
1381 if (matchSparcAsmModifiers(EVal, EndLoc&: E)) {
1382 E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
1383 Op = SparcOperand::CreateImm(Val: EVal, S, E);
1384 }
1385 break;
1386 }
1387
1388 case AsmToken::Plus:
1389 case AsmToken::Minus:
1390 case AsmToken::Integer:
1391 case AsmToken::LParen:
1392 case AsmToken::Dot:
1393 case AsmToken::Identifier:
1394 if (getParser().parseExpression(Res&: EVal, EndLoc&: E))
1395 break;
1396
1397 int64_t Res;
1398 if (!EVal->evaluateAsAbsolute(Res)) {
1399 SparcMCExpr::VariantKind Kind = SparcMCExpr::VK_Sparc_13;
1400
1401 if (getContext().getObjectFileInfo()->isPositionIndependent()) {
1402 if (isCall)
1403 Kind = SparcMCExpr::VK_Sparc_WPLT30;
1404 else
1405 Kind = SparcMCExpr::VK_Sparc_GOT13;
1406 }
1407 EVal = SparcMCExpr::create(Kind, Expr: EVal, Ctx&: getContext());
1408 }
1409 Op = SparcOperand::CreateImm(Val: EVal, S, E);
1410 break;
1411 }
1412 return Op ? ParseStatus::Success : ParseStatus::Failure;
1413}
1414
1415ParseStatus SparcAsmParser::parseBranchModifiers(OperandVector &Operands) {
1416 // parse (,a|,pn|,pt)+
1417
1418 while (getLexer().is(K: AsmToken::Comma)) {
1419 Parser.Lex(); // Eat the comma
1420
1421 if (!getLexer().is(K: AsmToken::Identifier))
1422 return ParseStatus::Failure;
1423 StringRef modName = Parser.getTok().getString();
1424 if (modName == "a" || modName == "pn" || modName == "pt") {
1425 Operands.push_back(Elt: SparcOperand::CreateToken(Str: modName,
1426 S: Parser.getTok().getLoc()));
1427 Parser.Lex(); // eat the identifier.
1428 }
1429 }
1430 return ParseStatus::Success;
1431}
1432
1433ParseStatus SparcAsmParser::parseExpression(int64_t &Val) {
1434 AsmToken Tok = getLexer().getTok();
1435
1436 if (!isPossibleExpression(Token: Tok))
1437 return ParseStatus::NoMatch;
1438
1439 return getParser().parseAbsoluteExpression(Res&: Val);
1440}
1441
1442MCRegister SparcAsmParser::matchRegisterName(const AsmToken &Tok,
1443 unsigned &RegKind) {
1444 RegKind = SparcOperand::rk_None;
1445 if (!Tok.is(K: AsmToken::Identifier))
1446 return SP::NoRegister;
1447
1448 StringRef Name = Tok.getString();
1449 MCRegister Reg = MatchRegisterName(Name: Name.lower());
1450 if (!Reg)
1451 Reg = MatchRegisterAltName(Name: Name.lower());
1452
1453 if (Reg) {
1454 // Some registers have identical spellings. The generated matcher might
1455 // have chosen one or another spelling, e.g. "%fp" or "%i6" might have been
1456 // matched to either SP::I6 or SP::I6_I7. Other parts of SparcAsmParser
1457 // are not prepared for this, so we do some canonicalization.
1458
1459 // See the note in SparcRegisterInfo.td near ASRRegs register class.
1460 if (Reg == SP::ASR4 && Name == "tick") {
1461 RegKind = SparcOperand::rk_Special;
1462 return SP::TICK;
1463 }
1464
1465 if (MRI.getRegClass(i: SP::IntRegsRegClassID).contains(Reg)) {
1466 RegKind = SparcOperand::rk_IntReg;
1467 return Reg;
1468 }
1469 if (MRI.getRegClass(i: SP::FPRegsRegClassID).contains(Reg)) {
1470 RegKind = SparcOperand::rk_FloatReg;
1471 return Reg;
1472 }
1473 if (MRI.getRegClass(i: SP::CoprocRegsRegClassID).contains(Reg)) {
1474 RegKind = SparcOperand::rk_CoprocReg;
1475 return Reg;
1476 }
1477
1478 // Canonicalize G0_G1 ... G30_G31 etc. to G0 ... G30.
1479 if (MRI.getRegClass(i: SP::IntPairRegClassID).contains(Reg)) {
1480 RegKind = SparcOperand::rk_IntReg;
1481 return MRI.getSubReg(Reg, Idx: SP::sub_even);
1482 }
1483
1484 // Canonicalize D0 ... D15 to F0 ... F30.
1485 if (MRI.getRegClass(i: SP::DFPRegsRegClassID).contains(Reg)) {
1486 // D16 ... D31 do not have sub-registers.
1487 if (MCRegister SubReg = MRI.getSubReg(Reg, Idx: SP::sub_even)) {
1488 RegKind = SparcOperand::rk_FloatReg;
1489 return SubReg;
1490 }
1491 RegKind = SparcOperand::rk_DoubleReg;
1492 return Reg;
1493 }
1494
1495 // The generated matcher does not currently return QFP registers.
1496 // If it changes, we will need to handle them in a similar way.
1497 assert(!MRI.getRegClass(SP::QFPRegsRegClassID).contains(Reg));
1498
1499 // Canonicalize C0_C1 ... C30_C31 to C0 ... C30.
1500 if (MRI.getRegClass(i: SP::CoprocPairRegClassID).contains(Reg)) {
1501 RegKind = SparcOperand::rk_CoprocReg;
1502 return MRI.getSubReg(Reg, Idx: SP::sub_even);
1503 }
1504
1505 // Other registers do not need special handling.
1506 RegKind = SparcOperand::rk_Special;
1507 return Reg;
1508 }
1509
1510 // If we still have no match, try custom parsing.
1511 // Not all registers and their spellings are modeled in td files.
1512
1513 // %r0 - %r31
1514 int64_t RegNo = 0;
1515 if (Name.starts_with_insensitive(Prefix: "r") &&
1516 !Name.substr(Start: 1, N: 2).getAsInteger(Radix: 10, Result&: RegNo) && RegNo < 31) {
1517 RegKind = SparcOperand::rk_IntReg;
1518 return IntRegs[RegNo];
1519 }
1520
1521 if (Name == "xcc") {
1522 // FIXME:: check 64bit.
1523 RegKind = SparcOperand::rk_Special;
1524 return SP::ICC;
1525 }
1526
1527 // JPS1 extension - aliases for ASRs
1528 // Section 5.2.11 - Ancillary State Registers (ASRs)
1529 if (Name == "pcr") {
1530 RegKind = SparcOperand::rk_Special;
1531 return SP::ASR16;
1532 }
1533 if (Name == "pic") {
1534 RegKind = SparcOperand::rk_Special;
1535 return SP::ASR17;
1536 }
1537 if (Name == "dcr") {
1538 RegKind = SparcOperand::rk_Special;
1539 return SP::ASR18;
1540 }
1541 if (Name == "gsr") {
1542 RegKind = SparcOperand::rk_Special;
1543 return SP::ASR19;
1544 }
1545 if (Name == "set_softint") {
1546 RegKind = SparcOperand::rk_Special;
1547 return SP::ASR20;
1548 }
1549 if (Name == "clear_softint") {
1550 RegKind = SparcOperand::rk_Special;
1551 return SP::ASR21;
1552 }
1553 if (Name == "softint") {
1554 RegKind = SparcOperand::rk_Special;
1555 return SP::ASR22;
1556 }
1557 if (Name == "tick_cmpr") {
1558 RegKind = SparcOperand::rk_Special;
1559 return SP::ASR23;
1560 }
1561 if (Name == "stick" || Name == "sys_tick") {
1562 RegKind = SparcOperand::rk_Special;
1563 return SP::ASR24;
1564 }
1565 if (Name == "stick_cmpr" || Name == "sys_tick_cmpr") {
1566 RegKind = SparcOperand::rk_Special;
1567 return SP::ASR25;
1568 }
1569
1570 return SP::NoRegister;
1571}
1572
1573// Determine if an expression contains a reference to the symbol
1574// "_GLOBAL_OFFSET_TABLE_".
1575static bool hasGOTReference(const MCExpr *Expr) {
1576 switch (Expr->getKind()) {
1577 case MCExpr::Target:
1578 if (const SparcMCExpr *SE = dyn_cast<SparcMCExpr>(Val: Expr))
1579 return hasGOTReference(Expr: SE->getSubExpr());
1580 break;
1581
1582 case MCExpr::Constant:
1583 break;
1584
1585 case MCExpr::Binary: {
1586 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Val: Expr);
1587 return hasGOTReference(Expr: BE->getLHS()) || hasGOTReference(Expr: BE->getRHS());
1588 }
1589
1590 case MCExpr::SymbolRef: {
1591 const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Val: Expr);
1592 return (SymRef.getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_");
1593 }
1594
1595 case MCExpr::Unary:
1596 return hasGOTReference(Expr: cast<MCUnaryExpr>(Val: Expr)->getSubExpr());
1597 }
1598 return false;
1599}
1600
1601const SparcMCExpr *
1602SparcAsmParser::adjustPICRelocation(SparcMCExpr::VariantKind VK,
1603 const MCExpr *subExpr) {
1604 // When in PIC mode, "%lo(...)" and "%hi(...)" behave differently.
1605 // If the expression refers contains _GLOBAL_OFFSET_TABLE, it is
1606 // actually a %pc10 or %pc22 relocation. Otherwise, they are interpreted
1607 // as %got10 or %got22 relocation.
1608
1609 if (getContext().getObjectFileInfo()->isPositionIndependent()) {
1610 switch(VK) {
1611 default: break;
1612 case SparcMCExpr::VK_Sparc_LO:
1613 VK = (hasGOTReference(Expr: subExpr) ? SparcMCExpr::VK_Sparc_PC10
1614 : SparcMCExpr::VK_Sparc_GOT10);
1615 break;
1616 case SparcMCExpr::VK_Sparc_HI:
1617 VK = (hasGOTReference(Expr: subExpr) ? SparcMCExpr::VK_Sparc_PC22
1618 : SparcMCExpr::VK_Sparc_GOT22);
1619 break;
1620 }
1621 }
1622
1623 return SparcMCExpr::create(Kind: VK, Expr: subExpr, Ctx&: getContext());
1624}
1625
1626bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
1627 SMLoc &EndLoc) {
1628 AsmToken Tok = Parser.getTok();
1629 if (!Tok.is(K: AsmToken::Identifier))
1630 return false;
1631
1632 StringRef name = Tok.getString();
1633
1634 SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name);
1635 switch (VK) {
1636 case SparcMCExpr::VK_Sparc_None:
1637 Error(L: getLoc(), Msg: "invalid operand modifier");
1638 return false;
1639
1640 case SparcMCExpr::VK_Sparc_GOTDATA_OP:
1641 case SparcMCExpr::VK_Sparc_TLS_GD_ADD:
1642 case SparcMCExpr::VK_Sparc_TLS_GD_CALL:
1643 case SparcMCExpr::VK_Sparc_TLS_IE_ADD:
1644 case SparcMCExpr::VK_Sparc_TLS_IE_LD:
1645 case SparcMCExpr::VK_Sparc_TLS_IE_LDX:
1646 case SparcMCExpr::VK_Sparc_TLS_LDM_ADD:
1647 case SparcMCExpr::VK_Sparc_TLS_LDM_CALL:
1648 case SparcMCExpr::VK_Sparc_TLS_LDO_ADD:
1649 // These are special-cased at tablegen level.
1650 return false;
1651
1652 default:
1653 break;
1654 }
1655
1656 Parser.Lex(); // Eat the identifier.
1657 if (Parser.getTok().getKind() != AsmToken::LParen)
1658 return false;
1659
1660 Parser.Lex(); // Eat the LParen token.
1661 const MCExpr *subExpr;
1662 if (Parser.parseParenExpression(Res&: subExpr, EndLoc))
1663 return false;
1664
1665 EVal = adjustPICRelocation(VK, subExpr);
1666 return true;
1667}
1668
1669bool SparcAsmParser::isPossibleExpression(const AsmToken &Token) {
1670 switch (Token.getKind()) {
1671 case AsmToken::LParen:
1672 case AsmToken::Integer:
1673 case AsmToken::Identifier:
1674 case AsmToken::Plus:
1675 case AsmToken::Minus:
1676 case AsmToken::Tilde:
1677 return true;
1678 default:
1679 return false;
1680 }
1681}
1682
1683extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcAsmParser() {
1684 RegisterMCAsmParser<SparcAsmParser> A(getTheSparcTarget());
1685 RegisterMCAsmParser<SparcAsmParser> B(getTheSparcV9Target());
1686 RegisterMCAsmParser<SparcAsmParser> C(getTheSparcelTarget());
1687}
1688
1689unsigned SparcAsmParser::validateTargetOperandClass(MCParsedAsmOperand &GOp,
1690 unsigned Kind) {
1691 SparcOperand &Op = (SparcOperand &)GOp;
1692 if (Op.isFloatOrDoubleReg()) {
1693 switch (Kind) {
1694 default: break;
1695 case MCK_DFPRegs:
1696 if (!Op.isFloatReg() || SparcOperand::MorphToDoubleReg(Op))
1697 return MCTargetAsmParser::Match_Success;
1698 break;
1699 case MCK_QFPRegs:
1700 if (SparcOperand::MorphToQuadReg(Op))
1701 return MCTargetAsmParser::Match_Success;
1702 break;
1703 }
1704 }
1705 if (Op.isIntReg() && Kind == MCK_IntPair) {
1706 if (SparcOperand::MorphToIntPairReg(Op))
1707 return MCTargetAsmParser::Match_Success;
1708 }
1709 if (Op.isCoprocReg() && Kind == MCK_CoprocPair) {
1710 if (SparcOperand::MorphToCoprocPairReg(Op))
1711 return MCTargetAsmParser::Match_Success;
1712 }
1713 return Match_InvalidOperand;
1714}
1715