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