xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- SparcAsmParser.cpp - Parse Sparc assembly to MCInst instructions --===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MCTargetDesc/SparcMCExpr.h"
100b57cec5SDimitry Andric #include "MCTargetDesc/SparcMCTargetDesc.h"
110b57cec5SDimitry Andric #include "TargetInfo/SparcTargetInfo.h"
120b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
130b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
140b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
155f757f3fSDimitry Andric #include "llvm/MC/MCAsmMacro.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
195f757f3fSDimitry Andric #include "llvm/MC/MCInstBuilder.h"
2081ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
30349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
310b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
320b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
335f757f3fSDimitry Andric #include "llvm/Support/MathExtras.h"
340b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
350b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
3606c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
370b57cec5SDimitry Andric #include <algorithm>
380b57cec5SDimitry Andric #include <cassert>
390b57cec5SDimitry Andric #include <cstdint>
400b57cec5SDimitry Andric #include <memory>
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric using namespace llvm;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric // The generated AsmMatcher SparcGenAsmMatcher uses "Sparc" as the target
450b57cec5SDimitry Andric // namespace. But SPARC backend uses "SP" as its namespace.
460b57cec5SDimitry Andric namespace llvm {
470b57cec5SDimitry Andric namespace Sparc {
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric     using namespace SP;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric } // end namespace Sparc
520b57cec5SDimitry Andric } // end namespace llvm
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric namespace {
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric class SparcOperand;
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric class SparcAsmParser : public MCTargetAsmParser {
590b57cec5SDimitry Andric   MCAsmParser &Parser;
60*0fca6ea1SDimitry Andric   const MCRegisterInfo &MRI;
610b57cec5SDimitry Andric 
6281ad6265SDimitry Andric   enum class TailRelocKind { Load_GOT, Add_TLS, Load_TLS, Call_TLS };
6381ad6265SDimitry Andric 
640b57cec5SDimitry Andric   /// @name Auto-generated Match Functions
650b57cec5SDimitry Andric   /// {
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric #define GET_ASSEMBLER_HEADER
680b57cec5SDimitry Andric #include "SparcGenAsmMatcher.inc"
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   /// }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   // public interface of the MCTargetAsmParser.
730b57cec5SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
740b57cec5SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
750b57cec5SDimitry Andric                                uint64_t &ErrorInfo,
760b57cec5SDimitry Andric                                bool MatchingInlineAsm) override;
775f757f3fSDimitry Andric   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
785f757f3fSDimitry Andric   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
795ffd83dbSDimitry Andric                                SMLoc &EndLoc) override;
800b57cec5SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
810b57cec5SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
8206c3fb27SDimitry Andric   ParseStatus parseDirective(AsmToken DirectiveID) override;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
850b57cec5SDimitry Andric                                       unsigned Kind) override;
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   // Custom parse functions for Sparc specific operands.
885f757f3fSDimitry Andric   ParseStatus parseMEMOperand(OperandVector &Operands);
890b57cec5SDimitry Andric 
905f757f3fSDimitry Andric   ParseStatus parseMembarTag(OperandVector &Operands);
915f757f3fSDimitry Andric 
925f757f3fSDimitry Andric   ParseStatus parseASITag(OperandVector &Operands);
930b57cec5SDimitry Andric 
94*0fca6ea1SDimitry Andric   ParseStatus parsePrefetchTag(OperandVector &Operands);
95*0fca6ea1SDimitry Andric 
9681ad6265SDimitry Andric   template <TailRelocKind Kind>
975f757f3fSDimitry Andric   ParseStatus parseTailRelocSym(OperandVector &Operands);
9881ad6265SDimitry Andric 
995f757f3fSDimitry Andric   template <unsigned N> ParseStatus parseShiftAmtImm(OperandVector &Operands);
100e8d8bef9SDimitry Andric 
1015f757f3fSDimitry Andric   ParseStatus parseCallTarget(OperandVector &Operands);
102e8d8bef9SDimitry Andric 
1035f757f3fSDimitry Andric   ParseStatus parseOperand(OperandVector &Operands, StringRef Name);
1040b57cec5SDimitry Andric 
1055f757f3fSDimitry Andric   ParseStatus parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Operand,
1060b57cec5SDimitry Andric                                    bool isCall = false);
1070b57cec5SDimitry Andric 
1085f757f3fSDimitry Andric   ParseStatus parseBranchModifiers(OperandVector &Operands);
1090b57cec5SDimitry Andric 
110*0fca6ea1SDimitry Andric   ParseStatus parseExpression(int64_t &Val);
111*0fca6ea1SDimitry Andric 
1120b57cec5SDimitry Andric   // Helper function for dealing with %lo / %hi in PIC mode.
1130b57cec5SDimitry Andric   const SparcMCExpr *adjustPICRelocation(SparcMCExpr::VariantKind VK,
1140b57cec5SDimitry Andric                                          const MCExpr *subExpr);
1150b57cec5SDimitry Andric 
116*0fca6ea1SDimitry Andric   // Helper function to see if current token can start an expression.
117*0fca6ea1SDimitry Andric   bool isPossibleExpression(const AsmToken &Token);
118*0fca6ea1SDimitry Andric 
119*0fca6ea1SDimitry Andric   // Check if mnemonic is valid.
120*0fca6ea1SDimitry Andric   MatchResultTy mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
121*0fca6ea1SDimitry Andric 
1220b57cec5SDimitry Andric   // returns true if Tok is matched to a register and returns register in RegNo.
123*0fca6ea1SDimitry Andric   MCRegister matchRegisterName(const AsmToken &Tok, unsigned &RegKind);
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc);
1260b57cec5SDimitry Andric 
is64Bit() const1270b57cec5SDimitry Andric   bool is64Bit() const {
1280b57cec5SDimitry Andric     return getSTI().getTargetTriple().getArch() == Triple::sparcv9;
1290b57cec5SDimitry Andric   }
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   bool expandSET(MCInst &Inst, SMLoc IDLoc,
1320b57cec5SDimitry Andric                  SmallVectorImpl<MCInst> &Instructions);
1330b57cec5SDimitry Andric 
1345f757f3fSDimitry Andric   bool expandSETX(MCInst &Inst, SMLoc IDLoc,
1355f757f3fSDimitry Andric                   SmallVectorImpl<MCInst> &Instructions);
1365f757f3fSDimitry Andric 
getLoc() const13781ad6265SDimitry Andric   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
13881ad6265SDimitry Andric 
1390b57cec5SDimitry Andric public:
SparcAsmParser(const MCSubtargetInfo & sti,MCAsmParser & parser,const MCInstrInfo & MII,const MCTargetOptions & Options)1400b57cec5SDimitry Andric   SparcAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
141*0fca6ea1SDimitry Andric                  const MCInstrInfo &MII, const MCTargetOptions &Options)
142*0fca6ea1SDimitry Andric       : MCTargetAsmParser(Options, sti, MII), Parser(parser),
143*0fca6ea1SDimitry Andric         MRI(*Parser.getContext().getRegisterInfo()) {
1440b57cec5SDimitry Andric     Parser.addAliasForDirective(".half", ".2byte");
1450b57cec5SDimitry Andric     Parser.addAliasForDirective(".uahalf", ".2byte");
1460b57cec5SDimitry Andric     Parser.addAliasForDirective(".word", ".4byte");
1470b57cec5SDimitry Andric     Parser.addAliasForDirective(".uaword", ".4byte");
1480b57cec5SDimitry Andric     Parser.addAliasForDirective(".nword", is64Bit() ? ".8byte" : ".4byte");
1490b57cec5SDimitry Andric     if (is64Bit())
1500b57cec5SDimitry Andric       Parser.addAliasForDirective(".xword", ".8byte");
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric     // Initialize the set of available features.
1530b57cec5SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric };
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric } // end anonymous namespace
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   static const MCPhysReg IntRegs[32] = {
1600b57cec5SDimitry Andric     Sparc::G0, Sparc::G1, Sparc::G2, Sparc::G3,
1610b57cec5SDimitry Andric     Sparc::G4, Sparc::G5, Sparc::G6, Sparc::G7,
1620b57cec5SDimitry Andric     Sparc::O0, Sparc::O1, Sparc::O2, Sparc::O3,
1630b57cec5SDimitry Andric     Sparc::O4, Sparc::O5, Sparc::O6, Sparc::O7,
1640b57cec5SDimitry Andric     Sparc::L0, Sparc::L1, Sparc::L2, Sparc::L3,
1650b57cec5SDimitry Andric     Sparc::L4, Sparc::L5, Sparc::L6, Sparc::L7,
1660b57cec5SDimitry Andric     Sparc::I0, Sparc::I1, Sparc::I2, Sparc::I3,
1670b57cec5SDimitry Andric     Sparc::I4, Sparc::I5, Sparc::I6, Sparc::I7 };
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   static const MCPhysReg DoubleRegs[32] = {
1700b57cec5SDimitry Andric     Sparc::D0,  Sparc::D1,  Sparc::D2,  Sparc::D3,
1710b57cec5SDimitry Andric     Sparc::D4,  Sparc::D5,  Sparc::D6,  Sparc::D7,
1720b57cec5SDimitry Andric     Sparc::D8,  Sparc::D9,  Sparc::D10, Sparc::D11,
1730b57cec5SDimitry Andric     Sparc::D12, Sparc::D13, Sparc::D14, Sparc::D15,
1740b57cec5SDimitry Andric     Sparc::D16, Sparc::D17, Sparc::D18, Sparc::D19,
1750b57cec5SDimitry Andric     Sparc::D20, Sparc::D21, Sparc::D22, Sparc::D23,
1760b57cec5SDimitry Andric     Sparc::D24, Sparc::D25, Sparc::D26, Sparc::D27,
1770b57cec5SDimitry Andric     Sparc::D28, Sparc::D29, Sparc::D30, Sparc::D31 };
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   static const MCPhysReg QuadFPRegs[32] = {
1800b57cec5SDimitry Andric     Sparc::Q0,  Sparc::Q1,  Sparc::Q2,  Sparc::Q3,
1810b57cec5SDimitry Andric     Sparc::Q4,  Sparc::Q5,  Sparc::Q6,  Sparc::Q7,
1820b57cec5SDimitry Andric     Sparc::Q8,  Sparc::Q9,  Sparc::Q10, Sparc::Q11,
1830b57cec5SDimitry Andric     Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 };
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   static const MCPhysReg IntPairRegs[] = {
1860b57cec5SDimitry Andric     Sparc::G0_G1, Sparc::G2_G3, Sparc::G4_G5, Sparc::G6_G7,
1870b57cec5SDimitry Andric     Sparc::O0_O1, Sparc::O2_O3, Sparc::O4_O5, Sparc::O6_O7,
1880b57cec5SDimitry Andric     Sparc::L0_L1, Sparc::L2_L3, Sparc::L4_L5, Sparc::L6_L7,
1890b57cec5SDimitry Andric     Sparc::I0_I1, Sparc::I2_I3, Sparc::I4_I5, Sparc::I6_I7};
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   static const MCPhysReg CoprocPairRegs[] = {
1920b57cec5SDimitry Andric     Sparc::C0_C1,   Sparc::C2_C3,   Sparc::C4_C5,   Sparc::C6_C7,
1930b57cec5SDimitry Andric     Sparc::C8_C9,   Sparc::C10_C11, Sparc::C12_C13, Sparc::C14_C15,
1940b57cec5SDimitry Andric     Sparc::C16_C17, Sparc::C18_C19, Sparc::C20_C21, Sparc::C22_C23,
1950b57cec5SDimitry Andric     Sparc::C24_C25, Sparc::C26_C27, Sparc::C28_C29, Sparc::C30_C31};
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric namespace {
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric /// SparcOperand - Instances of this class represent a parsed Sparc machine
2000b57cec5SDimitry Andric /// instruction.
2010b57cec5SDimitry Andric class SparcOperand : public MCParsedAsmOperand {
2020b57cec5SDimitry Andric public:
2030b57cec5SDimitry Andric   enum RegisterKind {
2040b57cec5SDimitry Andric     rk_None,
2050b57cec5SDimitry Andric     rk_IntReg,
2060b57cec5SDimitry Andric     rk_IntPairReg,
2070b57cec5SDimitry Andric     rk_FloatReg,
2080b57cec5SDimitry Andric     rk_DoubleReg,
2090b57cec5SDimitry Andric     rk_QuadReg,
2100b57cec5SDimitry Andric     rk_CoprocReg,
2110b57cec5SDimitry Andric     rk_CoprocPairReg,
2120b57cec5SDimitry Andric     rk_Special,
2130b57cec5SDimitry Andric   };
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric private:
2160b57cec5SDimitry Andric   enum KindTy {
2170b57cec5SDimitry Andric     k_Token,
2180b57cec5SDimitry Andric     k_Register,
2190b57cec5SDimitry Andric     k_Immediate,
2200b57cec5SDimitry Andric     k_MemoryReg,
2215f757f3fSDimitry Andric     k_MemoryImm,
222*0fca6ea1SDimitry Andric     k_ASITag,
223*0fca6ea1SDimitry Andric     k_PrefetchTag,
2240b57cec5SDimitry Andric   } Kind;
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   SMLoc StartLoc, EndLoc;
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   struct Token {
2290b57cec5SDimitry Andric     const char *Data;
2300b57cec5SDimitry Andric     unsigned Length;
2310b57cec5SDimitry Andric   };
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric   struct RegOp {
2340b57cec5SDimitry Andric     unsigned RegNum;
2350b57cec5SDimitry Andric     RegisterKind Kind;
2360b57cec5SDimitry Andric   };
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   struct ImmOp {
2390b57cec5SDimitry Andric     const MCExpr *Val;
2400b57cec5SDimitry Andric   };
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   struct MemOp {
2430b57cec5SDimitry Andric     unsigned Base;
2440b57cec5SDimitry Andric     unsigned OffsetReg;
2450b57cec5SDimitry Andric     const MCExpr *Off;
2460b57cec5SDimitry Andric   };
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric   union {
2490b57cec5SDimitry Andric     struct Token Tok;
2500b57cec5SDimitry Andric     struct RegOp Reg;
2510b57cec5SDimitry Andric     struct ImmOp Imm;
2520b57cec5SDimitry Andric     struct MemOp Mem;
2535f757f3fSDimitry Andric     unsigned ASI;
254*0fca6ea1SDimitry Andric     unsigned Prefetch;
2550b57cec5SDimitry Andric   };
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric public:
SparcOperand(KindTy K)25804eeddc0SDimitry Andric   SparcOperand(KindTy K) : Kind(K) {}
2590b57cec5SDimitry Andric 
isToken() const2600b57cec5SDimitry Andric   bool isToken() const override { return Kind == k_Token; }
isReg() const2610b57cec5SDimitry Andric   bool isReg() const override { return Kind == k_Register; }
isImm() const2620b57cec5SDimitry Andric   bool isImm() const override { return Kind == k_Immediate; }
isMem() const2630b57cec5SDimitry Andric   bool isMem() const override { return isMEMrr() || isMEMri(); }
isMEMrr() const2640b57cec5SDimitry Andric   bool isMEMrr() const { return Kind == k_MemoryReg; }
isMEMri() const2650b57cec5SDimitry Andric   bool isMEMri() const { return Kind == k_MemoryImm; }
isMembarTag() const2660b57cec5SDimitry Andric   bool isMembarTag() const { return Kind == k_Immediate; }
isASITag() const2675f757f3fSDimitry Andric   bool isASITag() const { return Kind == k_ASITag; }
isPrefetchTag() const268*0fca6ea1SDimitry Andric   bool isPrefetchTag() const { return Kind == k_PrefetchTag; }
isTailRelocSym() const26981ad6265SDimitry Andric   bool isTailRelocSym() const { return Kind == k_Immediate; }
2700b57cec5SDimitry Andric 
isCallTarget() const271e8d8bef9SDimitry Andric   bool isCallTarget() const {
272e8d8bef9SDimitry Andric     if (!isImm())
273e8d8bef9SDimitry Andric       return false;
274e8d8bef9SDimitry Andric 
275e8d8bef9SDimitry Andric     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val))
276e8d8bef9SDimitry Andric       return CE->getValue() % 4 == 0;
277e8d8bef9SDimitry Andric 
278e8d8bef9SDimitry Andric     return true;
279e8d8bef9SDimitry Andric   }
280e8d8bef9SDimitry Andric 
isShiftAmtImm5() const281e8d8bef9SDimitry Andric   bool isShiftAmtImm5() const {
282e8d8bef9SDimitry Andric     if (!isImm())
283e8d8bef9SDimitry Andric       return false;
284e8d8bef9SDimitry Andric 
285e8d8bef9SDimitry Andric     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val))
286e8d8bef9SDimitry Andric       return isUInt<5>(CE->getValue());
287e8d8bef9SDimitry Andric 
288e8d8bef9SDimitry Andric     return false;
289e8d8bef9SDimitry Andric   }
290e8d8bef9SDimitry Andric 
isShiftAmtImm6() const291e8d8bef9SDimitry Andric   bool isShiftAmtImm6() const {
292e8d8bef9SDimitry Andric     if (!isImm())
293e8d8bef9SDimitry Andric       return false;
294e8d8bef9SDimitry Andric 
295e8d8bef9SDimitry Andric     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val))
296e8d8bef9SDimitry Andric       return isUInt<6>(CE->getValue());
297e8d8bef9SDimitry Andric 
298e8d8bef9SDimitry Andric     return false;
299e8d8bef9SDimitry Andric   }
300e8d8bef9SDimitry Andric 
isIntReg() const3010b57cec5SDimitry Andric   bool isIntReg() const {
3020b57cec5SDimitry Andric     return (Kind == k_Register && Reg.Kind == rk_IntReg);
3030b57cec5SDimitry Andric   }
3040b57cec5SDimitry Andric 
isFloatReg() const3050b57cec5SDimitry Andric   bool isFloatReg() const {
3060b57cec5SDimitry Andric     return (Kind == k_Register && Reg.Kind == rk_FloatReg);
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric 
isFloatOrDoubleReg() const3090b57cec5SDimitry Andric   bool isFloatOrDoubleReg() const {
3100b57cec5SDimitry Andric     return (Kind == k_Register && (Reg.Kind == rk_FloatReg
3110b57cec5SDimitry Andric                                    || Reg.Kind == rk_DoubleReg));
3120b57cec5SDimitry Andric   }
3130b57cec5SDimitry Andric 
isCoprocReg() const3140b57cec5SDimitry Andric   bool isCoprocReg() const {
3150b57cec5SDimitry Andric     return (Kind == k_Register && Reg.Kind == rk_CoprocReg);
3160b57cec5SDimitry Andric   }
3170b57cec5SDimitry Andric 
getToken() const3180b57cec5SDimitry Andric   StringRef getToken() const {
3190b57cec5SDimitry Andric     assert(Kind == k_Token && "Invalid access!");
3200b57cec5SDimitry Andric     return StringRef(Tok.Data, Tok.Length);
3210b57cec5SDimitry Andric   }
3220b57cec5SDimitry Andric 
getReg() const323*0fca6ea1SDimitry Andric   MCRegister getReg() const override {
3240b57cec5SDimitry Andric     assert((Kind == k_Register) && "Invalid access!");
3250b57cec5SDimitry Andric     return Reg.RegNum;
3260b57cec5SDimitry Andric   }
3270b57cec5SDimitry Andric 
getImm() const3280b57cec5SDimitry Andric   const MCExpr *getImm() const {
3290b57cec5SDimitry Andric     assert((Kind == k_Immediate) && "Invalid access!");
3300b57cec5SDimitry Andric     return Imm.Val;
3310b57cec5SDimitry Andric   }
3320b57cec5SDimitry Andric 
getMemBase() const3330b57cec5SDimitry Andric   unsigned getMemBase() const {
3340b57cec5SDimitry Andric     assert((Kind == k_MemoryReg || Kind == k_MemoryImm) && "Invalid access!");
3350b57cec5SDimitry Andric     return Mem.Base;
3360b57cec5SDimitry Andric   }
3370b57cec5SDimitry Andric 
getMemOffsetReg() const3380b57cec5SDimitry Andric   unsigned getMemOffsetReg() const {
3390b57cec5SDimitry Andric     assert((Kind == k_MemoryReg) && "Invalid access!");
3400b57cec5SDimitry Andric     return Mem.OffsetReg;
3410b57cec5SDimitry Andric   }
3420b57cec5SDimitry Andric 
getMemOff() const3430b57cec5SDimitry Andric   const MCExpr *getMemOff() const {
3440b57cec5SDimitry Andric     assert((Kind == k_MemoryImm) && "Invalid access!");
3450b57cec5SDimitry Andric     return Mem.Off;
3460b57cec5SDimitry Andric   }
3470b57cec5SDimitry Andric 
getASITag() const3485f757f3fSDimitry Andric   unsigned getASITag() const {
3495f757f3fSDimitry Andric     assert((Kind == k_ASITag) && "Invalid access!");
3505f757f3fSDimitry Andric     return ASI;
3515f757f3fSDimitry Andric   }
3525f757f3fSDimitry Andric 
getPrefetchTag() const353*0fca6ea1SDimitry Andric   unsigned getPrefetchTag() const {
354*0fca6ea1SDimitry Andric     assert((Kind == k_PrefetchTag) && "Invalid access!");
355*0fca6ea1SDimitry Andric     return Prefetch;
356*0fca6ea1SDimitry Andric   }
357*0fca6ea1SDimitry Andric 
3580b57cec5SDimitry Andric   /// getStartLoc - Get the location of the first token of this operand.
getStartLoc() const3590b57cec5SDimitry Andric   SMLoc getStartLoc() const override {
3600b57cec5SDimitry Andric     return StartLoc;
3610b57cec5SDimitry Andric   }
3620b57cec5SDimitry Andric   /// getEndLoc - Get the location of the last token of this operand.
getEndLoc() const3630b57cec5SDimitry Andric   SMLoc getEndLoc() const override {
3640b57cec5SDimitry Andric     return EndLoc;
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric 
print(raw_ostream & OS) const3670b57cec5SDimitry Andric   void print(raw_ostream &OS) const override {
3680b57cec5SDimitry Andric     switch (Kind) {
3690b57cec5SDimitry Andric     case k_Token:     OS << "Token: " << getToken() << "\n"; break;
3700b57cec5SDimitry Andric     case k_Register:  OS << "Reg: #" << getReg() << "\n"; break;
3710b57cec5SDimitry Andric     case k_Immediate: OS << "Imm: " << getImm() << "\n"; break;
3720b57cec5SDimitry Andric     case k_MemoryReg: OS << "Mem: " << getMemBase() << "+"
3730b57cec5SDimitry Andric                          << getMemOffsetReg() << "\n"; break;
3740b57cec5SDimitry Andric     case k_MemoryImm: assert(getMemOff() != nullptr);
3750b57cec5SDimitry Andric       OS << "Mem: " << getMemBase()
3760b57cec5SDimitry Andric          << "+" << *getMemOff()
3770b57cec5SDimitry Andric          << "\n"; break;
3785f757f3fSDimitry Andric     case k_ASITag:
3795f757f3fSDimitry Andric       OS << "ASI tag: " << getASITag() << "\n";
3805f757f3fSDimitry Andric       break;
381*0fca6ea1SDimitry Andric     case k_PrefetchTag:
382*0fca6ea1SDimitry Andric       OS << "Prefetch tag: " << getPrefetchTag() << "\n";
383*0fca6ea1SDimitry Andric       break;
3840b57cec5SDimitry Andric     }
3850b57cec5SDimitry Andric   }
3860b57cec5SDimitry Andric 
addRegOperands(MCInst & Inst,unsigned N) const3870b57cec5SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const {
3880b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
3890b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getReg()));
3900b57cec5SDimitry Andric   }
3910b57cec5SDimitry Andric 
addImmOperands(MCInst & Inst,unsigned N) const3920b57cec5SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const {
3930b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
3940b57cec5SDimitry Andric     const MCExpr *Expr = getImm();
3950b57cec5SDimitry Andric     addExpr(Inst, Expr);
3960b57cec5SDimitry Andric   }
3970b57cec5SDimitry Andric 
addShiftAmtImm5Operands(MCInst & Inst,unsigned N) const398e8d8bef9SDimitry Andric   void addShiftAmtImm5Operands(MCInst &Inst, unsigned N) const {
399e8d8bef9SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
400e8d8bef9SDimitry Andric     addExpr(Inst, getImm());
401e8d8bef9SDimitry Andric   }
addShiftAmtImm6Operands(MCInst & Inst,unsigned N) const402e8d8bef9SDimitry Andric   void addShiftAmtImm6Operands(MCInst &Inst, unsigned N) const {
403e8d8bef9SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
404e8d8bef9SDimitry Andric     addExpr(Inst, getImm());
405e8d8bef9SDimitry Andric   }
406e8d8bef9SDimitry Andric 
addExpr(MCInst & Inst,const MCExpr * Expr) const4070b57cec5SDimitry Andric   void addExpr(MCInst &Inst, const MCExpr *Expr) const{
4080b57cec5SDimitry Andric     // Add as immediate when possible.  Null MCExpr = 0.
4090b57cec5SDimitry Andric     if (!Expr)
4100b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createImm(0));
4110b57cec5SDimitry Andric     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
4120b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createImm(CE->getValue()));
4130b57cec5SDimitry Andric     else
4140b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createExpr(Expr));
4150b57cec5SDimitry Andric   }
4160b57cec5SDimitry Andric 
addMEMrrOperands(MCInst & Inst,unsigned N) const4170b57cec5SDimitry Andric   void addMEMrrOperands(MCInst &Inst, unsigned N) const {
4180b57cec5SDimitry Andric     assert(N == 2 && "Invalid number of operands!");
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getMemBase()));
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric     assert(getMemOffsetReg() != 0 && "Invalid offset");
4230b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));
4240b57cec5SDimitry Andric   }
4250b57cec5SDimitry Andric 
addMEMriOperands(MCInst & Inst,unsigned N) const4260b57cec5SDimitry Andric   void addMEMriOperands(MCInst &Inst, unsigned N) const {
4270b57cec5SDimitry Andric     assert(N == 2 && "Invalid number of operands!");
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getMemBase()));
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric     const MCExpr *Expr = getMemOff();
4320b57cec5SDimitry Andric     addExpr(Inst, Expr);
4330b57cec5SDimitry Andric   }
4340b57cec5SDimitry Andric 
addASITagOperands(MCInst & Inst,unsigned N) const4355f757f3fSDimitry Andric   void addASITagOperands(MCInst &Inst, unsigned N) const {
4365f757f3fSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
4375f757f3fSDimitry Andric     Inst.addOperand(MCOperand::createImm(getASITag()));
4385f757f3fSDimitry Andric   }
4395f757f3fSDimitry Andric 
addPrefetchTagOperands(MCInst & Inst,unsigned N) const440*0fca6ea1SDimitry Andric   void addPrefetchTagOperands(MCInst &Inst, unsigned N) const {
441*0fca6ea1SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
442*0fca6ea1SDimitry Andric     Inst.addOperand(MCOperand::createImm(getPrefetchTag()));
443*0fca6ea1SDimitry Andric   }
444*0fca6ea1SDimitry Andric 
addMembarTagOperands(MCInst & Inst,unsigned N) const4450b57cec5SDimitry Andric   void addMembarTagOperands(MCInst &Inst, unsigned N) const {
4460b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
4470b57cec5SDimitry Andric     const MCExpr *Expr = getImm();
4480b57cec5SDimitry Andric     addExpr(Inst, Expr);
4490b57cec5SDimitry Andric   }
4500b57cec5SDimitry Andric 
addCallTargetOperands(MCInst & Inst,unsigned N) const451e8d8bef9SDimitry Andric   void addCallTargetOperands(MCInst &Inst, unsigned N) const {
452e8d8bef9SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
453e8d8bef9SDimitry Andric     addExpr(Inst, getImm());
454e8d8bef9SDimitry Andric   }
455e8d8bef9SDimitry Andric 
addTailRelocSymOperands(MCInst & Inst,unsigned N) const45681ad6265SDimitry Andric   void addTailRelocSymOperands(MCInst &Inst, unsigned N) const {
45781ad6265SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
45881ad6265SDimitry Andric     addExpr(Inst, getImm());
45981ad6265SDimitry Andric   }
46081ad6265SDimitry Andric 
CreateToken(StringRef Str,SMLoc S)4610b57cec5SDimitry Andric   static std::unique_ptr<SparcOperand> CreateToken(StringRef Str, SMLoc S) {
4628bcb0991SDimitry Andric     auto Op = std::make_unique<SparcOperand>(k_Token);
4630b57cec5SDimitry Andric     Op->Tok.Data = Str.data();
4640b57cec5SDimitry Andric     Op->Tok.Length = Str.size();
4650b57cec5SDimitry Andric     Op->StartLoc = S;
4660b57cec5SDimitry Andric     Op->EndLoc = S;
4670b57cec5SDimitry Andric     return Op;
4680b57cec5SDimitry Andric   }
4690b57cec5SDimitry Andric 
CreateReg(unsigned RegNum,unsigned Kind,SMLoc S,SMLoc E)4700b57cec5SDimitry Andric   static std::unique_ptr<SparcOperand> CreateReg(unsigned RegNum, unsigned Kind,
4710b57cec5SDimitry Andric                                                  SMLoc S, SMLoc E) {
4728bcb0991SDimitry Andric     auto Op = std::make_unique<SparcOperand>(k_Register);
4730b57cec5SDimitry Andric     Op->Reg.RegNum = RegNum;
4740b57cec5SDimitry Andric     Op->Reg.Kind   = (SparcOperand::RegisterKind)Kind;
4750b57cec5SDimitry Andric     Op->StartLoc = S;
4760b57cec5SDimitry Andric     Op->EndLoc = E;
4770b57cec5SDimitry Andric     return Op;
4780b57cec5SDimitry Andric   }
4790b57cec5SDimitry Andric 
CreateImm(const MCExpr * Val,SMLoc S,SMLoc E)4800b57cec5SDimitry Andric   static std::unique_ptr<SparcOperand> CreateImm(const MCExpr *Val, SMLoc S,
4810b57cec5SDimitry Andric                                                  SMLoc E) {
4828bcb0991SDimitry Andric     auto Op = std::make_unique<SparcOperand>(k_Immediate);
4830b57cec5SDimitry Andric     Op->Imm.Val = Val;
4840b57cec5SDimitry Andric     Op->StartLoc = S;
4850b57cec5SDimitry Andric     Op->EndLoc = E;
4860b57cec5SDimitry Andric     return Op;
4870b57cec5SDimitry Andric   }
4880b57cec5SDimitry Andric 
CreateASITag(unsigned Val,SMLoc S,SMLoc E)4895f757f3fSDimitry Andric   static std::unique_ptr<SparcOperand> CreateASITag(unsigned Val, SMLoc S,
4905f757f3fSDimitry Andric                                                     SMLoc E) {
4915f757f3fSDimitry Andric     auto Op = std::make_unique<SparcOperand>(k_ASITag);
4925f757f3fSDimitry Andric     Op->ASI = Val;
4935f757f3fSDimitry Andric     Op->StartLoc = S;
4945f757f3fSDimitry Andric     Op->EndLoc = E;
4955f757f3fSDimitry Andric     return Op;
4965f757f3fSDimitry Andric   }
4975f757f3fSDimitry Andric 
CreatePrefetchTag(unsigned Val,SMLoc S,SMLoc E)498*0fca6ea1SDimitry Andric   static std::unique_ptr<SparcOperand> CreatePrefetchTag(unsigned Val, SMLoc S,
499*0fca6ea1SDimitry Andric                                                          SMLoc E) {
500*0fca6ea1SDimitry Andric     auto Op = std::make_unique<SparcOperand>(k_PrefetchTag);
501*0fca6ea1SDimitry Andric     Op->Prefetch = Val;
502*0fca6ea1SDimitry Andric     Op->StartLoc = S;
503*0fca6ea1SDimitry Andric     Op->EndLoc = E;
504*0fca6ea1SDimitry Andric     return Op;
505*0fca6ea1SDimitry Andric   }
506*0fca6ea1SDimitry Andric 
MorphToIntPairReg(SparcOperand & Op)5070b57cec5SDimitry Andric   static bool MorphToIntPairReg(SparcOperand &Op) {
5080b57cec5SDimitry Andric     unsigned Reg = Op.getReg();
5090b57cec5SDimitry Andric     assert(Op.Reg.Kind == rk_IntReg);
5100b57cec5SDimitry Andric     unsigned regIdx = 32;
5110b57cec5SDimitry Andric     if (Reg >= Sparc::G0 && Reg <= Sparc::G7)
5120b57cec5SDimitry Andric       regIdx = Reg - Sparc::G0;
5130b57cec5SDimitry Andric     else if (Reg >= Sparc::O0 && Reg <= Sparc::O7)
5140b57cec5SDimitry Andric       regIdx = Reg - Sparc::O0 + 8;
5150b57cec5SDimitry Andric     else if (Reg >= Sparc::L0 && Reg <= Sparc::L7)
5160b57cec5SDimitry Andric       regIdx = Reg - Sparc::L0 + 16;
5170b57cec5SDimitry Andric     else if (Reg >= Sparc::I0 && Reg <= Sparc::I7)
5180b57cec5SDimitry Andric       regIdx = Reg - Sparc::I0 + 24;
5190b57cec5SDimitry Andric     if (regIdx % 2 || regIdx > 31)
5200b57cec5SDimitry Andric       return false;
5210b57cec5SDimitry Andric     Op.Reg.RegNum = IntPairRegs[regIdx / 2];
5220b57cec5SDimitry Andric     Op.Reg.Kind = rk_IntPairReg;
5230b57cec5SDimitry Andric     return true;
5240b57cec5SDimitry Andric   }
5250b57cec5SDimitry Andric 
MorphToDoubleReg(SparcOperand & Op)5260b57cec5SDimitry Andric   static bool MorphToDoubleReg(SparcOperand &Op) {
5270b57cec5SDimitry Andric     unsigned Reg = Op.getReg();
5280b57cec5SDimitry Andric     assert(Op.Reg.Kind == rk_FloatReg);
5290b57cec5SDimitry Andric     unsigned regIdx = Reg - Sparc::F0;
5300b57cec5SDimitry Andric     if (regIdx % 2 || regIdx > 31)
5310b57cec5SDimitry Andric       return false;
5320b57cec5SDimitry Andric     Op.Reg.RegNum = DoubleRegs[regIdx / 2];
5330b57cec5SDimitry Andric     Op.Reg.Kind = rk_DoubleReg;
5340b57cec5SDimitry Andric     return true;
5350b57cec5SDimitry Andric   }
5360b57cec5SDimitry Andric 
MorphToQuadReg(SparcOperand & Op)5370b57cec5SDimitry Andric   static bool MorphToQuadReg(SparcOperand &Op) {
5380b57cec5SDimitry Andric     unsigned Reg = Op.getReg();
5390b57cec5SDimitry Andric     unsigned regIdx = 0;
5400b57cec5SDimitry Andric     switch (Op.Reg.Kind) {
5410b57cec5SDimitry Andric     default: llvm_unreachable("Unexpected register kind!");
5420b57cec5SDimitry Andric     case rk_FloatReg:
5430b57cec5SDimitry Andric       regIdx = Reg - Sparc::F0;
5440b57cec5SDimitry Andric       if (regIdx % 4 || regIdx > 31)
5450b57cec5SDimitry Andric         return false;
5460b57cec5SDimitry Andric       Reg = QuadFPRegs[regIdx / 4];
5470b57cec5SDimitry Andric       break;
5480b57cec5SDimitry Andric     case rk_DoubleReg:
5490b57cec5SDimitry Andric       regIdx =  Reg - Sparc::D0;
5500b57cec5SDimitry Andric       if (regIdx % 2 || regIdx > 31)
5510b57cec5SDimitry Andric         return false;
5520b57cec5SDimitry Andric       Reg = QuadFPRegs[regIdx / 2];
5530b57cec5SDimitry Andric       break;
5540b57cec5SDimitry Andric     }
5550b57cec5SDimitry Andric     Op.Reg.RegNum = Reg;
5560b57cec5SDimitry Andric     Op.Reg.Kind = rk_QuadReg;
5570b57cec5SDimitry Andric     return true;
5580b57cec5SDimitry Andric   }
5590b57cec5SDimitry Andric 
MorphToCoprocPairReg(SparcOperand & Op)5600b57cec5SDimitry Andric   static bool MorphToCoprocPairReg(SparcOperand &Op) {
5610b57cec5SDimitry Andric     unsigned Reg = Op.getReg();
5620b57cec5SDimitry Andric     assert(Op.Reg.Kind == rk_CoprocReg);
5630b57cec5SDimitry Andric     unsigned regIdx = 32;
5640b57cec5SDimitry Andric     if (Reg >= Sparc::C0 && Reg <= Sparc::C31)
5650b57cec5SDimitry Andric       regIdx = Reg - Sparc::C0;
5660b57cec5SDimitry Andric     if (regIdx % 2 || regIdx > 31)
5670b57cec5SDimitry Andric       return false;
5680b57cec5SDimitry Andric     Op.Reg.RegNum = CoprocPairRegs[regIdx / 2];
5690b57cec5SDimitry Andric     Op.Reg.Kind = rk_CoprocPairReg;
5700b57cec5SDimitry Andric     return true;
5710b57cec5SDimitry Andric   }
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric   static std::unique_ptr<SparcOperand>
MorphToMEMrr(unsigned Base,std::unique_ptr<SparcOperand> Op)5740b57cec5SDimitry Andric   MorphToMEMrr(unsigned Base, std::unique_ptr<SparcOperand> Op) {
5750b57cec5SDimitry Andric     unsigned offsetReg = Op->getReg();
5760b57cec5SDimitry Andric     Op->Kind = k_MemoryReg;
5770b57cec5SDimitry Andric     Op->Mem.Base = Base;
5780b57cec5SDimitry Andric     Op->Mem.OffsetReg = offsetReg;
5790b57cec5SDimitry Andric     Op->Mem.Off = nullptr;
5800b57cec5SDimitry Andric     return Op;
5810b57cec5SDimitry Andric   }
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric   static std::unique_ptr<SparcOperand>
CreateMEMr(unsigned Base,SMLoc S,SMLoc E)5840b57cec5SDimitry Andric   CreateMEMr(unsigned Base, SMLoc S, SMLoc E) {
5858bcb0991SDimitry Andric     auto Op = std::make_unique<SparcOperand>(k_MemoryReg);
5860b57cec5SDimitry Andric     Op->Mem.Base = Base;
5870b57cec5SDimitry Andric     Op->Mem.OffsetReg = Sparc::G0;  // always 0
5880b57cec5SDimitry Andric     Op->Mem.Off = nullptr;
5890b57cec5SDimitry Andric     Op->StartLoc = S;
5900b57cec5SDimitry Andric     Op->EndLoc = E;
5910b57cec5SDimitry Andric     return Op;
5920b57cec5SDimitry Andric   }
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric   static std::unique_ptr<SparcOperand>
MorphToMEMri(unsigned Base,std::unique_ptr<SparcOperand> Op)5950b57cec5SDimitry Andric   MorphToMEMri(unsigned Base, std::unique_ptr<SparcOperand> Op) {
5960b57cec5SDimitry Andric     const MCExpr *Imm  = Op->getImm();
5970b57cec5SDimitry Andric     Op->Kind = k_MemoryImm;
5980b57cec5SDimitry Andric     Op->Mem.Base = Base;
5990b57cec5SDimitry Andric     Op->Mem.OffsetReg = 0;
6000b57cec5SDimitry Andric     Op->Mem.Off = Imm;
6010b57cec5SDimitry Andric     return Op;
6020b57cec5SDimitry Andric   }
6030b57cec5SDimitry Andric };
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric } // end anonymous namespace
6060b57cec5SDimitry Andric 
607*0fca6ea1SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
608*0fca6ea1SDimitry Andric #define GET_REGISTER_MATCHER
609*0fca6ea1SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER
610*0fca6ea1SDimitry Andric #include "SparcGenAsmMatcher.inc"
611*0fca6ea1SDimitry Andric 
612*0fca6ea1SDimitry Andric // Use a custom function instead of the one from SparcGenAsmMatcher
613*0fca6ea1SDimitry Andric // so we can differentiate between unavailable and unknown instructions.
614*0fca6ea1SDimitry Andric SparcAsmParser::MatchResultTy
mnemonicIsValid(StringRef Mnemonic,unsigned VariantID)615*0fca6ea1SDimitry Andric SparcAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
616*0fca6ea1SDimitry Andric   // Process all MnemonicAliases to remap the mnemonic.
617*0fca6ea1SDimitry Andric   applyMnemonicAliases(Mnemonic, getAvailableFeatures(), VariantID);
618*0fca6ea1SDimitry Andric 
619*0fca6ea1SDimitry Andric   // Find the appropriate table for this asm variant.
620*0fca6ea1SDimitry Andric   const MatchEntry *Start, *End;
621*0fca6ea1SDimitry Andric   switch (VariantID) {
622*0fca6ea1SDimitry Andric   default:
623*0fca6ea1SDimitry Andric     llvm_unreachable("invalid variant!");
624*0fca6ea1SDimitry Andric   case 0:
625*0fca6ea1SDimitry Andric     Start = std::begin(MatchTable0);
626*0fca6ea1SDimitry Andric     End = std::end(MatchTable0);
627*0fca6ea1SDimitry Andric     break;
628*0fca6ea1SDimitry Andric   }
629*0fca6ea1SDimitry Andric 
630*0fca6ea1SDimitry Andric   // Search the table.
631*0fca6ea1SDimitry Andric   auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
632*0fca6ea1SDimitry Andric 
633*0fca6ea1SDimitry Andric   if (MnemonicRange.first == MnemonicRange.second)
634*0fca6ea1SDimitry Andric     return Match_MnemonicFail;
635*0fca6ea1SDimitry Andric 
636*0fca6ea1SDimitry Andric   for (const MatchEntry *it = MnemonicRange.first, *ie = MnemonicRange.second;
637*0fca6ea1SDimitry Andric        it != ie; ++it) {
638*0fca6ea1SDimitry Andric     const FeatureBitset &RequiredFeatures =
639*0fca6ea1SDimitry Andric         FeatureBitsets[it->RequiredFeaturesIdx];
640*0fca6ea1SDimitry Andric     if ((getAvailableFeatures() & RequiredFeatures) == RequiredFeatures)
641*0fca6ea1SDimitry Andric       return Match_Success;
642*0fca6ea1SDimitry Andric   }
643*0fca6ea1SDimitry Andric   return Match_MissingFeature;
644*0fca6ea1SDimitry Andric }
645*0fca6ea1SDimitry Andric 
expandSET(MCInst & Inst,SMLoc IDLoc,SmallVectorImpl<MCInst> & Instructions)6460b57cec5SDimitry Andric bool SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc,
6470b57cec5SDimitry Andric                                SmallVectorImpl<MCInst> &Instructions) {
6480b57cec5SDimitry Andric   MCOperand MCRegOp = Inst.getOperand(0);
6490b57cec5SDimitry Andric   MCOperand MCValOp = Inst.getOperand(1);
6500b57cec5SDimitry Andric   assert(MCRegOp.isReg());
6510b57cec5SDimitry Andric   assert(MCValOp.isImm() || MCValOp.isExpr());
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric   // the imm operand can be either an expression or an immediate.
6540b57cec5SDimitry Andric   bool IsImm = Inst.getOperand(1).isImm();
6550b57cec5SDimitry Andric   int64_t RawImmValue = IsImm ? MCValOp.getImm() : 0;
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric   // Allow either a signed or unsigned 32-bit immediate.
6580b57cec5SDimitry Andric   if (RawImmValue < -2147483648LL || RawImmValue > 4294967295LL) {
6590b57cec5SDimitry Andric     return Error(IDLoc,
6600b57cec5SDimitry Andric                  "set: argument must be between -2147483648 and 4294967295");
6610b57cec5SDimitry Andric   }
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric   // If the value was expressed as a large unsigned number, that's ok.
6640b57cec5SDimitry Andric   // We want to see if it "looks like" a small signed number.
6650b57cec5SDimitry Andric   int32_t ImmValue = RawImmValue;
6660b57cec5SDimitry Andric   // For 'set' you can't use 'or' with a negative operand on V9 because
6670b57cec5SDimitry Andric   // that would splat the sign bit across the upper half of the destination
6680b57cec5SDimitry Andric   // register, whereas 'set' is defined to zero the high 32 bits.
6690b57cec5SDimitry Andric   bool IsEffectivelyImm13 =
6700b57cec5SDimitry Andric       IsImm && ((is64Bit() ? 0 : -4096) <= ImmValue && ImmValue < 4096);
6710b57cec5SDimitry Andric   const MCExpr *ValExpr;
6720b57cec5SDimitry Andric   if (IsImm)
6730b57cec5SDimitry Andric     ValExpr = MCConstantExpr::create(ImmValue, getContext());
6740b57cec5SDimitry Andric   else
6750b57cec5SDimitry Andric     ValExpr = MCValOp.getExpr();
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric   MCOperand PrevReg = MCOperand::createReg(Sparc::G0);
6780b57cec5SDimitry Andric 
6790b57cec5SDimitry Andric   // If not just a signed imm13 value, then either we use a 'sethi' with a
6800b57cec5SDimitry Andric   // following 'or', or a 'sethi' by itself if there are no more 1 bits.
6810b57cec5SDimitry Andric   // In either case, start with the 'sethi'.
6820b57cec5SDimitry Andric   if (!IsEffectivelyImm13) {
6830b57cec5SDimitry Andric     MCInst TmpInst;
6840b57cec5SDimitry Andric     const MCExpr *Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_HI, ValExpr);
6850b57cec5SDimitry Andric     TmpInst.setLoc(IDLoc);
6860b57cec5SDimitry Andric     TmpInst.setOpcode(SP::SETHIi);
6870b57cec5SDimitry Andric     TmpInst.addOperand(MCRegOp);
6880b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createExpr(Expr));
6890b57cec5SDimitry Andric     Instructions.push_back(TmpInst);
6900b57cec5SDimitry Andric     PrevReg = MCRegOp;
6910b57cec5SDimitry Andric   }
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric   // The low bits require touching in 3 cases:
6940b57cec5SDimitry Andric   // * A non-immediate value will always require both instructions.
6950b57cec5SDimitry Andric   // * An effectively imm13 value needs only an 'or' instruction.
6960b57cec5SDimitry Andric   // * Otherwise, an immediate that is not effectively imm13 requires the
6970b57cec5SDimitry Andric   //   'or' only if bits remain after clearing the 22 bits that 'sethi' set.
6980b57cec5SDimitry Andric   // If the low bits are known zeros, there's nothing to do.
6990b57cec5SDimitry Andric   // In the second case, and only in that case, must we NOT clear
7000b57cec5SDimitry Andric   // bits of the immediate value via the %lo() assembler function.
7010b57cec5SDimitry Andric   // Note also, the 'or' instruction doesn't mind a large value in the case
7020b57cec5SDimitry Andric   // where the operand to 'set' was 0xFFFFFzzz - it does exactly what you mean.
7030b57cec5SDimitry Andric   if (!IsImm || IsEffectivelyImm13 || (ImmValue & 0x3ff)) {
7040b57cec5SDimitry Andric     MCInst TmpInst;
7050b57cec5SDimitry Andric     const MCExpr *Expr;
7060b57cec5SDimitry Andric     if (IsEffectivelyImm13)
7070b57cec5SDimitry Andric       Expr = ValExpr;
7080b57cec5SDimitry Andric     else
7090b57cec5SDimitry Andric       Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_LO, ValExpr);
7100b57cec5SDimitry Andric     TmpInst.setLoc(IDLoc);
7110b57cec5SDimitry Andric     TmpInst.setOpcode(SP::ORri);
7120b57cec5SDimitry Andric     TmpInst.addOperand(MCRegOp);
7130b57cec5SDimitry Andric     TmpInst.addOperand(PrevReg);
7140b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createExpr(Expr));
7150b57cec5SDimitry Andric     Instructions.push_back(TmpInst);
7160b57cec5SDimitry Andric   }
7170b57cec5SDimitry Andric   return false;
7180b57cec5SDimitry Andric }
7190b57cec5SDimitry Andric 
expandSETX(MCInst & Inst,SMLoc IDLoc,SmallVectorImpl<MCInst> & Instructions)7205f757f3fSDimitry Andric bool SparcAsmParser::expandSETX(MCInst &Inst, SMLoc IDLoc,
7215f757f3fSDimitry Andric                                 SmallVectorImpl<MCInst> &Instructions) {
7225f757f3fSDimitry Andric   MCOperand MCRegOp = Inst.getOperand(0);
7235f757f3fSDimitry Andric   MCOperand MCValOp = Inst.getOperand(1);
7245f757f3fSDimitry Andric   MCOperand MCTmpOp = Inst.getOperand(2);
7255f757f3fSDimitry Andric   assert(MCRegOp.isReg() && MCTmpOp.isReg());
7265f757f3fSDimitry Andric   assert(MCValOp.isImm() || MCValOp.isExpr());
7275f757f3fSDimitry Andric 
7285f757f3fSDimitry Andric   // the imm operand can be either an expression or an immediate.
7295f757f3fSDimitry Andric   bool IsImm = MCValOp.isImm();
7305f757f3fSDimitry Andric   int64_t ImmValue = IsImm ? MCValOp.getImm() : 0;
7315f757f3fSDimitry Andric 
7325f757f3fSDimitry Andric   const MCExpr *ValExpr = IsImm ? MCConstantExpr::create(ImmValue, getContext())
7335f757f3fSDimitry Andric                                 : MCValOp.getExpr();
7345f757f3fSDimitry Andric 
7355f757f3fSDimitry Andric   // Very small immediates can be expressed directly as a single `or`.
7365f757f3fSDimitry Andric   if (IsImm && isInt<13>(ImmValue)) {
7375f757f3fSDimitry Andric     // or rd, val, rd
7385f757f3fSDimitry Andric     Instructions.push_back(MCInstBuilder(SP::ORri)
7395f757f3fSDimitry Andric                                .addReg(MCRegOp.getReg())
7405f757f3fSDimitry Andric                                .addReg(Sparc::G0)
7415f757f3fSDimitry Andric                                .addExpr(ValExpr));
7425f757f3fSDimitry Andric     return false;
7435f757f3fSDimitry Andric   }
7445f757f3fSDimitry Andric 
7455f757f3fSDimitry Andric   // Otherwise, first we set the lower half of the register.
7465f757f3fSDimitry Andric 
7475f757f3fSDimitry Andric   // sethi %hi(val), rd
7485f757f3fSDimitry Andric   Instructions.push_back(
7495f757f3fSDimitry Andric       MCInstBuilder(SP::SETHIi)
7505f757f3fSDimitry Andric           .addReg(MCRegOp.getReg())
7515f757f3fSDimitry Andric           .addExpr(adjustPICRelocation(SparcMCExpr::VK_Sparc_HI, ValExpr)));
7525f757f3fSDimitry Andric   // or    rd, %lo(val), rd
7535f757f3fSDimitry Andric   Instructions.push_back(
7545f757f3fSDimitry Andric       MCInstBuilder(SP::ORri)
7555f757f3fSDimitry Andric           .addReg(MCRegOp.getReg())
7565f757f3fSDimitry Andric           .addReg(MCRegOp.getReg())
7575f757f3fSDimitry Andric           .addExpr(adjustPICRelocation(SparcMCExpr::VK_Sparc_LO, ValExpr)));
7585f757f3fSDimitry Andric 
7595f757f3fSDimitry Andric   // Small positive immediates can be expressed as a single `sethi`+`or`
7605f757f3fSDimitry Andric   // combination, so we can just return here.
7615f757f3fSDimitry Andric   if (IsImm && isUInt<32>(ImmValue))
7625f757f3fSDimitry Andric     return false;
7635f757f3fSDimitry Andric 
7645f757f3fSDimitry Andric   // For bigger immediates, we need to generate the upper half, then shift and
7655f757f3fSDimitry Andric   // merge it with the lower half that has just been generated above.
7665f757f3fSDimitry Andric 
7675f757f3fSDimitry Andric   // sethi %hh(val), tmp
7685f757f3fSDimitry Andric   Instructions.push_back(
7695f757f3fSDimitry Andric       MCInstBuilder(SP::SETHIi)
7705f757f3fSDimitry Andric           .addReg(MCTmpOp.getReg())
7715f757f3fSDimitry Andric           .addExpr(adjustPICRelocation(SparcMCExpr::VK_Sparc_HH, ValExpr)));
7725f757f3fSDimitry Andric   // or    tmp, %hm(val), tmp
7735f757f3fSDimitry Andric   Instructions.push_back(
7745f757f3fSDimitry Andric       MCInstBuilder(SP::ORri)
7755f757f3fSDimitry Andric           .addReg(MCTmpOp.getReg())
7765f757f3fSDimitry Andric           .addReg(MCTmpOp.getReg())
7775f757f3fSDimitry Andric           .addExpr(adjustPICRelocation(SparcMCExpr::VK_Sparc_HM, ValExpr)));
7785f757f3fSDimitry Andric   // sllx  tmp, 32, tmp
7795f757f3fSDimitry Andric   Instructions.push_back(MCInstBuilder(SP::SLLXri)
7805f757f3fSDimitry Andric                              .addReg(MCTmpOp.getReg())
7815f757f3fSDimitry Andric                              .addReg(MCTmpOp.getReg())
7825f757f3fSDimitry Andric                              .addImm(32));
7835f757f3fSDimitry Andric   // or    tmp, rd, rd
7845f757f3fSDimitry Andric   Instructions.push_back(MCInstBuilder(SP::ORrr)
7855f757f3fSDimitry Andric                              .addReg(MCRegOp.getReg())
7865f757f3fSDimitry Andric                              .addReg(MCTmpOp.getReg())
7875f757f3fSDimitry Andric                              .addReg(MCRegOp.getReg()));
7885f757f3fSDimitry Andric 
7895f757f3fSDimitry Andric   return false;
7905f757f3fSDimitry Andric }
7915f757f3fSDimitry Andric 
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)7920b57cec5SDimitry Andric bool SparcAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
7930b57cec5SDimitry Andric                                              OperandVector &Operands,
7940b57cec5SDimitry Andric                                              MCStreamer &Out,
7950b57cec5SDimitry Andric                                              uint64_t &ErrorInfo,
7960b57cec5SDimitry Andric                                              bool MatchingInlineAsm) {
7970b57cec5SDimitry Andric   MCInst Inst;
7980b57cec5SDimitry Andric   SmallVector<MCInst, 8> Instructions;
7990b57cec5SDimitry Andric   unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
8000b57cec5SDimitry Andric                                               MatchingInlineAsm);
8010b57cec5SDimitry Andric   switch (MatchResult) {
8020b57cec5SDimitry Andric   case Match_Success: {
8030b57cec5SDimitry Andric     switch (Inst.getOpcode()) {
8040b57cec5SDimitry Andric     default:
8050b57cec5SDimitry Andric       Inst.setLoc(IDLoc);
8060b57cec5SDimitry Andric       Instructions.push_back(Inst);
8070b57cec5SDimitry Andric       break;
8080b57cec5SDimitry Andric     case SP::SET:
8090b57cec5SDimitry Andric       if (expandSET(Inst, IDLoc, Instructions))
8100b57cec5SDimitry Andric         return true;
8110b57cec5SDimitry Andric       break;
8125f757f3fSDimitry Andric     case SP::SETX:
8135f757f3fSDimitry Andric       if (expandSETX(Inst, IDLoc, Instructions))
8145f757f3fSDimitry Andric         return true;
8155f757f3fSDimitry Andric       break;
8160b57cec5SDimitry Andric     }
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric     for (const MCInst &I : Instructions) {
8195ffd83dbSDimitry Andric       Out.emitInstruction(I, getSTI());
8200b57cec5SDimitry Andric     }
8210b57cec5SDimitry Andric     return false;
8220b57cec5SDimitry Andric   }
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric   case Match_MissingFeature:
8250b57cec5SDimitry Andric     return Error(IDLoc,
8260b57cec5SDimitry Andric                  "instruction requires a CPU feature not currently enabled");
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric   case Match_InvalidOperand: {
8290b57cec5SDimitry Andric     SMLoc ErrorLoc = IDLoc;
8300b57cec5SDimitry Andric     if (ErrorInfo != ~0ULL) {
8310b57cec5SDimitry Andric       if (ErrorInfo >= Operands.size())
8320b57cec5SDimitry Andric         return Error(IDLoc, "too few operands for instruction");
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric       ErrorLoc = ((SparcOperand &)*Operands[ErrorInfo]).getStartLoc();
8350b57cec5SDimitry Andric       if (ErrorLoc == SMLoc())
8360b57cec5SDimitry Andric         ErrorLoc = IDLoc;
8370b57cec5SDimitry Andric     }
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric     return Error(ErrorLoc, "invalid operand for instruction");
8400b57cec5SDimitry Andric   }
8410b57cec5SDimitry Andric   case Match_MnemonicFail:
8420b57cec5SDimitry Andric     return Error(IDLoc, "invalid instruction mnemonic");
8430b57cec5SDimitry Andric   }
8440b57cec5SDimitry Andric   llvm_unreachable("Implement any new match types added!");
8450b57cec5SDimitry Andric }
8460b57cec5SDimitry Andric 
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)8475f757f3fSDimitry Andric bool SparcAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
8480b57cec5SDimitry Andric                                    SMLoc &EndLoc) {
8495f757f3fSDimitry Andric   if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
8505ffd83dbSDimitry Andric     return Error(StartLoc, "invalid register name");
8515ffd83dbSDimitry Andric   return false;
8525ffd83dbSDimitry Andric }
8535ffd83dbSDimitry Andric 
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)8545f757f3fSDimitry Andric ParseStatus SparcAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
8555ffd83dbSDimitry Andric                                              SMLoc &EndLoc) {
8560b57cec5SDimitry Andric   const AsmToken &Tok = Parser.getTok();
8570b57cec5SDimitry Andric   StartLoc = Tok.getLoc();
8580b57cec5SDimitry Andric   EndLoc = Tok.getEndLoc();
8595f757f3fSDimitry Andric   Reg = Sparc::NoRegister;
8600b57cec5SDimitry Andric   if (getLexer().getKind() != AsmToken::Percent)
8615f757f3fSDimitry Andric     return ParseStatus::NoMatch;
8620b57cec5SDimitry Andric   Parser.Lex();
863*0fca6ea1SDimitry Andric   unsigned RegKind = SparcOperand::rk_None;
864*0fca6ea1SDimitry Andric   Reg = matchRegisterName(Tok, RegKind);
865*0fca6ea1SDimitry Andric   if (Reg) {
8660b57cec5SDimitry Andric     Parser.Lex();
8675f757f3fSDimitry Andric     return ParseStatus::Success;
8680b57cec5SDimitry Andric   }
8690b57cec5SDimitry Andric 
8705ffd83dbSDimitry Andric   getLexer().UnLex(Tok);
8715f757f3fSDimitry Andric   return ParseStatus::NoMatch;
8720b57cec5SDimitry Andric }
8730b57cec5SDimitry Andric 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)8740b57cec5SDimitry Andric bool SparcAsmParser::ParseInstruction(ParseInstructionInfo &Info,
8750b57cec5SDimitry Andric                                       StringRef Name, SMLoc NameLoc,
8760b57cec5SDimitry Andric                                       OperandVector &Operands) {
877*0fca6ea1SDimitry Andric   // Validate and reject unavailable mnemonics early before
878*0fca6ea1SDimitry Andric   // running any operand parsing.
879*0fca6ea1SDimitry Andric   // This is needed because some operands (mainly memory ones)
880*0fca6ea1SDimitry Andric   // differ between V8 and V9 ISA and so any operand parsing errors
881*0fca6ea1SDimitry Andric   // will cause IAS to bail out before it reaches MatchAndEmitInstruction
882*0fca6ea1SDimitry Andric   // (where the instruction as a whole, including the mnemonic, is validated
883*0fca6ea1SDimitry Andric   // once again just before emission).
884*0fca6ea1SDimitry Andric   // As a nice side effect this also allows us to reject unknown
885*0fca6ea1SDimitry Andric   // instructions and suggest replacements.
886*0fca6ea1SDimitry Andric   MatchResultTy MS = mnemonicIsValid(Name, 0);
887*0fca6ea1SDimitry Andric   switch (MS) {
888*0fca6ea1SDimitry Andric   case Match_Success:
889*0fca6ea1SDimitry Andric     break;
890*0fca6ea1SDimitry Andric   case Match_MissingFeature:
891*0fca6ea1SDimitry Andric     return Error(NameLoc,
892*0fca6ea1SDimitry Andric                  "instruction requires a CPU feature not currently enabled");
893*0fca6ea1SDimitry Andric   case Match_MnemonicFail:
894*0fca6ea1SDimitry Andric     return Error(NameLoc,
895*0fca6ea1SDimitry Andric                  "invalid instruction mnemonic" +
896*0fca6ea1SDimitry Andric                      SparcMnemonicSpellCheck(Name, getAvailableFeatures(), 0));
897*0fca6ea1SDimitry Andric   default:
898*0fca6ea1SDimitry Andric     llvm_unreachable("invalid return status!");
899*0fca6ea1SDimitry Andric   }
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric   // First operand in MCInst is instruction mnemonic.
9020b57cec5SDimitry Andric   Operands.push_back(SparcOperand::CreateToken(Name, NameLoc));
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric   // apply mnemonic aliases, if any, so that we can parse operands correctly.
9050b57cec5SDimitry Andric   applyMnemonicAliases(Name, getAvailableFeatures(), 0);
9060b57cec5SDimitry Andric 
9070b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
9080b57cec5SDimitry Andric     // Read the first operand.
9090b57cec5SDimitry Andric     if (getLexer().is(AsmToken::Comma)) {
9105f757f3fSDimitry Andric       if (!parseBranchModifiers(Operands).isSuccess()) {
9110b57cec5SDimitry Andric         SMLoc Loc = getLexer().getLoc();
9120b57cec5SDimitry Andric         return Error(Loc, "unexpected token");
9130b57cec5SDimitry Andric       }
9140b57cec5SDimitry Andric     }
9155f757f3fSDimitry Andric     if (!parseOperand(Operands, Name).isSuccess()) {
9160b57cec5SDimitry Andric       SMLoc Loc = getLexer().getLoc();
9170b57cec5SDimitry Andric       return Error(Loc, "unexpected token");
9180b57cec5SDimitry Andric     }
9190b57cec5SDimitry Andric 
9200b57cec5SDimitry Andric     while (getLexer().is(AsmToken::Comma) || getLexer().is(AsmToken::Plus)) {
9210b57cec5SDimitry Andric       if (getLexer().is(AsmToken::Plus)) {
9220b57cec5SDimitry Andric       // Plus tokens are significant in software_traps (p83, sparcv8.pdf). We must capture them.
9230b57cec5SDimitry Andric         Operands.push_back(SparcOperand::CreateToken("+", Parser.getTok().getLoc()));
9240b57cec5SDimitry Andric       }
9250b57cec5SDimitry Andric       Parser.Lex(); // Eat the comma or plus.
9260b57cec5SDimitry Andric       // Parse and remember the operand.
9275f757f3fSDimitry Andric       if (!parseOperand(Operands, Name).isSuccess()) {
9280b57cec5SDimitry Andric         SMLoc Loc = getLexer().getLoc();
9290b57cec5SDimitry Andric         return Error(Loc, "unexpected token");
9300b57cec5SDimitry Andric       }
9310b57cec5SDimitry Andric     }
9320b57cec5SDimitry Andric   }
9330b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
9340b57cec5SDimitry Andric     SMLoc Loc = getLexer().getLoc();
9350b57cec5SDimitry Andric     return Error(Loc, "unexpected token");
9360b57cec5SDimitry Andric   }
9370b57cec5SDimitry Andric   Parser.Lex(); // Consume the EndOfStatement.
9380b57cec5SDimitry Andric   return false;
9390b57cec5SDimitry Andric }
9400b57cec5SDimitry Andric 
parseDirective(AsmToken DirectiveID)94106c3fb27SDimitry Andric ParseStatus SparcAsmParser::parseDirective(AsmToken DirectiveID) {
9420b57cec5SDimitry Andric   StringRef IDVal = DirectiveID.getString();
9430b57cec5SDimitry Andric 
9440b57cec5SDimitry Andric   if (IDVal == ".register") {
9450b57cec5SDimitry Andric     // For now, ignore .register directive.
9460b57cec5SDimitry Andric     Parser.eatToEndOfStatement();
94706c3fb27SDimitry Andric     return ParseStatus::Success;
9480b57cec5SDimitry Andric   }
9490b57cec5SDimitry Andric   if (IDVal == ".proc") {
9500b57cec5SDimitry Andric     // For compatibility, ignore this directive.
9510b57cec5SDimitry Andric     // (It's supposed to be an "optimization" in the Sun assembler)
9520b57cec5SDimitry Andric     Parser.eatToEndOfStatement();
95306c3fb27SDimitry Andric     return ParseStatus::Success;
9540b57cec5SDimitry Andric   }
9550b57cec5SDimitry Andric 
9560b57cec5SDimitry Andric   // Let the MC layer to handle other directives.
95706c3fb27SDimitry Andric   return ParseStatus::NoMatch;
9580b57cec5SDimitry Andric }
9590b57cec5SDimitry Andric 
parseMEMOperand(OperandVector & Operands)9605f757f3fSDimitry Andric ParseStatus SparcAsmParser::parseMEMOperand(OperandVector &Operands) {
9610b57cec5SDimitry Andric   SMLoc S, E;
9620b57cec5SDimitry Andric 
963e8d8bef9SDimitry Andric   std::unique_ptr<SparcOperand> LHS;
9645f757f3fSDimitry Andric   if (!parseSparcAsmOperand(LHS).isSuccess())
9655f757f3fSDimitry Andric     return ParseStatus::NoMatch;
9660b57cec5SDimitry Andric 
967e8d8bef9SDimitry Andric   // Single immediate operand
968e8d8bef9SDimitry Andric   if (LHS->isImm()) {
969e8d8bef9SDimitry Andric     Operands.push_back(SparcOperand::MorphToMEMri(Sparc::G0, std::move(LHS)));
9705f757f3fSDimitry Andric     return ParseStatus::Success;
9710b57cec5SDimitry Andric   }
9720b57cec5SDimitry Andric 
9735f757f3fSDimitry Andric   if (!LHS->isIntReg())
9745f757f3fSDimitry Andric     return Error(LHS->getStartLoc(), "invalid register kind for this operand");
975e8d8bef9SDimitry Andric 
976e8d8bef9SDimitry Andric   AsmToken Tok = getLexer().getTok();
977e8d8bef9SDimitry Andric   // The plus token may be followed by a register or an immediate value, the
978e8d8bef9SDimitry Andric   // minus one is always interpreted as sign for the immediate value
979e8d8bef9SDimitry Andric   if (Tok.is(AsmToken::Plus) || Tok.is(AsmToken::Minus)) {
980e8d8bef9SDimitry Andric     (void)Parser.parseOptionalToken(AsmToken::Plus);
981e8d8bef9SDimitry Andric 
982e8d8bef9SDimitry Andric     std::unique_ptr<SparcOperand> RHS;
9835f757f3fSDimitry Andric     if (!parseSparcAsmOperand(RHS).isSuccess())
9845f757f3fSDimitry Andric       return ParseStatus::NoMatch;
9850b57cec5SDimitry Andric 
9865f757f3fSDimitry Andric     if (RHS->isReg() && !RHS->isIntReg())
9875f757f3fSDimitry Andric       return Error(RHS->getStartLoc(),
9885f757f3fSDimitry Andric                    "invalid register kind for this operand");
989e8d8bef9SDimitry Andric 
9900b57cec5SDimitry Andric     Operands.push_back(
991e8d8bef9SDimitry Andric         RHS->isImm()
992e8d8bef9SDimitry Andric             ? SparcOperand::MorphToMEMri(LHS->getReg(), std::move(RHS))
993e8d8bef9SDimitry Andric             : SparcOperand::MorphToMEMrr(LHS->getReg(), std::move(RHS)));
9940b57cec5SDimitry Andric 
9955f757f3fSDimitry Andric     return ParseStatus::Success;
9960b57cec5SDimitry Andric   }
9970b57cec5SDimitry Andric 
998e8d8bef9SDimitry Andric   Operands.push_back(SparcOperand::CreateMEMr(LHS->getReg(), S, E));
9995f757f3fSDimitry Andric   return ParseStatus::Success;
1000e8d8bef9SDimitry Andric }
1001e8d8bef9SDimitry Andric 
1002e8d8bef9SDimitry Andric template <unsigned N>
parseShiftAmtImm(OperandVector & Operands)10035f757f3fSDimitry Andric ParseStatus SparcAsmParser::parseShiftAmtImm(OperandVector &Operands) {
1004e8d8bef9SDimitry Andric   SMLoc S = Parser.getTok().getLoc();
1005e8d8bef9SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1006e8d8bef9SDimitry Andric 
1007e8d8bef9SDimitry Andric   // This is a register, not an immediate
1008e8d8bef9SDimitry Andric   if (getLexer().getKind() == AsmToken::Percent)
10095f757f3fSDimitry Andric     return ParseStatus::NoMatch;
1010e8d8bef9SDimitry Andric 
1011e8d8bef9SDimitry Andric   const MCExpr *Expr;
1012e8d8bef9SDimitry Andric   if (getParser().parseExpression(Expr))
10135f757f3fSDimitry Andric     return ParseStatus::Failure;
1014e8d8bef9SDimitry Andric 
1015e8d8bef9SDimitry Andric   const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
10165f757f3fSDimitry Andric   if (!CE)
10175f757f3fSDimitry Andric     return Error(S, "constant expression expected");
1018e8d8bef9SDimitry Andric 
10195f757f3fSDimitry Andric   if (!isUInt<N>(CE->getValue()))
10205f757f3fSDimitry Andric     return Error(S, "immediate shift value out of range");
1021e8d8bef9SDimitry Andric 
1022e8d8bef9SDimitry Andric   Operands.push_back(SparcOperand::CreateImm(Expr, S, E));
10235f757f3fSDimitry Andric   return ParseStatus::Success;
1024e8d8bef9SDimitry Andric }
1025e8d8bef9SDimitry Andric 
102681ad6265SDimitry Andric template <SparcAsmParser::TailRelocKind Kind>
parseTailRelocSym(OperandVector & Operands)10275f757f3fSDimitry Andric ParseStatus SparcAsmParser::parseTailRelocSym(OperandVector &Operands) {
102881ad6265SDimitry Andric   SMLoc S = getLoc();
102981ad6265SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
103081ad6265SDimitry Andric 
103181ad6265SDimitry Andric   auto MatchesKind = [](SparcMCExpr::VariantKind VK) -> bool {
103281ad6265SDimitry Andric     switch (Kind) {
103381ad6265SDimitry Andric     case TailRelocKind::Load_GOT:
103481ad6265SDimitry Andric       // Non-TLS relocations on ld (or ldx).
103581ad6265SDimitry Andric       // ld [%rr + %rr], %rr, %rel(sym)
103681ad6265SDimitry Andric       return VK == SparcMCExpr::VK_Sparc_GOTDATA_OP;
103781ad6265SDimitry Andric     case TailRelocKind::Add_TLS:
103881ad6265SDimitry Andric       // TLS relocations on add.
103981ad6265SDimitry Andric       // add %rr, %rr, %rr, %rel(sym)
104081ad6265SDimitry Andric       switch (VK) {
104181ad6265SDimitry Andric       case SparcMCExpr::VK_Sparc_TLS_GD_ADD:
104281ad6265SDimitry Andric       case SparcMCExpr::VK_Sparc_TLS_IE_ADD:
104381ad6265SDimitry Andric       case SparcMCExpr::VK_Sparc_TLS_LDM_ADD:
104481ad6265SDimitry Andric       case SparcMCExpr::VK_Sparc_TLS_LDO_ADD:
104581ad6265SDimitry Andric         return true;
104681ad6265SDimitry Andric       default:
104781ad6265SDimitry Andric         return false;
104881ad6265SDimitry Andric       }
104981ad6265SDimitry Andric     case TailRelocKind::Load_TLS:
105081ad6265SDimitry Andric       // TLS relocations on ld (or ldx).
105181ad6265SDimitry Andric       // ld[x] %addr, %rr, %rel(sym)
105281ad6265SDimitry Andric       switch (VK) {
105381ad6265SDimitry Andric       case SparcMCExpr::VK_Sparc_TLS_IE_LD:
105481ad6265SDimitry Andric       case SparcMCExpr::VK_Sparc_TLS_IE_LDX:
105581ad6265SDimitry Andric         return true;
105681ad6265SDimitry Andric       default:
105781ad6265SDimitry Andric         return false;
105881ad6265SDimitry Andric       }
105981ad6265SDimitry Andric     case TailRelocKind::Call_TLS:
106081ad6265SDimitry Andric       // TLS relocations on call.
106181ad6265SDimitry Andric       // call sym, %rel(sym)
106281ad6265SDimitry Andric       switch (VK) {
106381ad6265SDimitry Andric       case SparcMCExpr::VK_Sparc_TLS_GD_CALL:
106481ad6265SDimitry Andric       case SparcMCExpr::VK_Sparc_TLS_LDM_CALL:
106581ad6265SDimitry Andric         return true;
106681ad6265SDimitry Andric       default:
106781ad6265SDimitry Andric         return false;
106881ad6265SDimitry Andric       }
106981ad6265SDimitry Andric     }
107081ad6265SDimitry Andric     llvm_unreachable("Unhandled SparcAsmParser::TailRelocKind enum");
107181ad6265SDimitry Andric   };
107281ad6265SDimitry Andric 
10735f757f3fSDimitry Andric   if (getLexer().getKind() != AsmToken::Percent)
10745f757f3fSDimitry Andric     return Error(getLoc(), "expected '%' for operand modifier");
107581ad6265SDimitry Andric 
107681ad6265SDimitry Andric   const AsmToken Tok = Parser.getTok();
107781ad6265SDimitry Andric   getParser().Lex(); // Eat '%'
107881ad6265SDimitry Andric 
10795f757f3fSDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
10805f757f3fSDimitry Andric     return Error(getLoc(), "expected valid identifier for operand modifier");
108181ad6265SDimitry Andric 
108281ad6265SDimitry Andric   StringRef Name = getParser().getTok().getIdentifier();
108381ad6265SDimitry Andric   SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(Name);
10845f757f3fSDimitry Andric   if (VK == SparcMCExpr::VK_Sparc_None)
10855f757f3fSDimitry Andric     return Error(getLoc(), "invalid operand modifier");
108681ad6265SDimitry Andric 
108781ad6265SDimitry Andric   if (!MatchesKind(VK)) {
108881ad6265SDimitry Andric     // Did not match the specified set of relocation types, put '%' back.
108981ad6265SDimitry Andric     getLexer().UnLex(Tok);
10905f757f3fSDimitry Andric     return ParseStatus::NoMatch;
109181ad6265SDimitry Andric   }
109281ad6265SDimitry Andric 
109381ad6265SDimitry Andric   Parser.Lex(); // Eat the identifier.
10945f757f3fSDimitry Andric   if (getLexer().getKind() != AsmToken::LParen)
10955f757f3fSDimitry Andric     return Error(getLoc(), "expected '('");
109681ad6265SDimitry Andric 
109781ad6265SDimitry Andric   getParser().Lex(); // Eat '('
109881ad6265SDimitry Andric   const MCExpr *SubExpr;
10995f757f3fSDimitry Andric   if (getParser().parseParenExpression(SubExpr, E))
11005f757f3fSDimitry Andric     return ParseStatus::Failure;
110181ad6265SDimitry Andric 
110281ad6265SDimitry Andric   const MCExpr *Val = adjustPICRelocation(VK, SubExpr);
110381ad6265SDimitry Andric   Operands.push_back(SparcOperand::CreateImm(Val, S, E));
11045f757f3fSDimitry Andric   return ParseStatus::Success;
110581ad6265SDimitry Andric }
110681ad6265SDimitry Andric 
parseMembarTag(OperandVector & Operands)11075f757f3fSDimitry Andric ParseStatus SparcAsmParser::parseMembarTag(OperandVector &Operands) {
11080b57cec5SDimitry Andric   SMLoc S = Parser.getTok().getLoc();
11090b57cec5SDimitry Andric   const MCExpr *EVal;
11100b57cec5SDimitry Andric   int64_t ImmVal = 0;
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric   std::unique_ptr<SparcOperand> Mask;
11135f757f3fSDimitry Andric   if (parseSparcAsmOperand(Mask).isSuccess()) {
11140b57cec5SDimitry Andric     if (!Mask->isImm() || !Mask->getImm()->evaluateAsAbsolute(ImmVal) ||
11155f757f3fSDimitry Andric         ImmVal < 0 || ImmVal > 127)
11165f757f3fSDimitry Andric       return Error(S, "invalid membar mask number");
11170b57cec5SDimitry Andric   }
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric   while (getLexer().getKind() == AsmToken::Hash) {
11200b57cec5SDimitry Andric     SMLoc TagStart = getLexer().getLoc();
11210b57cec5SDimitry Andric     Parser.Lex(); // Eat the '#'.
11220b57cec5SDimitry Andric     unsigned MaskVal = StringSwitch<unsigned>(Parser.getTok().getString())
11230b57cec5SDimitry Andric       .Case("LoadLoad", 0x1)
11240b57cec5SDimitry Andric       .Case("StoreLoad", 0x2)
11250b57cec5SDimitry Andric       .Case("LoadStore", 0x4)
11260b57cec5SDimitry Andric       .Case("StoreStore", 0x8)
11270b57cec5SDimitry Andric       .Case("Lookaside", 0x10)
11280b57cec5SDimitry Andric       .Case("MemIssue", 0x20)
11290b57cec5SDimitry Andric       .Case("Sync", 0x40)
11300b57cec5SDimitry Andric       .Default(0);
11310b57cec5SDimitry Andric 
11320b57cec5SDimitry Andric     Parser.Lex(); // Eat the identifier token.
11330b57cec5SDimitry Andric 
11345f757f3fSDimitry Andric     if (!MaskVal)
11355f757f3fSDimitry Andric       return Error(TagStart, "unknown membar tag");
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric     ImmVal |= MaskVal;
11380b57cec5SDimitry Andric 
11390b57cec5SDimitry Andric     if (getLexer().getKind() == AsmToken::Pipe)
11400b57cec5SDimitry Andric       Parser.Lex(); // Eat the '|'.
11410b57cec5SDimitry Andric   }
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric   EVal = MCConstantExpr::create(ImmVal, getContext());
11440b57cec5SDimitry Andric   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
11450b57cec5SDimitry Andric   Operands.push_back(SparcOperand::CreateImm(EVal, S, E));
11465f757f3fSDimitry Andric   return ParseStatus::Success;
11470b57cec5SDimitry Andric }
11480b57cec5SDimitry Andric 
parseASITag(OperandVector & Operands)11495f757f3fSDimitry Andric ParseStatus SparcAsmParser::parseASITag(OperandVector &Operands) {
11505f757f3fSDimitry Andric   SMLoc S = Parser.getTok().getLoc();
11515f757f3fSDimitry Andric   SMLoc E = Parser.getTok().getEndLoc();
11525f757f3fSDimitry Andric   int64_t ASIVal = 0;
11535f757f3fSDimitry Andric 
1154*0fca6ea1SDimitry Andric   if (getLexer().getKind() != AsmToken::Hash) {
1155*0fca6ea1SDimitry Andric     // If the ASI tag provided is not a named tag, then it
1156*0fca6ea1SDimitry Andric     // must be a constant expression.
1157*0fca6ea1SDimitry Andric     ParseStatus ParseExprStatus = parseExpression(ASIVal);
1158*0fca6ea1SDimitry Andric     if (!ParseExprStatus.isSuccess())
1159*0fca6ea1SDimitry Andric       return ParseExprStatus;
1160*0fca6ea1SDimitry Andric 
1161*0fca6ea1SDimitry Andric     if (!isUInt<8>(ASIVal))
1162*0fca6ea1SDimitry Andric       return Error(S, "invalid ASI number, must be between 0 and 255");
1163*0fca6ea1SDimitry Andric 
1164*0fca6ea1SDimitry Andric     Operands.push_back(SparcOperand::CreateASITag(ASIVal, S, E));
1165*0fca6ea1SDimitry Andric     return ParseStatus::Success;
1166*0fca6ea1SDimitry Andric   }
1167*0fca6ea1SDimitry Andric 
11685f757f3fSDimitry Andric   // For now we only support named tags for 64-bit/V9 systems.
11695f757f3fSDimitry Andric   // TODO: add support for 32-bit/V8 systems.
11705f757f3fSDimitry Andric   SMLoc TagStart = getLexer().peekTok(false).getLoc();
11715f757f3fSDimitry Andric   Parser.Lex(); // Eat the '#'.
1172*0fca6ea1SDimitry Andric   const StringRef ASIName = Parser.getTok().getString();
1173*0fca6ea1SDimitry Andric   const SparcASITag::ASITag *ASITag = SparcASITag::lookupASITagByName(ASIName);
11745f757f3fSDimitry Andric   if (!ASITag)
11755f757f3fSDimitry Andric     ASITag = SparcASITag::lookupASITagByAltName(ASIName);
11765f757f3fSDimitry Andric   Parser.Lex(); // Eat the identifier token.
11775f757f3fSDimitry Andric 
11785f757f3fSDimitry Andric   if (!ASITag)
11795f757f3fSDimitry Andric     return Error(TagStart, "unknown ASI tag");
11805f757f3fSDimitry Andric 
11815f757f3fSDimitry Andric   ASIVal = ASITag->Encoding;
11825f757f3fSDimitry Andric 
11835f757f3fSDimitry Andric   Operands.push_back(SparcOperand::CreateASITag(ASIVal, S, E));
11845f757f3fSDimitry Andric   return ParseStatus::Success;
11855f757f3fSDimitry Andric }
11865f757f3fSDimitry Andric 
parsePrefetchTag(OperandVector & Operands)1187*0fca6ea1SDimitry Andric ParseStatus SparcAsmParser::parsePrefetchTag(OperandVector &Operands) {
1188*0fca6ea1SDimitry Andric   SMLoc S = Parser.getTok().getLoc();
1189*0fca6ea1SDimitry Andric   SMLoc E = Parser.getTok().getEndLoc();
1190*0fca6ea1SDimitry Andric   int64_t PrefetchVal = 0;
1191*0fca6ea1SDimitry Andric 
1192*0fca6ea1SDimitry Andric   if (getLexer().getKind() != AsmToken::Hash) {
1193*0fca6ea1SDimitry Andric     // If the prefetch tag provided is not a named tag, then it
1194*0fca6ea1SDimitry Andric     // must be a constant expression.
1195*0fca6ea1SDimitry Andric     ParseStatus ParseExprStatus = parseExpression(PrefetchVal);
1196*0fca6ea1SDimitry Andric     if (!ParseExprStatus.isSuccess())
1197*0fca6ea1SDimitry Andric       return ParseExprStatus;
1198*0fca6ea1SDimitry Andric 
1199*0fca6ea1SDimitry Andric     if (!isUInt<8>(PrefetchVal))
1200*0fca6ea1SDimitry Andric       return Error(S, "invalid prefetch number, must be between 0 and 31");
1201*0fca6ea1SDimitry Andric 
1202*0fca6ea1SDimitry Andric     Operands.push_back(SparcOperand::CreatePrefetchTag(PrefetchVal, S, E));
1203*0fca6ea1SDimitry Andric     return ParseStatus::Success;
1204*0fca6ea1SDimitry Andric   }
1205*0fca6ea1SDimitry Andric 
1206*0fca6ea1SDimitry Andric   SMLoc TagStart = getLexer().peekTok(false).getLoc();
1207*0fca6ea1SDimitry Andric   Parser.Lex(); // Eat the '#'.
1208*0fca6ea1SDimitry Andric   const StringRef PrefetchName = Parser.getTok().getString();
1209*0fca6ea1SDimitry Andric   const SparcPrefetchTag::PrefetchTag *PrefetchTag =
1210*0fca6ea1SDimitry Andric       SparcPrefetchTag::lookupPrefetchTagByName(PrefetchName);
1211*0fca6ea1SDimitry Andric   Parser.Lex(); // Eat the identifier token.
1212*0fca6ea1SDimitry Andric 
1213*0fca6ea1SDimitry Andric   if (!PrefetchTag)
1214*0fca6ea1SDimitry Andric     return Error(TagStart, "unknown prefetch tag");
1215*0fca6ea1SDimitry Andric 
1216*0fca6ea1SDimitry Andric   PrefetchVal = PrefetchTag->Encoding;
1217*0fca6ea1SDimitry Andric 
1218*0fca6ea1SDimitry Andric   Operands.push_back(SparcOperand::CreatePrefetchTag(PrefetchVal, S, E));
1219*0fca6ea1SDimitry Andric   return ParseStatus::Success;
1220*0fca6ea1SDimitry Andric }
1221*0fca6ea1SDimitry Andric 
parseCallTarget(OperandVector & Operands)12225f757f3fSDimitry Andric ParseStatus SparcAsmParser::parseCallTarget(OperandVector &Operands) {
1223e8d8bef9SDimitry Andric   SMLoc S = Parser.getTok().getLoc();
1224e8d8bef9SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1225e8d8bef9SDimitry Andric 
1226e8d8bef9SDimitry Andric   switch (getLexer().getKind()) {
1227e8d8bef9SDimitry Andric   default:
12285f757f3fSDimitry Andric     return ParseStatus::NoMatch;
1229e8d8bef9SDimitry Andric   case AsmToken::LParen:
1230e8d8bef9SDimitry Andric   case AsmToken::Integer:
1231e8d8bef9SDimitry Andric   case AsmToken::Identifier:
1232e8d8bef9SDimitry Andric   case AsmToken::Dot:
1233e8d8bef9SDimitry Andric     break;
1234e8d8bef9SDimitry Andric   }
1235e8d8bef9SDimitry Andric 
1236e8d8bef9SDimitry Andric   const MCExpr *DestValue;
1237e8d8bef9SDimitry Andric   if (getParser().parseExpression(DestValue))
12385f757f3fSDimitry Andric     return ParseStatus::NoMatch;
1239e8d8bef9SDimitry Andric 
1240e8d8bef9SDimitry Andric   bool IsPic = getContext().getObjectFileInfo()->isPositionIndependent();
1241e8d8bef9SDimitry Andric   SparcMCExpr::VariantKind Kind =
1242e8d8bef9SDimitry Andric       IsPic ? SparcMCExpr::VK_Sparc_WPLT30 : SparcMCExpr::VK_Sparc_WDISP30;
1243e8d8bef9SDimitry Andric 
1244e8d8bef9SDimitry Andric   const MCExpr *DestExpr = SparcMCExpr::create(Kind, DestValue, getContext());
1245e8d8bef9SDimitry Andric   Operands.push_back(SparcOperand::CreateImm(DestExpr, S, E));
12465f757f3fSDimitry Andric   return ParseStatus::Success;
1247e8d8bef9SDimitry Andric }
1248e8d8bef9SDimitry Andric 
parseOperand(OperandVector & Operands,StringRef Mnemonic)12495f757f3fSDimitry Andric ParseStatus SparcAsmParser::parseOperand(OperandVector &Operands,
12505f757f3fSDimitry Andric                                          StringRef Mnemonic) {
12510b57cec5SDimitry Andric 
12525f757f3fSDimitry Andric   ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
12530b57cec5SDimitry Andric 
12540b57cec5SDimitry Andric   // If there wasn't a custom match, try the generic matcher below. Otherwise,
12550b57cec5SDimitry Andric   // there was a match, but an error occurred, in which case, just return that
12560b57cec5SDimitry Andric   // the operand parsing failed.
12575f757f3fSDimitry Andric   if (Res.isSuccess() || Res.isFailure())
12585f757f3fSDimitry Andric     return Res;
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric   if (getLexer().is(AsmToken::LBrac)) {
12610b57cec5SDimitry Andric     // Memory operand
12620b57cec5SDimitry Andric     Operands.push_back(SparcOperand::CreateToken("[",
12630b57cec5SDimitry Andric                                                  Parser.getTok().getLoc()));
12640b57cec5SDimitry Andric     Parser.Lex(); // Eat the [
12650b57cec5SDimitry Andric 
12665f757f3fSDimitry Andric     if (Mnemonic == "cas" || Mnemonic == "casl" || Mnemonic == "casa" ||
12675f757f3fSDimitry Andric         Mnemonic == "casx" || Mnemonic == "casxl" || Mnemonic == "casxa") {
12680b57cec5SDimitry Andric       SMLoc S = Parser.getTok().getLoc();
12690b57cec5SDimitry Andric       if (getLexer().getKind() != AsmToken::Percent)
12705f757f3fSDimitry Andric         return ParseStatus::NoMatch;
12710b57cec5SDimitry Andric       Parser.Lex(); // eat %
12720b57cec5SDimitry Andric 
1273bdd1243dSDimitry Andric       unsigned RegKind;
1274*0fca6ea1SDimitry Andric       MCRegister Reg = matchRegisterName(Parser.getTok(), RegKind);
1275*0fca6ea1SDimitry Andric       if (!Reg)
12765f757f3fSDimitry Andric         return ParseStatus::NoMatch;
12770b57cec5SDimitry Andric 
12780b57cec5SDimitry Andric       Parser.Lex(); // Eat the identifier token.
12790b57cec5SDimitry Andric       SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
1280*0fca6ea1SDimitry Andric       Operands.push_back(SparcOperand::CreateReg(Reg, RegKind, S, E));
12815f757f3fSDimitry Andric       Res = ParseStatus::Success;
12820b57cec5SDimitry Andric     } else {
12835f757f3fSDimitry Andric       Res = parseMEMOperand(Operands);
12840b57cec5SDimitry Andric     }
12850b57cec5SDimitry Andric 
12865f757f3fSDimitry Andric     if (!Res.isSuccess())
12875f757f3fSDimitry Andric       return Res;
12880b57cec5SDimitry Andric 
12890b57cec5SDimitry Andric     if (!getLexer().is(AsmToken::RBrac))
12905f757f3fSDimitry Andric       return ParseStatus::Failure;
12910b57cec5SDimitry Andric 
12920b57cec5SDimitry Andric     Operands.push_back(SparcOperand::CreateToken("]",
12930b57cec5SDimitry Andric                                                  Parser.getTok().getLoc()));
12940b57cec5SDimitry Andric     Parser.Lex(); // Eat the ]
12950b57cec5SDimitry Andric 
12960b57cec5SDimitry Andric     // Parse an optional address-space identifier after the address.
12975f757f3fSDimitry Andric     // This will be either an immediate constant expression, or, on 64-bit
12985f757f3fSDimitry Andric     // processors, the %asi register.
1299*0fca6ea1SDimitry Andric     if (getLexer().is(AsmToken::Percent)) {
13005f757f3fSDimitry Andric       SMLoc S = Parser.getTok().getLoc();
1301*0fca6ea1SDimitry Andric       if (!is64Bit())
1302*0fca6ea1SDimitry Andric         return Error(
1303*0fca6ea1SDimitry Andric             S, "malformed ASI tag, must be a constant integer expression");
1304*0fca6ea1SDimitry Andric 
13055f757f3fSDimitry Andric       Parser.Lex(); // Eat the %.
13065f757f3fSDimitry Andric       const AsmToken Tok = Parser.getTok();
13075f757f3fSDimitry Andric       if (Tok.is(AsmToken::Identifier) && Tok.getString() == "asi") {
13085f757f3fSDimitry Andric         // Here we patch the MEM operand from [base + %g0] into [base + 0]
13095f757f3fSDimitry Andric         // as memory operations with ASI tag stored in %asi register needs
13105f757f3fSDimitry Andric         // to use immediate offset. We need to do this because Reg addressing
13115f757f3fSDimitry Andric         // will be parsed as Reg+G0 initially.
13125f757f3fSDimitry Andric         // This allows forms such as `ldxa [%o0] %asi, %o0` to parse correctly.
13135f757f3fSDimitry Andric         SparcOperand &OldMemOp = (SparcOperand &)*Operands[Operands.size() - 2];
13145f757f3fSDimitry Andric         if (OldMemOp.isMEMrr()) {
13155f757f3fSDimitry Andric           if (OldMemOp.getMemOffsetReg() != Sparc::G0) {
13165f757f3fSDimitry Andric             return Error(S, "invalid operand for instruction");
13170b57cec5SDimitry Andric           }
13185f757f3fSDimitry Andric           Operands[Operands.size() - 2] = SparcOperand::MorphToMEMri(
13195f757f3fSDimitry Andric               OldMemOp.getMemBase(),
13205f757f3fSDimitry Andric               SparcOperand::CreateImm(MCConstantExpr::create(0, getContext()),
13215f757f3fSDimitry Andric                                       OldMemOp.getStartLoc(),
13225f757f3fSDimitry Andric                                       OldMemOp.getEndLoc()));
13235f757f3fSDimitry Andric         }
13245f757f3fSDimitry Andric         Parser.Lex(); // Eat the identifier.
13255f757f3fSDimitry Andric         // In this context, we convert the register operand into
13265f757f3fSDimitry Andric         // a plain "%asi" token since the register access is already
13275f757f3fSDimitry Andric         // implicit in the instruction definition and encoding.
13285f757f3fSDimitry Andric         // See LoadASI/StoreASI in SparcInstrInfo.td.
13295f757f3fSDimitry Andric         Operands.push_back(SparcOperand::CreateToken("%asi", S));
13305f757f3fSDimitry Andric         return ParseStatus::Success;
13315f757f3fSDimitry Andric       }
13325f757f3fSDimitry Andric 
13335f757f3fSDimitry Andric       return Error(S, "malformed ASI tag, must be %asi, a constant integer "
13345f757f3fSDimitry Andric                       "expression, or a named tag");
13355f757f3fSDimitry Andric     }
13365f757f3fSDimitry Andric 
13375f757f3fSDimitry Andric     // If we're not at the end of statement and the next token is not a comma,
13385f757f3fSDimitry Andric     // then it is an immediate ASI value.
13395f757f3fSDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement) &&
13405f757f3fSDimitry Andric         getLexer().isNot(AsmToken::Comma))
13415f757f3fSDimitry Andric       return parseASITag(Operands);
13425f757f3fSDimitry Andric     return ParseStatus::Success;
13430b57cec5SDimitry Andric   }
13440b57cec5SDimitry Andric 
13450b57cec5SDimitry Andric   std::unique_ptr<SparcOperand> Op;
13460b57cec5SDimitry Andric 
13475f757f3fSDimitry Andric   Res = parseSparcAsmOperand(Op, (Mnemonic == "call"));
13485f757f3fSDimitry Andric   if (!Res.isSuccess() || !Op)
13495f757f3fSDimitry Andric     return ParseStatus::Failure;
13500b57cec5SDimitry Andric 
13510b57cec5SDimitry Andric   // Push the parsed operand into the list of operands
13520b57cec5SDimitry Andric   Operands.push_back(std::move(Op));
13530b57cec5SDimitry Andric 
13545f757f3fSDimitry Andric   return ParseStatus::Success;
13550b57cec5SDimitry Andric }
13560b57cec5SDimitry Andric 
13575f757f3fSDimitry Andric ParseStatus
parseSparcAsmOperand(std::unique_ptr<SparcOperand> & Op,bool isCall)13580b57cec5SDimitry Andric SparcAsmParser::parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Op,
13590b57cec5SDimitry Andric                                      bool isCall) {
13600b57cec5SDimitry Andric   SMLoc S = Parser.getTok().getLoc();
13610b57cec5SDimitry Andric   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
13620b57cec5SDimitry Andric   const MCExpr *EVal;
13630b57cec5SDimitry Andric 
13640b57cec5SDimitry Andric   Op = nullptr;
13650b57cec5SDimitry Andric   switch (getLexer().getKind()) {
13660b57cec5SDimitry Andric   default:  break;
13670b57cec5SDimitry Andric 
1368bdd1243dSDimitry Andric   case AsmToken::Percent: {
13690b57cec5SDimitry Andric     Parser.Lex(); // Eat the '%'.
13700b57cec5SDimitry Andric     unsigned RegKind;
1371*0fca6ea1SDimitry Andric     if (MCRegister Reg = matchRegisterName(Parser.getTok(), RegKind)) {
13725f757f3fSDimitry Andric       StringRef Name = Parser.getTok().getString();
13730b57cec5SDimitry Andric       Parser.Lex(); // Eat the identifier token.
13740b57cec5SDimitry Andric       E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
13755f757f3fSDimitry Andric       if (Reg == Sparc::ICC && Name == "xcc")
13760b57cec5SDimitry Andric         Op = SparcOperand::CreateToken("%xcc", S);
13770b57cec5SDimitry Andric       else
13785f757f3fSDimitry Andric         Op = SparcOperand::CreateReg(Reg, RegKind, S, E);
13790b57cec5SDimitry Andric       break;
13800b57cec5SDimitry Andric     }
13810b57cec5SDimitry Andric     if (matchSparcAsmModifiers(EVal, E)) {
13820b57cec5SDimitry Andric       E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
13830b57cec5SDimitry Andric       Op = SparcOperand::CreateImm(EVal, S, E);
13840b57cec5SDimitry Andric     }
13850b57cec5SDimitry Andric     break;
1386bdd1243dSDimitry Andric   }
13870b57cec5SDimitry Andric 
1388e8d8bef9SDimitry Andric   case AsmToken::Plus:
13890b57cec5SDimitry Andric   case AsmToken::Minus:
13900b57cec5SDimitry Andric   case AsmToken::Integer:
13910b57cec5SDimitry Andric   case AsmToken::LParen:
13920b57cec5SDimitry Andric   case AsmToken::Dot:
1393fe6060f1SDimitry Andric   case AsmToken::Identifier:
1394fe6060f1SDimitry Andric     if (getParser().parseExpression(EVal, E))
13950b57cec5SDimitry Andric       break;
13960b57cec5SDimitry Andric 
1397fe6060f1SDimitry Andric     int64_t Res;
1398fe6060f1SDimitry Andric     if (!EVal->evaluateAsAbsolute(Res)) {
13990b57cec5SDimitry Andric       SparcMCExpr::VariantKind Kind = SparcMCExpr::VK_Sparc_13;
14000b57cec5SDimitry Andric 
14010b57cec5SDimitry Andric       if (getContext().getObjectFileInfo()->isPositionIndependent()) {
14020b57cec5SDimitry Andric         if (isCall)
14030b57cec5SDimitry Andric           Kind = SparcMCExpr::VK_Sparc_WPLT30;
14040b57cec5SDimitry Andric         else
14050b57cec5SDimitry Andric           Kind = SparcMCExpr::VK_Sparc_GOT13;
14060b57cec5SDimitry Andric       }
1407fe6060f1SDimitry Andric       EVal = SparcMCExpr::create(Kind, EVal, getContext());
14080b57cec5SDimitry Andric     }
1409fe6060f1SDimitry Andric     Op = SparcOperand::CreateImm(EVal, S, E);
14100b57cec5SDimitry Andric     break;
14110b57cec5SDimitry Andric   }
14125f757f3fSDimitry Andric   return Op ? ParseStatus::Success : ParseStatus::Failure;
14130b57cec5SDimitry Andric }
14140b57cec5SDimitry Andric 
parseBranchModifiers(OperandVector & Operands)14155f757f3fSDimitry Andric ParseStatus SparcAsmParser::parseBranchModifiers(OperandVector &Operands) {
14160b57cec5SDimitry Andric   // parse (,a|,pn|,pt)+
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric   while (getLexer().is(AsmToken::Comma)) {
14190b57cec5SDimitry Andric     Parser.Lex(); // Eat the comma
14200b57cec5SDimitry Andric 
14210b57cec5SDimitry Andric     if (!getLexer().is(AsmToken::Identifier))
14225f757f3fSDimitry Andric       return ParseStatus::Failure;
14230b57cec5SDimitry Andric     StringRef modName = Parser.getTok().getString();
14240b57cec5SDimitry Andric     if (modName == "a" || modName == "pn" || modName == "pt") {
14250b57cec5SDimitry Andric       Operands.push_back(SparcOperand::CreateToken(modName,
14260b57cec5SDimitry Andric                                                    Parser.getTok().getLoc()));
14270b57cec5SDimitry Andric       Parser.Lex(); // eat the identifier.
14280b57cec5SDimitry Andric     }
14290b57cec5SDimitry Andric   }
14305f757f3fSDimitry Andric   return ParseStatus::Success;
14310b57cec5SDimitry Andric }
14320b57cec5SDimitry Andric 
parseExpression(int64_t & Val)1433*0fca6ea1SDimitry Andric ParseStatus SparcAsmParser::parseExpression(int64_t &Val) {
1434*0fca6ea1SDimitry Andric   AsmToken Tok = getLexer().getTok();
1435*0fca6ea1SDimitry Andric 
1436*0fca6ea1SDimitry Andric   if (!isPossibleExpression(Tok))
1437*0fca6ea1SDimitry Andric     return ParseStatus::NoMatch;
1438*0fca6ea1SDimitry Andric 
1439*0fca6ea1SDimitry Andric   return getParser().parseAbsoluteExpression(Val);
1440*0fca6ea1SDimitry Andric }
1441*0fca6ea1SDimitry Andric 
matchRegisterName(const AsmToken & Tok,unsigned & RegKind)1442*0fca6ea1SDimitry Andric MCRegister SparcAsmParser::matchRegisterName(const AsmToken &Tok,
14430b57cec5SDimitry Andric                                              unsigned &RegKind) {
14440b57cec5SDimitry Andric   RegKind = SparcOperand::rk_None;
1445*0fca6ea1SDimitry Andric   if (!Tok.is(AsmToken::Identifier))
1446*0fca6ea1SDimitry Andric     return SP::NoRegister;
14470b57cec5SDimitry Andric 
1448*0fca6ea1SDimitry Andric   StringRef Name = Tok.getString();
1449*0fca6ea1SDimitry Andric   MCRegister Reg = MatchRegisterName(Name.lower());
1450*0fca6ea1SDimitry Andric   if (!Reg)
1451*0fca6ea1SDimitry Andric     Reg = MatchRegisterAltName(Name.lower());
1452*0fca6ea1SDimitry Andric 
1453*0fca6ea1SDimitry Andric   if (Reg) {
1454*0fca6ea1SDimitry Andric     // Some registers have identical spellings. The generated matcher might
1455*0fca6ea1SDimitry Andric     // have chosen one or another spelling, e.g. "%fp" or "%i6" might have been
1456*0fca6ea1SDimitry Andric     // matched to either SP::I6 or SP::I6_I7. Other parts of SparcAsmParser
1457*0fca6ea1SDimitry Andric     // are not prepared for this, so we do some canonicalization.
1458*0fca6ea1SDimitry Andric 
1459*0fca6ea1SDimitry Andric     // See the note in SparcRegisterInfo.td near ASRRegs register class.
1460*0fca6ea1SDimitry Andric     if (Reg == SP::ASR4 && Name == "tick") {
1461*0fca6ea1SDimitry Andric       RegKind = SparcOperand::rk_Special;
1462*0fca6ea1SDimitry Andric       return SP::TICK;
1463*0fca6ea1SDimitry Andric     }
1464*0fca6ea1SDimitry Andric 
1465*0fca6ea1SDimitry Andric     if (MRI.getRegClass(SP::IntRegsRegClassID).contains(Reg)) {
14660b57cec5SDimitry Andric       RegKind = SparcOperand::rk_IntReg;
1467*0fca6ea1SDimitry Andric       return Reg;
14680b57cec5SDimitry Andric     }
1469*0fca6ea1SDimitry Andric     if (MRI.getRegClass(SP::FPRegsRegClassID).contains(Reg)) {
14700b57cec5SDimitry Andric       RegKind = SparcOperand::rk_FloatReg;
1471*0fca6ea1SDimitry Andric       return Reg;
14720b57cec5SDimitry Andric     }
1473*0fca6ea1SDimitry Andric     if (MRI.getRegClass(SP::CoprocRegsRegClassID).contains(Reg)) {
1474*0fca6ea1SDimitry Andric       RegKind = SparcOperand::rk_CoprocReg;
1475*0fca6ea1SDimitry Andric       return Reg;
1476*0fca6ea1SDimitry Andric     }
1477*0fca6ea1SDimitry Andric 
1478*0fca6ea1SDimitry Andric     // Canonicalize G0_G1 ... G30_G31 etc. to G0 ... G30.
1479*0fca6ea1SDimitry Andric     if (MRI.getRegClass(SP::IntPairRegClassID).contains(Reg)) {
1480*0fca6ea1SDimitry Andric       RegKind = SparcOperand::rk_IntReg;
1481*0fca6ea1SDimitry Andric       return MRI.getSubReg(Reg, SP::sub_even);
1482*0fca6ea1SDimitry Andric     }
1483*0fca6ea1SDimitry Andric 
1484*0fca6ea1SDimitry Andric     // Canonicalize D0 ... D15 to F0 ... F30.
1485*0fca6ea1SDimitry Andric     if (MRI.getRegClass(SP::DFPRegsRegClassID).contains(Reg)) {
1486*0fca6ea1SDimitry Andric       // D16 ... D31 do not have sub-registers.
1487*0fca6ea1SDimitry Andric       if (MCRegister SubReg = MRI.getSubReg(Reg, SP::sub_even)) {
1488*0fca6ea1SDimitry Andric         RegKind = SparcOperand::rk_FloatReg;
1489*0fca6ea1SDimitry Andric         return SubReg;
1490*0fca6ea1SDimitry Andric       }
14910b57cec5SDimitry Andric       RegKind = SparcOperand::rk_DoubleReg;
1492*0fca6ea1SDimitry Andric       return Reg;
14930b57cec5SDimitry Andric     }
14940b57cec5SDimitry Andric 
1495*0fca6ea1SDimitry Andric     // The generated matcher does not currently return QFP registers.
1496*0fca6ea1SDimitry Andric     // If it changes, we will need to handle them in a similar way.
1497*0fca6ea1SDimitry Andric     assert(!MRI.getRegClass(SP::QFPRegsRegClassID).contains(Reg));
1498*0fca6ea1SDimitry Andric 
1499*0fca6ea1SDimitry Andric     // Canonicalize C0_C1 ... C30_C31 to C0 ... C30.
1500*0fca6ea1SDimitry Andric     if (MRI.getRegClass(SP::CoprocPairRegClassID).contains(Reg)) {
1501*0fca6ea1SDimitry Andric       RegKind = SparcOperand::rk_CoprocReg;
1502*0fca6ea1SDimitry Andric       return MRI.getSubReg(Reg, SP::sub_even);
1503*0fca6ea1SDimitry Andric     }
1504*0fca6ea1SDimitry Andric 
1505*0fca6ea1SDimitry Andric     // Other registers do not need special handling.
1506*0fca6ea1SDimitry Andric     RegKind = SparcOperand::rk_Special;
1507*0fca6ea1SDimitry Andric     return Reg;
1508*0fca6ea1SDimitry Andric   }
1509*0fca6ea1SDimitry Andric 
1510*0fca6ea1SDimitry Andric   // If we still have no match, try custom parsing.
1511*0fca6ea1SDimitry Andric   // Not all registers and their spellings are modeled in td files.
1512*0fca6ea1SDimitry Andric 
15130b57cec5SDimitry Andric   // %r0 - %r31
1514*0fca6ea1SDimitry Andric   int64_t RegNo = 0;
1515*0fca6ea1SDimitry Andric   if (Name.starts_with_insensitive("r") &&
1516*0fca6ea1SDimitry Andric       !Name.substr(1, 2).getAsInteger(10, RegNo) && RegNo < 31) {
15170b57cec5SDimitry Andric     RegKind = SparcOperand::rk_IntReg;
1518*0fca6ea1SDimitry Andric     return IntRegs[RegNo];
15190b57cec5SDimitry Andric   }
15200b57cec5SDimitry Andric 
1521*0fca6ea1SDimitry Andric   if (Name == "xcc") {
1522*0fca6ea1SDimitry Andric     // FIXME:: check 64bit.
15230b57cec5SDimitry Andric     RegKind = SparcOperand::rk_Special;
1524*0fca6ea1SDimitry Andric     return SP::ICC;
15255f757f3fSDimitry Andric   }
15265f757f3fSDimitry Andric 
15275f757f3fSDimitry Andric   // JPS1 extension - aliases for ASRs
1528*0fca6ea1SDimitry Andric   // Section 5.2.11 - Ancillary State Registers (ASRs)
1529*0fca6ea1SDimitry Andric   if (Name == "pcr") {
15305f757f3fSDimitry Andric     RegKind = SparcOperand::rk_Special;
1531*0fca6ea1SDimitry Andric     return SP::ASR16;
15325f757f3fSDimitry Andric   }
1533*0fca6ea1SDimitry Andric   if (Name == "pic") {
15345f757f3fSDimitry Andric     RegKind = SparcOperand::rk_Special;
1535*0fca6ea1SDimitry Andric     return SP::ASR17;
15365f757f3fSDimitry Andric   }
1537*0fca6ea1SDimitry Andric   if (Name == "dcr") {
15385f757f3fSDimitry Andric     RegKind = SparcOperand::rk_Special;
1539*0fca6ea1SDimitry Andric     return SP::ASR18;
15405f757f3fSDimitry Andric   }
1541*0fca6ea1SDimitry Andric   if (Name == "gsr") {
15425f757f3fSDimitry Andric     RegKind = SparcOperand::rk_Special;
1543*0fca6ea1SDimitry Andric     return SP::ASR19;
15445f757f3fSDimitry Andric   }
1545*0fca6ea1SDimitry Andric   if (Name == "set_softint") {
15465f757f3fSDimitry Andric     RegKind = SparcOperand::rk_Special;
1547*0fca6ea1SDimitry Andric     return SP::ASR20;
15485f757f3fSDimitry Andric   }
1549*0fca6ea1SDimitry Andric   if (Name == "clear_softint") {
15505f757f3fSDimitry Andric     RegKind = SparcOperand::rk_Special;
1551*0fca6ea1SDimitry Andric     return SP::ASR21;
15525f757f3fSDimitry Andric   }
1553*0fca6ea1SDimitry Andric   if (Name == "softint") {
15545f757f3fSDimitry Andric     RegKind = SparcOperand::rk_Special;
1555*0fca6ea1SDimitry Andric     return SP::ASR22;
15565f757f3fSDimitry Andric   }
1557*0fca6ea1SDimitry Andric   if (Name == "tick_cmpr") {
1558fe6060f1SDimitry Andric     RegKind = SparcOperand::rk_Special;
1559*0fca6ea1SDimitry Andric     return SP::ASR23;
1560fe6060f1SDimitry Andric   }
1561*0fca6ea1SDimitry Andric   if (Name == "stick" || Name == "sys_tick") {
1562*0fca6ea1SDimitry Andric     RegKind = SparcOperand::rk_Special;
1563*0fca6ea1SDimitry Andric     return SP::ASR24;
15640b57cec5SDimitry Andric   }
1565*0fca6ea1SDimitry Andric   if (Name == "stick_cmpr" || Name == "sys_tick_cmpr") {
1566*0fca6ea1SDimitry Andric     RegKind = SparcOperand::rk_Special;
1567*0fca6ea1SDimitry Andric     return SP::ASR25;
1568*0fca6ea1SDimitry Andric   }
1569*0fca6ea1SDimitry Andric 
1570*0fca6ea1SDimitry Andric   return SP::NoRegister;
15710b57cec5SDimitry Andric }
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric // Determine if an expression contains a reference to the symbol
15740b57cec5SDimitry Andric // "_GLOBAL_OFFSET_TABLE_".
hasGOTReference(const MCExpr * Expr)15750b57cec5SDimitry Andric static bool hasGOTReference(const MCExpr *Expr) {
15760b57cec5SDimitry Andric   switch (Expr->getKind()) {
15770b57cec5SDimitry Andric   case MCExpr::Target:
15780b57cec5SDimitry Andric     if (const SparcMCExpr *SE = dyn_cast<SparcMCExpr>(Expr))
15790b57cec5SDimitry Andric       return hasGOTReference(SE->getSubExpr());
15800b57cec5SDimitry Andric     break;
15810b57cec5SDimitry Andric 
15820b57cec5SDimitry Andric   case MCExpr::Constant:
15830b57cec5SDimitry Andric     break;
15840b57cec5SDimitry Andric 
15850b57cec5SDimitry Andric   case MCExpr::Binary: {
15860b57cec5SDimitry Andric     const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
15870b57cec5SDimitry Andric     return hasGOTReference(BE->getLHS()) || hasGOTReference(BE->getRHS());
15880b57cec5SDimitry Andric   }
15890b57cec5SDimitry Andric 
15900b57cec5SDimitry Andric   case MCExpr::SymbolRef: {
15910b57cec5SDimitry Andric     const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
15920b57cec5SDimitry Andric     return (SymRef.getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_");
15930b57cec5SDimitry Andric   }
15940b57cec5SDimitry Andric 
15950b57cec5SDimitry Andric   case MCExpr::Unary:
15960b57cec5SDimitry Andric     return hasGOTReference(cast<MCUnaryExpr>(Expr)->getSubExpr());
15970b57cec5SDimitry Andric   }
15980b57cec5SDimitry Andric   return false;
15990b57cec5SDimitry Andric }
16000b57cec5SDimitry Andric 
16010b57cec5SDimitry Andric const SparcMCExpr *
adjustPICRelocation(SparcMCExpr::VariantKind VK,const MCExpr * subExpr)16020b57cec5SDimitry Andric SparcAsmParser::adjustPICRelocation(SparcMCExpr::VariantKind VK,
16030b57cec5SDimitry Andric                                     const MCExpr *subExpr) {
16040b57cec5SDimitry Andric   // When in PIC mode, "%lo(...)" and "%hi(...)" behave differently.
1605e8d8bef9SDimitry Andric   // If the expression refers contains _GLOBAL_OFFSET_TABLE, it is
16060b57cec5SDimitry Andric   // actually a %pc10 or %pc22 relocation. Otherwise, they are interpreted
16070b57cec5SDimitry Andric   // as %got10 or %got22 relocation.
16080b57cec5SDimitry Andric 
16090b57cec5SDimitry Andric   if (getContext().getObjectFileInfo()->isPositionIndependent()) {
16100b57cec5SDimitry Andric     switch(VK) {
16110b57cec5SDimitry Andric     default: break;
16120b57cec5SDimitry Andric     case SparcMCExpr::VK_Sparc_LO:
16130b57cec5SDimitry Andric       VK = (hasGOTReference(subExpr) ? SparcMCExpr::VK_Sparc_PC10
16140b57cec5SDimitry Andric                                      : SparcMCExpr::VK_Sparc_GOT10);
16150b57cec5SDimitry Andric       break;
16160b57cec5SDimitry Andric     case SparcMCExpr::VK_Sparc_HI:
16170b57cec5SDimitry Andric       VK = (hasGOTReference(subExpr) ? SparcMCExpr::VK_Sparc_PC22
16180b57cec5SDimitry Andric                                      : SparcMCExpr::VK_Sparc_GOT22);
16190b57cec5SDimitry Andric       break;
16200b57cec5SDimitry Andric     }
16210b57cec5SDimitry Andric   }
16220b57cec5SDimitry Andric 
16230b57cec5SDimitry Andric   return SparcMCExpr::create(VK, subExpr, getContext());
16240b57cec5SDimitry Andric }
16250b57cec5SDimitry Andric 
matchSparcAsmModifiers(const MCExpr * & EVal,SMLoc & EndLoc)16260b57cec5SDimitry Andric bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
16270b57cec5SDimitry Andric                                             SMLoc &EndLoc) {
16280b57cec5SDimitry Andric   AsmToken Tok = Parser.getTok();
16290b57cec5SDimitry Andric   if (!Tok.is(AsmToken::Identifier))
16300b57cec5SDimitry Andric     return false;
16310b57cec5SDimitry Andric 
16320b57cec5SDimitry Andric   StringRef name = Tok.getString();
16330b57cec5SDimitry Andric 
16340b57cec5SDimitry Andric   SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name);
163581ad6265SDimitry Andric   switch (VK) {
163681ad6265SDimitry Andric   case SparcMCExpr::VK_Sparc_None:
163781ad6265SDimitry Andric     Error(getLoc(), "invalid operand modifier");
16380b57cec5SDimitry Andric     return false;
16390b57cec5SDimitry Andric 
164081ad6265SDimitry Andric   case SparcMCExpr::VK_Sparc_GOTDATA_OP:
164181ad6265SDimitry Andric   case SparcMCExpr::VK_Sparc_TLS_GD_ADD:
164281ad6265SDimitry Andric   case SparcMCExpr::VK_Sparc_TLS_GD_CALL:
164381ad6265SDimitry Andric   case SparcMCExpr::VK_Sparc_TLS_IE_ADD:
164481ad6265SDimitry Andric   case SparcMCExpr::VK_Sparc_TLS_IE_LD:
164581ad6265SDimitry Andric   case SparcMCExpr::VK_Sparc_TLS_IE_LDX:
164681ad6265SDimitry Andric   case SparcMCExpr::VK_Sparc_TLS_LDM_ADD:
164781ad6265SDimitry Andric   case SparcMCExpr::VK_Sparc_TLS_LDM_CALL:
164881ad6265SDimitry Andric   case SparcMCExpr::VK_Sparc_TLS_LDO_ADD:
164981ad6265SDimitry Andric     // These are special-cased at tablegen level.
165081ad6265SDimitry Andric     return false;
165181ad6265SDimitry Andric 
165281ad6265SDimitry Andric   default:
165381ad6265SDimitry Andric     break;
165481ad6265SDimitry Andric   }
165581ad6265SDimitry Andric 
16560b57cec5SDimitry Andric   Parser.Lex(); // Eat the identifier.
16570b57cec5SDimitry Andric   if (Parser.getTok().getKind() != AsmToken::LParen)
16580b57cec5SDimitry Andric     return false;
16590b57cec5SDimitry Andric 
16600b57cec5SDimitry Andric   Parser.Lex(); // Eat the LParen token.
16610b57cec5SDimitry Andric   const MCExpr *subExpr;
16620b57cec5SDimitry Andric   if (Parser.parseParenExpression(subExpr, EndLoc))
16630b57cec5SDimitry Andric     return false;
16640b57cec5SDimitry Andric 
16650b57cec5SDimitry Andric   EVal = adjustPICRelocation(VK, subExpr);
16660b57cec5SDimitry Andric   return true;
16670b57cec5SDimitry Andric }
16680b57cec5SDimitry Andric 
isPossibleExpression(const AsmToken & Token)1669*0fca6ea1SDimitry Andric bool SparcAsmParser::isPossibleExpression(const AsmToken &Token) {
1670*0fca6ea1SDimitry Andric   switch (Token.getKind()) {
1671*0fca6ea1SDimitry Andric   case AsmToken::LParen:
1672*0fca6ea1SDimitry Andric   case AsmToken::Integer:
1673*0fca6ea1SDimitry Andric   case AsmToken::Identifier:
1674*0fca6ea1SDimitry Andric   case AsmToken::Plus:
1675*0fca6ea1SDimitry Andric   case AsmToken::Minus:
1676*0fca6ea1SDimitry Andric   case AsmToken::Tilde:
1677*0fca6ea1SDimitry Andric     return true;
1678*0fca6ea1SDimitry Andric   default:
1679*0fca6ea1SDimitry Andric     return false;
1680*0fca6ea1SDimitry Andric   }
1681*0fca6ea1SDimitry Andric }
1682*0fca6ea1SDimitry Andric 
LLVMInitializeSparcAsmParser()1683480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcAsmParser() {
16840b57cec5SDimitry Andric   RegisterMCAsmParser<SparcAsmParser> A(getTheSparcTarget());
16850b57cec5SDimitry Andric   RegisterMCAsmParser<SparcAsmParser> B(getTheSparcV9Target());
16860b57cec5SDimitry Andric   RegisterMCAsmParser<SparcAsmParser> C(getTheSparcelTarget());
16870b57cec5SDimitry Andric }
16880b57cec5SDimitry Andric 
validateTargetOperandClass(MCParsedAsmOperand & GOp,unsigned Kind)16890b57cec5SDimitry Andric unsigned SparcAsmParser::validateTargetOperandClass(MCParsedAsmOperand &GOp,
16900b57cec5SDimitry Andric                                                     unsigned Kind) {
16910b57cec5SDimitry Andric   SparcOperand &Op = (SparcOperand &)GOp;
16920b57cec5SDimitry Andric   if (Op.isFloatOrDoubleReg()) {
16930b57cec5SDimitry Andric     switch (Kind) {
16940b57cec5SDimitry Andric     default: break;
16950b57cec5SDimitry Andric     case MCK_DFPRegs:
16960b57cec5SDimitry Andric       if (!Op.isFloatReg() || SparcOperand::MorphToDoubleReg(Op))
16970b57cec5SDimitry Andric         return MCTargetAsmParser::Match_Success;
16980b57cec5SDimitry Andric       break;
16990b57cec5SDimitry Andric     case MCK_QFPRegs:
17000b57cec5SDimitry Andric       if (SparcOperand::MorphToQuadReg(Op))
17010b57cec5SDimitry Andric         return MCTargetAsmParser::Match_Success;
17020b57cec5SDimitry Andric       break;
17030b57cec5SDimitry Andric     }
17040b57cec5SDimitry Andric   }
17050b57cec5SDimitry Andric   if (Op.isIntReg() && Kind == MCK_IntPair) {
17060b57cec5SDimitry Andric     if (SparcOperand::MorphToIntPairReg(Op))
17070b57cec5SDimitry Andric       return MCTargetAsmParser::Match_Success;
17080b57cec5SDimitry Andric   }
17090b57cec5SDimitry Andric   if (Op.isCoprocReg() && Kind == MCK_CoprocPair) {
17100b57cec5SDimitry Andric      if (SparcOperand::MorphToCoprocPairReg(Op))
17110b57cec5SDimitry Andric        return MCTargetAsmParser::Match_Success;
17120b57cec5SDimitry Andric    }
17130b57cec5SDimitry Andric   return Match_InvalidOperand;
17140b57cec5SDimitry Andric }
1715