1251607Sdim//===-- SystemZAsmParser.cpp - Parse SystemZ assembly instructions --------===//
2251607Sdim//
3251607Sdim//                     The LLVM Compiler Infrastructure
4251607Sdim//
5251607Sdim// This file is distributed under the University of Illinois Open Source
6251607Sdim// License. See LICENSE.TXT for details.
7251607Sdim//
8251607Sdim//===----------------------------------------------------------------------===//
9251607Sdim
10251607Sdim#include "MCTargetDesc/SystemZMCTargetDesc.h"
11263509Sdim#include "llvm/ADT/STLExtras.h"
12263509Sdim#include "llvm/MC/MCContext.h"
13251607Sdim#include "llvm/MC/MCExpr.h"
14251607Sdim#include "llvm/MC/MCInst.h"
15251607Sdim#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
16251607Sdim#include "llvm/MC/MCStreamer.h"
17251607Sdim#include "llvm/MC/MCSubtargetInfo.h"
18251607Sdim#include "llvm/MC/MCTargetAsmParser.h"
19251607Sdim#include "llvm/Support/TargetRegistry.h"
20251607Sdim
21251607Sdimusing namespace llvm;
22251607Sdim
23251607Sdim// Return true if Expr is in the range [MinValue, MaxValue].
24251607Sdimstatic bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) {
25251607Sdim  if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) {
26251607Sdim    int64_t Value = CE->getValue();
27251607Sdim    return Value >= MinValue && Value <= MaxValue;
28251607Sdim  }
29251607Sdim  return false;
30251607Sdim}
31251607Sdim
32251607Sdimnamespace {
33263509Sdimenum RegisterKind {
34263509Sdim  GR32Reg,
35263509Sdim  GRH32Reg,
36263509Sdim  GR64Reg,
37263509Sdim  GR128Reg,
38263509Sdim  ADDR32Reg,
39263509Sdim  ADDR64Reg,
40263509Sdim  FP32Reg,
41263509Sdim  FP64Reg,
42263509Sdim  FP128Reg
43263509Sdim};
44263509Sdim
45263509Sdimenum MemoryKind {
46263509Sdim  BDMem,
47263509Sdim  BDXMem,
48263509Sdim  BDLMem
49263509Sdim};
50263509Sdim
51251607Sdimclass SystemZOperand : public MCParsedAsmOperand {
52251607Sdimpublic:
53251607Sdimprivate:
54251607Sdim  enum OperandKind {
55263509Sdim    KindInvalid,
56251607Sdim    KindToken,
57251607Sdim    KindReg,
58251607Sdim    KindAccessReg,
59251607Sdim    KindImm,
60251607Sdim    KindMem
61251607Sdim  };
62251607Sdim
63251607Sdim  OperandKind Kind;
64251607Sdim  SMLoc StartLoc, EndLoc;
65251607Sdim
66251607Sdim  // A string of length Length, starting at Data.
67251607Sdim  struct TokenOp {
68251607Sdim    const char *Data;
69251607Sdim    unsigned Length;
70251607Sdim  };
71251607Sdim
72263509Sdim  // LLVM register Num, which has kind Kind.  In some ways it might be
73263509Sdim  // easier for this class to have a register bank (general, floating-point
74263509Sdim  // or access) and a raw register number (0-15).  This would postpone the
75263509Sdim  // interpretation of the operand to the add*() methods and avoid the need
76263509Sdim  // for context-dependent parsing.  However, we do things the current way
77263509Sdim  // because of the virtual getReg() method, which needs to distinguish
78263509Sdim  // between (say) %r0 used as a single register and %r0 used as a pair.
79263509Sdim  // Context-dependent parsing can also give us slightly better error
80263509Sdim  // messages when invalid pairs like %r1 are used.
81251607Sdim  struct RegOp {
82251607Sdim    RegisterKind Kind;
83251607Sdim    unsigned Num;
84251607Sdim  };
85251607Sdim
86251607Sdim  // Base + Disp + Index, where Base and Index are LLVM registers or 0.
87251607Sdim  // RegKind says what type the registers have (ADDR32Reg or ADDR64Reg).
88263509Sdim  // Length is the operand length for D(L,B)-style operands, otherwise
89263509Sdim  // it is null.
90251607Sdim  struct MemOp {
91251607Sdim    unsigned Base : 8;
92251607Sdim    unsigned Index : 8;
93251607Sdim    unsigned RegKind : 8;
94251607Sdim    unsigned Unused : 8;
95251607Sdim    const MCExpr *Disp;
96263509Sdim    const MCExpr *Length;
97251607Sdim  };
98251607Sdim
99251607Sdim  union {
100251607Sdim    TokenOp Token;
101251607Sdim    RegOp Reg;
102251607Sdim    unsigned AccessReg;
103251607Sdim    const MCExpr *Imm;
104251607Sdim    MemOp Mem;
105251607Sdim  };
106251607Sdim
107251607Sdim  SystemZOperand(OperandKind kind, SMLoc startLoc, SMLoc endLoc)
108251607Sdim    : Kind(kind), StartLoc(startLoc), EndLoc(endLoc)
109251607Sdim  {}
110251607Sdim
111251607Sdim  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
112251607Sdim    // Add as immediates when possible.  Null MCExpr = 0.
113251607Sdim    if (Expr == 0)
114251607Sdim      Inst.addOperand(MCOperand::CreateImm(0));
115251607Sdim    else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
116251607Sdim      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
117251607Sdim    else
118251607Sdim      Inst.addOperand(MCOperand::CreateExpr(Expr));
119251607Sdim  }
120251607Sdim
121251607Sdimpublic:
122251607Sdim  // Create particular kinds of operand.
123263509Sdim  static SystemZOperand *createInvalid(SMLoc StartLoc, SMLoc EndLoc) {
124263509Sdim    return new SystemZOperand(KindInvalid, StartLoc, EndLoc);
125263509Sdim  }
126251607Sdim  static SystemZOperand *createToken(StringRef Str, SMLoc Loc) {
127251607Sdim    SystemZOperand *Op = new SystemZOperand(KindToken, Loc, Loc);
128251607Sdim    Op->Token.Data = Str.data();
129251607Sdim    Op->Token.Length = Str.size();
130251607Sdim    return Op;
131251607Sdim  }
132251607Sdim  static SystemZOperand *createReg(RegisterKind Kind, unsigned Num,
133251607Sdim                                   SMLoc StartLoc, SMLoc EndLoc) {
134251607Sdim    SystemZOperand *Op = new SystemZOperand(KindReg, StartLoc, EndLoc);
135251607Sdim    Op->Reg.Kind = Kind;
136251607Sdim    Op->Reg.Num = Num;
137251607Sdim    return Op;
138251607Sdim  }
139251607Sdim  static SystemZOperand *createAccessReg(unsigned Num, SMLoc StartLoc,
140251607Sdim                                         SMLoc EndLoc) {
141251607Sdim    SystemZOperand *Op = new SystemZOperand(KindAccessReg, StartLoc, EndLoc);
142251607Sdim    Op->AccessReg = Num;
143251607Sdim    return Op;
144251607Sdim  }
145251607Sdim  static SystemZOperand *createImm(const MCExpr *Expr, SMLoc StartLoc,
146251607Sdim                                   SMLoc EndLoc) {
147251607Sdim    SystemZOperand *Op = new SystemZOperand(KindImm, StartLoc, EndLoc);
148251607Sdim    Op->Imm = Expr;
149251607Sdim    return Op;
150251607Sdim  }
151251607Sdim  static SystemZOperand *createMem(RegisterKind RegKind, unsigned Base,
152251607Sdim                                   const MCExpr *Disp, unsigned Index,
153263509Sdim                                   const MCExpr *Length, SMLoc StartLoc,
154263509Sdim                                   SMLoc EndLoc) {
155251607Sdim    SystemZOperand *Op = new SystemZOperand(KindMem, StartLoc, EndLoc);
156251607Sdim    Op->Mem.RegKind = RegKind;
157251607Sdim    Op->Mem.Base = Base;
158251607Sdim    Op->Mem.Index = Index;
159251607Sdim    Op->Mem.Disp = Disp;
160263509Sdim    Op->Mem.Length = Length;
161251607Sdim    return Op;
162251607Sdim  }
163251607Sdim
164251607Sdim  // Token operands
165251607Sdim  virtual bool isToken() const LLVM_OVERRIDE {
166251607Sdim    return Kind == KindToken;
167251607Sdim  }
168251607Sdim  StringRef getToken() const {
169251607Sdim    assert(Kind == KindToken && "Not a token");
170251607Sdim    return StringRef(Token.Data, Token.Length);
171251607Sdim  }
172251607Sdim
173251607Sdim  // Register operands.
174251607Sdim  virtual bool isReg() const LLVM_OVERRIDE {
175251607Sdim    return Kind == KindReg;
176251607Sdim  }
177251607Sdim  bool isReg(RegisterKind RegKind) const {
178251607Sdim    return Kind == KindReg && Reg.Kind == RegKind;
179251607Sdim  }
180251607Sdim  virtual unsigned getReg() const LLVM_OVERRIDE {
181251607Sdim    assert(Kind == KindReg && "Not a register");
182251607Sdim    return Reg.Num;
183251607Sdim  }
184251607Sdim
185251607Sdim  // Access register operands.  Access registers aren't exposed to LLVM
186251607Sdim  // as registers.
187251607Sdim  bool isAccessReg() const {
188251607Sdim    return Kind == KindAccessReg;
189251607Sdim  }
190251607Sdim
191251607Sdim  // Immediate operands.
192251607Sdim  virtual bool isImm() const LLVM_OVERRIDE {
193251607Sdim    return Kind == KindImm;
194251607Sdim  }
195251607Sdim  bool isImm(int64_t MinValue, int64_t MaxValue) const {
196251607Sdim    return Kind == KindImm && inRange(Imm, MinValue, MaxValue);
197251607Sdim  }
198251607Sdim  const MCExpr *getImm() const {
199251607Sdim    assert(Kind == KindImm && "Not an immediate");
200251607Sdim    return Imm;
201251607Sdim  }
202251607Sdim
203251607Sdim  // Memory operands.
204251607Sdim  virtual bool isMem() const LLVM_OVERRIDE {
205251607Sdim    return Kind == KindMem;
206251607Sdim  }
207263509Sdim  bool isMem(RegisterKind RegKind, MemoryKind MemKind) const {
208251607Sdim    return (Kind == KindMem &&
209251607Sdim            Mem.RegKind == RegKind &&
210263509Sdim            (MemKind == BDXMem || !Mem.Index) &&
211263509Sdim            (MemKind == BDLMem) == (Mem.Length != 0));
212251607Sdim  }
213263509Sdim  bool isMemDisp12(RegisterKind RegKind, MemoryKind MemKind) const {
214263509Sdim    return isMem(RegKind, MemKind) && inRange(Mem.Disp, 0, 0xfff);
215251607Sdim  }
216263509Sdim  bool isMemDisp20(RegisterKind RegKind, MemoryKind MemKind) const {
217263509Sdim    return isMem(RegKind, MemKind) && inRange(Mem.Disp, -524288, 524287);
218251607Sdim  }
219263509Sdim  bool isMemDisp12Len8(RegisterKind RegKind) const {
220263509Sdim    return isMemDisp12(RegKind, BDLMem) && inRange(Mem.Length, 1, 0x100);
221263509Sdim  }
222251607Sdim
223251607Sdim  // Override MCParsedAsmOperand.
224251607Sdim  virtual SMLoc getStartLoc() const LLVM_OVERRIDE { return StartLoc; }
225251607Sdim  virtual SMLoc getEndLoc() const LLVM_OVERRIDE { return EndLoc; }
226251607Sdim  virtual void print(raw_ostream &OS) const LLVM_OVERRIDE;
227251607Sdim
228251607Sdim  // Used by the TableGen code to add particular types of operand
229251607Sdim  // to an instruction.
230251607Sdim  void addRegOperands(MCInst &Inst, unsigned N) const {
231251607Sdim    assert(N == 1 && "Invalid number of operands");
232251607Sdim    Inst.addOperand(MCOperand::CreateReg(getReg()));
233251607Sdim  }
234251607Sdim  void addAccessRegOperands(MCInst &Inst, unsigned N) const {
235251607Sdim    assert(N == 1 && "Invalid number of operands");
236251607Sdim    assert(Kind == KindAccessReg && "Invalid operand type");
237251607Sdim    Inst.addOperand(MCOperand::CreateImm(AccessReg));
238251607Sdim  }
239251607Sdim  void addImmOperands(MCInst &Inst, unsigned N) const {
240251607Sdim    assert(N == 1 && "Invalid number of operands");
241251607Sdim    addExpr(Inst, getImm());
242251607Sdim  }
243251607Sdim  void addBDAddrOperands(MCInst &Inst, unsigned N) const {
244251607Sdim    assert(N == 2 && "Invalid number of operands");
245251607Sdim    assert(Kind == KindMem && Mem.Index == 0 && "Invalid operand type");
246251607Sdim    Inst.addOperand(MCOperand::CreateReg(Mem.Base));
247251607Sdim    addExpr(Inst, Mem.Disp);
248251607Sdim  }
249251607Sdim  void addBDXAddrOperands(MCInst &Inst, unsigned N) const {
250251607Sdim    assert(N == 3 && "Invalid number of operands");
251251607Sdim    assert(Kind == KindMem && "Invalid operand type");
252251607Sdim    Inst.addOperand(MCOperand::CreateReg(Mem.Base));
253251607Sdim    addExpr(Inst, Mem.Disp);
254251607Sdim    Inst.addOperand(MCOperand::CreateReg(Mem.Index));
255251607Sdim  }
256263509Sdim  void addBDLAddrOperands(MCInst &Inst, unsigned N) const {
257263509Sdim    assert(N == 3 && "Invalid number of operands");
258263509Sdim    assert(Kind == KindMem && "Invalid operand type");
259263509Sdim    Inst.addOperand(MCOperand::CreateReg(Mem.Base));
260263509Sdim    addExpr(Inst, Mem.Disp);
261263509Sdim    addExpr(Inst, Mem.Length);
262263509Sdim  }
263251607Sdim
264251607Sdim  // Used by the TableGen code to check for particular operand types.
265251607Sdim  bool isGR32() const { return isReg(GR32Reg); }
266263509Sdim  bool isGRH32() const { return isReg(GRH32Reg); }
267263509Sdim  bool isGRX32() const { return false; }
268251607Sdim  bool isGR64() const { return isReg(GR64Reg); }
269251607Sdim  bool isGR128() const { return isReg(GR128Reg); }
270251607Sdim  bool isADDR32() const { return isReg(ADDR32Reg); }
271251607Sdim  bool isADDR64() const { return isReg(ADDR64Reg); }
272251607Sdim  bool isADDR128() const { return false; }
273251607Sdim  bool isFP32() const { return isReg(FP32Reg); }
274251607Sdim  bool isFP64() const { return isReg(FP64Reg); }
275251607Sdim  bool isFP128() const { return isReg(FP128Reg); }
276263509Sdim  bool isBDAddr32Disp12() const { return isMemDisp12(ADDR32Reg, BDMem); }
277263509Sdim  bool isBDAddr32Disp20() const { return isMemDisp20(ADDR32Reg, BDMem); }
278263509Sdim  bool isBDAddr64Disp12() const { return isMemDisp12(ADDR64Reg, BDMem); }
279263509Sdim  bool isBDAddr64Disp20() const { return isMemDisp20(ADDR64Reg, BDMem); }
280263509Sdim  bool isBDXAddr64Disp12() const { return isMemDisp12(ADDR64Reg, BDXMem); }
281263509Sdim  bool isBDXAddr64Disp20() const { return isMemDisp20(ADDR64Reg, BDXMem); }
282263509Sdim  bool isBDLAddr64Disp12Len8() const { return isMemDisp12Len8(ADDR64Reg); }
283251607Sdim  bool isU4Imm() const { return isImm(0, 15); }
284251607Sdim  bool isU6Imm() const { return isImm(0, 63); }
285251607Sdim  bool isU8Imm() const { return isImm(0, 255); }
286251607Sdim  bool isS8Imm() const { return isImm(-128, 127); }
287251607Sdim  bool isU16Imm() const { return isImm(0, 65535); }
288251607Sdim  bool isS16Imm() const { return isImm(-32768, 32767); }
289251607Sdim  bool isU32Imm() const { return isImm(0, (1LL << 32) - 1); }
290251607Sdim  bool isS32Imm() const { return isImm(-(1LL << 31), (1LL << 31) - 1); }
291251607Sdim};
292251607Sdim
293251607Sdimclass SystemZAsmParser : public MCTargetAsmParser {
294251607Sdim#define GET_ASSEMBLER_HEADER
295251607Sdim#include "SystemZGenAsmMatcher.inc"
296251607Sdim
297251607Sdimprivate:
298251607Sdim  MCSubtargetInfo &STI;
299251607Sdim  MCAsmParser &Parser;
300263509Sdim  enum RegisterGroup {
301263509Sdim    RegGR,
302263509Sdim    RegFP,
303263509Sdim    RegAccess
304263509Sdim  };
305251607Sdim  struct Register {
306263509Sdim    RegisterGroup Group;
307263509Sdim    unsigned Num;
308251607Sdim    SMLoc StartLoc, EndLoc;
309251607Sdim  };
310251607Sdim
311251607Sdim  bool parseRegister(Register &Reg);
312251607Sdim
313263509Sdim  bool parseRegister(Register &Reg, RegisterGroup Group, const unsigned *Regs,
314263509Sdim                     bool IsAddress = false);
315251607Sdim
316251607Sdim  OperandMatchResultTy
317251607Sdim  parseRegister(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
318263509Sdim                RegisterGroup Group, const unsigned *Regs, RegisterKind Kind);
319251607Sdim
320263509Sdim  bool parseAddress(unsigned &Base, const MCExpr *&Disp,
321263509Sdim                    unsigned &Index, const MCExpr *&Length,
322263509Sdim                    const unsigned *Regs, RegisterKind RegKind);
323263509Sdim
324251607Sdim  OperandMatchResultTy
325251607Sdim  parseAddress(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
326263509Sdim               const unsigned *Regs, RegisterKind RegKind,
327263509Sdim               MemoryKind MemKind);
328251607Sdim
329251607Sdim  bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
330251607Sdim                    StringRef Mnemonic);
331251607Sdim
332251607Sdimpublic:
333263509Sdim  SystemZAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
334263509Sdim                   const MCInstrInfo &MII)
335263509Sdim      : MCTargetAsmParser(), STI(sti), Parser(parser) {
336251607Sdim    MCAsmParserExtension::Initialize(Parser);
337251607Sdim
338251607Sdim    // Initialize the set of available features.
339251607Sdim    setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
340251607Sdim  }
341251607Sdim
342251607Sdim  // Override MCTargetAsmParser.
343251607Sdim  virtual bool ParseDirective(AsmToken DirectiveID) LLVM_OVERRIDE;
344251607Sdim  virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
345251607Sdim                             SMLoc &EndLoc) LLVM_OVERRIDE;
346251607Sdim  virtual bool ParseInstruction(ParseInstructionInfo &Info,
347251607Sdim                                StringRef Name, SMLoc NameLoc,
348251607Sdim                                SmallVectorImpl<MCParsedAsmOperand*> &Operands)
349251607Sdim    LLVM_OVERRIDE;
350251607Sdim  virtual bool
351251607Sdim    MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
352251607Sdim                            SmallVectorImpl<MCParsedAsmOperand*> &Operands,
353251607Sdim                            MCStreamer &Out, unsigned &ErrorInfo,
354251607Sdim                            bool MatchingInlineAsm) LLVM_OVERRIDE;
355251607Sdim
356251607Sdim  // Used by the TableGen code to parse particular operand types.
357251607Sdim  OperandMatchResultTy
358251607Sdim  parseGR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
359263509Sdim    return parseRegister(Operands, RegGR, SystemZMC::GR32Regs, GR32Reg);
360251607Sdim  }
361251607Sdim  OperandMatchResultTy
362263509Sdim  parseGRH32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
363263509Sdim    return parseRegister(Operands, RegGR, SystemZMC::GRH32Regs, GRH32Reg);
364263509Sdim  }
365263509Sdim  OperandMatchResultTy
366263509Sdim  parseGRX32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
367263509Sdim    llvm_unreachable("GRX32 should only be used for pseudo instructions");
368263509Sdim  }
369263509Sdim  OperandMatchResultTy
370251607Sdim  parseGR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
371263509Sdim    return parseRegister(Operands, RegGR, SystemZMC::GR64Regs, GR64Reg);
372251607Sdim  }
373251607Sdim  OperandMatchResultTy
374251607Sdim  parseGR128(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
375263509Sdim    return parseRegister(Operands, RegGR, SystemZMC::GR128Regs, GR128Reg);
376251607Sdim  }
377251607Sdim  OperandMatchResultTy
378251607Sdim  parseADDR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
379263509Sdim    return parseRegister(Operands, RegGR, SystemZMC::GR32Regs, ADDR32Reg);
380251607Sdim  }
381251607Sdim  OperandMatchResultTy
382251607Sdim  parseADDR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
383263509Sdim    return parseRegister(Operands, RegGR, SystemZMC::GR64Regs, ADDR64Reg);
384251607Sdim  }
385251607Sdim  OperandMatchResultTy
386251607Sdim  parseADDR128(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
387251607Sdim    llvm_unreachable("Shouldn't be used as an operand");
388251607Sdim  }
389251607Sdim  OperandMatchResultTy
390251607Sdim  parseFP32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
391263509Sdim    return parseRegister(Operands, RegFP, SystemZMC::FP32Regs, FP32Reg);
392251607Sdim  }
393251607Sdim  OperandMatchResultTy
394251607Sdim  parseFP64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
395263509Sdim    return parseRegister(Operands, RegFP, SystemZMC::FP64Regs, FP64Reg);
396251607Sdim  }
397251607Sdim  OperandMatchResultTy
398251607Sdim  parseFP128(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
399263509Sdim    return parseRegister(Operands, RegFP, SystemZMC::FP128Regs, FP128Reg);
400251607Sdim  }
401251607Sdim  OperandMatchResultTy
402251607Sdim  parseBDAddr32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
403263509Sdim    return parseAddress(Operands, SystemZMC::GR32Regs, ADDR32Reg, BDMem);
404251607Sdim  }
405251607Sdim  OperandMatchResultTy
406251607Sdim  parseBDAddr64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
407263509Sdim    return parseAddress(Operands, SystemZMC::GR64Regs, ADDR64Reg, BDMem);
408251607Sdim  }
409251607Sdim  OperandMatchResultTy
410251607Sdim  parseBDXAddr64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
411263509Sdim    return parseAddress(Operands, SystemZMC::GR64Regs, ADDR64Reg, BDXMem);
412251607Sdim  }
413251607Sdim  OperandMatchResultTy
414263509Sdim  parseBDLAddr64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
415263509Sdim    return parseAddress(Operands, SystemZMC::GR64Regs, ADDR64Reg, BDLMem);
416263509Sdim  }
417263509Sdim  OperandMatchResultTy
418251607Sdim  parseAccessReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
419263509Sdim  OperandMatchResultTy
420263509Sdim  parsePCRel(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
421263509Sdim             int64_t MinVal, int64_t MaxVal);
422263509Sdim  OperandMatchResultTy
423263509Sdim  parsePCRel16(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
424263509Sdim    return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1);
425263509Sdim  }
426263509Sdim  OperandMatchResultTy
427263509Sdim  parsePCRel32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
428263509Sdim    return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1);
429263509Sdim  }
430251607Sdim};
431251607Sdim}
432251607Sdim
433251607Sdim#define GET_REGISTER_MATCHER
434251607Sdim#define GET_SUBTARGET_FEATURE_NAME
435251607Sdim#define GET_MATCHER_IMPLEMENTATION
436251607Sdim#include "SystemZGenAsmMatcher.inc"
437251607Sdim
438251607Sdimvoid SystemZOperand::print(raw_ostream &OS) const {
439251607Sdim  llvm_unreachable("Not implemented");
440251607Sdim}
441251607Sdim
442251607Sdim// Parse one register of the form %<prefix><number>.
443251607Sdimbool SystemZAsmParser::parseRegister(Register &Reg) {
444251607Sdim  Reg.StartLoc = Parser.getTok().getLoc();
445251607Sdim
446251607Sdim  // Eat the % prefix.
447251607Sdim  if (Parser.getTok().isNot(AsmToken::Percent))
448263509Sdim    return Error(Parser.getTok().getLoc(), "register expected");
449251607Sdim  Parser.Lex();
450251607Sdim
451251607Sdim  // Expect a register name.
452251607Sdim  if (Parser.getTok().isNot(AsmToken::Identifier))
453263509Sdim    return Error(Reg.StartLoc, "invalid register");
454251607Sdim
455263509Sdim  // Check that there's a prefix.
456251607Sdim  StringRef Name = Parser.getTok().getString();
457251607Sdim  if (Name.size() < 2)
458263509Sdim    return Error(Reg.StartLoc, "invalid register");
459263509Sdim  char Prefix = Name[0];
460251607Sdim
461251607Sdim  // Treat the rest of the register name as a register number.
462263509Sdim  if (Name.substr(1).getAsInteger(10, Reg.Num))
463263509Sdim    return Error(Reg.StartLoc, "invalid register");
464251607Sdim
465263509Sdim  // Look for valid combinations of prefix and number.
466263509Sdim  if (Prefix == 'r' && Reg.Num < 16)
467263509Sdim    Reg.Group = RegGR;
468263509Sdim  else if (Prefix == 'f' && Reg.Num < 16)
469263509Sdim    Reg.Group = RegFP;
470263509Sdim  else if (Prefix == 'a' && Reg.Num < 16)
471263509Sdim    Reg.Group = RegAccess;
472263509Sdim  else
473263509Sdim    return Error(Reg.StartLoc, "invalid register");
474263509Sdim
475251607Sdim  Reg.EndLoc = Parser.getTok().getLoc();
476251607Sdim  Parser.Lex();
477251607Sdim  return false;
478251607Sdim}
479251607Sdim
480263509Sdim// Parse a register of group Group.  If Regs is nonnull, use it to map
481263509Sdim// the raw register number to LLVM numbering, with zero entries indicating
482263509Sdim// an invalid register.  IsAddress says whether the register appears in an
483263509Sdim// address context.
484263509Sdimbool SystemZAsmParser::parseRegister(Register &Reg, RegisterGroup Group,
485263509Sdim                                     const unsigned *Regs, bool IsAddress) {
486251607Sdim  if (parseRegister(Reg))
487263509Sdim    return true;
488263509Sdim  if (Reg.Group != Group)
489263509Sdim    return Error(Reg.StartLoc, "invalid operand for instruction");
490263509Sdim  if (Regs && Regs[Reg.Num] == 0)
491263509Sdim    return Error(Reg.StartLoc, "invalid register pair");
492263509Sdim  if (Reg.Num == 0 && IsAddress)
493263509Sdim    return Error(Reg.StartLoc, "%r0 used in an address");
494263509Sdim  if (Regs)
495263509Sdim    Reg.Num = Regs[Reg.Num];
496263509Sdim  return false;
497251607Sdim}
498251607Sdim
499263509Sdim// Parse a register and add it to Operands.  The other arguments are as above.
500251607SdimSystemZAsmParser::OperandMatchResultTy
501251607SdimSystemZAsmParser::parseRegister(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
502263509Sdim                                RegisterGroup Group, const unsigned *Regs,
503263509Sdim                                RegisterKind Kind) {
504263509Sdim  if (Parser.getTok().isNot(AsmToken::Percent))
505263509Sdim    return MatchOperand_NoMatch;
506263509Sdim
507251607Sdim  Register Reg;
508263509Sdim  bool IsAddress = (Kind == ADDR32Reg || Kind == ADDR64Reg);
509263509Sdim  if (parseRegister(Reg, Group, Regs, IsAddress))
510263509Sdim    return MatchOperand_ParseFail;
511263509Sdim
512263509Sdim  Operands.push_back(SystemZOperand::createReg(Kind, Reg.Num,
513263509Sdim                                               Reg.StartLoc, Reg.EndLoc));
514263509Sdim  return MatchOperand_Success;
515251607Sdim}
516251607Sdim
517263509Sdim// Parse a memory operand into Base, Disp, Index and Length.
518263509Sdim// Regs maps asm register numbers to LLVM register numbers and RegKind
519263509Sdim// says what kind of address register we're using (ADDR32Reg or ADDR64Reg).
520263509Sdimbool SystemZAsmParser::parseAddress(unsigned &Base, const MCExpr *&Disp,
521263509Sdim                                    unsigned &Index, const MCExpr *&Length,
522263509Sdim                                    const unsigned *Regs,
523263509Sdim                                    RegisterKind RegKind) {
524251607Sdim  // Parse the displacement, which must always be present.
525251607Sdim  if (getParser().parseExpression(Disp))
526263509Sdim    return true;
527251607Sdim
528251607Sdim  // Parse the optional base and index.
529263509Sdim  Index = 0;
530263509Sdim  Base = 0;
531263509Sdim  Length = 0;
532251607Sdim  if (getLexer().is(AsmToken::LParen)) {
533251607Sdim    Parser.Lex();
534251607Sdim
535263509Sdim    if (getLexer().is(AsmToken::Percent)) {
536263509Sdim      // Parse the first register and decide whether it's a base or an index.
537263509Sdim      Register Reg;
538263509Sdim      if (parseRegister(Reg, RegGR, Regs, RegKind))
539263509Sdim        return true;
540263509Sdim      if (getLexer().is(AsmToken::Comma))
541263509Sdim        Index = Reg.Num;
542263509Sdim      else
543263509Sdim        Base = Reg.Num;
544263509Sdim    } else {
545263509Sdim      // Parse the length.
546263509Sdim      if (getParser().parseExpression(Length))
547263509Sdim        return true;
548263509Sdim    }
549251607Sdim
550263509Sdim    // Check whether there's a second register.  It's the base if so.
551251607Sdim    if (getLexer().is(AsmToken::Comma)) {
552251607Sdim      Parser.Lex();
553263509Sdim      Register Reg;
554263509Sdim      if (parseRegister(Reg, RegGR, Regs, RegKind))
555263509Sdim        return true;
556263509Sdim      Base = Reg.Num;
557251607Sdim    }
558251607Sdim
559251607Sdim    // Consume the closing bracket.
560251607Sdim    if (getLexer().isNot(AsmToken::RParen))
561263509Sdim      return Error(Parser.getTok().getLoc(), "unexpected token in address");
562251607Sdim    Parser.Lex();
563251607Sdim  }
564263509Sdim  return false;
565263509Sdim}
566251607Sdim
567263509Sdim// Parse a memory operand and add it to Operands.  The other arguments
568263509Sdim// are as above.
569263509SdimSystemZAsmParser::OperandMatchResultTy
570263509SdimSystemZAsmParser::parseAddress(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
571263509Sdim                               const unsigned *Regs, RegisterKind RegKind,
572263509Sdim                               MemoryKind MemKind) {
573263509Sdim  SMLoc StartLoc = Parser.getTok().getLoc();
574263509Sdim  unsigned Base, Index;
575263509Sdim  const MCExpr *Disp;
576263509Sdim  const MCExpr *Length;
577263509Sdim  if (parseAddress(Base, Disp, Index, Length, Regs, RegKind))
578263509Sdim    return MatchOperand_ParseFail;
579263509Sdim
580263509Sdim  if (Index && MemKind != BDXMem)
581263509Sdim    {
582263509Sdim      Error(StartLoc, "invalid use of indexed addressing");
583263509Sdim      return MatchOperand_ParseFail;
584263509Sdim    }
585263509Sdim
586263509Sdim  if (Length && MemKind != BDLMem)
587263509Sdim    {
588263509Sdim      Error(StartLoc, "invalid use of length addressing");
589263509Sdim      return MatchOperand_ParseFail;
590263509Sdim    }
591263509Sdim
592263509Sdim  if (!Length && MemKind == BDLMem)
593263509Sdim    {
594263509Sdim      Error(StartLoc, "missing length in address");
595263509Sdim      return MatchOperand_ParseFail;
596263509Sdim    }
597263509Sdim
598251607Sdim  SMLoc EndLoc =
599251607Sdim    SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
600251607Sdim  Operands.push_back(SystemZOperand::createMem(RegKind, Base, Disp, Index,
601263509Sdim                                               Length, StartLoc, EndLoc));
602251607Sdim  return MatchOperand_Success;
603251607Sdim}
604251607Sdim
605251607Sdimbool SystemZAsmParser::ParseDirective(AsmToken DirectiveID) {
606251607Sdim  return true;
607251607Sdim}
608251607Sdim
609251607Sdimbool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
610251607Sdim                                     SMLoc &EndLoc) {
611251607Sdim  Register Reg;
612251607Sdim  if (parseRegister(Reg))
613263509Sdim    return true;
614263509Sdim  if (Reg.Group == RegGR)
615263509Sdim    RegNo = SystemZMC::GR64Regs[Reg.Num];
616263509Sdim  else if (Reg.Group == RegFP)
617263509Sdim    RegNo = SystemZMC::FP64Regs[Reg.Num];
618251607Sdim  else
619263509Sdim    // FIXME: Access registers aren't modelled as LLVM registers yet.
620263509Sdim    return Error(Reg.StartLoc, "invalid operand for instruction");
621251607Sdim  StartLoc = Reg.StartLoc;
622251607Sdim  EndLoc = Reg.EndLoc;
623251607Sdim  return false;
624251607Sdim}
625251607Sdim
626251607Sdimbool SystemZAsmParser::
627251607SdimParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
628251607Sdim                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
629251607Sdim  Operands.push_back(SystemZOperand::createToken(Name, NameLoc));
630251607Sdim
631251607Sdim  // Read the remaining operands.
632251607Sdim  if (getLexer().isNot(AsmToken::EndOfStatement)) {
633251607Sdim    // Read the first operand.
634251607Sdim    if (parseOperand(Operands, Name)) {
635251607Sdim      Parser.eatToEndOfStatement();
636251607Sdim      return true;
637251607Sdim    }
638251607Sdim
639251607Sdim    // Read any subsequent operands.
640251607Sdim    while (getLexer().is(AsmToken::Comma)) {
641251607Sdim      Parser.Lex();
642251607Sdim      if (parseOperand(Operands, Name)) {
643251607Sdim        Parser.eatToEndOfStatement();
644251607Sdim        return true;
645251607Sdim      }
646251607Sdim    }
647251607Sdim    if (getLexer().isNot(AsmToken::EndOfStatement)) {
648251607Sdim      SMLoc Loc = getLexer().getLoc();
649251607Sdim      Parser.eatToEndOfStatement();
650251607Sdim      return Error(Loc, "unexpected token in argument list");
651251607Sdim    }
652251607Sdim  }
653251607Sdim
654251607Sdim  // Consume the EndOfStatement.
655251607Sdim  Parser.Lex();
656251607Sdim  return false;
657251607Sdim}
658251607Sdim
659251607Sdimbool SystemZAsmParser::
660251607SdimparseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
661251607Sdim             StringRef Mnemonic) {
662251607Sdim  // Check if the current operand has a custom associated parser, if so, try to
663251607Sdim  // custom parse the operand, or fallback to the general approach.
664251607Sdim  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
665251607Sdim  if (ResTy == MatchOperand_Success)
666251607Sdim    return false;
667251607Sdim
668251607Sdim  // If there wasn't a custom match, try the generic matcher below. Otherwise,
669251607Sdim  // there was a match, but an error occurred, in which case, just return that
670251607Sdim  // the operand parsing failed.
671251607Sdim  if (ResTy == MatchOperand_ParseFail)
672251607Sdim    return true;
673251607Sdim
674263509Sdim  // Check for a register.  All real register operands should have used
675263509Sdim  // a context-dependent parse routine, which gives the required register
676263509Sdim  // class.  The code is here to mop up other cases, like those where
677263509Sdim  // the instruction isn't recognized.
678263509Sdim  if (Parser.getTok().is(AsmToken::Percent)) {
679263509Sdim    Register Reg;
680263509Sdim    if (parseRegister(Reg))
681263509Sdim      return true;
682263509Sdim    Operands.push_back(SystemZOperand::createInvalid(Reg.StartLoc, Reg.EndLoc));
683263509Sdim    return false;
684263509Sdim  }
685263509Sdim
686263509Sdim  // The only other type of operand is an immediate or address.  As above,
687263509Sdim  // real address operands should have used a context-dependent parse routine,
688263509Sdim  // so we treat any plain expression as an immediate.
689251607Sdim  SMLoc StartLoc = Parser.getTok().getLoc();
690263509Sdim  unsigned Base, Index;
691263509Sdim  const MCExpr *Expr, *Length;
692263509Sdim  if (parseAddress(Base, Expr, Index, Length, SystemZMC::GR64Regs, ADDR64Reg))
693251607Sdim    return true;
694251607Sdim
695251607Sdim  SMLoc EndLoc =
696251607Sdim    SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
697263509Sdim  if (Base || Index || Length)
698263509Sdim    Operands.push_back(SystemZOperand::createInvalid(StartLoc, EndLoc));
699263509Sdim  else
700263509Sdim    Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));
701251607Sdim  return false;
702251607Sdim}
703251607Sdim
704251607Sdimbool SystemZAsmParser::
705251607SdimMatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
706251607Sdim                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
707251607Sdim                        MCStreamer &Out, unsigned &ErrorInfo,
708251607Sdim                        bool MatchingInlineAsm) {
709251607Sdim  MCInst Inst;
710251607Sdim  unsigned MatchResult;
711251607Sdim
712251607Sdim  MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
713251607Sdim                                     MatchingInlineAsm);
714251607Sdim  switch (MatchResult) {
715251607Sdim  default: break;
716251607Sdim  case Match_Success:
717251607Sdim    Inst.setLoc(IDLoc);
718251607Sdim    Out.EmitInstruction(Inst);
719251607Sdim    return false;
720251607Sdim
721251607Sdim  case Match_MissingFeature: {
722251607Sdim    assert(ErrorInfo && "Unknown missing feature!");
723251607Sdim    // Special case the error message for the very common case where only
724251607Sdim    // a single subtarget feature is missing
725251607Sdim    std::string Msg = "instruction requires:";
726251607Sdim    unsigned Mask = 1;
727251607Sdim    for (unsigned I = 0; I < sizeof(ErrorInfo) * 8 - 1; ++I) {
728251607Sdim      if (ErrorInfo & Mask) {
729251607Sdim        Msg += " ";
730251607Sdim        Msg += getSubtargetFeatureName(ErrorInfo & Mask);
731251607Sdim      }
732251607Sdim      Mask <<= 1;
733251607Sdim    }
734251607Sdim    return Error(IDLoc, Msg);
735251607Sdim  }
736251607Sdim
737251607Sdim  case Match_InvalidOperand: {
738251607Sdim    SMLoc ErrorLoc = IDLoc;
739251607Sdim    if (ErrorInfo != ~0U) {
740251607Sdim      if (ErrorInfo >= Operands.size())
741251607Sdim        return Error(IDLoc, "too few operands for instruction");
742251607Sdim
743251607Sdim      ErrorLoc = ((SystemZOperand*)Operands[ErrorInfo])->getStartLoc();
744251607Sdim      if (ErrorLoc == SMLoc())
745251607Sdim        ErrorLoc = IDLoc;
746251607Sdim    }
747251607Sdim    return Error(ErrorLoc, "invalid operand for instruction");
748251607Sdim  }
749251607Sdim
750251607Sdim  case Match_MnemonicFail:
751251607Sdim    return Error(IDLoc, "invalid instruction");
752251607Sdim  }
753251607Sdim
754251607Sdim  llvm_unreachable("Unexpected match type");
755251607Sdim}
756251607Sdim
757251607SdimSystemZAsmParser::OperandMatchResultTy SystemZAsmParser::
758251607SdimparseAccessReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
759263509Sdim  if (Parser.getTok().isNot(AsmToken::Percent))
760263509Sdim    return MatchOperand_NoMatch;
761263509Sdim
762251607Sdim  Register Reg;
763263509Sdim  if (parseRegister(Reg, RegAccess, 0))
764263509Sdim    return MatchOperand_ParseFail;
765263509Sdim
766263509Sdim  Operands.push_back(SystemZOperand::createAccessReg(Reg.Num,
767263509Sdim                                                     Reg.StartLoc,
768263509Sdim                                                     Reg.EndLoc));
769263509Sdim  return MatchOperand_Success;
770263509Sdim}
771263509Sdim
772263509SdimSystemZAsmParser::OperandMatchResultTy SystemZAsmParser::
773263509SdimparsePCRel(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
774263509Sdim           int64_t MinVal, int64_t MaxVal) {
775263509Sdim  MCContext &Ctx = getContext();
776263509Sdim  MCStreamer &Out = getStreamer();
777263509Sdim  const MCExpr *Expr;
778263509Sdim  SMLoc StartLoc = Parser.getTok().getLoc();
779263509Sdim  if (getParser().parseExpression(Expr))
780251607Sdim    return MatchOperand_NoMatch;
781263509Sdim
782263509Sdim  // For consistency with the GNU assembler, treat immediates as offsets
783263509Sdim  // from ".".
784263509Sdim  if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) {
785263509Sdim    int64_t Value = CE->getValue();
786263509Sdim    if ((Value & 1) || Value < MinVal || Value > MaxVal) {
787263509Sdim      Error(StartLoc, "offset out of range");
788263509Sdim      return MatchOperand_ParseFail;
789263509Sdim    }
790263509Sdim    MCSymbol *Sym = Ctx.CreateTempSymbol();
791263509Sdim    Out.EmitLabel(Sym);
792263509Sdim    const MCExpr *Base = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
793263509Sdim                                                 Ctx);
794263509Sdim    Expr = Value == 0 ? Base : MCBinaryExpr::CreateAdd(Base, Expr, Ctx);
795251607Sdim  }
796263509Sdim
797263509Sdim  SMLoc EndLoc =
798263509Sdim    SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
799263509Sdim  Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));
800251607Sdim  return MatchOperand_Success;
801251607Sdim}
802251607Sdim
803251607Sdim// Force static initialization.
804251607Sdimextern "C" void LLVMInitializeSystemZAsmParser() {
805251607Sdim  RegisterMCAsmParser<SystemZAsmParser> X(TheSystemZTarget);
806251607Sdim}
807