xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- SystemZAsmParser.cpp - Parse SystemZ assembly instructions --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MCTargetDesc/SystemZInstPrinter.h"
10fe6060f1SDimitry Andric #include "MCTargetDesc/SystemZMCAsmInfo.h"
110b57cec5SDimitry Andric #include "MCTargetDesc/SystemZMCTargetDesc.h"
12349cc55cSDimitry Andric #include "SystemZTargetStreamer.h"
130b57cec5SDimitry Andric #include "TargetInfo/SystemZTargetInfo.h"
140b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
150b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
1606c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
170b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
18fe6060f1SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
2381ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
31349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
320b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
330b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
340b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
350b57cec5SDimitry Andric #include <algorithm>
360b57cec5SDimitry Andric #include <cassert>
370b57cec5SDimitry Andric #include <cstddef>
380b57cec5SDimitry Andric #include <cstdint>
390b57cec5SDimitry Andric #include <iterator>
400b57cec5SDimitry Andric #include <memory>
410b57cec5SDimitry Andric #include <string>
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric using namespace llvm;
440b57cec5SDimitry Andric 
45349cc55cSDimitry Andric // Return true if Expr is in the range [MinValue, MaxValue]. If AllowSymbol
46349cc55cSDimitry Andric // is true any MCExpr is accepted (address displacement).
inRange(const MCExpr * Expr,int64_t MinValue,int64_t MaxValue,bool AllowSymbol=false)47349cc55cSDimitry Andric static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue,
48349cc55cSDimitry Andric                     bool AllowSymbol = false) {
490b57cec5SDimitry Andric   if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
500b57cec5SDimitry Andric     int64_t Value = CE->getValue();
510b57cec5SDimitry Andric     return Value >= MinValue && Value <= MaxValue;
520b57cec5SDimitry Andric   }
53349cc55cSDimitry Andric   return AllowSymbol;
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric namespace {
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric enum RegisterKind {
590b57cec5SDimitry Andric   GR32Reg,
600b57cec5SDimitry Andric   GRH32Reg,
610b57cec5SDimitry Andric   GR64Reg,
620b57cec5SDimitry Andric   GR128Reg,
630b57cec5SDimitry Andric   FP32Reg,
640b57cec5SDimitry Andric   FP64Reg,
650b57cec5SDimitry Andric   FP128Reg,
660b57cec5SDimitry Andric   VR32Reg,
670b57cec5SDimitry Andric   VR64Reg,
680b57cec5SDimitry Andric   VR128Reg,
690b57cec5SDimitry Andric   AR32Reg,
700b57cec5SDimitry Andric   CR64Reg,
710b57cec5SDimitry Andric };
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric enum MemoryKind {
740b57cec5SDimitry Andric   BDMem,
750b57cec5SDimitry Andric   BDXMem,
760b57cec5SDimitry Andric   BDLMem,
770b57cec5SDimitry Andric   BDRMem,
780b57cec5SDimitry Andric   BDVMem
790b57cec5SDimitry Andric };
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric class SystemZOperand : public MCParsedAsmOperand {
820b57cec5SDimitry Andric private:
830b57cec5SDimitry Andric   enum OperandKind {
840b57cec5SDimitry Andric     KindInvalid,
850b57cec5SDimitry Andric     KindToken,
860b57cec5SDimitry Andric     KindReg,
870b57cec5SDimitry Andric     KindImm,
880b57cec5SDimitry Andric     KindImmTLS,
890b57cec5SDimitry Andric     KindMem
900b57cec5SDimitry Andric   };
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   OperandKind Kind;
930b57cec5SDimitry Andric   SMLoc StartLoc, EndLoc;
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // A string of length Length, starting at Data.
960b57cec5SDimitry Andric   struct TokenOp {
970b57cec5SDimitry Andric     const char *Data;
980b57cec5SDimitry Andric     unsigned Length;
990b57cec5SDimitry Andric   };
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   // LLVM register Num, which has kind Kind.  In some ways it might be
1020b57cec5SDimitry Andric   // easier for this class to have a register bank (general, floating-point
1030b57cec5SDimitry Andric   // or access) and a raw register number (0-15).  This would postpone the
1040b57cec5SDimitry Andric   // interpretation of the operand to the add*() methods and avoid the need
1050b57cec5SDimitry Andric   // for context-dependent parsing.  However, we do things the current way
1060b57cec5SDimitry Andric   // because of the virtual getReg() method, which needs to distinguish
1070b57cec5SDimitry Andric   // between (say) %r0 used as a single register and %r0 used as a pair.
1080b57cec5SDimitry Andric   // Context-dependent parsing can also give us slightly better error
1090b57cec5SDimitry Andric   // messages when invalid pairs like %r1 are used.
1100b57cec5SDimitry Andric   struct RegOp {
1110b57cec5SDimitry Andric     RegisterKind Kind;
1120b57cec5SDimitry Andric     unsigned Num;
1130b57cec5SDimitry Andric   };
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   // Base + Disp + Index, where Base and Index are LLVM registers or 0.
1160b57cec5SDimitry Andric   // MemKind says what type of memory this is and RegKind says what type
1175ffd83dbSDimitry Andric   // the base register has (GR32Reg or GR64Reg).  Length is the operand
1180b57cec5SDimitry Andric   // length for D(L,B)-style operands, otherwise it is null.
1190b57cec5SDimitry Andric   struct MemOp {
1200b57cec5SDimitry Andric     unsigned Base : 12;
1210b57cec5SDimitry Andric     unsigned Index : 12;
1220b57cec5SDimitry Andric     unsigned MemKind : 4;
1230b57cec5SDimitry Andric     unsigned RegKind : 4;
1240b57cec5SDimitry Andric     const MCExpr *Disp;
1250b57cec5SDimitry Andric     union {
1260b57cec5SDimitry Andric       const MCExpr *Imm;
1270b57cec5SDimitry Andric       unsigned Reg;
1280b57cec5SDimitry Andric     } Length;
1290b57cec5SDimitry Andric   };
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   // Imm is an immediate operand, and Sym is an optional TLS symbol
1320b57cec5SDimitry Andric   // for use with a __tls_get_offset marker relocation.
1330b57cec5SDimitry Andric   struct ImmTLSOp {
1340b57cec5SDimitry Andric     const MCExpr *Imm;
1350b57cec5SDimitry Andric     const MCExpr *Sym;
1360b57cec5SDimitry Andric   };
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   union {
1390b57cec5SDimitry Andric     TokenOp Token;
1400b57cec5SDimitry Andric     RegOp Reg;
1410b57cec5SDimitry Andric     const MCExpr *Imm;
1420b57cec5SDimitry Andric     ImmTLSOp ImmTLS;
1430b57cec5SDimitry Andric     MemOp Mem;
1440b57cec5SDimitry Andric   };
1450b57cec5SDimitry Andric 
addExpr(MCInst & Inst,const MCExpr * Expr) const1460b57cec5SDimitry Andric   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1470b57cec5SDimitry Andric     // Add as immediates when possible.  Null MCExpr = 0.
1480b57cec5SDimitry Andric     if (!Expr)
1490b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createImm(0));
1500b57cec5SDimitry Andric     else if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
1510b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createImm(CE->getValue()));
1520b57cec5SDimitry Andric     else
1530b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createExpr(Expr));
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric public:
SystemZOperand(OperandKind Kind,SMLoc StartLoc,SMLoc EndLoc)1575f757f3fSDimitry Andric   SystemZOperand(OperandKind Kind, SMLoc StartLoc, SMLoc EndLoc)
1585f757f3fSDimitry Andric       : Kind(Kind), StartLoc(StartLoc), EndLoc(EndLoc) {}
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   // Create particular kinds of operand.
createInvalid(SMLoc StartLoc,SMLoc EndLoc)1610b57cec5SDimitry Andric   static std::unique_ptr<SystemZOperand> createInvalid(SMLoc StartLoc,
1620b57cec5SDimitry Andric                                                        SMLoc EndLoc) {
1638bcb0991SDimitry Andric     return std::make_unique<SystemZOperand>(KindInvalid, StartLoc, EndLoc);
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric 
createToken(StringRef Str,SMLoc Loc)1660b57cec5SDimitry Andric   static std::unique_ptr<SystemZOperand> createToken(StringRef Str, SMLoc Loc) {
1678bcb0991SDimitry Andric     auto Op = std::make_unique<SystemZOperand>(KindToken, Loc, Loc);
1680b57cec5SDimitry Andric     Op->Token.Data = Str.data();
1690b57cec5SDimitry Andric     Op->Token.Length = Str.size();
1700b57cec5SDimitry Andric     return Op;
1710b57cec5SDimitry Andric   }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   static std::unique_ptr<SystemZOperand>
createReg(RegisterKind Kind,unsigned Num,SMLoc StartLoc,SMLoc EndLoc)1740b57cec5SDimitry Andric   createReg(RegisterKind Kind, unsigned Num, SMLoc StartLoc, SMLoc EndLoc) {
1758bcb0991SDimitry Andric     auto Op = std::make_unique<SystemZOperand>(KindReg, StartLoc, EndLoc);
1760b57cec5SDimitry Andric     Op->Reg.Kind = Kind;
1770b57cec5SDimitry Andric     Op->Reg.Num = Num;
1780b57cec5SDimitry Andric     return Op;
1790b57cec5SDimitry Andric   }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   static std::unique_ptr<SystemZOperand>
createImm(const MCExpr * Expr,SMLoc StartLoc,SMLoc EndLoc)1820b57cec5SDimitry Andric   createImm(const MCExpr *Expr, SMLoc StartLoc, SMLoc EndLoc) {
1838bcb0991SDimitry Andric     auto Op = std::make_unique<SystemZOperand>(KindImm, StartLoc, EndLoc);
1840b57cec5SDimitry Andric     Op->Imm = Expr;
1850b57cec5SDimitry Andric     return Op;
1860b57cec5SDimitry Andric   }
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   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)1890b57cec5SDimitry Andric   createMem(MemoryKind MemKind, RegisterKind RegKind, unsigned Base,
1900b57cec5SDimitry Andric             const MCExpr *Disp, unsigned Index, const MCExpr *LengthImm,
1910b57cec5SDimitry Andric             unsigned LengthReg, SMLoc StartLoc, SMLoc EndLoc) {
1928bcb0991SDimitry Andric     auto Op = std::make_unique<SystemZOperand>(KindMem, StartLoc, EndLoc);
1930b57cec5SDimitry Andric     Op->Mem.MemKind = MemKind;
1940b57cec5SDimitry Andric     Op->Mem.RegKind = RegKind;
1950b57cec5SDimitry Andric     Op->Mem.Base = Base;
1960b57cec5SDimitry Andric     Op->Mem.Index = Index;
1970b57cec5SDimitry Andric     Op->Mem.Disp = Disp;
1980b57cec5SDimitry Andric     if (MemKind == BDLMem)
1990b57cec5SDimitry Andric       Op->Mem.Length.Imm = LengthImm;
2000b57cec5SDimitry Andric     if (MemKind == BDRMem)
2010b57cec5SDimitry Andric       Op->Mem.Length.Reg = LengthReg;
2020b57cec5SDimitry Andric     return Op;
2030b57cec5SDimitry Andric   }
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   static std::unique_ptr<SystemZOperand>
createImmTLS(const MCExpr * Imm,const MCExpr * Sym,SMLoc StartLoc,SMLoc EndLoc)2060b57cec5SDimitry Andric   createImmTLS(const MCExpr *Imm, const MCExpr *Sym,
2070b57cec5SDimitry Andric                SMLoc StartLoc, SMLoc EndLoc) {
2088bcb0991SDimitry Andric     auto Op = std::make_unique<SystemZOperand>(KindImmTLS, StartLoc, EndLoc);
2090b57cec5SDimitry Andric     Op->ImmTLS.Imm = Imm;
2100b57cec5SDimitry Andric     Op->ImmTLS.Sym = Sym;
2110b57cec5SDimitry Andric     return Op;
2120b57cec5SDimitry Andric   }
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   // Token operands
isToken() const2150b57cec5SDimitry Andric   bool isToken() const override {
2160b57cec5SDimitry Andric     return Kind == KindToken;
2170b57cec5SDimitry Andric   }
getToken() const2180b57cec5SDimitry Andric   StringRef getToken() const {
2190b57cec5SDimitry Andric     assert(Kind == KindToken && "Not a token");
2200b57cec5SDimitry Andric     return StringRef(Token.Data, Token.Length);
2210b57cec5SDimitry Andric   }
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   // Register operands.
isReg() const2240b57cec5SDimitry Andric   bool isReg() const override {
2250b57cec5SDimitry Andric     return Kind == KindReg;
2260b57cec5SDimitry Andric   }
isReg(RegisterKind RegKind) const2270b57cec5SDimitry Andric   bool isReg(RegisterKind RegKind) const {
2280b57cec5SDimitry Andric     return Kind == KindReg && Reg.Kind == RegKind;
2290b57cec5SDimitry Andric   }
getReg() const230*0fca6ea1SDimitry Andric   MCRegister getReg() const override {
2310b57cec5SDimitry Andric     assert(Kind == KindReg && "Not a register");
2320b57cec5SDimitry Andric     return Reg.Num;
2330b57cec5SDimitry Andric   }
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   // Immediate operands.
isImm() const2360b57cec5SDimitry Andric   bool isImm() const override {
2370b57cec5SDimitry Andric     return Kind == KindImm;
2380b57cec5SDimitry Andric   }
isImm(int64_t MinValue,int64_t MaxValue) const2390b57cec5SDimitry Andric   bool isImm(int64_t MinValue, int64_t MaxValue) const {
24006c3fb27SDimitry Andric     return Kind == KindImm && inRange(Imm, MinValue, MaxValue, true);
2410b57cec5SDimitry Andric   }
getImm() const2420b57cec5SDimitry Andric   const MCExpr *getImm() const {
2430b57cec5SDimitry Andric     assert(Kind == KindImm && "Not an immediate");
2440b57cec5SDimitry Andric     return Imm;
2450b57cec5SDimitry Andric   }
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   // Immediate operands with optional TLS symbol.
isImmTLS() const2480b57cec5SDimitry Andric   bool isImmTLS() const {
2490b57cec5SDimitry Andric     return Kind == KindImmTLS;
2500b57cec5SDimitry Andric   }
2510b57cec5SDimitry Andric 
getImmTLS() const2520b57cec5SDimitry Andric   const ImmTLSOp getImmTLS() const {
2530b57cec5SDimitry Andric     assert(Kind == KindImmTLS && "Not a TLS immediate");
2540b57cec5SDimitry Andric     return ImmTLS;
2550b57cec5SDimitry Andric   }
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   // Memory operands.
isMem() const2580b57cec5SDimitry Andric   bool isMem() const override {
2590b57cec5SDimitry Andric     return Kind == KindMem;
2600b57cec5SDimitry Andric   }
isMem(MemoryKind MemKind) const2610b57cec5SDimitry Andric   bool isMem(MemoryKind MemKind) const {
2620b57cec5SDimitry Andric     return (Kind == KindMem &&
2630b57cec5SDimitry Andric             (Mem.MemKind == MemKind ||
2640b57cec5SDimitry Andric              // A BDMem can be treated as a BDXMem in which the index
2650b57cec5SDimitry Andric              // register field is 0.
2660b57cec5SDimitry Andric              (Mem.MemKind == BDMem && MemKind == BDXMem)));
2670b57cec5SDimitry Andric   }
isMem(MemoryKind MemKind,RegisterKind RegKind) const2680b57cec5SDimitry Andric   bool isMem(MemoryKind MemKind, RegisterKind RegKind) const {
2690b57cec5SDimitry Andric     return isMem(MemKind) && Mem.RegKind == RegKind;
2700b57cec5SDimitry Andric   }
isMemDisp12(MemoryKind MemKind,RegisterKind RegKind) const2710b57cec5SDimitry Andric   bool isMemDisp12(MemoryKind MemKind, RegisterKind RegKind) const {
272349cc55cSDimitry Andric     return isMem(MemKind, RegKind) && inRange(Mem.Disp, 0, 0xfff, true);
2730b57cec5SDimitry Andric   }
isMemDisp20(MemoryKind MemKind,RegisterKind RegKind) const2740b57cec5SDimitry Andric   bool isMemDisp20(MemoryKind MemKind, RegisterKind RegKind) const {
275349cc55cSDimitry Andric     return isMem(MemKind, RegKind) && inRange(Mem.Disp, -524288, 524287, true);
2760b57cec5SDimitry Andric   }
isMemDisp12Len4(RegisterKind RegKind) const2770b57cec5SDimitry Andric   bool isMemDisp12Len4(RegisterKind RegKind) const {
2780b57cec5SDimitry Andric     return isMemDisp12(BDLMem, RegKind) && inRange(Mem.Length.Imm, 1, 0x10);
2790b57cec5SDimitry Andric   }
isMemDisp12Len8(RegisterKind RegKind) const2800b57cec5SDimitry Andric   bool isMemDisp12Len8(RegisterKind RegKind) const {
2810b57cec5SDimitry Andric     return isMemDisp12(BDLMem, RegKind) && inRange(Mem.Length.Imm, 1, 0x100);
2820b57cec5SDimitry Andric   }
2830b57cec5SDimitry Andric 
getMem() const2840b57cec5SDimitry Andric   const MemOp& getMem() const {
2850b57cec5SDimitry Andric     assert(Kind == KindMem && "Not a Mem operand");
2860b57cec5SDimitry Andric     return Mem;
2870b57cec5SDimitry Andric   }
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   // Override MCParsedAsmOperand.
getStartLoc() const2900b57cec5SDimitry Andric   SMLoc getStartLoc() const override { return StartLoc; }
getEndLoc() const2910b57cec5SDimitry Andric   SMLoc getEndLoc() const override { return EndLoc; }
2920b57cec5SDimitry Andric   void print(raw_ostream &OS) const override;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   /// getLocRange - Get the range between the first and last token of this
2950b57cec5SDimitry Andric   /// operand.
getLocRange() const2960b57cec5SDimitry Andric   SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric   // Used by the TableGen code to add particular types of operand
2990b57cec5SDimitry Andric   // to an instruction.
addRegOperands(MCInst & Inst,unsigned N) const3000b57cec5SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const {
3010b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands");
3020b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getReg()));
3030b57cec5SDimitry Andric   }
addImmOperands(MCInst & Inst,unsigned N) const3040b57cec5SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const {
3050b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands");
3060b57cec5SDimitry Andric     addExpr(Inst, getImm());
3070b57cec5SDimitry Andric   }
addBDAddrOperands(MCInst & Inst,unsigned N) const3080b57cec5SDimitry Andric   void addBDAddrOperands(MCInst &Inst, unsigned N) const {
3090b57cec5SDimitry Andric     assert(N == 2 && "Invalid number of operands");
3100b57cec5SDimitry Andric     assert(isMem(BDMem) && "Invalid operand type");
3110b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Mem.Base));
3120b57cec5SDimitry Andric     addExpr(Inst, Mem.Disp);
3130b57cec5SDimitry Andric   }
addBDXAddrOperands(MCInst & Inst,unsigned N) const3140b57cec5SDimitry Andric   void addBDXAddrOperands(MCInst &Inst, unsigned N) const {
3150b57cec5SDimitry Andric     assert(N == 3 && "Invalid number of operands");
3160b57cec5SDimitry Andric     assert(isMem(BDXMem) && "Invalid operand type");
3170b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Mem.Base));
3180b57cec5SDimitry Andric     addExpr(Inst, Mem.Disp);
3190b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Mem.Index));
3200b57cec5SDimitry Andric   }
addBDLAddrOperands(MCInst & Inst,unsigned N) const3210b57cec5SDimitry Andric   void addBDLAddrOperands(MCInst &Inst, unsigned N) const {
3220b57cec5SDimitry Andric     assert(N == 3 && "Invalid number of operands");
3230b57cec5SDimitry Andric     assert(isMem(BDLMem) && "Invalid operand type");
3240b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Mem.Base));
3250b57cec5SDimitry Andric     addExpr(Inst, Mem.Disp);
3260b57cec5SDimitry Andric     addExpr(Inst, Mem.Length.Imm);
3270b57cec5SDimitry Andric   }
addBDRAddrOperands(MCInst & Inst,unsigned N) const3280b57cec5SDimitry Andric   void addBDRAddrOperands(MCInst &Inst, unsigned N) const {
3290b57cec5SDimitry Andric     assert(N == 3 && "Invalid number of operands");
3300b57cec5SDimitry Andric     assert(isMem(BDRMem) && "Invalid operand type");
3310b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Mem.Base));
3320b57cec5SDimitry Andric     addExpr(Inst, Mem.Disp);
3330b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Mem.Length.Reg));
3340b57cec5SDimitry Andric   }
addBDVAddrOperands(MCInst & Inst,unsigned N) const3350b57cec5SDimitry Andric   void addBDVAddrOperands(MCInst &Inst, unsigned N) const {
3360b57cec5SDimitry Andric     assert(N == 3 && "Invalid number of operands");
3370b57cec5SDimitry Andric     assert(isMem(BDVMem) && "Invalid operand type");
3380b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Mem.Base));
3390b57cec5SDimitry Andric     addExpr(Inst, Mem.Disp);
3400b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Mem.Index));
3410b57cec5SDimitry Andric   }
addImmTLSOperands(MCInst & Inst,unsigned N) const3420b57cec5SDimitry Andric   void addImmTLSOperands(MCInst &Inst, unsigned N) const {
3430b57cec5SDimitry Andric     assert(N == 2 && "Invalid number of operands");
3440b57cec5SDimitry Andric     assert(Kind == KindImmTLS && "Invalid operand type");
3450b57cec5SDimitry Andric     addExpr(Inst, ImmTLS.Imm);
3460b57cec5SDimitry Andric     if (ImmTLS.Sym)
3470b57cec5SDimitry Andric       addExpr(Inst, ImmTLS.Sym);
3480b57cec5SDimitry Andric   }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   // Used by the TableGen code to check for particular operand types.
isGR32() const3510b57cec5SDimitry Andric   bool isGR32() const { return isReg(GR32Reg); }
isGRH32() const3520b57cec5SDimitry Andric   bool isGRH32() const { return isReg(GRH32Reg); }
isGRX32() const3530b57cec5SDimitry Andric   bool isGRX32() const { return false; }
isGR64() const3540b57cec5SDimitry Andric   bool isGR64() const { return isReg(GR64Reg); }
isGR128() const3550b57cec5SDimitry Andric   bool isGR128() const { return isReg(GR128Reg); }
isADDR32() const3565ffd83dbSDimitry Andric   bool isADDR32() const { return isReg(GR32Reg); }
isADDR64() const3575ffd83dbSDimitry Andric   bool isADDR64() const { return isReg(GR64Reg); }
isADDR128() const3580b57cec5SDimitry Andric   bool isADDR128() const { return false; }
isFP32() const3590b57cec5SDimitry Andric   bool isFP32() const { return isReg(FP32Reg); }
isFP64() const3600b57cec5SDimitry Andric   bool isFP64() const { return isReg(FP64Reg); }
isFP128() const3610b57cec5SDimitry Andric   bool isFP128() const { return isReg(FP128Reg); }
isVR32() const3620b57cec5SDimitry Andric   bool isVR32() const { return isReg(VR32Reg); }
isVR64() const3630b57cec5SDimitry Andric   bool isVR64() const { return isReg(VR64Reg); }
isVF128() const3640b57cec5SDimitry Andric   bool isVF128() const { return false; }
isVR128() const3650b57cec5SDimitry Andric   bool isVR128() const { return isReg(VR128Reg); }
isAR32() const3660b57cec5SDimitry Andric   bool isAR32() const { return isReg(AR32Reg); }
isCR64() const3670b57cec5SDimitry Andric   bool isCR64() const { return isReg(CR64Reg); }
isAnyReg() const3680b57cec5SDimitry Andric   bool isAnyReg() const { return (isReg() || isImm(0, 15)); }
isBDAddr32Disp12() const3695ffd83dbSDimitry Andric   bool isBDAddr32Disp12() const { return isMemDisp12(BDMem, GR32Reg); }
isBDAddr32Disp20() const3705ffd83dbSDimitry Andric   bool isBDAddr32Disp20() const { return isMemDisp20(BDMem, GR32Reg); }
isBDAddr64Disp12() const3715ffd83dbSDimitry Andric   bool isBDAddr64Disp12() const { return isMemDisp12(BDMem, GR64Reg); }
isBDAddr64Disp20() const3725ffd83dbSDimitry Andric   bool isBDAddr64Disp20() const { return isMemDisp20(BDMem, GR64Reg); }
isBDXAddr64Disp12() const3735ffd83dbSDimitry Andric   bool isBDXAddr64Disp12() const { return isMemDisp12(BDXMem, GR64Reg); }
isBDXAddr64Disp20() const3745ffd83dbSDimitry Andric   bool isBDXAddr64Disp20() const { return isMemDisp20(BDXMem, GR64Reg); }
isBDLAddr64Disp12Len4() const3755ffd83dbSDimitry Andric   bool isBDLAddr64Disp12Len4() const { return isMemDisp12Len4(GR64Reg); }
isBDLAddr64Disp12Len8() const3765ffd83dbSDimitry Andric   bool isBDLAddr64Disp12Len8() const { return isMemDisp12Len8(GR64Reg); }
isBDRAddr64Disp12() const3775ffd83dbSDimitry Andric   bool isBDRAddr64Disp12() const { return isMemDisp12(BDRMem, GR64Reg); }
isBDVAddr64Disp12() const3785ffd83dbSDimitry Andric   bool isBDVAddr64Disp12() const { return isMemDisp12(BDVMem, GR64Reg); }
isU1Imm() const3790b57cec5SDimitry Andric   bool isU1Imm() const { return isImm(0, 1); }
isU2Imm() const3800b57cec5SDimitry Andric   bool isU2Imm() const { return isImm(0, 3); }
isU3Imm() const3810b57cec5SDimitry Andric   bool isU3Imm() const { return isImm(0, 7); }
isU4Imm() const3820b57cec5SDimitry Andric   bool isU4Imm() const { return isImm(0, 15); }
isU8Imm() const3830b57cec5SDimitry Andric   bool isU8Imm() const { return isImm(0, 255); }
isS8Imm() const3840b57cec5SDimitry Andric   bool isS8Imm() const { return isImm(-128, 127); }
isU12Imm() const3850b57cec5SDimitry Andric   bool isU12Imm() const { return isImm(0, 4095); }
isU16Imm() const3860b57cec5SDimitry Andric   bool isU16Imm() const { return isImm(0, 65535); }
isS16Imm() const3870b57cec5SDimitry Andric   bool isS16Imm() const { return isImm(-32768, 32767); }
isU32Imm() const3880b57cec5SDimitry Andric   bool isU32Imm() const { return isImm(0, (1LL << 32) - 1); }
isS32Imm() const3890b57cec5SDimitry Andric   bool isS32Imm() const { return isImm(-(1LL << 31), (1LL << 31) - 1); }
isU48Imm() const3900b57cec5SDimitry Andric   bool isU48Imm() const { return isImm(0, (1LL << 48) - 1); }
3910b57cec5SDimitry Andric };
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric class SystemZAsmParser : public MCTargetAsmParser {
3940b57cec5SDimitry Andric #define GET_ASSEMBLER_HEADER
3950b57cec5SDimitry Andric #include "SystemZGenAsmMatcher.inc"
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric private:
3980b57cec5SDimitry Andric   MCAsmParser &Parser;
3990b57cec5SDimitry Andric   enum RegisterGroup {
4000b57cec5SDimitry Andric     RegGR,
4010b57cec5SDimitry Andric     RegFP,
4020b57cec5SDimitry Andric     RegV,
4030b57cec5SDimitry Andric     RegAR,
4040b57cec5SDimitry Andric     RegCR
4050b57cec5SDimitry Andric   };
4060b57cec5SDimitry Andric   struct Register {
4070b57cec5SDimitry Andric     RegisterGroup Group;
4080b57cec5SDimitry Andric     unsigned Num;
4090b57cec5SDimitry Andric     SMLoc StartLoc, EndLoc;
4100b57cec5SDimitry Andric   };
4110b57cec5SDimitry Andric 
getTargetStreamer()412349cc55cSDimitry Andric   SystemZTargetStreamer &getTargetStreamer() {
413349cc55cSDimitry Andric     assert(getParser().getStreamer().getTargetStreamer() &&
414349cc55cSDimitry Andric            "do not have a target streamer");
415349cc55cSDimitry Andric     MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
416349cc55cSDimitry Andric     return static_cast<SystemZTargetStreamer &>(TS);
417349cc55cSDimitry Andric   }
418349cc55cSDimitry Andric 
4195ffd83dbSDimitry Andric   bool parseRegister(Register &Reg, bool RestoreOnFailure = false);
4200b57cec5SDimitry Andric 
4215ffd83dbSDimitry Andric   bool parseIntegerRegister(Register &Reg, RegisterGroup Group);
4220b57cec5SDimitry Andric 
4235f757f3fSDimitry Andric   ParseStatus parseRegister(OperandVector &Operands, RegisterKind Kind);
4240b57cec5SDimitry Andric 
4255f757f3fSDimitry Andric   ParseStatus parseAnyRegister(OperandVector &Operands);
4260b57cec5SDimitry Andric 
4275ffd83dbSDimitry Andric   bool parseAddress(bool &HaveReg1, Register &Reg1, bool &HaveReg2,
4285ffd83dbSDimitry Andric                     Register &Reg2, const MCExpr *&Disp, const MCExpr *&Length,
4295ffd83dbSDimitry Andric                     bool HasLength = false, bool HasVectorIndex = false);
4300b57cec5SDimitry Andric   bool parseAddressRegister(Register &Reg);
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   bool ParseDirectiveInsn(SMLoc L);
433349cc55cSDimitry Andric   bool ParseDirectiveMachine(SMLoc L);
434bdd1243dSDimitry Andric   bool ParseGNUAttribute(SMLoc L);
4350b57cec5SDimitry Andric 
4365f757f3fSDimitry Andric   ParseStatus parseAddress(OperandVector &Operands, MemoryKind MemKind,
4370b57cec5SDimitry Andric                            RegisterKind RegKind);
4380b57cec5SDimitry Andric 
4395f757f3fSDimitry Andric   ParseStatus parsePCRel(OperandVector &Operands, int64_t MinVal,
4400b57cec5SDimitry Andric                          int64_t MaxVal, bool AllowTLS);
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
4430b57cec5SDimitry Andric 
444fe6060f1SDimitry Andric   // Both the hlasm and att variants still rely on the basic gnu asm
445fe6060f1SDimitry Andric   // format with respect to inputs, clobbers, outputs etc.
446fe6060f1SDimitry Andric   //
447fe6060f1SDimitry Andric   // However, calling the overriden getAssemblerDialect() method in
448fe6060f1SDimitry Andric   // AsmParser is problematic. It either returns the AssemblerDialect field
449fe6060f1SDimitry Andric   // in the MCAsmInfo instance if the AssemblerDialect field in AsmParser is
450fe6060f1SDimitry Andric   // unset, otherwise it returns the private AssemblerDialect field in
451fe6060f1SDimitry Andric   // AsmParser.
452fe6060f1SDimitry Andric   //
453fe6060f1SDimitry Andric   // The problematic part is because, we forcibly set the inline asm dialect
454fe6060f1SDimitry Andric   // in the AsmParser instance in AsmPrinterInlineAsm.cpp. Soo any query
455fe6060f1SDimitry Andric   // to the overriden getAssemblerDialect function in AsmParser.cpp, will
456fe6060f1SDimitry Andric   // not return the assembler dialect set in the respective MCAsmInfo instance.
457fe6060f1SDimitry Andric   //
458fe6060f1SDimitry Andric   // For this purpose, we explicitly query the SystemZMCAsmInfo instance
459fe6060f1SDimitry Andric   // here, to get the "correct" assembler dialect, and use it in various
460fe6060f1SDimitry Andric   // functions.
getMAIAssemblerDialect()461fe6060f1SDimitry Andric   unsigned getMAIAssemblerDialect() {
462fe6060f1SDimitry Andric     return Parser.getContext().getAsmInfo()->getAssemblerDialect();
463fe6060f1SDimitry Andric   }
464fe6060f1SDimitry Andric 
465fe6060f1SDimitry Andric   // An alphabetic character in HLASM is a letter from 'A' through 'Z',
466fe6060f1SDimitry Andric   // or from 'a' through 'z', or '$', '_','#', or '@'.
isHLASMAlpha(char C)467fe6060f1SDimitry Andric   inline bool isHLASMAlpha(char C) {
468fe6060f1SDimitry Andric     return isAlpha(C) || llvm::is_contained("_@#$", C);
469fe6060f1SDimitry Andric   }
470fe6060f1SDimitry Andric 
471fe6060f1SDimitry Andric   // A digit in HLASM is a number from 0 to 9.
isHLASMAlnum(char C)472fe6060f1SDimitry Andric   inline bool isHLASMAlnum(char C) { return isHLASMAlpha(C) || isDigit(C); }
473fe6060f1SDimitry Andric 
474fe6060f1SDimitry Andric   // Are we parsing using the AD_HLASM dialect?
isParsingHLASM()475fe6060f1SDimitry Andric   inline bool isParsingHLASM() { return getMAIAssemblerDialect() == AD_HLASM; }
476fe6060f1SDimitry Andric 
477fe6060f1SDimitry Andric   // Are we parsing using the AD_ATT dialect?
isParsingATT()478fe6060f1SDimitry Andric   inline bool isParsingATT() { return getMAIAssemblerDialect() == AD_ATT; }
479fe6060f1SDimitry Andric 
4800b57cec5SDimitry Andric public:
SystemZAsmParser(const MCSubtargetInfo & sti,MCAsmParser & parser,const MCInstrInfo & MII,const MCTargetOptions & Options)4810b57cec5SDimitry Andric   SystemZAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
4820b57cec5SDimitry Andric                    const MCInstrInfo &MII,
4830b57cec5SDimitry Andric                    const MCTargetOptions &Options)
4840b57cec5SDimitry Andric     : MCTargetAsmParser(Options, sti, MII), Parser(parser) {
4850b57cec5SDimitry Andric     MCAsmParserExtension::Initialize(Parser);
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric     // Alias the .word directive to .short.
4880b57cec5SDimitry Andric     parser.addAliasForDirective(".word", ".short");
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric     // Initialize the set of available features.
4910b57cec5SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
4920b57cec5SDimitry Andric   }
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric   // Override MCTargetAsmParser.
49506c3fb27SDimitry Andric   ParseStatus parseDirective(AsmToken DirectiveID) override;
4965f757f3fSDimitry Andric   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
497bdd1243dSDimitry Andric   bool ParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,
4985ffd83dbSDimitry Andric                      bool RestoreOnFailure);
4995f757f3fSDimitry Andric   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
5005ffd83dbSDimitry Andric                                SMLoc &EndLoc) override;
5010b57cec5SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
5020b57cec5SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
5030b57cec5SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5040b57cec5SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
5050b57cec5SDimitry Andric                                uint64_t &ErrorInfo,
5060b57cec5SDimitry Andric                                bool MatchingInlineAsm) override;
507fe6060f1SDimitry Andric   bool isLabel(AsmToken &Token) override;
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric   // Used by the TableGen code to parse particular operand types.
parseGR32(OperandVector & Operands)5105f757f3fSDimitry Andric   ParseStatus parseGR32(OperandVector &Operands) {
5115ffd83dbSDimitry Andric     return parseRegister(Operands, GR32Reg);
5120b57cec5SDimitry Andric   }
parseGRH32(OperandVector & Operands)5135f757f3fSDimitry Andric   ParseStatus parseGRH32(OperandVector &Operands) {
5145ffd83dbSDimitry Andric     return parseRegister(Operands, GRH32Reg);
5150b57cec5SDimitry Andric   }
parseGRX32(OperandVector & Operands)5165f757f3fSDimitry Andric   ParseStatus parseGRX32(OperandVector &Operands) {
5170b57cec5SDimitry Andric     llvm_unreachable("GRX32 should only be used for pseudo instructions");
5180b57cec5SDimitry Andric   }
parseGR64(OperandVector & Operands)5195f757f3fSDimitry Andric   ParseStatus parseGR64(OperandVector &Operands) {
5205ffd83dbSDimitry Andric     return parseRegister(Operands, GR64Reg);
5210b57cec5SDimitry Andric   }
parseGR128(OperandVector & Operands)5225f757f3fSDimitry Andric   ParseStatus parseGR128(OperandVector &Operands) {
5235ffd83dbSDimitry Andric     return parseRegister(Operands, GR128Reg);
5240b57cec5SDimitry Andric   }
parseADDR32(OperandVector & Operands)5255f757f3fSDimitry Andric   ParseStatus parseADDR32(OperandVector &Operands) {
5265ffd83dbSDimitry Andric     // For the AsmParser, we will accept %r0 for ADDR32 as well.
5275ffd83dbSDimitry Andric     return parseRegister(Operands, GR32Reg);
5280b57cec5SDimitry Andric   }
parseADDR64(OperandVector & Operands)5295f757f3fSDimitry Andric   ParseStatus parseADDR64(OperandVector &Operands) {
5305ffd83dbSDimitry Andric     // For the AsmParser, we will accept %r0 for ADDR64 as well.
5315ffd83dbSDimitry Andric     return parseRegister(Operands, GR64Reg);
5320b57cec5SDimitry Andric   }
parseADDR128(OperandVector & Operands)5335f757f3fSDimitry Andric   ParseStatus parseADDR128(OperandVector &Operands) {
5340b57cec5SDimitry Andric     llvm_unreachable("Shouldn't be used as an operand");
5350b57cec5SDimitry Andric   }
parseFP32(OperandVector & Operands)5365f757f3fSDimitry Andric   ParseStatus parseFP32(OperandVector &Operands) {
5375ffd83dbSDimitry Andric     return parseRegister(Operands, FP32Reg);
5380b57cec5SDimitry Andric   }
parseFP64(OperandVector & Operands)5395f757f3fSDimitry Andric   ParseStatus parseFP64(OperandVector &Operands) {
5405ffd83dbSDimitry Andric     return parseRegister(Operands, FP64Reg);
5410b57cec5SDimitry Andric   }
parseFP128(OperandVector & Operands)5425f757f3fSDimitry Andric   ParseStatus parseFP128(OperandVector &Operands) {
5435ffd83dbSDimitry Andric     return parseRegister(Operands, FP128Reg);
5440b57cec5SDimitry Andric   }
parseVR32(OperandVector & Operands)5455f757f3fSDimitry Andric   ParseStatus parseVR32(OperandVector &Operands) {
5465ffd83dbSDimitry Andric     return parseRegister(Operands, VR32Reg);
5470b57cec5SDimitry Andric   }
parseVR64(OperandVector & Operands)5485f757f3fSDimitry Andric   ParseStatus parseVR64(OperandVector &Operands) {
5495ffd83dbSDimitry Andric     return parseRegister(Operands, VR64Reg);
5500b57cec5SDimitry Andric   }
parseVF128(OperandVector & Operands)5515f757f3fSDimitry Andric   ParseStatus parseVF128(OperandVector &Operands) {
5520b57cec5SDimitry Andric     llvm_unreachable("Shouldn't be used as an operand");
5530b57cec5SDimitry Andric   }
parseVR128(OperandVector & Operands)5545f757f3fSDimitry Andric   ParseStatus parseVR128(OperandVector &Operands) {
5555ffd83dbSDimitry Andric     return parseRegister(Operands, VR128Reg);
5560b57cec5SDimitry Andric   }
parseAR32(OperandVector & Operands)5575f757f3fSDimitry Andric   ParseStatus parseAR32(OperandVector &Operands) {
5585ffd83dbSDimitry Andric     return parseRegister(Operands, AR32Reg);
5590b57cec5SDimitry Andric   }
parseCR64(OperandVector & Operands)5605f757f3fSDimitry Andric   ParseStatus parseCR64(OperandVector &Operands) {
5615ffd83dbSDimitry Andric     return parseRegister(Operands, CR64Reg);
5620b57cec5SDimitry Andric   }
parseAnyReg(OperandVector & Operands)5635f757f3fSDimitry Andric   ParseStatus parseAnyReg(OperandVector &Operands) {
5640b57cec5SDimitry Andric     return parseAnyRegister(Operands);
5650b57cec5SDimitry Andric   }
parseBDAddr32(OperandVector & Operands)5665f757f3fSDimitry Andric   ParseStatus parseBDAddr32(OperandVector &Operands) {
5675ffd83dbSDimitry Andric     return parseAddress(Operands, BDMem, GR32Reg);
5680b57cec5SDimitry Andric   }
parseBDAddr64(OperandVector & Operands)5695f757f3fSDimitry Andric   ParseStatus parseBDAddr64(OperandVector &Operands) {
5705ffd83dbSDimitry Andric     return parseAddress(Operands, BDMem, GR64Reg);
5710b57cec5SDimitry Andric   }
parseBDXAddr64(OperandVector & Operands)5725f757f3fSDimitry Andric   ParseStatus parseBDXAddr64(OperandVector &Operands) {
5735ffd83dbSDimitry Andric     return parseAddress(Operands, BDXMem, GR64Reg);
5740b57cec5SDimitry Andric   }
parseBDLAddr64(OperandVector & Operands)5755f757f3fSDimitry Andric   ParseStatus parseBDLAddr64(OperandVector &Operands) {
5765ffd83dbSDimitry Andric     return parseAddress(Operands, BDLMem, GR64Reg);
5770b57cec5SDimitry Andric   }
parseBDRAddr64(OperandVector & Operands)5785f757f3fSDimitry Andric   ParseStatus parseBDRAddr64(OperandVector &Operands) {
5795ffd83dbSDimitry Andric     return parseAddress(Operands, BDRMem, GR64Reg);
5800b57cec5SDimitry Andric   }
parseBDVAddr64(OperandVector & Operands)5815f757f3fSDimitry Andric   ParseStatus parseBDVAddr64(OperandVector &Operands) {
5825ffd83dbSDimitry Andric     return parseAddress(Operands, BDVMem, GR64Reg);
5830b57cec5SDimitry Andric   }
parsePCRel12(OperandVector & Operands)5845f757f3fSDimitry Andric   ParseStatus parsePCRel12(OperandVector &Operands) {
5850b57cec5SDimitry Andric     return parsePCRel(Operands, -(1LL << 12), (1LL << 12) - 1, false);
5860b57cec5SDimitry Andric   }
parsePCRel16(OperandVector & Operands)5875f757f3fSDimitry Andric   ParseStatus parsePCRel16(OperandVector &Operands) {
5880b57cec5SDimitry Andric     return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, false);
5890b57cec5SDimitry Andric   }
parsePCRel24(OperandVector & Operands)5905f757f3fSDimitry Andric   ParseStatus parsePCRel24(OperandVector &Operands) {
5910b57cec5SDimitry Andric     return parsePCRel(Operands, -(1LL << 24), (1LL << 24) - 1, false);
5920b57cec5SDimitry Andric   }
parsePCRel32(OperandVector & Operands)5935f757f3fSDimitry Andric   ParseStatus parsePCRel32(OperandVector &Operands) {
5940b57cec5SDimitry Andric     return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1, false);
5950b57cec5SDimitry Andric   }
parsePCRelTLS16(OperandVector & Operands)5965f757f3fSDimitry Andric   ParseStatus parsePCRelTLS16(OperandVector &Operands) {
5970b57cec5SDimitry Andric     return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, true);
5980b57cec5SDimitry Andric   }
parsePCRelTLS32(OperandVector & Operands)5995f757f3fSDimitry Andric   ParseStatus parsePCRelTLS32(OperandVector &Operands) {
6000b57cec5SDimitry Andric     return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1, true);
6010b57cec5SDimitry Andric   }
6020b57cec5SDimitry Andric };
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric } // end anonymous namespace
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric #define GET_REGISTER_MATCHER
6070b57cec5SDimitry Andric #define GET_SUBTARGET_FEATURE_NAME
6080b57cec5SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
6090b57cec5SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER
6100b57cec5SDimitry Andric #include "SystemZGenAsmMatcher.inc"
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric // Used for the .insn directives; contains information needed to parse the
6130b57cec5SDimitry Andric // operands in the directive.
6140b57cec5SDimitry Andric struct InsnMatchEntry {
6150b57cec5SDimitry Andric   StringRef Format;
6160b57cec5SDimitry Andric   uint64_t Opcode;
6170b57cec5SDimitry Andric   int32_t NumOperands;
618e8d8bef9SDimitry Andric   MatchClassKind OperandKinds[7];
6190b57cec5SDimitry Andric };
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric // For equal_range comparison.
6220b57cec5SDimitry Andric struct CompareInsn {
operator ()CompareInsn6230b57cec5SDimitry Andric   bool operator() (const InsnMatchEntry &LHS, StringRef RHS) {
6240b57cec5SDimitry Andric     return LHS.Format < RHS;
6250b57cec5SDimitry Andric   }
operator ()CompareInsn6260b57cec5SDimitry Andric   bool operator() (StringRef LHS, const InsnMatchEntry &RHS) {
6270b57cec5SDimitry Andric     return LHS < RHS.Format;
6280b57cec5SDimitry Andric   }
operator ()CompareInsn6290b57cec5SDimitry Andric   bool operator() (const InsnMatchEntry &LHS, const InsnMatchEntry &RHS) {
6300b57cec5SDimitry Andric     return LHS.Format < RHS.Format;
6310b57cec5SDimitry Andric   }
6320b57cec5SDimitry Andric };
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric // Table initializing information for parsing the .insn directive.
6350b57cec5SDimitry Andric static struct InsnMatchEntry InsnMatchTable[] = {
6360b57cec5SDimitry Andric   /* Format, Opcode, NumOperands, OperandKinds */
6370b57cec5SDimitry Andric   { "e", SystemZ::InsnE, 1,
6380b57cec5SDimitry Andric     { MCK_U16Imm } },
6390b57cec5SDimitry Andric   { "ri", SystemZ::InsnRI, 3,
6400b57cec5SDimitry Andric     { MCK_U32Imm, MCK_AnyReg, MCK_S16Imm } },
6410b57cec5SDimitry Andric   { "rie", SystemZ::InsnRIE, 4,
6420b57cec5SDimitry Andric     { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_PCRel16 } },
6430b57cec5SDimitry Andric   { "ril", SystemZ::InsnRIL, 3,
6440b57cec5SDimitry Andric     { MCK_U48Imm, MCK_AnyReg, MCK_PCRel32 } },
6450b57cec5SDimitry Andric   { "rilu", SystemZ::InsnRILU, 3,
6460b57cec5SDimitry Andric     { MCK_U48Imm, MCK_AnyReg, MCK_U32Imm } },
6470b57cec5SDimitry Andric   { "ris", SystemZ::InsnRIS, 5,
6480b57cec5SDimitry Andric     { MCK_U48Imm, MCK_AnyReg, MCK_S8Imm, MCK_U4Imm, MCK_BDAddr64Disp12 } },
6490b57cec5SDimitry Andric   { "rr", SystemZ::InsnRR, 3,
6500b57cec5SDimitry Andric     { MCK_U16Imm, MCK_AnyReg, MCK_AnyReg } },
6510b57cec5SDimitry Andric   { "rre", SystemZ::InsnRRE, 3,
6520b57cec5SDimitry Andric     { MCK_U32Imm, MCK_AnyReg, MCK_AnyReg } },
6530b57cec5SDimitry Andric   { "rrf", SystemZ::InsnRRF, 5,
6540b57cec5SDimitry Andric     { MCK_U32Imm, MCK_AnyReg, MCK_AnyReg, MCK_AnyReg, MCK_U4Imm } },
6550b57cec5SDimitry Andric   { "rrs", SystemZ::InsnRRS, 5,
6560b57cec5SDimitry Andric     { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_U4Imm, MCK_BDAddr64Disp12 } },
6570b57cec5SDimitry Andric   { "rs", SystemZ::InsnRS, 4,
6580b57cec5SDimitry Andric     { MCK_U32Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDAddr64Disp12 } },
6590b57cec5SDimitry Andric   { "rse", SystemZ::InsnRSE, 4,
6600b57cec5SDimitry Andric     { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDAddr64Disp12 } },
6610b57cec5SDimitry Andric   { "rsi", SystemZ::InsnRSI, 4,
6620b57cec5SDimitry Andric     { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_PCRel16 } },
6630b57cec5SDimitry Andric   { "rsy", SystemZ::InsnRSY, 4,
6640b57cec5SDimitry Andric     { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDAddr64Disp20 } },
6650b57cec5SDimitry Andric   { "rx", SystemZ::InsnRX, 3,
6660b57cec5SDimitry Andric     { MCK_U32Imm, MCK_AnyReg, MCK_BDXAddr64Disp12 } },
6670b57cec5SDimitry Andric   { "rxe", SystemZ::InsnRXE, 3,
6680b57cec5SDimitry Andric     { MCK_U48Imm, MCK_AnyReg, MCK_BDXAddr64Disp12 } },
6690b57cec5SDimitry Andric   { "rxf", SystemZ::InsnRXF, 4,
6700b57cec5SDimitry Andric     { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDXAddr64Disp12 } },
6710b57cec5SDimitry Andric   { "rxy", SystemZ::InsnRXY, 3,
6720b57cec5SDimitry Andric     { MCK_U48Imm, MCK_AnyReg, MCK_BDXAddr64Disp20 } },
6730b57cec5SDimitry Andric   { "s", SystemZ::InsnS, 2,
6740b57cec5SDimitry Andric     { MCK_U32Imm, MCK_BDAddr64Disp12 } },
6750b57cec5SDimitry Andric   { "si", SystemZ::InsnSI, 3,
6760b57cec5SDimitry Andric     { MCK_U32Imm, MCK_BDAddr64Disp12, MCK_S8Imm } },
6770b57cec5SDimitry Andric   { "sil", SystemZ::InsnSIL, 3,
6780b57cec5SDimitry Andric     { MCK_U48Imm, MCK_BDAddr64Disp12, MCK_U16Imm } },
6790b57cec5SDimitry Andric   { "siy", SystemZ::InsnSIY, 3,
6800b57cec5SDimitry Andric     { MCK_U48Imm, MCK_BDAddr64Disp20, MCK_U8Imm } },
6810b57cec5SDimitry Andric   { "ss", SystemZ::InsnSS, 4,
6820b57cec5SDimitry Andric     { MCK_U48Imm, MCK_BDXAddr64Disp12, MCK_BDAddr64Disp12, MCK_AnyReg } },
6830b57cec5SDimitry Andric   { "sse", SystemZ::InsnSSE, 3,
6840b57cec5SDimitry Andric     { MCK_U48Imm, MCK_BDAddr64Disp12, MCK_BDAddr64Disp12 } },
6850b57cec5SDimitry Andric   { "ssf", SystemZ::InsnSSF, 4,
686e8d8bef9SDimitry Andric     { MCK_U48Imm, MCK_BDAddr64Disp12, MCK_BDAddr64Disp12, MCK_AnyReg } },
687e8d8bef9SDimitry Andric   { "vri", SystemZ::InsnVRI, 6,
688e8d8bef9SDimitry Andric     { MCK_U48Imm, MCK_VR128, MCK_VR128, MCK_U12Imm, MCK_U4Imm, MCK_U4Imm } },
689e8d8bef9SDimitry Andric   { "vrr", SystemZ::InsnVRR, 7,
690e8d8bef9SDimitry Andric     { MCK_U48Imm, MCK_VR128, MCK_VR128, MCK_VR128, MCK_U4Imm, MCK_U4Imm,
691e8d8bef9SDimitry Andric       MCK_U4Imm } },
692e8d8bef9SDimitry Andric   { "vrs", SystemZ::InsnVRS, 5,
693e8d8bef9SDimitry Andric     { MCK_U48Imm, MCK_AnyReg, MCK_VR128, MCK_BDAddr64Disp12, MCK_U4Imm } },
694e8d8bef9SDimitry Andric   { "vrv", SystemZ::InsnVRV, 4,
695e8d8bef9SDimitry Andric     { MCK_U48Imm, MCK_VR128, MCK_BDVAddr64Disp12, MCK_U4Imm } },
696e8d8bef9SDimitry Andric   { "vrx", SystemZ::InsnVRX, 4,
697e8d8bef9SDimitry Andric     { MCK_U48Imm, MCK_VR128, MCK_BDXAddr64Disp12, MCK_U4Imm } },
698e8d8bef9SDimitry Andric   { "vsi", SystemZ::InsnVSI, 4,
699e8d8bef9SDimitry Andric     { MCK_U48Imm, MCK_VR128, MCK_BDAddr64Disp12, MCK_U8Imm } }
7000b57cec5SDimitry Andric };
7010b57cec5SDimitry Andric 
printMCExpr(const MCExpr * E,raw_ostream & OS)7020b57cec5SDimitry Andric static void printMCExpr(const MCExpr *E, raw_ostream &OS) {
7030b57cec5SDimitry Andric   if (!E)
7040b57cec5SDimitry Andric     return;
7050b57cec5SDimitry Andric   if (auto *CE = dyn_cast<MCConstantExpr>(E))
7060b57cec5SDimitry Andric     OS << *CE;
7070b57cec5SDimitry Andric   else if (auto *UE = dyn_cast<MCUnaryExpr>(E))
7080b57cec5SDimitry Andric     OS << *UE;
7090b57cec5SDimitry Andric   else if (auto *BE = dyn_cast<MCBinaryExpr>(E))
7100b57cec5SDimitry Andric     OS << *BE;
7110b57cec5SDimitry Andric   else if (auto *SRE = dyn_cast<MCSymbolRefExpr>(E))
7120b57cec5SDimitry Andric     OS << *SRE;
7130b57cec5SDimitry Andric   else
7140b57cec5SDimitry Andric     OS << *E;
7150b57cec5SDimitry Andric }
7160b57cec5SDimitry Andric 
print(raw_ostream & OS) const7170b57cec5SDimitry Andric void SystemZOperand::print(raw_ostream &OS) const {
7180b57cec5SDimitry Andric   switch (Kind) {
7190b57cec5SDimitry Andric   case KindToken:
7200b57cec5SDimitry Andric     OS << "Token:" << getToken();
7210b57cec5SDimitry Andric     break;
7220b57cec5SDimitry Andric   case KindReg:
7230b57cec5SDimitry Andric     OS << "Reg:" << SystemZInstPrinter::getRegisterName(getReg());
7240b57cec5SDimitry Andric     break;
7250b57cec5SDimitry Andric   case KindImm:
7260b57cec5SDimitry Andric     OS << "Imm:";
7270b57cec5SDimitry Andric     printMCExpr(getImm(), OS);
7280b57cec5SDimitry Andric     break;
7290b57cec5SDimitry Andric   case KindImmTLS:
7300b57cec5SDimitry Andric     OS << "ImmTLS:";
7310b57cec5SDimitry Andric     printMCExpr(getImmTLS().Imm, OS);
7320b57cec5SDimitry Andric     if (getImmTLS().Sym) {
7330b57cec5SDimitry Andric       OS << ", ";
7340b57cec5SDimitry Andric       printMCExpr(getImmTLS().Sym, OS);
7350b57cec5SDimitry Andric     }
7360b57cec5SDimitry Andric     break;
7370b57cec5SDimitry Andric   case KindMem: {
7380b57cec5SDimitry Andric     const MemOp &Op = getMem();
7390b57cec5SDimitry Andric     OS << "Mem:" << *cast<MCConstantExpr>(Op.Disp);
7400b57cec5SDimitry Andric     if (Op.Base) {
7410b57cec5SDimitry Andric       OS << "(";
7420b57cec5SDimitry Andric       if (Op.MemKind == BDLMem)
7430b57cec5SDimitry Andric         OS << *cast<MCConstantExpr>(Op.Length.Imm) << ",";
7440b57cec5SDimitry Andric       else if (Op.MemKind == BDRMem)
7450b57cec5SDimitry Andric         OS << SystemZInstPrinter::getRegisterName(Op.Length.Reg) << ",";
7460b57cec5SDimitry Andric       if (Op.Index)
7470b57cec5SDimitry Andric         OS << SystemZInstPrinter::getRegisterName(Op.Index) << ",";
7480b57cec5SDimitry Andric       OS << SystemZInstPrinter::getRegisterName(Op.Base);
7490b57cec5SDimitry Andric       OS << ")";
7500b57cec5SDimitry Andric     }
7510b57cec5SDimitry Andric     break;
7520b57cec5SDimitry Andric   }
7530b57cec5SDimitry Andric   case KindInvalid:
7540b57cec5SDimitry Andric     break;
7550b57cec5SDimitry Andric   }
7560b57cec5SDimitry Andric }
7570b57cec5SDimitry Andric 
7580b57cec5SDimitry Andric // Parse one register of the form %<prefix><number>.
parseRegister(Register & Reg,bool RestoreOnFailure)7595ffd83dbSDimitry Andric bool SystemZAsmParser::parseRegister(Register &Reg, bool RestoreOnFailure) {
7600b57cec5SDimitry Andric   Reg.StartLoc = Parser.getTok().getLoc();
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   // Eat the % prefix.
7630b57cec5SDimitry Andric   if (Parser.getTok().isNot(AsmToken::Percent))
7640b57cec5SDimitry Andric     return Error(Parser.getTok().getLoc(), "register expected");
7655ffd83dbSDimitry Andric   const AsmToken &PercentTok = Parser.getTok();
7660b57cec5SDimitry Andric   Parser.Lex();
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric   // Expect a register name.
7695ffd83dbSDimitry Andric   if (Parser.getTok().isNot(AsmToken::Identifier)) {
7705ffd83dbSDimitry Andric     if (RestoreOnFailure)
7715ffd83dbSDimitry Andric       getLexer().UnLex(PercentTok);
7720b57cec5SDimitry Andric     return Error(Reg.StartLoc, "invalid register");
7735ffd83dbSDimitry Andric   }
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric   // Check that there's a prefix.
7760b57cec5SDimitry Andric   StringRef Name = Parser.getTok().getString();
7775ffd83dbSDimitry Andric   if (Name.size() < 2) {
7785ffd83dbSDimitry Andric     if (RestoreOnFailure)
7795ffd83dbSDimitry Andric       getLexer().UnLex(PercentTok);
7800b57cec5SDimitry Andric     return Error(Reg.StartLoc, "invalid register");
7815ffd83dbSDimitry Andric   }
7820b57cec5SDimitry Andric   char Prefix = Name[0];
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric   // Treat the rest of the register name as a register number.
7855ffd83dbSDimitry Andric   if (Name.substr(1).getAsInteger(10, Reg.Num)) {
7865ffd83dbSDimitry Andric     if (RestoreOnFailure)
7875ffd83dbSDimitry Andric       getLexer().UnLex(PercentTok);
7880b57cec5SDimitry Andric     return Error(Reg.StartLoc, "invalid register");
7895ffd83dbSDimitry Andric   }
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric   // Look for valid combinations of prefix and number.
7920b57cec5SDimitry Andric   if (Prefix == 'r' && Reg.Num < 16)
7930b57cec5SDimitry Andric     Reg.Group = RegGR;
7940b57cec5SDimitry Andric   else if (Prefix == 'f' && Reg.Num < 16)
7950b57cec5SDimitry Andric     Reg.Group = RegFP;
7960b57cec5SDimitry Andric   else if (Prefix == 'v' && Reg.Num < 32)
7970b57cec5SDimitry Andric     Reg.Group = RegV;
7980b57cec5SDimitry Andric   else if (Prefix == 'a' && Reg.Num < 16)
7990b57cec5SDimitry Andric     Reg.Group = RegAR;
8000b57cec5SDimitry Andric   else if (Prefix == 'c' && Reg.Num < 16)
8010b57cec5SDimitry Andric     Reg.Group = RegCR;
8025ffd83dbSDimitry Andric   else {
8035ffd83dbSDimitry Andric     if (RestoreOnFailure)
8045ffd83dbSDimitry Andric       getLexer().UnLex(PercentTok);
8050b57cec5SDimitry Andric     return Error(Reg.StartLoc, "invalid register");
8065ffd83dbSDimitry Andric   }
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric   Reg.EndLoc = Parser.getTok().getLoc();
8090b57cec5SDimitry Andric   Parser.Lex();
8100b57cec5SDimitry Andric   return false;
8110b57cec5SDimitry Andric }
8120b57cec5SDimitry Andric 
8135ffd83dbSDimitry Andric // Parse a register of kind Kind and add it to Operands.
parseRegister(OperandVector & Operands,RegisterKind Kind)8145f757f3fSDimitry Andric ParseStatus SystemZAsmParser::parseRegister(OperandVector &Operands,
8155f757f3fSDimitry Andric                                             RegisterKind Kind) {
8165ffd83dbSDimitry Andric   Register Reg;
8175ffd83dbSDimitry Andric   RegisterGroup Group;
8185ffd83dbSDimitry Andric   switch (Kind) {
8195ffd83dbSDimitry Andric   case GR32Reg:
8205ffd83dbSDimitry Andric   case GRH32Reg:
8215ffd83dbSDimitry Andric   case GR64Reg:
8225ffd83dbSDimitry Andric   case GR128Reg:
8235ffd83dbSDimitry Andric     Group = RegGR;
8245ffd83dbSDimitry Andric     break;
8255ffd83dbSDimitry Andric   case FP32Reg:
8265ffd83dbSDimitry Andric   case FP64Reg:
8275ffd83dbSDimitry Andric   case FP128Reg:
8285ffd83dbSDimitry Andric     Group = RegFP;
8295ffd83dbSDimitry Andric     break;
8305ffd83dbSDimitry Andric   case VR32Reg:
8315ffd83dbSDimitry Andric   case VR64Reg:
8325ffd83dbSDimitry Andric   case VR128Reg:
8335ffd83dbSDimitry Andric     Group = RegV;
8345ffd83dbSDimitry Andric     break;
8355ffd83dbSDimitry Andric   case AR32Reg:
8365ffd83dbSDimitry Andric     Group = RegAR;
8375ffd83dbSDimitry Andric     break;
8385ffd83dbSDimitry Andric   case CR64Reg:
8395ffd83dbSDimitry Andric     Group = RegCR;
8405ffd83dbSDimitry Andric     break;
8410b57cec5SDimitry Andric   }
8420b57cec5SDimitry Andric 
8435ffd83dbSDimitry Andric   // Handle register names of the form %<prefix><number>
844fe6060f1SDimitry Andric   if (isParsingATT() && Parser.getTok().is(AsmToken::Percent)) {
8455ffd83dbSDimitry Andric     if (parseRegister(Reg))
8465f757f3fSDimitry Andric       return ParseStatus::Failure;
8470b57cec5SDimitry Andric 
8485ffd83dbSDimitry Andric     // Check the parsed register group "Reg.Group" with the expected "Group"
8495ffd83dbSDimitry Andric     // Have to error out if user specified wrong prefix.
8505ffd83dbSDimitry Andric     switch (Group) {
8515ffd83dbSDimitry Andric     case RegGR:
8525ffd83dbSDimitry Andric     case RegFP:
8535ffd83dbSDimitry Andric     case RegAR:
8545ffd83dbSDimitry Andric     case RegCR:
8555f757f3fSDimitry Andric       if (Group != Reg.Group)
8565f757f3fSDimitry Andric         return Error(Reg.StartLoc, "invalid operand for instruction");
8575ffd83dbSDimitry Andric       break;
8585ffd83dbSDimitry Andric     case RegV:
8595f757f3fSDimitry Andric       if (Reg.Group != RegV && Reg.Group != RegFP)
8605f757f3fSDimitry Andric         return Error(Reg.StartLoc, "invalid operand for instruction");
8615ffd83dbSDimitry Andric       break;
8625ffd83dbSDimitry Andric     }
8635ffd83dbSDimitry Andric   } else if (Parser.getTok().is(AsmToken::Integer)) {
8645ffd83dbSDimitry Andric     if (parseIntegerRegister(Reg, Group))
8655f757f3fSDimitry Andric       return ParseStatus::Failure;
8665ffd83dbSDimitry Andric   }
8675ffd83dbSDimitry Andric   // Otherwise we didn't match a register operand.
8685ffd83dbSDimitry Andric   else
8695f757f3fSDimitry Andric     return ParseStatus::NoMatch;
8705ffd83dbSDimitry Andric 
8715ffd83dbSDimitry Andric   // Determine the LLVM register number according to Kind.
8725ffd83dbSDimitry Andric   const unsigned *Regs;
8735ffd83dbSDimitry Andric   switch (Kind) {
8745ffd83dbSDimitry Andric   case GR32Reg:  Regs = SystemZMC::GR32Regs;  break;
8755ffd83dbSDimitry Andric   case GRH32Reg: Regs = SystemZMC::GRH32Regs; break;
8765ffd83dbSDimitry Andric   case GR64Reg:  Regs = SystemZMC::GR64Regs;  break;
8775ffd83dbSDimitry Andric   case GR128Reg: Regs = SystemZMC::GR128Regs; break;
8785ffd83dbSDimitry Andric   case FP32Reg:  Regs = SystemZMC::FP32Regs;  break;
8795ffd83dbSDimitry Andric   case FP64Reg:  Regs = SystemZMC::FP64Regs;  break;
8805ffd83dbSDimitry Andric   case FP128Reg: Regs = SystemZMC::FP128Regs; break;
8815ffd83dbSDimitry Andric   case VR32Reg:  Regs = SystemZMC::VR32Regs;  break;
8825ffd83dbSDimitry Andric   case VR64Reg:  Regs = SystemZMC::VR64Regs;  break;
8835ffd83dbSDimitry Andric   case VR128Reg: Regs = SystemZMC::VR128Regs; break;
8845ffd83dbSDimitry Andric   case AR32Reg:  Regs = SystemZMC::AR32Regs;  break;
8855ffd83dbSDimitry Andric   case CR64Reg:  Regs = SystemZMC::CR64Regs;  break;
8865ffd83dbSDimitry Andric   }
8875f757f3fSDimitry Andric   if (Regs[Reg.Num] == 0)
8885f757f3fSDimitry Andric     return Error(Reg.StartLoc, "invalid register pair");
8895ffd83dbSDimitry Andric 
8905ffd83dbSDimitry Andric   Operands.push_back(
8915ffd83dbSDimitry Andric       SystemZOperand::createReg(Kind, Regs[Reg.Num], Reg.StartLoc, Reg.EndLoc));
8925f757f3fSDimitry Andric   return ParseStatus::Success;
8930b57cec5SDimitry Andric }
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric // Parse any type of register (including integers) and add it to Operands.
parseAnyRegister(OperandVector & Operands)8965f757f3fSDimitry Andric ParseStatus SystemZAsmParser::parseAnyRegister(OperandVector &Operands) {
897e8d8bef9SDimitry Andric   SMLoc StartLoc = Parser.getTok().getLoc();
898e8d8bef9SDimitry Andric 
8990b57cec5SDimitry Andric   // Handle integer values.
9000b57cec5SDimitry Andric   if (Parser.getTok().is(AsmToken::Integer)) {
9010b57cec5SDimitry Andric     const MCExpr *Register;
9020b57cec5SDimitry Andric     if (Parser.parseExpression(Register))
9035f757f3fSDimitry Andric       return ParseStatus::Failure;
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric     if (auto *CE = dyn_cast<MCConstantExpr>(Register)) {
9060b57cec5SDimitry Andric       int64_t Value = CE->getValue();
9075f757f3fSDimitry Andric       if (Value < 0 || Value > 15)
9085f757f3fSDimitry Andric         return Error(StartLoc, "invalid register");
9090b57cec5SDimitry Andric     }
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric     SMLoc EndLoc =
9120b57cec5SDimitry Andric       SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric     Operands.push_back(SystemZOperand::createImm(Register, StartLoc, EndLoc));
9150b57cec5SDimitry Andric   }
9160b57cec5SDimitry Andric   else {
917fe6060f1SDimitry Andric     if (isParsingHLASM())
9185f757f3fSDimitry Andric       return ParseStatus::NoMatch;
919fe6060f1SDimitry Andric 
9200b57cec5SDimitry Andric     Register Reg;
9210b57cec5SDimitry Andric     if (parseRegister(Reg))
9225f757f3fSDimitry Andric       return ParseStatus::Failure;
9230b57cec5SDimitry Andric 
9245f757f3fSDimitry Andric     if (Reg.Num > 15)
9255f757f3fSDimitry Andric       return Error(StartLoc, "invalid register");
926e8d8bef9SDimitry Andric 
9270b57cec5SDimitry Andric     // Map to the correct register kind.
9280b57cec5SDimitry Andric     RegisterKind Kind;
9290b57cec5SDimitry Andric     unsigned RegNo;
9300b57cec5SDimitry Andric     if (Reg.Group == RegGR) {
9310b57cec5SDimitry Andric       Kind = GR64Reg;
9320b57cec5SDimitry Andric       RegNo = SystemZMC::GR64Regs[Reg.Num];
9330b57cec5SDimitry Andric     }
9340b57cec5SDimitry Andric     else if (Reg.Group == RegFP) {
9350b57cec5SDimitry Andric       Kind = FP64Reg;
9360b57cec5SDimitry Andric       RegNo = SystemZMC::FP64Regs[Reg.Num];
9370b57cec5SDimitry Andric     }
9380b57cec5SDimitry Andric     else if (Reg.Group == RegV) {
9390b57cec5SDimitry Andric       Kind = VR128Reg;
9400b57cec5SDimitry Andric       RegNo = SystemZMC::VR128Regs[Reg.Num];
9410b57cec5SDimitry Andric     }
9420b57cec5SDimitry Andric     else if (Reg.Group == RegAR) {
9430b57cec5SDimitry Andric       Kind = AR32Reg;
9440b57cec5SDimitry Andric       RegNo = SystemZMC::AR32Regs[Reg.Num];
9450b57cec5SDimitry Andric     }
9460b57cec5SDimitry Andric     else if (Reg.Group == RegCR) {
9470b57cec5SDimitry Andric       Kind = CR64Reg;
9480b57cec5SDimitry Andric       RegNo = SystemZMC::CR64Regs[Reg.Num];
9490b57cec5SDimitry Andric     }
9500b57cec5SDimitry Andric     else {
9515f757f3fSDimitry Andric       return ParseStatus::Failure;
9520b57cec5SDimitry Andric     }
9530b57cec5SDimitry Andric 
9540b57cec5SDimitry Andric     Operands.push_back(SystemZOperand::createReg(Kind, RegNo,
9550b57cec5SDimitry Andric                                                  Reg.StartLoc, Reg.EndLoc));
9560b57cec5SDimitry Andric   }
9575f757f3fSDimitry Andric   return ParseStatus::Success;
9580b57cec5SDimitry Andric }
9590b57cec5SDimitry Andric 
parseIntegerRegister(Register & Reg,RegisterGroup Group)9605ffd83dbSDimitry Andric bool SystemZAsmParser::parseIntegerRegister(Register &Reg,
9615ffd83dbSDimitry Andric                                             RegisterGroup Group) {
9625ffd83dbSDimitry Andric   Reg.StartLoc = Parser.getTok().getLoc();
9635ffd83dbSDimitry Andric   // We have an integer token
9645ffd83dbSDimitry Andric   const MCExpr *Register;
9655ffd83dbSDimitry Andric   if (Parser.parseExpression(Register))
9665ffd83dbSDimitry Andric     return true;
9675ffd83dbSDimitry Andric 
9685ffd83dbSDimitry Andric   const auto *CE = dyn_cast<MCConstantExpr>(Register);
9695ffd83dbSDimitry Andric   if (!CE)
9705ffd83dbSDimitry Andric     return true;
9715ffd83dbSDimitry Andric 
9725ffd83dbSDimitry Andric   int64_t MaxRegNum = (Group == RegV) ? 31 : 15;
9735ffd83dbSDimitry Andric   int64_t Value = CE->getValue();
9745ffd83dbSDimitry Andric   if (Value < 0 || Value > MaxRegNum) {
9755ffd83dbSDimitry Andric     Error(Parser.getTok().getLoc(), "invalid register");
9765ffd83dbSDimitry Andric     return true;
9775ffd83dbSDimitry Andric   }
9785ffd83dbSDimitry Andric 
9795ffd83dbSDimitry Andric   // Assign the Register Number
9805ffd83dbSDimitry Andric   Reg.Num = (unsigned)Value;
9815ffd83dbSDimitry Andric   Reg.Group = Group;
9825ffd83dbSDimitry Andric   Reg.EndLoc = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
9835ffd83dbSDimitry Andric 
9845ffd83dbSDimitry Andric   // At this point, successfully parsed an integer register.
9855ffd83dbSDimitry Andric   return false;
9865ffd83dbSDimitry Andric }
9875ffd83dbSDimitry Andric 
9880b57cec5SDimitry Andric // 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)9890b57cec5SDimitry Andric bool SystemZAsmParser::parseAddress(bool &HaveReg1, Register &Reg1,
9900b57cec5SDimitry Andric                                     bool &HaveReg2, Register &Reg2,
9915ffd83dbSDimitry Andric                                     const MCExpr *&Disp, const MCExpr *&Length,
9925ffd83dbSDimitry Andric                                     bool HasLength, bool HasVectorIndex) {
9930b57cec5SDimitry Andric   // Parse the displacement, which must always be present.
9940b57cec5SDimitry Andric   if (getParser().parseExpression(Disp))
9950b57cec5SDimitry Andric     return true;
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric   // Parse the optional base and index.
9980b57cec5SDimitry Andric   HaveReg1 = false;
9990b57cec5SDimitry Andric   HaveReg2 = false;
10000b57cec5SDimitry Andric   Length = nullptr;
10015ffd83dbSDimitry Andric 
10025ffd83dbSDimitry Andric   // If we have a scenario as below:
10035ffd83dbSDimitry Andric   //   vgef %v0, 0(0), 0
10045ffd83dbSDimitry Andric   // This is an example of a "BDVMem" instruction type.
10055ffd83dbSDimitry Andric   //
10065ffd83dbSDimitry Andric   // So when we parse this as an integer register, the register group
10075ffd83dbSDimitry Andric   // needs to be tied to "RegV". Usually when the prefix is passed in
10085ffd83dbSDimitry Andric   // as %<prefix><reg-number> its easy to check which group it should belong to
10095ffd83dbSDimitry Andric   // However, if we're passing in just the integer there's no real way to
10105ffd83dbSDimitry Andric   // "check" what register group it should belong to.
10115ffd83dbSDimitry Andric   //
10125ffd83dbSDimitry Andric   // When the user passes in the register as an integer, the user assumes that
10135ffd83dbSDimitry Andric   // the compiler is responsible for substituting it as the right kind of
10145ffd83dbSDimitry Andric   // register. Whereas, when the user specifies a "prefix", the onus is on
10155ffd83dbSDimitry Andric   // the user to make sure they pass in the right kind of register.
10165ffd83dbSDimitry Andric   //
10175ffd83dbSDimitry Andric   // The restriction only applies to the first Register (i.e. Reg1). Reg2 is
10185ffd83dbSDimitry Andric   // always a general register. Reg1 should be of group RegV if "HasVectorIndex"
10195ffd83dbSDimitry Andric   // (i.e. insn is of type BDVMem) is true.
10205ffd83dbSDimitry Andric   RegisterGroup RegGroup = HasVectorIndex ? RegV : RegGR;
10215ffd83dbSDimitry Andric 
10220b57cec5SDimitry Andric   if (getLexer().is(AsmToken::LParen)) {
10230b57cec5SDimitry Andric     Parser.Lex();
10240b57cec5SDimitry Andric 
1025fe6060f1SDimitry Andric     if (isParsingATT() && getLexer().is(AsmToken::Percent)) {
10260b57cec5SDimitry Andric       // Parse the first register.
10270b57cec5SDimitry Andric       HaveReg1 = true;
10280b57cec5SDimitry Andric       if (parseRegister(Reg1))
10290b57cec5SDimitry Andric         return true;
10305ffd83dbSDimitry Andric     }
10315ffd83dbSDimitry Andric     // So if we have an integer as the first token in ([tok1], ..), it could:
10325ffd83dbSDimitry Andric     // 1. Refer to a "Register" (i.e X,R,V fields in BD[X|R|V]Mem type of
10335ffd83dbSDimitry Andric     // instructions)
10345ffd83dbSDimitry Andric     // 2. Refer to a "Length" field (i.e L field in BDLMem type of instructions)
10355ffd83dbSDimitry Andric     else if (getLexer().is(AsmToken::Integer)) {
10365ffd83dbSDimitry Andric       if (HasLength) {
10375ffd83dbSDimitry Andric         // Instruction has a "Length" field, safe to parse the first token as
10385ffd83dbSDimitry Andric         // the "Length" field
10390b57cec5SDimitry Andric         if (getParser().parseExpression(Length))
10400b57cec5SDimitry Andric           return true;
10415ffd83dbSDimitry Andric       } else {
10425ffd83dbSDimitry Andric         // Otherwise, if the instruction has no "Length" field, parse the
10435ffd83dbSDimitry Andric         // token as a "Register". We don't have to worry about whether the
10445ffd83dbSDimitry Andric         // instruction is invalid here, because the caller will take care of
10455ffd83dbSDimitry Andric         // error reporting.
10465ffd83dbSDimitry Andric         HaveReg1 = true;
10475ffd83dbSDimitry Andric         if (parseIntegerRegister(Reg1, RegGroup))
10485ffd83dbSDimitry Andric           return true;
10495ffd83dbSDimitry Andric       }
10505ffd83dbSDimitry Andric     } else {
10515ffd83dbSDimitry Andric       // If its not an integer or a percent token, then if the instruction
10525ffd83dbSDimitry Andric       // is reported to have a "Length" then, parse it as "Length".
10535ffd83dbSDimitry Andric       if (HasLength) {
10545ffd83dbSDimitry Andric         if (getParser().parseExpression(Length))
10555ffd83dbSDimitry Andric           return true;
10565ffd83dbSDimitry Andric       }
10570b57cec5SDimitry Andric     }
10580b57cec5SDimitry Andric 
10590b57cec5SDimitry Andric     // Check whether there's a second register.
10600b57cec5SDimitry Andric     if (getLexer().is(AsmToken::Comma)) {
10610b57cec5SDimitry Andric       Parser.Lex();
10620b57cec5SDimitry Andric       HaveReg2 = true;
10635ffd83dbSDimitry Andric 
10645ffd83dbSDimitry Andric       if (getLexer().is(AsmToken::Integer)) {
10655ffd83dbSDimitry Andric         if (parseIntegerRegister(Reg2, RegGR))
10665ffd83dbSDimitry Andric           return true;
10675ffd83dbSDimitry Andric       } else {
1068fe6060f1SDimitry Andric         if (isParsingATT() && parseRegister(Reg2))
10690b57cec5SDimitry Andric           return true;
10700b57cec5SDimitry Andric       }
10715ffd83dbSDimitry Andric     }
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric     // Consume the closing bracket.
10740b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::RParen))
10750b57cec5SDimitry Andric       return Error(Parser.getTok().getLoc(), "unexpected token in address");
10760b57cec5SDimitry Andric     Parser.Lex();
10770b57cec5SDimitry Andric   }
10780b57cec5SDimitry Andric   return false;
10790b57cec5SDimitry Andric }
10800b57cec5SDimitry Andric 
10810b57cec5SDimitry Andric // Verify that Reg is a valid address register (base or index).
10820b57cec5SDimitry Andric bool
parseAddressRegister(Register & Reg)10830b57cec5SDimitry Andric SystemZAsmParser::parseAddressRegister(Register &Reg) {
10840b57cec5SDimitry Andric   if (Reg.Group == RegV) {
10850b57cec5SDimitry Andric     Error(Reg.StartLoc, "invalid use of vector addressing");
10860b57cec5SDimitry Andric     return true;
10875f757f3fSDimitry Andric   }
10885f757f3fSDimitry Andric   if (Reg.Group != RegGR) {
10890b57cec5SDimitry Andric     Error(Reg.StartLoc, "invalid address register");
10900b57cec5SDimitry Andric     return true;
10910b57cec5SDimitry Andric   }
10920b57cec5SDimitry Andric   return false;
10930b57cec5SDimitry Andric }
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric // Parse a memory operand and add it to Operands.  The other arguments
10960b57cec5SDimitry Andric // are as above.
parseAddress(OperandVector & Operands,MemoryKind MemKind,RegisterKind RegKind)10975f757f3fSDimitry Andric ParseStatus SystemZAsmParser::parseAddress(OperandVector &Operands,
10985f757f3fSDimitry Andric                                            MemoryKind MemKind,
10995ffd83dbSDimitry Andric                                            RegisterKind RegKind) {
11000b57cec5SDimitry Andric   SMLoc StartLoc = Parser.getTok().getLoc();
11010b57cec5SDimitry Andric   unsigned Base = 0, Index = 0, LengthReg = 0;
11020b57cec5SDimitry Andric   Register Reg1, Reg2;
11030b57cec5SDimitry Andric   bool HaveReg1, HaveReg2;
11040b57cec5SDimitry Andric   const MCExpr *Disp;
11050b57cec5SDimitry Andric   const MCExpr *Length;
11065ffd83dbSDimitry Andric 
11075ffd83dbSDimitry Andric   bool HasLength = (MemKind == BDLMem) ? true : false;
11085ffd83dbSDimitry Andric   bool HasVectorIndex = (MemKind == BDVMem) ? true : false;
11095ffd83dbSDimitry Andric   if (parseAddress(HaveReg1, Reg1, HaveReg2, Reg2, Disp, Length, HasLength,
11105ffd83dbSDimitry Andric                    HasVectorIndex))
11115f757f3fSDimitry Andric     return ParseStatus::Failure;
11120b57cec5SDimitry Andric 
11135ffd83dbSDimitry Andric   const unsigned *Regs;
11145ffd83dbSDimitry Andric   switch (RegKind) {
11155ffd83dbSDimitry Andric   case GR32Reg: Regs = SystemZMC::GR32Regs; break;
11165ffd83dbSDimitry Andric   case GR64Reg: Regs = SystemZMC::GR64Regs; break;
11175ffd83dbSDimitry Andric   default: llvm_unreachable("invalid RegKind");
11185ffd83dbSDimitry Andric   }
11195ffd83dbSDimitry Andric 
11200b57cec5SDimitry Andric   switch (MemKind) {
11210b57cec5SDimitry Andric   case BDMem:
11220b57cec5SDimitry Andric     // If we have Reg1, it must be an address register.
11230b57cec5SDimitry Andric     if (HaveReg1) {
11240b57cec5SDimitry Andric       if (parseAddressRegister(Reg1))
11255f757f3fSDimitry Andric         return ParseStatus::Failure;
11265f757f3fSDimitry Andric       Base = Reg1.Num == 0 ? 0 : Regs[Reg1.Num];
11270b57cec5SDimitry Andric     }
11285ffd83dbSDimitry Andric     // There must be no Reg2.
11295f757f3fSDimitry Andric     if (HaveReg2)
11305f757f3fSDimitry Andric       return Error(StartLoc, "invalid use of indexed addressing");
11310b57cec5SDimitry Andric     break;
11320b57cec5SDimitry Andric   case BDXMem:
11330b57cec5SDimitry Andric     // If we have Reg1, it must be an address register.
11340b57cec5SDimitry Andric     if (HaveReg1) {
11350b57cec5SDimitry Andric       if (parseAddressRegister(Reg1))
11365f757f3fSDimitry Andric         return ParseStatus::Failure;
11370b57cec5SDimitry Andric       // If the are two registers, the first one is the index and the
11380b57cec5SDimitry Andric       // second is the base.
11390b57cec5SDimitry Andric       if (HaveReg2)
11405f757f3fSDimitry Andric         Index = Reg1.Num == 0 ? 0 : Regs[Reg1.Num];
11410b57cec5SDimitry Andric       else
11425f757f3fSDimitry Andric         Base = Reg1.Num == 0 ? 0 : Regs[Reg1.Num];
11430b57cec5SDimitry Andric     }
11440b57cec5SDimitry Andric     // If we have Reg2, it must be an address register.
11450b57cec5SDimitry Andric     if (HaveReg2) {
11460b57cec5SDimitry Andric       if (parseAddressRegister(Reg2))
11475f757f3fSDimitry Andric         return ParseStatus::Failure;
11485f757f3fSDimitry Andric       Base = Reg2.Num == 0 ? 0 : Regs[Reg2.Num];
11490b57cec5SDimitry Andric     }
11500b57cec5SDimitry Andric     break;
11510b57cec5SDimitry Andric   case BDLMem:
11520b57cec5SDimitry Andric     // If we have Reg2, it must be an address register.
11530b57cec5SDimitry Andric     if (HaveReg2) {
11540b57cec5SDimitry Andric       if (parseAddressRegister(Reg2))
11555f757f3fSDimitry Andric         return ParseStatus::Failure;
11565f757f3fSDimitry Andric       Base = Reg2.Num == 0 ? 0 : Regs[Reg2.Num];
11570b57cec5SDimitry Andric     }
11580b57cec5SDimitry Andric     // We cannot support base+index addressing.
11595f757f3fSDimitry Andric     if (HaveReg1 && HaveReg2)
11605f757f3fSDimitry Andric       return Error(StartLoc, "invalid use of indexed addressing");
11610b57cec5SDimitry Andric     // We must have a length.
11625f757f3fSDimitry Andric     if (!Length)
11635f757f3fSDimitry Andric       return Error(StartLoc, "missing length in address");
11640b57cec5SDimitry Andric     break;
11650b57cec5SDimitry Andric   case BDRMem:
11660b57cec5SDimitry Andric     // We must have Reg1, and it must be a GPR.
11675f757f3fSDimitry Andric     if (!HaveReg1 || Reg1.Group != RegGR)
11685f757f3fSDimitry Andric       return Error(StartLoc, "invalid operand for instruction");
11690b57cec5SDimitry Andric     LengthReg = SystemZMC::GR64Regs[Reg1.Num];
11700b57cec5SDimitry Andric     // If we have Reg2, it must be an address register.
11710b57cec5SDimitry Andric     if (HaveReg2) {
11720b57cec5SDimitry Andric       if (parseAddressRegister(Reg2))
11735f757f3fSDimitry Andric         return ParseStatus::Failure;
11745f757f3fSDimitry Andric       Base = Reg2.Num == 0 ? 0 : Regs[Reg2.Num];
11750b57cec5SDimitry Andric     }
11760b57cec5SDimitry Andric     break;
11770b57cec5SDimitry Andric   case BDVMem:
11780b57cec5SDimitry Andric     // We must have Reg1, and it must be a vector register.
11795f757f3fSDimitry Andric     if (!HaveReg1 || Reg1.Group != RegV)
11805f757f3fSDimitry Andric       return Error(StartLoc, "vector index required in address");
11810b57cec5SDimitry Andric     Index = SystemZMC::VR128Regs[Reg1.Num];
11820b57cec5SDimitry Andric     // If we have Reg2, it must be an address register.
11830b57cec5SDimitry Andric     if (HaveReg2) {
11840b57cec5SDimitry Andric       if (parseAddressRegister(Reg2))
11855f757f3fSDimitry Andric         return ParseStatus::Failure;
11865f757f3fSDimitry Andric       Base = Reg2.Num == 0 ? 0 : Regs[Reg2.Num];
11870b57cec5SDimitry Andric     }
11880b57cec5SDimitry Andric     break;
11890b57cec5SDimitry Andric   }
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric   SMLoc EndLoc =
11920b57cec5SDimitry Andric       SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
11930b57cec5SDimitry Andric   Operands.push_back(SystemZOperand::createMem(MemKind, RegKind, Base, Disp,
11940b57cec5SDimitry Andric                                                Index, Length, LengthReg,
11950b57cec5SDimitry Andric                                                StartLoc, EndLoc));
11965f757f3fSDimitry Andric   return ParseStatus::Success;
11970b57cec5SDimitry Andric }
11980b57cec5SDimitry Andric 
parseDirective(AsmToken DirectiveID)119906c3fb27SDimitry Andric ParseStatus SystemZAsmParser::parseDirective(AsmToken DirectiveID) {
12000b57cec5SDimitry Andric   StringRef IDVal = DirectiveID.getIdentifier();
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric   if (IDVal == ".insn")
12030b57cec5SDimitry Andric     return ParseDirectiveInsn(DirectiveID.getLoc());
1204349cc55cSDimitry Andric   if (IDVal == ".machine")
1205349cc55cSDimitry Andric     return ParseDirectiveMachine(DirectiveID.getLoc());
12065f757f3fSDimitry Andric   if (IDVal.starts_with(".gnu_attribute"))
1207bdd1243dSDimitry Andric     return ParseGNUAttribute(DirectiveID.getLoc());
12080b57cec5SDimitry Andric 
120906c3fb27SDimitry Andric   return ParseStatus::NoMatch;
12100b57cec5SDimitry Andric }
12110b57cec5SDimitry Andric 
12120b57cec5SDimitry Andric /// ParseDirectiveInsn
12130b57cec5SDimitry Andric /// ::= .insn [ format, encoding, (operands (, operands)*) ]
ParseDirectiveInsn(SMLoc L)12140b57cec5SDimitry Andric bool SystemZAsmParser::ParseDirectiveInsn(SMLoc L) {
12150b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
12160b57cec5SDimitry Andric 
12170b57cec5SDimitry Andric   // Expect instruction format as identifier.
12180b57cec5SDimitry Andric   StringRef Format;
12190b57cec5SDimitry Andric   SMLoc ErrorLoc = Parser.getTok().getLoc();
12200b57cec5SDimitry Andric   if (Parser.parseIdentifier(Format))
12210b57cec5SDimitry Andric     return Error(ErrorLoc, "expected instruction format");
12220b57cec5SDimitry Andric 
12230b57cec5SDimitry Andric   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;
12240b57cec5SDimitry Andric 
12250b57cec5SDimitry Andric   // Find entry for this format in InsnMatchTable.
12260b57cec5SDimitry Andric   auto EntryRange =
12270b57cec5SDimitry Andric     std::equal_range(std::begin(InsnMatchTable), std::end(InsnMatchTable),
12280b57cec5SDimitry Andric                      Format, CompareInsn());
12290b57cec5SDimitry Andric 
12300b57cec5SDimitry Andric   // If first == second, couldn't find a match in the table.
12310b57cec5SDimitry Andric   if (EntryRange.first == EntryRange.second)
12320b57cec5SDimitry Andric     return Error(ErrorLoc, "unrecognized format");
12330b57cec5SDimitry Andric 
12340b57cec5SDimitry Andric   struct InsnMatchEntry *Entry = EntryRange.first;
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric   // Format should match from equal_range.
12370b57cec5SDimitry Andric   assert(Entry->Format == Format);
12380b57cec5SDimitry Andric 
12390b57cec5SDimitry Andric   // Parse the following operands using the table's information.
12405f757f3fSDimitry Andric   for (int I = 0; I < Entry->NumOperands; I++) {
12415f757f3fSDimitry Andric     MatchClassKind Kind = Entry->OperandKinds[I];
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric     SMLoc StartLoc = Parser.getTok().getLoc();
12440b57cec5SDimitry Andric 
12450b57cec5SDimitry Andric     // Always expect commas as separators for operands.
12460b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::Comma))
12470b57cec5SDimitry Andric       return Error(StartLoc, "unexpected token in directive");
12480b57cec5SDimitry Andric     Lex();
12490b57cec5SDimitry Andric 
12500b57cec5SDimitry Andric     // Parse operands.
12515f757f3fSDimitry Andric     ParseStatus ResTy;
12520b57cec5SDimitry Andric     if (Kind == MCK_AnyReg)
12530b57cec5SDimitry Andric       ResTy = parseAnyReg(Operands);
1254e8d8bef9SDimitry Andric     else if (Kind == MCK_VR128)
1255e8d8bef9SDimitry Andric       ResTy = parseVR128(Operands);
12560b57cec5SDimitry Andric     else if (Kind == MCK_BDXAddr64Disp12 || Kind == MCK_BDXAddr64Disp20)
12570b57cec5SDimitry Andric       ResTy = parseBDXAddr64(Operands);
12580b57cec5SDimitry Andric     else if (Kind == MCK_BDAddr64Disp12 || Kind == MCK_BDAddr64Disp20)
12590b57cec5SDimitry Andric       ResTy = parseBDAddr64(Operands);
1260e8d8bef9SDimitry Andric     else if (Kind == MCK_BDVAddr64Disp12)
1261e8d8bef9SDimitry Andric       ResTy = parseBDVAddr64(Operands);
12620b57cec5SDimitry Andric     else if (Kind == MCK_PCRel32)
12630b57cec5SDimitry Andric       ResTy = parsePCRel32(Operands);
12640b57cec5SDimitry Andric     else if (Kind == MCK_PCRel16)
12650b57cec5SDimitry Andric       ResTy = parsePCRel16(Operands);
12660b57cec5SDimitry Andric     else {
12670b57cec5SDimitry Andric       // Only remaining operand kind is an immediate.
12680b57cec5SDimitry Andric       const MCExpr *Expr;
12690b57cec5SDimitry Andric       SMLoc StartLoc = Parser.getTok().getLoc();
12700b57cec5SDimitry Andric 
12710b57cec5SDimitry Andric       // Expect immediate expression.
12720b57cec5SDimitry Andric       if (Parser.parseExpression(Expr))
12730b57cec5SDimitry Andric         return Error(StartLoc, "unexpected token in directive");
12740b57cec5SDimitry Andric 
12750b57cec5SDimitry Andric       SMLoc EndLoc =
12760b57cec5SDimitry Andric         SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
12770b57cec5SDimitry Andric 
12780b57cec5SDimitry Andric       Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));
12795f757f3fSDimitry Andric       ResTy = ParseStatus::Success;
12800b57cec5SDimitry Andric     }
12810b57cec5SDimitry Andric 
12825f757f3fSDimitry Andric     if (!ResTy.isSuccess())
12830b57cec5SDimitry Andric       return true;
12840b57cec5SDimitry Andric   }
12850b57cec5SDimitry Andric 
12860b57cec5SDimitry Andric   // Build the instruction with the parsed operands.
12870b57cec5SDimitry Andric   MCInst Inst = MCInstBuilder(Entry->Opcode);
12880b57cec5SDimitry Andric 
12895f757f3fSDimitry Andric   for (size_t I = 0; I < Operands.size(); I++) {
12905f757f3fSDimitry Andric     MCParsedAsmOperand &Operand = *Operands[I];
12915f757f3fSDimitry Andric     MatchClassKind Kind = Entry->OperandKinds[I];
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric     // Verify operand.
12940b57cec5SDimitry Andric     unsigned Res = validateOperandClass(Operand, Kind);
12950b57cec5SDimitry Andric     if (Res != Match_Success)
12960b57cec5SDimitry Andric       return Error(Operand.getStartLoc(), "unexpected operand type");
12970b57cec5SDimitry Andric 
12980b57cec5SDimitry Andric     // Add operands to instruction.
12990b57cec5SDimitry Andric     SystemZOperand &ZOperand = static_cast<SystemZOperand &>(Operand);
13000b57cec5SDimitry Andric     if (ZOperand.isReg())
13010b57cec5SDimitry Andric       ZOperand.addRegOperands(Inst, 1);
13020b57cec5SDimitry Andric     else if (ZOperand.isMem(BDMem))
13030b57cec5SDimitry Andric       ZOperand.addBDAddrOperands(Inst, 2);
13040b57cec5SDimitry Andric     else if (ZOperand.isMem(BDXMem))
13050b57cec5SDimitry Andric       ZOperand.addBDXAddrOperands(Inst, 3);
1306e8d8bef9SDimitry Andric     else if (ZOperand.isMem(BDVMem))
1307e8d8bef9SDimitry Andric       ZOperand.addBDVAddrOperands(Inst, 3);
13080b57cec5SDimitry Andric     else if (ZOperand.isImm())
13090b57cec5SDimitry Andric       ZOperand.addImmOperands(Inst, 1);
13100b57cec5SDimitry Andric     else
13110b57cec5SDimitry Andric       llvm_unreachable("unexpected operand type");
13120b57cec5SDimitry Andric   }
13130b57cec5SDimitry Andric 
13140b57cec5SDimitry Andric   // Emit as a regular instruction.
13155ffd83dbSDimitry Andric   Parser.getStreamer().emitInstruction(Inst, getSTI());
13160b57cec5SDimitry Andric 
13170b57cec5SDimitry Andric   return false;
13180b57cec5SDimitry Andric }
13190b57cec5SDimitry Andric 
1320349cc55cSDimitry Andric /// ParseDirectiveMachine
1321349cc55cSDimitry Andric /// ::= .machine [ mcpu ]
ParseDirectiveMachine(SMLoc L)1322349cc55cSDimitry Andric bool SystemZAsmParser::ParseDirectiveMachine(SMLoc L) {
1323349cc55cSDimitry Andric   MCAsmParser &Parser = getParser();
1324349cc55cSDimitry Andric   if (Parser.getTok().isNot(AsmToken::Identifier) &&
1325349cc55cSDimitry Andric       Parser.getTok().isNot(AsmToken::String))
132606c3fb27SDimitry Andric     return TokError("unexpected token in '.machine' directive");
1327349cc55cSDimitry Andric 
1328349cc55cSDimitry Andric   StringRef CPU = Parser.getTok().getIdentifier();
1329349cc55cSDimitry Andric   Parser.Lex();
133006c3fb27SDimitry Andric   if (parseEOL())
133106c3fb27SDimitry Andric     return true;
1332349cc55cSDimitry Andric 
1333349cc55cSDimitry Andric   MCSubtargetInfo &STI = copySTI();
1334349cc55cSDimitry Andric   STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, "");
1335349cc55cSDimitry Andric   setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
1336349cc55cSDimitry Andric 
1337349cc55cSDimitry Andric   getTargetStreamer().emitMachine(CPU);
1338349cc55cSDimitry Andric 
1339349cc55cSDimitry Andric   return false;
1340349cc55cSDimitry Andric }
1341349cc55cSDimitry Andric 
ParseGNUAttribute(SMLoc L)1342bdd1243dSDimitry Andric bool SystemZAsmParser::ParseGNUAttribute(SMLoc L) {
1343bdd1243dSDimitry Andric   int64_t Tag;
1344bdd1243dSDimitry Andric   int64_t IntegerValue;
1345bdd1243dSDimitry Andric   if (!Parser.parseGNUAttribute(L, Tag, IntegerValue))
134606c3fb27SDimitry Andric     return Error(L, "malformed .gnu_attribute directive");
1347bdd1243dSDimitry Andric 
1348bdd1243dSDimitry Andric   // Tag_GNU_S390_ABI_Vector tag is '8' and can be 0, 1, or 2.
134906c3fb27SDimitry Andric   if (Tag != 8 || (IntegerValue < 0 || IntegerValue > 2))
135006c3fb27SDimitry Andric     return Error(L, "unrecognized .gnu_attribute tag/value pair.");
1351bdd1243dSDimitry Andric 
1352bdd1243dSDimitry Andric   Parser.getStreamer().emitGNUAttribute(Tag, IntegerValue);
1353bdd1243dSDimitry Andric 
135406c3fb27SDimitry Andric   return parseEOL();
1355bdd1243dSDimitry Andric }
1356bdd1243dSDimitry Andric 
ParseRegister(MCRegister & RegNo,SMLoc & StartLoc,SMLoc & EndLoc,bool RestoreOnFailure)1357bdd1243dSDimitry Andric bool SystemZAsmParser::ParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
13585ffd83dbSDimitry Andric                                      SMLoc &EndLoc, bool RestoreOnFailure) {
13590b57cec5SDimitry Andric   Register Reg;
13605ffd83dbSDimitry Andric   if (parseRegister(Reg, RestoreOnFailure))
13610b57cec5SDimitry Andric     return true;
13620b57cec5SDimitry Andric   if (Reg.Group == RegGR)
13630b57cec5SDimitry Andric     RegNo = SystemZMC::GR64Regs[Reg.Num];
13640b57cec5SDimitry Andric   else if (Reg.Group == RegFP)
13650b57cec5SDimitry Andric     RegNo = SystemZMC::FP64Regs[Reg.Num];
13660b57cec5SDimitry Andric   else if (Reg.Group == RegV)
13670b57cec5SDimitry Andric     RegNo = SystemZMC::VR128Regs[Reg.Num];
13680b57cec5SDimitry Andric   else if (Reg.Group == RegAR)
13690b57cec5SDimitry Andric     RegNo = SystemZMC::AR32Regs[Reg.Num];
13700b57cec5SDimitry Andric   else if (Reg.Group == RegCR)
13710b57cec5SDimitry Andric     RegNo = SystemZMC::CR64Regs[Reg.Num];
13720b57cec5SDimitry Andric   StartLoc = Reg.StartLoc;
13730b57cec5SDimitry Andric   EndLoc = Reg.EndLoc;
13740b57cec5SDimitry Andric   return false;
13750b57cec5SDimitry Andric }
13760b57cec5SDimitry Andric 
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)13775f757f3fSDimitry Andric bool SystemZAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
13785ffd83dbSDimitry Andric                                      SMLoc &EndLoc) {
13795f757f3fSDimitry Andric   return ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/false);
13805ffd83dbSDimitry Andric }
13815ffd83dbSDimitry Andric 
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)13825f757f3fSDimitry Andric ParseStatus SystemZAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
13835ffd83dbSDimitry Andric                                                SMLoc &EndLoc) {
13845f757f3fSDimitry Andric   bool Result = ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/true);
13855ffd83dbSDimitry Andric   bool PendingErrors = getParser().hasPendingError();
13865ffd83dbSDimitry Andric   getParser().clearPendingErrors();
13875ffd83dbSDimitry Andric   if (PendingErrors)
13885f757f3fSDimitry Andric     return ParseStatus::Failure;
13895ffd83dbSDimitry Andric   if (Result)
13905f757f3fSDimitry Andric     return ParseStatus::NoMatch;
13915f757f3fSDimitry Andric   return ParseStatus::Success;
13925ffd83dbSDimitry Andric }
13935ffd83dbSDimitry Andric 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)13940b57cec5SDimitry Andric bool SystemZAsmParser::ParseInstruction(ParseInstructionInfo &Info,
13950b57cec5SDimitry Andric                                         StringRef Name, SMLoc NameLoc,
13960b57cec5SDimitry Andric                                         OperandVector &Operands) {
1397e8d8bef9SDimitry Andric 
1398e8d8bef9SDimitry Andric   // Apply mnemonic aliases first, before doing anything else, in
1399e8d8bef9SDimitry Andric   // case the target uses it.
1400fe6060f1SDimitry Andric   applyMnemonicAliases(Name, getAvailableFeatures(), getMAIAssemblerDialect());
1401e8d8bef9SDimitry Andric 
14020b57cec5SDimitry Andric   Operands.push_back(SystemZOperand::createToken(Name, NameLoc));
14030b57cec5SDimitry Andric 
14040b57cec5SDimitry Andric   // Read the remaining operands.
14050b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
14060b57cec5SDimitry Andric     // Read the first operand.
14070b57cec5SDimitry Andric     if (parseOperand(Operands, Name)) {
14080b57cec5SDimitry Andric       return true;
14090b57cec5SDimitry Andric     }
14100b57cec5SDimitry Andric 
14110b57cec5SDimitry Andric     // Read any subsequent operands.
14120b57cec5SDimitry Andric     while (getLexer().is(AsmToken::Comma)) {
14130b57cec5SDimitry Andric       Parser.Lex();
1414fe6060f1SDimitry Andric 
1415fe6060f1SDimitry Andric       if (isParsingHLASM() && getLexer().is(AsmToken::Space))
1416fe6060f1SDimitry Andric         return Error(
1417fe6060f1SDimitry Andric             Parser.getTok().getLoc(),
1418fe6060f1SDimitry Andric             "No space allowed between comma that separates operand entries");
1419fe6060f1SDimitry Andric 
14200b57cec5SDimitry Andric       if (parseOperand(Operands, Name)) {
14210b57cec5SDimitry Andric         return true;
14220b57cec5SDimitry Andric       }
14230b57cec5SDimitry Andric     }
1424fe6060f1SDimitry Andric 
1425fe6060f1SDimitry Andric     // Under the HLASM variant, we could have the remark field
1426fe6060f1SDimitry Andric     // The remark field occurs after the operation entries
1427fe6060f1SDimitry Andric     // There is a space that separates the operation entries and the
1428fe6060f1SDimitry Andric     // remark field.
1429fe6060f1SDimitry Andric     if (isParsingHLASM() && getTok().is(AsmToken::Space)) {
1430fe6060f1SDimitry Andric       // We've confirmed that there is a Remark field.
1431fe6060f1SDimitry Andric       StringRef Remark(getLexer().LexUntilEndOfStatement());
1432fe6060f1SDimitry Andric       Parser.Lex();
1433fe6060f1SDimitry Andric 
1434fe6060f1SDimitry Andric       // If there is nothing after the space, then there is nothing to emit
1435fe6060f1SDimitry Andric       // We could have a situation as this:
1436fe6060f1SDimitry Andric       // "  \n"
1437fe6060f1SDimitry Andric       // After lexing above, we will have
1438fe6060f1SDimitry Andric       // "\n"
1439fe6060f1SDimitry Andric       // This isn't an explicit remark field, so we don't have to output
1440fe6060f1SDimitry Andric       // this as a comment.
1441fe6060f1SDimitry Andric       if (Remark.size())
1442fe6060f1SDimitry Andric         // Output the entire Remarks Field as a comment
1443fe6060f1SDimitry Andric         getStreamer().AddComment(Remark);
1444fe6060f1SDimitry Andric     }
1445fe6060f1SDimitry Andric 
14460b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
14470b57cec5SDimitry Andric       SMLoc Loc = getLexer().getLoc();
14480b57cec5SDimitry Andric       return Error(Loc, "unexpected token in argument list");
14490b57cec5SDimitry Andric     }
14500b57cec5SDimitry Andric   }
14510b57cec5SDimitry Andric 
14520b57cec5SDimitry Andric   // Consume the EndOfStatement.
14530b57cec5SDimitry Andric   Parser.Lex();
14540b57cec5SDimitry Andric   return false;
14550b57cec5SDimitry Andric }
14560b57cec5SDimitry Andric 
parseOperand(OperandVector & Operands,StringRef Mnemonic)14570b57cec5SDimitry Andric bool SystemZAsmParser::parseOperand(OperandVector &Operands,
14580b57cec5SDimitry Andric                                     StringRef Mnemonic) {
14590b57cec5SDimitry Andric   // Check if the current operand has a custom associated parser, if so, try to
14600b57cec5SDimitry Andric   // custom parse the operand, or fallback to the general approach.  Force all
14610b57cec5SDimitry Andric   // features to be available during the operand check, or else we will fail to
14620b57cec5SDimitry Andric   // find the custom parser, and then we will later get an InvalidOperand error
14630b57cec5SDimitry Andric   // instead of a MissingFeature errror.
14640b57cec5SDimitry Andric   FeatureBitset AvailableFeatures = getAvailableFeatures();
14650b57cec5SDimitry Andric   FeatureBitset All;
14660b57cec5SDimitry Andric   All.set();
14670b57cec5SDimitry Andric   setAvailableFeatures(All);
14685f757f3fSDimitry Andric   ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
14690b57cec5SDimitry Andric   setAvailableFeatures(AvailableFeatures);
14705f757f3fSDimitry Andric   if (Res.isSuccess())
14710b57cec5SDimitry Andric     return false;
14720b57cec5SDimitry Andric 
14730b57cec5SDimitry Andric   // If there wasn't a custom match, try the generic matcher below. Otherwise,
14740b57cec5SDimitry Andric   // there was a match, but an error occurred, in which case, just return that
14750b57cec5SDimitry Andric   // the operand parsing failed.
14765f757f3fSDimitry Andric   if (Res.isFailure())
14770b57cec5SDimitry Andric     return true;
14780b57cec5SDimitry Andric 
14790b57cec5SDimitry Andric   // Check for a register.  All real register operands should have used
14800b57cec5SDimitry Andric   // a context-dependent parse routine, which gives the required register
14810b57cec5SDimitry Andric   // class.  The code is here to mop up other cases, like those where
14820b57cec5SDimitry Andric   // the instruction isn't recognized.
1483fe6060f1SDimitry Andric   if (isParsingATT() && Parser.getTok().is(AsmToken::Percent)) {
14840b57cec5SDimitry Andric     Register Reg;
14850b57cec5SDimitry Andric     if (parseRegister(Reg))
14860b57cec5SDimitry Andric       return true;
14870b57cec5SDimitry Andric     Operands.push_back(SystemZOperand::createInvalid(Reg.StartLoc, Reg.EndLoc));
14880b57cec5SDimitry Andric     return false;
14890b57cec5SDimitry Andric   }
14900b57cec5SDimitry Andric 
14910b57cec5SDimitry Andric   // The only other type of operand is an immediate or address.  As above,
14920b57cec5SDimitry Andric   // real address operands should have used a context-dependent parse routine,
14930b57cec5SDimitry Andric   // so we treat any plain expression as an immediate.
14940b57cec5SDimitry Andric   SMLoc StartLoc = Parser.getTok().getLoc();
14950b57cec5SDimitry Andric   Register Reg1, Reg2;
14960b57cec5SDimitry Andric   bool HaveReg1, HaveReg2;
14970b57cec5SDimitry Andric   const MCExpr *Expr;
14980b57cec5SDimitry Andric   const MCExpr *Length;
14995ffd83dbSDimitry Andric   if (parseAddress(HaveReg1, Reg1, HaveReg2, Reg2, Expr, Length,
15005ffd83dbSDimitry Andric                    /*HasLength*/ true, /*HasVectorIndex*/ true))
15010b57cec5SDimitry Andric     return true;
15020b57cec5SDimitry Andric   // If the register combination is not valid for any instruction, reject it.
15030b57cec5SDimitry Andric   // Otherwise, fall back to reporting an unrecognized instruction.
15040b57cec5SDimitry Andric   if (HaveReg1 && Reg1.Group != RegGR && Reg1.Group != RegV
15050b57cec5SDimitry Andric       && parseAddressRegister(Reg1))
15060b57cec5SDimitry Andric     return true;
15070b57cec5SDimitry Andric   if (HaveReg2 && parseAddressRegister(Reg2))
15080b57cec5SDimitry Andric     return true;
15090b57cec5SDimitry Andric 
15100b57cec5SDimitry Andric   SMLoc EndLoc =
15110b57cec5SDimitry Andric     SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
15120b57cec5SDimitry Andric   if (HaveReg1 || HaveReg2 || Length)
15130b57cec5SDimitry Andric     Operands.push_back(SystemZOperand::createInvalid(StartLoc, EndLoc));
15140b57cec5SDimitry Andric   else
15150b57cec5SDimitry Andric     Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));
15160b57cec5SDimitry Andric   return false;
15170b57cec5SDimitry Andric }
15180b57cec5SDimitry Andric 
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)15190b57cec5SDimitry Andric bool SystemZAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
15200b57cec5SDimitry Andric                                                OperandVector &Operands,
15210b57cec5SDimitry Andric                                                MCStreamer &Out,
15220b57cec5SDimitry Andric                                                uint64_t &ErrorInfo,
15230b57cec5SDimitry Andric                                                bool MatchingInlineAsm) {
15240b57cec5SDimitry Andric   MCInst Inst;
15250b57cec5SDimitry Andric   unsigned MatchResult;
15260b57cec5SDimitry Andric 
1527fe6060f1SDimitry Andric   unsigned Dialect = getMAIAssemblerDialect();
1528fe6060f1SDimitry Andric 
15290b57cec5SDimitry Andric   FeatureBitset MissingFeatures;
1530fe6060f1SDimitry Andric   MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1531fe6060f1SDimitry Andric                                      MatchingInlineAsm, Dialect);
15320b57cec5SDimitry Andric   switch (MatchResult) {
15330b57cec5SDimitry Andric   case Match_Success:
15340b57cec5SDimitry Andric     Inst.setLoc(IDLoc);
15355ffd83dbSDimitry Andric     Out.emitInstruction(Inst, getSTI());
15360b57cec5SDimitry Andric     return false;
15370b57cec5SDimitry Andric 
15380b57cec5SDimitry Andric   case Match_MissingFeature: {
15390b57cec5SDimitry Andric     assert(MissingFeatures.any() && "Unknown missing feature!");
15400b57cec5SDimitry Andric     // Special case the error message for the very common case where only
15410b57cec5SDimitry Andric     // a single subtarget feature is missing
15420b57cec5SDimitry Andric     std::string Msg = "instruction requires:";
15430b57cec5SDimitry Andric     for (unsigned I = 0, E = MissingFeatures.size(); I != E; ++I) {
15440b57cec5SDimitry Andric       if (MissingFeatures[I]) {
15450b57cec5SDimitry Andric         Msg += " ";
15460b57cec5SDimitry Andric         Msg += getSubtargetFeatureName(I);
15470b57cec5SDimitry Andric       }
15480b57cec5SDimitry Andric     }
15490b57cec5SDimitry Andric     return Error(IDLoc, Msg);
15500b57cec5SDimitry Andric   }
15510b57cec5SDimitry Andric 
15520b57cec5SDimitry Andric   case Match_InvalidOperand: {
15530b57cec5SDimitry Andric     SMLoc ErrorLoc = IDLoc;
15540b57cec5SDimitry Andric     if (ErrorInfo != ~0ULL) {
15550b57cec5SDimitry Andric       if (ErrorInfo >= Operands.size())
15560b57cec5SDimitry Andric         return Error(IDLoc, "too few operands for instruction");
15570b57cec5SDimitry Andric 
15580b57cec5SDimitry Andric       ErrorLoc = ((SystemZOperand &)*Operands[ErrorInfo]).getStartLoc();
15590b57cec5SDimitry Andric       if (ErrorLoc == SMLoc())
15600b57cec5SDimitry Andric         ErrorLoc = IDLoc;
15610b57cec5SDimitry Andric     }
15620b57cec5SDimitry Andric     return Error(ErrorLoc, "invalid operand for instruction");
15630b57cec5SDimitry Andric   }
15640b57cec5SDimitry Andric 
15650b57cec5SDimitry Andric   case Match_MnemonicFail: {
15660b57cec5SDimitry Andric     FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
15670b57cec5SDimitry Andric     std::string Suggestion = SystemZMnemonicSpellCheck(
1568fe6060f1SDimitry Andric         ((SystemZOperand &)*Operands[0]).getToken(), FBS, Dialect);
15690b57cec5SDimitry Andric     return Error(IDLoc, "invalid instruction" + Suggestion,
15700b57cec5SDimitry Andric                  ((SystemZOperand &)*Operands[0]).getLocRange());
15710b57cec5SDimitry Andric   }
15720b57cec5SDimitry Andric   }
15730b57cec5SDimitry Andric 
15740b57cec5SDimitry Andric   llvm_unreachable("Unexpected match type");
15750b57cec5SDimitry Andric }
15760b57cec5SDimitry Andric 
parsePCRel(OperandVector & Operands,int64_t MinVal,int64_t MaxVal,bool AllowTLS)15775f757f3fSDimitry Andric ParseStatus SystemZAsmParser::parsePCRel(OperandVector &Operands,
15785f757f3fSDimitry Andric                                          int64_t MinVal, int64_t MaxVal,
15795f757f3fSDimitry Andric                                          bool AllowTLS) {
15800b57cec5SDimitry Andric   MCContext &Ctx = getContext();
15810b57cec5SDimitry Andric   MCStreamer &Out = getStreamer();
15820b57cec5SDimitry Andric   const MCExpr *Expr;
15830b57cec5SDimitry Andric   SMLoc StartLoc = Parser.getTok().getLoc();
15840b57cec5SDimitry Andric   if (getParser().parseExpression(Expr))
15855f757f3fSDimitry Andric     return ParseStatus::NoMatch;
15860b57cec5SDimitry Andric 
15875f757f3fSDimitry Andric   auto IsOutOfRangeConstant = [&](const MCExpr *E, bool Negate) -> bool {
1588480093f4SDimitry Andric     if (auto *CE = dyn_cast<MCConstantExpr>(E)) {
1589480093f4SDimitry Andric       int64_t Value = CE->getValue();
159081ad6265SDimitry Andric       if (Negate)
159181ad6265SDimitry Andric         Value = -Value;
1592480093f4SDimitry Andric       if ((Value & 1) || Value < MinVal || Value > MaxVal)
1593480093f4SDimitry Andric         return true;
1594480093f4SDimitry Andric     }
1595480093f4SDimitry Andric     return false;
1596480093f4SDimitry Andric   };
1597480093f4SDimitry Andric 
15980b57cec5SDimitry Andric   // For consistency with the GNU assembler, treat immediates as offsets
15990b57cec5SDimitry Andric   // from ".".
16000b57cec5SDimitry Andric   if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
16015f757f3fSDimitry Andric     if (isParsingHLASM())
16025f757f3fSDimitry Andric       return Error(StartLoc, "Expected PC-relative expression");
16035f757f3fSDimitry Andric     if (IsOutOfRangeConstant(CE, false))
16045f757f3fSDimitry Andric       return Error(StartLoc, "offset out of range");
1605480093f4SDimitry Andric     int64_t Value = CE->getValue();
16060b57cec5SDimitry Andric     MCSymbol *Sym = Ctx.createTempSymbol();
16075ffd83dbSDimitry Andric     Out.emitLabel(Sym);
16080b57cec5SDimitry Andric     const MCExpr *Base = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
16090b57cec5SDimitry Andric                                                  Ctx);
16100b57cec5SDimitry Andric     Expr = Value == 0 ? Base : MCBinaryExpr::createAdd(Base, Expr, Ctx);
16110b57cec5SDimitry Andric   }
16120b57cec5SDimitry Andric 
1613480093f4SDimitry Andric   // For consistency with the GNU assembler, conservatively assume that a
1614480093f4SDimitry Andric   // constant offset must by itself be within the given size range.
1615480093f4SDimitry Andric   if (const auto *BE = dyn_cast<MCBinaryExpr>(Expr))
16165f757f3fSDimitry Andric     if (IsOutOfRangeConstant(BE->getLHS(), false) ||
16175f757f3fSDimitry Andric         IsOutOfRangeConstant(BE->getRHS(),
16185f757f3fSDimitry Andric                              BE->getOpcode() == MCBinaryExpr::Sub))
16195f757f3fSDimitry Andric       return Error(StartLoc, "offset out of range");
1620480093f4SDimitry Andric 
16210b57cec5SDimitry Andric   // Optionally match :tls_gdcall: or :tls_ldcall: followed by a TLS symbol.
16220b57cec5SDimitry Andric   const MCExpr *Sym = nullptr;
16230b57cec5SDimitry Andric   if (AllowTLS && getLexer().is(AsmToken::Colon)) {
16240b57cec5SDimitry Andric     Parser.Lex();
16250b57cec5SDimitry Andric 
16265f757f3fSDimitry Andric     if (Parser.getTok().isNot(AsmToken::Identifier))
16275f757f3fSDimitry Andric       return Error(Parser.getTok().getLoc(), "unexpected token");
16280b57cec5SDimitry Andric 
16290b57cec5SDimitry Andric     MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
16300b57cec5SDimitry Andric     StringRef Name = Parser.getTok().getString();
16310b57cec5SDimitry Andric     if (Name == "tls_gdcall")
16320b57cec5SDimitry Andric       Kind = MCSymbolRefExpr::VK_TLSGD;
16330b57cec5SDimitry Andric     else if (Name == "tls_ldcall")
16340b57cec5SDimitry Andric       Kind = MCSymbolRefExpr::VK_TLSLDM;
16355f757f3fSDimitry Andric     else
16365f757f3fSDimitry Andric       return Error(Parser.getTok().getLoc(), "unknown TLS tag");
16370b57cec5SDimitry Andric     Parser.Lex();
16380b57cec5SDimitry Andric 
16395f757f3fSDimitry Andric     if (Parser.getTok().isNot(AsmToken::Colon))
16405f757f3fSDimitry Andric       return Error(Parser.getTok().getLoc(), "unexpected token");
16410b57cec5SDimitry Andric     Parser.Lex();
16420b57cec5SDimitry Andric 
16435f757f3fSDimitry Andric     if (Parser.getTok().isNot(AsmToken::Identifier))
16445f757f3fSDimitry Andric       return Error(Parser.getTok().getLoc(), "unexpected token");
16450b57cec5SDimitry Andric 
16460b57cec5SDimitry Andric     StringRef Identifier = Parser.getTok().getString();
16470b57cec5SDimitry Andric     Sym = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(Identifier),
16480b57cec5SDimitry Andric                                   Kind, Ctx);
16490b57cec5SDimitry Andric     Parser.Lex();
16500b57cec5SDimitry Andric   }
16510b57cec5SDimitry Andric 
16520b57cec5SDimitry Andric   SMLoc EndLoc =
16530b57cec5SDimitry Andric     SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
16540b57cec5SDimitry Andric 
16550b57cec5SDimitry Andric   if (AllowTLS)
16560b57cec5SDimitry Andric     Operands.push_back(SystemZOperand::createImmTLS(Expr, Sym,
16570b57cec5SDimitry Andric                                                     StartLoc, EndLoc));
16580b57cec5SDimitry Andric   else
16590b57cec5SDimitry Andric     Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));
16600b57cec5SDimitry Andric 
16615f757f3fSDimitry Andric   return ParseStatus::Success;
16620b57cec5SDimitry Andric }
16630b57cec5SDimitry Andric 
isLabel(AsmToken & Token)1664fe6060f1SDimitry Andric bool SystemZAsmParser::isLabel(AsmToken &Token) {
1665fe6060f1SDimitry Andric   if (isParsingATT())
1666fe6060f1SDimitry Andric     return true;
1667fe6060f1SDimitry Andric 
1668fe6060f1SDimitry Andric   // HLASM labels are ordinary symbols.
1669fe6060f1SDimitry Andric   // An HLASM label always starts at column 1.
1670fe6060f1SDimitry Andric   // An ordinary symbol syntax is laid out as follows:
1671fe6060f1SDimitry Andric   // Rules:
1672fe6060f1SDimitry Andric   // 1. Has to start with an "alphabetic character". Can be followed by up to
1673fe6060f1SDimitry Andric   //    62 alphanumeric characters. An "alphabetic character", in this scenario,
1674fe6060f1SDimitry Andric   //    is a letter from 'A' through 'Z', or from 'a' through 'z',
1675fe6060f1SDimitry Andric   //    or '$', '_', '#', or '@'
1676fe6060f1SDimitry Andric   // 2. Labels are case-insensitive. E.g. "lab123", "LAB123", "lAb123", etc.
1677fe6060f1SDimitry Andric   //    are all treated as the same symbol. However, the processing for the case
1678fe6060f1SDimitry Andric   //    folding will not be done in this function.
1679fe6060f1SDimitry Andric   StringRef RawLabel = Token.getString();
1680fe6060f1SDimitry Andric   SMLoc Loc = Token.getLoc();
1681fe6060f1SDimitry Andric 
1682fe6060f1SDimitry Andric   // An HLASM label cannot be empty.
1683fe6060f1SDimitry Andric   if (!RawLabel.size())
1684fe6060f1SDimitry Andric     return !Error(Loc, "HLASM Label cannot be empty");
1685fe6060f1SDimitry Andric 
1686fe6060f1SDimitry Andric   // An HLASM label cannot exceed greater than 63 characters.
1687fe6060f1SDimitry Andric   if (RawLabel.size() > 63)
1688fe6060f1SDimitry Andric     return !Error(Loc, "Maximum length for HLASM Label is 63 characters");
1689fe6060f1SDimitry Andric 
1690fe6060f1SDimitry Andric   // A label must start with an "alphabetic character".
1691fe6060f1SDimitry Andric   if (!isHLASMAlpha(RawLabel[0]))
1692fe6060f1SDimitry Andric     return !Error(Loc, "HLASM Label has to start with an alphabetic "
1693fe6060f1SDimitry Andric                        "character or the underscore character");
1694fe6060f1SDimitry Andric 
1695fe6060f1SDimitry Andric   // Now, we've established that the length is valid
1696fe6060f1SDimitry Andric   // and the first character is alphabetic.
1697fe6060f1SDimitry Andric   // Check whether remaining string is alphanumeric.
1698fe6060f1SDimitry Andric   for (unsigned I = 1; I < RawLabel.size(); ++I)
1699fe6060f1SDimitry Andric     if (!isHLASMAlnum(RawLabel[I]))
1700fe6060f1SDimitry Andric       return !Error(Loc, "HLASM Label has to be alphanumeric");
1701fe6060f1SDimitry Andric 
1702fe6060f1SDimitry Andric   return true;
1703fe6060f1SDimitry Andric }
1704fe6060f1SDimitry Andric 
17050b57cec5SDimitry Andric // Force static initialization.
17065f757f3fSDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming)
LLVMInitializeSystemZAsmParser()1707480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmParser() {
17080b57cec5SDimitry Andric   RegisterMCAsmParser<SystemZAsmParser> X(getTheSystemZTarget());
17090b57cec5SDimitry Andric }
1710