15f613dfdSUlrich Weigand //===-- SystemZAsmParser.cpp - Parse SystemZ assembly instructions --------===//
25f613dfdSUlrich Weigand //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f613dfdSUlrich Weigand //
75f613dfdSUlrich Weigand //===----------------------------------------------------------------------===//
85f613dfdSUlrich Weigand 
9d0124bd7SRichard Trieu #include "MCTargetDesc/SystemZInstPrinter.h"
107a46d34aSAnirudh Prasad #include "MCTargetDesc/SystemZMCAsmInfo.h"
115f613dfdSUlrich Weigand #include "MCTargetDesc/SystemZMCTargetDesc.h"
121a5ab3e9SJonas Paulsson #include "SystemZTargetStreamer.h"
131e6f98b8SRichard Trieu #include "TargetInfo/SystemZTargetInfo.h"
14690d8ea1SCraig Topper #include "llvm/ADT/STLExtras.h"
156bda14b3SChandler Carruth #include "llvm/ADT/SmallVector.h"
1606869c04SEugene Zelenko #include "llvm/ADT/StringRef.h"
17bcc1aba6SAnirudh Prasad #include "llvm/MC/MCAsmInfo.h"
181fb5883dSRichard Sandiford #include "llvm/MC/MCContext.h"
195f613dfdSUlrich Weigand #include "llvm/MC/MCExpr.h"
205f613dfdSUlrich Weigand #include "llvm/MC/MCInst.h"
214fbc3f4aSZhan Jun Liau #include "llvm/MC/MCInstBuilder.h"
2206943537Sserge-sans-paille #include "llvm/MC/MCInstrInfo.h"
2306869c04SEugene Zelenko #include "llvm/MC/MCParser/MCAsmLexer.h"
2406869c04SEugene Zelenko #include "llvm/MC/MCParser/MCAsmParser.h"
2506869c04SEugene Zelenko #include "llvm/MC/MCParser/MCAsmParserExtension.h"
265f613dfdSUlrich Weigand #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
27b3e8a6d2SBenjamin Kramer #include "llvm/MC/MCParser/MCTargetAsmParser.h"
285f613dfdSUlrich Weigand #include "llvm/MC/MCStreamer.h"
295f613dfdSUlrich Weigand #include "llvm/MC/MCSubtargetInfo.h"
3089b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
3106869c04SEugene Zelenko #include "llvm/Support/Casting.h"
3206869c04SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
3306869c04SEugene Zelenko #include "llvm/Support/SMLoc.h"
3406869c04SEugene Zelenko #include <algorithm>
3506869c04SEugene Zelenko #include <cassert>
3606869c04SEugene Zelenko #include <cstddef>
3706869c04SEugene Zelenko #include <cstdint>
3806869c04SEugene Zelenko #include <iterator>
3906869c04SEugene Zelenko #include <memory>
4006869c04SEugene Zelenko #include <string>
415f613dfdSUlrich Weigand 
425f613dfdSUlrich Weigand using namespace llvm;
435f613dfdSUlrich Weigand 
441c3ef9efSJonas Paulsson // Return true if Expr is in the range [MinValue, MaxValue]. If AllowSymbol
451c3ef9efSJonas Paulsson // is true any MCExpr is accepted (address displacement).
inRange(const MCExpr * Expr,int64_t MinValue,int64_t MaxValue,bool AllowSymbol=false)461c3ef9efSJonas Paulsson static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue,
471c3ef9efSJonas Paulsson                     bool AllowSymbol = false) {
4821f5d68aSRichard Sandiford   if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
495f613dfdSUlrich Weigand     int64_t Value = CE->getValue();
505f613dfdSUlrich Weigand     return Value >= MinValue && Value <= MaxValue;
515f613dfdSUlrich Weigand   }
521c3ef9efSJonas Paulsson   return AllowSymbol;
535f613dfdSUlrich Weigand }
545f613dfdSUlrich Weigand 
555f613dfdSUlrich Weigand namespace {
5606869c04SEugene Zelenko 
575f613dfdSUlrich Weigand enum RegisterKind {
585f613dfdSUlrich Weigand   GR32Reg,
59f9496060SRichard Sandiford   GRH32Reg,
605f613dfdSUlrich Weigand   GR64Reg,
615f613dfdSUlrich Weigand   GR128Reg,
625f613dfdSUlrich Weigand   FP32Reg,
635f613dfdSUlrich Weigand   FP64Reg,
64a8b04e1cSUlrich Weigand   FP128Reg,
65a8b04e1cSUlrich Weigand   VR32Reg,
66a8b04e1cSUlrich Weigand   VR64Reg,
67fffc7110SUlrich Weigand   VR128Reg,
68fffc7110SUlrich Weigand   AR32Reg,
6903ab2e2bSUlrich Weigand   CR64Reg,
705f613dfdSUlrich Weigand };
715f613dfdSUlrich Weigand 
721d959008SRichard Sandiford enum MemoryKind {
731d959008SRichard Sandiford   BDMem,
741d959008SRichard Sandiford   BDXMem,
75a8b04e1cSUlrich Weigand   BDLMem,
76ec5d779eSUlrich Weigand   BDRMem,
77a8b04e1cSUlrich Weigand   BDVMem
781d959008SRichard Sandiford };
791d959008SRichard Sandiford 
801d959008SRichard Sandiford class SystemZOperand : public MCParsedAsmOperand {
815f613dfdSUlrich Weigand private:
825f613dfdSUlrich Weigand   enum OperandKind {
83dc5ed713SRichard Sandiford     KindInvalid,
845f613dfdSUlrich Weigand     KindToken,
855f613dfdSUlrich Weigand     KindReg,
865f613dfdSUlrich Weigand     KindImm,
877bdd7c23SUlrich Weigand     KindImmTLS,
885f613dfdSUlrich Weigand     KindMem
895f613dfdSUlrich Weigand   };
905f613dfdSUlrich Weigand 
915f613dfdSUlrich Weigand   OperandKind Kind;
925f613dfdSUlrich Weigand   SMLoc StartLoc, EndLoc;
935f613dfdSUlrich Weigand 
945f613dfdSUlrich Weigand   // A string of length Length, starting at Data.
955f613dfdSUlrich Weigand   struct TokenOp {
965f613dfdSUlrich Weigand     const char *Data;
975f613dfdSUlrich Weigand     unsigned Length;
985f613dfdSUlrich Weigand   };
995f613dfdSUlrich Weigand 
100675f8699SRichard Sandiford   // LLVM register Num, which has kind Kind.  In some ways it might be
101675f8699SRichard Sandiford   // easier for this class to have a register bank (general, floating-point
102675f8699SRichard Sandiford   // or access) and a raw register number (0-15).  This would postpone the
103675f8699SRichard Sandiford   // interpretation of the operand to the add*() methods and avoid the need
104675f8699SRichard Sandiford   // for context-dependent parsing.  However, we do things the current way
105675f8699SRichard Sandiford   // because of the virtual getReg() method, which needs to distinguish
106675f8699SRichard Sandiford   // between (say) %r0 used as a single register and %r0 used as a pair.
107675f8699SRichard Sandiford   // Context-dependent parsing can also give us slightly better error
108675f8699SRichard Sandiford   // messages when invalid pairs like %r1 are used.
1095f613dfdSUlrich Weigand   struct RegOp {
1105f613dfdSUlrich Weigand     RegisterKind Kind;
1115f613dfdSUlrich Weigand     unsigned Num;
1125f613dfdSUlrich Weigand   };
1135f613dfdSUlrich Weigand 
1145f613dfdSUlrich Weigand   // Base + Disp + Index, where Base and Index are LLVM registers or 0.
1151f698b00SUlrich Weigand   // MemKind says what type of memory this is and RegKind says what type
116c726c920SUlrich Weigand   // the base register has (GR32Reg or GR64Reg).  Length is the operand
1171f698b00SUlrich Weigand   // length for D(L,B)-style operands, otherwise it is null.
1185f613dfdSUlrich Weigand   struct MemOp {
119a8b04e1cSUlrich Weigand     unsigned Base : 12;
120a8b04e1cSUlrich Weigand     unsigned Index : 12;
121a8b04e1cSUlrich Weigand     unsigned MemKind : 4;
122a8b04e1cSUlrich Weigand     unsigned RegKind : 4;
1235f613dfdSUlrich Weigand     const MCExpr *Disp;
124ec5d779eSUlrich Weigand     union {
125ec5d779eSUlrich Weigand       const MCExpr *Imm;
126ec5d779eSUlrich Weigand       unsigned Reg;
127ec5d779eSUlrich Weigand     } Length;
1285f613dfdSUlrich Weigand   };
1295f613dfdSUlrich Weigand 
1307bdd7c23SUlrich Weigand   // Imm is an immediate operand, and Sym is an optional TLS symbol
1317bdd7c23SUlrich Weigand   // for use with a __tls_get_offset marker relocation.
1327bdd7c23SUlrich Weigand   struct ImmTLSOp {
1337bdd7c23SUlrich Weigand     const MCExpr *Imm;
1347bdd7c23SUlrich Weigand     const MCExpr *Sym;
1357bdd7c23SUlrich Weigand   };
1367bdd7c23SUlrich Weigand 
1375f613dfdSUlrich Weigand   union {
1385f613dfdSUlrich Weigand     TokenOp Token;
1395f613dfdSUlrich Weigand     RegOp Reg;
1405f613dfdSUlrich Weigand     const MCExpr *Imm;
1417bdd7c23SUlrich Weigand     ImmTLSOp ImmTLS;
1425f613dfdSUlrich Weigand     MemOp Mem;
1435f613dfdSUlrich Weigand   };
1445f613dfdSUlrich Weigand 
addExpr(MCInst & Inst,const MCExpr * Expr) const1455f613dfdSUlrich Weigand   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1465f613dfdSUlrich Weigand     // Add as immediates when possible.  Null MCExpr = 0.
147062a2baeSCraig Topper     if (!Expr)
148e9119e41SJim Grosbach       Inst.addOperand(MCOperand::createImm(0));
14921f5d68aSRichard Sandiford     else if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
150e9119e41SJim Grosbach       Inst.addOperand(MCOperand::createImm(CE->getValue()));
1515f613dfdSUlrich Weigand     else
152e9119e41SJim Grosbach       Inst.addOperand(MCOperand::createExpr(Expr));
1535f613dfdSUlrich Weigand   }
1545f613dfdSUlrich Weigand 
1555f613dfdSUlrich Weigand public:
SystemZOperand(OperandKind kind,SMLoc startLoc,SMLoc endLoc)156960ea3f0SDavid Blaikie   SystemZOperand(OperandKind kind, SMLoc startLoc, SMLoc endLoc)
157960ea3f0SDavid Blaikie       : Kind(kind), StartLoc(startLoc), EndLoc(endLoc) {}
158960ea3f0SDavid Blaikie 
1595f613dfdSUlrich Weigand   // Create particular kinds of operand.
createInvalid(SMLoc StartLoc,SMLoc EndLoc)160960ea3f0SDavid Blaikie   static std::unique_ptr<SystemZOperand> createInvalid(SMLoc StartLoc,
161960ea3f0SDavid Blaikie                                                        SMLoc EndLoc) {
1620eaee545SJonas Devlieghere     return std::make_unique<SystemZOperand>(KindInvalid, StartLoc, EndLoc);
163dc5ed713SRichard Sandiford   }
16406869c04SEugene Zelenko 
createToken(StringRef Str,SMLoc Loc)165960ea3f0SDavid Blaikie   static std::unique_ptr<SystemZOperand> createToken(StringRef Str, SMLoc Loc) {
1660eaee545SJonas Devlieghere     auto Op = std::make_unique<SystemZOperand>(KindToken, Loc, Loc);
1675f613dfdSUlrich Weigand     Op->Token.Data = Str.data();
1685f613dfdSUlrich Weigand     Op->Token.Length = Str.size();
1695f613dfdSUlrich Weigand     return Op;
1705f613dfdSUlrich Weigand   }
17106869c04SEugene Zelenko 
172960ea3f0SDavid Blaikie   static std::unique_ptr<SystemZOperand>
createReg(RegisterKind Kind,unsigned Num,SMLoc StartLoc,SMLoc EndLoc)173960ea3f0SDavid Blaikie   createReg(RegisterKind Kind, unsigned Num, SMLoc StartLoc, SMLoc EndLoc) {
1740eaee545SJonas Devlieghere     auto Op = std::make_unique<SystemZOperand>(KindReg, StartLoc, EndLoc);
1755f613dfdSUlrich Weigand     Op->Reg.Kind = Kind;
1765f613dfdSUlrich Weigand     Op->Reg.Num = Num;
1775f613dfdSUlrich Weigand     return Op;
1785f613dfdSUlrich Weigand   }
17906869c04SEugene Zelenko 
180960ea3f0SDavid Blaikie   static std::unique_ptr<SystemZOperand>
createImm(const MCExpr * Expr,SMLoc StartLoc,SMLoc EndLoc)181960ea3f0SDavid Blaikie   createImm(const MCExpr *Expr, SMLoc StartLoc, SMLoc EndLoc) {
1820eaee545SJonas Devlieghere     auto Op = std::make_unique<SystemZOperand>(KindImm, StartLoc, EndLoc);
1835f613dfdSUlrich Weigand     Op->Imm = Expr;
1845f613dfdSUlrich Weigand     return Op;
1855f613dfdSUlrich Weigand   }
18606869c04SEugene Zelenko 
187960ea3f0SDavid Blaikie   static std::unique_ptr<SystemZOperand>
createMem(MemoryKind MemKind,RegisterKind RegKind,unsigned Base,const MCExpr * Disp,unsigned Index,const MCExpr * LengthImm,unsigned LengthReg,SMLoc StartLoc,SMLoc EndLoc)1881f698b00SUlrich Weigand   createMem(MemoryKind MemKind, RegisterKind RegKind, unsigned Base,
189ec5d779eSUlrich Weigand             const MCExpr *Disp, unsigned Index, const MCExpr *LengthImm,
190ec5d779eSUlrich Weigand             unsigned LengthReg, SMLoc StartLoc, SMLoc EndLoc) {
1910eaee545SJonas Devlieghere     auto Op = std::make_unique<SystemZOperand>(KindMem, StartLoc, EndLoc);
1921f698b00SUlrich Weigand     Op->Mem.MemKind = MemKind;
1935f613dfdSUlrich Weigand     Op->Mem.RegKind = RegKind;
1945f613dfdSUlrich Weigand     Op->Mem.Base = Base;
1955f613dfdSUlrich Weigand     Op->Mem.Index = Index;
1965f613dfdSUlrich Weigand     Op->Mem.Disp = Disp;
197ec5d779eSUlrich Weigand     if (MemKind == BDLMem)
198ec5d779eSUlrich Weigand       Op->Mem.Length.Imm = LengthImm;
199ec5d779eSUlrich Weigand     if (MemKind == BDRMem)
200ec5d779eSUlrich Weigand       Op->Mem.Length.Reg = LengthReg;
2015f613dfdSUlrich Weigand     return Op;
2025f613dfdSUlrich Weigand   }
20306869c04SEugene Zelenko 
2047bdd7c23SUlrich Weigand   static std::unique_ptr<SystemZOperand>
createImmTLS(const MCExpr * Imm,const MCExpr * Sym,SMLoc StartLoc,SMLoc EndLoc)2057bdd7c23SUlrich Weigand   createImmTLS(const MCExpr *Imm, const MCExpr *Sym,
2067bdd7c23SUlrich Weigand                SMLoc StartLoc, SMLoc EndLoc) {
2070eaee545SJonas Devlieghere     auto Op = std::make_unique<SystemZOperand>(KindImmTLS, StartLoc, EndLoc);
2087bdd7c23SUlrich Weigand     Op->ImmTLS.Imm = Imm;
2097bdd7c23SUlrich Weigand     Op->ImmTLS.Sym = Sym;
2107bdd7c23SUlrich Weigand     return Op;
2117bdd7c23SUlrich Weigand   }
2125f613dfdSUlrich Weigand 
2135f613dfdSUlrich Weigand   // Token operands
isToken() const214b4d67b59SRichard Sandiford   bool isToken() const override {
2155f613dfdSUlrich Weigand     return Kind == KindToken;
2165f613dfdSUlrich Weigand   }
getToken() const2175f613dfdSUlrich Weigand   StringRef getToken() const {
2185f613dfdSUlrich Weigand     assert(Kind == KindToken && "Not a token");
2195f613dfdSUlrich Weigand     return StringRef(Token.Data, Token.Length);
2205f613dfdSUlrich Weigand   }
2215f613dfdSUlrich Weigand 
2225f613dfdSUlrich Weigand   // Register operands.
isReg() const223b4d67b59SRichard Sandiford   bool isReg() const override {
2245f613dfdSUlrich Weigand     return Kind == KindReg;
2255f613dfdSUlrich Weigand   }
isReg(RegisterKind RegKind) const2265f613dfdSUlrich Weigand   bool isReg(RegisterKind RegKind) const {
2275f613dfdSUlrich Weigand     return Kind == KindReg && Reg.Kind == RegKind;
2285f613dfdSUlrich Weigand   }
getReg() const229b4d67b59SRichard Sandiford   unsigned getReg() const override {
2305f613dfdSUlrich Weigand     assert(Kind == KindReg && "Not a register");
2315f613dfdSUlrich Weigand     return Reg.Num;
2325f613dfdSUlrich Weigand   }
2335f613dfdSUlrich Weigand 
2345f613dfdSUlrich Weigand   // Immediate operands.
isImm() const235b4d67b59SRichard Sandiford   bool isImm() const override {
2365f613dfdSUlrich Weigand     return Kind == KindImm;
2375f613dfdSUlrich Weigand   }
isImm(int64_t MinValue,int64_t MaxValue) const2385f613dfdSUlrich Weigand   bool isImm(int64_t MinValue, int64_t MaxValue) const {
2395f613dfdSUlrich Weigand     return Kind == KindImm && inRange(Imm, MinValue, MaxValue);
2405f613dfdSUlrich Weigand   }
getImm() const2415f613dfdSUlrich Weigand   const MCExpr *getImm() const {
2425f613dfdSUlrich Weigand     assert(Kind == KindImm && "Not an immediate");
2435f613dfdSUlrich Weigand     return Imm;
2445f613dfdSUlrich Weigand   }
2455f613dfdSUlrich Weigand 
2467bdd7c23SUlrich Weigand   // Immediate operands with optional TLS symbol.
isImmTLS() const2477bdd7c23SUlrich Weigand   bool isImmTLS() const {
2487bdd7c23SUlrich Weigand     return Kind == KindImmTLS;
2497bdd7c23SUlrich Weigand   }
2507bdd7c23SUlrich Weigand 
getImmTLS() const251dda46307SJonas Paulsson   const ImmTLSOp getImmTLS() const {
252dda46307SJonas Paulsson     assert(Kind == KindImmTLS && "Not a TLS immediate");
253dda46307SJonas Paulsson     return ImmTLS;
254dda46307SJonas Paulsson   }
255dda46307SJonas Paulsson 
2565f613dfdSUlrich Weigand   // Memory operands.
isMem() const257b4d67b59SRichard Sandiford   bool isMem() const override {
2585f613dfdSUlrich Weigand     return Kind == KindMem;
2595f613dfdSUlrich Weigand   }
isMem(MemoryKind MemKind) const2601f698b00SUlrich Weigand   bool isMem(MemoryKind MemKind) const {
2615f613dfdSUlrich Weigand     return (Kind == KindMem &&
2621f698b00SUlrich Weigand             (Mem.MemKind == MemKind ||
2631f698b00SUlrich Weigand              // A BDMem can be treated as a BDXMem in which the index
2641f698b00SUlrich Weigand              // register field is 0.
2651f698b00SUlrich Weigand              (Mem.MemKind == BDMem && MemKind == BDXMem)));
2665f613dfdSUlrich Weigand   }
isMem(MemoryKind MemKind,RegisterKind RegKind) const2671f698b00SUlrich Weigand   bool isMem(MemoryKind MemKind, RegisterKind RegKind) const {
2681f698b00SUlrich Weigand     return isMem(MemKind) && Mem.RegKind == RegKind;
2695f613dfdSUlrich Weigand   }
isMemDisp12(MemoryKind MemKind,RegisterKind RegKind) const2701f698b00SUlrich Weigand   bool isMemDisp12(MemoryKind MemKind, RegisterKind RegKind) const {
2711c3ef9efSJonas Paulsson     return isMem(MemKind, RegKind) && inRange(Mem.Disp, 0, 0xfff, true);
2721f698b00SUlrich Weigand   }
isMemDisp20(MemoryKind MemKind,RegisterKind RegKind) const2731f698b00SUlrich Weigand   bool isMemDisp20(MemoryKind MemKind, RegisterKind RegKind) const {
2741c3ef9efSJonas Paulsson     return isMem(MemKind, RegKind) && inRange(Mem.Disp, -524288, 524287, true);
2751d959008SRichard Sandiford   }
isMemDisp12Len4(RegisterKind RegKind) const276c7eb5a95SUlrich Weigand   bool isMemDisp12Len4(RegisterKind RegKind) const {
277c7eb5a95SUlrich Weigand     return isMemDisp12(BDLMem, RegKind) && inRange(Mem.Length.Imm, 1, 0x10);
278c7eb5a95SUlrich Weigand   }
isMemDisp12Len8(RegisterKind RegKind) const2791d959008SRichard Sandiford   bool isMemDisp12Len8(RegisterKind RegKind) const {
280ec5d779eSUlrich Weigand     return isMemDisp12(BDLMem, RegKind) && inRange(Mem.Length.Imm, 1, 0x100);
281a8b04e1cSUlrich Weigand   }
2825f613dfdSUlrich Weigand 
getMem() const283dda46307SJonas Paulsson   const MemOp& getMem() const {
284dda46307SJonas Paulsson     assert(Kind == KindMem && "Not a Mem operand");
285dda46307SJonas Paulsson     return Mem;
286dda46307SJonas Paulsson   }
287dda46307SJonas Paulsson 
2885f613dfdSUlrich Weigand   // Override MCParsedAsmOperand.
getStartLoc() const289b4d67b59SRichard Sandiford   SMLoc getStartLoc() const override { return StartLoc; }
getEndLoc() const2900da86301SPeter Collingbourne   SMLoc getEndLoc() const override { return EndLoc; }
291b4d67b59SRichard Sandiford   void print(raw_ostream &OS) const override;
2925f613dfdSUlrich Weigand 
293d667417eSJonas Paulsson   /// getLocRange - Get the range between the first and last token of this
294d667417eSJonas Paulsson   /// operand.
getLocRange() const295d667417eSJonas Paulsson   SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
296d667417eSJonas Paulsson 
2975f613dfdSUlrich Weigand   // Used by the TableGen code to add particular types of operand
2985f613dfdSUlrich Weigand   // to an instruction.
addRegOperands(MCInst & Inst,unsigned N) const2995f613dfdSUlrich Weigand   void addRegOperands(MCInst &Inst, unsigned N) const {
3005f613dfdSUlrich Weigand     assert(N == 1 && "Invalid number of operands");
301e9119e41SJim Grosbach     Inst.addOperand(MCOperand::createReg(getReg()));
3025f613dfdSUlrich Weigand   }
addImmOperands(MCInst & Inst,unsigned N) const3035f613dfdSUlrich Weigand   void addImmOperands(MCInst &Inst, unsigned N) const {
3045f613dfdSUlrich Weigand     assert(N == 1 && "Invalid number of operands");
3055f613dfdSUlrich Weigand     addExpr(Inst, getImm());
3065f613dfdSUlrich Weigand   }
addBDAddrOperands(MCInst & Inst,unsigned N) const3075f613dfdSUlrich Weigand   void addBDAddrOperands(MCInst &Inst, unsigned N) const {
3085f613dfdSUlrich Weigand     assert(N == 2 && "Invalid number of operands");
3091f698b00SUlrich Weigand     assert(isMem(BDMem) && "Invalid operand type");
310e9119e41SJim Grosbach     Inst.addOperand(MCOperand::createReg(Mem.Base));
3115f613dfdSUlrich Weigand     addExpr(Inst, Mem.Disp);
3125f613dfdSUlrich Weigand   }
addBDXAddrOperands(MCInst & Inst,unsigned N) const3135f613dfdSUlrich Weigand   void addBDXAddrOperands(MCInst &Inst, unsigned N) const {
3145f613dfdSUlrich Weigand     assert(N == 3 && "Invalid number of operands");
3151f698b00SUlrich Weigand     assert(isMem(BDXMem) && "Invalid operand type");
316e9119e41SJim Grosbach     Inst.addOperand(MCOperand::createReg(Mem.Base));
3175f613dfdSUlrich Weigand     addExpr(Inst, Mem.Disp);
318e9119e41SJim Grosbach     Inst.addOperand(MCOperand::createReg(Mem.Index));
3195f613dfdSUlrich Weigand   }
addBDLAddrOperands(MCInst & Inst,unsigned N) const3201d959008SRichard Sandiford   void addBDLAddrOperands(MCInst &Inst, unsigned N) const {
3211d959008SRichard Sandiford     assert(N == 3 && "Invalid number of operands");
3221f698b00SUlrich Weigand     assert(isMem(BDLMem) && "Invalid operand type");
323e9119e41SJim Grosbach     Inst.addOperand(MCOperand::createReg(Mem.Base));
3241d959008SRichard Sandiford     addExpr(Inst, Mem.Disp);
325ec5d779eSUlrich Weigand     addExpr(Inst, Mem.Length.Imm);
326ec5d779eSUlrich Weigand   }
addBDRAddrOperands(MCInst & Inst,unsigned N) const327ec5d779eSUlrich Weigand   void addBDRAddrOperands(MCInst &Inst, unsigned N) const {
328ec5d779eSUlrich Weigand     assert(N == 3 && "Invalid number of operands");
329ec5d779eSUlrich Weigand     assert(isMem(BDRMem) && "Invalid operand type");
330ec5d779eSUlrich Weigand     Inst.addOperand(MCOperand::createReg(Mem.Base));
331ec5d779eSUlrich Weigand     addExpr(Inst, Mem.Disp);
332ec5d779eSUlrich Weigand     Inst.addOperand(MCOperand::createReg(Mem.Length.Reg));
333ec5d779eSUlrich Weigand   }
addBDVAddrOperands(MCInst & Inst,unsigned N) const334ec5d779eSUlrich Weigand   void addBDVAddrOperands(MCInst &Inst, unsigned N) const {
335ec5d779eSUlrich Weigand     assert(N == 3 && "Invalid number of operands");
336ec5d779eSUlrich Weigand     assert(isMem(BDVMem) && "Invalid operand type");
337ec5d779eSUlrich Weigand     Inst.addOperand(MCOperand::createReg(Mem.Base));
338ec5d779eSUlrich Weigand     addExpr(Inst, Mem.Disp);
339ec5d779eSUlrich Weigand     Inst.addOperand(MCOperand::createReg(Mem.Index));
3401d959008SRichard Sandiford   }
addImmTLSOperands(MCInst & Inst,unsigned N) const3417bdd7c23SUlrich Weigand   void addImmTLSOperands(MCInst &Inst, unsigned N) const {
3427bdd7c23SUlrich Weigand     assert(N == 2 && "Invalid number of operands");
3437bdd7c23SUlrich Weigand     assert(Kind == KindImmTLS && "Invalid operand type");
3447bdd7c23SUlrich Weigand     addExpr(Inst, ImmTLS.Imm);
3457bdd7c23SUlrich Weigand     if (ImmTLS.Sym)
3467bdd7c23SUlrich Weigand       addExpr(Inst, ImmTLS.Sym);
3477bdd7c23SUlrich Weigand   }
3485f613dfdSUlrich Weigand 
3495f613dfdSUlrich Weigand   // Used by the TableGen code to check for particular operand types.
isGR32() const3505f613dfdSUlrich Weigand   bool isGR32() const { return isReg(GR32Reg); }
isGRH32() const351f9496060SRichard Sandiford   bool isGRH32() const { return isReg(GRH32Reg); }
isGRX32() const3520755c93bSRichard Sandiford   bool isGRX32() const { return false; }
isGR64() const3535f613dfdSUlrich Weigand   bool isGR64() const { return isReg(GR64Reg); }
isGR128() const3545f613dfdSUlrich Weigand   bool isGR128() const { return isReg(GR128Reg); }
isADDR32() const355c726c920SUlrich Weigand   bool isADDR32() const { return isReg(GR32Reg); }
isADDR64() const356c726c920SUlrich Weigand   bool isADDR64() const { return isReg(GR64Reg); }
isADDR128() const3575f613dfdSUlrich Weigand   bool isADDR128() const { return false; }
isFP32() const3585f613dfdSUlrich Weigand   bool isFP32() const { return isReg(FP32Reg); }
isFP64() const3595f613dfdSUlrich Weigand   bool isFP64() const { return isReg(FP64Reg); }
isFP128() const3605f613dfdSUlrich Weigand   bool isFP128() const { return isReg(FP128Reg); }
isVR32() const361a8b04e1cSUlrich Weigand   bool isVR32() const { return isReg(VR32Reg); }
isVR64() const362a8b04e1cSUlrich Weigand   bool isVR64() const { return isReg(VR64Reg); }
isVF128() const363a8b04e1cSUlrich Weigand   bool isVF128() const { return false; }
isVR128() const364a8b04e1cSUlrich Weigand   bool isVR128() const { return isReg(VR128Reg); }
isAR32() const365fffc7110SUlrich Weigand   bool isAR32() const { return isReg(AR32Reg); }
isCR64() const36603ab2e2bSUlrich Weigand   bool isCR64() const { return isReg(CR64Reg); }
isAnyReg() const3674fbc3f4aSZhan Jun Liau   bool isAnyReg() const { return (isReg() || isImm(0, 15)); }
isBDAddr32Disp12() const368c726c920SUlrich Weigand   bool isBDAddr32Disp12() const { return isMemDisp12(BDMem, GR32Reg); }
isBDAddr32Disp20() const369c726c920SUlrich Weigand   bool isBDAddr32Disp20() const { return isMemDisp20(BDMem, GR32Reg); }
isBDAddr64Disp12() const370c726c920SUlrich Weigand   bool isBDAddr64Disp12() const { return isMemDisp12(BDMem, GR64Reg); }
isBDAddr64Disp20() const371c726c920SUlrich Weigand   bool isBDAddr64Disp20() const { return isMemDisp20(BDMem, GR64Reg); }
isBDXAddr64Disp12() const372c726c920SUlrich Weigand   bool isBDXAddr64Disp12() const { return isMemDisp12(BDXMem, GR64Reg); }
isBDXAddr64Disp20() const373c726c920SUlrich Weigand   bool isBDXAddr64Disp20() const { return isMemDisp20(BDXMem, GR64Reg); }
isBDLAddr64Disp12Len4() const374c726c920SUlrich Weigand   bool isBDLAddr64Disp12Len4() const { return isMemDisp12Len4(GR64Reg); }
isBDLAddr64Disp12Len8() const375c726c920SUlrich Weigand   bool isBDLAddr64Disp12Len8() const { return isMemDisp12Len8(GR64Reg); }
isBDRAddr64Disp12() const376c726c920SUlrich Weigand   bool isBDRAddr64Disp12() const { return isMemDisp12(BDRMem, GR64Reg); }
isBDVAddr64Disp12() const377c726c920SUlrich Weigand   bool isBDVAddr64Disp12() const { return isMemDisp12(BDVMem, GR64Reg); }
isU1Imm() const378a8b04e1cSUlrich Weigand   bool isU1Imm() const { return isImm(0, 1); }
isU2Imm() const379a8b04e1cSUlrich Weigand   bool isU2Imm() const { return isImm(0, 3); }
isU3Imm() const380a8b04e1cSUlrich Weigand   bool isU3Imm() const { return isImm(0, 7); }
isU4Imm() const3815f613dfdSUlrich Weigand   bool isU4Imm() const { return isImm(0, 15); }
isU6Imm() const3825f613dfdSUlrich Weigand   bool isU6Imm() const { return isImm(0, 63); }
isU8Imm() const3835f613dfdSUlrich Weigand   bool isU8Imm() const { return isImm(0, 255); }
isS8Imm() const3845f613dfdSUlrich Weigand   bool isS8Imm() const { return isImm(-128, 127); }
isU12Imm() const385a8b04e1cSUlrich Weigand   bool isU12Imm() const { return isImm(0, 4095); }
isU16Imm() const3865f613dfdSUlrich Weigand   bool isU16Imm() const { return isImm(0, 65535); }
isS16Imm() const3875f613dfdSUlrich Weigand   bool isS16Imm() const { return isImm(-32768, 32767); }
isU32Imm() const3885f613dfdSUlrich Weigand   bool isU32Imm() const { return isImm(0, (1LL << 32) - 1); }
isS32Imm() const3895f613dfdSUlrich Weigand   bool isS32Imm() const { return isImm(-(1LL << 31), (1LL << 31) - 1); }
isU48Imm() const3904fbc3f4aSZhan Jun Liau   bool isU48Imm() const { return isImm(0, (1LL << 48) - 1); }
3915f613dfdSUlrich Weigand };
3925f613dfdSUlrich Weigand 
3935f613dfdSUlrich Weigand class SystemZAsmParser : public MCTargetAsmParser {
3945f613dfdSUlrich Weigand #define GET_ASSEMBLER_HEADER
3955f613dfdSUlrich Weigand #include "SystemZGenAsmMatcher.inc"
3965f613dfdSUlrich Weigand 
3975f613dfdSUlrich Weigand private:
3985f613dfdSUlrich Weigand   MCAsmParser &Parser;
399675f8699SRichard Sandiford   enum RegisterGroup {
400675f8699SRichard Sandiford     RegGR,
401675f8699SRichard Sandiford     RegFP,
402a8b04e1cSUlrich Weigand     RegV,
40303ab2e2bSUlrich Weigand     RegAR,
40403ab2e2bSUlrich Weigand     RegCR
405675f8699SRichard Sandiford   };
4065f613dfdSUlrich Weigand   struct Register {
407675f8699SRichard Sandiford     RegisterGroup Group;
408675f8699SRichard Sandiford     unsigned Num;
4095f613dfdSUlrich Weigand     SMLoc StartLoc, EndLoc;
4105f613dfdSUlrich Weigand   };
4115f613dfdSUlrich Weigand 
getTargetStreamer()4121a5ab3e9SJonas Paulsson   SystemZTargetStreamer &getTargetStreamer() {
4131a5ab3e9SJonas Paulsson     assert(getParser().getStreamer().getTargetStreamer() &&
4141a5ab3e9SJonas Paulsson            "do not have a target streamer");
4151a5ab3e9SJonas Paulsson     MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
4161a5ab3e9SJonas Paulsson     return static_cast<SystemZTargetStreamer &>(TS);
4171a5ab3e9SJonas Paulsson   }
4181a5ab3e9SJonas Paulsson 
4198d5bf042SEric Astor   bool parseRegister(Register &Reg, bool RestoreOnFailure = false);
4205f613dfdSUlrich Weigand 
421cca8578eSUlrich Weigand   bool parseIntegerRegister(Register &Reg, RegisterGroup Group);
422cca8578eSUlrich Weigand 
423960ea3f0SDavid Blaikie   OperandMatchResultTy parseRegister(OperandVector &Operands,
424960ea3f0SDavid Blaikie                                      RegisterKind Kind);
4255f613dfdSUlrich Weigand 
4264fbc3f4aSZhan Jun Liau   OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
4274fbc3f4aSZhan Jun Liau 
428cca8578eSUlrich Weigand   bool parseAddress(bool &HaveReg1, Register &Reg1, bool &HaveReg2,
429cca8578eSUlrich Weigand                     Register &Reg2, const MCExpr *&Disp, const MCExpr *&Length,
430cca8578eSUlrich Weigand                     bool HasLength = false, bool HasVectorIndex = false);
431ec5d779eSUlrich Weigand   bool parseAddressRegister(Register &Reg);
432dc5ed713SRichard Sandiford 
4334fbc3f4aSZhan Jun Liau   bool ParseDirectiveInsn(SMLoc L);
4341a5ab3e9SJonas Paulsson   bool ParseDirectiveMachine(SMLoc L);
4354fbc3f4aSZhan Jun Liau 
436960ea3f0SDavid Blaikie   OperandMatchResultTy parseAddress(OperandVector &Operands,
4376bfde063SUlrich Weigand                                     MemoryKind MemKind,
4381f698b00SUlrich Weigand                                     RegisterKind RegKind);
4395f613dfdSUlrich Weigand 
4407bdd7c23SUlrich Weigand   OperandMatchResultTy parsePCRel(OperandVector &Operands, int64_t MinVal,
4417bdd7c23SUlrich Weigand                                   int64_t MaxVal, bool AllowTLS);
4427bdd7c23SUlrich Weigand 
443960ea3f0SDavid Blaikie   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
4445f613dfdSUlrich Weigand 
445bcc1aba6SAnirudh Prasad   // Both the hlasm and att variants still rely on the basic gnu asm
446bcc1aba6SAnirudh Prasad   // format with respect to inputs, clobbers, outputs etc.
447bcc1aba6SAnirudh Prasad   //
448bcc1aba6SAnirudh Prasad   // However, calling the overriden getAssemblerDialect() method in
449bcc1aba6SAnirudh Prasad   // AsmParser is problematic. It either returns the AssemblerDialect field
450bcc1aba6SAnirudh Prasad   // in the MCAsmInfo instance if the AssemblerDialect field in AsmParser is
451bcc1aba6SAnirudh Prasad   // unset, otherwise it returns the private AssemblerDialect field in
452bcc1aba6SAnirudh Prasad   // AsmParser.
453bcc1aba6SAnirudh Prasad   //
454bcc1aba6SAnirudh Prasad   // The problematic part is because, we forcibly set the inline asm dialect
455bcc1aba6SAnirudh Prasad   // in the AsmParser instance in AsmPrinterInlineAsm.cpp. Soo any query
456bcc1aba6SAnirudh Prasad   // to the overriden getAssemblerDialect function in AsmParser.cpp, will
457bcc1aba6SAnirudh Prasad   // not return the assembler dialect set in the respective MCAsmInfo instance.
458bcc1aba6SAnirudh Prasad   //
459bcc1aba6SAnirudh Prasad   // For this purpose, we explicitly query the SystemZMCAsmInfo instance
460bcc1aba6SAnirudh Prasad   // here, to get the "correct" assembler dialect, and use it in various
461bcc1aba6SAnirudh Prasad   // functions.
getMAIAssemblerDialect()462bcc1aba6SAnirudh Prasad   unsigned getMAIAssemblerDialect() {
463bcc1aba6SAnirudh Prasad     return Parser.getContext().getAsmInfo()->getAssemblerDialect();
464bcc1aba6SAnirudh Prasad   }
465bcc1aba6SAnirudh Prasad 
4667a46d34aSAnirudh Prasad   // An alphabetic character in HLASM is a letter from 'A' through 'Z',
4677a46d34aSAnirudh Prasad   // or from 'a' through 'z', or '$', '_','#', or '@'.
isHLASMAlpha(char C)4687a46d34aSAnirudh Prasad   inline bool isHLASMAlpha(char C) {
4697a46d34aSAnirudh Prasad     return isAlpha(C) || llvm::is_contained("_@#$", C);
4707a46d34aSAnirudh Prasad   }
4717a46d34aSAnirudh Prasad 
4727a46d34aSAnirudh Prasad   // A digit in HLASM is a number from 0 to 9.
isHLASMAlnum(char C)4737a46d34aSAnirudh Prasad   inline bool isHLASMAlnum(char C) { return isHLASMAlpha(C) || isDigit(C); }
4747a46d34aSAnirudh Prasad 
4757da22dfcSAnirudh Prasad   // Are we parsing using the AD_HLASM dialect?
isParsingHLASM()4767da22dfcSAnirudh Prasad   inline bool isParsingHLASM() { return getMAIAssemblerDialect() == AD_HLASM; }
4777da22dfcSAnirudh Prasad 
4787da22dfcSAnirudh Prasad   // Are we parsing using the AD_ATT dialect?
isParsingATT()4797da22dfcSAnirudh Prasad   inline bool isParsingATT() { return getMAIAssemblerDialect() == AD_ATT; }
4807da22dfcSAnirudh Prasad 
4815f613dfdSUlrich Weigand public:
SystemZAsmParser(const MCSubtargetInfo & sti,MCAsmParser & parser,const MCInstrInfo & MII,const MCTargetOptions & Options)482b11ef089SAkira Hatanaka   SystemZAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
4830a951b77SEvgeniy Stepanov                    const MCInstrInfo &MII,
4840a951b77SEvgeniy Stepanov                    const MCTargetOptions &Options)
4854191b9eaSOliver Stannard     : MCTargetAsmParser(Options, sti, MII), Parser(parser) {
4865f613dfdSUlrich Weigand     MCAsmParserExtension::Initialize(Parser);
4875f613dfdSUlrich Weigand 
4887d4d436cSZhan Jun Liau     // Alias the .word directive to .short.
4897d4d436cSZhan Jun Liau     parser.addAliasForDirective(".word", ".short");
4907d4d436cSZhan Jun Liau 
4915f613dfdSUlrich Weigand     // Initialize the set of available features.
492bd9fc284SAkira Hatanaka     setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
4935f613dfdSUlrich Weigand   }
4945f613dfdSUlrich Weigand 
4955f613dfdSUlrich Weigand   // Override MCTargetAsmParser.
496b4d67b59SRichard Sandiford   bool ParseDirective(AsmToken DirectiveID) override;
497b4d67b59SRichard Sandiford   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
4988d5bf042SEric Astor   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,
4998d5bf042SEric Astor                      bool RestoreOnFailure);
5008d5bf042SEric Astor   OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5018d5bf042SEric Astor                                         SMLoc &EndLoc) override;
502960ea3f0SDavid Blaikie   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
503960ea3f0SDavid Blaikie                         SMLoc NameLoc, OperandVector &Operands) override;
504b4d67b59SRichard Sandiford   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
505960ea3f0SDavid Blaikie                                OperandVector &Operands, MCStreamer &Out,
50626bb14e6STim Northover                                uint64_t &ErrorInfo,
50773156025SCraig Topper                                bool MatchingInlineAsm) override;
5087a46d34aSAnirudh Prasad   bool isLabel(AsmToken &Token) override;
5095f613dfdSUlrich Weigand 
5105f613dfdSUlrich Weigand   // Used by the TableGen code to parse particular operand types.
parseGR32(OperandVector & Operands)511960ea3f0SDavid Blaikie   OperandMatchResultTy parseGR32(OperandVector &Operands) {
5126bfde063SUlrich Weigand     return parseRegister(Operands, GR32Reg);
5135f613dfdSUlrich Weigand   }
parseGRH32(OperandVector & Operands)514960ea3f0SDavid Blaikie   OperandMatchResultTy parseGRH32(OperandVector &Operands) {
5156bfde063SUlrich Weigand     return parseRegister(Operands, GRH32Reg);
516f9496060SRichard Sandiford   }
parseGRX32(OperandVector & Operands)517960ea3f0SDavid Blaikie   OperandMatchResultTy parseGRX32(OperandVector &Operands) {
5180755c93bSRichard Sandiford     llvm_unreachable("GRX32 should only be used for pseudo instructions");
5190755c93bSRichard Sandiford   }
parseGR64(OperandVector & Operands)520960ea3f0SDavid Blaikie   OperandMatchResultTy parseGR64(OperandVector &Operands) {
5216bfde063SUlrich Weigand     return parseRegister(Operands, GR64Reg);
5225f613dfdSUlrich Weigand   }
parseGR128(OperandVector & Operands)523960ea3f0SDavid Blaikie   OperandMatchResultTy parseGR128(OperandVector &Operands) {
5246bfde063SUlrich Weigand     return parseRegister(Operands, GR128Reg);
5255f613dfdSUlrich Weigand   }
parseADDR32(OperandVector & Operands)526960ea3f0SDavid Blaikie   OperandMatchResultTy parseADDR32(OperandVector &Operands) {
527c726c920SUlrich Weigand     // For the AsmParser, we will accept %r0 for ADDR32 as well.
5286bfde063SUlrich Weigand     return parseRegister(Operands, GR32Reg);
5295f613dfdSUlrich Weigand   }
parseADDR64(OperandVector & Operands)530960ea3f0SDavid Blaikie   OperandMatchResultTy parseADDR64(OperandVector &Operands) {
531c726c920SUlrich Weigand     // For the AsmParser, we will accept %r0 for ADDR64 as well.
5326bfde063SUlrich Weigand     return parseRegister(Operands, GR64Reg);
5335f613dfdSUlrich Weigand   }
parseADDR128(OperandVector & Operands)534960ea3f0SDavid Blaikie   OperandMatchResultTy parseADDR128(OperandVector &Operands) {
5355f613dfdSUlrich Weigand     llvm_unreachable("Shouldn't be used as an operand");
5365f613dfdSUlrich Weigand   }
parseFP32(OperandVector & Operands)537960ea3f0SDavid Blaikie   OperandMatchResultTy parseFP32(OperandVector &Operands) {
5386bfde063SUlrich Weigand     return parseRegister(Operands, FP32Reg);
5395f613dfdSUlrich Weigand   }
parseFP64(OperandVector & Operands)540960ea3f0SDavid Blaikie   OperandMatchResultTy parseFP64(OperandVector &Operands) {
5416bfde063SUlrich Weigand     return parseRegister(Operands, FP64Reg);
5425f613dfdSUlrich Weigand   }
parseFP128(OperandVector & Operands)543960ea3f0SDavid Blaikie   OperandMatchResultTy parseFP128(OperandVector &Operands) {
5446bfde063SUlrich Weigand     return parseRegister(Operands, FP128Reg);
5455f613dfdSUlrich Weigand   }
parseVR32(OperandVector & Operands)546a8b04e1cSUlrich Weigand   OperandMatchResultTy parseVR32(OperandVector &Operands) {
5476bfde063SUlrich Weigand     return parseRegister(Operands, VR32Reg);
548a8b04e1cSUlrich Weigand   }
parseVR64(OperandVector & Operands)549a8b04e1cSUlrich Weigand   OperandMatchResultTy parseVR64(OperandVector &Operands) {
5506bfde063SUlrich Weigand     return parseRegister(Operands, VR64Reg);
551a8b04e1cSUlrich Weigand   }
parseVF128(OperandVector & Operands)552a8b04e1cSUlrich Weigand   OperandMatchResultTy parseVF128(OperandVector &Operands) {
553a8b04e1cSUlrich Weigand     llvm_unreachable("Shouldn't be used as an operand");
554a8b04e1cSUlrich Weigand   }
parseVR128(OperandVector & Operands)555a8b04e1cSUlrich Weigand   OperandMatchResultTy parseVR128(OperandVector &Operands) {
5566bfde063SUlrich Weigand     return parseRegister(Operands, VR128Reg);
557a8b04e1cSUlrich Weigand   }
parseAR32(OperandVector & Operands)558fffc7110SUlrich Weigand   OperandMatchResultTy parseAR32(OperandVector &Operands) {
5596bfde063SUlrich Weigand     return parseRegister(Operands, AR32Reg);
560fffc7110SUlrich Weigand   }
parseCR64(OperandVector & Operands)56103ab2e2bSUlrich Weigand   OperandMatchResultTy parseCR64(OperandVector &Operands) {
5626bfde063SUlrich Weigand     return parseRegister(Operands, CR64Reg);
56303ab2e2bSUlrich Weigand   }
parseAnyReg(OperandVector & Operands)5644fbc3f4aSZhan Jun Liau   OperandMatchResultTy parseAnyReg(OperandVector &Operands) {
5654fbc3f4aSZhan Jun Liau     return parseAnyRegister(Operands);
5664fbc3f4aSZhan Jun Liau   }
parseBDAddr32(OperandVector & Operands)567960ea3f0SDavid Blaikie   OperandMatchResultTy parseBDAddr32(OperandVector &Operands) {
5686bfde063SUlrich Weigand     return parseAddress(Operands, BDMem, GR32Reg);
5695f613dfdSUlrich Weigand   }
parseBDAddr64(OperandVector & Operands)570960ea3f0SDavid Blaikie   OperandMatchResultTy parseBDAddr64(OperandVector &Operands) {
5716bfde063SUlrich Weigand     return parseAddress(Operands, BDMem, GR64Reg);
5725f613dfdSUlrich Weigand   }
parseBDXAddr64(OperandVector & Operands)573960ea3f0SDavid Blaikie   OperandMatchResultTy parseBDXAddr64(OperandVector &Operands) {
5746bfde063SUlrich Weigand     return parseAddress(Operands, BDXMem, GR64Reg);
5751d959008SRichard Sandiford   }
parseBDLAddr64(OperandVector & Operands)576960ea3f0SDavid Blaikie   OperandMatchResultTy parseBDLAddr64(OperandVector &Operands) {
5776bfde063SUlrich Weigand     return parseAddress(Operands, BDLMem, GR64Reg);
5785f613dfdSUlrich Weigand   }
parseBDRAddr64(OperandVector & Operands)579ec5d779eSUlrich Weigand   OperandMatchResultTy parseBDRAddr64(OperandVector &Operands) {
5806bfde063SUlrich Weigand     return parseAddress(Operands, BDRMem, GR64Reg);
581ec5d779eSUlrich Weigand   }
parseBDVAddr64(OperandVector & Operands)582a8b04e1cSUlrich Weigand   OperandMatchResultTy parseBDVAddr64(OperandVector &Operands) {
5836bfde063SUlrich Weigand     return parseAddress(Operands, BDVMem, GR64Reg);
584a8b04e1cSUlrich Weigand   }
parsePCRel12(OperandVector & Operands)58584404f30SUlrich Weigand   OperandMatchResultTy parsePCRel12(OperandVector &Operands) {
58684404f30SUlrich Weigand     return parsePCRel(Operands, -(1LL << 12), (1LL << 12) - 1, false);
58784404f30SUlrich Weigand   }
parsePCRel16(OperandVector & Operands)588960ea3f0SDavid Blaikie   OperandMatchResultTy parsePCRel16(OperandVector &Operands) {
5897bdd7c23SUlrich Weigand     return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, false);
5901fb5883dSRichard Sandiford   }
parsePCRel24(OperandVector & Operands)59184404f30SUlrich Weigand   OperandMatchResultTy parsePCRel24(OperandVector &Operands) {
59284404f30SUlrich Weigand     return parsePCRel(Operands, -(1LL << 24), (1LL << 24) - 1, false);
59384404f30SUlrich Weigand   }
parsePCRel32(OperandVector & Operands)594960ea3f0SDavid Blaikie   OperandMatchResultTy parsePCRel32(OperandVector &Operands) {
5957bdd7c23SUlrich Weigand     return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1, false);
5967bdd7c23SUlrich Weigand   }
parsePCRelTLS16(OperandVector & Operands)5977bdd7c23SUlrich Weigand   OperandMatchResultTy parsePCRelTLS16(OperandVector &Operands) {
5987bdd7c23SUlrich Weigand     return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, true);
5997bdd7c23SUlrich Weigand   }
parsePCRelTLS32(OperandVector & Operands)6007bdd7c23SUlrich Weigand   OperandMatchResultTy parsePCRelTLS32(OperandVector &Operands) {
6017bdd7c23SUlrich Weigand     return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1, true);
6021fb5883dSRichard Sandiford   }
6035f613dfdSUlrich Weigand };
60406869c04SEugene Zelenko 
605c231269fSRichard Sandiford } // end anonymous namespace
6065f613dfdSUlrich Weigand 
6075f613dfdSUlrich Weigand #define GET_REGISTER_MATCHER
6085f613dfdSUlrich Weigand #define GET_SUBTARGET_FEATURE_NAME
6095f613dfdSUlrich Weigand #define GET_MATCHER_IMPLEMENTATION
6102a06028cSCraig Topper #define GET_MNEMONIC_SPELL_CHECKER
6115f613dfdSUlrich Weigand #include "SystemZGenAsmMatcher.inc"
6125f613dfdSUlrich Weigand 
6134fbc3f4aSZhan Jun Liau // Used for the .insn directives; contains information needed to parse the
6144fbc3f4aSZhan Jun Liau // operands in the directive.
6154fbc3f4aSZhan Jun Liau struct InsnMatchEntry {
6164fbc3f4aSZhan Jun Liau   StringRef Format;
6174fbc3f4aSZhan Jun Liau   uint64_t Opcode;
6184fbc3f4aSZhan Jun Liau   int32_t NumOperands;
61934b61d6cSJonas Paulsson   MatchClassKind OperandKinds[7];
6204fbc3f4aSZhan Jun Liau };
6214fbc3f4aSZhan Jun Liau 
6224fbc3f4aSZhan Jun Liau // For equal_range comparison.
6234fbc3f4aSZhan Jun Liau struct CompareInsn {
operator ()CompareInsn6244fbc3f4aSZhan Jun Liau   bool operator() (const InsnMatchEntry &LHS, StringRef RHS) {
6254fbc3f4aSZhan Jun Liau     return LHS.Format < RHS;
6264fbc3f4aSZhan Jun Liau   }
operator ()CompareInsn6274fbc3f4aSZhan Jun Liau   bool operator() (StringRef LHS, const InsnMatchEntry &RHS) {
6284fbc3f4aSZhan Jun Liau     return LHS < RHS.Format;
6294fbc3f4aSZhan Jun Liau   }
operator ()CompareInsn63017586582SRoger Ferrer Ibanez   bool operator() (const InsnMatchEntry &LHS, const InsnMatchEntry &RHS) {
63117586582SRoger Ferrer Ibanez     return LHS.Format < RHS.Format;
63217586582SRoger Ferrer Ibanez   }
6334fbc3f4aSZhan Jun Liau };
6344fbc3f4aSZhan Jun Liau 
6354fbc3f4aSZhan Jun Liau // Table initializing information for parsing the .insn directive.
6364fbc3f4aSZhan Jun Liau static struct InsnMatchEntry InsnMatchTable[] = {
6374fbc3f4aSZhan Jun Liau   /* Format, Opcode, NumOperands, OperandKinds */
6384fbc3f4aSZhan Jun Liau   { "e", SystemZ::InsnE, 1,
6394fbc3f4aSZhan Jun Liau     { MCK_U16Imm } },
6404fbc3f4aSZhan Jun Liau   { "ri", SystemZ::InsnRI, 3,
6414fbc3f4aSZhan Jun Liau     { MCK_U32Imm, MCK_AnyReg, MCK_S16Imm } },
6424fbc3f4aSZhan Jun Liau   { "rie", SystemZ::InsnRIE, 4,
6434fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_PCRel16 } },
6444fbc3f4aSZhan Jun Liau   { "ril", SystemZ::InsnRIL, 3,
6454fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_AnyReg, MCK_PCRel32 } },
6464fbc3f4aSZhan Jun Liau   { "rilu", SystemZ::InsnRILU, 3,
6474fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_AnyReg, MCK_U32Imm } },
6484fbc3f4aSZhan Jun Liau   { "ris", SystemZ::InsnRIS, 5,
6494fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_AnyReg, MCK_S8Imm, MCK_U4Imm, MCK_BDAddr64Disp12 } },
6504fbc3f4aSZhan Jun Liau   { "rr", SystemZ::InsnRR, 3,
6514fbc3f4aSZhan Jun Liau     { MCK_U16Imm, MCK_AnyReg, MCK_AnyReg } },
6524fbc3f4aSZhan Jun Liau   { "rre", SystemZ::InsnRRE, 3,
6534fbc3f4aSZhan Jun Liau     { MCK_U32Imm, MCK_AnyReg, MCK_AnyReg } },
6544fbc3f4aSZhan Jun Liau   { "rrf", SystemZ::InsnRRF, 5,
6554fbc3f4aSZhan Jun Liau     { MCK_U32Imm, MCK_AnyReg, MCK_AnyReg, MCK_AnyReg, MCK_U4Imm } },
6564fbc3f4aSZhan Jun Liau   { "rrs", SystemZ::InsnRRS, 5,
6574fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_U4Imm, MCK_BDAddr64Disp12 } },
6584fbc3f4aSZhan Jun Liau   { "rs", SystemZ::InsnRS, 4,
6594fbc3f4aSZhan Jun Liau     { MCK_U32Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDAddr64Disp12 } },
6604fbc3f4aSZhan Jun Liau   { "rse", SystemZ::InsnRSE, 4,
6614fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDAddr64Disp12 } },
6624fbc3f4aSZhan Jun Liau   { "rsi", SystemZ::InsnRSI, 4,
6634fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_PCRel16 } },
6644fbc3f4aSZhan Jun Liau   { "rsy", SystemZ::InsnRSY, 4,
6654fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDAddr64Disp20 } },
6664fbc3f4aSZhan Jun Liau   { "rx", SystemZ::InsnRX, 3,
6674fbc3f4aSZhan Jun Liau     { MCK_U32Imm, MCK_AnyReg, MCK_BDXAddr64Disp12 } },
6684fbc3f4aSZhan Jun Liau   { "rxe", SystemZ::InsnRXE, 3,
6694fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_AnyReg, MCK_BDXAddr64Disp12 } },
6704fbc3f4aSZhan Jun Liau   { "rxf", SystemZ::InsnRXF, 4,
6714fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDXAddr64Disp12 } },
6724fbc3f4aSZhan Jun Liau   { "rxy", SystemZ::InsnRXY, 3,
6734fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_AnyReg, MCK_BDXAddr64Disp20 } },
6744fbc3f4aSZhan Jun Liau   { "s", SystemZ::InsnS, 2,
6754fbc3f4aSZhan Jun Liau     { MCK_U32Imm, MCK_BDAddr64Disp12 } },
6764fbc3f4aSZhan Jun Liau   { "si", SystemZ::InsnSI, 3,
6774fbc3f4aSZhan Jun Liau     { MCK_U32Imm, MCK_BDAddr64Disp12, MCK_S8Imm } },
6784fbc3f4aSZhan Jun Liau   { "sil", SystemZ::InsnSIL, 3,
6794fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_BDAddr64Disp12, MCK_U16Imm } },
6804fbc3f4aSZhan Jun Liau   { "siy", SystemZ::InsnSIY, 3,
6814fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_BDAddr64Disp20, MCK_U8Imm } },
6824fbc3f4aSZhan Jun Liau   { "ss", SystemZ::InsnSS, 4,
6834fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_BDXAddr64Disp12, MCK_BDAddr64Disp12, MCK_AnyReg } },
6844fbc3f4aSZhan Jun Liau   { "sse", SystemZ::InsnSSE, 3,
6854fbc3f4aSZhan Jun Liau     { MCK_U48Imm, MCK_BDAddr64Disp12, MCK_BDAddr64Disp12 } },
6864fbc3f4aSZhan Jun Liau   { "ssf", SystemZ::InsnSSF, 4,
68734b61d6cSJonas Paulsson     { MCK_U48Imm, MCK_BDAddr64Disp12, MCK_BDAddr64Disp12, MCK_AnyReg } },
68834b61d6cSJonas Paulsson   { "vri", SystemZ::InsnVRI, 6,
6895588dbceSJonas Paulsson     { MCK_U48Imm, MCK_VR128, MCK_VR128, MCK_U12Imm, MCK_U4Imm, MCK_U4Imm } },
69034b61d6cSJonas Paulsson   { "vrr", SystemZ::InsnVRR, 7,
6915588dbceSJonas Paulsson     { MCK_U48Imm, MCK_VR128, MCK_VR128, MCK_VR128, MCK_U4Imm, MCK_U4Imm,
69234b61d6cSJonas Paulsson       MCK_U4Imm } },
69334b61d6cSJonas Paulsson   { "vrs", SystemZ::InsnVRS, 5,
6945588dbceSJonas Paulsson     { MCK_U48Imm, MCK_AnyReg, MCK_VR128, MCK_BDAddr64Disp12, MCK_U4Imm } },
69534b61d6cSJonas Paulsson   { "vrv", SystemZ::InsnVRV, 4,
6965588dbceSJonas Paulsson     { MCK_U48Imm, MCK_VR128, MCK_BDVAddr64Disp12, MCK_U4Imm } },
69734b61d6cSJonas Paulsson   { "vrx", SystemZ::InsnVRX, 4,
6985588dbceSJonas Paulsson     { MCK_U48Imm, MCK_VR128, MCK_BDXAddr64Disp12, MCK_U4Imm } },
69934b61d6cSJonas Paulsson   { "vsi", SystemZ::InsnVSI, 4,
7005588dbceSJonas Paulsson     { MCK_U48Imm, MCK_VR128, MCK_BDAddr64Disp12, MCK_U8Imm } }
7014fbc3f4aSZhan Jun Liau };
7024fbc3f4aSZhan Jun Liau 
printMCExpr(const MCExpr * E,raw_ostream & OS)703dda46307SJonas Paulsson static void printMCExpr(const MCExpr *E, raw_ostream &OS) {
704dda46307SJonas Paulsson   if (!E)
705dda46307SJonas Paulsson     return;
706dda46307SJonas Paulsson   if (auto *CE = dyn_cast<MCConstantExpr>(E))
707dda46307SJonas Paulsson     OS << *CE;
708dda46307SJonas Paulsson   else if (auto *UE = dyn_cast<MCUnaryExpr>(E))
709dda46307SJonas Paulsson     OS << *UE;
710dda46307SJonas Paulsson   else if (auto *BE = dyn_cast<MCBinaryExpr>(E))
711dda46307SJonas Paulsson     OS << *BE;
712dda46307SJonas Paulsson   else if (auto *SRE = dyn_cast<MCSymbolRefExpr>(E))
713dda46307SJonas Paulsson     OS << *SRE;
714dda46307SJonas Paulsson   else
715dda46307SJonas Paulsson     OS << *E;
716dda46307SJonas Paulsson }
717dda46307SJonas Paulsson 
print(raw_ostream & OS) const7185f613dfdSUlrich Weigand void SystemZOperand::print(raw_ostream &OS) const {
719dda46307SJonas Paulsson   switch (Kind) {
720dda46307SJonas Paulsson   case KindToken:
721dda46307SJonas Paulsson     OS << "Token:" << getToken();
722dda46307SJonas Paulsson     break;
723dda46307SJonas Paulsson   case KindReg:
724dda46307SJonas Paulsson     OS << "Reg:" << SystemZInstPrinter::getRegisterName(getReg());
725dda46307SJonas Paulsson     break;
726dda46307SJonas Paulsson   case KindImm:
727dda46307SJonas Paulsson     OS << "Imm:";
728dda46307SJonas Paulsson     printMCExpr(getImm(), OS);
729dda46307SJonas Paulsson     break;
730dda46307SJonas Paulsson   case KindImmTLS:
731dda46307SJonas Paulsson     OS << "ImmTLS:";
732dda46307SJonas Paulsson     printMCExpr(getImmTLS().Imm, OS);
733dda46307SJonas Paulsson     if (getImmTLS().Sym) {
734dda46307SJonas Paulsson       OS << ", ";
735dda46307SJonas Paulsson       printMCExpr(getImmTLS().Sym, OS);
736dda46307SJonas Paulsson     }
737dda46307SJonas Paulsson     break;
738dda46307SJonas Paulsson   case KindMem: {
739dda46307SJonas Paulsson     const MemOp &Op = getMem();
740dda46307SJonas Paulsson     OS << "Mem:" << *cast<MCConstantExpr>(Op.Disp);
741dda46307SJonas Paulsson     if (Op.Base) {
742dda46307SJonas Paulsson       OS << "(";
743dda46307SJonas Paulsson       if (Op.MemKind == BDLMem)
744dda46307SJonas Paulsson         OS << *cast<MCConstantExpr>(Op.Length.Imm) << ",";
745dda46307SJonas Paulsson       else if (Op.MemKind == BDRMem)
746dda46307SJonas Paulsson         OS << SystemZInstPrinter::getRegisterName(Op.Length.Reg) << ",";
747dda46307SJonas Paulsson       if (Op.Index)
748dda46307SJonas Paulsson         OS << SystemZInstPrinter::getRegisterName(Op.Index) << ",";
749dda46307SJonas Paulsson       OS << SystemZInstPrinter::getRegisterName(Op.Base);
750dda46307SJonas Paulsson       OS << ")";
751dda46307SJonas Paulsson     }
752dda46307SJonas Paulsson     break;
753dda46307SJonas Paulsson   }
754dda46307SJonas Paulsson   case KindInvalid:
755dda46307SJonas Paulsson     break;
756dda46307SJonas Paulsson   }
7575f613dfdSUlrich Weigand }
7585f613dfdSUlrich Weigand 
7595f613dfdSUlrich Weigand // Parse one register of the form %<prefix><number>.
parseRegister(Register & Reg,bool RestoreOnFailure)7608d5bf042SEric Astor bool SystemZAsmParser::parseRegister(Register &Reg, bool RestoreOnFailure) {
7615f613dfdSUlrich Weigand   Reg.StartLoc = Parser.getTok().getLoc();
7625f613dfdSUlrich Weigand 
7635f613dfdSUlrich Weigand   // Eat the % prefix.
7645f613dfdSUlrich Weigand   if (Parser.getTok().isNot(AsmToken::Percent))
765dc5ed713SRichard Sandiford     return Error(Parser.getTok().getLoc(), "register expected");
7668d5bf042SEric Astor   const AsmToken &PercentTok = Parser.getTok();
7675f613dfdSUlrich Weigand   Parser.Lex();
7685f613dfdSUlrich Weigand 
7695f613dfdSUlrich Weigand   // Expect a register name.
7708d5bf042SEric Astor   if (Parser.getTok().isNot(AsmToken::Identifier)) {
7718d5bf042SEric Astor     if (RestoreOnFailure)
7728d5bf042SEric Astor       getLexer().UnLex(PercentTok);
773dc5ed713SRichard Sandiford     return Error(Reg.StartLoc, "invalid register");
7748d5bf042SEric Astor   }
7755f613dfdSUlrich Weigand 
776675f8699SRichard Sandiford   // Check that there's a prefix.
7775f613dfdSUlrich Weigand   StringRef Name = Parser.getTok().getString();
7788d5bf042SEric Astor   if (Name.size() < 2) {
7798d5bf042SEric Astor     if (RestoreOnFailure)
7808d5bf042SEric Astor       getLexer().UnLex(PercentTok);
781dc5ed713SRichard Sandiford     return Error(Reg.StartLoc, "invalid register");
7828d5bf042SEric Astor   }
783675f8699SRichard Sandiford   char Prefix = Name[0];
7845f613dfdSUlrich Weigand 
7855f613dfdSUlrich Weigand   // Treat the rest of the register name as a register number.
7868d5bf042SEric Astor   if (Name.substr(1).getAsInteger(10, Reg.Num)) {
7878d5bf042SEric Astor     if (RestoreOnFailure)
7888d5bf042SEric Astor       getLexer().UnLex(PercentTok);
789dc5ed713SRichard Sandiford     return Error(Reg.StartLoc, "invalid register");
7908d5bf042SEric Astor   }
791675f8699SRichard Sandiford 
792675f8699SRichard Sandiford   // Look for valid combinations of prefix and number.
793675f8699SRichard Sandiford   if (Prefix == 'r' && Reg.Num < 16)
794675f8699SRichard Sandiford     Reg.Group = RegGR;
795675f8699SRichard Sandiford   else if (Prefix == 'f' && Reg.Num < 16)
796675f8699SRichard Sandiford     Reg.Group = RegFP;
797a8b04e1cSUlrich Weigand   else if (Prefix == 'v' && Reg.Num < 32)
798a8b04e1cSUlrich Weigand     Reg.Group = RegV;
799675f8699SRichard Sandiford   else if (Prefix == 'a' && Reg.Num < 16)
800fffc7110SUlrich Weigand     Reg.Group = RegAR;
80103ab2e2bSUlrich Weigand   else if (Prefix == 'c' && Reg.Num < 16)
80203ab2e2bSUlrich Weigand     Reg.Group = RegCR;
8038d5bf042SEric Astor   else {
8048d5bf042SEric Astor     if (RestoreOnFailure)
8058d5bf042SEric Astor       getLexer().UnLex(PercentTok);
806dc5ed713SRichard Sandiford     return Error(Reg.StartLoc, "invalid register");
8078d5bf042SEric Astor   }
8085f613dfdSUlrich Weigand 
8095f613dfdSUlrich Weigand   Reg.EndLoc = Parser.getTok().getLoc();
8105f613dfdSUlrich Weigand   Parser.Lex();
8115f613dfdSUlrich Weigand   return false;
8125f613dfdSUlrich Weigand }
8135f613dfdSUlrich Weigand 
8146bfde063SUlrich Weigand // Parse a register of kind Kind and add it to Operands.
81558eba099SAlex Bradbury OperandMatchResultTy
parseRegister(OperandVector & Operands,RegisterKind Kind)8166bfde063SUlrich Weigand SystemZAsmParser::parseRegister(OperandVector &Operands, RegisterKind Kind) {
817dc5ed713SRichard Sandiford   Register Reg;
818cca8578eSUlrich Weigand   RegisterGroup Group;
8196bfde063SUlrich Weigand   switch (Kind) {
8206bfde063SUlrich Weigand   case GR32Reg:
8216bfde063SUlrich Weigand   case GRH32Reg:
8226bfde063SUlrich Weigand   case GR64Reg:
8236bfde063SUlrich Weigand   case GR128Reg:
824cca8578eSUlrich Weigand     Group = RegGR;
8256bfde063SUlrich Weigand     break;
8266bfde063SUlrich Weigand   case FP32Reg:
8276bfde063SUlrich Weigand   case FP64Reg:
8286bfde063SUlrich Weigand   case FP128Reg:
829cca8578eSUlrich Weigand     Group = RegFP;
8306bfde063SUlrich Weigand     break;
8316bfde063SUlrich Weigand   case VR32Reg:
8326bfde063SUlrich Weigand   case VR64Reg:
8336bfde063SUlrich Weigand   case VR128Reg:
834cca8578eSUlrich Weigand     Group = RegV;
8356bfde063SUlrich Weigand     break;
8366bfde063SUlrich Weigand   case AR32Reg:
837cca8578eSUlrich Weigand     Group = RegAR;
8386bfde063SUlrich Weigand     break;
8396bfde063SUlrich Weigand   case CR64Reg:
840cca8578eSUlrich Weigand     Group = RegCR;
8416bfde063SUlrich Weigand     break;
8426bfde063SUlrich Weigand   }
843cca8578eSUlrich Weigand 
844cca8578eSUlrich Weigand   // Handle register names of the form %<prefix><number>
8453ed6a6f6SAnirudh Prasad   if (isParsingATT() && Parser.getTok().is(AsmToken::Percent)) {
846cca8578eSUlrich Weigand     if (parseRegister(Reg))
847cca8578eSUlrich Weigand       return MatchOperand_ParseFail;
848cca8578eSUlrich Weigand 
849cca8578eSUlrich Weigand     // Check the parsed register group "Reg.Group" with the expected "Group"
850cca8578eSUlrich Weigand     // Have to error out if user specified wrong prefix.
851cca8578eSUlrich Weigand     switch (Group) {
852cca8578eSUlrich Weigand     case RegGR:
853cca8578eSUlrich Weigand     case RegFP:
854cca8578eSUlrich Weigand     case RegAR:
855cca8578eSUlrich Weigand     case RegCR:
856cca8578eSUlrich Weigand       if (Group != Reg.Group) {
8576bfde063SUlrich Weigand         Error(Reg.StartLoc, "invalid operand for instruction");
8586bfde063SUlrich Weigand         return MatchOperand_ParseFail;
8596bfde063SUlrich Weigand       }
860e1de2773SUlrich Weigand       break;
861cca8578eSUlrich Weigand     case RegV:
862cca8578eSUlrich Weigand       if (Reg.Group != RegV && Reg.Group != RegFP) {
863cca8578eSUlrich Weigand         Error(Reg.StartLoc, "invalid operand for instruction");
864cca8578eSUlrich Weigand         return MatchOperand_ParseFail;
865cca8578eSUlrich Weigand       }
866e1de2773SUlrich Weigand       break;
867e1de2773SUlrich Weigand     }
868cca8578eSUlrich Weigand   } else if (Parser.getTok().is(AsmToken::Integer)) {
869cca8578eSUlrich Weigand     if (parseIntegerRegister(Reg, Group))
870e1de2773SUlrich Weigand       return MatchOperand_ParseFail;
871e1de2773SUlrich Weigand   }
872e1de2773SUlrich Weigand   // Otherwise we didn't match a register operand.
873e1de2773SUlrich Weigand   else
874e1de2773SUlrich Weigand     return MatchOperand_NoMatch;
875e1de2773SUlrich Weigand 
8766bfde063SUlrich Weigand   // Determine the LLVM register number according to Kind.
8776bfde063SUlrich Weigand   const unsigned *Regs;
8786bfde063SUlrich Weigand   switch (Kind) {
8796bfde063SUlrich Weigand   case GR32Reg:  Regs = SystemZMC::GR32Regs;  break;
8806bfde063SUlrich Weigand   case GRH32Reg: Regs = SystemZMC::GRH32Regs; break;
8816bfde063SUlrich Weigand   case GR64Reg:  Regs = SystemZMC::GR64Regs;  break;
8826bfde063SUlrich Weigand   case GR128Reg: Regs = SystemZMC::GR128Regs; break;
8836bfde063SUlrich Weigand   case FP32Reg:  Regs = SystemZMC::FP32Regs;  break;
8846bfde063SUlrich Weigand   case FP64Reg:  Regs = SystemZMC::FP64Regs;  break;
8856bfde063SUlrich Weigand   case FP128Reg: Regs = SystemZMC::FP128Regs; break;
8866bfde063SUlrich Weigand   case VR32Reg:  Regs = SystemZMC::VR32Regs;  break;
8876bfde063SUlrich Weigand   case VR64Reg:  Regs = SystemZMC::VR64Regs;  break;
8886bfde063SUlrich Weigand   case VR128Reg: Regs = SystemZMC::VR128Regs; break;
8896bfde063SUlrich Weigand   case AR32Reg:  Regs = SystemZMC::AR32Regs;  break;
8906bfde063SUlrich Weigand   case CR64Reg:  Regs = SystemZMC::CR64Regs;  break;
8916bfde063SUlrich Weigand   }
892cca8578eSUlrich Weigand   if (Regs[Reg.Num] == 0) {
893cca8578eSUlrich Weigand     Error(Reg.StartLoc, "invalid register pair");
8946bfde063SUlrich Weigand     return MatchOperand_ParseFail;
8956bfde063SUlrich Weigand   }
8966bfde063SUlrich Weigand 
897cca8578eSUlrich Weigand   Operands.push_back(
898cca8578eSUlrich Weigand       SystemZOperand::createReg(Kind, Regs[Reg.Num], Reg.StartLoc, Reg.EndLoc));
899dc5ed713SRichard Sandiford   return MatchOperand_Success;
900dc5ed713SRichard Sandiford }
901dc5ed713SRichard Sandiford 
9024fbc3f4aSZhan Jun Liau // Parse any type of register (including integers) and add it to Operands.
90358eba099SAlex Bradbury OperandMatchResultTy
parseAnyRegister(OperandVector & Operands)9044fbc3f4aSZhan Jun Liau SystemZAsmParser::parseAnyRegister(OperandVector &Operands) {
9055588dbceSJonas Paulsson   SMLoc StartLoc = Parser.getTok().getLoc();
9065588dbceSJonas Paulsson 
9074fbc3f4aSZhan Jun Liau   // Handle integer values.
9084fbc3f4aSZhan Jun Liau   if (Parser.getTok().is(AsmToken::Integer)) {
9094fbc3f4aSZhan Jun Liau     const MCExpr *Register;
9104fbc3f4aSZhan Jun Liau     if (Parser.parseExpression(Register))
9114fbc3f4aSZhan Jun Liau       return MatchOperand_ParseFail;
9124fbc3f4aSZhan Jun Liau 
9134fbc3f4aSZhan Jun Liau     if (auto *CE = dyn_cast<MCConstantExpr>(Register)) {
9144fbc3f4aSZhan Jun Liau       int64_t Value = CE->getValue();
9154fbc3f4aSZhan Jun Liau       if (Value < 0 || Value > 15) {
9164fbc3f4aSZhan Jun Liau         Error(StartLoc, "invalid register");
9174fbc3f4aSZhan Jun Liau         return MatchOperand_ParseFail;
9184fbc3f4aSZhan Jun Liau       }
9194fbc3f4aSZhan Jun Liau     }
9204fbc3f4aSZhan Jun Liau 
9214fbc3f4aSZhan Jun Liau     SMLoc EndLoc =
9224fbc3f4aSZhan Jun Liau       SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
9234fbc3f4aSZhan Jun Liau 
9244fbc3f4aSZhan Jun Liau     Operands.push_back(SystemZOperand::createImm(Register, StartLoc, EndLoc));
9254fbc3f4aSZhan Jun Liau   }
9264fbc3f4aSZhan Jun Liau   else {
9273ed6a6f6SAnirudh Prasad     if (isParsingHLASM())
9283ed6a6f6SAnirudh Prasad       return MatchOperand_NoMatch;
9293ed6a6f6SAnirudh Prasad 
9304fbc3f4aSZhan Jun Liau     Register Reg;
9314fbc3f4aSZhan Jun Liau     if (parseRegister(Reg))
9324fbc3f4aSZhan Jun Liau       return MatchOperand_ParseFail;
9334fbc3f4aSZhan Jun Liau 
9345588dbceSJonas Paulsson     if (Reg.Num > 15) {
9355588dbceSJonas Paulsson       Error(StartLoc, "invalid register");
9365588dbceSJonas Paulsson       return MatchOperand_ParseFail;
9375588dbceSJonas Paulsson     }
9385588dbceSJonas Paulsson 
9394fbc3f4aSZhan Jun Liau     // Map to the correct register kind.
9404fbc3f4aSZhan Jun Liau     RegisterKind Kind;
9414fbc3f4aSZhan Jun Liau     unsigned RegNo;
9424fbc3f4aSZhan Jun Liau     if (Reg.Group == RegGR) {
9434fbc3f4aSZhan Jun Liau       Kind = GR64Reg;
9444fbc3f4aSZhan Jun Liau       RegNo = SystemZMC::GR64Regs[Reg.Num];
9454fbc3f4aSZhan Jun Liau     }
9464fbc3f4aSZhan Jun Liau     else if (Reg.Group == RegFP) {
9474fbc3f4aSZhan Jun Liau       Kind = FP64Reg;
9484fbc3f4aSZhan Jun Liau       RegNo = SystemZMC::FP64Regs[Reg.Num];
9494fbc3f4aSZhan Jun Liau     }
9504fbc3f4aSZhan Jun Liau     else if (Reg.Group == RegV) {
9514fbc3f4aSZhan Jun Liau       Kind = VR128Reg;
9524fbc3f4aSZhan Jun Liau       RegNo = SystemZMC::VR128Regs[Reg.Num];
9534fbc3f4aSZhan Jun Liau     }
954fffc7110SUlrich Weigand     else if (Reg.Group == RegAR) {
955fffc7110SUlrich Weigand       Kind = AR32Reg;
956fffc7110SUlrich Weigand       RegNo = SystemZMC::AR32Regs[Reg.Num];
957fffc7110SUlrich Weigand     }
95803ab2e2bSUlrich Weigand     else if (Reg.Group == RegCR) {
95903ab2e2bSUlrich Weigand       Kind = CR64Reg;
96003ab2e2bSUlrich Weigand       RegNo = SystemZMC::CR64Regs[Reg.Num];
96103ab2e2bSUlrich Weigand     }
9624fbc3f4aSZhan Jun Liau     else {
9634fbc3f4aSZhan Jun Liau       return MatchOperand_ParseFail;
9644fbc3f4aSZhan Jun Liau     }
9654fbc3f4aSZhan Jun Liau 
9664fbc3f4aSZhan Jun Liau     Operands.push_back(SystemZOperand::createReg(Kind, RegNo,
9674fbc3f4aSZhan Jun Liau                                                  Reg.StartLoc, Reg.EndLoc));
9684fbc3f4aSZhan Jun Liau   }
9694fbc3f4aSZhan Jun Liau   return MatchOperand_Success;
9704fbc3f4aSZhan Jun Liau }
9714fbc3f4aSZhan Jun Liau 
parseIntegerRegister(Register & Reg,RegisterGroup Group)972cca8578eSUlrich Weigand bool SystemZAsmParser::parseIntegerRegister(Register &Reg,
973cca8578eSUlrich Weigand                                             RegisterGroup Group) {
974cca8578eSUlrich Weigand   Reg.StartLoc = Parser.getTok().getLoc();
975cca8578eSUlrich Weigand   // We have an integer token
976cca8578eSUlrich Weigand   const MCExpr *Register;
977cca8578eSUlrich Weigand   if (Parser.parseExpression(Register))
978cca8578eSUlrich Weigand     return true;
979cca8578eSUlrich Weigand 
980cca8578eSUlrich Weigand   const auto *CE = dyn_cast<MCConstantExpr>(Register);
981cca8578eSUlrich Weigand   if (!CE)
982cca8578eSUlrich Weigand     return true;
983cca8578eSUlrich Weigand 
984cca8578eSUlrich Weigand   int64_t MaxRegNum = (Group == RegV) ? 31 : 15;
985cca8578eSUlrich Weigand   int64_t Value = CE->getValue();
986cca8578eSUlrich Weigand   if (Value < 0 || Value > MaxRegNum) {
987cca8578eSUlrich Weigand     Error(Parser.getTok().getLoc(), "invalid register");
988cca8578eSUlrich Weigand     return true;
989cca8578eSUlrich Weigand   }
990cca8578eSUlrich Weigand 
991cca8578eSUlrich Weigand   // Assign the Register Number
992cca8578eSUlrich Weigand   Reg.Num = (unsigned)Value;
993cca8578eSUlrich Weigand   Reg.Group = Group;
994cca8578eSUlrich Weigand   Reg.EndLoc = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
995cca8578eSUlrich Weigand 
996cca8578eSUlrich Weigand   // At this point, successfully parsed an integer register.
997cca8578eSUlrich Weigand   return false;
998cca8578eSUlrich Weigand }
999cca8578eSUlrich Weigand 
1000ec5d779eSUlrich Weigand // Parse a memory operand into Reg1, Reg2, Disp, and Length.
parseAddress(bool & HaveReg1,Register & Reg1,bool & HaveReg2,Register & Reg2,const MCExpr * & Disp,const MCExpr * & Length,bool HasLength,bool HasVectorIndex)1001ec5d779eSUlrich Weigand bool SystemZAsmParser::parseAddress(bool &HaveReg1, Register &Reg1,
1002ec5d779eSUlrich Weigand                                     bool &HaveReg2, Register &Reg2,
1003cca8578eSUlrich Weigand                                     const MCExpr *&Disp, const MCExpr *&Length,
1004cca8578eSUlrich Weigand                                     bool HasLength, bool HasVectorIndex) {
1005dc5ed713SRichard Sandiford   // Parse the displacement, which must always be present.
1006dc5ed713SRichard Sandiford   if (getParser().parseExpression(Disp))
1007dc5ed713SRichard Sandiford     return true;
1008dc5ed713SRichard Sandiford 
10095f613dfdSUlrich Weigand   // Parse the optional base and index.
1010ec5d779eSUlrich Weigand   HaveReg1 = false;
1011ec5d779eSUlrich Weigand   HaveReg2 = false;
1012062a2baeSCraig Topper   Length = nullptr;
1013cca8578eSUlrich Weigand 
1014cca8578eSUlrich Weigand   // If we have a scenario as below:
1015cca8578eSUlrich Weigand   //   vgef %v0, 0(0), 0
1016cca8578eSUlrich Weigand   // This is an example of a "BDVMem" instruction type.
1017cca8578eSUlrich Weigand   //
1018cca8578eSUlrich Weigand   // So when we parse this as an integer register, the register group
1019cca8578eSUlrich Weigand   // needs to be tied to "RegV". Usually when the prefix is passed in
1020cca8578eSUlrich Weigand   // as %<prefix><reg-number> its easy to check which group it should belong to
1021cca8578eSUlrich Weigand   // However, if we're passing in just the integer there's no real way to
1022cca8578eSUlrich Weigand   // "check" what register group it should belong to.
1023cca8578eSUlrich Weigand   //
1024cca8578eSUlrich Weigand   // When the user passes in the register as an integer, the user assumes that
1025cca8578eSUlrich Weigand   // the compiler is responsible for substituting it as the right kind of
1026cca8578eSUlrich Weigand   // register. Whereas, when the user specifies a "prefix", the onus is on
1027cca8578eSUlrich Weigand   // the user to make sure they pass in the right kind of register.
1028cca8578eSUlrich Weigand   //
1029cca8578eSUlrich Weigand   // The restriction only applies to the first Register (i.e. Reg1). Reg2 is
1030cca8578eSUlrich Weigand   // always a general register. Reg1 should be of group RegV if "HasVectorIndex"
1031cca8578eSUlrich Weigand   // (i.e. insn is of type BDVMem) is true.
1032cca8578eSUlrich Weigand   RegisterGroup RegGroup = HasVectorIndex ? RegV : RegGR;
1033cca8578eSUlrich Weigand 
10345f613dfdSUlrich Weigand   if (getLexer().is(AsmToken::LParen)) {
10355f613dfdSUlrich Weigand     Parser.Lex();
10365f613dfdSUlrich Weigand 
10373ed6a6f6SAnirudh Prasad     if (isParsingATT() && getLexer().is(AsmToken::Percent)) {
1038ec5d779eSUlrich Weigand       // Parse the first register.
1039ec5d779eSUlrich Weigand       HaveReg1 = true;
1040ec5d779eSUlrich Weigand       if (parseRegister(Reg1))
1041dc5ed713SRichard Sandiford         return true;
1042cca8578eSUlrich Weigand     }
1043cca8578eSUlrich Weigand     // So if we have an integer as the first token in ([tok1], ..), it could:
1044cca8578eSUlrich Weigand     // 1. Refer to a "Register" (i.e X,R,V fields in BD[X|R|V]Mem type of
1045cca8578eSUlrich Weigand     // instructions)
1046cca8578eSUlrich Weigand     // 2. Refer to a "Length" field (i.e L field in BDLMem type of instructions)
1047cca8578eSUlrich Weigand     else if (getLexer().is(AsmToken::Integer)) {
1048cca8578eSUlrich Weigand       if (HasLength) {
1049cca8578eSUlrich Weigand         // Instruction has a "Length" field, safe to parse the first token as
1050cca8578eSUlrich Weigand         // the "Length" field
10511d959008SRichard Sandiford         if (getParser().parseExpression(Length))
1052dc5ed713SRichard Sandiford           return true;
1053cca8578eSUlrich Weigand       } else {
1054cca8578eSUlrich Weigand         // Otherwise, if the instruction has no "Length" field, parse the
1055cca8578eSUlrich Weigand         // token as a "Register". We don't have to worry about whether the
1056cca8578eSUlrich Weigand         // instruction is invalid here, because the caller will take care of
1057cca8578eSUlrich Weigand         // error reporting.
1058cca8578eSUlrich Weigand         HaveReg1 = true;
1059cca8578eSUlrich Weigand         if (parseIntegerRegister(Reg1, RegGroup))
1060cca8578eSUlrich Weigand           return true;
1061cca8578eSUlrich Weigand       }
1062cca8578eSUlrich Weigand     } else {
1063cca8578eSUlrich Weigand       // If its not an integer or a percent token, then if the instruction
1064cca8578eSUlrich Weigand       // is reported to have a "Length" then, parse it as "Length".
1065cca8578eSUlrich Weigand       if (HasLength) {
1066cca8578eSUlrich Weigand         if (getParser().parseExpression(Length))
1067cca8578eSUlrich Weigand           return true;
1068cca8578eSUlrich Weigand       }
10695f613dfdSUlrich Weigand     }
10701d959008SRichard Sandiford 
1071ec5d779eSUlrich Weigand     // Check whether there's a second register.
10721d959008SRichard Sandiford     if (getLexer().is(AsmToken::Comma)) {
10731d959008SRichard Sandiford       Parser.Lex();
1074ec5d779eSUlrich Weigand       HaveReg2 = true;
1075cca8578eSUlrich Weigand 
1076cca8578eSUlrich Weigand       if (getLexer().is(AsmToken::Integer)) {
1077cca8578eSUlrich Weigand         if (parseIntegerRegister(Reg2, RegGR))
1078cca8578eSUlrich Weigand           return true;
1079cca8578eSUlrich Weigand       } else {
10803ed6a6f6SAnirudh Prasad         if (isParsingATT() && parseRegister(Reg2))
10811d959008SRichard Sandiford           return true;
10821d959008SRichard Sandiford       }
1083cca8578eSUlrich Weigand     }
10845f613dfdSUlrich Weigand 
10855f613dfdSUlrich Weigand     // Consume the closing bracket.
10865f613dfdSUlrich Weigand     if (getLexer().isNot(AsmToken::RParen))
1087dc5ed713SRichard Sandiford       return Error(Parser.getTok().getLoc(), "unexpected token in address");
10885f613dfdSUlrich Weigand     Parser.Lex();
10895f613dfdSUlrich Weigand   }
1090dc5ed713SRichard Sandiford   return false;
1091dc5ed713SRichard Sandiford }
1092dc5ed713SRichard Sandiford 
1093ec5d779eSUlrich Weigand // Verify that Reg is a valid address register (base or index).
1094ec5d779eSUlrich Weigand bool
parseAddressRegister(Register & Reg)1095ec5d779eSUlrich Weigand SystemZAsmParser::parseAddressRegister(Register &Reg) {
1096ec5d779eSUlrich Weigand   if (Reg.Group == RegV) {
1097ec5d779eSUlrich Weigand     Error(Reg.StartLoc, "invalid use of vector addressing");
1098ec5d779eSUlrich Weigand     return true;
1099ec5d779eSUlrich Weigand   } else if (Reg.Group != RegGR) {
1100ec5d779eSUlrich Weigand     Error(Reg.StartLoc, "invalid address register");
1101ec5d779eSUlrich Weigand     return true;
1102ec5d779eSUlrich Weigand   }
1103ec5d779eSUlrich Weigand   return false;
1104ec5d779eSUlrich Weigand }
1105ec5d779eSUlrich Weigand 
1106dc5ed713SRichard Sandiford // Parse a memory operand and add it to Operands.  The other arguments
1107dc5ed713SRichard Sandiford // are as above.
110858eba099SAlex Bradbury OperandMatchResultTy
parseAddress(OperandVector & Operands,MemoryKind MemKind,RegisterKind RegKind)11091f698b00SUlrich Weigand SystemZAsmParser::parseAddress(OperandVector &Operands, MemoryKind MemKind,
11106bfde063SUlrich Weigand                                RegisterKind RegKind) {
1111dc5ed713SRichard Sandiford   SMLoc StartLoc = Parser.getTok().getLoc();
1112ec5d779eSUlrich Weigand   unsigned Base = 0, Index = 0, LengthReg = 0;
1113ec5d779eSUlrich Weigand   Register Reg1, Reg2;
1114ec5d779eSUlrich Weigand   bool HaveReg1, HaveReg2;
1115dc5ed713SRichard Sandiford   const MCExpr *Disp;
11161d959008SRichard Sandiford   const MCExpr *Length;
1117cca8578eSUlrich Weigand 
1118cca8578eSUlrich Weigand   bool HasLength = (MemKind == BDLMem) ? true : false;
1119cca8578eSUlrich Weigand   bool HasVectorIndex = (MemKind == BDVMem) ? true : false;
1120cca8578eSUlrich Weigand   if (parseAddress(HaveReg1, Reg1, HaveReg2, Reg2, Disp, Length, HasLength,
1121cca8578eSUlrich Weigand                    HasVectorIndex))
1122dc5ed713SRichard Sandiford     return MatchOperand_ParseFail;
11235f613dfdSUlrich Weigand 
11246bfde063SUlrich Weigand   const unsigned *Regs;
11256bfde063SUlrich Weigand   switch (RegKind) {
11266bfde063SUlrich Weigand   case GR32Reg: Regs = SystemZMC::GR32Regs; break;
11276bfde063SUlrich Weigand   case GR64Reg: Regs = SystemZMC::GR64Regs; break;
11286bfde063SUlrich Weigand   default: llvm_unreachable("invalid RegKind");
11296bfde063SUlrich Weigand   }
11306bfde063SUlrich Weigand 
1131ec5d779eSUlrich Weigand   switch (MemKind) {
1132ec5d779eSUlrich Weigand   case BDMem:
1133ec5d779eSUlrich Weigand     // If we have Reg1, it must be an address register.
1134ec5d779eSUlrich Weigand     if (HaveReg1) {
1135ec5d779eSUlrich Weigand       if (parseAddressRegister(Reg1))
1136a8b04e1cSUlrich Weigand         return MatchOperand_ParseFail;
1137ec5d779eSUlrich Weigand       Base = Regs[Reg1.Num];
1138a8b04e1cSUlrich Weigand     }
1139cca8578eSUlrich Weigand     // There must be no Reg2.
1140ec5d779eSUlrich Weigand     if (HaveReg2) {
1141ec5d779eSUlrich Weigand       Error(StartLoc, "invalid use of indexed addressing");
1142ec5d779eSUlrich Weigand       return MatchOperand_ParseFail;
1143ec5d779eSUlrich Weigand     }
1144ec5d779eSUlrich Weigand     break;
1145ec5d779eSUlrich Weigand   case BDXMem:
1146ec5d779eSUlrich Weigand     // If we have Reg1, it must be an address register.
1147ec5d779eSUlrich Weigand     if (HaveReg1) {
1148ec5d779eSUlrich Weigand       if (parseAddressRegister(Reg1))
1149ec5d779eSUlrich Weigand         return MatchOperand_ParseFail;
1150ec5d779eSUlrich Weigand       // If the are two registers, the first one is the index and the
1151ec5d779eSUlrich Weigand       // second is the base.
1152ec5d779eSUlrich Weigand       if (HaveReg2)
1153ec5d779eSUlrich Weigand         Index = Regs[Reg1.Num];
1154ec5d779eSUlrich Weigand       else
1155ec5d779eSUlrich Weigand         Base = Regs[Reg1.Num];
1156ec5d779eSUlrich Weigand     }
1157ec5d779eSUlrich Weigand     // If we have Reg2, it must be an address register.
1158ec5d779eSUlrich Weigand     if (HaveReg2) {
1159ec5d779eSUlrich Weigand       if (parseAddressRegister(Reg2))
1160ec5d779eSUlrich Weigand         return MatchOperand_ParseFail;
1161ec5d779eSUlrich Weigand       Base = Regs[Reg2.Num];
1162ec5d779eSUlrich Weigand     }
1163ec5d779eSUlrich Weigand     break;
1164ec5d779eSUlrich Weigand   case BDLMem:
1165ec5d779eSUlrich Weigand     // If we have Reg2, it must be an address register.
1166ec5d779eSUlrich Weigand     if (HaveReg2) {
1167ec5d779eSUlrich Weigand       if (parseAddressRegister(Reg2))
1168ec5d779eSUlrich Weigand         return MatchOperand_ParseFail;
1169ec5d779eSUlrich Weigand       Base = Regs[Reg2.Num];
1170ec5d779eSUlrich Weigand     }
1171ec5d779eSUlrich Weigand     // We cannot support base+index addressing.
1172ec5d779eSUlrich Weigand     if (HaveReg1 && HaveReg2) {
1173ec5d779eSUlrich Weigand       Error(StartLoc, "invalid use of indexed addressing");
1174ec5d779eSUlrich Weigand       return MatchOperand_ParseFail;
1175ec5d779eSUlrich Weigand     }
1176ec5d779eSUlrich Weigand     // We must have a length.
1177ec5d779eSUlrich Weigand     if (!Length) {
11781d959008SRichard Sandiford       Error(StartLoc, "missing length in address");
11791d959008SRichard Sandiford       return MatchOperand_ParseFail;
11801d959008SRichard Sandiford     }
1181ec5d779eSUlrich Weigand     break;
1182ec5d779eSUlrich Weigand   case BDRMem:
1183ec5d779eSUlrich Weigand     // We must have Reg1, and it must be a GPR.
1184ec5d779eSUlrich Weigand     if (!HaveReg1 || Reg1.Group != RegGR) {
1185ec5d779eSUlrich Weigand       Error(StartLoc, "invalid operand for instruction");
1186ec5d779eSUlrich Weigand       return MatchOperand_ParseFail;
1187ec5d779eSUlrich Weigand     }
1188ec5d779eSUlrich Weigand     LengthReg = SystemZMC::GR64Regs[Reg1.Num];
1189ec5d779eSUlrich Weigand     // If we have Reg2, it must be an address register.
1190ec5d779eSUlrich Weigand     if (HaveReg2) {
1191ec5d779eSUlrich Weigand       if (parseAddressRegister(Reg2))
1192ec5d779eSUlrich Weigand         return MatchOperand_ParseFail;
1193ec5d779eSUlrich Weigand       Base = Regs[Reg2.Num];
1194ec5d779eSUlrich Weigand     }
1195ec5d779eSUlrich Weigand     break;
1196ec5d779eSUlrich Weigand   case BDVMem:
1197ec5d779eSUlrich Weigand     // We must have Reg1, and it must be a vector register.
1198ec5d779eSUlrich Weigand     if (!HaveReg1 || Reg1.Group != RegV) {
1199ec5d779eSUlrich Weigand       Error(StartLoc, "vector index required in address");
1200ec5d779eSUlrich Weigand       return MatchOperand_ParseFail;
1201ec5d779eSUlrich Weigand     }
1202ec5d779eSUlrich Weigand     Index = SystemZMC::VR128Regs[Reg1.Num];
1203ec5d779eSUlrich Weigand     // If we have Reg2, it must be an address register.
1204ec5d779eSUlrich Weigand     if (HaveReg2) {
1205ec5d779eSUlrich Weigand       if (parseAddressRegister(Reg2))
1206ec5d779eSUlrich Weigand         return MatchOperand_ParseFail;
1207ec5d779eSUlrich Weigand       Base = Regs[Reg2.Num];
1208ec5d779eSUlrich Weigand     }
1209ec5d779eSUlrich Weigand     break;
1210ec5d779eSUlrich Weigand   }
12111d959008SRichard Sandiford 
12125f613dfdSUlrich Weigand   SMLoc EndLoc =
12135f613dfdSUlrich Weigand       SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
12141f698b00SUlrich Weigand   Operands.push_back(SystemZOperand::createMem(MemKind, RegKind, Base, Disp,
1215ec5d779eSUlrich Weigand                                                Index, Length, LengthReg,
1216ec5d779eSUlrich Weigand                                                StartLoc, EndLoc));
12175f613dfdSUlrich Weigand   return MatchOperand_Success;
12185f613dfdSUlrich Weigand }
12195f613dfdSUlrich Weigand 
ParseDirective(AsmToken DirectiveID)12205f613dfdSUlrich Weigand bool SystemZAsmParser::ParseDirective(AsmToken DirectiveID) {
12214fbc3f4aSZhan Jun Liau   StringRef IDVal = DirectiveID.getIdentifier();
12224fbc3f4aSZhan Jun Liau 
12234fbc3f4aSZhan Jun Liau   if (IDVal == ".insn")
12244fbc3f4aSZhan Jun Liau     return ParseDirectiveInsn(DirectiveID.getLoc());
12251a5ab3e9SJonas Paulsson   if (IDVal == ".machine")
12261a5ab3e9SJonas Paulsson     return ParseDirectiveMachine(DirectiveID.getLoc());
12274fbc3f4aSZhan Jun Liau 
12285f613dfdSUlrich Weigand   return true;
12295f613dfdSUlrich Weigand }
12305f613dfdSUlrich Weigand 
12314fbc3f4aSZhan Jun Liau /// ParseDirectiveInsn
12324fbc3f4aSZhan Jun Liau /// ::= .insn [ format, encoding, (operands (, operands)*) ]
ParseDirectiveInsn(SMLoc L)12334fbc3f4aSZhan Jun Liau bool SystemZAsmParser::ParseDirectiveInsn(SMLoc L) {
12344fbc3f4aSZhan Jun Liau   MCAsmParser &Parser = getParser();
12354fbc3f4aSZhan Jun Liau 
12364fbc3f4aSZhan Jun Liau   // Expect instruction format as identifier.
12374fbc3f4aSZhan Jun Liau   StringRef Format;
12384fbc3f4aSZhan Jun Liau   SMLoc ErrorLoc = Parser.getTok().getLoc();
12394fbc3f4aSZhan Jun Liau   if (Parser.parseIdentifier(Format))
12404fbc3f4aSZhan Jun Liau     return Error(ErrorLoc, "expected instruction format");
12414fbc3f4aSZhan Jun Liau 
12424fbc3f4aSZhan Jun Liau   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;
12434fbc3f4aSZhan Jun Liau 
12444fbc3f4aSZhan Jun Liau   // Find entry for this format in InsnMatchTable.
12454fbc3f4aSZhan Jun Liau   auto EntryRange =
12464fbc3f4aSZhan Jun Liau     std::equal_range(std::begin(InsnMatchTable), std::end(InsnMatchTable),
12474fbc3f4aSZhan Jun Liau                      Format, CompareInsn());
12484fbc3f4aSZhan Jun Liau 
12494fbc3f4aSZhan Jun Liau   // If first == second, couldn't find a match in the table.
12504fbc3f4aSZhan Jun Liau   if (EntryRange.first == EntryRange.second)
12514fbc3f4aSZhan Jun Liau     return Error(ErrorLoc, "unrecognized format");
12524fbc3f4aSZhan Jun Liau 
12534fbc3f4aSZhan Jun Liau   struct InsnMatchEntry *Entry = EntryRange.first;
12544fbc3f4aSZhan Jun Liau 
12554fbc3f4aSZhan Jun Liau   // Format should match from equal_range.
12564fbc3f4aSZhan Jun Liau   assert(Entry->Format == Format);
12574fbc3f4aSZhan Jun Liau 
12584fbc3f4aSZhan Jun Liau   // Parse the following operands using the table's information.
12594fbc3f4aSZhan Jun Liau   for (int i = 0; i < Entry->NumOperands; i++) {
12604fbc3f4aSZhan Jun Liau     MatchClassKind Kind = Entry->OperandKinds[i];
12614fbc3f4aSZhan Jun Liau 
12624fbc3f4aSZhan Jun Liau     SMLoc StartLoc = Parser.getTok().getLoc();
12634fbc3f4aSZhan Jun Liau 
12644fbc3f4aSZhan Jun Liau     // Always expect commas as separators for operands.
12654fbc3f4aSZhan Jun Liau     if (getLexer().isNot(AsmToken::Comma))
12664fbc3f4aSZhan Jun Liau       return Error(StartLoc, "unexpected token in directive");
12674fbc3f4aSZhan Jun Liau     Lex();
12684fbc3f4aSZhan Jun Liau 
12694fbc3f4aSZhan Jun Liau     // Parse operands.
12704fbc3f4aSZhan Jun Liau     OperandMatchResultTy ResTy;
12714fbc3f4aSZhan Jun Liau     if (Kind == MCK_AnyReg)
12724fbc3f4aSZhan Jun Liau       ResTy = parseAnyReg(Operands);
12735588dbceSJonas Paulsson     else if (Kind == MCK_VR128)
12745588dbceSJonas Paulsson       ResTy = parseVR128(Operands);
12754fbc3f4aSZhan Jun Liau     else if (Kind == MCK_BDXAddr64Disp12 || Kind == MCK_BDXAddr64Disp20)
12764fbc3f4aSZhan Jun Liau       ResTy = parseBDXAddr64(Operands);
12774fbc3f4aSZhan Jun Liau     else if (Kind == MCK_BDAddr64Disp12 || Kind == MCK_BDAddr64Disp20)
12784fbc3f4aSZhan Jun Liau       ResTy = parseBDAddr64(Operands);
127934b61d6cSJonas Paulsson     else if (Kind == MCK_BDVAddr64Disp12)
128034b61d6cSJonas Paulsson       ResTy = parseBDVAddr64(Operands);
12814fbc3f4aSZhan Jun Liau     else if (Kind == MCK_PCRel32)
12824fbc3f4aSZhan Jun Liau       ResTy = parsePCRel32(Operands);
12834fbc3f4aSZhan Jun Liau     else if (Kind == MCK_PCRel16)
12844fbc3f4aSZhan Jun Liau       ResTy = parsePCRel16(Operands);
12854fbc3f4aSZhan Jun Liau     else {
12864fbc3f4aSZhan Jun Liau       // Only remaining operand kind is an immediate.
12874fbc3f4aSZhan Jun Liau       const MCExpr *Expr;
12884fbc3f4aSZhan Jun Liau       SMLoc StartLoc = Parser.getTok().getLoc();
12894fbc3f4aSZhan Jun Liau 
12904fbc3f4aSZhan Jun Liau       // Expect immediate expression.
12914fbc3f4aSZhan Jun Liau       if (Parser.parseExpression(Expr))
12924fbc3f4aSZhan Jun Liau         return Error(StartLoc, "unexpected token in directive");
12934fbc3f4aSZhan Jun Liau 
12944fbc3f4aSZhan Jun Liau       SMLoc EndLoc =
12954fbc3f4aSZhan Jun Liau         SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
12964fbc3f4aSZhan Jun Liau 
12974fbc3f4aSZhan Jun Liau       Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));
12984fbc3f4aSZhan Jun Liau       ResTy = MatchOperand_Success;
12994fbc3f4aSZhan Jun Liau     }
13004fbc3f4aSZhan Jun Liau 
13014fbc3f4aSZhan Jun Liau     if (ResTy != MatchOperand_Success)
13024fbc3f4aSZhan Jun Liau       return true;
13034fbc3f4aSZhan Jun Liau   }
13044fbc3f4aSZhan Jun Liau 
13054fbc3f4aSZhan Jun Liau   // Build the instruction with the parsed operands.
13064fbc3f4aSZhan Jun Liau   MCInst Inst = MCInstBuilder(Entry->Opcode);
13074fbc3f4aSZhan Jun Liau 
13084fbc3f4aSZhan Jun Liau   for (size_t i = 0; i < Operands.size(); i++) {
13094fbc3f4aSZhan Jun Liau     MCParsedAsmOperand &Operand = *Operands[i];
13104fbc3f4aSZhan Jun Liau     MatchClassKind Kind = Entry->OperandKinds[i];
13114fbc3f4aSZhan Jun Liau 
13124fbc3f4aSZhan Jun Liau     // Verify operand.
13134fbc3f4aSZhan Jun Liau     unsigned Res = validateOperandClass(Operand, Kind);
13144fbc3f4aSZhan Jun Liau     if (Res != Match_Success)
13154fbc3f4aSZhan Jun Liau       return Error(Operand.getStartLoc(), "unexpected operand type");
13164fbc3f4aSZhan Jun Liau 
13174fbc3f4aSZhan Jun Liau     // Add operands to instruction.
13184fbc3f4aSZhan Jun Liau     SystemZOperand &ZOperand = static_cast<SystemZOperand &>(Operand);
13194fbc3f4aSZhan Jun Liau     if (ZOperand.isReg())
13204fbc3f4aSZhan Jun Liau       ZOperand.addRegOperands(Inst, 1);
13214fbc3f4aSZhan Jun Liau     else if (ZOperand.isMem(BDMem))
13224fbc3f4aSZhan Jun Liau       ZOperand.addBDAddrOperands(Inst, 2);
13234fbc3f4aSZhan Jun Liau     else if (ZOperand.isMem(BDXMem))
13244fbc3f4aSZhan Jun Liau       ZOperand.addBDXAddrOperands(Inst, 3);
132534b61d6cSJonas Paulsson     else if (ZOperand.isMem(BDVMem))
132634b61d6cSJonas Paulsson       ZOperand.addBDVAddrOperands(Inst, 3);
13274fbc3f4aSZhan Jun Liau     else if (ZOperand.isImm())
13284fbc3f4aSZhan Jun Liau       ZOperand.addImmOperands(Inst, 1);
13294fbc3f4aSZhan Jun Liau     else
13304fbc3f4aSZhan Jun Liau       llvm_unreachable("unexpected operand type");
13314fbc3f4aSZhan Jun Liau   }
13324fbc3f4aSZhan Jun Liau 
13334fbc3f4aSZhan Jun Liau   // Emit as a regular instruction.
1334bcd24b2dSFangrui Song   Parser.getStreamer().emitInstruction(Inst, getSTI());
13354fbc3f4aSZhan Jun Liau 
13364fbc3f4aSZhan Jun Liau   return false;
13374fbc3f4aSZhan Jun Liau }
13384fbc3f4aSZhan Jun Liau 
13391a5ab3e9SJonas Paulsson /// ParseDirectiveMachine
13401a5ab3e9SJonas Paulsson /// ::= .machine [ mcpu ]
ParseDirectiveMachine(SMLoc L)13411a5ab3e9SJonas Paulsson bool SystemZAsmParser::ParseDirectiveMachine(SMLoc L) {
13421a5ab3e9SJonas Paulsson   MCAsmParser &Parser = getParser();
13431a5ab3e9SJonas Paulsson   if (Parser.getTok().isNot(AsmToken::Identifier) &&
13441a5ab3e9SJonas Paulsson       Parser.getTok().isNot(AsmToken::String))
13451a5ab3e9SJonas Paulsson     return Error(L, "unexpected token in '.machine' directive");
13461a5ab3e9SJonas Paulsson 
13471a5ab3e9SJonas Paulsson   StringRef CPU = Parser.getTok().getIdentifier();
13481a5ab3e9SJonas Paulsson   Parser.Lex();
13491a5ab3e9SJonas Paulsson   if (parseToken(AsmToken::EndOfStatement))
13501a5ab3e9SJonas Paulsson     return addErrorSuffix(" in '.machine' directive");
13511a5ab3e9SJonas Paulsson 
13521a5ab3e9SJonas Paulsson   MCSubtargetInfo &STI = copySTI();
13531a5ab3e9SJonas Paulsson   STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, "");
13541a5ab3e9SJonas Paulsson   setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
13551a5ab3e9SJonas Paulsson 
13561a5ab3e9SJonas Paulsson   getTargetStreamer().emitMachine(CPU);
13571a5ab3e9SJonas Paulsson 
13581a5ab3e9SJonas Paulsson   return false;
13591a5ab3e9SJonas Paulsson }
13601a5ab3e9SJonas Paulsson 
ParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc,bool RestoreOnFailure)13615f613dfdSUlrich Weigand bool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
13628d5bf042SEric Astor                                      SMLoc &EndLoc, bool RestoreOnFailure) {
13635f613dfdSUlrich Weigand   Register Reg;
13648d5bf042SEric Astor   if (parseRegister(Reg, RestoreOnFailure))
1365dc5ed713SRichard Sandiford     return true;
1366675f8699SRichard Sandiford   if (Reg.Group == RegGR)
1367675f8699SRichard Sandiford     RegNo = SystemZMC::GR64Regs[Reg.Num];
1368675f8699SRichard Sandiford   else if (Reg.Group == RegFP)
1369675f8699SRichard Sandiford     RegNo = SystemZMC::FP64Regs[Reg.Num];
1370a8b04e1cSUlrich Weigand   else if (Reg.Group == RegV)
1371a8b04e1cSUlrich Weigand     RegNo = SystemZMC::VR128Regs[Reg.Num];
1372fffc7110SUlrich Weigand   else if (Reg.Group == RegAR)
1373fffc7110SUlrich Weigand     RegNo = SystemZMC::AR32Regs[Reg.Num];
137403ab2e2bSUlrich Weigand   else if (Reg.Group == RegCR)
137503ab2e2bSUlrich Weigand     RegNo = SystemZMC::CR64Regs[Reg.Num];
13765f613dfdSUlrich Weigand   StartLoc = Reg.StartLoc;
13775f613dfdSUlrich Weigand   EndLoc = Reg.EndLoc;
13785f613dfdSUlrich Weigand   return false;
13795f613dfdSUlrich Weigand }
13805f613dfdSUlrich Weigand 
ParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)13818d5bf042SEric Astor bool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
13828d5bf042SEric Astor                                      SMLoc &EndLoc) {
13838d5bf042SEric Astor   return ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/false);
13848d5bf042SEric Astor }
13858d5bf042SEric Astor 
tryParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)13868d5bf042SEric Astor OperandMatchResultTy SystemZAsmParser::tryParseRegister(unsigned &RegNo,
13878d5bf042SEric Astor                                                         SMLoc &StartLoc,
13888d5bf042SEric Astor                                                         SMLoc &EndLoc) {
13898d5bf042SEric Astor   bool Result =
13908d5bf042SEric Astor       ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/true);
13918d5bf042SEric Astor   bool PendingErrors = getParser().hasPendingError();
13928d5bf042SEric Astor   getParser().clearPendingErrors();
13938d5bf042SEric Astor   if (PendingErrors)
13948d5bf042SEric Astor     return MatchOperand_ParseFail;
13958d5bf042SEric Astor   if (Result)
13968d5bf042SEric Astor     return MatchOperand_NoMatch;
13978d5bf042SEric Astor   return MatchOperand_Success;
13988d5bf042SEric Astor }
13998d5bf042SEric Astor 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)1400960ea3f0SDavid Blaikie bool SystemZAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1401960ea3f0SDavid Blaikie                                         StringRef Name, SMLoc NameLoc,
1402960ea3f0SDavid Blaikie                                         OperandVector &Operands) {
1403f03c21dfSAnirudh Prasad 
1404f03c21dfSAnirudh Prasad   // Apply mnemonic aliases first, before doing anything else, in
1405f03c21dfSAnirudh Prasad   // case the target uses it.
1406bcc1aba6SAnirudh Prasad   applyMnemonicAliases(Name, getAvailableFeatures(), getMAIAssemblerDialect());
1407f03c21dfSAnirudh Prasad 
14085f613dfdSUlrich Weigand   Operands.push_back(SystemZOperand::createToken(Name, NameLoc));
14095f613dfdSUlrich Weigand 
14105f613dfdSUlrich Weigand   // Read the remaining operands.
14115f613dfdSUlrich Weigand   if (getLexer().isNot(AsmToken::EndOfStatement)) {
14125f613dfdSUlrich Weigand     // Read the first operand.
14135f613dfdSUlrich Weigand     if (parseOperand(Operands, Name)) {
14145f613dfdSUlrich Weigand       return true;
14155f613dfdSUlrich Weigand     }
14165f613dfdSUlrich Weigand 
14175f613dfdSUlrich Weigand     // Read any subsequent operands.
14185f613dfdSUlrich Weigand     while (getLexer().is(AsmToken::Comma)) {
14195f613dfdSUlrich Weigand       Parser.Lex();
1420f076da66SAnirudh Prasad 
1421f076da66SAnirudh Prasad       if (isParsingHLASM() && getLexer().is(AsmToken::Space))
1422f076da66SAnirudh Prasad         return Error(
1423f076da66SAnirudh Prasad             Parser.getTok().getLoc(),
1424f076da66SAnirudh Prasad             "No space allowed between comma that separates operand entries");
1425f076da66SAnirudh Prasad 
14265f613dfdSUlrich Weigand       if (parseOperand(Operands, Name)) {
14275f613dfdSUlrich Weigand         return true;
14285f613dfdSUlrich Weigand       }
14295f613dfdSUlrich Weigand     }
1430f076da66SAnirudh Prasad 
1431f076da66SAnirudh Prasad     // Under the HLASM variant, we could have the remark field
1432f076da66SAnirudh Prasad     // The remark field occurs after the operation entries
1433f076da66SAnirudh Prasad     // There is a space that separates the operation entries and the
1434f076da66SAnirudh Prasad     // remark field.
1435f076da66SAnirudh Prasad     if (isParsingHLASM() && getTok().is(AsmToken::Space)) {
1436f076da66SAnirudh Prasad       // We've confirmed that there is a Remark field.
1437f076da66SAnirudh Prasad       StringRef Remark(getLexer().LexUntilEndOfStatement());
1438f076da66SAnirudh Prasad       Parser.Lex();
1439f076da66SAnirudh Prasad 
1440f076da66SAnirudh Prasad       // If there is nothing after the space, then there is nothing to emit
1441f076da66SAnirudh Prasad       // We could have a situation as this:
1442f076da66SAnirudh Prasad       // "  \n"
1443f076da66SAnirudh Prasad       // After lexing above, we will have
1444f076da66SAnirudh Prasad       // "\n"
1445f076da66SAnirudh Prasad       // This isn't an explicit remark field, so we don't have to output
1446f076da66SAnirudh Prasad       // this as a comment.
1447f076da66SAnirudh Prasad       if (Remark.size())
1448f076da66SAnirudh Prasad         // Output the entire Remarks Field as a comment
1449f076da66SAnirudh Prasad         getStreamer().AddComment(Remark);
1450f076da66SAnirudh Prasad     }
1451f076da66SAnirudh Prasad 
14525f613dfdSUlrich Weigand     if (getLexer().isNot(AsmToken::EndOfStatement)) {
14535f613dfdSUlrich Weigand       SMLoc Loc = getLexer().getLoc();
14545f613dfdSUlrich Weigand       return Error(Loc, "unexpected token in argument list");
14555f613dfdSUlrich Weigand     }
14565f613dfdSUlrich Weigand   }
14575f613dfdSUlrich Weigand 
14585f613dfdSUlrich Weigand   // Consume the EndOfStatement.
14595f613dfdSUlrich Weigand   Parser.Lex();
14605f613dfdSUlrich Weigand   return false;
14615f613dfdSUlrich Weigand }
14625f613dfdSUlrich Weigand 
parseOperand(OperandVector & Operands,StringRef Mnemonic)1463960ea3f0SDavid Blaikie bool SystemZAsmParser::parseOperand(OperandVector &Operands,
14645f613dfdSUlrich Weigand                                     StringRef Mnemonic) {
14655f613dfdSUlrich Weigand   // Check if the current operand has a custom associated parser, if so, try to
1466d9001301SUlrich Weigand   // custom parse the operand, or fallback to the general approach.  Force all
1467d9001301SUlrich Weigand   // features to be available during the operand check, or else we will fail to
1468d9001301SUlrich Weigand   // find the custom parser, and then we will later get an InvalidOperand error
1469d9001301SUlrich Weigand   // instead of a MissingFeature errror.
1470e98944edSStanislav Mekhanoshin   FeatureBitset AvailableFeatures = getAvailableFeatures();
1471e98944edSStanislav Mekhanoshin   FeatureBitset All;
1472e98944edSStanislav Mekhanoshin   All.set();
1473e98944edSStanislav Mekhanoshin   setAvailableFeatures(All);
14745f613dfdSUlrich Weigand   OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1475d9001301SUlrich Weigand   setAvailableFeatures(AvailableFeatures);
14765f613dfdSUlrich Weigand   if (ResTy == MatchOperand_Success)
14775f613dfdSUlrich Weigand     return false;
14785f613dfdSUlrich Weigand 
14795f613dfdSUlrich Weigand   // If there wasn't a custom match, try the generic matcher below. Otherwise,
14805f613dfdSUlrich Weigand   // there was a match, but an error occurred, in which case, just return that
14815f613dfdSUlrich Weigand   // the operand parsing failed.
14825f613dfdSUlrich Weigand   if (ResTy == MatchOperand_ParseFail)
14835f613dfdSUlrich Weigand     return true;
14845f613dfdSUlrich Weigand 
1485dc5ed713SRichard Sandiford   // Check for a register.  All real register operands should have used
1486dc5ed713SRichard Sandiford   // a context-dependent parse routine, which gives the required register
1487dc5ed713SRichard Sandiford   // class.  The code is here to mop up other cases, like those where
1488dc5ed713SRichard Sandiford   // the instruction isn't recognized.
14893ed6a6f6SAnirudh Prasad   if (isParsingATT() && Parser.getTok().is(AsmToken::Percent)) {
1490dc5ed713SRichard Sandiford     Register Reg;
1491dc5ed713SRichard Sandiford     if (parseRegister(Reg))
1492dc5ed713SRichard Sandiford       return true;
1493dc5ed713SRichard Sandiford     Operands.push_back(SystemZOperand::createInvalid(Reg.StartLoc, Reg.EndLoc));
1494dc5ed713SRichard Sandiford     return false;
1495dc5ed713SRichard Sandiford   }
1496dc5ed713SRichard Sandiford 
1497dc5ed713SRichard Sandiford   // The only other type of operand is an immediate or address.  As above,
1498dc5ed713SRichard Sandiford   // real address operands should have used a context-dependent parse routine,
1499dc5ed713SRichard Sandiford   // so we treat any plain expression as an immediate.
15005f613dfdSUlrich Weigand   SMLoc StartLoc = Parser.getTok().getLoc();
1501ec5d779eSUlrich Weigand   Register Reg1, Reg2;
1502ec5d779eSUlrich Weigand   bool HaveReg1, HaveReg2;
1503ec5d779eSUlrich Weigand   const MCExpr *Expr;
1504ec5d779eSUlrich Weigand   const MCExpr *Length;
1505cca8578eSUlrich Weigand   if (parseAddress(HaveReg1, Reg1, HaveReg2, Reg2, Expr, Length,
1506cca8578eSUlrich Weigand                    /*HasLength*/ true, /*HasVectorIndex*/ true))
150775d2f1b1SUlrich Weigand     return true;
1508ec5d779eSUlrich Weigand   // If the register combination is not valid for any instruction, reject it.
1509ec5d779eSUlrich Weigand   // Otherwise, fall back to reporting an unrecognized instruction.
1510ec5d779eSUlrich Weigand   if (HaveReg1 && Reg1.Group != RegGR && Reg1.Group != RegV
1511ec5d779eSUlrich Weigand       && parseAddressRegister(Reg1))
151275d2f1b1SUlrich Weigand     return true;
1513ec5d779eSUlrich Weigand   if (HaveReg2 && parseAddressRegister(Reg2))
151475d2f1b1SUlrich Weigand     return true;
15155f613dfdSUlrich Weigand 
15165f613dfdSUlrich Weigand   SMLoc EndLoc =
15175f613dfdSUlrich Weigand     SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1518ec5d779eSUlrich Weigand   if (HaveReg1 || HaveReg2 || Length)
1519dc5ed713SRichard Sandiford     Operands.push_back(SystemZOperand::createInvalid(StartLoc, EndLoc));
1520dc5ed713SRichard Sandiford   else
15215f613dfdSUlrich Weigand     Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));
15225f613dfdSUlrich Weigand   return false;
15235f613dfdSUlrich Weigand }
15245f613dfdSUlrich Weigand 
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)1525960ea3f0SDavid Blaikie bool SystemZAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1526960ea3f0SDavid Blaikie                                                OperandVector &Operands,
1527960ea3f0SDavid Blaikie                                                MCStreamer &Out,
152826bb14e6STim Northover                                                uint64_t &ErrorInfo,
15295f613dfdSUlrich Weigand                                                bool MatchingInlineAsm) {
15305f613dfdSUlrich Weigand   MCInst Inst;
15315f613dfdSUlrich Weigand   unsigned MatchResult;
15325f613dfdSUlrich Weigand 
1533bcc1aba6SAnirudh Prasad   unsigned Dialect = getMAIAssemblerDialect();
1534bcc1aba6SAnirudh Prasad 
1535e98944edSStanislav Mekhanoshin   FeatureBitset MissingFeatures;
1536bcc1aba6SAnirudh Prasad   MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1537bcc1aba6SAnirudh Prasad                                      MatchingInlineAsm, Dialect);
15385f613dfdSUlrich Weigand   switch (MatchResult) {
15395f613dfdSUlrich Weigand   case Match_Success:
15405f613dfdSUlrich Weigand     Inst.setLoc(IDLoc);
1541bcd24b2dSFangrui Song     Out.emitInstruction(Inst, getSTI());
15425f613dfdSUlrich Weigand     return false;
15435f613dfdSUlrich Weigand 
15445f613dfdSUlrich Weigand   case Match_MissingFeature: {
1545e98944edSStanislav Mekhanoshin     assert(MissingFeatures.any() && "Unknown missing feature!");
15465f613dfdSUlrich Weigand     // Special case the error message for the very common case where only
15475f613dfdSUlrich Weigand     // a single subtarget feature is missing
15485f613dfdSUlrich Weigand     std::string Msg = "instruction requires:";
1549e98944edSStanislav Mekhanoshin     for (unsigned I = 0, E = MissingFeatures.size(); I != E; ++I) {
1550e98944edSStanislav Mekhanoshin       if (MissingFeatures[I]) {
15515f613dfdSUlrich Weigand         Msg += " ";
1552e98944edSStanislav Mekhanoshin         Msg += getSubtargetFeatureName(I);
15535f613dfdSUlrich Weigand       }
15545f613dfdSUlrich Weigand     }
15555f613dfdSUlrich Weigand     return Error(IDLoc, Msg);
15565f613dfdSUlrich Weigand   }
15575f613dfdSUlrich Weigand 
15585f613dfdSUlrich Weigand   case Match_InvalidOperand: {
15595f613dfdSUlrich Weigand     SMLoc ErrorLoc = IDLoc;
156026bb14e6STim Northover     if (ErrorInfo != ~0ULL) {
15615f613dfdSUlrich Weigand       if (ErrorInfo >= Operands.size())
15625f613dfdSUlrich Weigand         return Error(IDLoc, "too few operands for instruction");
15635f613dfdSUlrich Weigand 
1564960ea3f0SDavid Blaikie       ErrorLoc = ((SystemZOperand &)*Operands[ErrorInfo]).getStartLoc();
15655f613dfdSUlrich Weigand       if (ErrorLoc == SMLoc())
15665f613dfdSUlrich Weigand         ErrorLoc = IDLoc;
15675f613dfdSUlrich Weigand     }
15685f613dfdSUlrich Weigand     return Error(ErrorLoc, "invalid operand for instruction");
15695f613dfdSUlrich Weigand   }
15705f613dfdSUlrich Weigand 
1571d667417eSJonas Paulsson   case Match_MnemonicFail: {
1572e98944edSStanislav Mekhanoshin     FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1573d667417eSJonas Paulsson     std::string Suggestion = SystemZMnemonicSpellCheck(
1574bcc1aba6SAnirudh Prasad         ((SystemZOperand &)*Operands[0]).getToken(), FBS, Dialect);
1575d667417eSJonas Paulsson     return Error(IDLoc, "invalid instruction" + Suggestion,
1576d667417eSJonas Paulsson                  ((SystemZOperand &)*Operands[0]).getLocRange());
1577d667417eSJonas Paulsson   }
15785f613dfdSUlrich Weigand   }
15795f613dfdSUlrich Weigand 
15805f613dfdSUlrich Weigand   llvm_unreachable("Unexpected match type");
15815f613dfdSUlrich Weigand }
15825f613dfdSUlrich Weigand 
158358eba099SAlex Bradbury OperandMatchResultTy
parsePCRel(OperandVector & Operands,int64_t MinVal,int64_t MaxVal,bool AllowTLS)1584960ea3f0SDavid Blaikie SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal,
15857bdd7c23SUlrich Weigand                              int64_t MaxVal, bool AllowTLS) {
15861fb5883dSRichard Sandiford   MCContext &Ctx = getContext();
15871fb5883dSRichard Sandiford   MCStreamer &Out = getStreamer();
15881fb5883dSRichard Sandiford   const MCExpr *Expr;
15891fb5883dSRichard Sandiford   SMLoc StartLoc = Parser.getTok().getLoc();
15901fb5883dSRichard Sandiford   if (getParser().parseExpression(Expr))
15911fb5883dSRichard Sandiford     return MatchOperand_NoMatch;
15921fb5883dSRichard Sandiford 
1593*7070c6a9SIlya Leoshkevich   auto isOutOfRangeConstant = [&](const MCExpr *E, bool Negate) -> bool {
1594580310ffSJonas Paulsson     if (auto *CE = dyn_cast<MCConstantExpr>(E)) {
1595580310ffSJonas Paulsson       int64_t Value = CE->getValue();
1596*7070c6a9SIlya Leoshkevich       if (Negate)
1597*7070c6a9SIlya Leoshkevich         Value = -Value;
1598580310ffSJonas Paulsson       if ((Value & 1) || Value < MinVal || Value > MaxVal)
1599580310ffSJonas Paulsson         return true;
1600580310ffSJonas Paulsson     }
1601580310ffSJonas Paulsson     return false;
1602580310ffSJonas Paulsson   };
1603580310ffSJonas Paulsson 
16041fb5883dSRichard Sandiford   // For consistency with the GNU assembler, treat immediates as offsets
16051fb5883dSRichard Sandiford   // from ".".
160621f5d68aSRichard Sandiford   if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
1607ca02fab7SAnirudh Prasad     if (isParsingHLASM()) {
1608ca02fab7SAnirudh Prasad       Error(StartLoc, "Expected PC-relative expression");
1609ca02fab7SAnirudh Prasad       return MatchOperand_ParseFail;
1610ca02fab7SAnirudh Prasad     }
1611*7070c6a9SIlya Leoshkevich     if (isOutOfRangeConstant(CE, false)) {
16121fb5883dSRichard Sandiford       Error(StartLoc, "offset out of range");
16131fb5883dSRichard Sandiford       return MatchOperand_ParseFail;
16141fb5883dSRichard Sandiford     }
1615580310ffSJonas Paulsson     int64_t Value = CE->getValue();
16166f482000SJim Grosbach     MCSymbol *Sym = Ctx.createTempSymbol();
16176d2d589bSFangrui Song     Out.emitLabel(Sym);
161813760bd1SJim Grosbach     const MCExpr *Base = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
16191fb5883dSRichard Sandiford                                                  Ctx);
162013760bd1SJim Grosbach     Expr = Value == 0 ? Base : MCBinaryExpr::createAdd(Base, Expr, Ctx);
16211fb5883dSRichard Sandiford   }
16221fb5883dSRichard Sandiford 
1623580310ffSJonas Paulsson   // For consistency with the GNU assembler, conservatively assume that a
1624580310ffSJonas Paulsson   // constant offset must by itself be within the given size range.
1625580310ffSJonas Paulsson   if (const auto *BE = dyn_cast<MCBinaryExpr>(Expr))
1626*7070c6a9SIlya Leoshkevich     if (isOutOfRangeConstant(BE->getLHS(), false) ||
1627*7070c6a9SIlya Leoshkevich         isOutOfRangeConstant(BE->getRHS(),
1628*7070c6a9SIlya Leoshkevich                              BE->getOpcode() == MCBinaryExpr::Sub)) {
1629580310ffSJonas Paulsson       Error(StartLoc, "offset out of range");
1630580310ffSJonas Paulsson       return MatchOperand_ParseFail;
1631580310ffSJonas Paulsson     }
1632580310ffSJonas Paulsson 
16337bdd7c23SUlrich Weigand   // Optionally match :tls_gdcall: or :tls_ldcall: followed by a TLS symbol.
16347bdd7c23SUlrich Weigand   const MCExpr *Sym = nullptr;
16357bdd7c23SUlrich Weigand   if (AllowTLS && getLexer().is(AsmToken::Colon)) {
16367bdd7c23SUlrich Weigand     Parser.Lex();
16377bdd7c23SUlrich Weigand 
16387bdd7c23SUlrich Weigand     if (Parser.getTok().isNot(AsmToken::Identifier)) {
16397bdd7c23SUlrich Weigand       Error(Parser.getTok().getLoc(), "unexpected token");
16407bdd7c23SUlrich Weigand       return MatchOperand_ParseFail;
16417bdd7c23SUlrich Weigand     }
16427bdd7c23SUlrich Weigand 
16437bdd7c23SUlrich Weigand     MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
16447bdd7c23SUlrich Weigand     StringRef Name = Parser.getTok().getString();
16457bdd7c23SUlrich Weigand     if (Name == "tls_gdcall")
16467bdd7c23SUlrich Weigand       Kind = MCSymbolRefExpr::VK_TLSGD;
16477bdd7c23SUlrich Weigand     else if (Name == "tls_ldcall")
16487bdd7c23SUlrich Weigand       Kind = MCSymbolRefExpr::VK_TLSLDM;
16497bdd7c23SUlrich Weigand     else {
16507bdd7c23SUlrich Weigand       Error(Parser.getTok().getLoc(), "unknown TLS tag");
16517bdd7c23SUlrich Weigand       return MatchOperand_ParseFail;
16527bdd7c23SUlrich Weigand     }
16537bdd7c23SUlrich Weigand     Parser.Lex();
16547bdd7c23SUlrich Weigand 
16557bdd7c23SUlrich Weigand     if (Parser.getTok().isNot(AsmToken::Colon)) {
16567bdd7c23SUlrich Weigand       Error(Parser.getTok().getLoc(), "unexpected token");
16577bdd7c23SUlrich Weigand       return MatchOperand_ParseFail;
16587bdd7c23SUlrich Weigand     }
16597bdd7c23SUlrich Weigand     Parser.Lex();
16607bdd7c23SUlrich Weigand 
16617bdd7c23SUlrich Weigand     if (Parser.getTok().isNot(AsmToken::Identifier)) {
16627bdd7c23SUlrich Weigand       Error(Parser.getTok().getLoc(), "unexpected token");
16637bdd7c23SUlrich Weigand       return MatchOperand_ParseFail;
16647bdd7c23SUlrich Weigand     }
16657bdd7c23SUlrich Weigand 
16667bdd7c23SUlrich Weigand     StringRef Identifier = Parser.getTok().getString();
166713760bd1SJim Grosbach     Sym = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(Identifier),
16687bdd7c23SUlrich Weigand                                   Kind, Ctx);
16697bdd7c23SUlrich Weigand     Parser.Lex();
16707bdd7c23SUlrich Weigand   }
16717bdd7c23SUlrich Weigand 
16721fb5883dSRichard Sandiford   SMLoc EndLoc =
16731fb5883dSRichard Sandiford     SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
16747bdd7c23SUlrich Weigand 
16757bdd7c23SUlrich Weigand   if (AllowTLS)
16767bdd7c23SUlrich Weigand     Operands.push_back(SystemZOperand::createImmTLS(Expr, Sym,
16777bdd7c23SUlrich Weigand                                                     StartLoc, EndLoc));
16787bdd7c23SUlrich Weigand   else
16791fb5883dSRichard Sandiford     Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));
16807bdd7c23SUlrich Weigand 
16811fb5883dSRichard Sandiford   return MatchOperand_Success;
16821fb5883dSRichard Sandiford }
16831fb5883dSRichard Sandiford 
isLabel(AsmToken & Token)16847a46d34aSAnirudh Prasad bool SystemZAsmParser::isLabel(AsmToken &Token) {
16857da22dfcSAnirudh Prasad   if (isParsingATT())
16867a46d34aSAnirudh Prasad     return true;
16877a46d34aSAnirudh Prasad 
16887a46d34aSAnirudh Prasad   // HLASM labels are ordinary symbols.
16897a46d34aSAnirudh Prasad   // An HLASM label always starts at column 1.
16907a46d34aSAnirudh Prasad   // An ordinary symbol syntax is laid out as follows:
16917a46d34aSAnirudh Prasad   // Rules:
16927a46d34aSAnirudh Prasad   // 1. Has to start with an "alphabetic character". Can be followed by up to
16937a46d34aSAnirudh Prasad   //    62 alphanumeric characters. An "alphabetic character", in this scenario,
16947a46d34aSAnirudh Prasad   //    is a letter from 'A' through 'Z', or from 'a' through 'z',
16957a46d34aSAnirudh Prasad   //    or '$', '_', '#', or '@'
16967a46d34aSAnirudh Prasad   // 2. Labels are case-insensitive. E.g. "lab123", "LAB123", "lAb123", etc.
16977a46d34aSAnirudh Prasad   //    are all treated as the same symbol. However, the processing for the case
16987a46d34aSAnirudh Prasad   //    folding will not be done in this function.
16997a46d34aSAnirudh Prasad   StringRef RawLabel = Token.getString();
17007a46d34aSAnirudh Prasad   SMLoc Loc = Token.getLoc();
17017a46d34aSAnirudh Prasad 
17027a46d34aSAnirudh Prasad   // An HLASM label cannot be empty.
17037a46d34aSAnirudh Prasad   if (!RawLabel.size())
17047a46d34aSAnirudh Prasad     return !Error(Loc, "HLASM Label cannot be empty");
17057a46d34aSAnirudh Prasad 
17067a46d34aSAnirudh Prasad   // An HLASM label cannot exceed greater than 63 characters.
17077a46d34aSAnirudh Prasad   if (RawLabel.size() > 63)
17087a46d34aSAnirudh Prasad     return !Error(Loc, "Maximum length for HLASM Label is 63 characters");
17097a46d34aSAnirudh Prasad 
17107a46d34aSAnirudh Prasad   // A label must start with an "alphabetic character".
17117a46d34aSAnirudh Prasad   if (!isHLASMAlpha(RawLabel[0]))
17127a46d34aSAnirudh Prasad     return !Error(Loc, "HLASM Label has to start with an alphabetic "
17137a46d34aSAnirudh Prasad                        "character or the underscore character");
17147a46d34aSAnirudh Prasad 
17157a46d34aSAnirudh Prasad   // Now, we've established that the length is valid
17167a46d34aSAnirudh Prasad   // and the first character is alphabetic.
17177a46d34aSAnirudh Prasad   // Check whether remaining string is alphanumeric.
17187a46d34aSAnirudh Prasad   for (unsigned I = 1; I < RawLabel.size(); ++I)
17197a46d34aSAnirudh Prasad     if (!isHLASMAlnum(RawLabel[I]))
17207a46d34aSAnirudh Prasad       return !Error(Loc, "HLASM Label has to be alphanumeric");
17217a46d34aSAnirudh Prasad 
17227a46d34aSAnirudh Prasad   return true;
17237a46d34aSAnirudh Prasad }
17247a46d34aSAnirudh Prasad 
17255f613dfdSUlrich Weigand // Force static initialization.
LLVMInitializeSystemZAsmParser()17260dbcb363STom Stellard extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmParser() {
1727f42454b9SMehdi Amini   RegisterMCAsmParser<SystemZAsmParser> X(getTheSystemZTarget());
17285f613dfdSUlrich Weigand }
1729