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