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