| 1 | //===-- VEAsmParser.cpp - Parse VE assembly to MCInst instructions --------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "MCTargetDesc/VEMCAsmInfo.h" |
| 10 | #include "MCTargetDesc/VEMCTargetDesc.h" |
| 11 | #include "TargetInfo/VETargetInfo.h" |
| 12 | #include "VE.h" |
| 13 | #include "llvm/ADT/SmallVector.h" |
| 14 | #include "llvm/ADT/StringRef.h" |
| 15 | #include "llvm/ADT/Twine.h" |
| 16 | #include "llvm/MC/MCContext.h" |
| 17 | #include "llvm/MC/MCExpr.h" |
| 18 | #include "llvm/MC/MCInst.h" |
| 19 | #include "llvm/MC/MCInstrInfo.h" |
| 20 | #include "llvm/MC/MCParser/AsmLexer.h" |
| 21 | #include "llvm/MC/MCParser/MCAsmParser.h" |
| 22 | #include "llvm/MC/MCParser/MCParsedAsmOperand.h" |
| 23 | #include "llvm/MC/MCParser/MCTargetAsmParser.h" |
| 24 | #include "llvm/MC/MCStreamer.h" |
| 25 | #include "llvm/MC/MCSubtargetInfo.h" |
| 26 | #include "llvm/MC/MCSymbol.h" |
| 27 | #include "llvm/MC/TargetRegistry.h" |
| 28 | #include "llvm/Support/Compiler.h" |
| 29 | #include "llvm/Support/raw_ostream.h" |
| 30 | #include <memory> |
| 31 | |
| 32 | using namespace llvm; |
| 33 | |
| 34 | #define DEBUG_TYPE "ve-asmparser" |
| 35 | |
| 36 | namespace { |
| 37 | |
| 38 | class VEOperand; |
| 39 | |
| 40 | class VEAsmParser : public MCTargetAsmParser { |
| 41 | MCAsmParser &Parser; |
| 42 | |
| 43 | /// @name Auto-generated Match Functions |
| 44 | /// { |
| 45 | |
| 46 | #define |
| 47 | #include "VEGenAsmMatcher.inc" |
| 48 | |
| 49 | /// } |
| 50 | |
| 51 | // public interface of the MCTargetAsmParser. |
| 52 | bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
| 53 | OperandVector &Operands, MCStreamer &Out, |
| 54 | uint64_t &ErrorInfo, |
| 55 | bool MatchingInlineAsm) override; |
| 56 | bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; |
| 57 | int parseRegisterName(MCRegister (*matchFn)(StringRef)); |
| 58 | ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, |
| 59 | SMLoc &EndLoc) override; |
| 60 | bool parseInstruction(ParseInstructionInfo &Info, StringRef Name, |
| 61 | SMLoc NameLoc, OperandVector &Operands) override; |
| 62 | ParseStatus parseDirective(AsmToken DirectiveID) override; |
| 63 | |
| 64 | unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, |
| 65 | unsigned Kind) override; |
| 66 | |
| 67 | // Custom parse functions for VE specific operands. |
| 68 | ParseStatus parseMEMOperand(OperandVector &Operands); |
| 69 | ParseStatus parseMEMAsOperand(OperandVector &Operands); |
| 70 | ParseStatus parseCCOpOperand(OperandVector &Operands); |
| 71 | ParseStatus parseRDOpOperand(OperandVector &Operands); |
| 72 | ParseStatus parseMImmOperand(OperandVector &Operands); |
| 73 | ParseStatus parseOperand(OperandVector &Operands, StringRef Name); |
| 74 | ParseStatus parseVEAsmOperand(std::unique_ptr<VEOperand> &Operand); |
| 75 | |
| 76 | // Helper function to parse expression with a symbol. |
| 77 | const MCExpr *extractSpecifier(const MCExpr *E, VE::Specifier &Variant); |
| 78 | bool parseExpression(const MCExpr *&EVal); |
| 79 | |
| 80 | // Split the mnemonic stripping conditional code and quantifiers |
| 81 | StringRef splitMnemonic(StringRef Name, SMLoc NameLoc, |
| 82 | OperandVector *Operands); |
| 83 | |
| 84 | bool parseLiteralValues(unsigned Size, SMLoc L); |
| 85 | |
| 86 | public: |
| 87 | VEAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, |
| 88 | const MCInstrInfo &MII, const MCTargetOptions &Options) |
| 89 | : MCTargetAsmParser(Options, sti, MII), Parser(parser) { |
| 90 | // Initialize the set of available features. |
| 91 | setAvailableFeatures(ComputeAvailableFeatures(FB: getSTI().getFeatureBits())); |
| 92 | } |
| 93 | }; |
| 94 | |
| 95 | } // end anonymous namespace |
| 96 | |
| 97 | static const MCPhysReg I32Regs[64] = { |
| 98 | VE::SW0, VE::SW1, VE::SW2, VE::SW3, VE::SW4, VE::SW5, VE::SW6, |
| 99 | VE::SW7, VE::SW8, VE::SW9, VE::SW10, VE::SW11, VE::SW12, VE::SW13, |
| 100 | VE::SW14, VE::SW15, VE::SW16, VE::SW17, VE::SW18, VE::SW19, VE::SW20, |
| 101 | VE::SW21, VE::SW22, VE::SW23, VE::SW24, VE::SW25, VE::SW26, VE::SW27, |
| 102 | VE::SW28, VE::SW29, VE::SW30, VE::SW31, VE::SW32, VE::SW33, VE::SW34, |
| 103 | VE::SW35, VE::SW36, VE::SW37, VE::SW38, VE::SW39, VE::SW40, VE::SW41, |
| 104 | VE::SW42, VE::SW43, VE::SW44, VE::SW45, VE::SW46, VE::SW47, VE::SW48, |
| 105 | VE::SW49, VE::SW50, VE::SW51, VE::SW52, VE::SW53, VE::SW54, VE::SW55, |
| 106 | VE::SW56, VE::SW57, VE::SW58, VE::SW59, VE::SW60, VE::SW61, VE::SW62, |
| 107 | VE::SW63}; |
| 108 | |
| 109 | static const MCPhysReg F32Regs[64] = { |
| 110 | VE::SF0, VE::SF1, VE::SF2, VE::SF3, VE::SF4, VE::SF5, VE::SF6, |
| 111 | VE::SF7, VE::SF8, VE::SF9, VE::SF10, VE::SF11, VE::SF12, VE::SF13, |
| 112 | VE::SF14, VE::SF15, VE::SF16, VE::SF17, VE::SF18, VE::SF19, VE::SF20, |
| 113 | VE::SF21, VE::SF22, VE::SF23, VE::SF24, VE::SF25, VE::SF26, VE::SF27, |
| 114 | VE::SF28, VE::SF29, VE::SF30, VE::SF31, VE::SF32, VE::SF33, VE::SF34, |
| 115 | VE::SF35, VE::SF36, VE::SF37, VE::SF38, VE::SF39, VE::SF40, VE::SF41, |
| 116 | VE::SF42, VE::SF43, VE::SF44, VE::SF45, VE::SF46, VE::SF47, VE::SF48, |
| 117 | VE::SF49, VE::SF50, VE::SF51, VE::SF52, VE::SF53, VE::SF54, VE::SF55, |
| 118 | VE::SF56, VE::SF57, VE::SF58, VE::SF59, VE::SF60, VE::SF61, VE::SF62, |
| 119 | VE::SF63}; |
| 120 | |
| 121 | static const MCPhysReg F128Regs[32] = { |
| 122 | VE::Q0, VE::Q1, VE::Q2, VE::Q3, VE::Q4, VE::Q5, VE::Q6, VE::Q7, |
| 123 | VE::Q8, VE::Q9, VE::Q10, VE::Q11, VE::Q12, VE::Q13, VE::Q14, VE::Q15, |
| 124 | VE::Q16, VE::Q17, VE::Q18, VE::Q19, VE::Q20, VE::Q21, VE::Q22, VE::Q23, |
| 125 | VE::Q24, VE::Q25, VE::Q26, VE::Q27, VE::Q28, VE::Q29, VE::Q30, VE::Q31}; |
| 126 | |
| 127 | static const MCPhysReg VM512Regs[8] = {VE::VMP0, VE::VMP1, VE::VMP2, VE::VMP3, |
| 128 | VE::VMP4, VE::VMP5, VE::VMP6, VE::VMP7}; |
| 129 | |
| 130 | static const MCPhysReg MISCRegs[31] = { |
| 131 | VE::USRCC, VE::PSW, VE::SAR, VE::NoRegister, |
| 132 | VE::NoRegister, VE::NoRegister, VE::NoRegister, VE::PMMR, |
| 133 | VE::PMCR0, VE::PMCR1, VE::PMCR2, VE::PMCR3, |
| 134 | VE::NoRegister, VE::NoRegister, VE::NoRegister, VE::NoRegister, |
| 135 | VE::PMC0, VE::PMC1, VE::PMC2, VE::PMC3, |
| 136 | VE::PMC4, VE::PMC5, VE::PMC6, VE::PMC7, |
| 137 | VE::PMC8, VE::PMC9, VE::PMC10, VE::PMC11, |
| 138 | VE::PMC12, VE::PMC13, VE::PMC14}; |
| 139 | |
| 140 | namespace { |
| 141 | |
| 142 | /// VEOperand - Instances of this class represent a parsed VE machine |
| 143 | /// instruction. |
| 144 | class VEOperand : public MCParsedAsmOperand { |
| 145 | private: |
| 146 | enum KindTy { |
| 147 | k_Token, |
| 148 | k_Register, |
| 149 | k_Immediate, |
| 150 | // SX-Aurora ASX form is disp(index, base). |
| 151 | k_MemoryRegRegImm, // base=reg, index=reg, disp=imm |
| 152 | k_MemoryRegImmImm, // base=reg, index=imm, disp=imm |
| 153 | k_MemoryZeroRegImm, // base=0, index=reg, disp=imm |
| 154 | k_MemoryZeroImmImm, // base=0, index=imm, disp=imm |
| 155 | // SX-Aurora AS form is disp(base). |
| 156 | k_MemoryRegImm, // base=reg, disp=imm |
| 157 | k_MemoryZeroImm, // base=0, disp=imm |
| 158 | // Other special cases for Aurora VE |
| 159 | k_CCOp, // condition code |
| 160 | k_RDOp, // rounding mode |
| 161 | k_MImmOp, // Special immediate value of sequential bit stream of 0 or 1. |
| 162 | } Kind; |
| 163 | |
| 164 | SMLoc StartLoc, EndLoc; |
| 165 | |
| 166 | struct Token { |
| 167 | const char *Data; |
| 168 | unsigned Length; |
| 169 | }; |
| 170 | |
| 171 | struct RegOp { |
| 172 | unsigned RegNum; |
| 173 | }; |
| 174 | |
| 175 | struct ImmOp { |
| 176 | const MCExpr *Val; |
| 177 | }; |
| 178 | |
| 179 | struct MemOp { |
| 180 | unsigned Base; |
| 181 | unsigned IndexReg; |
| 182 | const MCExpr *Index; |
| 183 | const MCExpr *Offset; |
| 184 | }; |
| 185 | |
| 186 | struct CCOp { |
| 187 | unsigned CCVal; |
| 188 | }; |
| 189 | |
| 190 | struct RDOp { |
| 191 | unsigned RDVal; |
| 192 | }; |
| 193 | |
| 194 | struct MImmOp { |
| 195 | const MCExpr *Val; |
| 196 | bool M0Flag; |
| 197 | }; |
| 198 | |
| 199 | union { |
| 200 | struct Token Tok; |
| 201 | struct RegOp Reg; |
| 202 | struct ImmOp Imm; |
| 203 | struct MemOp Mem; |
| 204 | struct CCOp CC; |
| 205 | struct RDOp RD; |
| 206 | struct MImmOp MImm; |
| 207 | }; |
| 208 | |
| 209 | public: |
| 210 | VEOperand(KindTy K) : Kind(K) {} |
| 211 | |
| 212 | bool isToken() const override { return Kind == k_Token; } |
| 213 | bool isReg() const override { return Kind == k_Register; } |
| 214 | bool isImm() const override { return Kind == k_Immediate; } |
| 215 | bool isMem() const override { |
| 216 | return isMEMrri() || isMEMrii() || isMEMzri() || isMEMzii() || isMEMri() || |
| 217 | isMEMzi(); |
| 218 | } |
| 219 | bool isMEMrri() const { return Kind == k_MemoryRegRegImm; } |
| 220 | bool isMEMrii() const { return Kind == k_MemoryRegImmImm; } |
| 221 | bool isMEMzri() const { return Kind == k_MemoryZeroRegImm; } |
| 222 | bool isMEMzii() const { return Kind == k_MemoryZeroImmImm; } |
| 223 | bool isMEMri() const { return Kind == k_MemoryRegImm; } |
| 224 | bool isMEMzi() const { return Kind == k_MemoryZeroImm; } |
| 225 | bool isCCOp() const { return Kind == k_CCOp; } |
| 226 | bool isRDOp() const { return Kind == k_RDOp; } |
| 227 | bool isZero() { |
| 228 | if (!isImm()) |
| 229 | return false; |
| 230 | |
| 231 | // Constant case |
| 232 | if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Val: Imm.Val)) { |
| 233 | int64_t Value = ConstExpr->getValue(); |
| 234 | return Value == 0; |
| 235 | } |
| 236 | return false; |
| 237 | } |
| 238 | bool isUImm0to2() { |
| 239 | if (!isImm()) |
| 240 | return false; |
| 241 | |
| 242 | // Constant case |
| 243 | if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Val: Imm.Val)) { |
| 244 | int64_t Value = ConstExpr->getValue(); |
| 245 | return Value >= 0 && Value < 3; |
| 246 | } |
| 247 | return false; |
| 248 | } |
| 249 | bool isUImm1() { |
| 250 | if (!isImm()) |
| 251 | return false; |
| 252 | |
| 253 | // Constant case |
| 254 | if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Val: Imm.Val)) { |
| 255 | int64_t Value = ConstExpr->getValue(); |
| 256 | return isUInt<1>(x: Value); |
| 257 | } |
| 258 | return false; |
| 259 | } |
| 260 | bool isUImm2() { |
| 261 | if (!isImm()) |
| 262 | return false; |
| 263 | |
| 264 | // Constant case |
| 265 | if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Val: Imm.Val)) { |
| 266 | int64_t Value = ConstExpr->getValue(); |
| 267 | return isUInt<2>(x: Value); |
| 268 | } |
| 269 | return false; |
| 270 | } |
| 271 | bool isUImm3() { |
| 272 | if (!isImm()) |
| 273 | return false; |
| 274 | |
| 275 | // Constant case |
| 276 | if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Val: Imm.Val)) { |
| 277 | int64_t Value = ConstExpr->getValue(); |
| 278 | return isUInt<3>(x: Value); |
| 279 | } |
| 280 | return false; |
| 281 | } |
| 282 | bool isUImm4() { |
| 283 | if (!isImm()) |
| 284 | return false; |
| 285 | |
| 286 | // Constant case |
| 287 | if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Val: Imm.Val)) { |
| 288 | int64_t Value = ConstExpr->getValue(); |
| 289 | return isUInt<4>(x: Value); |
| 290 | } |
| 291 | return false; |
| 292 | } |
| 293 | bool isUImm6() { |
| 294 | if (!isImm()) |
| 295 | return false; |
| 296 | |
| 297 | // Constant case |
| 298 | if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Val: Imm.Val)) { |
| 299 | int64_t Value = ConstExpr->getValue(); |
| 300 | return isUInt<6>(x: Value); |
| 301 | } |
| 302 | return false; |
| 303 | } |
| 304 | bool isUImm7() { |
| 305 | if (!isImm()) |
| 306 | return false; |
| 307 | |
| 308 | // Constant case |
| 309 | if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Val: Imm.Val)) { |
| 310 | int64_t Value = ConstExpr->getValue(); |
| 311 | return isUInt<7>(x: Value); |
| 312 | } |
| 313 | return false; |
| 314 | } |
| 315 | bool isSImm7() { |
| 316 | if (!isImm()) |
| 317 | return false; |
| 318 | |
| 319 | // Constant case |
| 320 | if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Val: Imm.Val)) { |
| 321 | int64_t Value = ConstExpr->getValue(); |
| 322 | return isInt<7>(x: Value); |
| 323 | } |
| 324 | return false; |
| 325 | } |
| 326 | bool isMImm() const { |
| 327 | if (Kind != k_MImmOp) |
| 328 | return false; |
| 329 | |
| 330 | // Constant case |
| 331 | if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Val: MImm.Val)) { |
| 332 | int64_t Value = ConstExpr->getValue(); |
| 333 | return isUInt<6>(x: Value); |
| 334 | } |
| 335 | return false; |
| 336 | } |
| 337 | |
| 338 | StringRef getToken() const { |
| 339 | assert(Kind == k_Token && "Invalid access!" ); |
| 340 | return StringRef(Tok.Data, Tok.Length); |
| 341 | } |
| 342 | |
| 343 | MCRegister getReg() const override { |
| 344 | assert((Kind == k_Register) && "Invalid access!" ); |
| 345 | return Reg.RegNum; |
| 346 | } |
| 347 | |
| 348 | const MCExpr *getImm() const { |
| 349 | assert((Kind == k_Immediate) && "Invalid access!" ); |
| 350 | return Imm.Val; |
| 351 | } |
| 352 | |
| 353 | unsigned getMemBase() const { |
| 354 | assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm || |
| 355 | Kind == k_MemoryRegImm) && |
| 356 | "Invalid access!" ); |
| 357 | return Mem.Base; |
| 358 | } |
| 359 | |
| 360 | unsigned getMemIndexReg() const { |
| 361 | assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryZeroRegImm) && |
| 362 | "Invalid access!" ); |
| 363 | return Mem.IndexReg; |
| 364 | } |
| 365 | |
| 366 | const MCExpr *getMemIndex() const { |
| 367 | assert((Kind == k_MemoryRegImmImm || Kind == k_MemoryZeroImmImm) && |
| 368 | "Invalid access!" ); |
| 369 | return Mem.Index; |
| 370 | } |
| 371 | |
| 372 | const MCExpr *getMemOffset() const { |
| 373 | assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm || |
| 374 | Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm || |
| 375 | Kind == k_MemoryRegImm || Kind == k_MemoryZeroImm) && |
| 376 | "Invalid access!" ); |
| 377 | return Mem.Offset; |
| 378 | } |
| 379 | |
| 380 | void setMemOffset(const MCExpr *off) { |
| 381 | assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm || |
| 382 | Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm || |
| 383 | Kind == k_MemoryRegImm || Kind == k_MemoryZeroImm) && |
| 384 | "Invalid access!" ); |
| 385 | Mem.Offset = off; |
| 386 | } |
| 387 | |
| 388 | unsigned getCCVal() const { |
| 389 | assert((Kind == k_CCOp) && "Invalid access!" ); |
| 390 | return CC.CCVal; |
| 391 | } |
| 392 | |
| 393 | unsigned getRDVal() const { |
| 394 | assert((Kind == k_RDOp) && "Invalid access!" ); |
| 395 | return RD.RDVal; |
| 396 | } |
| 397 | |
| 398 | const MCExpr *getMImmVal() const { |
| 399 | assert((Kind == k_MImmOp) && "Invalid access!" ); |
| 400 | return MImm.Val; |
| 401 | } |
| 402 | bool getM0Flag() const { |
| 403 | assert((Kind == k_MImmOp) && "Invalid access!" ); |
| 404 | return MImm.M0Flag; |
| 405 | } |
| 406 | |
| 407 | /// getStartLoc - Get the location of the first token of this operand. |
| 408 | SMLoc getStartLoc() const override { return StartLoc; } |
| 409 | /// getEndLoc - Get the location of the last token of this operand. |
| 410 | SMLoc getEndLoc() const override { return EndLoc; } |
| 411 | |
| 412 | void print(raw_ostream &OS, const MCAsmInfo &MAI) const override { |
| 413 | switch (Kind) { |
| 414 | case k_Token: |
| 415 | OS << "Token: " << getToken() << "\n" ; |
| 416 | break; |
| 417 | case k_Register: |
| 418 | OS << "Reg: #" << getReg() << "\n" ; |
| 419 | break; |
| 420 | case k_Immediate: |
| 421 | OS << "Imm: " << getImm() << "\n" ; |
| 422 | break; |
| 423 | case k_MemoryRegRegImm: |
| 424 | assert(getMemOffset() != nullptr); |
| 425 | OS << "Mem: #" << getMemBase() << "+#" << getMemIndexReg() << "+" ; |
| 426 | MAI.printExpr(OS, *getMemOffset()); |
| 427 | OS << "\n" ; |
| 428 | break; |
| 429 | case k_MemoryRegImmImm: |
| 430 | assert(getMemIndex() != nullptr && getMemOffset() != nullptr); |
| 431 | OS << "Mem: #" << getMemBase() << "+" ; |
| 432 | MAI.printExpr(OS, *getMemIndex()); |
| 433 | OS << "+" ; |
| 434 | MAI.printExpr(OS, *getMemOffset()); |
| 435 | OS << "\n" ; |
| 436 | break; |
| 437 | case k_MemoryZeroRegImm: |
| 438 | assert(getMemOffset() != nullptr); |
| 439 | OS << "Mem: 0+#" << getMemIndexReg() << "+" ; |
| 440 | MAI.printExpr(OS, *getMemOffset()); |
| 441 | OS << "\n" ; |
| 442 | break; |
| 443 | case k_MemoryZeroImmImm: |
| 444 | assert(getMemIndex() != nullptr && getMemOffset() != nullptr); |
| 445 | OS << "Mem: 0+" ; |
| 446 | MAI.printExpr(OS, *getMemIndex()); |
| 447 | OS << "+" ; |
| 448 | MAI.printExpr(OS, *getMemOffset()); |
| 449 | OS << "\n" ; |
| 450 | break; |
| 451 | case k_MemoryRegImm: |
| 452 | assert(getMemOffset() != nullptr); |
| 453 | OS << "Mem: #" << getMemBase() << "+" ; |
| 454 | MAI.printExpr(OS, *getMemOffset()); |
| 455 | OS << "\n" ; |
| 456 | break; |
| 457 | case k_MemoryZeroImm: |
| 458 | assert(getMemOffset() != nullptr); |
| 459 | OS << "Mem: 0+" ; |
| 460 | MAI.printExpr(OS, *getMemOffset()); |
| 461 | OS << "\n" ; |
| 462 | break; |
| 463 | case k_CCOp: |
| 464 | OS << "CCOp: " << getCCVal() << "\n" ; |
| 465 | break; |
| 466 | case k_RDOp: |
| 467 | OS << "RDOp: " << getRDVal() << "\n" ; |
| 468 | break; |
| 469 | case k_MImmOp: |
| 470 | OS << "MImm: (" << getMImmVal() << (getM0Flag() ? ")0" : ")1" ) << "\n" ; |
| 471 | break; |
| 472 | } |
| 473 | } |
| 474 | |
| 475 | void addRegOperands(MCInst &Inst, unsigned N) const { |
| 476 | assert(N == 1 && "Invalid number of operands!" ); |
| 477 | Inst.addOperand(Op: MCOperand::createReg(Reg: getReg())); |
| 478 | } |
| 479 | |
| 480 | void addImmOperands(MCInst &Inst, unsigned N) const { |
| 481 | assert(N == 1 && "Invalid number of operands!" ); |
| 482 | const MCExpr *Expr = getImm(); |
| 483 | addExpr(Inst, Expr); |
| 484 | } |
| 485 | |
| 486 | void addZeroOperands(MCInst &Inst, unsigned N) const { |
| 487 | addImmOperands(Inst, N); |
| 488 | } |
| 489 | |
| 490 | void addUImm0to2Operands(MCInst &Inst, unsigned N) const { |
| 491 | addImmOperands(Inst, N); |
| 492 | } |
| 493 | |
| 494 | void addUImm1Operands(MCInst &Inst, unsigned N) const { |
| 495 | addImmOperands(Inst, N); |
| 496 | } |
| 497 | |
| 498 | void addUImm2Operands(MCInst &Inst, unsigned N) const { |
| 499 | addImmOperands(Inst, N); |
| 500 | } |
| 501 | |
| 502 | void addUImm3Operands(MCInst &Inst, unsigned N) const { |
| 503 | addImmOperands(Inst, N); |
| 504 | } |
| 505 | |
| 506 | void addUImm4Operands(MCInst &Inst, unsigned N) const { |
| 507 | addImmOperands(Inst, N); |
| 508 | } |
| 509 | |
| 510 | void addUImm6Operands(MCInst &Inst, unsigned N) const { |
| 511 | addImmOperands(Inst, N); |
| 512 | } |
| 513 | |
| 514 | void addUImm7Operands(MCInst &Inst, unsigned N) const { |
| 515 | addImmOperands(Inst, N); |
| 516 | } |
| 517 | |
| 518 | void addSImm7Operands(MCInst &Inst, unsigned N) const { |
| 519 | addImmOperands(Inst, N); |
| 520 | } |
| 521 | |
| 522 | void addExpr(MCInst &Inst, const MCExpr *Expr) const { |
| 523 | // Add as immediate when possible. Null MCExpr = 0. |
| 524 | if (!Expr) |
| 525 | Inst.addOperand(Op: MCOperand::createImm(Val: 0)); |
| 526 | else if (const auto *CE = dyn_cast<MCConstantExpr>(Val: Expr)) |
| 527 | Inst.addOperand(Op: MCOperand::createImm(Val: CE->getValue())); |
| 528 | else |
| 529 | Inst.addOperand(Op: MCOperand::createExpr(Val: Expr)); |
| 530 | } |
| 531 | |
| 532 | void addMEMrriOperands(MCInst &Inst, unsigned N) const { |
| 533 | assert(N == 3 && "Invalid number of operands!" ); |
| 534 | |
| 535 | Inst.addOperand(Op: MCOperand::createReg(Reg: getMemBase())); |
| 536 | Inst.addOperand(Op: MCOperand::createReg(Reg: getMemIndexReg())); |
| 537 | addExpr(Inst, Expr: getMemOffset()); |
| 538 | } |
| 539 | |
| 540 | void addMEMriiOperands(MCInst &Inst, unsigned N) const { |
| 541 | assert(N == 3 && "Invalid number of operands!" ); |
| 542 | |
| 543 | Inst.addOperand(Op: MCOperand::createReg(Reg: getMemBase())); |
| 544 | addExpr(Inst, Expr: getMemIndex()); |
| 545 | addExpr(Inst, Expr: getMemOffset()); |
| 546 | } |
| 547 | |
| 548 | void addMEMzriOperands(MCInst &Inst, unsigned N) const { |
| 549 | assert(N == 3 && "Invalid number of operands!" ); |
| 550 | |
| 551 | Inst.addOperand(Op: MCOperand::createImm(Val: 0)); |
| 552 | Inst.addOperand(Op: MCOperand::createReg(Reg: getMemIndexReg())); |
| 553 | addExpr(Inst, Expr: getMemOffset()); |
| 554 | } |
| 555 | |
| 556 | void addMEMziiOperands(MCInst &Inst, unsigned N) const { |
| 557 | assert(N == 3 && "Invalid number of operands!" ); |
| 558 | |
| 559 | Inst.addOperand(Op: MCOperand::createImm(Val: 0)); |
| 560 | addExpr(Inst, Expr: getMemIndex()); |
| 561 | addExpr(Inst, Expr: getMemOffset()); |
| 562 | } |
| 563 | |
| 564 | void addMEMriOperands(MCInst &Inst, unsigned N) const { |
| 565 | assert(N == 2 && "Invalid number of operands!" ); |
| 566 | |
| 567 | Inst.addOperand(Op: MCOperand::createReg(Reg: getMemBase())); |
| 568 | addExpr(Inst, Expr: getMemOffset()); |
| 569 | } |
| 570 | |
| 571 | void addMEMziOperands(MCInst &Inst, unsigned N) const { |
| 572 | assert(N == 2 && "Invalid number of operands!" ); |
| 573 | |
| 574 | Inst.addOperand(Op: MCOperand::createImm(Val: 0)); |
| 575 | addExpr(Inst, Expr: getMemOffset()); |
| 576 | } |
| 577 | |
| 578 | void addCCOpOperands(MCInst &Inst, unsigned N) const { |
| 579 | assert(N == 1 && "Invalid number of operands!" ); |
| 580 | |
| 581 | Inst.addOperand(Op: MCOperand::createImm(Val: getCCVal())); |
| 582 | } |
| 583 | |
| 584 | void addRDOpOperands(MCInst &Inst, unsigned N) const { |
| 585 | assert(N == 1 && "Invalid number of operands!" ); |
| 586 | |
| 587 | Inst.addOperand(Op: MCOperand::createImm(Val: getRDVal())); |
| 588 | } |
| 589 | |
| 590 | void addMImmOperands(MCInst &Inst, unsigned N) const { |
| 591 | assert(N == 1 && "Invalid number of operands!" ); |
| 592 | const auto *ConstExpr = dyn_cast<MCConstantExpr>(Val: getMImmVal()); |
| 593 | assert(ConstExpr && "Null operands!" ); |
| 594 | int64_t Value = ConstExpr->getValue(); |
| 595 | if (getM0Flag()) |
| 596 | Value += 64; |
| 597 | Inst.addOperand(Op: MCOperand::createImm(Val: Value)); |
| 598 | } |
| 599 | |
| 600 | static std::unique_ptr<VEOperand> CreateToken(StringRef Str, SMLoc S) { |
| 601 | auto Op = std::make_unique<VEOperand>(args: k_Token); |
| 602 | Op->Tok.Data = Str.data(); |
| 603 | Op->Tok.Length = Str.size(); |
| 604 | Op->StartLoc = S; |
| 605 | Op->EndLoc = S; |
| 606 | return Op; |
| 607 | } |
| 608 | |
| 609 | static std::unique_ptr<VEOperand> CreateReg(unsigned RegNum, SMLoc S, |
| 610 | SMLoc E) { |
| 611 | auto Op = std::make_unique<VEOperand>(args: k_Register); |
| 612 | Op->Reg.RegNum = RegNum; |
| 613 | Op->StartLoc = S; |
| 614 | Op->EndLoc = E; |
| 615 | return Op; |
| 616 | } |
| 617 | |
| 618 | static std::unique_ptr<VEOperand> CreateImm(const MCExpr *Val, SMLoc S, |
| 619 | SMLoc E) { |
| 620 | auto Op = std::make_unique<VEOperand>(args: k_Immediate); |
| 621 | Op->Imm.Val = Val; |
| 622 | Op->StartLoc = S; |
| 623 | Op->EndLoc = E; |
| 624 | return Op; |
| 625 | } |
| 626 | |
| 627 | static std::unique_ptr<VEOperand> CreateCCOp(unsigned CCVal, SMLoc S, |
| 628 | SMLoc E) { |
| 629 | auto Op = std::make_unique<VEOperand>(args: k_CCOp); |
| 630 | Op->CC.CCVal = CCVal; |
| 631 | Op->StartLoc = S; |
| 632 | Op->EndLoc = E; |
| 633 | return Op; |
| 634 | } |
| 635 | |
| 636 | static std::unique_ptr<VEOperand> CreateRDOp(unsigned RDVal, SMLoc S, |
| 637 | SMLoc E) { |
| 638 | auto Op = std::make_unique<VEOperand>(args: k_RDOp); |
| 639 | Op->RD.RDVal = RDVal; |
| 640 | Op->StartLoc = S; |
| 641 | Op->EndLoc = E; |
| 642 | return Op; |
| 643 | } |
| 644 | |
| 645 | static std::unique_ptr<VEOperand> CreateMImm(const MCExpr *Val, bool Flag, |
| 646 | SMLoc S, SMLoc E) { |
| 647 | auto Op = std::make_unique<VEOperand>(args: k_MImmOp); |
| 648 | Op->MImm.Val = Val; |
| 649 | Op->MImm.M0Flag = Flag; |
| 650 | Op->StartLoc = S; |
| 651 | Op->EndLoc = E; |
| 652 | return Op; |
| 653 | } |
| 654 | |
| 655 | static bool MorphToI32Reg(VEOperand &Op) { |
| 656 | unsigned Reg = Op.getReg(); |
| 657 | unsigned regIdx = Reg - VE::SX0; |
| 658 | if (regIdx > 63) |
| 659 | return false; |
| 660 | Op.Reg.RegNum = I32Regs[regIdx]; |
| 661 | return true; |
| 662 | } |
| 663 | |
| 664 | static bool MorphToF32Reg(VEOperand &Op) { |
| 665 | unsigned Reg = Op.getReg(); |
| 666 | unsigned regIdx = Reg - VE::SX0; |
| 667 | if (regIdx > 63) |
| 668 | return false; |
| 669 | Op.Reg.RegNum = F32Regs[regIdx]; |
| 670 | return true; |
| 671 | } |
| 672 | |
| 673 | static bool MorphToF128Reg(VEOperand &Op) { |
| 674 | unsigned Reg = Op.getReg(); |
| 675 | unsigned regIdx = Reg - VE::SX0; |
| 676 | if (regIdx % 2 || regIdx > 63) |
| 677 | return false; |
| 678 | Op.Reg.RegNum = F128Regs[regIdx / 2]; |
| 679 | return true; |
| 680 | } |
| 681 | |
| 682 | static bool MorphToVM512Reg(VEOperand &Op) { |
| 683 | unsigned Reg = Op.getReg(); |
| 684 | unsigned regIdx = Reg - VE::VM0; |
| 685 | if (regIdx % 2 || regIdx > 15) |
| 686 | return false; |
| 687 | Op.Reg.RegNum = VM512Regs[regIdx / 2]; |
| 688 | return true; |
| 689 | } |
| 690 | |
| 691 | static bool MorphToMISCReg(VEOperand &Op) { |
| 692 | const auto *ConstExpr = dyn_cast<MCConstantExpr>(Val: Op.getImm()); |
| 693 | if (!ConstExpr) |
| 694 | return false; |
| 695 | unsigned regIdx = ConstExpr->getValue(); |
| 696 | if (regIdx > 31 || MISCRegs[regIdx] == VE::NoRegister) |
| 697 | return false; |
| 698 | Op.Kind = k_Register; |
| 699 | Op.Reg.RegNum = MISCRegs[regIdx]; |
| 700 | return true; |
| 701 | } |
| 702 | |
| 703 | static std::unique_ptr<VEOperand> |
| 704 | MorphToMEMri(unsigned Base, std::unique_ptr<VEOperand> Op) { |
| 705 | const MCExpr *Imm = Op->getImm(); |
| 706 | Op->Kind = k_MemoryRegImm; |
| 707 | Op->Mem.Base = Base; |
| 708 | Op->Mem.IndexReg = 0; |
| 709 | Op->Mem.Index = nullptr; |
| 710 | Op->Mem.Offset = Imm; |
| 711 | return Op; |
| 712 | } |
| 713 | |
| 714 | static std::unique_ptr<VEOperand> |
| 715 | MorphToMEMzi(std::unique_ptr<VEOperand> Op) { |
| 716 | const MCExpr *Imm = Op->getImm(); |
| 717 | Op->Kind = k_MemoryZeroImm; |
| 718 | Op->Mem.Base = 0; |
| 719 | Op->Mem.IndexReg = 0; |
| 720 | Op->Mem.Index = nullptr; |
| 721 | Op->Mem.Offset = Imm; |
| 722 | return Op; |
| 723 | } |
| 724 | |
| 725 | static std::unique_ptr<VEOperand> |
| 726 | MorphToMEMrri(unsigned Base, unsigned Index, std::unique_ptr<VEOperand> Op) { |
| 727 | const MCExpr *Imm = Op->getImm(); |
| 728 | Op->Kind = k_MemoryRegRegImm; |
| 729 | Op->Mem.Base = Base; |
| 730 | Op->Mem.IndexReg = Index; |
| 731 | Op->Mem.Index = nullptr; |
| 732 | Op->Mem.Offset = Imm; |
| 733 | return Op; |
| 734 | } |
| 735 | |
| 736 | static std::unique_ptr<VEOperand> |
| 737 | MorphToMEMrii(unsigned Base, const MCExpr *Index, |
| 738 | std::unique_ptr<VEOperand> Op) { |
| 739 | const MCExpr *Imm = Op->getImm(); |
| 740 | Op->Kind = k_MemoryRegImmImm; |
| 741 | Op->Mem.Base = Base; |
| 742 | Op->Mem.IndexReg = 0; |
| 743 | Op->Mem.Index = Index; |
| 744 | Op->Mem.Offset = Imm; |
| 745 | return Op; |
| 746 | } |
| 747 | |
| 748 | static std::unique_ptr<VEOperand> |
| 749 | MorphToMEMzri(unsigned Index, std::unique_ptr<VEOperand> Op) { |
| 750 | const MCExpr *Imm = Op->getImm(); |
| 751 | Op->Kind = k_MemoryZeroRegImm; |
| 752 | Op->Mem.Base = 0; |
| 753 | Op->Mem.IndexReg = Index; |
| 754 | Op->Mem.Index = nullptr; |
| 755 | Op->Mem.Offset = Imm; |
| 756 | return Op; |
| 757 | } |
| 758 | |
| 759 | static std::unique_ptr<VEOperand> |
| 760 | MorphToMEMzii(const MCExpr *Index, std::unique_ptr<VEOperand> Op) { |
| 761 | const MCExpr *Imm = Op->getImm(); |
| 762 | Op->Kind = k_MemoryZeroImmImm; |
| 763 | Op->Mem.Base = 0; |
| 764 | Op->Mem.IndexReg = 0; |
| 765 | Op->Mem.Index = Index; |
| 766 | Op->Mem.Offset = Imm; |
| 767 | return Op; |
| 768 | } |
| 769 | }; |
| 770 | |
| 771 | } // end anonymous namespace |
| 772 | |
| 773 | bool VEAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
| 774 | OperandVector &Operands, |
| 775 | MCStreamer &Out, uint64_t &ErrorInfo, |
| 776 | bool MatchingInlineAsm) { |
| 777 | MCInst Inst; |
| 778 | unsigned MatchResult = |
| 779 | MatchInstructionImpl(Operands, Inst, ErrorInfo, matchingInlineAsm: MatchingInlineAsm); |
| 780 | switch (MatchResult) { |
| 781 | case Match_Success: |
| 782 | Inst.setLoc(IDLoc); |
| 783 | Out.emitInstruction(Inst, STI: getSTI()); |
| 784 | return false; |
| 785 | |
| 786 | case Match_MissingFeature: |
| 787 | return Error(L: IDLoc, |
| 788 | Msg: "instruction requires a CPU feature not currently enabled" ); |
| 789 | |
| 790 | case Match_InvalidOperand: { |
| 791 | SMLoc ErrorLoc = IDLoc; |
| 792 | if (ErrorInfo != ~0ULL) { |
| 793 | if (ErrorInfo >= Operands.size()) |
| 794 | return Error(L: IDLoc, Msg: "too few operands for instruction" ); |
| 795 | |
| 796 | ErrorLoc = ((VEOperand &)*Operands[ErrorInfo]).getStartLoc(); |
| 797 | if (ErrorLoc == SMLoc()) |
| 798 | ErrorLoc = IDLoc; |
| 799 | } |
| 800 | |
| 801 | return Error(L: ErrorLoc, Msg: "invalid operand for instruction" ); |
| 802 | } |
| 803 | case Match_MnemonicFail: |
| 804 | return Error(L: IDLoc, Msg: "invalid instruction mnemonic" ); |
| 805 | } |
| 806 | llvm_unreachable("Implement any new match types added!" ); |
| 807 | } |
| 808 | |
| 809 | bool VEAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, |
| 810 | SMLoc &EndLoc) { |
| 811 | if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess()) |
| 812 | return Error(L: StartLoc, Msg: "invalid register name" ); |
| 813 | return false; |
| 814 | } |
| 815 | |
| 816 | /// Parses a register name using a given matching function. |
| 817 | /// Checks for lowercase or uppercase if necessary. |
| 818 | int VEAsmParser::parseRegisterName(MCRegister (*matchFn)(StringRef)) { |
| 819 | StringRef Name = Parser.getTok().getString(); |
| 820 | |
| 821 | int RegNum = matchFn(Name); |
| 822 | |
| 823 | // GCC supports case insensitive register names. All of the VE registers |
| 824 | // are all lower case. |
| 825 | if (RegNum == VE::NoRegister) { |
| 826 | RegNum = matchFn(Name.lower()); |
| 827 | } |
| 828 | |
| 829 | return RegNum; |
| 830 | } |
| 831 | |
| 832 | /// Maps from the set of all register names to a register number. |
| 833 | /// \note Generated by TableGen. |
| 834 | static MCRegister MatchRegisterName(StringRef Name); |
| 835 | |
| 836 | /// Maps from the set of all alternative registernames to a register number. |
| 837 | /// \note Generated by TableGen. |
| 838 | static MCRegister MatchRegisterAltName(StringRef Name); |
| 839 | |
| 840 | ParseStatus VEAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, |
| 841 | SMLoc &EndLoc) { |
| 842 | const AsmToken Tok = Parser.getTok(); |
| 843 | StartLoc = Tok.getLoc(); |
| 844 | EndLoc = Tok.getEndLoc(); |
| 845 | Reg = VE::NoRegister; |
| 846 | if (getLexer().getKind() != AsmToken::Percent) |
| 847 | return ParseStatus::NoMatch; |
| 848 | Parser.Lex(); |
| 849 | |
| 850 | Reg = parseRegisterName(matchFn: &MatchRegisterName); |
| 851 | if (Reg == VE::NoRegister) |
| 852 | Reg = parseRegisterName(matchFn: &MatchRegisterAltName); |
| 853 | |
| 854 | if (Reg != VE::NoRegister) { |
| 855 | Parser.Lex(); |
| 856 | return ParseStatus::Success; |
| 857 | } |
| 858 | |
| 859 | getLexer().UnLex(Token: Tok); |
| 860 | return ParseStatus::NoMatch; |
| 861 | } |
| 862 | |
| 863 | static StringRef parseCC(StringRef Name, unsigned Prefix, unsigned Suffix, |
| 864 | bool IntegerCC, bool OmitCC, SMLoc NameLoc, |
| 865 | OperandVector *Operands) { |
| 866 | // Parse instructions with a conditional code. For example, 'bne' is |
| 867 | // converted into two operands 'b' and 'ne'. |
| 868 | StringRef Cond = Name.slice(Start: Prefix, End: Suffix); |
| 869 | VECC::CondCode CondCode = |
| 870 | IntegerCC ? stringToVEICondCode(S: Cond) : stringToVEFCondCode(S: Cond); |
| 871 | |
| 872 | // If OmitCC is enabled, CC_AT and CC_AF is treated as a part of mnemonic. |
| 873 | if (CondCode != VECC::UNKNOWN && |
| 874 | (!OmitCC || (CondCode != VECC::CC_AT && CondCode != VECC::CC_AF))) { |
| 875 | StringRef SuffixStr = Name.substr(Start: Suffix); |
| 876 | // Push "b". |
| 877 | Name = Name.slice(Start: 0, End: Prefix); |
| 878 | Operands->push_back(Elt: VEOperand::CreateToken(Str: Name, S: NameLoc)); |
| 879 | // Push $cond part. |
| 880 | SMLoc CondLoc = SMLoc::getFromPointer(Ptr: NameLoc.getPointer() + Prefix); |
| 881 | SMLoc SuffixLoc = SMLoc::getFromPointer(Ptr: NameLoc.getPointer() + Suffix); |
| 882 | Operands->push_back(Elt: VEOperand::CreateCCOp(CCVal: CondCode, S: CondLoc, E: SuffixLoc)); |
| 883 | // push suffix like ".l.t" |
| 884 | if (!SuffixStr.empty()) |
| 885 | Operands->push_back(Elt: VEOperand::CreateToken(Str: SuffixStr, S: SuffixLoc)); |
| 886 | } else { |
| 887 | Operands->push_back(Elt: VEOperand::CreateToken(Str: Name, S: NameLoc)); |
| 888 | } |
| 889 | return Name; |
| 890 | } |
| 891 | |
| 892 | static StringRef parseRD(StringRef Name, unsigned Prefix, SMLoc NameLoc, |
| 893 | OperandVector *Operands) { |
| 894 | // Parse instructions with a conditional code. For example, 'cvt.w.d.sx.rz' |
| 895 | // is converted into two operands 'cvt.w.d.sx' and '.rz'. |
| 896 | StringRef RD = Name.substr(Start: Prefix); |
| 897 | VERD::RoundingMode RoundingMode = stringToVERD(S: RD); |
| 898 | |
| 899 | if (RoundingMode != VERD::UNKNOWN) { |
| 900 | Name = Name.slice(Start: 0, End: Prefix); |
| 901 | // push 1st like `cvt.w.d.sx` |
| 902 | Operands->push_back(Elt: VEOperand::CreateToken(Str: Name, S: NameLoc)); |
| 903 | SMLoc SuffixLoc = |
| 904 | SMLoc::getFromPointer(Ptr: NameLoc.getPointer() + (RD.data() - Name.data())); |
| 905 | SMLoc SuffixEnd = |
| 906 | SMLoc::getFromPointer(Ptr: NameLoc.getPointer() + (RD.end() - Name.data())); |
| 907 | // push $round if it has rounding mode |
| 908 | Operands->push_back( |
| 909 | Elt: VEOperand::CreateRDOp(RDVal: RoundingMode, S: SuffixLoc, E: SuffixEnd)); |
| 910 | } else { |
| 911 | Operands->push_back(Elt: VEOperand::CreateToken(Str: Name, S: NameLoc)); |
| 912 | } |
| 913 | return Name; |
| 914 | } |
| 915 | |
| 916 | // Split the mnemonic into ASM operand, conditional code and instruction |
| 917 | // qualifier (half-word, byte). |
| 918 | StringRef VEAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc, |
| 919 | OperandVector *Operands) { |
| 920 | // Create the leading tokens for the mnemonic |
| 921 | StringRef Mnemonic = Name; |
| 922 | |
| 923 | if (Name[0] == 'b') { |
| 924 | // Match b?? or br??. |
| 925 | size_t Start = 1; |
| 926 | size_t Next = Name.find(C: '.'); |
| 927 | // Adjust position of CondCode. |
| 928 | if (Name.size() > 1 && Name[1] == 'r') |
| 929 | Start = 2; |
| 930 | // Check suffix. |
| 931 | bool ICC = true; |
| 932 | if (Next + 1 < Name.size() && |
| 933 | (Name[Next + 1] == 'd' || Name[Next + 1] == 's')) |
| 934 | ICC = false; |
| 935 | Mnemonic = parseCC(Name, Prefix: Start, Suffix: Next, IntegerCC: ICC, OmitCC: true, NameLoc, Operands); |
| 936 | } else if (Name.starts_with(Prefix: "cmov.l." ) || Name.starts_with(Prefix: "cmov.w." ) || |
| 937 | Name.starts_with(Prefix: "cmov.d." ) || Name.starts_with(Prefix: "cmov.s." )) { |
| 938 | bool ICC = Name[5] == 'l' || Name[5] == 'w'; |
| 939 | Mnemonic = parseCC(Name, Prefix: 7, Suffix: Name.size(), IntegerCC: ICC, OmitCC: false, NameLoc, Operands); |
| 940 | } else if (Name.starts_with(Prefix: "cvt.w.d.sx" ) || Name.starts_with(Prefix: "cvt.w.d.zx" ) || |
| 941 | Name.starts_with(Prefix: "cvt.w.s.sx" ) || Name.starts_with(Prefix: "cvt.w.s.zx" )) { |
| 942 | Mnemonic = parseRD(Name, Prefix: 10, NameLoc, Operands); |
| 943 | } else if (Name.starts_with(Prefix: "cvt.l.d" )) { |
| 944 | Mnemonic = parseRD(Name, Prefix: 7, NameLoc, Operands); |
| 945 | } else if (Name.starts_with(Prefix: "vcvt.w.d.sx" ) || |
| 946 | Name.starts_with(Prefix: "vcvt.w.d.zx" ) || |
| 947 | Name.starts_with(Prefix: "vcvt.w.s.sx" ) || |
| 948 | Name.starts_with(Prefix: "vcvt.w.s.zx" )) { |
| 949 | Mnemonic = parseRD(Name, Prefix: 11, NameLoc, Operands); |
| 950 | } else if (Name.starts_with(Prefix: "vcvt.l.d" )) { |
| 951 | Mnemonic = parseRD(Name, Prefix: 8, NameLoc, Operands); |
| 952 | } else if (Name.starts_with(Prefix: "pvcvt.w.s.lo" ) || |
| 953 | Name.starts_with(Prefix: "pvcvt.w.s.up" )) { |
| 954 | Mnemonic = parseRD(Name, Prefix: 12, NameLoc, Operands); |
| 955 | } else if (Name.starts_with(Prefix: "pvcvt.w.s" )) { |
| 956 | Mnemonic = parseRD(Name, Prefix: 9, NameLoc, Operands); |
| 957 | } else if (Name.starts_with(Prefix: "vfmk.l." ) || Name.starts_with(Prefix: "vfmk.w." ) || |
| 958 | Name.starts_with(Prefix: "vfmk.d." ) || Name.starts_with(Prefix: "vfmk.s." )) { |
| 959 | bool ICC = Name[5] == 'l' || Name[5] == 'w' ? true : false; |
| 960 | Mnemonic = parseCC(Name, Prefix: 7, Suffix: Name.size(), IntegerCC: ICC, OmitCC: true, NameLoc, Operands); |
| 961 | } else if (Name.starts_with(Prefix: "pvfmk.w.lo." ) || |
| 962 | Name.starts_with(Prefix: "pvfmk.w.up." ) || |
| 963 | Name.starts_with(Prefix: "pvfmk.s.lo." ) || |
| 964 | Name.starts_with(Prefix: "pvfmk.s.up." )) { |
| 965 | bool ICC = Name[6] == 'l' || Name[6] == 'w' ? true : false; |
| 966 | Mnemonic = parseCC(Name, Prefix: 11, Suffix: Name.size(), IntegerCC: ICC, OmitCC: true, NameLoc, Operands); |
| 967 | } else { |
| 968 | Operands->push_back(Elt: VEOperand::CreateToken(Str: Mnemonic, S: NameLoc)); |
| 969 | } |
| 970 | |
| 971 | return Mnemonic; |
| 972 | } |
| 973 | |
| 974 | static void applyMnemonicAliases(StringRef &Mnemonic, |
| 975 | const FeatureBitset &Features, |
| 976 | unsigned VariantID); |
| 977 | |
| 978 | bool VEAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name, |
| 979 | SMLoc NameLoc, OperandVector &Operands) { |
| 980 | // If the target architecture uses MnemonicAlias, call it here to parse |
| 981 | // operands correctly. |
| 982 | applyMnemonicAliases(Mnemonic&: Name, Features: getAvailableFeatures(), VariantID: 0); |
| 983 | |
| 984 | // Split name to first token and the rest, e.g. "bgt.l.t" to "b", "gt", and |
| 985 | // ".l.t". We treat "b" as a mnemonic, "gt" as first operand, and ".l.t" |
| 986 | // as second operand. |
| 987 | StringRef Mnemonic = splitMnemonic(Name, NameLoc, Operands: &Operands); |
| 988 | |
| 989 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) { |
| 990 | // Read the first operand. |
| 991 | if (!parseOperand(Operands, Name: Mnemonic).isSuccess()) { |
| 992 | SMLoc Loc = getLexer().getLoc(); |
| 993 | return Error(L: Loc, Msg: "unexpected token" ); |
| 994 | } |
| 995 | |
| 996 | while (getLexer().is(K: AsmToken::Comma)) { |
| 997 | Parser.Lex(); // Eat the comma. |
| 998 | // Parse and remember the operand. |
| 999 | if (!parseOperand(Operands, Name: Mnemonic).isSuccess()) { |
| 1000 | SMLoc Loc = getLexer().getLoc(); |
| 1001 | return Error(L: Loc, Msg: "unexpected token" ); |
| 1002 | } |
| 1003 | } |
| 1004 | } |
| 1005 | if (getLexer().isNot(K: AsmToken::EndOfStatement)) { |
| 1006 | SMLoc Loc = getLexer().getLoc(); |
| 1007 | return Error(L: Loc, Msg: "unexpected token" ); |
| 1008 | } |
| 1009 | Parser.Lex(); // Consume the EndOfStatement. |
| 1010 | return false; |
| 1011 | } |
| 1012 | |
| 1013 | ParseStatus VEAsmParser::parseDirective(AsmToken DirectiveID) { |
| 1014 | std::string IDVal = DirectiveID.getIdentifier().lower(); |
| 1015 | |
| 1016 | // Defines VE specific directives. Reference is "Vector Engine Assembly |
| 1017 | // Language Reference Manual": |
| 1018 | // https://www.hpc.nec/documents/sdk/pdfs/VectorEngine-as-manual-v1.3.pdf |
| 1019 | |
| 1020 | // The .word is 4 bytes long on VE. |
| 1021 | if (IDVal == ".word" ) |
| 1022 | return parseLiteralValues(Size: 4, L: DirectiveID.getLoc()); |
| 1023 | |
| 1024 | // The .long is 8 bytes long on VE. |
| 1025 | if (IDVal == ".long" ) |
| 1026 | return parseLiteralValues(Size: 8, L: DirectiveID.getLoc()); |
| 1027 | |
| 1028 | // The .llong is 8 bytes long on VE. |
| 1029 | if (IDVal == ".llong" ) |
| 1030 | return parseLiteralValues(Size: 8, L: DirectiveID.getLoc()); |
| 1031 | |
| 1032 | // Let the MC layer to handle other directives. |
| 1033 | return ParseStatus::NoMatch; |
| 1034 | } |
| 1035 | |
| 1036 | /// parseLiteralValues |
| 1037 | /// ::= .word expression [, expression]* |
| 1038 | /// ::= .long expression [, expression]* |
| 1039 | /// ::= .llong expression [, expression]* |
| 1040 | bool VEAsmParser::parseLiteralValues(unsigned Size, SMLoc L) { |
| 1041 | auto parseOne = [&]() -> bool { |
| 1042 | const MCExpr *Value; |
| 1043 | if (getParser().parseExpression(Res&: Value)) |
| 1044 | return true; |
| 1045 | getParser().getStreamer().emitValue(Value, Size, Loc: L); |
| 1046 | return false; |
| 1047 | }; |
| 1048 | return (parseMany(parseOne)); |
| 1049 | } |
| 1050 | |
| 1051 | /// Extract \code @lo32/@hi32/etc \endcode specifier from expression. |
| 1052 | /// Recursively scan the expression and check for VK_HI32/LO32/etc |
| 1053 | /// symbol variants. If all symbols with modifier use the same |
| 1054 | /// variant, return the corresponding VE::Specifier, |
| 1055 | /// and a modified expression using the default symbol variant. |
| 1056 | /// Otherwise, return NULL. |
| 1057 | const MCExpr *VEAsmParser::(const MCExpr *E, |
| 1058 | VE::Specifier &Variant) { |
| 1059 | MCContext &Context = getParser().getContext(); |
| 1060 | Variant = VE::S_None; |
| 1061 | |
| 1062 | switch (E->getKind()) { |
| 1063 | case MCExpr::Target: |
| 1064 | case MCExpr::Constant: |
| 1065 | return nullptr; |
| 1066 | case MCExpr::Specifier: |
| 1067 | llvm_unreachable("unused by this backend" ); |
| 1068 | |
| 1069 | case MCExpr::SymbolRef: { |
| 1070 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Val: E); |
| 1071 | |
| 1072 | switch (SRE->getSpecifier()) { |
| 1073 | case VE::S_None: |
| 1074 | // Use VK_REFLONG to a symbol without modifiers. |
| 1075 | Variant = VE::S_REFLONG; |
| 1076 | break; |
| 1077 | case VE::S_HI32: |
| 1078 | Variant = VE::S_HI32; |
| 1079 | break; |
| 1080 | case VE::S_LO32: |
| 1081 | Variant = VE::S_LO32; |
| 1082 | break; |
| 1083 | case VE::S_PC_HI32: |
| 1084 | Variant = VE::S_PC_HI32; |
| 1085 | break; |
| 1086 | case VE::S_PC_LO32: |
| 1087 | Variant = VE::S_PC_LO32; |
| 1088 | break; |
| 1089 | case VE::S_GOT_HI32: |
| 1090 | Variant = VE::S_GOT_HI32; |
| 1091 | break; |
| 1092 | case VE::S_GOT_LO32: |
| 1093 | Variant = VE::S_GOT_LO32; |
| 1094 | break; |
| 1095 | case VE::S_GOTOFF_HI32: |
| 1096 | Variant = VE::S_GOTOFF_HI32; |
| 1097 | break; |
| 1098 | case VE::S_GOTOFF_LO32: |
| 1099 | Variant = VE::S_GOTOFF_LO32; |
| 1100 | break; |
| 1101 | case VE::S_PLT_HI32: |
| 1102 | Variant = VE::S_PLT_HI32; |
| 1103 | break; |
| 1104 | case VE::S_PLT_LO32: |
| 1105 | Variant = VE::S_PLT_LO32; |
| 1106 | break; |
| 1107 | case VE::S_TLS_GD_HI32: |
| 1108 | Variant = VE::S_TLS_GD_HI32; |
| 1109 | break; |
| 1110 | case VE::S_TLS_GD_LO32: |
| 1111 | Variant = VE::S_TLS_GD_LO32; |
| 1112 | break; |
| 1113 | case VE::S_TPOFF_HI32: |
| 1114 | Variant = VE::S_TPOFF_HI32; |
| 1115 | break; |
| 1116 | case VE::S_TPOFF_LO32: |
| 1117 | Variant = VE::S_TPOFF_LO32; |
| 1118 | break; |
| 1119 | default: |
| 1120 | return nullptr; |
| 1121 | } |
| 1122 | |
| 1123 | return MCSymbolRefExpr::create(Symbol: &SRE->getSymbol(), Ctx&: Context); |
| 1124 | } |
| 1125 | |
| 1126 | case MCExpr::Unary: { |
| 1127 | const MCUnaryExpr *UE = cast<MCUnaryExpr>(Val: E); |
| 1128 | const MCExpr *Sub = extractSpecifier(E: UE->getSubExpr(), Variant); |
| 1129 | if (!Sub) |
| 1130 | return nullptr; |
| 1131 | return MCUnaryExpr::create(Op: UE->getOpcode(), Expr: Sub, Ctx&: Context); |
| 1132 | } |
| 1133 | |
| 1134 | case MCExpr::Binary: { |
| 1135 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(Val: E); |
| 1136 | VE::Specifier LHSVariant, RHSVariant; |
| 1137 | const MCExpr *LHS = extractSpecifier(E: BE->getLHS(), Variant&: LHSVariant); |
| 1138 | const MCExpr *RHS = extractSpecifier(E: BE->getRHS(), Variant&: RHSVariant); |
| 1139 | |
| 1140 | if (!LHS && !RHS) |
| 1141 | return nullptr; |
| 1142 | |
| 1143 | if (!LHS) |
| 1144 | LHS = BE->getLHS(); |
| 1145 | if (!RHS) |
| 1146 | RHS = BE->getRHS(); |
| 1147 | |
| 1148 | if (LHSVariant == VE::S_None) |
| 1149 | Variant = RHSVariant; |
| 1150 | else if (RHSVariant == VE::S_None) |
| 1151 | Variant = LHSVariant; |
| 1152 | else if (LHSVariant == RHSVariant) |
| 1153 | Variant = LHSVariant; |
| 1154 | else |
| 1155 | return nullptr; |
| 1156 | |
| 1157 | return MCBinaryExpr::create(Op: BE->getOpcode(), LHS, RHS, Ctx&: Context); |
| 1158 | } |
| 1159 | } |
| 1160 | |
| 1161 | llvm_unreachable("Invalid expression kind!" ); |
| 1162 | } |
| 1163 | |
| 1164 | /// This differs from the default "parseExpression" in that it handles |
| 1165 | /// relocation specifiers. |
| 1166 | bool VEAsmParser::parseExpression(const MCExpr *&EVal) { |
| 1167 | // Handle \code symbol @lo32/@hi32/etc \endcode. |
| 1168 | if (getParser().parseExpression(Res&: EVal)) |
| 1169 | return true; |
| 1170 | |
| 1171 | // Convert MCSymbolRefExpr with specifier to MCSpecifierExpr. |
| 1172 | VE::Specifier Specifier; |
| 1173 | const MCExpr *E = extractSpecifier(E: EVal, Variant&: Specifier); |
| 1174 | if (E) |
| 1175 | EVal = MCSpecifierExpr::create(Expr: E, S: Specifier, Ctx&: getParser().getContext()); |
| 1176 | |
| 1177 | return false; |
| 1178 | } |
| 1179 | |
| 1180 | ParseStatus VEAsmParser::parseMEMOperand(OperandVector &Operands) { |
| 1181 | LLVM_DEBUG(dbgs() << "parseMEMOperand\n" ); |
| 1182 | const AsmToken &Tok = Parser.getTok(); |
| 1183 | SMLoc S = Tok.getLoc(); |
| 1184 | SMLoc E = Tok.getEndLoc(); |
| 1185 | // Parse ASX format |
| 1186 | // disp |
| 1187 | // disp(, base) |
| 1188 | // disp(index) |
| 1189 | // disp(index, base) |
| 1190 | // (, base) |
| 1191 | // (index) |
| 1192 | // (index, base) |
| 1193 | |
| 1194 | std::unique_ptr<VEOperand> Offset; |
| 1195 | switch (getLexer().getKind()) { |
| 1196 | default: |
| 1197 | return ParseStatus::NoMatch; |
| 1198 | |
| 1199 | case AsmToken::Minus: |
| 1200 | case AsmToken::Integer: |
| 1201 | case AsmToken::Dot: |
| 1202 | case AsmToken::Identifier: { |
| 1203 | const MCExpr *EVal; |
| 1204 | if (!parseExpression(EVal)) |
| 1205 | Offset = VEOperand::CreateImm(Val: EVal, S, E); |
| 1206 | else |
| 1207 | return ParseStatus::NoMatch; |
| 1208 | break; |
| 1209 | } |
| 1210 | |
| 1211 | case AsmToken::LParen: |
| 1212 | // empty disp (= 0) |
| 1213 | Offset = |
| 1214 | VEOperand::CreateImm(Val: MCConstantExpr::create(Value: 0, Ctx&: getContext()), S, E); |
| 1215 | break; |
| 1216 | } |
| 1217 | |
| 1218 | switch (getLexer().getKind()) { |
| 1219 | default: |
| 1220 | return ParseStatus::Failure; |
| 1221 | |
| 1222 | case AsmToken::EndOfStatement: |
| 1223 | Operands.push_back(Elt: VEOperand::MorphToMEMzii( |
| 1224 | Index: MCConstantExpr::create(Value: 0, Ctx&: getContext()), Op: std::move(Offset))); |
| 1225 | return ParseStatus::Success; |
| 1226 | |
| 1227 | case AsmToken::LParen: |
| 1228 | Parser.Lex(); // Eat the ( |
| 1229 | break; |
| 1230 | } |
| 1231 | |
| 1232 | const MCExpr *IndexValue = nullptr; |
| 1233 | MCRegister IndexReg; |
| 1234 | |
| 1235 | switch (getLexer().getKind()) { |
| 1236 | default: |
| 1237 | if (parseRegister(Reg&: IndexReg, StartLoc&: S, EndLoc&: E)) |
| 1238 | return ParseStatus::Failure; |
| 1239 | break; |
| 1240 | |
| 1241 | case AsmToken::Minus: |
| 1242 | case AsmToken::Integer: |
| 1243 | case AsmToken::Dot: |
| 1244 | if (getParser().parseExpression(Res&: IndexValue, EndLoc&: E)) |
| 1245 | return ParseStatus::Failure; |
| 1246 | break; |
| 1247 | |
| 1248 | case AsmToken::Comma: |
| 1249 | // empty index |
| 1250 | IndexValue = MCConstantExpr::create(Value: 0, Ctx&: getContext()); |
| 1251 | break; |
| 1252 | } |
| 1253 | |
| 1254 | switch (getLexer().getKind()) { |
| 1255 | default: |
| 1256 | return ParseStatus::Failure; |
| 1257 | |
| 1258 | case AsmToken::RParen: |
| 1259 | Parser.Lex(); // Eat the ) |
| 1260 | Operands.push_back( |
| 1261 | Elt: IndexValue ? VEOperand::MorphToMEMzii(Index: IndexValue, Op: std::move(Offset)) |
| 1262 | : VEOperand::MorphToMEMzri(Index: IndexReg, Op: std::move(Offset))); |
| 1263 | return ParseStatus::Success; |
| 1264 | |
| 1265 | case AsmToken::Comma: |
| 1266 | Parser.Lex(); // Eat the , |
| 1267 | break; |
| 1268 | } |
| 1269 | |
| 1270 | MCRegister BaseReg; |
| 1271 | if (parseRegister(Reg&: BaseReg, StartLoc&: S, EndLoc&: E)) |
| 1272 | return ParseStatus::Failure; |
| 1273 | |
| 1274 | if (!Parser.getTok().is(K: AsmToken::RParen)) |
| 1275 | return ParseStatus::Failure; |
| 1276 | |
| 1277 | Parser.Lex(); // Eat the ) |
| 1278 | Operands.push_back( |
| 1279 | Elt: IndexValue |
| 1280 | ? VEOperand::MorphToMEMrii(Base: BaseReg, Index: IndexValue, Op: std::move(Offset)) |
| 1281 | : VEOperand::MorphToMEMrri(Base: BaseReg, Index: IndexReg, Op: std::move(Offset))); |
| 1282 | |
| 1283 | return ParseStatus::Success; |
| 1284 | } |
| 1285 | |
| 1286 | ParseStatus VEAsmParser::parseMEMAsOperand(OperandVector &Operands) { |
| 1287 | LLVM_DEBUG(dbgs() << "parseMEMAsOperand\n" ); |
| 1288 | const AsmToken &Tok = Parser.getTok(); |
| 1289 | SMLoc S = Tok.getLoc(); |
| 1290 | SMLoc E = Tok.getEndLoc(); |
| 1291 | // Parse AS format |
| 1292 | // disp |
| 1293 | // disp(, base) |
| 1294 | // disp(base) |
| 1295 | // disp() |
| 1296 | // (, base) |
| 1297 | // (base) |
| 1298 | // base |
| 1299 | |
| 1300 | MCRegister BaseReg; |
| 1301 | std::unique_ptr<VEOperand> Offset; |
| 1302 | switch (getLexer().getKind()) { |
| 1303 | default: |
| 1304 | return ParseStatus::NoMatch; |
| 1305 | |
| 1306 | case AsmToken::Minus: |
| 1307 | case AsmToken::Integer: |
| 1308 | case AsmToken::Dot: |
| 1309 | case AsmToken::Identifier: { |
| 1310 | const MCExpr *EVal; |
| 1311 | if (!parseExpression(EVal)) |
| 1312 | Offset = VEOperand::CreateImm(Val: EVal, S, E); |
| 1313 | else |
| 1314 | return ParseStatus::NoMatch; |
| 1315 | break; |
| 1316 | } |
| 1317 | |
| 1318 | case AsmToken::Percent: |
| 1319 | if (parseRegister(Reg&: BaseReg, StartLoc&: S, EndLoc&: E)) |
| 1320 | return ParseStatus::NoMatch; |
| 1321 | Offset = |
| 1322 | VEOperand::CreateImm(Val: MCConstantExpr::create(Value: 0, Ctx&: getContext()), S, E); |
| 1323 | break; |
| 1324 | |
| 1325 | case AsmToken::LParen: |
| 1326 | // empty disp (= 0) |
| 1327 | Offset = |
| 1328 | VEOperand::CreateImm(Val: MCConstantExpr::create(Value: 0, Ctx&: getContext()), S, E); |
| 1329 | break; |
| 1330 | } |
| 1331 | |
| 1332 | switch (getLexer().getKind()) { |
| 1333 | default: |
| 1334 | return ParseStatus::Failure; |
| 1335 | |
| 1336 | case AsmToken::EndOfStatement: |
| 1337 | case AsmToken::Comma: |
| 1338 | Operands.push_back(Elt: BaseReg != VE::NoRegister |
| 1339 | ? VEOperand::MorphToMEMri(Base: BaseReg, Op: std::move(Offset)) |
| 1340 | : VEOperand::MorphToMEMzi(Op: std::move(Offset))); |
| 1341 | return ParseStatus::Success; |
| 1342 | |
| 1343 | case AsmToken::LParen: |
| 1344 | if (BaseReg != VE::NoRegister) |
| 1345 | return ParseStatus::Failure; |
| 1346 | Parser.Lex(); // Eat the ( |
| 1347 | break; |
| 1348 | } |
| 1349 | |
| 1350 | switch (getLexer().getKind()) { |
| 1351 | default: |
| 1352 | if (parseRegister(Reg&: BaseReg, StartLoc&: S, EndLoc&: E)) |
| 1353 | return ParseStatus::Failure; |
| 1354 | break; |
| 1355 | |
| 1356 | case AsmToken::Comma: |
| 1357 | Parser.Lex(); // Eat the , |
| 1358 | if (parseRegister(Reg&: BaseReg, StartLoc&: S, EndLoc&: E)) |
| 1359 | return ParseStatus::Failure; |
| 1360 | break; |
| 1361 | |
| 1362 | case AsmToken::RParen: |
| 1363 | break; |
| 1364 | } |
| 1365 | |
| 1366 | if (!Parser.getTok().is(K: AsmToken::RParen)) |
| 1367 | return ParseStatus::Failure; |
| 1368 | |
| 1369 | Parser.Lex(); // Eat the ) |
| 1370 | Operands.push_back(Elt: BaseReg != VE::NoRegister |
| 1371 | ? VEOperand::MorphToMEMri(Base: BaseReg, Op: std::move(Offset)) |
| 1372 | : VEOperand::MorphToMEMzi(Op: std::move(Offset))); |
| 1373 | |
| 1374 | return ParseStatus::Success; |
| 1375 | } |
| 1376 | |
| 1377 | ParseStatus VEAsmParser::parseMImmOperand(OperandVector &Operands) { |
| 1378 | LLVM_DEBUG(dbgs() << "parseMImmOperand\n" ); |
| 1379 | |
| 1380 | // Parsing "(" + number + ")0/1" |
| 1381 | const AsmToken Tok1 = Parser.getTok(); |
| 1382 | if (!Tok1.is(K: AsmToken::LParen)) |
| 1383 | return ParseStatus::NoMatch; |
| 1384 | |
| 1385 | Parser.Lex(); // Eat the '('. |
| 1386 | |
| 1387 | const AsmToken Tok2 = Parser.getTok(); |
| 1388 | SMLoc E; |
| 1389 | const MCExpr *EVal; |
| 1390 | if (!Tok2.is(K: AsmToken::Integer) || getParser().parseExpression(Res&: EVal, EndLoc&: E)) { |
| 1391 | getLexer().UnLex(Token: Tok1); |
| 1392 | return ParseStatus::NoMatch; |
| 1393 | } |
| 1394 | |
| 1395 | const AsmToken Tok3 = Parser.getTok(); |
| 1396 | if (!Tok3.is(K: AsmToken::RParen)) { |
| 1397 | getLexer().UnLex(Token: Tok2); |
| 1398 | getLexer().UnLex(Token: Tok1); |
| 1399 | return ParseStatus::NoMatch; |
| 1400 | } |
| 1401 | Parser.Lex(); // Eat the ')'. |
| 1402 | |
| 1403 | const AsmToken &Tok4 = Parser.getTok(); |
| 1404 | StringRef Suffix = Tok4.getString(); |
| 1405 | if (Suffix != "1" && Suffix != "0" ) { |
| 1406 | getLexer().UnLex(Token: Tok3); |
| 1407 | getLexer().UnLex(Token: Tok2); |
| 1408 | getLexer().UnLex(Token: Tok1); |
| 1409 | return ParseStatus::NoMatch; |
| 1410 | } |
| 1411 | Parser.Lex(); // Eat the value. |
| 1412 | SMLoc EndLoc = SMLoc::getFromPointer(Ptr: Suffix.end()); |
| 1413 | Operands.push_back( |
| 1414 | Elt: VEOperand::CreateMImm(Val: EVal, Flag: Suffix == "0" , S: Tok1.getLoc(), E: EndLoc)); |
| 1415 | return ParseStatus::Success; |
| 1416 | } |
| 1417 | |
| 1418 | ParseStatus VEAsmParser::parseOperand(OperandVector &Operands, |
| 1419 | StringRef Mnemonic) { |
| 1420 | LLVM_DEBUG(dbgs() << "parseOperand\n" ); |
| 1421 | ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic); |
| 1422 | |
| 1423 | // If there wasn't a custom match, try the generic matcher below. Otherwise, |
| 1424 | // there was a match, but an error occurred, in which case, just return that |
| 1425 | // the operand parsing failed. |
| 1426 | if (Res.isSuccess() || Res.isFailure()) |
| 1427 | return Res; |
| 1428 | |
| 1429 | switch (getLexer().getKind()) { |
| 1430 | case AsmToken::LParen: { |
| 1431 | // Parsing "(" + %vreg + ", " + %vreg + ")" |
| 1432 | const AsmToken Tok1 = Parser.getTok(); |
| 1433 | Parser.Lex(); // Eat the '('. |
| 1434 | |
| 1435 | MCRegister Reg1; |
| 1436 | SMLoc S1, E1; |
| 1437 | if (!tryParseRegister(Reg&: Reg1, StartLoc&: S1, EndLoc&: E1).isSuccess()) { |
| 1438 | getLexer().UnLex(Token: Tok1); |
| 1439 | return ParseStatus::NoMatch; |
| 1440 | } |
| 1441 | |
| 1442 | if (!Parser.getTok().is(K: AsmToken::Comma)) |
| 1443 | return ParseStatus::Failure; |
| 1444 | Parser.Lex(); // Eat the ','. |
| 1445 | |
| 1446 | MCRegister Reg2; |
| 1447 | SMLoc S2, E2; |
| 1448 | if (!tryParseRegister(Reg&: Reg2, StartLoc&: S2, EndLoc&: E2).isSuccess()) |
| 1449 | return ParseStatus::Failure; |
| 1450 | |
| 1451 | if (!Parser.getTok().is(K: AsmToken::RParen)) |
| 1452 | return ParseStatus::Failure; |
| 1453 | |
| 1454 | Operands.push_back(Elt: VEOperand::CreateToken(Str: Tok1.getString(), S: Tok1.getLoc())); |
| 1455 | Operands.push_back(Elt: VEOperand::CreateReg(RegNum: Reg1, S: S1, E: E1)); |
| 1456 | Operands.push_back(Elt: VEOperand::CreateReg(RegNum: Reg2, S: S2, E: E2)); |
| 1457 | Operands.push_back(Elt: VEOperand::CreateToken(Str: Parser.getTok().getString(), |
| 1458 | S: Parser.getTok().getLoc())); |
| 1459 | Parser.Lex(); // Eat the ')'. |
| 1460 | break; |
| 1461 | } |
| 1462 | default: { |
| 1463 | std::unique_ptr<VEOperand> Op; |
| 1464 | Res = parseVEAsmOperand(Operand&: Op); |
| 1465 | if (!Res.isSuccess() || !Op) |
| 1466 | return ParseStatus::Failure; |
| 1467 | |
| 1468 | // Push the parsed operand into the list of operands |
| 1469 | Operands.push_back(Elt: std::move(Op)); |
| 1470 | |
| 1471 | if (!Parser.getTok().is(K: AsmToken::LParen)) |
| 1472 | break; |
| 1473 | |
| 1474 | // Parsing %vec-reg + "(" + %sclar-reg/number + ")" |
| 1475 | std::unique_ptr<VEOperand> Op1 = VEOperand::CreateToken( |
| 1476 | Str: Parser.getTok().getString(), S: Parser.getTok().getLoc()); |
| 1477 | Parser.Lex(); // Eat the '('. |
| 1478 | |
| 1479 | std::unique_ptr<VEOperand> Op2; |
| 1480 | Res = parseVEAsmOperand(Operand&: Op2); |
| 1481 | if (!Res.isSuccess() || !Op2) |
| 1482 | return ParseStatus::Failure; |
| 1483 | |
| 1484 | if (!Parser.getTok().is(K: AsmToken::RParen)) |
| 1485 | return ParseStatus::Failure; |
| 1486 | |
| 1487 | Operands.push_back(Elt: std::move(Op1)); |
| 1488 | Operands.push_back(Elt: std::move(Op2)); |
| 1489 | Operands.push_back(Elt: VEOperand::CreateToken(Str: Parser.getTok().getString(), |
| 1490 | S: Parser.getTok().getLoc())); |
| 1491 | Parser.Lex(); // Eat the ')'. |
| 1492 | break; |
| 1493 | } |
| 1494 | } |
| 1495 | |
| 1496 | return ParseStatus::Success; |
| 1497 | } |
| 1498 | |
| 1499 | ParseStatus VEAsmParser::parseVEAsmOperand(std::unique_ptr<VEOperand> &Op) { |
| 1500 | LLVM_DEBUG(dbgs() << "parseVEAsmOperand\n" ); |
| 1501 | SMLoc S = Parser.getTok().getLoc(); |
| 1502 | SMLoc E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1); |
| 1503 | const MCExpr *EVal; |
| 1504 | |
| 1505 | Op = nullptr; |
| 1506 | switch (getLexer().getKind()) { |
| 1507 | default: |
| 1508 | break; |
| 1509 | |
| 1510 | case AsmToken::Percent: { |
| 1511 | MCRegister Reg; |
| 1512 | if (tryParseRegister(Reg, StartLoc&: S, EndLoc&: E).isSuccess()) |
| 1513 | Op = VEOperand::CreateReg(RegNum: Reg, S, E); |
| 1514 | break; |
| 1515 | } |
| 1516 | case AsmToken::Minus: |
| 1517 | case AsmToken::Integer: |
| 1518 | case AsmToken::Dot: |
| 1519 | case AsmToken::Identifier: |
| 1520 | if (!parseExpression(EVal)) |
| 1521 | Op = VEOperand::CreateImm(Val: EVal, S, E); |
| 1522 | break; |
| 1523 | } |
| 1524 | return Op ? ParseStatus::Success : ParseStatus::Failure; |
| 1525 | } |
| 1526 | |
| 1527 | // Force static initialization. |
| 1528 | extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmParser() { |
| 1529 | RegisterMCAsmParser<VEAsmParser> A(getTheVETarget()); |
| 1530 | } |
| 1531 | |
| 1532 | #define GET_REGISTER_MATCHER |
| 1533 | #define GET_MATCHER_IMPLEMENTATION |
| 1534 | #include "VEGenAsmMatcher.inc" |
| 1535 | |
| 1536 | unsigned VEAsmParser::validateTargetOperandClass(MCParsedAsmOperand &GOp, |
| 1537 | unsigned Kind) { |
| 1538 | VEOperand &Op = (VEOperand &)GOp; |
| 1539 | |
| 1540 | // VE uses identical register name for all registers like both |
| 1541 | // F32 and I32 uses "%s23". Need to convert the name of them |
| 1542 | // for validation. |
| 1543 | switch (Kind) { |
| 1544 | default: |
| 1545 | break; |
| 1546 | case MCK_F32: |
| 1547 | if (Op.isReg() && VEOperand::MorphToF32Reg(Op)) |
| 1548 | return MCTargetAsmParser::Match_Success; |
| 1549 | break; |
| 1550 | case MCK_I32: |
| 1551 | if (Op.isReg() && VEOperand::MorphToI32Reg(Op)) |
| 1552 | return MCTargetAsmParser::Match_Success; |
| 1553 | break; |
| 1554 | case MCK_F128: |
| 1555 | if (Op.isReg() && VEOperand::MorphToF128Reg(Op)) |
| 1556 | return MCTargetAsmParser::Match_Success; |
| 1557 | break; |
| 1558 | case MCK_VM512: |
| 1559 | if (Op.isReg() && VEOperand::MorphToVM512Reg(Op)) |
| 1560 | return MCTargetAsmParser::Match_Success; |
| 1561 | break; |
| 1562 | case MCK_MISC: |
| 1563 | if (Op.isImm() && VEOperand::MorphToMISCReg(Op)) |
| 1564 | return MCTargetAsmParser::Match_Success; |
| 1565 | break; |
| 1566 | } |
| 1567 | return Match_InvalidOperand; |
| 1568 | } |
| 1569 | |