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