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" 11251607Sdim#include "llvm/MC/MCExpr.h" 12251607Sdim#include "llvm/MC/MCInst.h" 13251607Sdim#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 14251607Sdim#include "llvm/MC/MCStreamer.h" 15251607Sdim#include "llvm/MC/MCSubtargetInfo.h" 16251607Sdim#include "llvm/MC/MCTargetAsmParser.h" 17251607Sdim#include "llvm/Support/TargetRegistry.h" 18251607Sdim 19251607Sdimusing namespace llvm; 20251607Sdim 21251607Sdim// Return true if Expr is in the range [MinValue, MaxValue]. 22251607Sdimstatic bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) { 23251607Sdim if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) { 24251607Sdim int64_t Value = CE->getValue(); 25251607Sdim return Value >= MinValue && Value <= MaxValue; 26251607Sdim } 27251607Sdim return false; 28251607Sdim} 29251607Sdim 30251607Sdimnamespace { 31251607Sdimclass SystemZOperand : public MCParsedAsmOperand { 32251607Sdimpublic: 33251607Sdim enum RegisterKind { 34251607Sdim GR32Reg, 35251607Sdim GR64Reg, 36251607Sdim GR128Reg, 37251607Sdim ADDR32Reg, 38251607Sdim ADDR64Reg, 39251607Sdim FP32Reg, 40251607Sdim FP64Reg, 41251607Sdim FP128Reg 42251607Sdim }; 43251607Sdim 44251607Sdimprivate: 45251607Sdim enum OperandKind { 46251607Sdim KindToken, 47251607Sdim KindReg, 48251607Sdim KindAccessReg, 49251607Sdim KindImm, 50251607Sdim KindMem 51251607Sdim }; 52251607Sdim 53251607Sdim OperandKind Kind; 54251607Sdim SMLoc StartLoc, EndLoc; 55251607Sdim 56251607Sdim // A string of length Length, starting at Data. 57251607Sdim struct TokenOp { 58251607Sdim const char *Data; 59251607Sdim unsigned Length; 60251607Sdim }; 61251607Sdim 62251607Sdim // LLVM register Num, which has kind Kind. 63251607Sdim struct RegOp { 64251607Sdim RegisterKind Kind; 65251607Sdim unsigned Num; 66251607Sdim }; 67251607Sdim 68251607Sdim // Base + Disp + Index, where Base and Index are LLVM registers or 0. 69251607Sdim // RegKind says what type the registers have (ADDR32Reg or ADDR64Reg). 70251607Sdim struct MemOp { 71251607Sdim unsigned Base : 8; 72251607Sdim unsigned Index : 8; 73251607Sdim unsigned RegKind : 8; 74251607Sdim unsigned Unused : 8; 75251607Sdim const MCExpr *Disp; 76251607Sdim }; 77251607Sdim 78251607Sdim union { 79251607Sdim TokenOp Token; 80251607Sdim RegOp Reg; 81251607Sdim unsigned AccessReg; 82251607Sdim const MCExpr *Imm; 83251607Sdim MemOp Mem; 84251607Sdim }; 85251607Sdim 86251607Sdim SystemZOperand(OperandKind kind, SMLoc startLoc, SMLoc endLoc) 87251607Sdim : Kind(kind), StartLoc(startLoc), EndLoc(endLoc) 88251607Sdim {} 89251607Sdim 90251607Sdim void addExpr(MCInst &Inst, const MCExpr *Expr) const { 91251607Sdim // Add as immediates when possible. Null MCExpr = 0. 92251607Sdim if (Expr == 0) 93251607Sdim Inst.addOperand(MCOperand::CreateImm(0)); 94251607Sdim else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) 95251607Sdim Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 96251607Sdim else 97251607Sdim Inst.addOperand(MCOperand::CreateExpr(Expr)); 98251607Sdim } 99251607Sdim 100251607Sdimpublic: 101251607Sdim // Create particular kinds of operand. 102251607Sdim static SystemZOperand *createToken(StringRef Str, SMLoc Loc) { 103251607Sdim SystemZOperand *Op = new SystemZOperand(KindToken, Loc, Loc); 104251607Sdim Op->Token.Data = Str.data(); 105251607Sdim Op->Token.Length = Str.size(); 106251607Sdim return Op; 107251607Sdim } 108251607Sdim static SystemZOperand *createReg(RegisterKind Kind, unsigned Num, 109251607Sdim SMLoc StartLoc, SMLoc EndLoc) { 110251607Sdim SystemZOperand *Op = new SystemZOperand(KindReg, StartLoc, EndLoc); 111251607Sdim Op->Reg.Kind = Kind; 112251607Sdim Op->Reg.Num = Num; 113251607Sdim return Op; 114251607Sdim } 115251607Sdim static SystemZOperand *createAccessReg(unsigned Num, SMLoc StartLoc, 116251607Sdim SMLoc EndLoc) { 117251607Sdim SystemZOperand *Op = new SystemZOperand(KindAccessReg, StartLoc, EndLoc); 118251607Sdim Op->AccessReg = Num; 119251607Sdim return Op; 120251607Sdim } 121251607Sdim static SystemZOperand *createImm(const MCExpr *Expr, SMLoc StartLoc, 122251607Sdim SMLoc EndLoc) { 123251607Sdim SystemZOperand *Op = new SystemZOperand(KindImm, StartLoc, EndLoc); 124251607Sdim Op->Imm = Expr; 125251607Sdim return Op; 126251607Sdim } 127251607Sdim static SystemZOperand *createMem(RegisterKind RegKind, unsigned Base, 128251607Sdim const MCExpr *Disp, unsigned Index, 129251607Sdim SMLoc StartLoc, SMLoc EndLoc) { 130251607Sdim SystemZOperand *Op = new SystemZOperand(KindMem, StartLoc, EndLoc); 131251607Sdim Op->Mem.RegKind = RegKind; 132251607Sdim Op->Mem.Base = Base; 133251607Sdim Op->Mem.Index = Index; 134251607Sdim Op->Mem.Disp = Disp; 135251607Sdim return Op; 136251607Sdim } 137251607Sdim 138251607Sdim // Token operands 139251607Sdim virtual bool isToken() const LLVM_OVERRIDE { 140251607Sdim return Kind == KindToken; 141251607Sdim } 142251607Sdim StringRef getToken() const { 143251607Sdim assert(Kind == KindToken && "Not a token"); 144251607Sdim return StringRef(Token.Data, Token.Length); 145251607Sdim } 146251607Sdim 147251607Sdim // Register operands. 148251607Sdim virtual bool isReg() const LLVM_OVERRIDE { 149251607Sdim return Kind == KindReg; 150251607Sdim } 151251607Sdim bool isReg(RegisterKind RegKind) const { 152251607Sdim return Kind == KindReg && Reg.Kind == RegKind; 153251607Sdim } 154251607Sdim virtual unsigned getReg() const LLVM_OVERRIDE { 155251607Sdim assert(Kind == KindReg && "Not a register"); 156251607Sdim return Reg.Num; 157251607Sdim } 158251607Sdim 159251607Sdim // Access register operands. Access registers aren't exposed to LLVM 160251607Sdim // as registers. 161251607Sdim bool isAccessReg() const { 162251607Sdim return Kind == KindAccessReg; 163251607Sdim } 164251607Sdim 165251607Sdim // Immediate operands. 166251607Sdim virtual bool isImm() const LLVM_OVERRIDE { 167251607Sdim return Kind == KindImm; 168251607Sdim } 169251607Sdim bool isImm(int64_t MinValue, int64_t MaxValue) const { 170251607Sdim return Kind == KindImm && inRange(Imm, MinValue, MaxValue); 171251607Sdim } 172251607Sdim const MCExpr *getImm() const { 173251607Sdim assert(Kind == KindImm && "Not an immediate"); 174251607Sdim return Imm; 175251607Sdim } 176251607Sdim 177251607Sdim // Memory operands. 178251607Sdim virtual bool isMem() const LLVM_OVERRIDE { 179251607Sdim return Kind == KindMem; 180251607Sdim } 181251607Sdim bool isMem(RegisterKind RegKind, bool HasIndex) const { 182251607Sdim return (Kind == KindMem && 183251607Sdim Mem.RegKind == RegKind && 184251607Sdim (HasIndex || !Mem.Index)); 185251607Sdim } 186251607Sdim bool isMemDisp12(RegisterKind RegKind, bool HasIndex) const { 187251607Sdim return isMem(RegKind, HasIndex) && inRange(Mem.Disp, 0, 0xfff); 188251607Sdim } 189251607Sdim bool isMemDisp20(RegisterKind RegKind, bool HasIndex) const { 190251607Sdim return isMem(RegKind, HasIndex) && inRange(Mem.Disp, -524288, 524287); 191251607Sdim } 192251607Sdim 193251607Sdim // Override MCParsedAsmOperand. 194251607Sdim virtual SMLoc getStartLoc() const LLVM_OVERRIDE { return StartLoc; } 195251607Sdim virtual SMLoc getEndLoc() const LLVM_OVERRIDE { return EndLoc; } 196251607Sdim virtual void print(raw_ostream &OS) const LLVM_OVERRIDE; 197251607Sdim 198251607Sdim // Used by the TableGen code to add particular types of operand 199251607Sdim // to an instruction. 200251607Sdim void addRegOperands(MCInst &Inst, unsigned N) const { 201251607Sdim assert(N == 1 && "Invalid number of operands"); 202251607Sdim Inst.addOperand(MCOperand::CreateReg(getReg())); 203251607Sdim } 204251607Sdim void addAccessRegOperands(MCInst &Inst, unsigned N) const { 205251607Sdim assert(N == 1 && "Invalid number of operands"); 206251607Sdim assert(Kind == KindAccessReg && "Invalid operand type"); 207251607Sdim Inst.addOperand(MCOperand::CreateImm(AccessReg)); 208251607Sdim } 209251607Sdim void addImmOperands(MCInst &Inst, unsigned N) const { 210251607Sdim assert(N == 1 && "Invalid number of operands"); 211251607Sdim addExpr(Inst, getImm()); 212251607Sdim } 213251607Sdim void addBDAddrOperands(MCInst &Inst, unsigned N) const { 214251607Sdim assert(N == 2 && "Invalid number of operands"); 215251607Sdim assert(Kind == KindMem && Mem.Index == 0 && "Invalid operand type"); 216251607Sdim Inst.addOperand(MCOperand::CreateReg(Mem.Base)); 217251607Sdim addExpr(Inst, Mem.Disp); 218251607Sdim } 219251607Sdim void addBDXAddrOperands(MCInst &Inst, unsigned N) const { 220251607Sdim assert(N == 3 && "Invalid number of operands"); 221251607Sdim assert(Kind == KindMem && "Invalid operand type"); 222251607Sdim Inst.addOperand(MCOperand::CreateReg(Mem.Base)); 223251607Sdim addExpr(Inst, Mem.Disp); 224251607Sdim Inst.addOperand(MCOperand::CreateReg(Mem.Index)); 225251607Sdim } 226251607Sdim 227251607Sdim // Used by the TableGen code to check for particular operand types. 228251607Sdim bool isGR32() const { return isReg(GR32Reg); } 229251607Sdim bool isGR64() const { return isReg(GR64Reg); } 230251607Sdim bool isGR128() const { return isReg(GR128Reg); } 231251607Sdim bool isADDR32() const { return isReg(ADDR32Reg); } 232251607Sdim bool isADDR64() const { return isReg(ADDR64Reg); } 233251607Sdim bool isADDR128() const { return false; } 234251607Sdim bool isFP32() const { return isReg(FP32Reg); } 235251607Sdim bool isFP64() const { return isReg(FP64Reg); } 236251607Sdim bool isFP128() const { return isReg(FP128Reg); } 237251607Sdim bool isBDAddr32Disp12() const { return isMemDisp12(ADDR32Reg, false); } 238251607Sdim bool isBDAddr32Disp20() const { return isMemDisp20(ADDR32Reg, false); } 239251607Sdim bool isBDAddr64Disp12() const { return isMemDisp12(ADDR64Reg, false); } 240251607Sdim bool isBDAddr64Disp20() const { return isMemDisp20(ADDR64Reg, false); } 241251607Sdim bool isBDXAddr64Disp12() const { return isMemDisp12(ADDR64Reg, true); } 242251607Sdim bool isBDXAddr64Disp20() const { return isMemDisp20(ADDR64Reg, true); } 243251607Sdim bool isU4Imm() const { return isImm(0, 15); } 244251607Sdim bool isU6Imm() const { return isImm(0, 63); } 245251607Sdim bool isU8Imm() const { return isImm(0, 255); } 246251607Sdim bool isS8Imm() const { return isImm(-128, 127); } 247251607Sdim bool isU16Imm() const { return isImm(0, 65535); } 248251607Sdim bool isS16Imm() const { return isImm(-32768, 32767); } 249251607Sdim bool isU32Imm() const { return isImm(0, (1LL << 32) - 1); } 250251607Sdim bool isS32Imm() const { return isImm(-(1LL << 31), (1LL << 31) - 1); } 251251607Sdim}; 252251607Sdim 253251607Sdim// Maps of asm register numbers to LLVM register numbers, with 0 indicating 254251607Sdim// an invalid register. We don't use register class directly because that 255251607Sdim// specifies the allocation order. 256251607Sdimstatic const unsigned GR32Regs[] = { 257251607Sdim SystemZ::R0W, SystemZ::R1W, SystemZ::R2W, SystemZ::R3W, 258251607Sdim SystemZ::R4W, SystemZ::R5W, SystemZ::R6W, SystemZ::R7W, 259251607Sdim SystemZ::R8W, SystemZ::R9W, SystemZ::R10W, SystemZ::R11W, 260251607Sdim SystemZ::R12W, SystemZ::R13W, SystemZ::R14W, SystemZ::R15W 261251607Sdim}; 262251607Sdimstatic const unsigned GR64Regs[] = { 263251607Sdim SystemZ::R0D, SystemZ::R1D, SystemZ::R2D, SystemZ::R3D, 264251607Sdim SystemZ::R4D, SystemZ::R5D, SystemZ::R6D, SystemZ::R7D, 265251607Sdim SystemZ::R8D, SystemZ::R9D, SystemZ::R10D, SystemZ::R11D, 266251607Sdim SystemZ::R12D, SystemZ::R13D, SystemZ::R14D, SystemZ::R15D 267251607Sdim}; 268251607Sdimstatic const unsigned GR128Regs[] = { 269251607Sdim SystemZ::R0Q, 0, SystemZ::R2Q, 0, 270251607Sdim SystemZ::R4Q, 0, SystemZ::R6Q, 0, 271251607Sdim SystemZ::R8Q, 0, SystemZ::R10Q, 0, 272251607Sdim SystemZ::R12Q, 0, SystemZ::R14Q, 0 273251607Sdim}; 274251607Sdimstatic const unsigned FP32Regs[] = { 275251607Sdim SystemZ::F0S, SystemZ::F1S, SystemZ::F2S, SystemZ::F3S, 276251607Sdim SystemZ::F4S, SystemZ::F5S, SystemZ::F6S, SystemZ::F7S, 277251607Sdim SystemZ::F8S, SystemZ::F9S, SystemZ::F10S, SystemZ::F11S, 278251607Sdim SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S 279251607Sdim}; 280251607Sdimstatic const unsigned FP64Regs[] = { 281251607Sdim SystemZ::F0D, SystemZ::F1D, SystemZ::F2D, SystemZ::F3D, 282251607Sdim SystemZ::F4D, SystemZ::F5D, SystemZ::F6D, SystemZ::F7D, 283251607Sdim SystemZ::F8D, SystemZ::F9D, SystemZ::F10D, SystemZ::F11D, 284251607Sdim SystemZ::F12D, SystemZ::F13D, SystemZ::F14D, SystemZ::F15D 285251607Sdim}; 286251607Sdimstatic const unsigned FP128Regs[] = { 287251607Sdim SystemZ::F0Q, SystemZ::F1Q, 0, 0, 288251607Sdim SystemZ::F4Q, SystemZ::F5Q, 0, 0, 289251607Sdim SystemZ::F8Q, SystemZ::F9Q, 0, 0, 290251607Sdim SystemZ::F12Q, SystemZ::F13Q, 0, 0 291251607Sdim}; 292251607Sdim 293251607Sdimclass SystemZAsmParser : public MCTargetAsmParser { 294251607Sdim#define GET_ASSEMBLER_HEADER 295251607Sdim#include "SystemZGenAsmMatcher.inc" 296251607Sdim 297251607Sdimprivate: 298251607Sdim MCSubtargetInfo &STI; 299251607Sdim MCAsmParser &Parser; 300251607Sdim struct Register { 301251607Sdim char Prefix; 302251607Sdim unsigned Number; 303251607Sdim SMLoc StartLoc, EndLoc; 304251607Sdim }; 305251607Sdim 306251607Sdim bool parseRegister(Register &Reg); 307251607Sdim 308251607Sdim OperandMatchResultTy 309251607Sdim parseRegister(Register &Reg, char Prefix, const unsigned *Regs, 310251607Sdim bool IsAddress = false); 311251607Sdim 312251607Sdim OperandMatchResultTy 313251607Sdim parseRegister(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 314251607Sdim char Prefix, const unsigned *Regs, 315251607Sdim SystemZOperand::RegisterKind Kind, 316251607Sdim bool IsAddress = false); 317251607Sdim 318251607Sdim OperandMatchResultTy 319251607Sdim parseAddress(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 320251607Sdim const unsigned *Regs, SystemZOperand::RegisterKind RegKind, 321251607Sdim bool HasIndex); 322251607Sdim 323251607Sdim bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 324251607Sdim StringRef Mnemonic); 325251607Sdim 326251607Sdimpublic: 327251607Sdim SystemZAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser) 328251607Sdim : MCTargetAsmParser(), STI(sti), Parser(parser) { 329251607Sdim MCAsmParserExtension::Initialize(Parser); 330251607Sdim 331251607Sdim // Initialize the set of available features. 332251607Sdim setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 333251607Sdim } 334251607Sdim 335251607Sdim // Override MCTargetAsmParser. 336251607Sdim virtual bool ParseDirective(AsmToken DirectiveID) LLVM_OVERRIDE; 337251607Sdim virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 338251607Sdim SMLoc &EndLoc) LLVM_OVERRIDE; 339251607Sdim virtual bool ParseInstruction(ParseInstructionInfo &Info, 340251607Sdim StringRef Name, SMLoc NameLoc, 341251607Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands) 342251607Sdim LLVM_OVERRIDE; 343251607Sdim virtual bool 344251607Sdim MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 345251607Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands, 346251607Sdim MCStreamer &Out, unsigned &ErrorInfo, 347251607Sdim bool MatchingInlineAsm) LLVM_OVERRIDE; 348251607Sdim 349251607Sdim // Used by the TableGen code to parse particular operand types. 350251607Sdim OperandMatchResultTy 351251607Sdim parseGR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 352251607Sdim return parseRegister(Operands, 'r', GR32Regs, SystemZOperand::GR32Reg); 353251607Sdim } 354251607Sdim OperandMatchResultTy 355251607Sdim parseGR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 356251607Sdim return parseRegister(Operands, 'r', GR64Regs, SystemZOperand::GR64Reg); 357251607Sdim } 358251607Sdim OperandMatchResultTy 359251607Sdim parseGR128(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 360251607Sdim return parseRegister(Operands, 'r', GR128Regs, SystemZOperand::GR128Reg); 361251607Sdim } 362251607Sdim OperandMatchResultTy 363251607Sdim parseADDR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 364251607Sdim return parseRegister(Operands, 'r', GR32Regs, SystemZOperand::ADDR32Reg, 365251607Sdim true); 366251607Sdim } 367251607Sdim OperandMatchResultTy 368251607Sdim parseADDR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 369251607Sdim return parseRegister(Operands, 'r', GR64Regs, SystemZOperand::ADDR64Reg, 370251607Sdim true); 371251607Sdim } 372251607Sdim OperandMatchResultTy 373251607Sdim parseADDR128(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 374251607Sdim llvm_unreachable("Shouldn't be used as an operand"); 375251607Sdim } 376251607Sdim OperandMatchResultTy 377251607Sdim parseFP32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 378251607Sdim return parseRegister(Operands, 'f', FP32Regs, SystemZOperand::FP32Reg); 379251607Sdim } 380251607Sdim OperandMatchResultTy 381251607Sdim parseFP64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 382251607Sdim return parseRegister(Operands, 'f', FP64Regs, SystemZOperand::FP64Reg); 383251607Sdim } 384251607Sdim OperandMatchResultTy 385251607Sdim parseFP128(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 386251607Sdim return parseRegister(Operands, 'f', FP128Regs, SystemZOperand::FP128Reg); 387251607Sdim } 388251607Sdim OperandMatchResultTy 389251607Sdim parseBDAddr32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 390251607Sdim return parseAddress(Operands, GR32Regs, SystemZOperand::ADDR32Reg, false); 391251607Sdim } 392251607Sdim OperandMatchResultTy 393251607Sdim parseBDAddr64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 394251607Sdim return parseAddress(Operands, GR64Regs, SystemZOperand::ADDR64Reg, false); 395251607Sdim } 396251607Sdim OperandMatchResultTy 397251607Sdim parseBDXAddr64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 398251607Sdim return parseAddress(Operands, GR64Regs, SystemZOperand::ADDR64Reg, true); 399251607Sdim } 400251607Sdim OperandMatchResultTy 401251607Sdim parseAccessReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 402251607Sdim}; 403251607Sdim} 404251607Sdim 405251607Sdim#define GET_REGISTER_MATCHER 406251607Sdim#define GET_SUBTARGET_FEATURE_NAME 407251607Sdim#define GET_MATCHER_IMPLEMENTATION 408251607Sdim#include "SystemZGenAsmMatcher.inc" 409251607Sdim 410251607Sdimvoid SystemZOperand::print(raw_ostream &OS) const { 411251607Sdim llvm_unreachable("Not implemented"); 412251607Sdim} 413251607Sdim 414251607Sdim// Parse one register of the form %<prefix><number>. 415251607Sdimbool SystemZAsmParser::parseRegister(Register &Reg) { 416251607Sdim Reg.StartLoc = Parser.getTok().getLoc(); 417251607Sdim 418251607Sdim // Eat the % prefix. 419251607Sdim if (Parser.getTok().isNot(AsmToken::Percent)) 420251607Sdim return true; 421251607Sdim Parser.Lex(); 422251607Sdim 423251607Sdim // Expect a register name. 424251607Sdim if (Parser.getTok().isNot(AsmToken::Identifier)) 425251607Sdim return true; 426251607Sdim 427251607Sdim // Check the prefix. 428251607Sdim StringRef Name = Parser.getTok().getString(); 429251607Sdim if (Name.size() < 2) 430251607Sdim return true; 431251607Sdim Reg.Prefix = Name[0]; 432251607Sdim 433251607Sdim // Treat the rest of the register name as a register number. 434251607Sdim if (Name.substr(1).getAsInteger(10, Reg.Number)) 435251607Sdim return true; 436251607Sdim 437251607Sdim Reg.EndLoc = Parser.getTok().getLoc(); 438251607Sdim Parser.Lex(); 439251607Sdim return false; 440251607Sdim} 441251607Sdim 442251607Sdim// Parse a register with prefix Prefix and convert it to LLVM numbering. 443251607Sdim// Regs maps asm register numbers to LLVM register numbers, with zero 444251607Sdim// entries indicating an invalid register. IsAddress says whether the 445251607Sdim// register appears in an address context. 446251607SdimSystemZAsmParser::OperandMatchResultTy 447251607SdimSystemZAsmParser::parseRegister(Register &Reg, char Prefix, 448251607Sdim const unsigned *Regs, bool IsAddress) { 449251607Sdim if (parseRegister(Reg)) 450251607Sdim return MatchOperand_NoMatch; 451251607Sdim if (Reg.Prefix != Prefix || Reg.Number > 15 || Regs[Reg.Number] == 0) { 452251607Sdim Error(Reg.StartLoc, "invalid register"); 453251607Sdim return MatchOperand_ParseFail; 454251607Sdim } 455251607Sdim if (Reg.Number == 0 && IsAddress) { 456251607Sdim Error(Reg.StartLoc, "%r0 used in an address"); 457251607Sdim return MatchOperand_ParseFail; 458251607Sdim } 459251607Sdim Reg.Number = Regs[Reg.Number]; 460251607Sdim return MatchOperand_Success; 461251607Sdim} 462251607Sdim 463251607Sdim// Parse a register and add it to Operands. Prefix is 'r' for GPRs, 464251607Sdim// 'f' for FPRs, etc. Regs maps asm register numbers to LLVM register numbers, 465251607Sdim// with zero entries indicating an invalid register. Kind is the type of 466251607Sdim// register represented by Regs and IsAddress says whether the register is 467251607Sdim// being parsed in an address context, meaning that %r0 evaluates as 0. 468251607SdimSystemZAsmParser::OperandMatchResultTy 469251607SdimSystemZAsmParser::parseRegister(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 470251607Sdim char Prefix, const unsigned *Regs, 471251607Sdim SystemZOperand::RegisterKind Kind, 472251607Sdim bool IsAddress) { 473251607Sdim Register Reg; 474251607Sdim OperandMatchResultTy Result = parseRegister(Reg, Prefix, Regs, IsAddress); 475251607Sdim if (Result == MatchOperand_Success) 476251607Sdim Operands.push_back(SystemZOperand::createReg(Kind, Reg.Number, 477251607Sdim Reg.StartLoc, Reg.EndLoc)); 478251607Sdim return Result; 479251607Sdim} 480251607Sdim 481251607Sdim// Parse a memory operand and add it to Operands. Regs maps asm register 482251607Sdim// numbers to LLVM address registers and RegKind says what kind of address 483251607Sdim// register we're using (ADDR32Reg or ADDR64Reg). HasIndex says whether 484251607Sdim// the address allows index registers. 485251607SdimSystemZAsmParser::OperandMatchResultTy 486251607SdimSystemZAsmParser::parseAddress(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 487251607Sdim const unsigned *Regs, 488251607Sdim SystemZOperand::RegisterKind RegKind, 489251607Sdim bool HasIndex) { 490251607Sdim SMLoc StartLoc = Parser.getTok().getLoc(); 491251607Sdim 492251607Sdim // Parse the displacement, which must always be present. 493251607Sdim const MCExpr *Disp; 494251607Sdim if (getParser().parseExpression(Disp)) 495251607Sdim return MatchOperand_NoMatch; 496251607Sdim 497251607Sdim // Parse the optional base and index. 498251607Sdim unsigned Index = 0; 499251607Sdim unsigned Base = 0; 500251607Sdim if (getLexer().is(AsmToken::LParen)) { 501251607Sdim Parser.Lex(); 502251607Sdim 503251607Sdim // Parse the first register. 504251607Sdim Register Reg; 505251607Sdim OperandMatchResultTy Result = parseRegister(Reg, 'r', GR64Regs, true); 506251607Sdim if (Result != MatchOperand_Success) 507251607Sdim return Result; 508251607Sdim 509251607Sdim // Check whether there's a second register. If so, the one that we 510251607Sdim // just parsed was the index. 511251607Sdim if (getLexer().is(AsmToken::Comma)) { 512251607Sdim Parser.Lex(); 513251607Sdim 514251607Sdim if (!HasIndex) { 515251607Sdim Error(Reg.StartLoc, "invalid use of indexed addressing"); 516251607Sdim return MatchOperand_ParseFail; 517251607Sdim } 518251607Sdim 519251607Sdim Index = Reg.Number; 520251607Sdim Result = parseRegister(Reg, 'r', GR64Regs, true); 521251607Sdim if (Result != MatchOperand_Success) 522251607Sdim return Result; 523251607Sdim } 524251607Sdim Base = Reg.Number; 525251607Sdim 526251607Sdim // Consume the closing bracket. 527251607Sdim if (getLexer().isNot(AsmToken::RParen)) 528251607Sdim return MatchOperand_NoMatch; 529251607Sdim Parser.Lex(); 530251607Sdim } 531251607Sdim 532251607Sdim SMLoc EndLoc = 533251607Sdim SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 534251607Sdim Operands.push_back(SystemZOperand::createMem(RegKind, Base, Disp, Index, 535251607Sdim StartLoc, EndLoc)); 536251607Sdim return MatchOperand_Success; 537251607Sdim} 538251607Sdim 539251607Sdimbool SystemZAsmParser::ParseDirective(AsmToken DirectiveID) { 540251607Sdim return true; 541251607Sdim} 542251607Sdim 543251607Sdimbool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 544251607Sdim SMLoc &EndLoc) { 545251607Sdim Register Reg; 546251607Sdim if (parseRegister(Reg)) 547251607Sdim return Error(Reg.StartLoc, "register expected"); 548251607Sdim if (Reg.Prefix == 'r' && Reg.Number < 16) 549251607Sdim RegNo = GR64Regs[Reg.Number]; 550251607Sdim else if (Reg.Prefix == 'f' && Reg.Number < 16) 551251607Sdim RegNo = FP64Regs[Reg.Number]; 552251607Sdim else 553251607Sdim return Error(Reg.StartLoc, "invalid register"); 554251607Sdim StartLoc = Reg.StartLoc; 555251607Sdim EndLoc = Reg.EndLoc; 556251607Sdim return false; 557251607Sdim} 558251607Sdim 559251607Sdimbool SystemZAsmParser:: 560251607SdimParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, 561251607Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 562251607Sdim Operands.push_back(SystemZOperand::createToken(Name, NameLoc)); 563251607Sdim 564251607Sdim // Read the remaining operands. 565251607Sdim if (getLexer().isNot(AsmToken::EndOfStatement)) { 566251607Sdim // Read the first operand. 567251607Sdim if (parseOperand(Operands, Name)) { 568251607Sdim Parser.eatToEndOfStatement(); 569251607Sdim return true; 570251607Sdim } 571251607Sdim 572251607Sdim // Read any subsequent operands. 573251607Sdim while (getLexer().is(AsmToken::Comma)) { 574251607Sdim Parser.Lex(); 575251607Sdim if (parseOperand(Operands, Name)) { 576251607Sdim Parser.eatToEndOfStatement(); 577251607Sdim return true; 578251607Sdim } 579251607Sdim } 580251607Sdim if (getLexer().isNot(AsmToken::EndOfStatement)) { 581251607Sdim SMLoc Loc = getLexer().getLoc(); 582251607Sdim Parser.eatToEndOfStatement(); 583251607Sdim return Error(Loc, "unexpected token in argument list"); 584251607Sdim } 585251607Sdim } 586251607Sdim 587251607Sdim // Consume the EndOfStatement. 588251607Sdim Parser.Lex(); 589251607Sdim return false; 590251607Sdim} 591251607Sdim 592251607Sdimbool SystemZAsmParser:: 593251607SdimparseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 594251607Sdim StringRef Mnemonic) { 595251607Sdim // Check if the current operand has a custom associated parser, if so, try to 596251607Sdim // custom parse the operand, or fallback to the general approach. 597251607Sdim OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 598251607Sdim if (ResTy == MatchOperand_Success) 599251607Sdim return false; 600251607Sdim 601251607Sdim // If there wasn't a custom match, try the generic matcher below. Otherwise, 602251607Sdim // there was a match, but an error occurred, in which case, just return that 603251607Sdim // the operand parsing failed. 604251607Sdim if (ResTy == MatchOperand_ParseFail) 605251607Sdim return true; 606251607Sdim 607251607Sdim // The only other type of operand is an immediate. 608251607Sdim const MCExpr *Expr; 609251607Sdim SMLoc StartLoc = Parser.getTok().getLoc(); 610251607Sdim if (getParser().parseExpression(Expr)) 611251607Sdim return true; 612251607Sdim 613251607Sdim SMLoc EndLoc = 614251607Sdim SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 615251607Sdim Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc)); 616251607Sdim return false; 617251607Sdim} 618251607Sdim 619251607Sdimbool SystemZAsmParser:: 620251607SdimMatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 621251607Sdim SmallVectorImpl<MCParsedAsmOperand*> &Operands, 622251607Sdim MCStreamer &Out, unsigned &ErrorInfo, 623251607Sdim bool MatchingInlineAsm) { 624251607Sdim MCInst Inst; 625251607Sdim unsigned MatchResult; 626251607Sdim 627251607Sdim MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, 628251607Sdim MatchingInlineAsm); 629251607Sdim switch (MatchResult) { 630251607Sdim default: break; 631251607Sdim case Match_Success: 632251607Sdim Inst.setLoc(IDLoc); 633251607Sdim Out.EmitInstruction(Inst); 634251607Sdim return false; 635251607Sdim 636251607Sdim case Match_MissingFeature: { 637251607Sdim assert(ErrorInfo && "Unknown missing feature!"); 638251607Sdim // Special case the error message for the very common case where only 639251607Sdim // a single subtarget feature is missing 640251607Sdim std::string Msg = "instruction requires:"; 641251607Sdim unsigned Mask = 1; 642251607Sdim for (unsigned I = 0; I < sizeof(ErrorInfo) * 8 - 1; ++I) { 643251607Sdim if (ErrorInfo & Mask) { 644251607Sdim Msg += " "; 645251607Sdim Msg += getSubtargetFeatureName(ErrorInfo & Mask); 646251607Sdim } 647251607Sdim Mask <<= 1; 648251607Sdim } 649251607Sdim return Error(IDLoc, Msg); 650251607Sdim } 651251607Sdim 652251607Sdim case Match_InvalidOperand: { 653251607Sdim SMLoc ErrorLoc = IDLoc; 654251607Sdim if (ErrorInfo != ~0U) { 655251607Sdim if (ErrorInfo >= Operands.size()) 656251607Sdim return Error(IDLoc, "too few operands for instruction"); 657251607Sdim 658251607Sdim ErrorLoc = ((SystemZOperand*)Operands[ErrorInfo])->getStartLoc(); 659251607Sdim if (ErrorLoc == SMLoc()) 660251607Sdim ErrorLoc = IDLoc; 661251607Sdim } 662251607Sdim return Error(ErrorLoc, "invalid operand for instruction"); 663251607Sdim } 664251607Sdim 665251607Sdim case Match_MnemonicFail: 666251607Sdim return Error(IDLoc, "invalid instruction"); 667251607Sdim } 668251607Sdim 669251607Sdim llvm_unreachable("Unexpected match type"); 670251607Sdim} 671251607Sdim 672251607SdimSystemZAsmParser::OperandMatchResultTy SystemZAsmParser:: 673251607SdimparseAccessReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 674251607Sdim Register Reg; 675251607Sdim if (parseRegister(Reg)) 676251607Sdim return MatchOperand_NoMatch; 677251607Sdim if (Reg.Prefix != 'a' || Reg.Number > 15) { 678251607Sdim Error(Reg.StartLoc, "invalid register"); 679251607Sdim return MatchOperand_ParseFail; 680251607Sdim } 681251607Sdim Operands.push_back(SystemZOperand::createAccessReg(Reg.Number, 682251607Sdim Reg.StartLoc, Reg.EndLoc)); 683251607Sdim return MatchOperand_Success; 684251607Sdim} 685251607Sdim 686251607Sdim// Force static initialization. 687251607Sdimextern "C" void LLVMInitializeSystemZAsmParser() { 688251607Sdim RegisterMCAsmParser<SystemZAsmParser> X(TheSystemZTarget); 689251607Sdim} 690