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