1262261Sdim//===-- SparcAsmParser.cpp - Parse Sparc assembly to MCInst instructions --===// 2262261Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6262261Sdim// 7262261Sdim//===----------------------------------------------------------------------===// 8262261Sdim 9309124Sdim#include "MCTargetDesc/SparcMCExpr.h" 10262261Sdim#include "MCTargetDesc/SparcMCTargetDesc.h" 11353358Sdim#include "TargetInfo/SparcTargetInfo.h" 12262261Sdim#include "llvm/ADT/STLExtras.h" 13321369Sdim#include "llvm/ADT/SmallVector.h" 14321369Sdim#include "llvm/ADT/StringRef.h" 15321369Sdim#include "llvm/ADT/Triple.h" 16262261Sdim#include "llvm/MC/MCContext.h" 17321369Sdim#include "llvm/MC/MCExpr.h" 18262261Sdim#include "llvm/MC/MCInst.h" 19276479Sdim#include "llvm/MC/MCObjectFileInfo.h" 20321369Sdim#include "llvm/MC/MCParser/MCAsmLexer.h" 21321369Sdim#include "llvm/MC/MCParser/MCAsmParser.h" 22262261Sdim#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 23309124Sdim#include "llvm/MC/MCParser/MCTargetAsmParser.h" 24296417Sdim#include "llvm/MC/MCRegisterInfo.h" 25262261Sdim#include "llvm/MC/MCStreamer.h" 26262261Sdim#include "llvm/MC/MCSubtargetInfo.h" 27276479Sdim#include "llvm/MC/MCSymbol.h" 28321369Sdim#include "llvm/Support/Casting.h" 29321369Sdim#include "llvm/Support/ErrorHandling.h" 30321369Sdim#include "llvm/Support/SMLoc.h" 31262261Sdim#include "llvm/Support/TargetRegistry.h" 32321369Sdim#include "llvm/Support/raw_ostream.h" 33321369Sdim#include <algorithm> 34321369Sdim#include <cassert> 35321369Sdim#include <cstdint> 36321369Sdim#include <memory> 37262261Sdim 38262261Sdimusing namespace llvm; 39262261Sdim 40262261Sdim// The generated AsmMatcher SparcGenAsmMatcher uses "Sparc" as the target 41262261Sdim// namespace. But SPARC backend uses "SP" as its namespace. 42262261Sdimnamespace llvm { 43321369Sdimnamespace Sparc { 44321369Sdim 45262261Sdim using namespace SP; 46262261Sdim 47321369Sdim} // end namespace Sparc 48321369Sdim} // end namespace llvm 49321369Sdim 50262261Sdimnamespace { 51321369Sdim 52262261Sdimclass SparcOperand; 53321369Sdim 54262261Sdimclass SparcAsmParser : public MCTargetAsmParser { 55262261Sdim MCAsmParser &Parser; 56262261Sdim 57262261Sdim /// @name Auto-generated Match Functions 58262261Sdim /// { 59262261Sdim 60262261Sdim#define GET_ASSEMBLER_HEADER 61262261Sdim#include "SparcGenAsmMatcher.inc" 62262261Sdim 63262261Sdim /// } 64262261Sdim 65262261Sdim // public interface of the MCTargetAsmParser. 66262261Sdim bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 67276479Sdim OperandVector &Operands, MCStreamer &Out, 68280031Sdim uint64_t &ErrorInfo, 69276479Sdim bool MatchingInlineAsm) override; 70276479Sdim bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; 71262261Sdim bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 72276479Sdim SMLoc NameLoc, OperandVector &Operands) override; 73276479Sdim bool ParseDirective(AsmToken DirectiveID) override; 74262261Sdim 75276479Sdim unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 76276479Sdim unsigned Kind) override; 77262261Sdim 78262261Sdim // Custom parse functions for Sparc specific operands. 79276479Sdim OperandMatchResultTy parseMEMOperand(OperandVector &Operands); 80262261Sdim 81344779Sdim OperandMatchResultTy parseMembarTag(OperandVector &Operands); 82344779Sdim 83276479Sdim OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Name); 84262261Sdim 85262261Sdim OperandMatchResultTy 86276479Sdim parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Operand, 87276479Sdim bool isCall = false); 88262261Sdim 89276479Sdim OperandMatchResultTy parseBranchModifiers(OperandVector &Operands); 90276479Sdim 91296417Sdim // Helper function for dealing with %lo / %hi in PIC mode. 92296417Sdim const SparcMCExpr *adjustPICRelocation(SparcMCExpr::VariantKind VK, 93296417Sdim const MCExpr *subExpr); 94296417Sdim 95262261Sdim // returns true if Tok is matched to a register and returns register in RegNo. 96262261Sdim bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, 97262261Sdim unsigned &RegKind); 98262261Sdim 99262261Sdim bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc); 100262261Sdim 101288943Sdim bool is64Bit() const { 102296417Sdim return getSTI().getTargetTriple().getArch() == Triple::sparcv9; 103288943Sdim } 104288943Sdim 105314564Sdim bool expandSET(MCInst &Inst, SMLoc IDLoc, 106288943Sdim SmallVectorImpl<MCInst> &Instructions); 107288943Sdim 108262261Sdimpublic: 109296417Sdim SparcAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, 110276479Sdim const MCInstrInfo &MII, 111276479Sdim const MCTargetOptions &Options) 112327952Sdim : MCTargetAsmParser(Options, sti, MII), Parser(parser) { 113341825Sdim Parser.addAliasForDirective(".half", ".2byte"); 114341825Sdim Parser.addAliasForDirective(".uahalf", ".2byte"); 115341825Sdim Parser.addAliasForDirective(".word", ".4byte"); 116341825Sdim Parser.addAliasForDirective(".uaword", ".4byte"); 117341825Sdim Parser.addAliasForDirective(".nword", is64Bit() ? ".8byte" : ".4byte"); 118341825Sdim if (is64Bit()) 119341825Sdim Parser.addAliasForDirective(".xword", ".8byte"); 120341825Sdim 121262261Sdim // Initialize the set of available features. 122296417Sdim setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); 123262261Sdim } 124262261Sdim}; 125262261Sdim 126321369Sdim} // end anonymous namespace 127321369Sdim 128296417Sdim static const MCPhysReg IntRegs[32] = { 129262261Sdim Sparc::G0, Sparc::G1, Sparc::G2, Sparc::G3, 130262261Sdim Sparc::G4, Sparc::G5, Sparc::G6, Sparc::G7, 131262261Sdim Sparc::O0, Sparc::O1, Sparc::O2, Sparc::O3, 132262261Sdim Sparc::O4, Sparc::O5, Sparc::O6, Sparc::O7, 133262261Sdim Sparc::L0, Sparc::L1, Sparc::L2, Sparc::L3, 134262261Sdim Sparc::L4, Sparc::L5, Sparc::L6, Sparc::L7, 135262261Sdim Sparc::I0, Sparc::I1, Sparc::I2, Sparc::I3, 136262261Sdim Sparc::I4, Sparc::I5, Sparc::I6, Sparc::I7 }; 137262261Sdim 138296417Sdim static const MCPhysReg FloatRegs[32] = { 139262261Sdim Sparc::F0, Sparc::F1, Sparc::F2, Sparc::F3, 140262261Sdim Sparc::F4, Sparc::F5, Sparc::F6, Sparc::F7, 141262261Sdim Sparc::F8, Sparc::F9, Sparc::F10, Sparc::F11, 142262261Sdim Sparc::F12, Sparc::F13, Sparc::F14, Sparc::F15, 143262261Sdim Sparc::F16, Sparc::F17, Sparc::F18, Sparc::F19, 144262261Sdim Sparc::F20, Sparc::F21, Sparc::F22, Sparc::F23, 145262261Sdim Sparc::F24, Sparc::F25, Sparc::F26, Sparc::F27, 146262261Sdim Sparc::F28, Sparc::F29, Sparc::F30, Sparc::F31 }; 147262261Sdim 148296417Sdim static const MCPhysReg DoubleRegs[32] = { 149262261Sdim Sparc::D0, Sparc::D1, Sparc::D2, Sparc::D3, 150262261Sdim Sparc::D4, Sparc::D5, Sparc::D6, Sparc::D7, 151314564Sdim Sparc::D8, Sparc::D9, Sparc::D10, Sparc::D11, 152262261Sdim Sparc::D12, Sparc::D13, Sparc::D14, Sparc::D15, 153262261Sdim Sparc::D16, Sparc::D17, Sparc::D18, Sparc::D19, 154262261Sdim Sparc::D20, Sparc::D21, Sparc::D22, Sparc::D23, 155262261Sdim Sparc::D24, Sparc::D25, Sparc::D26, Sparc::D27, 156262261Sdim Sparc::D28, Sparc::D29, Sparc::D30, Sparc::D31 }; 157262261Sdim 158296417Sdim static const MCPhysReg QuadFPRegs[32] = { 159262261Sdim Sparc::Q0, Sparc::Q1, Sparc::Q2, Sparc::Q3, 160262261Sdim Sparc::Q4, Sparc::Q5, Sparc::Q6, Sparc::Q7, 161262261Sdim Sparc::Q8, Sparc::Q9, Sparc::Q10, Sparc::Q11, 162262261Sdim Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 }; 163262261Sdim 164296417Sdim static const MCPhysReg ASRRegs[32] = { 165288943Sdim SP::Y, SP::ASR1, SP::ASR2, SP::ASR3, 166288943Sdim SP::ASR4, SP::ASR5, SP::ASR6, SP::ASR7, 167288943Sdim SP::ASR8, SP::ASR9, SP::ASR10, SP::ASR11, 168288943Sdim SP::ASR12, SP::ASR13, SP::ASR14, SP::ASR15, 169288943Sdim SP::ASR16, SP::ASR17, SP::ASR18, SP::ASR19, 170288943Sdim SP::ASR20, SP::ASR21, SP::ASR22, SP::ASR23, 171288943Sdim SP::ASR24, SP::ASR25, SP::ASR26, SP::ASR27, 172288943Sdim SP::ASR28, SP::ASR29, SP::ASR30, SP::ASR31}; 173262261Sdim 174296417Sdim static const MCPhysReg IntPairRegs[] = { 175296417Sdim Sparc::G0_G1, Sparc::G2_G3, Sparc::G4_G5, Sparc::G6_G7, 176296417Sdim Sparc::O0_O1, Sparc::O2_O3, Sparc::O4_O5, Sparc::O6_O7, 177296417Sdim Sparc::L0_L1, Sparc::L2_L3, Sparc::L4_L5, Sparc::L6_L7, 178296417Sdim Sparc::I0_I1, Sparc::I2_I3, Sparc::I4_I5, Sparc::I6_I7}; 179296417Sdim 180309124Sdim static const MCPhysReg CoprocRegs[32] = { 181309124Sdim Sparc::C0, Sparc::C1, Sparc::C2, Sparc::C3, 182309124Sdim Sparc::C4, Sparc::C5, Sparc::C6, Sparc::C7, 183309124Sdim Sparc::C8, Sparc::C9, Sparc::C10, Sparc::C11, 184309124Sdim Sparc::C12, Sparc::C13, Sparc::C14, Sparc::C15, 185309124Sdim Sparc::C16, Sparc::C17, Sparc::C18, Sparc::C19, 186309124Sdim Sparc::C20, Sparc::C21, Sparc::C22, Sparc::C23, 187309124Sdim Sparc::C24, Sparc::C25, Sparc::C26, Sparc::C27, 188309124Sdim Sparc::C28, Sparc::C29, Sparc::C30, Sparc::C31 }; 189309124Sdim 190309124Sdim static const MCPhysReg CoprocPairRegs[] = { 191309124Sdim Sparc::C0_C1, Sparc::C2_C3, Sparc::C4_C5, Sparc::C6_C7, 192309124Sdim Sparc::C8_C9, Sparc::C10_C11, Sparc::C12_C13, Sparc::C14_C15, 193309124Sdim Sparc::C16_C17, Sparc::C18_C19, Sparc::C20_C21, Sparc::C22_C23, 194309124Sdim Sparc::C24_C25, Sparc::C26_C27, Sparc::C28_C29, Sparc::C30_C31}; 195341825Sdim 196321369Sdimnamespace { 197321369Sdim 198262261Sdim/// SparcOperand - Instances of this class represent a parsed Sparc machine 199262261Sdim/// instruction. 200262261Sdimclass SparcOperand : public MCParsedAsmOperand { 201262261Sdimpublic: 202262261Sdim enum RegisterKind { 203262261Sdim rk_None, 204262261Sdim rk_IntReg, 205296417Sdim rk_IntPairReg, 206262261Sdim rk_FloatReg, 207262261Sdim rk_DoubleReg, 208262261Sdim rk_QuadReg, 209309124Sdim rk_CoprocReg, 210309124Sdim rk_CoprocPairReg, 211288943Sdim rk_Special, 212262261Sdim }; 213288943Sdim 214262261Sdimprivate: 215262261Sdim enum KindTy { 216262261Sdim k_Token, 217262261Sdim k_Register, 218262261Sdim k_Immediate, 219262261Sdim k_MemoryReg, 220262261Sdim k_MemoryImm 221262261Sdim } Kind; 222262261Sdim 223262261Sdim SMLoc StartLoc, EndLoc; 224262261Sdim 225262261Sdim struct Token { 226262261Sdim const char *Data; 227262261Sdim unsigned Length; 228262261Sdim }; 229262261Sdim 230262261Sdim struct RegOp { 231262261Sdim unsigned RegNum; 232262261Sdim RegisterKind Kind; 233262261Sdim }; 234262261Sdim 235262261Sdim struct ImmOp { 236262261Sdim const MCExpr *Val; 237262261Sdim }; 238262261Sdim 239262261Sdim struct MemOp { 240262261Sdim unsigned Base; 241262261Sdim unsigned OffsetReg; 242262261Sdim const MCExpr *Off; 243262261Sdim }; 244262261Sdim 245262261Sdim union { 246262261Sdim struct Token Tok; 247262261Sdim struct RegOp Reg; 248262261Sdim struct ImmOp Imm; 249262261Sdim struct MemOp Mem; 250262261Sdim }; 251321369Sdim 252262261Sdimpublic: 253276479Sdim SparcOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 254276479Sdim 255276479Sdim bool isToken() const override { return Kind == k_Token; } 256276479Sdim bool isReg() const override { return Kind == k_Register; } 257276479Sdim bool isImm() const override { return Kind == k_Immediate; } 258276479Sdim bool isMem() const override { return isMEMrr() || isMEMri(); } 259262261Sdim bool isMEMrr() const { return Kind == k_MemoryReg; } 260262261Sdim bool isMEMri() const { return Kind == k_MemoryImm; } 261344779Sdim bool isMembarTag() const { return Kind == k_Immediate; } 262262261Sdim 263296417Sdim bool isIntReg() const { 264296417Sdim return (Kind == k_Register && Reg.Kind == rk_IntReg); 265296417Sdim } 266296417Sdim 267262261Sdim bool isFloatReg() const { 268262261Sdim return (Kind == k_Register && Reg.Kind == rk_FloatReg); 269262261Sdim } 270262261Sdim 271262261Sdim bool isFloatOrDoubleReg() const { 272262261Sdim return (Kind == k_Register && (Reg.Kind == rk_FloatReg 273262261Sdim || Reg.Kind == rk_DoubleReg)); 274262261Sdim } 275262261Sdim 276309124Sdim bool isCoprocReg() const { 277309124Sdim return (Kind == k_Register && Reg.Kind == rk_CoprocReg); 278309124Sdim } 279262261Sdim 280262261Sdim StringRef getToken() const { 281262261Sdim assert(Kind == k_Token && "Invalid access!"); 282262261Sdim return StringRef(Tok.Data, Tok.Length); 283262261Sdim } 284262261Sdim 285276479Sdim unsigned getReg() const override { 286262261Sdim assert((Kind == k_Register) && "Invalid access!"); 287262261Sdim return Reg.RegNum; 288262261Sdim } 289262261Sdim 290262261Sdim const MCExpr *getImm() const { 291262261Sdim assert((Kind == k_Immediate) && "Invalid access!"); 292262261Sdim return Imm.Val; 293262261Sdim } 294262261Sdim 295262261Sdim unsigned getMemBase() const { 296262261Sdim assert((Kind == k_MemoryReg || Kind == k_MemoryImm) && "Invalid access!"); 297262261Sdim return Mem.Base; 298262261Sdim } 299262261Sdim 300262261Sdim unsigned getMemOffsetReg() const { 301262261Sdim assert((Kind == k_MemoryReg) && "Invalid access!"); 302262261Sdim return Mem.OffsetReg; 303262261Sdim } 304262261Sdim 305262261Sdim const MCExpr *getMemOff() const { 306262261Sdim assert((Kind == k_MemoryImm) && "Invalid access!"); 307262261Sdim return Mem.Off; 308262261Sdim } 309262261Sdim 310262261Sdim /// getStartLoc - Get the location of the first token of this operand. 311276479Sdim SMLoc getStartLoc() const override { 312262261Sdim return StartLoc; 313262261Sdim } 314262261Sdim /// getEndLoc - Get the location of the last token of this operand. 315276479Sdim SMLoc getEndLoc() const override { 316262261Sdim return EndLoc; 317262261Sdim } 318262261Sdim 319276479Sdim void print(raw_ostream &OS) const override { 320262261Sdim switch (Kind) { 321262261Sdim case k_Token: OS << "Token: " << getToken() << "\n"; break; 322262261Sdim case k_Register: OS << "Reg: #" << getReg() << "\n"; break; 323262261Sdim case k_Immediate: OS << "Imm: " << getImm() << "\n"; break; 324262261Sdim case k_MemoryReg: OS << "Mem: " << getMemBase() << "+" 325262261Sdim << getMemOffsetReg() << "\n"; break; 326276479Sdim case k_MemoryImm: assert(getMemOff() != nullptr); 327262261Sdim OS << "Mem: " << getMemBase() 328262261Sdim << "+" << *getMemOff() 329262261Sdim << "\n"; break; 330262261Sdim } 331262261Sdim } 332262261Sdim 333262261Sdim void addRegOperands(MCInst &Inst, unsigned N) const { 334262261Sdim assert(N == 1 && "Invalid number of operands!"); 335288943Sdim Inst.addOperand(MCOperand::createReg(getReg())); 336262261Sdim } 337262261Sdim 338262261Sdim void addImmOperands(MCInst &Inst, unsigned N) const { 339262261Sdim assert(N == 1 && "Invalid number of operands!"); 340262261Sdim const MCExpr *Expr = getImm(); 341262261Sdim addExpr(Inst, Expr); 342262261Sdim } 343262261Sdim 344262261Sdim void addExpr(MCInst &Inst, const MCExpr *Expr) const{ 345262261Sdim // Add as immediate when possible. Null MCExpr = 0. 346276479Sdim if (!Expr) 347288943Sdim Inst.addOperand(MCOperand::createImm(0)); 348262261Sdim else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) 349288943Sdim Inst.addOperand(MCOperand::createImm(CE->getValue())); 350262261Sdim else 351288943Sdim Inst.addOperand(MCOperand::createExpr(Expr)); 352262261Sdim } 353262261Sdim 354262261Sdim void addMEMrrOperands(MCInst &Inst, unsigned N) const { 355262261Sdim assert(N == 2 && "Invalid number of operands!"); 356262261Sdim 357288943Sdim Inst.addOperand(MCOperand::createReg(getMemBase())); 358262261Sdim 359262261Sdim assert(getMemOffsetReg() != 0 && "Invalid offset"); 360288943Sdim Inst.addOperand(MCOperand::createReg(getMemOffsetReg())); 361262261Sdim } 362262261Sdim 363262261Sdim void addMEMriOperands(MCInst &Inst, unsigned N) const { 364262261Sdim assert(N == 2 && "Invalid number of operands!"); 365262261Sdim 366288943Sdim Inst.addOperand(MCOperand::createReg(getMemBase())); 367262261Sdim 368262261Sdim const MCExpr *Expr = getMemOff(); 369262261Sdim addExpr(Inst, Expr); 370262261Sdim } 371262261Sdim 372344779Sdim void addMembarTagOperands(MCInst &Inst, unsigned N) const { 373344779Sdim assert(N == 1 && "Invalid number of operands!"); 374344779Sdim const MCExpr *Expr = getImm(); 375344779Sdim addExpr(Inst, Expr); 376344779Sdim } 377344779Sdim 378276479Sdim static std::unique_ptr<SparcOperand> CreateToken(StringRef Str, SMLoc S) { 379360784Sdim auto Op = std::make_unique<SparcOperand>(k_Token); 380262261Sdim Op->Tok.Data = Str.data(); 381262261Sdim Op->Tok.Length = Str.size(); 382262261Sdim Op->StartLoc = S; 383262261Sdim Op->EndLoc = S; 384262261Sdim return Op; 385262261Sdim } 386262261Sdim 387276479Sdim static std::unique_ptr<SparcOperand> CreateReg(unsigned RegNum, unsigned Kind, 388276479Sdim SMLoc S, SMLoc E) { 389360784Sdim auto Op = std::make_unique<SparcOperand>(k_Register); 390262261Sdim Op->Reg.RegNum = RegNum; 391262261Sdim Op->Reg.Kind = (SparcOperand::RegisterKind)Kind; 392262261Sdim Op->StartLoc = S; 393262261Sdim Op->EndLoc = E; 394262261Sdim return Op; 395262261Sdim } 396262261Sdim 397276479Sdim static std::unique_ptr<SparcOperand> CreateImm(const MCExpr *Val, SMLoc S, 398276479Sdim SMLoc E) { 399360784Sdim auto Op = std::make_unique<SparcOperand>(k_Immediate); 400262261Sdim Op->Imm.Val = Val; 401262261Sdim Op->StartLoc = S; 402262261Sdim Op->EndLoc = E; 403262261Sdim return Op; 404262261Sdim } 405262261Sdim 406296417Sdim static bool MorphToIntPairReg(SparcOperand &Op) { 407296417Sdim unsigned Reg = Op.getReg(); 408296417Sdim assert(Op.Reg.Kind == rk_IntReg); 409296417Sdim unsigned regIdx = 32; 410296417Sdim if (Reg >= Sparc::G0 && Reg <= Sparc::G7) 411296417Sdim regIdx = Reg - Sparc::G0; 412296417Sdim else if (Reg >= Sparc::O0 && Reg <= Sparc::O7) 413296417Sdim regIdx = Reg - Sparc::O0 + 8; 414296417Sdim else if (Reg >= Sparc::L0 && Reg <= Sparc::L7) 415296417Sdim regIdx = Reg - Sparc::L0 + 16; 416296417Sdim else if (Reg >= Sparc::I0 && Reg <= Sparc::I7) 417296417Sdim regIdx = Reg - Sparc::I0 + 24; 418296417Sdim if (regIdx % 2 || regIdx > 31) 419296417Sdim return false; 420296417Sdim Op.Reg.RegNum = IntPairRegs[regIdx / 2]; 421296417Sdim Op.Reg.Kind = rk_IntPairReg; 422296417Sdim return true; 423296417Sdim } 424296417Sdim 425276479Sdim static bool MorphToDoubleReg(SparcOperand &Op) { 426276479Sdim unsigned Reg = Op.getReg(); 427276479Sdim assert(Op.Reg.Kind == rk_FloatReg); 428262261Sdim unsigned regIdx = Reg - Sparc::F0; 429262261Sdim if (regIdx % 2 || regIdx > 31) 430276479Sdim return false; 431276479Sdim Op.Reg.RegNum = DoubleRegs[regIdx / 2]; 432276479Sdim Op.Reg.Kind = rk_DoubleReg; 433276479Sdim return true; 434262261Sdim } 435262261Sdim 436276479Sdim static bool MorphToQuadReg(SparcOperand &Op) { 437276479Sdim unsigned Reg = Op.getReg(); 438262261Sdim unsigned regIdx = 0; 439276479Sdim switch (Op.Reg.Kind) { 440276479Sdim default: llvm_unreachable("Unexpected register kind!"); 441262261Sdim case rk_FloatReg: 442262261Sdim regIdx = Reg - Sparc::F0; 443262261Sdim if (regIdx % 4 || regIdx > 31) 444276479Sdim return false; 445262261Sdim Reg = QuadFPRegs[regIdx / 4]; 446262261Sdim break; 447262261Sdim case rk_DoubleReg: 448262261Sdim regIdx = Reg - Sparc::D0; 449262261Sdim if (regIdx % 2 || regIdx > 31) 450276479Sdim return false; 451262261Sdim Reg = QuadFPRegs[regIdx / 2]; 452262261Sdim break; 453262261Sdim } 454276479Sdim Op.Reg.RegNum = Reg; 455276479Sdim Op.Reg.Kind = rk_QuadReg; 456276479Sdim return true; 457262261Sdim } 458262261Sdim 459309124Sdim static bool MorphToCoprocPairReg(SparcOperand &Op) { 460309124Sdim unsigned Reg = Op.getReg(); 461309124Sdim assert(Op.Reg.Kind == rk_CoprocReg); 462309124Sdim unsigned regIdx = 32; 463309124Sdim if (Reg >= Sparc::C0 && Reg <= Sparc::C31) 464309124Sdim regIdx = Reg - Sparc::C0; 465309124Sdim if (regIdx % 2 || regIdx > 31) 466309124Sdim return false; 467309124Sdim Op.Reg.RegNum = CoprocPairRegs[regIdx / 2]; 468309124Sdim Op.Reg.Kind = rk_CoprocPairReg; 469309124Sdim return true; 470309124Sdim } 471341825Sdim 472276479Sdim static std::unique_ptr<SparcOperand> 473276479Sdim MorphToMEMrr(unsigned Base, std::unique_ptr<SparcOperand> Op) { 474262261Sdim unsigned offsetReg = Op->getReg(); 475262261Sdim Op->Kind = k_MemoryReg; 476262261Sdim Op->Mem.Base = Base; 477262261Sdim Op->Mem.OffsetReg = offsetReg; 478276479Sdim Op->Mem.Off = nullptr; 479262261Sdim return Op; 480262261Sdim } 481262261Sdim 482276479Sdim static std::unique_ptr<SparcOperand> 483288943Sdim CreateMEMr(unsigned Base, SMLoc S, SMLoc E) { 484360784Sdim auto Op = std::make_unique<SparcOperand>(k_MemoryReg); 485262261Sdim Op->Mem.Base = Base; 486288943Sdim Op->Mem.OffsetReg = Sparc::G0; // always 0 487288943Sdim Op->Mem.Off = nullptr; 488262261Sdim Op->StartLoc = S; 489262261Sdim Op->EndLoc = E; 490262261Sdim return Op; 491262261Sdim } 492262261Sdim 493276479Sdim static std::unique_ptr<SparcOperand> 494276479Sdim MorphToMEMri(unsigned Base, std::unique_ptr<SparcOperand> Op) { 495262261Sdim const MCExpr *Imm = Op->getImm(); 496262261Sdim Op->Kind = k_MemoryImm; 497262261Sdim Op->Mem.Base = Base; 498262261Sdim Op->Mem.OffsetReg = 0; 499262261Sdim Op->Mem.Off = Imm; 500262261Sdim return Op; 501262261Sdim } 502262261Sdim}; 503262261Sdim 504321369Sdim} // end anonymous namespace 505262261Sdim 506314564Sdimbool SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc, 507288943Sdim SmallVectorImpl<MCInst> &Instructions) { 508288943Sdim MCOperand MCRegOp = Inst.getOperand(0); 509288943Sdim MCOperand MCValOp = Inst.getOperand(1); 510288943Sdim assert(MCRegOp.isReg()); 511288943Sdim assert(MCValOp.isImm() || MCValOp.isExpr()); 512288943Sdim 513288943Sdim // the imm operand can be either an expression or an immediate. 514288943Sdim bool IsImm = Inst.getOperand(1).isImm(); 515296417Sdim int64_t RawImmValue = IsImm ? MCValOp.getImm() : 0; 516296417Sdim 517296417Sdim // Allow either a signed or unsigned 32-bit immediate. 518296417Sdim if (RawImmValue < -2147483648LL || RawImmValue > 4294967295LL) { 519314564Sdim return Error(IDLoc, 520314564Sdim "set: argument must be between -2147483648 and 4294967295"); 521296417Sdim } 522296417Sdim 523296417Sdim // If the value was expressed as a large unsigned number, that's ok. 524296417Sdim // We want to see if it "looks like" a small signed number. 525296417Sdim int32_t ImmValue = RawImmValue; 526296417Sdim // For 'set' you can't use 'or' with a negative operand on V9 because 527296417Sdim // that would splat the sign bit across the upper half of the destination 528296417Sdim // register, whereas 'set' is defined to zero the high 32 bits. 529296417Sdim bool IsEffectivelyImm13 = 530296417Sdim IsImm && ((is64Bit() ? 0 : -4096) <= ImmValue && ImmValue < 4096); 531288943Sdim const MCExpr *ValExpr; 532288943Sdim if (IsImm) 533288943Sdim ValExpr = MCConstantExpr::create(ImmValue, getContext()); 534288943Sdim else 535288943Sdim ValExpr = MCValOp.getExpr(); 536288943Sdim 537288943Sdim MCOperand PrevReg = MCOperand::createReg(Sparc::G0); 538288943Sdim 539296417Sdim // If not just a signed imm13 value, then either we use a 'sethi' with a 540296417Sdim // following 'or', or a 'sethi' by itself if there are no more 1 bits. 541296417Sdim // In either case, start with the 'sethi'. 542296417Sdim if (!IsEffectivelyImm13) { 543288943Sdim MCInst TmpInst; 544296417Sdim const MCExpr *Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_HI, ValExpr); 545288943Sdim TmpInst.setLoc(IDLoc); 546288943Sdim TmpInst.setOpcode(SP::SETHIi); 547288943Sdim TmpInst.addOperand(MCRegOp); 548288943Sdim TmpInst.addOperand(MCOperand::createExpr(Expr)); 549288943Sdim Instructions.push_back(TmpInst); 550288943Sdim PrevReg = MCRegOp; 551288943Sdim } 552288943Sdim 553296417Sdim // The low bits require touching in 3 cases: 554296417Sdim // * A non-immediate value will always require both instructions. 555296417Sdim // * An effectively imm13 value needs only an 'or' instruction. 556296417Sdim // * Otherwise, an immediate that is not effectively imm13 requires the 557296417Sdim // 'or' only if bits remain after clearing the 22 bits that 'sethi' set. 558296417Sdim // If the low bits are known zeros, there's nothing to do. 559296417Sdim // In the second case, and only in that case, must we NOT clear 560296417Sdim // bits of the immediate value via the %lo() assembler function. 561296417Sdim // Note also, the 'or' instruction doesn't mind a large value in the case 562296417Sdim // where the operand to 'set' was 0xFFFFFzzz - it does exactly what you mean. 563296417Sdim if (!IsImm || IsEffectivelyImm13 || (ImmValue & 0x3ff)) { 564288943Sdim MCInst TmpInst; 565296417Sdim const MCExpr *Expr; 566296417Sdim if (IsEffectivelyImm13) 567296417Sdim Expr = ValExpr; 568296417Sdim else 569296417Sdim Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_LO, ValExpr); 570288943Sdim TmpInst.setLoc(IDLoc); 571288943Sdim TmpInst.setOpcode(SP::ORri); 572288943Sdim TmpInst.addOperand(MCRegOp); 573288943Sdim TmpInst.addOperand(PrevReg); 574288943Sdim TmpInst.addOperand(MCOperand::createExpr(Expr)); 575288943Sdim Instructions.push_back(TmpInst); 576288943Sdim } 577314564Sdim return false; 578288943Sdim} 579288943Sdim 580276479Sdimbool SparcAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 581276479Sdim OperandVector &Operands, 582276479Sdim MCStreamer &Out, 583280031Sdim uint64_t &ErrorInfo, 584276479Sdim bool MatchingInlineAsm) { 585262261Sdim MCInst Inst; 586262261Sdim SmallVector<MCInst, 8> Instructions; 587262261Sdim unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, 588262261Sdim MatchingInlineAsm); 589262261Sdim switch (MatchResult) { 590262261Sdim case Match_Success: { 591288943Sdim switch (Inst.getOpcode()) { 592288943Sdim default: 593288943Sdim Inst.setLoc(IDLoc); 594288943Sdim Instructions.push_back(Inst); 595288943Sdim break; 596288943Sdim case SP::SET: 597314564Sdim if (expandSET(Inst, IDLoc, Instructions)) 598314564Sdim return true; 599288943Sdim break; 600288943Sdim } 601288943Sdim 602288943Sdim for (const MCInst &I : Instructions) { 603296417Sdim Out.EmitInstruction(I, getSTI()); 604288943Sdim } 605262261Sdim return false; 606262261Sdim } 607262261Sdim 608262261Sdim case Match_MissingFeature: 609262261Sdim return Error(IDLoc, 610262261Sdim "instruction requires a CPU feature not currently enabled"); 611262261Sdim 612262261Sdim case Match_InvalidOperand: { 613262261Sdim SMLoc ErrorLoc = IDLoc; 614280031Sdim if (ErrorInfo != ~0ULL) { 615262261Sdim if (ErrorInfo >= Operands.size()) 616262261Sdim return Error(IDLoc, "too few operands for instruction"); 617262261Sdim 618276479Sdim ErrorLoc = ((SparcOperand &)*Operands[ErrorInfo]).getStartLoc(); 619262261Sdim if (ErrorLoc == SMLoc()) 620262261Sdim ErrorLoc = IDLoc; 621262261Sdim } 622262261Sdim 623262261Sdim return Error(ErrorLoc, "invalid operand for instruction"); 624262261Sdim } 625262261Sdim case Match_MnemonicFail: 626276479Sdim return Error(IDLoc, "invalid instruction mnemonic"); 627262261Sdim } 628280031Sdim llvm_unreachable("Implement any new match types added!"); 629262261Sdim} 630262261Sdim 631321369Sdimbool SparcAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 632321369Sdim SMLoc &EndLoc) { 633262261Sdim const AsmToken &Tok = Parser.getTok(); 634262261Sdim StartLoc = Tok.getLoc(); 635262261Sdim EndLoc = Tok.getEndLoc(); 636262261Sdim RegNo = 0; 637262261Sdim if (getLexer().getKind() != AsmToken::Percent) 638262261Sdim return false; 639262261Sdim Parser.Lex(); 640262261Sdim unsigned regKind = SparcOperand::rk_None; 641262261Sdim if (matchRegisterName(Tok, RegNo, regKind)) { 642262261Sdim Parser.Lex(); 643262261Sdim return false; 644262261Sdim } 645262261Sdim 646262261Sdim return Error(StartLoc, "invalid register name"); 647262261Sdim} 648262261Sdim 649353358Sdimstatic void applyMnemonicAliases(StringRef &Mnemonic, 650353358Sdim const FeatureBitset &Features, 651276479Sdim unsigned VariantID); 652276479Sdim 653276479Sdimbool SparcAsmParser::ParseInstruction(ParseInstructionInfo &Info, 654276479Sdim StringRef Name, SMLoc NameLoc, 655276479Sdim OperandVector &Operands) { 656276479Sdim 657262261Sdim // First operand in MCInst is instruction mnemonic. 658262261Sdim Operands.push_back(SparcOperand::CreateToken(Name, NameLoc)); 659262261Sdim 660276479Sdim // apply mnemonic aliases, if any, so that we can parse operands correctly. 661276479Sdim applyMnemonicAliases(Name, getAvailableFeatures(), 0); 662276479Sdim 663262261Sdim if (getLexer().isNot(AsmToken::EndOfStatement)) { 664262261Sdim // Read the first operand. 665276479Sdim if (getLexer().is(AsmToken::Comma)) { 666276479Sdim if (parseBranchModifiers(Operands) != MatchOperand_Success) { 667276479Sdim SMLoc Loc = getLexer().getLoc(); 668276479Sdim return Error(Loc, "unexpected token"); 669276479Sdim } 670276479Sdim } 671262261Sdim if (parseOperand(Operands, Name) != MatchOperand_Success) { 672262261Sdim SMLoc Loc = getLexer().getLoc(); 673262261Sdim return Error(Loc, "unexpected token"); 674262261Sdim } 675262261Sdim 676309124Sdim while (getLexer().is(AsmToken::Comma) || getLexer().is(AsmToken::Plus)) { 677309124Sdim if (getLexer().is(AsmToken::Plus)) { 678309124Sdim // Plus tokens are significant in software_traps (p83, sparcv8.pdf). We must capture them. 679309124Sdim Operands.push_back(SparcOperand::CreateToken("+", Parser.getTok().getLoc())); 680309124Sdim } 681309124Sdim Parser.Lex(); // Eat the comma or plus. 682262261Sdim // Parse and remember the operand. 683262261Sdim if (parseOperand(Operands, Name) != MatchOperand_Success) { 684262261Sdim SMLoc Loc = getLexer().getLoc(); 685262261Sdim return Error(Loc, "unexpected token"); 686262261Sdim } 687262261Sdim } 688262261Sdim } 689262261Sdim if (getLexer().isNot(AsmToken::EndOfStatement)) { 690262261Sdim SMLoc Loc = getLexer().getLoc(); 691262261Sdim return Error(Loc, "unexpected token"); 692262261Sdim } 693262261Sdim Parser.Lex(); // Consume the EndOfStatement. 694262261Sdim return false; 695262261Sdim} 696262261Sdim 697262261Sdimbool SparcAsmParser:: 698262261SdimParseDirective(AsmToken DirectiveID) 699262261Sdim{ 700276479Sdim StringRef IDVal = DirectiveID.getString(); 701276479Sdim 702276479Sdim if (IDVal == ".register") { 703276479Sdim // For now, ignore .register directive. 704276479Sdim Parser.eatToEndOfStatement(); 705276479Sdim return false; 706276479Sdim } 707309124Sdim if (IDVal == ".proc") { 708309124Sdim // For compatibility, ignore this directive. 709309124Sdim // (It's supposed to be an "optimization" in the Sun assembler) 710309124Sdim Parser.eatToEndOfStatement(); 711309124Sdim return false; 712309124Sdim } 713276479Sdim 714276479Sdim // Let the MC layer to handle other directives. 715276479Sdim return true; 716276479Sdim} 717276479Sdim 718314564SdimOperandMatchResultTy 719276479SdimSparcAsmParser::parseMEMOperand(OperandVector &Operands) { 720262261Sdim SMLoc S, E; 721262261Sdim unsigned BaseReg = 0; 722262261Sdim 723262261Sdim if (ParseRegister(BaseReg, S, E)) { 724262261Sdim return MatchOperand_NoMatch; 725262261Sdim } 726262261Sdim 727262261Sdim switch (getLexer().getKind()) { 728262261Sdim default: return MatchOperand_NoMatch; 729262261Sdim 730262261Sdim case AsmToken::Comma: 731262261Sdim case AsmToken::RBrac: 732262261Sdim case AsmToken::EndOfStatement: 733288943Sdim Operands.push_back(SparcOperand::CreateMEMr(BaseReg, S, E)); 734262261Sdim return MatchOperand_Success; 735262261Sdim 736262261Sdim case AsmToken:: Plus: 737262261Sdim Parser.Lex(); // Eat the '+' 738262261Sdim break; 739262261Sdim case AsmToken::Minus: 740262261Sdim break; 741262261Sdim } 742262261Sdim 743276479Sdim std::unique_ptr<SparcOperand> Offset; 744262261Sdim OperandMatchResultTy ResTy = parseSparcAsmOperand(Offset); 745262261Sdim if (ResTy != MatchOperand_Success || !Offset) 746262261Sdim return MatchOperand_NoMatch; 747262261Sdim 748276479Sdim Operands.push_back( 749276479Sdim Offset->isImm() ? SparcOperand::MorphToMEMri(BaseReg, std::move(Offset)) 750276479Sdim : SparcOperand::MorphToMEMrr(BaseReg, std::move(Offset))); 751262261Sdim 752262261Sdim return MatchOperand_Success; 753262261Sdim} 754262261Sdim 755344779SdimOperandMatchResultTy SparcAsmParser::parseMembarTag(OperandVector &Operands) { 756344779Sdim SMLoc S = Parser.getTok().getLoc(); 757344779Sdim const MCExpr *EVal; 758344779Sdim int64_t ImmVal = 0; 759344779Sdim 760344779Sdim std::unique_ptr<SparcOperand> Mask; 761344779Sdim if (parseSparcAsmOperand(Mask) == MatchOperand_Success) { 762344779Sdim if (!Mask->isImm() || !Mask->getImm()->evaluateAsAbsolute(ImmVal) || 763344779Sdim ImmVal < 0 || ImmVal > 127) { 764344779Sdim Error(S, "invalid membar mask number"); 765344779Sdim return MatchOperand_ParseFail; 766344779Sdim } 767344779Sdim } 768344779Sdim 769344779Sdim while (getLexer().getKind() == AsmToken::Hash) { 770344779Sdim SMLoc TagStart = getLexer().getLoc(); 771344779Sdim Parser.Lex(); // Eat the '#'. 772344779Sdim unsigned MaskVal = StringSwitch<unsigned>(Parser.getTok().getString()) 773344779Sdim .Case("LoadLoad", 0x1) 774344779Sdim .Case("StoreLoad", 0x2) 775344779Sdim .Case("LoadStore", 0x4) 776344779Sdim .Case("StoreStore", 0x8) 777344779Sdim .Case("Lookaside", 0x10) 778344779Sdim .Case("MemIssue", 0x20) 779344779Sdim .Case("Sync", 0x40) 780344779Sdim .Default(0); 781344779Sdim 782344779Sdim Parser.Lex(); // Eat the identifier token. 783344779Sdim 784344779Sdim if (!MaskVal) { 785344779Sdim Error(TagStart, "unknown membar tag"); 786344779Sdim return MatchOperand_ParseFail; 787344779Sdim } 788344779Sdim 789344779Sdim ImmVal |= MaskVal; 790344779Sdim 791344779Sdim if (getLexer().getKind() == AsmToken::Pipe) 792344779Sdim Parser.Lex(); // Eat the '|'. 793344779Sdim } 794344779Sdim 795344779Sdim EVal = MCConstantExpr::create(ImmVal, getContext()); 796344779Sdim SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 797344779Sdim Operands.push_back(SparcOperand::CreateImm(EVal, S, E)); 798344779Sdim return MatchOperand_Success; 799344779Sdim} 800344779Sdim 801314564SdimOperandMatchResultTy 802276479SdimSparcAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { 803262261Sdim 804262261Sdim OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 805262261Sdim 806262261Sdim // If there wasn't a custom match, try the generic matcher below. Otherwise, 807262261Sdim // there was a match, but an error occurred, in which case, just return that 808262261Sdim // the operand parsing failed. 809262261Sdim if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail) 810262261Sdim return ResTy; 811262261Sdim 812262261Sdim if (getLexer().is(AsmToken::LBrac)) { 813262261Sdim // Memory operand 814262261Sdim Operands.push_back(SparcOperand::CreateToken("[", 815262261Sdim Parser.getTok().getLoc())); 816262261Sdim Parser.Lex(); // Eat the [ 817262261Sdim 818309124Sdim if (Mnemonic == "cas" || Mnemonic == "casx" || Mnemonic == "casa") { 819262261Sdim SMLoc S = Parser.getTok().getLoc(); 820262261Sdim if (getLexer().getKind() != AsmToken::Percent) 821262261Sdim return MatchOperand_NoMatch; 822262261Sdim Parser.Lex(); // eat % 823262261Sdim 824262261Sdim unsigned RegNo, RegKind; 825262261Sdim if (!matchRegisterName(Parser.getTok(), RegNo, RegKind)) 826262261Sdim return MatchOperand_NoMatch; 827262261Sdim 828262261Sdim Parser.Lex(); // Eat the identifier token. 829262261Sdim SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1); 830262261Sdim Operands.push_back(SparcOperand::CreateReg(RegNo, RegKind, S, E)); 831262261Sdim ResTy = MatchOperand_Success; 832262261Sdim } else { 833262261Sdim ResTy = parseMEMOperand(Operands); 834262261Sdim } 835262261Sdim 836262261Sdim if (ResTy != MatchOperand_Success) 837262261Sdim return ResTy; 838262261Sdim 839262261Sdim if (!getLexer().is(AsmToken::RBrac)) 840262261Sdim return MatchOperand_ParseFail; 841262261Sdim 842262261Sdim Operands.push_back(SparcOperand::CreateToken("]", 843262261Sdim Parser.getTok().getLoc())); 844262261Sdim Parser.Lex(); // Eat the ] 845288943Sdim 846288943Sdim // Parse an optional address-space identifier after the address. 847288943Sdim if (getLexer().is(AsmToken::Integer)) { 848288943Sdim std::unique_ptr<SparcOperand> Op; 849288943Sdim ResTy = parseSparcAsmOperand(Op, false); 850288943Sdim if (ResTy != MatchOperand_Success || !Op) 851288943Sdim return MatchOperand_ParseFail; 852288943Sdim Operands.push_back(std::move(Op)); 853288943Sdim } 854262261Sdim return MatchOperand_Success; 855262261Sdim } 856262261Sdim 857276479Sdim std::unique_ptr<SparcOperand> Op; 858276479Sdim 859276479Sdim ResTy = parseSparcAsmOperand(Op, (Mnemonic == "call")); 860262261Sdim if (ResTy != MatchOperand_Success || !Op) 861262261Sdim return MatchOperand_ParseFail; 862262261Sdim 863262261Sdim // Push the parsed operand into the list of operands 864276479Sdim Operands.push_back(std::move(Op)); 865262261Sdim 866262261Sdim return MatchOperand_Success; 867262261Sdim} 868262261Sdim 869314564SdimOperandMatchResultTy 870276479SdimSparcAsmParser::parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Op, 871276479Sdim bool isCall) { 872262261Sdim SMLoc S = Parser.getTok().getLoc(); 873262261Sdim SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 874262261Sdim const MCExpr *EVal; 875262261Sdim 876276479Sdim Op = nullptr; 877262261Sdim switch (getLexer().getKind()) { 878262261Sdim default: break; 879262261Sdim 880262261Sdim case AsmToken::Percent: 881262261Sdim Parser.Lex(); // Eat the '%'. 882262261Sdim unsigned RegNo; 883262261Sdim unsigned RegKind; 884262261Sdim if (matchRegisterName(Parser.getTok(), RegNo, RegKind)) { 885262261Sdim StringRef name = Parser.getTok().getString(); 886262261Sdim Parser.Lex(); // Eat the identifier token. 887262261Sdim E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 888262261Sdim switch (RegNo) { 889262261Sdim default: 890262261Sdim Op = SparcOperand::CreateReg(RegNo, RegKind, S, E); 891262261Sdim break; 892288943Sdim case Sparc::PSR: 893288943Sdim Op = SparcOperand::CreateToken("%psr", S); 894262261Sdim break; 895296417Sdim case Sparc::FSR: 896296417Sdim Op = SparcOperand::CreateToken("%fsr", S); 897296417Sdim break; 898309124Sdim case Sparc::FQ: 899309124Sdim Op = SparcOperand::CreateToken("%fq", S); 900309124Sdim break; 901309124Sdim case Sparc::CPSR: 902309124Sdim Op = SparcOperand::CreateToken("%csr", S); 903309124Sdim break; 904309124Sdim case Sparc::CPQ: 905309124Sdim Op = SparcOperand::CreateToken("%cq", S); 906309124Sdim break; 907288943Sdim case Sparc::WIM: 908288943Sdim Op = SparcOperand::CreateToken("%wim", S); 909288943Sdim break; 910288943Sdim case Sparc::TBR: 911288943Sdim Op = SparcOperand::CreateToken("%tbr", S); 912288943Sdim break; 913262261Sdim case Sparc::ICC: 914262261Sdim if (name == "xcc") 915262261Sdim Op = SparcOperand::CreateToken("%xcc", S); 916262261Sdim else 917262261Sdim Op = SparcOperand::CreateToken("%icc", S); 918262261Sdim break; 919262261Sdim } 920262261Sdim break; 921262261Sdim } 922262261Sdim if (matchSparcAsmModifiers(EVal, E)) { 923262261Sdim E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 924262261Sdim Op = SparcOperand::CreateImm(EVal, S, E); 925262261Sdim } 926262261Sdim break; 927262261Sdim 928262261Sdim case AsmToken::Minus: 929262261Sdim case AsmToken::Integer: 930288943Sdim case AsmToken::LParen: 931296417Sdim case AsmToken::Dot: 932262261Sdim if (!getParser().parseExpression(EVal, E)) 933262261Sdim Op = SparcOperand::CreateImm(EVal, S, E); 934262261Sdim break; 935262261Sdim 936262261Sdim case AsmToken::Identifier: { 937262261Sdim StringRef Identifier; 938262261Sdim if (!getParser().parseIdentifier(Identifier)) { 939262261Sdim E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 940288943Sdim MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 941262261Sdim 942288943Sdim const MCExpr *Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, 943262261Sdim getContext()); 944341825Sdim SparcMCExpr::VariantKind Kind = SparcMCExpr::VK_Sparc_13; 945341825Sdim 946341825Sdim if (getContext().getObjectFileInfo()->isPositionIndependent()) { 947341825Sdim if (isCall) 948341825Sdim Kind = SparcMCExpr::VK_Sparc_WPLT30; 949341825Sdim else 950341825Sdim Kind = SparcMCExpr::VK_Sparc_GOT13; 951341825Sdim } 952341825Sdim 953341825Sdim Res = SparcMCExpr::create(Kind, Res, getContext()); 954341825Sdim 955262261Sdim Op = SparcOperand::CreateImm(Res, S, E); 956262261Sdim } 957262261Sdim break; 958262261Sdim } 959262261Sdim } 960262261Sdim return (Op) ? MatchOperand_Success : MatchOperand_ParseFail; 961262261Sdim} 962262261Sdim 963314564SdimOperandMatchResultTy 964276479SdimSparcAsmParser::parseBranchModifiers(OperandVector &Operands) { 965276479Sdim // parse (,a|,pn|,pt)+ 966276479Sdim 967276479Sdim while (getLexer().is(AsmToken::Comma)) { 968276479Sdim Parser.Lex(); // Eat the comma 969276479Sdim 970276479Sdim if (!getLexer().is(AsmToken::Identifier)) 971276479Sdim return MatchOperand_ParseFail; 972276479Sdim StringRef modName = Parser.getTok().getString(); 973276479Sdim if (modName == "a" || modName == "pn" || modName == "pt") { 974276479Sdim Operands.push_back(SparcOperand::CreateToken(modName, 975276479Sdim Parser.getTok().getLoc())); 976276479Sdim Parser.Lex(); // eat the identifier. 977276479Sdim } 978276479Sdim } 979276479Sdim return MatchOperand_Success; 980276479Sdim} 981276479Sdim 982321369Sdimbool SparcAsmParser::matchRegisterName(const AsmToken &Tok, unsigned &RegNo, 983321369Sdim unsigned &RegKind) { 984262261Sdim int64_t intVal = 0; 985262261Sdim RegNo = 0; 986262261Sdim RegKind = SparcOperand::rk_None; 987262261Sdim if (Tok.is(AsmToken::Identifier)) { 988262261Sdim StringRef name = Tok.getString(); 989262261Sdim 990262261Sdim // %fp 991262261Sdim if (name.equals("fp")) { 992262261Sdim RegNo = Sparc::I6; 993262261Sdim RegKind = SparcOperand::rk_IntReg; 994262261Sdim return true; 995262261Sdim } 996262261Sdim // %sp 997262261Sdim if (name.equals("sp")) { 998262261Sdim RegNo = Sparc::O6; 999262261Sdim RegKind = SparcOperand::rk_IntReg; 1000262261Sdim return true; 1001262261Sdim } 1002262261Sdim 1003262261Sdim if (name.equals("y")) { 1004262261Sdim RegNo = Sparc::Y; 1005288943Sdim RegKind = SparcOperand::rk_Special; 1006262261Sdim return true; 1007262261Sdim } 1008262261Sdim 1009288943Sdim if (name.substr(0, 3).equals_lower("asr") 1010288943Sdim && !name.substr(3).getAsInteger(10, intVal) 1011288943Sdim && intVal > 0 && intVal < 32) { 1012288943Sdim RegNo = ASRRegs[intVal]; 1013288943Sdim RegKind = SparcOperand::rk_Special; 1014288943Sdim return true; 1015288943Sdim } 1016288943Sdim 1017296417Sdim // %fprs is an alias of %asr6. 1018296417Sdim if (name.equals("fprs")) { 1019296417Sdim RegNo = ASRRegs[6]; 1020296417Sdim RegKind = SparcOperand::rk_Special; 1021296417Sdim return true; 1022296417Sdim } 1023296417Sdim 1024262261Sdim if (name.equals("icc")) { 1025262261Sdim RegNo = Sparc::ICC; 1026288943Sdim RegKind = SparcOperand::rk_Special; 1027262261Sdim return true; 1028262261Sdim } 1029262261Sdim 1030288943Sdim if (name.equals("psr")) { 1031288943Sdim RegNo = Sparc::PSR; 1032288943Sdim RegKind = SparcOperand::rk_Special; 1033288943Sdim return true; 1034288943Sdim } 1035288943Sdim 1036296417Sdim if (name.equals("fsr")) { 1037296417Sdim RegNo = Sparc::FSR; 1038296417Sdim RegKind = SparcOperand::rk_Special; 1039296417Sdim return true; 1040296417Sdim } 1041296417Sdim 1042309124Sdim if (name.equals("fq")) { 1043309124Sdim RegNo = Sparc::FQ; 1044309124Sdim RegKind = SparcOperand::rk_Special; 1045309124Sdim return true; 1046309124Sdim } 1047309124Sdim 1048309124Sdim if (name.equals("csr")) { 1049309124Sdim RegNo = Sparc::CPSR; 1050309124Sdim RegKind = SparcOperand::rk_Special; 1051309124Sdim return true; 1052309124Sdim } 1053309124Sdim 1054309124Sdim if (name.equals("cq")) { 1055309124Sdim RegNo = Sparc::CPQ; 1056309124Sdim RegKind = SparcOperand::rk_Special; 1057309124Sdim return true; 1058309124Sdim } 1059341825Sdim 1060288943Sdim if (name.equals("wim")) { 1061288943Sdim RegNo = Sparc::WIM; 1062288943Sdim RegKind = SparcOperand::rk_Special; 1063288943Sdim return true; 1064288943Sdim } 1065288943Sdim 1066288943Sdim if (name.equals("tbr")) { 1067288943Sdim RegNo = Sparc::TBR; 1068288943Sdim RegKind = SparcOperand::rk_Special; 1069288943Sdim return true; 1070288943Sdim } 1071288943Sdim 1072262261Sdim if (name.equals("xcc")) { 1073262261Sdim // FIXME:: check 64bit. 1074262261Sdim RegNo = Sparc::ICC; 1075288943Sdim RegKind = SparcOperand::rk_Special; 1076262261Sdim return true; 1077262261Sdim } 1078262261Sdim 1079262261Sdim // %fcc0 - %fcc3 1080262261Sdim if (name.substr(0, 3).equals_lower("fcc") 1081262261Sdim && !name.substr(3).getAsInteger(10, intVal) 1082262261Sdim && intVal < 4) { 1083262261Sdim // FIXME: check 64bit and handle %fcc1 - %fcc3 1084276479Sdim RegNo = Sparc::FCC0 + intVal; 1085288943Sdim RegKind = SparcOperand::rk_Special; 1086262261Sdim return true; 1087262261Sdim } 1088262261Sdim 1089262261Sdim // %g0 - %g7 1090262261Sdim if (name.substr(0, 1).equals_lower("g") 1091262261Sdim && !name.substr(1).getAsInteger(10, intVal) 1092262261Sdim && intVal < 8) { 1093262261Sdim RegNo = IntRegs[intVal]; 1094262261Sdim RegKind = SparcOperand::rk_IntReg; 1095262261Sdim return true; 1096262261Sdim } 1097262261Sdim // %o0 - %o7 1098262261Sdim if (name.substr(0, 1).equals_lower("o") 1099262261Sdim && !name.substr(1).getAsInteger(10, intVal) 1100262261Sdim && intVal < 8) { 1101262261Sdim RegNo = IntRegs[8 + intVal]; 1102262261Sdim RegKind = SparcOperand::rk_IntReg; 1103262261Sdim return true; 1104262261Sdim } 1105262261Sdim if (name.substr(0, 1).equals_lower("l") 1106262261Sdim && !name.substr(1).getAsInteger(10, intVal) 1107262261Sdim && intVal < 8) { 1108262261Sdim RegNo = IntRegs[16 + intVal]; 1109262261Sdim RegKind = SparcOperand::rk_IntReg; 1110262261Sdim return true; 1111262261Sdim } 1112262261Sdim if (name.substr(0, 1).equals_lower("i") 1113262261Sdim && !name.substr(1).getAsInteger(10, intVal) 1114262261Sdim && intVal < 8) { 1115262261Sdim RegNo = IntRegs[24 + intVal]; 1116262261Sdim RegKind = SparcOperand::rk_IntReg; 1117262261Sdim return true; 1118262261Sdim } 1119262261Sdim // %f0 - %f31 1120262261Sdim if (name.substr(0, 1).equals_lower("f") 1121262261Sdim && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 32) { 1122262261Sdim RegNo = FloatRegs[intVal]; 1123262261Sdim RegKind = SparcOperand::rk_FloatReg; 1124262261Sdim return true; 1125262261Sdim } 1126262261Sdim // %f32 - %f62 1127262261Sdim if (name.substr(0, 1).equals_lower("f") 1128262261Sdim && !name.substr(1, 2).getAsInteger(10, intVal) 1129262261Sdim && intVal >= 32 && intVal <= 62 && (intVal % 2 == 0)) { 1130262261Sdim // FIXME: Check V9 1131262261Sdim RegNo = DoubleRegs[intVal/2]; 1132262261Sdim RegKind = SparcOperand::rk_DoubleReg; 1133262261Sdim return true; 1134262261Sdim } 1135262261Sdim 1136262261Sdim // %r0 - %r31 1137262261Sdim if (name.substr(0, 1).equals_lower("r") 1138262261Sdim && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 31) { 1139262261Sdim RegNo = IntRegs[intVal]; 1140262261Sdim RegKind = SparcOperand::rk_IntReg; 1141262261Sdim return true; 1142262261Sdim } 1143296417Sdim 1144309124Sdim // %c0 - %c31 1145309124Sdim if (name.substr(0, 1).equals_lower("c") 1146309124Sdim && !name.substr(1).getAsInteger(10, intVal) 1147309124Sdim && intVal < 32) { 1148309124Sdim RegNo = CoprocRegs[intVal]; 1149309124Sdim RegKind = SparcOperand::rk_CoprocReg; 1150309124Sdim return true; 1151309124Sdim } 1152341825Sdim 1153296417Sdim if (name.equals("tpc")) { 1154296417Sdim RegNo = Sparc::TPC; 1155296417Sdim RegKind = SparcOperand::rk_Special; 1156296417Sdim return true; 1157296417Sdim } 1158296417Sdim if (name.equals("tnpc")) { 1159296417Sdim RegNo = Sparc::TNPC; 1160296417Sdim RegKind = SparcOperand::rk_Special; 1161296417Sdim return true; 1162296417Sdim } 1163296417Sdim if (name.equals("tstate")) { 1164296417Sdim RegNo = Sparc::TSTATE; 1165296417Sdim RegKind = SparcOperand::rk_Special; 1166296417Sdim return true; 1167296417Sdim } 1168296417Sdim if (name.equals("tt")) { 1169296417Sdim RegNo = Sparc::TT; 1170296417Sdim RegKind = SparcOperand::rk_Special; 1171296417Sdim return true; 1172296417Sdim } 1173296417Sdim if (name.equals("tick")) { 1174296417Sdim RegNo = Sparc::TICK; 1175296417Sdim RegKind = SparcOperand::rk_Special; 1176296417Sdim return true; 1177296417Sdim } 1178296417Sdim if (name.equals("tba")) { 1179296417Sdim RegNo = Sparc::TBA; 1180296417Sdim RegKind = SparcOperand::rk_Special; 1181296417Sdim return true; 1182296417Sdim } 1183296417Sdim if (name.equals("pstate")) { 1184296417Sdim RegNo = Sparc::PSTATE; 1185296417Sdim RegKind = SparcOperand::rk_Special; 1186296417Sdim return true; 1187296417Sdim } 1188296417Sdim if (name.equals("tl")) { 1189296417Sdim RegNo = Sparc::TL; 1190296417Sdim RegKind = SparcOperand::rk_Special; 1191296417Sdim return true; 1192296417Sdim } 1193296417Sdim if (name.equals("pil")) { 1194296417Sdim RegNo = Sparc::PIL; 1195296417Sdim RegKind = SparcOperand::rk_Special; 1196296417Sdim return true; 1197296417Sdim } 1198296417Sdim if (name.equals("cwp")) { 1199296417Sdim RegNo = Sparc::CWP; 1200296417Sdim RegKind = SparcOperand::rk_Special; 1201296417Sdim return true; 1202296417Sdim } 1203296417Sdim if (name.equals("cansave")) { 1204296417Sdim RegNo = Sparc::CANSAVE; 1205296417Sdim RegKind = SparcOperand::rk_Special; 1206296417Sdim return true; 1207296417Sdim } 1208296417Sdim if (name.equals("canrestore")) { 1209296417Sdim RegNo = Sparc::CANRESTORE; 1210296417Sdim RegKind = SparcOperand::rk_Special; 1211296417Sdim return true; 1212296417Sdim } 1213296417Sdim if (name.equals("cleanwin")) { 1214296417Sdim RegNo = Sparc::CLEANWIN; 1215296417Sdim RegKind = SparcOperand::rk_Special; 1216296417Sdim return true; 1217296417Sdim } 1218296417Sdim if (name.equals("otherwin")) { 1219296417Sdim RegNo = Sparc::OTHERWIN; 1220296417Sdim RegKind = SparcOperand::rk_Special; 1221296417Sdim return true; 1222296417Sdim } 1223296417Sdim if (name.equals("wstate")) { 1224296417Sdim RegNo = Sparc::WSTATE; 1225296417Sdim RegKind = SparcOperand::rk_Special; 1226296417Sdim return true; 1227296417Sdim } 1228262261Sdim } 1229262261Sdim return false; 1230262261Sdim} 1231262261Sdim 1232288943Sdim// Determine if an expression contains a reference to the symbol 1233288943Sdim// "_GLOBAL_OFFSET_TABLE_". 1234276479Sdimstatic bool hasGOTReference(const MCExpr *Expr) { 1235276479Sdim switch (Expr->getKind()) { 1236276479Sdim case MCExpr::Target: 1237276479Sdim if (const SparcMCExpr *SE = dyn_cast<SparcMCExpr>(Expr)) 1238276479Sdim return hasGOTReference(SE->getSubExpr()); 1239276479Sdim break; 1240262261Sdim 1241276479Sdim case MCExpr::Constant: 1242276479Sdim break; 1243276479Sdim 1244276479Sdim case MCExpr::Binary: { 1245276479Sdim const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); 1246276479Sdim return hasGOTReference(BE->getLHS()) || hasGOTReference(BE->getRHS()); 1247276479Sdim } 1248276479Sdim 1249276479Sdim case MCExpr::SymbolRef: { 1250276479Sdim const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); 1251276479Sdim return (SymRef.getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_"); 1252276479Sdim } 1253276479Sdim 1254276479Sdim case MCExpr::Unary: 1255276479Sdim return hasGOTReference(cast<MCUnaryExpr>(Expr)->getSubExpr()); 1256276479Sdim } 1257276479Sdim return false; 1258276479Sdim} 1259276479Sdim 1260296417Sdimconst SparcMCExpr * 1261296417SdimSparcAsmParser::adjustPICRelocation(SparcMCExpr::VariantKind VK, 1262321369Sdim const MCExpr *subExpr) { 1263296417Sdim // When in PIC mode, "%lo(...)" and "%hi(...)" behave differently. 1264296417Sdim // If the expression refers contains _GLOBAL_OFFSETE_TABLE, it is 1265296417Sdim // actually a %pc10 or %pc22 relocation. Otherwise, they are interpreted 1266296417Sdim // as %got10 or %got22 relocation. 1267296417Sdim 1268309124Sdim if (getContext().getObjectFileInfo()->isPositionIndependent()) { 1269296417Sdim switch(VK) { 1270296417Sdim default: break; 1271296417Sdim case SparcMCExpr::VK_Sparc_LO: 1272296417Sdim VK = (hasGOTReference(subExpr) ? SparcMCExpr::VK_Sparc_PC10 1273296417Sdim : SparcMCExpr::VK_Sparc_GOT10); 1274296417Sdim break; 1275296417Sdim case SparcMCExpr::VK_Sparc_HI: 1276296417Sdim VK = (hasGOTReference(subExpr) ? SparcMCExpr::VK_Sparc_PC22 1277296417Sdim : SparcMCExpr::VK_Sparc_GOT22); 1278296417Sdim break; 1279296417Sdim } 1280296417Sdim } 1281296417Sdim 1282296417Sdim return SparcMCExpr::create(VK, subExpr, getContext()); 1283296417Sdim} 1284296417Sdim 1285262261Sdimbool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal, 1286321369Sdim SMLoc &EndLoc) { 1287262261Sdim AsmToken Tok = Parser.getTok(); 1288262261Sdim if (!Tok.is(AsmToken::Identifier)) 1289262261Sdim return false; 1290262261Sdim 1291262261Sdim StringRef name = Tok.getString(); 1292262261Sdim 1293262261Sdim SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name); 1294262261Sdim 1295262261Sdim if (VK == SparcMCExpr::VK_Sparc_None) 1296262261Sdim return false; 1297262261Sdim 1298262261Sdim Parser.Lex(); // Eat the identifier. 1299262261Sdim if (Parser.getTok().getKind() != AsmToken::LParen) 1300262261Sdim return false; 1301262261Sdim 1302262261Sdim Parser.Lex(); // Eat the LParen token. 1303262261Sdim const MCExpr *subExpr; 1304262261Sdim if (Parser.parseParenExpression(subExpr, EndLoc)) 1305262261Sdim return false; 1306276479Sdim 1307296417Sdim EVal = adjustPICRelocation(VK, subExpr); 1308262261Sdim return true; 1309262261Sdim} 1310262261Sdim 1311360784Sdimextern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcAsmParser() { 1312314564Sdim RegisterMCAsmParser<SparcAsmParser> A(getTheSparcTarget()); 1313314564Sdim RegisterMCAsmParser<SparcAsmParser> B(getTheSparcV9Target()); 1314314564Sdim RegisterMCAsmParser<SparcAsmParser> C(getTheSparcelTarget()); 1315262261Sdim} 1316262261Sdim 1317262261Sdim#define GET_REGISTER_MATCHER 1318262261Sdim#define GET_MATCHER_IMPLEMENTATION 1319262261Sdim#include "SparcGenAsmMatcher.inc" 1320262261Sdim 1321276479Sdimunsigned SparcAsmParser::validateTargetOperandClass(MCParsedAsmOperand &GOp, 1322276479Sdim unsigned Kind) { 1323276479Sdim SparcOperand &Op = (SparcOperand &)GOp; 1324276479Sdim if (Op.isFloatOrDoubleReg()) { 1325262261Sdim switch (Kind) { 1326262261Sdim default: break; 1327262261Sdim case MCK_DFPRegs: 1328276479Sdim if (!Op.isFloatReg() || SparcOperand::MorphToDoubleReg(Op)) 1329262261Sdim return MCTargetAsmParser::Match_Success; 1330262261Sdim break; 1331262261Sdim case MCK_QFPRegs: 1332262261Sdim if (SparcOperand::MorphToQuadReg(Op)) 1333262261Sdim return MCTargetAsmParser::Match_Success; 1334262261Sdim break; 1335262261Sdim } 1336262261Sdim } 1337296417Sdim if (Op.isIntReg() && Kind == MCK_IntPair) { 1338296417Sdim if (SparcOperand::MorphToIntPairReg(Op)) 1339296417Sdim return MCTargetAsmParser::Match_Success; 1340296417Sdim } 1341309124Sdim if (Op.isCoprocReg() && Kind == MCK_CoprocPair) { 1342309124Sdim if (SparcOperand::MorphToCoprocPairReg(Op)) 1343309124Sdim return MCTargetAsmParser::Match_Success; 1344309124Sdim } 1345262261Sdim return Match_InvalidOperand; 1346262261Sdim} 1347