LLVM 17.0.0git
SparcAsmParser.cpp
Go to the documentation of this file.
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
12#include "llvm/ADT/STLExtras.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/MC/MCContext.h"
16#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCInst.h"
18#include "llvm/MC/MCInstrInfo.h"
25#include "llvm/MC/MCStreamer.h"
27#include "llvm/MC/MCSymbol.h"
31#include "llvm/Support/SMLoc.h"
34#include <algorithm>
35#include <cassert>
36#include <cstdint>
37#include <memory>
38
39using namespace llvm;
40
41// The generated AsmMatcher SparcGenAsmMatcher uses "Sparc" as the target
42// namespace. But SPARC backend uses "SP" as its namespace.
43namespace llvm {
44namespace Sparc {
45
46 using namespace SP;
47
48} // end namespace Sparc
49} // end namespace llvm
50
51namespace {
52
53class SparcOperand;
54
55class SparcAsmParser : public MCTargetAsmParser {
56 MCAsmParser &Parser;
57
58 enum class TailRelocKind { Load_GOT, Add_TLS, Load_TLS, Call_TLS };
59
60 /// @name Auto-generated Match Functions
61 /// {
62
63#define GET_ASSEMBLER_HEADER
64#include "SparcGenAsmMatcher.inc"
65
66 /// }
67
68 // public interface of the MCTargetAsmParser.
69 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
72 bool MatchingInlineAsm) override;
73 bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
74 SMLoc &EndLoc) override;
76 SMLoc &EndLoc) override;
78 SMLoc NameLoc, OperandVector &Operands) override;
79 bool ParseDirective(AsmToken DirectiveID) override;
80
82 unsigned Kind) override;
83
84 // Custom parse functions for Sparc specific operands.
86
88
89 template <TailRelocKind Kind>
91
92 template <unsigned N>
94
96
98
100 parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Operand,
101 bool isCall = false);
102
103 OperandMatchResultTy parseBranchModifiers(OperandVector &Operands);
104
105 // Helper function for dealing with %lo / %hi in PIC mode.
106 const SparcMCExpr *adjustPICRelocation(SparcMCExpr::VariantKind VK,
107 const MCExpr *subExpr);
108
109 // returns true if Tok is matched to a register and returns register in RegNo.
110 bool matchRegisterName(const AsmToken &Tok, MCRegister &RegNo,
111 unsigned &RegKind);
112
113 bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc);
114
115 bool is64Bit() const {
117 }
118
119 bool expandSET(MCInst &Inst, SMLoc IDLoc,
120 SmallVectorImpl<MCInst> &Instructions);
121
122 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
123
124public:
125 SparcAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
126 const MCInstrInfo &MII,
128 : MCTargetAsmParser(Options, sti, MII), Parser(parser) {
129 Parser.addAliasForDirective(".half", ".2byte");
130 Parser.addAliasForDirective(".uahalf", ".2byte");
131 Parser.addAliasForDirective(".word", ".4byte");
132 Parser.addAliasForDirective(".uaword", ".4byte");
133 Parser.addAliasForDirective(".nword", is64Bit() ? ".8byte" : ".4byte");
134 if (is64Bit())
135 Parser.addAliasForDirective(".xword", ".8byte");
136
137 // Initialize the set of available features.
138 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
139 }
140};
141
142} // end anonymous namespace
143
144 static const MCPhysReg IntRegs[32] = {
145 Sparc::G0, Sparc::G1, Sparc::G2, Sparc::G3,
146 Sparc::G4, Sparc::G5, Sparc::G6, Sparc::G7,
147 Sparc::O0, Sparc::O1, Sparc::O2, Sparc::O3,
148 Sparc::O4, Sparc::O5, Sparc::O6, Sparc::O7,
149 Sparc::L0, Sparc::L1, Sparc::L2, Sparc::L3,
150 Sparc::L4, Sparc::L5, Sparc::L6, Sparc::L7,
151 Sparc::I0, Sparc::I1, Sparc::I2, Sparc::I3,
152 Sparc::I4, Sparc::I5, Sparc::I6, Sparc::I7 };
153
154 static const MCPhysReg FloatRegs[32] = {
155 Sparc::F0, Sparc::F1, Sparc::F2, Sparc::F3,
156 Sparc::F4, Sparc::F5, Sparc::F6, Sparc::F7,
157 Sparc::F8, Sparc::F9, Sparc::F10, Sparc::F11,
158 Sparc::F12, Sparc::F13, Sparc::F14, Sparc::F15,
159 Sparc::F16, Sparc::F17, Sparc::F18, Sparc::F19,
160 Sparc::F20, Sparc::F21, Sparc::F22, Sparc::F23,
161 Sparc::F24, Sparc::F25, Sparc::F26, Sparc::F27,
162 Sparc::F28, Sparc::F29, Sparc::F30, Sparc::F31 };
163
164 static const MCPhysReg DoubleRegs[32] = {
165 Sparc::D0, Sparc::D1, Sparc::D2, Sparc::D3,
166 Sparc::D4, Sparc::D5, Sparc::D6, Sparc::D7,
167 Sparc::D8, Sparc::D9, Sparc::D10, Sparc::D11,
168 Sparc::D12, Sparc::D13, Sparc::D14, Sparc::D15,
169 Sparc::D16, Sparc::D17, Sparc::D18, Sparc::D19,
170 Sparc::D20, Sparc::D21, Sparc::D22, Sparc::D23,
171 Sparc::D24, Sparc::D25, Sparc::D26, Sparc::D27,
172 Sparc::D28, Sparc::D29, Sparc::D30, Sparc::D31 };
173
174 static const MCPhysReg QuadFPRegs[32] = {
175 Sparc::Q0, Sparc::Q1, Sparc::Q2, Sparc::Q3,
176 Sparc::Q4, Sparc::Q5, Sparc::Q6, Sparc::Q7,
177 Sparc::Q8, Sparc::Q9, Sparc::Q10, Sparc::Q11,
178 Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 };
179
180 static const MCPhysReg ASRRegs[32] = {
181 SP::Y, SP::ASR1, SP::ASR2, SP::ASR3,
182 SP::ASR4, SP::ASR5, SP::ASR6, SP::ASR7,
183 SP::ASR8, SP::ASR9, SP::ASR10, SP::ASR11,
184 SP::ASR12, SP::ASR13, SP::ASR14, SP::ASR15,
185 SP::ASR16, SP::ASR17, SP::ASR18, SP::ASR19,
186 SP::ASR20, SP::ASR21, SP::ASR22, SP::ASR23,
187 SP::ASR24, SP::ASR25, SP::ASR26, SP::ASR27,
188 SP::ASR28, SP::ASR29, SP::ASR30, SP::ASR31};
189
190 static const MCPhysReg IntPairRegs[] = {
191 Sparc::G0_G1, Sparc::G2_G3, Sparc::G4_G5, Sparc::G6_G7,
192 Sparc::O0_O1, Sparc::O2_O3, Sparc::O4_O5, Sparc::O6_O7,
193 Sparc::L0_L1, Sparc::L2_L3, Sparc::L4_L5, Sparc::L6_L7,
194 Sparc::I0_I1, Sparc::I2_I3, Sparc::I4_I5, Sparc::I6_I7};
195
196 static const MCPhysReg CoprocRegs[32] = {
197 Sparc::C0, Sparc::C1, Sparc::C2, Sparc::C3,
198 Sparc::C4, Sparc::C5, Sparc::C6, Sparc::C7,
199 Sparc::C8, Sparc::C9, Sparc::C10, Sparc::C11,
200 Sparc::C12, Sparc::C13, Sparc::C14, Sparc::C15,
201 Sparc::C16, Sparc::C17, Sparc::C18, Sparc::C19,
202 Sparc::C20, Sparc::C21, Sparc::C22, Sparc::C23,
203 Sparc::C24, Sparc::C25, Sparc::C26, Sparc::C27,
204 Sparc::C28, Sparc::C29, Sparc::C30, Sparc::C31 };
205
206 static const MCPhysReg CoprocPairRegs[] = {
207 Sparc::C0_C1, Sparc::C2_C3, Sparc::C4_C5, Sparc::C6_C7,
208 Sparc::C8_C9, Sparc::C10_C11, Sparc::C12_C13, Sparc::C14_C15,
209 Sparc::C16_C17, Sparc::C18_C19, Sparc::C20_C21, Sparc::C22_C23,
210 Sparc::C24_C25, Sparc::C26_C27, Sparc::C28_C29, Sparc::C30_C31};
211
212namespace {
213
214/// SparcOperand - Instances of this class represent a parsed Sparc machine
215/// instruction.
216class SparcOperand : public MCParsedAsmOperand {
217public:
218 enum RegisterKind {
219 rk_None,
220 rk_IntReg,
221 rk_IntPairReg,
222 rk_FloatReg,
223 rk_DoubleReg,
224 rk_QuadReg,
225 rk_CoprocReg,
226 rk_CoprocPairReg,
227 rk_Special,
228 };
229
230private:
231 enum KindTy {
232 k_Token,
233 k_Register,
234 k_Immediate,
235 k_MemoryReg,
236 k_MemoryImm
237 } Kind;
238
239 SMLoc StartLoc, EndLoc;
240
241 struct Token {
242 const char *Data;
243 unsigned Length;
244 };
245
246 struct RegOp {
247 unsigned RegNum;
248 RegisterKind Kind;
249 };
250
251 struct ImmOp {
252 const MCExpr *Val;
253 };
254
255 struct MemOp {
256 unsigned Base;
257 unsigned OffsetReg;
258 const MCExpr *Off;
259 };
260
261 union {
262 struct Token Tok;
263 struct RegOp Reg;
264 struct ImmOp Imm;
265 struct MemOp Mem;
266 };
267
268public:
269 SparcOperand(KindTy K) : Kind(K) {}
270
271 bool isToken() const override { return Kind == k_Token; }
272 bool isReg() const override { return Kind == k_Register; }
273 bool isImm() const override { return Kind == k_Immediate; }
274 bool isMem() const override { return isMEMrr() || isMEMri(); }
275 bool isMEMrr() const { return Kind == k_MemoryReg; }
276 bool isMEMri() const { return Kind == k_MemoryImm; }
277 bool isMembarTag() const { return Kind == k_Immediate; }
278 bool isTailRelocSym() const { return Kind == k_Immediate; }
279
280 bool isCallTarget() const {
281 if (!isImm())
282 return false;
283
284 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val))
285 return CE->getValue() % 4 == 0;
286
287 return true;
288 }
289
290 bool isShiftAmtImm5() const {
291 if (!isImm())
292 return false;
293
294 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val))
295 return isUInt<5>(CE->getValue());
296
297 return false;
298 }
299
300 bool isShiftAmtImm6() const {
301 if (!isImm())
302 return false;
303
304 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val))
305 return isUInt<6>(CE->getValue());
306
307 return false;
308 }
309
310 bool isIntReg() const {
311 return (Kind == k_Register && Reg.Kind == rk_IntReg);
312 }
313
314 bool isFloatReg() const {
315 return (Kind == k_Register && Reg.Kind == rk_FloatReg);
316 }
317
318 bool isFloatOrDoubleReg() const {
319 return (Kind == k_Register && (Reg.Kind == rk_FloatReg
320 || Reg.Kind == rk_DoubleReg));
321 }
322
323 bool isCoprocReg() const {
324 return (Kind == k_Register && Reg.Kind == rk_CoprocReg);
325 }
326
327 StringRef getToken() const {
328 assert(Kind == k_Token && "Invalid access!");
329 return StringRef(Tok.Data, Tok.Length);
330 }
331
332 unsigned getReg() const override {
333 assert((Kind == k_Register) && "Invalid access!");
334 return Reg.RegNum;
335 }
336
337 const MCExpr *getImm() const {
338 assert((Kind == k_Immediate) && "Invalid access!");
339 return Imm.Val;
340 }
341
342 unsigned getMemBase() const {
343 assert((Kind == k_MemoryReg || Kind == k_MemoryImm) && "Invalid access!");
344 return Mem.Base;
345 }
346
347 unsigned getMemOffsetReg() const {
348 assert((Kind == k_MemoryReg) && "Invalid access!");
349 return Mem.OffsetReg;
350 }
351
352 const MCExpr *getMemOff() const {
353 assert((Kind == k_MemoryImm) && "Invalid access!");
354 return Mem.Off;
355 }
356
357 /// getStartLoc - Get the location of the first token of this operand.
358 SMLoc getStartLoc() const override {
359 return StartLoc;
360 }
361 /// getEndLoc - Get the location of the last token of this operand.
362 SMLoc getEndLoc() const override {
363 return EndLoc;
364 }
365
366 void print(raw_ostream &OS) const override {
367 switch (Kind) {
368 case k_Token: OS << "Token: " << getToken() << "\n"; break;
369 case k_Register: OS << "Reg: #" << getReg() << "\n"; break;
370 case k_Immediate: OS << "Imm: " << getImm() << "\n"; break;
371 case k_MemoryReg: OS << "Mem: " << getMemBase() << "+"
372 << getMemOffsetReg() << "\n"; break;
373 case k_MemoryImm: assert(getMemOff() != nullptr);
374 OS << "Mem: " << getMemBase()
375 << "+" << *getMemOff()
376 << "\n"; break;
377 }
378 }
379
380 void addRegOperands(MCInst &Inst, unsigned N) const {
381 assert(N == 1 && "Invalid number of operands!");
383 }
384
385 void addImmOperands(MCInst &Inst, unsigned N) const {
386 assert(N == 1 && "Invalid number of operands!");
387 const MCExpr *Expr = getImm();
388 addExpr(Inst, Expr);
389 }
390
391 void addShiftAmtImm5Operands(MCInst &Inst, unsigned N) const {
392 assert(N == 1 && "Invalid number of operands!");
393 addExpr(Inst, getImm());
394 }
395 void addShiftAmtImm6Operands(MCInst &Inst, unsigned N) const {
396 assert(N == 1 && "Invalid number of operands!");
397 addExpr(Inst, getImm());
398 }
399
400 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
401 // Add as immediate when possible. Null MCExpr = 0.
402 if (!Expr)
404 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
405 Inst.addOperand(MCOperand::createImm(CE->getValue()));
406 else
408 }
409
410 void addMEMrrOperands(MCInst &Inst, unsigned N) const {
411 assert(N == 2 && "Invalid number of operands!");
412
413 Inst.addOperand(MCOperand::createReg(getMemBase()));
414
415 assert(getMemOffsetReg() != 0 && "Invalid offset");
416 Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));
417 }
418
419 void addMEMriOperands(MCInst &Inst, unsigned N) const {
420 assert(N == 2 && "Invalid number of operands!");
421
422 Inst.addOperand(MCOperand::createReg(getMemBase()));
423
424 const MCExpr *Expr = getMemOff();
425 addExpr(Inst, Expr);
426 }
427
428 void addMembarTagOperands(MCInst &Inst, unsigned N) const {
429 assert(N == 1 && "Invalid number of operands!");
430 const MCExpr *Expr = getImm();
431 addExpr(Inst, Expr);
432 }
433
434 void addCallTargetOperands(MCInst &Inst, unsigned N) const {
435 assert(N == 1 && "Invalid number of operands!");
436 addExpr(Inst, getImm());
437 }
438
439 void addTailRelocSymOperands(MCInst &Inst, unsigned N) const {
440 assert(N == 1 && "Invalid number of operands!");
441 addExpr(Inst, getImm());
442 }
443
444 static std::unique_ptr<SparcOperand> CreateToken(StringRef Str, SMLoc S) {
445 auto Op = std::make_unique<SparcOperand>(k_Token);
446 Op->Tok.Data = Str.data();
447 Op->Tok.Length = Str.size();
448 Op->StartLoc = S;
449 Op->EndLoc = S;
450 return Op;
451 }
452
453 static std::unique_ptr<SparcOperand> CreateReg(unsigned RegNum, unsigned Kind,
454 SMLoc S, SMLoc E) {
455 auto Op = std::make_unique<SparcOperand>(k_Register);
456 Op->Reg.RegNum = RegNum;
457 Op->Reg.Kind = (SparcOperand::RegisterKind)Kind;
458 Op->StartLoc = S;
459 Op->EndLoc = E;
460 return Op;
461 }
462
463 static std::unique_ptr<SparcOperand> CreateImm(const MCExpr *Val, SMLoc S,
464 SMLoc E) {
465 auto Op = std::make_unique<SparcOperand>(k_Immediate);
466 Op->Imm.Val = Val;
467 Op->StartLoc = S;
468 Op->EndLoc = E;
469 return Op;
470 }
471
472 static bool MorphToIntPairReg(SparcOperand &Op) {
473 unsigned Reg = Op.getReg();
474 assert(Op.Reg.Kind == rk_IntReg);
475 unsigned regIdx = 32;
476 if (Reg >= Sparc::G0 && Reg <= Sparc::G7)
477 regIdx = Reg - Sparc::G0;
478 else if (Reg >= Sparc::O0 && Reg <= Sparc::O7)
479 regIdx = Reg - Sparc::O0 + 8;
480 else if (Reg >= Sparc::L0 && Reg <= Sparc::L7)
481 regIdx = Reg - Sparc::L0 + 16;
482 else if (Reg >= Sparc::I0 && Reg <= Sparc::I7)
483 regIdx = Reg - Sparc::I0 + 24;
484 if (regIdx % 2 || regIdx > 31)
485 return false;
486 Op.Reg.RegNum = IntPairRegs[regIdx / 2];
487 Op.Reg.Kind = rk_IntPairReg;
488 return true;
489 }
490
491 static bool MorphToDoubleReg(SparcOperand &Op) {
492 unsigned Reg = Op.getReg();
493 assert(Op.Reg.Kind == rk_FloatReg);
494 unsigned regIdx = Reg - Sparc::F0;
495 if (regIdx % 2 || regIdx > 31)
496 return false;
497 Op.Reg.RegNum = DoubleRegs[regIdx / 2];
498 Op.Reg.Kind = rk_DoubleReg;
499 return true;
500 }
501
502 static bool MorphToQuadReg(SparcOperand &Op) {
503 unsigned Reg = Op.getReg();
504 unsigned regIdx = 0;
505 switch (Op.Reg.Kind) {
506 default: llvm_unreachable("Unexpected register kind!");
507 case rk_FloatReg:
508 regIdx = Reg - Sparc::F0;
509 if (regIdx % 4 || regIdx > 31)
510 return false;
511 Reg = QuadFPRegs[regIdx / 4];
512 break;
513 case rk_DoubleReg:
514 regIdx = Reg - Sparc::D0;
515 if (regIdx % 2 || regIdx > 31)
516 return false;
517 Reg = QuadFPRegs[regIdx / 2];
518 break;
519 }
520 Op.Reg.RegNum = Reg;
521 Op.Reg.Kind = rk_QuadReg;
522 return true;
523 }
524
525 static bool MorphToCoprocPairReg(SparcOperand &Op) {
526 unsigned Reg = Op.getReg();
527 assert(Op.Reg.Kind == rk_CoprocReg);
528 unsigned regIdx = 32;
529 if (Reg >= Sparc::C0 && Reg <= Sparc::C31)
530 regIdx = Reg - Sparc::C0;
531 if (regIdx % 2 || regIdx > 31)
532 return false;
533 Op.Reg.RegNum = CoprocPairRegs[regIdx / 2];
534 Op.Reg.Kind = rk_CoprocPairReg;
535 return true;
536 }
537
538 static std::unique_ptr<SparcOperand>
539 MorphToMEMrr(unsigned Base, std::unique_ptr<SparcOperand> Op) {
540 unsigned offsetReg = Op->getReg();
541 Op->Kind = k_MemoryReg;
542 Op->Mem.Base = Base;
543 Op->Mem.OffsetReg = offsetReg;
544 Op->Mem.Off = nullptr;
545 return Op;
546 }
547
548 static std::unique_ptr<SparcOperand>
549 CreateMEMr(unsigned Base, SMLoc S, SMLoc E) {
550 auto Op = std::make_unique<SparcOperand>(k_MemoryReg);
551 Op->Mem.Base = Base;
552 Op->Mem.OffsetReg = Sparc::G0; // always 0
553 Op->Mem.Off = nullptr;
554 Op->StartLoc = S;
555 Op->EndLoc = E;
556 return Op;
557 }
558
559 static std::unique_ptr<SparcOperand>
560 MorphToMEMri(unsigned Base, std::unique_ptr<SparcOperand> Op) {
561 const MCExpr *Imm = Op->getImm();
562 Op->Kind = k_MemoryImm;
563 Op->Mem.Base = Base;
564 Op->Mem.OffsetReg = 0;
565 Op->Mem.Off = Imm;
566 return Op;
567 }
568};
569
570} // end anonymous namespace
571
572bool SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc,
573 SmallVectorImpl<MCInst> &Instructions) {
574 MCOperand MCRegOp = Inst.getOperand(0);
575 MCOperand MCValOp = Inst.getOperand(1);
576 assert(MCRegOp.isReg());
577 assert(MCValOp.isImm() || MCValOp.isExpr());
578
579 // the imm operand can be either an expression or an immediate.
580 bool IsImm = Inst.getOperand(1).isImm();
581 int64_t RawImmValue = IsImm ? MCValOp.getImm() : 0;
582
583 // Allow either a signed or unsigned 32-bit immediate.
584 if (RawImmValue < -2147483648LL || RawImmValue > 4294967295LL) {
585 return Error(IDLoc,
586 "set: argument must be between -2147483648 and 4294967295");
587 }
588
589 // If the value was expressed as a large unsigned number, that's ok.
590 // We want to see if it "looks like" a small signed number.
591 int32_t ImmValue = RawImmValue;
592 // For 'set' you can't use 'or' with a negative operand on V9 because
593 // that would splat the sign bit across the upper half of the destination
594 // register, whereas 'set' is defined to zero the high 32 bits.
595 bool IsEffectivelyImm13 =
596 IsImm && ((is64Bit() ? 0 : -4096) <= ImmValue && ImmValue < 4096);
597 const MCExpr *ValExpr;
598 if (IsImm)
599 ValExpr = MCConstantExpr::create(ImmValue, getContext());
600 else
601 ValExpr = MCValOp.getExpr();
602
603 MCOperand PrevReg = MCOperand::createReg(Sparc::G0);
604
605 // If not just a signed imm13 value, then either we use a 'sethi' with a
606 // following 'or', or a 'sethi' by itself if there are no more 1 bits.
607 // In either case, start with the 'sethi'.
608 if (!IsEffectivelyImm13) {
609 MCInst TmpInst;
610 const MCExpr *Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_HI, ValExpr);
611 TmpInst.setLoc(IDLoc);
612 TmpInst.setOpcode(SP::SETHIi);
613 TmpInst.addOperand(MCRegOp);
614 TmpInst.addOperand(MCOperand::createExpr(Expr));
615 Instructions.push_back(TmpInst);
616 PrevReg = MCRegOp;
617 }
618
619 // The low bits require touching in 3 cases:
620 // * A non-immediate value will always require both instructions.
621 // * An effectively imm13 value needs only an 'or' instruction.
622 // * Otherwise, an immediate that is not effectively imm13 requires the
623 // 'or' only if bits remain after clearing the 22 bits that 'sethi' set.
624 // If the low bits are known zeros, there's nothing to do.
625 // In the second case, and only in that case, must we NOT clear
626 // bits of the immediate value via the %lo() assembler function.
627 // Note also, the 'or' instruction doesn't mind a large value in the case
628 // where the operand to 'set' was 0xFFFFFzzz - it does exactly what you mean.
629 if (!IsImm || IsEffectivelyImm13 || (ImmValue & 0x3ff)) {
630 MCInst TmpInst;
631 const MCExpr *Expr;
632 if (IsEffectivelyImm13)
633 Expr = ValExpr;
634 else
635 Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_LO, ValExpr);
636 TmpInst.setLoc(IDLoc);
637 TmpInst.setOpcode(SP::ORri);
638 TmpInst.addOperand(MCRegOp);
639 TmpInst.addOperand(PrevReg);
640 TmpInst.addOperand(MCOperand::createExpr(Expr));
641 Instructions.push_back(TmpInst);
642 }
643 return false;
644}
645
646bool SparcAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
648 MCStreamer &Out,
650 bool MatchingInlineAsm) {
651 MCInst Inst;
653 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
654 MatchingInlineAsm);
655 switch (MatchResult) {
656 case Match_Success: {
657 switch (Inst.getOpcode()) {
658 default:
659 Inst.setLoc(IDLoc);
660 Instructions.push_back(Inst);
661 break;
662 case SP::SET:
663 if (expandSET(Inst, IDLoc, Instructions))
664 return true;
665 break;
666 }
667
668 for (const MCInst &I : Instructions) {
669 Out.emitInstruction(I, getSTI());
670 }
671 return false;
672 }
673
674 case Match_MissingFeature:
675 return Error(IDLoc,
676 "instruction requires a CPU feature not currently enabled");
677
678 case Match_InvalidOperand: {
679 SMLoc ErrorLoc = IDLoc;
680 if (ErrorInfo != ~0ULL) {
681 if (ErrorInfo >= Operands.size())
682 return Error(IDLoc, "too few operands for instruction");
683
684 ErrorLoc = ((SparcOperand &)*Operands[ErrorInfo]).getStartLoc();
685 if (ErrorLoc == SMLoc())
686 ErrorLoc = IDLoc;
687 }
688
689 return Error(ErrorLoc, "invalid operand for instruction");
690 }
691 case Match_MnemonicFail:
692 return Error(IDLoc, "invalid instruction mnemonic");
693 }
694 llvm_unreachable("Implement any new match types added!");
695}
696
697bool SparcAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
698 SMLoc &EndLoc) {
699 if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
700 return Error(StartLoc, "invalid register name");
701 return false;
702}
703
704OperandMatchResultTy SparcAsmParser::tryParseRegister(MCRegister &RegNo,
705 SMLoc &StartLoc,
706 SMLoc &EndLoc) {
707 const AsmToken &Tok = Parser.getTok();
708 StartLoc = Tok.getLoc();
709 EndLoc = Tok.getEndLoc();
710 RegNo = 0;
711 if (getLexer().getKind() != AsmToken::Percent)
713 Parser.Lex();
714 unsigned regKind = SparcOperand::rk_None;
715 if (matchRegisterName(Tok, RegNo, regKind)) {
716 Parser.Lex();
718 }
719
720 getLexer().UnLex(Tok);
722}
723
724static void applyMnemonicAliases(StringRef &Mnemonic,
725 const FeatureBitset &Features,
726 unsigned VariantID);
727
728bool SparcAsmParser::ParseInstruction(ParseInstructionInfo &Info,
729 StringRef Name, SMLoc NameLoc,
731
732 // First operand in MCInst is instruction mnemonic.
733 Operands.push_back(SparcOperand::CreateToken(Name, NameLoc));
734
735 // apply mnemonic aliases, if any, so that we can parse operands correctly.
736 applyMnemonicAliases(Name, getAvailableFeatures(), 0);
737
738 if (getLexer().isNot(AsmToken::EndOfStatement)) {
739 // Read the first operand.
740 if (getLexer().is(AsmToken::Comma)) {
741 if (parseBranchModifiers(Operands) != MatchOperand_Success) {
742 SMLoc Loc = getLexer().getLoc();
743 return Error(Loc, "unexpected token");
744 }
745 }
746 if (parseOperand(Operands, Name) != MatchOperand_Success) {
747 SMLoc Loc = getLexer().getLoc();
748 return Error(Loc, "unexpected token");
749 }
750
751 while (getLexer().is(AsmToken::Comma) || getLexer().is(AsmToken::Plus)) {
752 if (getLexer().is(AsmToken::Plus)) {
753 // Plus tokens are significant in software_traps (p83, sparcv8.pdf). We must capture them.
754 Operands.push_back(SparcOperand::CreateToken("+", Parser.getTok().getLoc()));
755 }
756 Parser.Lex(); // Eat the comma or plus.
757 // Parse and remember the operand.
758 if (parseOperand(Operands, Name) != MatchOperand_Success) {
759 SMLoc Loc = getLexer().getLoc();
760 return Error(Loc, "unexpected token");
761 }
762 }
763 }
764 if (getLexer().isNot(AsmToken::EndOfStatement)) {
765 SMLoc Loc = getLexer().getLoc();
766 return Error(Loc, "unexpected token");
767 }
768 Parser.Lex(); // Consume the EndOfStatement.
769 return false;
770}
771
772bool SparcAsmParser::
773ParseDirective(AsmToken DirectiveID)
774{
775 StringRef IDVal = DirectiveID.getString();
776
777 if (IDVal == ".register") {
778 // For now, ignore .register directive.
779 Parser.eatToEndOfStatement();
780 return false;
781 }
782 if (IDVal == ".proc") {
783 // For compatibility, ignore this directive.
784 // (It's supposed to be an "optimization" in the Sun assembler)
785 Parser.eatToEndOfStatement();
786 return false;
787 }
788
789 // Let the MC layer to handle other directives.
790 return true;
791}
792
794SparcAsmParser::parseMEMOperand(OperandVector &Operands) {
795 SMLoc S, E;
796
797 std::unique_ptr<SparcOperand> LHS;
798 if (parseSparcAsmOperand(LHS) != MatchOperand_Success)
800
801 // Single immediate operand
802 if (LHS->isImm()) {
803 Operands.push_back(SparcOperand::MorphToMEMri(Sparc::G0, std::move(LHS)));
805 }
806
807 if (!LHS->isIntReg()) {
808 Error(LHS->getStartLoc(), "invalid register kind for this operand");
810 }
811
812 AsmToken Tok = getLexer().getTok();
813 // The plus token may be followed by a register or an immediate value, the
814 // minus one is always interpreted as sign for the immediate value
815 if (Tok.is(AsmToken::Plus) || Tok.is(AsmToken::Minus)) {
817
818 std::unique_ptr<SparcOperand> RHS;
819 if (parseSparcAsmOperand(RHS) != MatchOperand_Success)
821
822 if (RHS->isReg() && !RHS->isIntReg()) {
823 Error(RHS->getStartLoc(), "invalid register kind for this operand");
825 }
826
827 Operands.push_back(
828 RHS->isImm()
829 ? SparcOperand::MorphToMEMri(LHS->getReg(), std::move(RHS))
830 : SparcOperand::MorphToMEMrr(LHS->getReg(), std::move(RHS)));
831
833 }
834
835 Operands.push_back(SparcOperand::CreateMEMr(LHS->getReg(), S, E));
837}
838
839template <unsigned N>
840OperandMatchResultTy SparcAsmParser::parseShiftAmtImm(OperandVector &Operands) {
841 SMLoc S = Parser.getTok().getLoc();
843
844 // This is a register, not an immediate
845 if (getLexer().getKind() == AsmToken::Percent)
847
848 const MCExpr *Expr;
849 if (getParser().parseExpression(Expr))
851
852 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
853 if (!CE) {
854 Error(S, "constant expression expected");
856 }
857
858 if (!isUInt<N>(CE->getValue())) {
859 Error(S, "immediate shift value out of range");
861 }
862
863 Operands.push_back(SparcOperand::CreateImm(Expr, S, E));
865}
866
867template <SparcAsmParser::TailRelocKind Kind>
869SparcAsmParser::parseTailRelocSym(OperandVector &Operands) {
870 SMLoc S = getLoc();
872
873 auto MatchesKind = [](SparcMCExpr::VariantKind VK) -> bool {
874 switch (Kind) {
875 case TailRelocKind::Load_GOT:
876 // Non-TLS relocations on ld (or ldx).
877 // ld [%rr + %rr], %rr, %rel(sym)
879 case TailRelocKind::Add_TLS:
880 // TLS relocations on add.
881 // add %rr, %rr, %rr, %rel(sym)
882 switch (VK) {
887 return true;
888 default:
889 return false;
890 }
891 case TailRelocKind::Load_TLS:
892 // TLS relocations on ld (or ldx).
893 // ld[x] %addr, %rr, %rel(sym)
894 switch (VK) {
897 return true;
898 default:
899 return false;
900 }
901 case TailRelocKind::Call_TLS:
902 // TLS relocations on call.
903 // call sym, %rel(sym)
904 switch (VK) {
907 return true;
908 default:
909 return false;
910 }
911 }
912 llvm_unreachable("Unhandled SparcAsmParser::TailRelocKind enum");
913 };
914
915 if (getLexer().getKind() != AsmToken::Percent) {
916 Error(getLoc(), "expected '%' for operand modifier");
918 }
919
920 const AsmToken Tok = Parser.getTok();
921 getParser().Lex(); // Eat '%'
922
923 if (getLexer().getKind() != AsmToken::Identifier) {
924 Error(getLoc(), "expected valid identifier for operand modifier");
926 }
927
928 StringRef Name = getParser().getTok().getIdentifier();
930 if (VK == SparcMCExpr::VK_Sparc_None) {
931 Error(getLoc(), "invalid operand modifier");
933 }
934
935 if (!MatchesKind(VK)) {
936 // Did not match the specified set of relocation types, put '%' back.
937 getLexer().UnLex(Tok);
939 }
940
941 Parser.Lex(); // Eat the identifier.
942 if (getLexer().getKind() != AsmToken::LParen) {
943 Error(getLoc(), "expected '('");
945 }
946
947 getParser().Lex(); // Eat '('
948 const MCExpr *SubExpr;
949 if (getParser().parseParenExpression(SubExpr, E)) {
951 }
952
953 const MCExpr *Val = adjustPICRelocation(VK, SubExpr);
954 Operands.push_back(SparcOperand::CreateImm(Val, S, E));
956}
957
958OperandMatchResultTy SparcAsmParser::parseMembarTag(OperandVector &Operands) {
959 SMLoc S = Parser.getTok().getLoc();
960 const MCExpr *EVal;
961 int64_t ImmVal = 0;
962
963 std::unique_ptr<SparcOperand> Mask;
964 if (parseSparcAsmOperand(Mask) == MatchOperand_Success) {
965 if (!Mask->isImm() || !Mask->getImm()->evaluateAsAbsolute(ImmVal) ||
966 ImmVal < 0 || ImmVal > 127) {
967 Error(S, "invalid membar mask number");
969 }
970 }
971
972 while (getLexer().getKind() == AsmToken::Hash) {
973 SMLoc TagStart = getLexer().getLoc();
974 Parser.Lex(); // Eat the '#'.
975 unsigned MaskVal = StringSwitch<unsigned>(Parser.getTok().getString())
976 .Case("LoadLoad", 0x1)
977 .Case("StoreLoad", 0x2)
978 .Case("LoadStore", 0x4)
979 .Case("StoreStore", 0x8)
980 .Case("Lookaside", 0x10)
981 .Case("MemIssue", 0x20)
982 .Case("Sync", 0x40)
983 .Default(0);
984
985 Parser.Lex(); // Eat the identifier token.
986
987 if (!MaskVal) {
988 Error(TagStart, "unknown membar tag");
990 }
991
992 ImmVal |= MaskVal;
993
994 if (getLexer().getKind() == AsmToken::Pipe)
995 Parser.Lex(); // Eat the '|'.
996 }
997
998 EVal = MCConstantExpr::create(ImmVal, getContext());
1000 Operands.push_back(SparcOperand::CreateImm(EVal, S, E));
1001 return MatchOperand_Success;
1002}
1003
1004OperandMatchResultTy SparcAsmParser::parseCallTarget(OperandVector &Operands) {
1005 SMLoc S = Parser.getTok().getLoc();
1007
1008 switch (getLexer().getKind()) {
1009 default:
1010 return MatchOperand_NoMatch;
1011 case AsmToken::LParen:
1012 case AsmToken::Integer:
1014 case AsmToken::Dot:
1015 break;
1016 }
1017
1018 const MCExpr *DestValue;
1019 if (getParser().parseExpression(DestValue))
1020 return MatchOperand_NoMatch;
1021
1022 bool IsPic = getContext().getObjectFileInfo()->isPositionIndependent();
1025
1026 const MCExpr *DestExpr = SparcMCExpr::create(Kind, DestValue, getContext());
1027 Operands.push_back(SparcOperand::CreateImm(DestExpr, S, E));
1028 return MatchOperand_Success;
1029}
1030
1032SparcAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1033
1034 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1035
1036 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1037 // there was a match, but an error occurred, in which case, just return that
1038 // the operand parsing failed.
1039 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
1040 return ResTy;
1041
1042 if (getLexer().is(AsmToken::LBrac)) {
1043 // Memory operand
1044 Operands.push_back(SparcOperand::CreateToken("[",
1045 Parser.getTok().getLoc()));
1046 Parser.Lex(); // Eat the [
1047
1048 if (Mnemonic == "cas" || Mnemonic == "casx" || Mnemonic == "casa") {
1049 SMLoc S = Parser.getTok().getLoc();
1050 if (getLexer().getKind() != AsmToken::Percent)
1051 return MatchOperand_NoMatch;
1052 Parser.Lex(); // eat %
1053
1054 MCRegister RegNo;
1055 unsigned RegKind;
1056 if (!matchRegisterName(Parser.getTok(), RegNo, RegKind))
1057 return MatchOperand_NoMatch;
1058
1059 Parser.Lex(); // Eat the identifier token.
1061 Operands.push_back(SparcOperand::CreateReg(RegNo, RegKind, S, E));
1062 ResTy = MatchOperand_Success;
1063 } else {
1064 ResTy = parseMEMOperand(Operands);
1065 }
1066
1067 if (ResTy != MatchOperand_Success)
1068 return ResTy;
1069
1070 if (!getLexer().is(AsmToken::RBrac))
1072
1073 Operands.push_back(SparcOperand::CreateToken("]",
1074 Parser.getTok().getLoc()));
1075 Parser.Lex(); // Eat the ]
1076
1077 // Parse an optional address-space identifier after the address.
1078 if (getLexer().is(AsmToken::Integer)) {
1079 std::unique_ptr<SparcOperand> Op;
1080 ResTy = parseSparcAsmOperand(Op, false);
1081 if (ResTy != MatchOperand_Success || !Op)
1083 Operands.push_back(std::move(Op));
1084 }
1085 return MatchOperand_Success;
1086 }
1087
1088 std::unique_ptr<SparcOperand> Op;
1089
1090 ResTy = parseSparcAsmOperand(Op, (Mnemonic == "call"));
1091 if (ResTy != MatchOperand_Success || !Op)
1093
1094 // Push the parsed operand into the list of operands
1095 Operands.push_back(std::move(Op));
1096
1097 return MatchOperand_Success;
1098}
1099
1101SparcAsmParser::parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Op,
1102 bool isCall) {
1103 SMLoc S = Parser.getTok().getLoc();
1105 const MCExpr *EVal;
1106
1107 Op = nullptr;
1108 switch (getLexer().getKind()) {
1109 default: break;
1110
1111 case AsmToken::Percent: {
1112 Parser.Lex(); // Eat the '%'.
1113 MCRegister RegNo;
1114 unsigned RegKind;
1115 if (matchRegisterName(Parser.getTok(), RegNo, RegKind)) {
1116 StringRef name = Parser.getTok().getString();
1117 Parser.Lex(); // Eat the identifier token.
1118 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1119 switch (RegNo) {
1120 default:
1121 Op = SparcOperand::CreateReg(RegNo, RegKind, S, E);
1122 break;
1123 case Sparc::PSR:
1124 Op = SparcOperand::CreateToken("%psr", S);
1125 break;
1126 case Sparc::FSR:
1127 Op = SparcOperand::CreateToken("%fsr", S);
1128 break;
1129 case Sparc::FQ:
1130 Op = SparcOperand::CreateToken("%fq", S);
1131 break;
1132 case Sparc::CPSR:
1133 Op = SparcOperand::CreateToken("%csr", S);
1134 break;
1135 case Sparc::CPQ:
1136 Op = SparcOperand::CreateToken("%cq", S);
1137 break;
1138 case Sparc::WIM:
1139 Op = SparcOperand::CreateToken("%wim", S);
1140 break;
1141 case Sparc::TBR:
1142 Op = SparcOperand::CreateToken("%tbr", S);
1143 break;
1144 case Sparc::PC:
1145 Op = SparcOperand::CreateToken("%pc", S);
1146 break;
1147 case Sparc::ICC:
1148 if (name == "xcc")
1149 Op = SparcOperand::CreateToken("%xcc", S);
1150 else
1151 Op = SparcOperand::CreateToken("%icc", S);
1152 break;
1153 }
1154 break;
1155 }
1156 if (matchSparcAsmModifiers(EVal, E)) {
1157 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1158 Op = SparcOperand::CreateImm(EVal, S, E);
1159 }
1160 break;
1161 }
1162
1163 case AsmToken::Plus:
1164 case AsmToken::Minus:
1165 case AsmToken::Integer:
1166 case AsmToken::LParen:
1167 case AsmToken::Dot:
1169 if (getParser().parseExpression(EVal, E))
1170 break;
1171
1172 int64_t Res;
1173 if (!EVal->evaluateAsAbsolute(Res)) {
1175
1176 if (getContext().getObjectFileInfo()->isPositionIndependent()) {
1177 if (isCall)
1179 else
1181 }
1182 EVal = SparcMCExpr::create(Kind, EVal, getContext());
1183 }
1184 Op = SparcOperand::CreateImm(EVal, S, E);
1185 break;
1186 }
1188}
1189
1191SparcAsmParser::parseBranchModifiers(OperandVector &Operands) {
1192 // parse (,a|,pn|,pt)+
1193
1194 while (getLexer().is(AsmToken::Comma)) {
1195 Parser.Lex(); // Eat the comma
1196
1197 if (!getLexer().is(AsmToken::Identifier))
1199 StringRef modName = Parser.getTok().getString();
1200 if (modName == "a" || modName == "pn" || modName == "pt") {
1201 Operands.push_back(SparcOperand::CreateToken(modName,
1202 Parser.getTok().getLoc()));
1203 Parser.Lex(); // eat the identifier.
1204 }
1205 }
1206 return MatchOperand_Success;
1207}
1208
1209bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, MCRegister &RegNo,
1210 unsigned &RegKind) {
1211 int64_t intVal = 0;
1212 RegNo = 0;
1213 RegKind = SparcOperand::rk_None;
1214 if (Tok.is(AsmToken::Identifier)) {
1215 StringRef name = Tok.getString();
1216
1217 // %fp
1218 if (name.equals("fp")) {
1219 RegNo = Sparc::I6;
1220 RegKind = SparcOperand::rk_IntReg;
1221 return true;
1222 }
1223 // %sp
1224 if (name.equals("sp")) {
1225 RegNo = Sparc::O6;
1226 RegKind = SparcOperand::rk_IntReg;
1227 return true;
1228 }
1229
1230 if (name.equals("y")) {
1231 RegNo = Sparc::Y;
1232 RegKind = SparcOperand::rk_Special;
1233 return true;
1234 }
1235
1236 if (name.substr(0, 3).equals_insensitive("asr") &&
1237 !name.substr(3).getAsInteger(10, intVal) && intVal > 0 && intVal < 32) {
1238 RegNo = ASRRegs[intVal];
1239 RegKind = SparcOperand::rk_Special;
1240 return true;
1241 }
1242
1243 // %fprs is an alias of %asr6.
1244 if (name.equals("fprs")) {
1245 RegNo = ASRRegs[6];
1246 RegKind = SparcOperand::rk_Special;
1247 return true;
1248 }
1249
1250 if (name.equals("icc")) {
1251 RegNo = Sparc::ICC;
1252 RegKind = SparcOperand::rk_Special;
1253 return true;
1254 }
1255
1256 if (name.equals("psr")) {
1257 RegNo = Sparc::PSR;
1258 RegKind = SparcOperand::rk_Special;
1259 return true;
1260 }
1261
1262 if (name.equals("fsr")) {
1263 RegNo = Sparc::FSR;
1264 RegKind = SparcOperand::rk_Special;
1265 return true;
1266 }
1267
1268 if (name.equals("fq")) {
1269 RegNo = Sparc::FQ;
1270 RegKind = SparcOperand::rk_Special;
1271 return true;
1272 }
1273
1274 if (name.equals("csr")) {
1275 RegNo = Sparc::CPSR;
1276 RegKind = SparcOperand::rk_Special;
1277 return true;
1278 }
1279
1280 if (name.equals("cq")) {
1281 RegNo = Sparc::CPQ;
1282 RegKind = SparcOperand::rk_Special;
1283 return true;
1284 }
1285
1286 if (name.equals("wim")) {
1287 RegNo = Sparc::WIM;
1288 RegKind = SparcOperand::rk_Special;
1289 return true;
1290 }
1291
1292 if (name.equals("tbr")) {
1293 RegNo = Sparc::TBR;
1294 RegKind = SparcOperand::rk_Special;
1295 return true;
1296 }
1297
1298 if (name.equals("xcc")) {
1299 // FIXME:: check 64bit.
1300 RegNo = Sparc::ICC;
1301 RegKind = SparcOperand::rk_Special;
1302 return true;
1303 }
1304
1305 // %fcc0 - %fcc3
1306 if (name.substr(0, 3).equals_insensitive("fcc") &&
1307 !name.substr(3).getAsInteger(10, intVal) && intVal < 4) {
1308 // FIXME: check 64bit and handle %fcc1 - %fcc3
1309 RegNo = Sparc::FCC0 + intVal;
1310 RegKind = SparcOperand::rk_Special;
1311 return true;
1312 }
1313
1314 // %g0 - %g7
1315 if (name.substr(0, 1).equals_insensitive("g") &&
1316 !name.substr(1).getAsInteger(10, intVal) && intVal < 8) {
1317 RegNo = IntRegs[intVal];
1318 RegKind = SparcOperand::rk_IntReg;
1319 return true;
1320 }
1321 // %o0 - %o7
1322 if (name.substr(0, 1).equals_insensitive("o") &&
1323 !name.substr(1).getAsInteger(10, intVal) && intVal < 8) {
1324 RegNo = IntRegs[8 + intVal];
1325 RegKind = SparcOperand::rk_IntReg;
1326 return true;
1327 }
1328 if (name.substr(0, 1).equals_insensitive("l") &&
1329 !name.substr(1).getAsInteger(10, intVal) && intVal < 8) {
1330 RegNo = IntRegs[16 + intVal];
1331 RegKind = SparcOperand::rk_IntReg;
1332 return true;
1333 }
1334 if (name.substr(0, 1).equals_insensitive("i") &&
1335 !name.substr(1).getAsInteger(10, intVal) && intVal < 8) {
1336 RegNo = IntRegs[24 + intVal];
1337 RegKind = SparcOperand::rk_IntReg;
1338 return true;
1339 }
1340 // %f0 - %f31
1341 if (name.substr(0, 1).equals_insensitive("f") &&
1342 !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 32) {
1343 RegNo = FloatRegs[intVal];
1344 RegKind = SparcOperand::rk_FloatReg;
1345 return true;
1346 }
1347 // %f32 - %f62
1348 if (name.substr(0, 1).equals_insensitive("f") &&
1349 !name.substr(1, 2).getAsInteger(10, intVal) && intVal >= 32 &&
1350 intVal <= 62 && (intVal % 2 == 0)) {
1351 // FIXME: Check V9
1352 RegNo = DoubleRegs[intVal/2];
1353 RegKind = SparcOperand::rk_DoubleReg;
1354 return true;
1355 }
1356
1357 // %r0 - %r31
1358 if (name.substr(0, 1).equals_insensitive("r") &&
1359 !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 31) {
1360 RegNo = IntRegs[intVal];
1361 RegKind = SparcOperand::rk_IntReg;
1362 return true;
1363 }
1364
1365 // %c0 - %c31
1366 if (name.substr(0, 1).equals_insensitive("c") &&
1367 !name.substr(1).getAsInteger(10, intVal) && intVal < 32) {
1368 RegNo = CoprocRegs[intVal];
1369 RegKind = SparcOperand::rk_CoprocReg;
1370 return true;
1371 }
1372
1373 if (name.equals("tpc")) {
1374 RegNo = Sparc::TPC;
1375 RegKind = SparcOperand::rk_Special;
1376 return true;
1377 }
1378 if (name.equals("tnpc")) {
1379 RegNo = Sparc::TNPC;
1380 RegKind = SparcOperand::rk_Special;
1381 return true;
1382 }
1383 if (name.equals("tstate")) {
1384 RegNo = Sparc::TSTATE;
1385 RegKind = SparcOperand::rk_Special;
1386 return true;
1387 }
1388 if (name.equals("tt")) {
1389 RegNo = Sparc::TT;
1390 RegKind = SparcOperand::rk_Special;
1391 return true;
1392 }
1393 if (name.equals("tick")) {
1394 RegNo = Sparc::TICK;
1395 RegKind = SparcOperand::rk_Special;
1396 return true;
1397 }
1398 if (name.equals("tba")) {
1399 RegNo = Sparc::TBA;
1400 RegKind = SparcOperand::rk_Special;
1401 return true;
1402 }
1403 if (name.equals("pstate")) {
1404 RegNo = Sparc::PSTATE;
1405 RegKind = SparcOperand::rk_Special;
1406 return true;
1407 }
1408 if (name.equals("tl")) {
1409 RegNo = Sparc::TL;
1410 RegKind = SparcOperand::rk_Special;
1411 return true;
1412 }
1413 if (name.equals("pil")) {
1414 RegNo = Sparc::PIL;
1415 RegKind = SparcOperand::rk_Special;
1416 return true;
1417 }
1418 if (name.equals("cwp")) {
1419 RegNo = Sparc::CWP;
1420 RegKind = SparcOperand::rk_Special;
1421 return true;
1422 }
1423 if (name.equals("cansave")) {
1424 RegNo = Sparc::CANSAVE;
1425 RegKind = SparcOperand::rk_Special;
1426 return true;
1427 }
1428 if (name.equals("canrestore")) {
1429 RegNo = Sparc::CANRESTORE;
1430 RegKind = SparcOperand::rk_Special;
1431 return true;
1432 }
1433 if (name.equals("cleanwin")) {
1434 RegNo = Sparc::CLEANWIN;
1435 RegKind = SparcOperand::rk_Special;
1436 return true;
1437 }
1438 if (name.equals("otherwin")) {
1439 RegNo = Sparc::OTHERWIN;
1440 RegKind = SparcOperand::rk_Special;
1441 return true;
1442 }
1443 if (name.equals("wstate")) {
1444 RegNo = Sparc::WSTATE;
1445 RegKind = SparcOperand::rk_Special;
1446 return true;
1447 }
1448 if (name.equals("pc")) {
1449 RegNo = Sparc::PC;
1450 RegKind = SparcOperand::rk_Special;
1451 return true;
1452 }
1453 }
1454 return false;
1455}
1456
1457// Determine if an expression contains a reference to the symbol
1458// "_GLOBAL_OFFSET_TABLE_".
1459static bool hasGOTReference(const MCExpr *Expr) {
1460 switch (Expr->getKind()) {
1461 case MCExpr::Target:
1462 if (const SparcMCExpr *SE = dyn_cast<SparcMCExpr>(Expr))
1463 return hasGOTReference(SE->getSubExpr());
1464 break;
1465
1466 case MCExpr::Constant:
1467 break;
1468
1469 case MCExpr::Binary: {
1470 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
1471 return hasGOTReference(BE->getLHS()) || hasGOTReference(BE->getRHS());
1472 }
1473
1474 case MCExpr::SymbolRef: {
1475 const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
1476 return (SymRef.getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_");
1477 }
1478
1479 case MCExpr::Unary:
1480 return hasGOTReference(cast<MCUnaryExpr>(Expr)->getSubExpr());
1481 }
1482 return false;
1483}
1484
1485const SparcMCExpr *
1486SparcAsmParser::adjustPICRelocation(SparcMCExpr::VariantKind VK,
1487 const MCExpr *subExpr) {
1488 // When in PIC mode, "%lo(...)" and "%hi(...)" behave differently.
1489 // If the expression refers contains _GLOBAL_OFFSET_TABLE, it is
1490 // actually a %pc10 or %pc22 relocation. Otherwise, they are interpreted
1491 // as %got10 or %got22 relocation.
1492
1493 if (getContext().getObjectFileInfo()->isPositionIndependent()) {
1494 switch(VK) {
1495 default: break;
1499 break;
1503 break;
1504 }
1505 }
1506
1507 return SparcMCExpr::create(VK, subExpr, getContext());
1508}
1509
1510bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
1511 SMLoc &EndLoc) {
1512 AsmToken Tok = Parser.getTok();
1513 if (!Tok.is(AsmToken::Identifier))
1514 return false;
1515
1516 StringRef name = Tok.getString();
1517
1519 switch (VK) {
1521 Error(getLoc(), "invalid operand modifier");
1522 return false;
1523
1533 // These are special-cased at tablegen level.
1534 return false;
1535
1536 default:
1537 break;
1538 }
1539
1540 Parser.Lex(); // Eat the identifier.
1541 if (Parser.getTok().getKind() != AsmToken::LParen)
1542 return false;
1543
1544 Parser.Lex(); // Eat the LParen token.
1545 const MCExpr *subExpr;
1546 if (Parser.parseParenExpression(subExpr, EndLoc))
1547 return false;
1548
1549 EVal = adjustPICRelocation(VK, subExpr);
1550 return true;
1551}
1552
1557}
1558
1559#define GET_REGISTER_MATCHER
1560#define GET_MATCHER_IMPLEMENTATION
1561#include "SparcGenAsmMatcher.inc"
1562
1563unsigned SparcAsmParser::validateTargetOperandClass(MCParsedAsmOperand &GOp,
1564 unsigned Kind) {
1565 SparcOperand &Op = (SparcOperand &)GOp;
1566 if (Op.isFloatOrDoubleReg()) {
1567 switch (Kind) {
1568 default: break;
1569 case MCK_DFPRegs:
1570 if (!Op.isFloatReg() || SparcOperand::MorphToDoubleReg(Op))
1572 break;
1573 case MCK_QFPRegs:
1574 if (SparcOperand::MorphToQuadReg(Op))
1576 break;
1577 }
1578 }
1579 if (Op.isIntReg() && Kind == MCK_IntPair) {
1580 if (SparcOperand::MorphToIntPairReg(Op))
1582 }
1583 if (Op.isCoprocReg() && Kind == MCK_CoprocPair) {
1584 if (SparcOperand::MorphToCoprocPairReg(Op))
1586 }
1587 return Match_InvalidOperand;
1588}
static bool addCallTargetOperands(MachineInstrBuilder &CallInst, MachineIRBuilder &MIRBuilder, AMDGPUCallLowering::CallLoweringInfo &Info)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:127
std::string Name
static LVOptions Options
Definition: LVOptions.cpp:25
#define I(x, y, z)
Definition: MD5.cpp:58
mir Rename Register Operands
unsigned Reg
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const char * name
Definition: SMEABIPass.cpp:49
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
This file defines the SmallVector class.
static const MCPhysReg DoubleRegs[32]
static bool hasGOTReference(const MCExpr *Expr)
static const MCPhysReg IntRegs[32]
static void applyMnemonicAliases(StringRef &Mnemonic, const FeatureBitset &Features, unsigned VariantID)
static const MCPhysReg CoprocRegs[32]
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcAsmParser()
static const MCPhysReg IntPairRegs[]
static const MCPhysReg QuadFPRegs[32]
static const MCPhysReg ASRRegs[32]
static const MCPhysReg FloatRegs[32]
static const MCPhysReg CoprocPairRegs[]
static bool is64Bit(const char *name)
Value * RHS
Value * LHS
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:26
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmMacro.h:110
bool is(TokenKind K) const
Definition: MCAsmMacro.h:82
TokenKind getKind() const
Definition: MCAsmMacro.h:81
SMLoc getEndLoc() const
Definition: MCAsmLexer.cpp:30
Base class for user error types.
Definition: Error.h:348
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
Container class for subtarget features.
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:123
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
Definition: MCAsmParser.cpp:40
virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression, assuming that an initial '(' has already been consumed.
bool parseOptionalToken(AsmToken::TokenKind T)
Attempt to parse and consume token, returning true on success.
Definition: MCAsmParser.cpp:80
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
Binary assembler expressions.
Definition: MCExpr.h:481
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
Definition: MCExpr.h:628
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Definition: MCExpr.h:631
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
@ Unary
Unary expressions.
Definition: MCExpr.h:41
@ Constant
Constant expressions.
Definition: MCExpr.h:39
@ SymbolRef
References to labels and assigned expressions.
Definition: MCExpr.h:40
@ Target
Target specific expression.
Definition: MCExpr.h:42
@ Binary
Binary expressions.
Definition: MCExpr.h:38
ExprKind getKind() const
Definition: MCExpr.h:81
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
void setLoc(SMLoc loc)
Definition: MCInst.h:203
unsigned getOpcode() const
Definition: MCInst.h:198
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
void setOpcode(unsigned Op)
Definition: MCInst.h:197
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:206
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:162
int64_t getImm() const
Definition: MCInst.h:80
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
bool isImm() const
Definition: MCInst.h:62
bool isReg() const
Definition: MCInst.h:61
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
virtual unsigned getReg() const =0
virtual SMLoc getStartLoc() const =0
getStartLoc - Get the location of the first token of this operand.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool isMem() const =0
isMem - Is this a memory operand?
virtual void print(raw_ostream &OS) const =0
print - Print a debug representation of the operand to the given stream.
virtual bool isToken() const =0
isToken - Is this a token operand?
virtual bool isImm() const =0
isImm - Is this an immediate operand?
virtual SMLoc getEndLoc() const =0
getEndLoc - Get the location of the last token of this operand.
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:24
Streaming machine code generation interface.
Definition: MCStreamer.h:212
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
const MCSymbol & getSymbol() const
Definition: MCExpr.h:399
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:203
MCTargetAsmParser - Generic interface to target specific assembly parsers.
virtual bool ParseDirective(AsmToken DirectiveID)=0
ParseDirective - Parse a target specific assembler directive.
virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
void setAvailableFeatures(const FeatureBitset &Value)
const MCSubtargetInfo & getSTI() const
virtual unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind)
Allow a target to add special case operand matching for things that tblgen doesn't/can't handle effec...
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands)=0
ParseInstruction - Parse one assembly instruction.
virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm)=0
MatchAndEmitInstruction - Recognize a series of operands of a parsed instruction as an actual MCInst ...
virtual OperandMatchResultTy tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
tryParseRegister - parse one register if possible
Represents a location in source code.
Definition: SMLoc.h:23
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:36
const char * getPointer() const
Definition: SMLoc.h:34
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
static const SparcMCExpr * create(VariantKind Kind, const MCExpr *Expr, MCContext &Ctx)
Definition: SparcMCExpr.cpp:27
static VariantKind parseVariantKind(StringRef name)
Definition: SparcMCExpr.cpp:93
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
R Default(T Value)
Definition: StringSwitch.h:182
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition: Triple.h:356
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:119
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ CE
Windows NT (Windows on ARM)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Length
Definition: DWP.cpp:406
@ MatchOperand_NoMatch
@ MatchOperand_ParseFail
@ MatchOperand_Success
Target & getTheSparcTarget()
Target & getTheSparcV9Target()
Target & getTheSparcelTarget()
#define N
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...