1327952Sdim//===- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===// 2284677Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6284677Sdim// 7284677Sdim//===----------------------------------------------------------------------===// 8284677Sdim 9327952Sdim#include "AMDGPU.h" 10309124Sdim#include "AMDKernelCodeT.h" 11284677Sdim#include "MCTargetDesc/AMDGPUMCTargetDesc.h" 12285181Sdim#include "MCTargetDesc/AMDGPUTargetStreamer.h" 13309124Sdim#include "SIDefines.h" 14341825Sdim#include "SIInstrInfo.h" 15353358Sdim#include "TargetInfo/AMDGPUTargetInfo.h" 16321369Sdim#include "Utils/AMDGPUAsmUtils.h" 17285181Sdim#include "Utils/AMDGPUBaseInfo.h" 18309124Sdim#include "Utils/AMDKernelCodeTUtils.h" 19284677Sdim#include "llvm/ADT/APFloat.h" 20314564Sdim#include "llvm/ADT/APInt.h" 21321369Sdim#include "llvm/ADT/ArrayRef.h" 22321369Sdim#include "llvm/ADT/STLExtras.h" 23309124Sdim#include "llvm/ADT/SmallBitVector.h" 24284677Sdim#include "llvm/ADT/SmallString.h" 25314564Sdim#include "llvm/ADT/StringRef.h" 26284677Sdim#include "llvm/ADT/StringSwitch.h" 27284677Sdim#include "llvm/ADT/Twine.h" 28321369Sdim#include "llvm/BinaryFormat/ELF.h" 29314564Sdim#include "llvm/MC/MCAsmInfo.h" 30284677Sdim#include "llvm/MC/MCContext.h" 31284677Sdim#include "llvm/MC/MCExpr.h" 32284677Sdim#include "llvm/MC/MCInst.h" 33314564Sdim#include "llvm/MC/MCInstrDesc.h" 34284677Sdim#include "llvm/MC/MCInstrInfo.h" 35284677Sdim#include "llvm/MC/MCParser/MCAsmLexer.h" 36284677Sdim#include "llvm/MC/MCParser/MCAsmParser.h" 37314564Sdim#include "llvm/MC/MCParser/MCAsmParserExtension.h" 38284677Sdim#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 39309124Sdim#include "llvm/MC/MCParser/MCTargetAsmParser.h" 40284677Sdim#include "llvm/MC/MCRegisterInfo.h" 41284677Sdim#include "llvm/MC/MCStreamer.h" 42284677Sdim#include "llvm/MC/MCSubtargetInfo.h" 43314564Sdim#include "llvm/MC/MCSymbol.h" 44327952Sdim#include "llvm/Support/AMDGPUMetadata.h" 45341825Sdim#include "llvm/Support/AMDHSAKernelDescriptor.h" 46314564Sdim#include "llvm/Support/Casting.h" 47327952Sdim#include "llvm/Support/Compiler.h" 48360784Sdim#include "llvm/Support/Error.h" 49341825Sdim#include "llvm/Support/MachineValueType.h" 50314564Sdim#include "llvm/Support/MathExtras.h" 51314564Sdim#include "llvm/Support/SMLoc.h" 52344779Sdim#include "llvm/Support/TargetParser.h" 53284677Sdim#include "llvm/Support/TargetRegistry.h" 54284677Sdim#include "llvm/Support/raw_ostream.h" 55314564Sdim#include <algorithm> 56314564Sdim#include <cassert> 57314564Sdim#include <cstdint> 58314564Sdim#include <cstring> 59314564Sdim#include <iterator> 60314564Sdim#include <map> 61314564Sdim#include <memory> 62314564Sdim#include <string> 63284677Sdim 64284677Sdimusing namespace llvm; 65314564Sdimusing namespace llvm::AMDGPU; 66341825Sdimusing namespace llvm::amdhsa; 67284677Sdim 68284677Sdimnamespace { 69284677Sdim 70314564Sdimclass AMDGPUAsmParser; 71284677Sdim 72353358Sdimenum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_AGPR, IS_TTMP, IS_SPECIAL }; 73309124Sdim 74314564Sdim//===----------------------------------------------------------------------===// 75314564Sdim// Operand 76314564Sdim//===----------------------------------------------------------------------===// 77314564Sdim 78284677Sdimclass AMDGPUOperand : public MCParsedAsmOperand { 79284677Sdim enum KindTy { 80284677Sdim Token, 81284677Sdim Immediate, 82284677Sdim Register, 83284677Sdim Expression 84284677Sdim } Kind; 85284677Sdim 86284677Sdim SMLoc StartLoc, EndLoc; 87314564Sdim const AMDGPUAsmParser *AsmParser; 88284677Sdim 89284677Sdimpublic: 90321369Sdim AMDGPUOperand(KindTy Kind_, const AMDGPUAsmParser *AsmParser_) 91314564Sdim : MCParsedAsmOperand(), Kind(Kind_), AsmParser(AsmParser_) {} 92284677Sdim 93327952Sdim using Ptr = std::unique_ptr<AMDGPUOperand>; 94284677Sdim 95309124Sdim struct Modifiers { 96314564Sdim bool Abs = false; 97314564Sdim bool Neg = false; 98314564Sdim bool Sext = false; 99309124Sdim 100309124Sdim bool hasFPModifiers() const { return Abs || Neg; } 101309124Sdim bool hasIntModifiers() const { return Sext; } 102309124Sdim bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); } 103309124Sdim 104309124Sdim int64_t getFPModifiersOperand() const { 105309124Sdim int64_t Operand = 0; 106353358Sdim Operand |= Abs ? SISrcMods::ABS : 0u; 107353358Sdim Operand |= Neg ? SISrcMods::NEG : 0u; 108309124Sdim return Operand; 109309124Sdim } 110309124Sdim 111309124Sdim int64_t getIntModifiersOperand() const { 112309124Sdim int64_t Operand = 0; 113353358Sdim Operand |= Sext ? SISrcMods::SEXT : 0u; 114309124Sdim return Operand; 115309124Sdim } 116309124Sdim 117309124Sdim int64_t getModifiersOperand() const { 118309124Sdim assert(!(hasFPModifiers() && hasIntModifiers()) 119309124Sdim && "fp and int modifiers should not be used simultaneously"); 120309124Sdim if (hasFPModifiers()) { 121309124Sdim return getFPModifiersOperand(); 122309124Sdim } else if (hasIntModifiers()) { 123309124Sdim return getIntModifiersOperand(); 124309124Sdim } else { 125309124Sdim return 0; 126309124Sdim } 127309124Sdim } 128309124Sdim 129309124Sdim friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods); 130309124Sdim }; 131309124Sdim 132284677Sdim enum ImmTy { 133284677Sdim ImmTyNone, 134284677Sdim ImmTyGDS, 135341825Sdim ImmTyLDS, 136309124Sdim ImmTyOffen, 137309124Sdim ImmTyIdxen, 138309124Sdim ImmTyAddr64, 139284677Sdim ImmTyOffset, 140327952Sdim ImmTyInstOffset, 141309124Sdim ImmTyOffset0, 142309124Sdim ImmTyOffset1, 143353358Sdim ImmTyDLC, 144284677Sdim ImmTyGLC, 145284677Sdim ImmTySLC, 146360784Sdim ImmTySWZ, 147284677Sdim ImmTyTFE, 148341825Sdim ImmTyD16, 149309124Sdim ImmTyClampSI, 150309124Sdim ImmTyOModSI, 151353358Sdim ImmTyDPP8, 152309124Sdim ImmTyDppCtrl, 153309124Sdim ImmTyDppRowMask, 154309124Sdim ImmTyDppBankMask, 155309124Sdim ImmTyDppBoundCtrl, 156353358Sdim ImmTyDppFi, 157309124Sdim ImmTySdwaDstSel, 158309124Sdim ImmTySdwaSrc0Sel, 159309124Sdim ImmTySdwaSrc1Sel, 160309124Sdim ImmTySdwaDstUnused, 161309124Sdim ImmTyDMask, 162353358Sdim ImmTyDim, 163309124Sdim ImmTyUNorm, 164309124Sdim ImmTyDA, 165344779Sdim ImmTyR128A16, 166309124Sdim ImmTyLWE, 167314564Sdim ImmTyExpTgt, 168314564Sdim ImmTyExpCompr, 169314564Sdim ImmTyExpVM, 170344779Sdim ImmTyFORMAT, 171309124Sdim ImmTyHwreg, 172314564Sdim ImmTyOff, 173309124Sdim ImmTySendMsg, 174314564Sdim ImmTyInterpSlot, 175314564Sdim ImmTyInterpAttr, 176321369Sdim ImmTyAttrChan, 177321369Sdim ImmTyOpSel, 178321369Sdim ImmTyOpSelHi, 179321369Sdim ImmTyNegLo, 180321369Sdim ImmTyNegHi, 181327952Sdim ImmTySwizzle, 182353358Sdim ImmTyGprIdxMode, 183353358Sdim ImmTyHigh, 184353358Sdim ImmTyBLGP, 185353358Sdim ImmTyCBSZ, 186353358Sdim ImmTyABID, 187353358Sdim ImmTyEndpgm, 188284677Sdim }; 189284677Sdim 190353358Sdimprivate: 191284677Sdim struct TokOp { 192284677Sdim const char *Data; 193284677Sdim unsigned Length; 194284677Sdim }; 195284677Sdim 196284677Sdim struct ImmOp { 197314564Sdim int64_t Val; 198314564Sdim ImmTy Type; 199284677Sdim bool IsFPImm; 200309124Sdim Modifiers Mods; 201284677Sdim }; 202284677Sdim 203284677Sdim struct RegOp { 204284677Sdim unsigned RegNo; 205309124Sdim Modifiers Mods; 206284677Sdim }; 207284677Sdim 208284677Sdim union { 209284677Sdim TokOp Tok; 210284677Sdim ImmOp Imm; 211284677Sdim RegOp Reg; 212284677Sdim const MCExpr *Expr; 213284677Sdim }; 214284677Sdim 215353358Sdimpublic: 216309124Sdim bool isToken() const override { 217309124Sdim if (Kind == Token) 218309124Sdim return true; 219284677Sdim 220309124Sdim // When parsing operands, we can't always tell if something was meant to be 221309124Sdim // a token, like 'gds', or an expression that references a global variable. 222309124Sdim // In this case, we assume the string is an expression, and if we need to 223309124Sdim // interpret is a token, then we treat the symbol name as the token. 224360784Sdim return isSymbolRefExpr(); 225284677Sdim } 226284677Sdim 227360784Sdim bool isSymbolRefExpr() const { 228360784Sdim return isExpr() && Expr && isa<MCSymbolRefExpr>(Expr); 229360784Sdim } 230360784Sdim 231284677Sdim bool isImm() const override { 232284677Sdim return Kind == Immediate; 233284677Sdim } 234284677Sdim 235314564Sdim bool isInlinableImm(MVT type) const; 236314564Sdim bool isLiteralImm(MVT type) const; 237284677Sdim 238284677Sdim bool isRegKind() const { 239284677Sdim return Kind == Register; 240284677Sdim } 241284677Sdim 242284677Sdim bool isReg() const override { 243314564Sdim return isRegKind() && !hasModifiers(); 244284677Sdim } 245284677Sdim 246353358Sdim bool isRegOrImmWithInputMods(unsigned RCID, MVT type) const { 247353358Sdim return isRegClass(RCID) || isInlinableImm(type) || isLiteralImm(type); 248284677Sdim } 249284677Sdim 250314564Sdim bool isRegOrImmWithInt16InputMods() const { 251353358Sdim return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i16); 252314564Sdim } 253314564Sdim 254314564Sdim bool isRegOrImmWithInt32InputMods() const { 255353358Sdim return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i32); 256314564Sdim } 257314564Sdim 258314564Sdim bool isRegOrImmWithInt64InputMods() const { 259353358Sdim return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::i64); 260314564Sdim } 261314564Sdim 262314564Sdim bool isRegOrImmWithFP16InputMods() const { 263353358Sdim return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f16); 264314564Sdim } 265314564Sdim 266314564Sdim bool isRegOrImmWithFP32InputMods() const { 267353358Sdim return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f32); 268314564Sdim } 269314564Sdim 270314564Sdim bool isRegOrImmWithFP64InputMods() const { 271353358Sdim return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::f64); 272314564Sdim } 273314564Sdim 274314564Sdim bool isVReg() const { 275314564Sdim return isRegClass(AMDGPU::VGPR_32RegClassID) || 276314564Sdim isRegClass(AMDGPU::VReg_64RegClassID) || 277314564Sdim isRegClass(AMDGPU::VReg_96RegClassID) || 278314564Sdim isRegClass(AMDGPU::VReg_128RegClassID) || 279360784Sdim isRegClass(AMDGPU::VReg_160RegClassID) || 280314564Sdim isRegClass(AMDGPU::VReg_256RegClassID) || 281360784Sdim isRegClass(AMDGPU::VReg_512RegClassID) || 282360784Sdim isRegClass(AMDGPU::VReg_1024RegClassID); 283314564Sdim } 284314564Sdim 285353358Sdim bool isVReg32() const { 286353358Sdim return isRegClass(AMDGPU::VGPR_32RegClassID); 287353358Sdim } 288353358Sdim 289314564Sdim bool isVReg32OrOff() const { 290353358Sdim return isOff() || isVReg32(); 291314564Sdim } 292314564Sdim 293360784Sdim bool isNull() const { 294360784Sdim return isRegKind() && getReg() == AMDGPU::SGPR_NULL; 295360784Sdim } 296360784Sdim 297341825Sdim bool isSDWAOperand(MVT type) const; 298341825Sdim bool isSDWAFP16Operand() const; 299341825Sdim bool isSDWAFP32Operand() const; 300341825Sdim bool isSDWAInt16Operand() const; 301341825Sdim bool isSDWAInt32Operand() const; 302321369Sdim 303309124Sdim bool isImmTy(ImmTy ImmT) const { 304309124Sdim return isImm() && Imm.Type == ImmT; 305284677Sdim } 306314564Sdim 307309124Sdim bool isImmModifier() const { 308309124Sdim return isImm() && Imm.Type != ImmTyNone; 309284677Sdim } 310314564Sdim 311309124Sdim bool isClampSI() const { return isImmTy(ImmTyClampSI); } 312309124Sdim bool isOModSI() const { return isImmTy(ImmTyOModSI); } 313309124Sdim bool isDMask() const { return isImmTy(ImmTyDMask); } 314353358Sdim bool isDim() const { return isImmTy(ImmTyDim); } 315309124Sdim bool isUNorm() const { return isImmTy(ImmTyUNorm); } 316309124Sdim bool isDA() const { return isImmTy(ImmTyDA); } 317344779Sdim bool isR128A16() const { return isImmTy(ImmTyR128A16); } 318309124Sdim bool isLWE() const { return isImmTy(ImmTyLWE); } 319314564Sdim bool isOff() const { return isImmTy(ImmTyOff); } 320314564Sdim bool isExpTgt() const { return isImmTy(ImmTyExpTgt); } 321314564Sdim bool isExpVM() const { return isImmTy(ImmTyExpVM); } 322314564Sdim bool isExpCompr() const { return isImmTy(ImmTyExpCompr); } 323309124Sdim bool isOffen() const { return isImmTy(ImmTyOffen); } 324309124Sdim bool isIdxen() const { return isImmTy(ImmTyIdxen); } 325309124Sdim bool isAddr64() const { return isImmTy(ImmTyAddr64); } 326309124Sdim bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); } 327353358Sdim bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<8>(getImm()); } 328309124Sdim bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); } 329321369Sdim 330353358Sdim bool isFlatOffset() const { return isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset); } 331309124Sdim bool isGDS() const { return isImmTy(ImmTyGDS); } 332341825Sdim bool isLDS() const { return isImmTy(ImmTyLDS); } 333353358Sdim bool isDLC() const { return isImmTy(ImmTyDLC); } 334309124Sdim bool isGLC() const { return isImmTy(ImmTyGLC); } 335309124Sdim bool isSLC() const { return isImmTy(ImmTySLC); } 336360784Sdim bool isSWZ() const { return isImmTy(ImmTySWZ); } 337309124Sdim bool isTFE() const { return isImmTy(ImmTyTFE); } 338341825Sdim bool isD16() const { return isImmTy(ImmTyD16); } 339344779Sdim bool isFORMAT() const { return isImmTy(ImmTyFORMAT) && isUInt<8>(getImm()); } 340309124Sdim bool isBankMask() const { return isImmTy(ImmTyDppBankMask); } 341309124Sdim bool isRowMask() const { return isImmTy(ImmTyDppRowMask); } 342309124Sdim bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); } 343353358Sdim bool isFI() const { return isImmTy(ImmTyDppFi); } 344309124Sdim bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); } 345309124Sdim bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); } 346309124Sdim bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); } 347309124Sdim bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); } 348314564Sdim bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); } 349314564Sdim bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); } 350314564Sdim bool isAttrChan() const { return isImmTy(ImmTyAttrChan); } 351321369Sdim bool isOpSel() const { return isImmTy(ImmTyOpSel); } 352321369Sdim bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); } 353321369Sdim bool isNegLo() const { return isImmTy(ImmTyNegLo); } 354321369Sdim bool isNegHi() const { return isImmTy(ImmTyNegHi); } 355327952Sdim bool isHigh() const { return isImmTy(ImmTyHigh); } 356314564Sdim 357309124Sdim bool isMod() const { 358309124Sdim return isClampSI() || isOModSI(); 359284677Sdim } 360284677Sdim 361284677Sdim bool isRegOrImm() const { 362284677Sdim return isReg() || isImm(); 363284677Sdim } 364284677Sdim 365314564Sdim bool isRegClass(unsigned RCID) const; 366314564Sdim 367353358Sdim bool isInlineValue() const; 368353358Sdim 369314564Sdim bool isRegOrInlineNoMods(unsigned RCID, MVT type) const { 370314564Sdim return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers(); 371284677Sdim } 372284677Sdim 373314564Sdim bool isSCSrcB16() const { 374314564Sdim return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16); 375284677Sdim } 376284677Sdim 377321369Sdim bool isSCSrcV2B16() const { 378321369Sdim return isSCSrcB16(); 379321369Sdim } 380321369Sdim 381314564Sdim bool isSCSrcB32() const { 382314564Sdim return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32); 383309124Sdim } 384309124Sdim 385314564Sdim bool isSCSrcB64() const { 386314564Sdim return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64); 387284677Sdim } 388284677Sdim 389353358Sdim bool isBoolReg() const; 390353358Sdim 391314564Sdim bool isSCSrcF16() const { 392314564Sdim return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16); 393314564Sdim } 394314564Sdim 395321369Sdim bool isSCSrcV2F16() const { 396321369Sdim return isSCSrcF16(); 397321369Sdim } 398321369Sdim 399314564Sdim bool isSCSrcF32() const { 400314564Sdim return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32); 401314564Sdim } 402314564Sdim 403314564Sdim bool isSCSrcF64() const { 404314564Sdim return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64); 405314564Sdim } 406314564Sdim 407314564Sdim bool isSSrcB32() const { 408314564Sdim return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr(); 409314564Sdim } 410314564Sdim 411314564Sdim bool isSSrcB16() const { 412314564Sdim return isSCSrcB16() || isLiteralImm(MVT::i16); 413314564Sdim } 414314564Sdim 415321369Sdim bool isSSrcV2B16() const { 416321369Sdim llvm_unreachable("cannot happen"); 417321369Sdim return isSSrcB16(); 418321369Sdim } 419321369Sdim 420314564Sdim bool isSSrcB64() const { 421309124Sdim // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits. 422309124Sdim // See isVSrc64(). 423314564Sdim return isSCSrcB64() || isLiteralImm(MVT::i64); 424284677Sdim } 425284677Sdim 426314564Sdim bool isSSrcF32() const { 427314564Sdim return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr(); 428284677Sdim } 429284677Sdim 430314564Sdim bool isSSrcF64() const { 431314564Sdim return isSCSrcB64() || isLiteralImm(MVT::f64); 432284677Sdim } 433284677Sdim 434314564Sdim bool isSSrcF16() const { 435314564Sdim return isSCSrcB16() || isLiteralImm(MVT::f16); 436284677Sdim } 437284677Sdim 438321369Sdim bool isSSrcV2F16() const { 439321369Sdim llvm_unreachable("cannot happen"); 440321369Sdim return isSSrcF16(); 441321369Sdim } 442321369Sdim 443353358Sdim bool isSSrcOrLdsB32() const { 444353358Sdim return isRegOrInlineNoMods(AMDGPU::SRegOrLds_32RegClassID, MVT::i32) || 445353358Sdim isLiteralImm(MVT::i32) || isExpr(); 446353358Sdim } 447353358Sdim 448314564Sdim bool isVCSrcB32() const { 449314564Sdim return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32); 450284677Sdim } 451284677Sdim 452314564Sdim bool isVCSrcB64() const { 453314564Sdim return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64); 454314564Sdim } 455314564Sdim 456314564Sdim bool isVCSrcB16() const { 457314564Sdim return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16); 458314564Sdim } 459314564Sdim 460321369Sdim bool isVCSrcV2B16() const { 461321369Sdim return isVCSrcB16(); 462321369Sdim } 463321369Sdim 464314564Sdim bool isVCSrcF32() const { 465314564Sdim return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32); 466314564Sdim } 467314564Sdim 468314564Sdim bool isVCSrcF64() const { 469314564Sdim return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64); 470314564Sdim } 471314564Sdim 472314564Sdim bool isVCSrcF16() const { 473314564Sdim return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16); 474314564Sdim } 475314564Sdim 476321369Sdim bool isVCSrcV2F16() const { 477321369Sdim return isVCSrcF16(); 478321369Sdim } 479321369Sdim 480314564Sdim bool isVSrcB32() const { 481341825Sdim return isVCSrcF32() || isLiteralImm(MVT::i32) || isExpr(); 482314564Sdim } 483314564Sdim 484314564Sdim bool isVSrcB64() const { 485314564Sdim return isVCSrcF64() || isLiteralImm(MVT::i64); 486314564Sdim } 487314564Sdim 488314564Sdim bool isVSrcB16() const { 489314564Sdim return isVCSrcF16() || isLiteralImm(MVT::i16); 490314564Sdim } 491314564Sdim 492321369Sdim bool isVSrcV2B16() const { 493353358Sdim return isVSrcB16() || isLiteralImm(MVT::v2i16); 494321369Sdim } 495321369Sdim 496314564Sdim bool isVSrcF32() const { 497341825Sdim return isVCSrcF32() || isLiteralImm(MVT::f32) || isExpr(); 498314564Sdim } 499314564Sdim 500314564Sdim bool isVSrcF64() const { 501314564Sdim return isVCSrcF64() || isLiteralImm(MVT::f64); 502314564Sdim } 503314564Sdim 504314564Sdim bool isVSrcF16() const { 505314564Sdim return isVCSrcF16() || isLiteralImm(MVT::f16); 506314564Sdim } 507314564Sdim 508321369Sdim bool isVSrcV2F16() const { 509353358Sdim return isVSrcF16() || isLiteralImm(MVT::v2f16); 510321369Sdim } 511321369Sdim 512353358Sdim bool isVISrcB32() const { 513353358Sdim return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i32); 514353358Sdim } 515353358Sdim 516353358Sdim bool isVISrcB16() const { 517353358Sdim return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i16); 518353358Sdim } 519353358Sdim 520353358Sdim bool isVISrcV2B16() const { 521353358Sdim return isVISrcB16(); 522353358Sdim } 523353358Sdim 524353358Sdim bool isVISrcF32() const { 525353358Sdim return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f32); 526353358Sdim } 527353358Sdim 528353358Sdim bool isVISrcF16() const { 529353358Sdim return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f16); 530353358Sdim } 531353358Sdim 532353358Sdim bool isVISrcV2F16() const { 533353358Sdim return isVISrcF16() || isVISrcB32(); 534353358Sdim } 535353358Sdim 536353358Sdim bool isAISrcB32() const { 537353358Sdim return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i32); 538353358Sdim } 539353358Sdim 540353358Sdim bool isAISrcB16() const { 541353358Sdim return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i16); 542353358Sdim } 543353358Sdim 544353358Sdim bool isAISrcV2B16() const { 545353358Sdim return isAISrcB16(); 546353358Sdim } 547353358Sdim 548353358Sdim bool isAISrcF32() const { 549353358Sdim return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f32); 550353358Sdim } 551353358Sdim 552353358Sdim bool isAISrcF16() const { 553353358Sdim return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f16); 554353358Sdim } 555353358Sdim 556353358Sdim bool isAISrcV2F16() const { 557353358Sdim return isAISrcF16() || isAISrcB32(); 558353358Sdim } 559353358Sdim 560353358Sdim bool isAISrc_128B32() const { 561353358Sdim return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i32); 562353358Sdim } 563353358Sdim 564353358Sdim bool isAISrc_128B16() const { 565353358Sdim return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i16); 566353358Sdim } 567353358Sdim 568353358Sdim bool isAISrc_128V2B16() const { 569353358Sdim return isAISrc_128B16(); 570353358Sdim } 571353358Sdim 572353358Sdim bool isAISrc_128F32() const { 573353358Sdim return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f32); 574353358Sdim } 575353358Sdim 576353358Sdim bool isAISrc_128F16() const { 577353358Sdim return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f16); 578353358Sdim } 579353358Sdim 580353358Sdim bool isAISrc_128V2F16() const { 581353358Sdim return isAISrc_128F16() || isAISrc_128B32(); 582353358Sdim } 583353358Sdim 584353358Sdim bool isAISrc_512B32() const { 585353358Sdim return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i32); 586353358Sdim } 587353358Sdim 588353358Sdim bool isAISrc_512B16() const { 589353358Sdim return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i16); 590353358Sdim } 591353358Sdim 592353358Sdim bool isAISrc_512V2B16() const { 593353358Sdim return isAISrc_512B16(); 594353358Sdim } 595353358Sdim 596353358Sdim bool isAISrc_512F32() const { 597353358Sdim return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f32); 598353358Sdim } 599353358Sdim 600353358Sdim bool isAISrc_512F16() const { 601353358Sdim return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f16); 602353358Sdim } 603353358Sdim 604353358Sdim bool isAISrc_512V2F16() const { 605353358Sdim return isAISrc_512F16() || isAISrc_512B32(); 606353358Sdim } 607353358Sdim 608353358Sdim bool isAISrc_1024B32() const { 609353358Sdim return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i32); 610353358Sdim } 611353358Sdim 612353358Sdim bool isAISrc_1024B16() const { 613353358Sdim return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i16); 614353358Sdim } 615353358Sdim 616353358Sdim bool isAISrc_1024V2B16() const { 617353358Sdim return isAISrc_1024B16(); 618353358Sdim } 619353358Sdim 620353358Sdim bool isAISrc_1024F32() const { 621353358Sdim return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f32); 622353358Sdim } 623353358Sdim 624353358Sdim bool isAISrc_1024F16() const { 625353358Sdim return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f16); 626353358Sdim } 627353358Sdim 628353358Sdim bool isAISrc_1024V2F16() const { 629353358Sdim return isAISrc_1024F16() || isAISrc_1024B32(); 630353358Sdim } 631353358Sdim 632314564Sdim bool isKImmFP32() const { 633314564Sdim return isLiteralImm(MVT::f32); 634314564Sdim } 635314564Sdim 636314564Sdim bool isKImmFP16() const { 637314564Sdim return isLiteralImm(MVT::f16); 638314564Sdim } 639314564Sdim 640284677Sdim bool isMem() const override { 641284677Sdim return false; 642284677Sdim } 643284677Sdim 644284677Sdim bool isExpr() const { 645284677Sdim return Kind == Expression; 646284677Sdim } 647284677Sdim 648284677Sdim bool isSoppBrTarget() const { 649284677Sdim return isExpr() || isImm(); 650284677Sdim } 651284677Sdim 652309124Sdim bool isSWaitCnt() const; 653309124Sdim bool isHwreg() const; 654309124Sdim bool isSendMsg() const; 655321369Sdim bool isSwizzle() const; 656314564Sdim bool isSMRDOffset8() const; 657314564Sdim bool isSMRDOffset20() const; 658309124Sdim bool isSMRDLiteralOffset() const; 659353358Sdim bool isDPP8() const; 660309124Sdim bool isDPPCtrl() const; 661353358Sdim bool isBLGP() const; 662353358Sdim bool isCBSZ() const; 663353358Sdim bool isABID() const; 664314564Sdim bool isGPRIdxMode() const; 665321369Sdim bool isS16Imm() const; 666321369Sdim bool isU16Imm() const; 667353358Sdim bool isEndpgm() const; 668309124Sdim 669309124Sdim StringRef getExpressionAsToken() const { 670309124Sdim assert(isExpr()); 671309124Sdim const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr); 672309124Sdim return S->getSymbol().getName(); 673309124Sdim } 674309124Sdim 675309124Sdim StringRef getToken() const { 676309124Sdim assert(isToken()); 677309124Sdim 678309124Sdim if (Kind == Expression) 679309124Sdim return getExpressionAsToken(); 680309124Sdim 681309124Sdim return StringRef(Tok.Data, Tok.Length); 682309124Sdim } 683309124Sdim 684309124Sdim int64_t getImm() const { 685309124Sdim assert(isImm()); 686309124Sdim return Imm.Val; 687309124Sdim } 688309124Sdim 689321369Sdim ImmTy getImmTy() const { 690309124Sdim assert(isImm()); 691309124Sdim return Imm.Type; 692309124Sdim } 693309124Sdim 694309124Sdim unsigned getReg() const override { 695353358Sdim assert(isRegKind()); 696309124Sdim return Reg.RegNo; 697309124Sdim } 698309124Sdim 699284677Sdim SMLoc getStartLoc() const override { 700284677Sdim return StartLoc; 701284677Sdim } 702284677Sdim 703284677Sdim SMLoc getEndLoc() const override { 704284677Sdim return EndLoc; 705284677Sdim } 706284677Sdim 707327952Sdim SMRange getLocRange() const { 708327952Sdim return SMRange(StartLoc, EndLoc); 709327952Sdim } 710327952Sdim 711309124Sdim Modifiers getModifiers() const { 712309124Sdim assert(isRegKind() || isImmTy(ImmTyNone)); 713309124Sdim return isRegKind() ? Reg.Mods : Imm.Mods; 714309124Sdim } 715309124Sdim 716309124Sdim void setModifiers(Modifiers Mods) { 717309124Sdim assert(isRegKind() || isImmTy(ImmTyNone)); 718309124Sdim if (isRegKind()) 719309124Sdim Reg.Mods = Mods; 720309124Sdim else 721309124Sdim Imm.Mods = Mods; 722309124Sdim } 723309124Sdim 724309124Sdim bool hasModifiers() const { 725309124Sdim return getModifiers().hasModifiers(); 726309124Sdim } 727314564Sdim 728309124Sdim bool hasFPModifiers() const { 729309124Sdim return getModifiers().hasFPModifiers(); 730309124Sdim } 731309124Sdim 732309124Sdim bool hasIntModifiers() const { 733309124Sdim return getModifiers().hasIntModifiers(); 734309124Sdim } 735309124Sdim 736321369Sdim uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const; 737321369Sdim 738314564Sdim void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const; 739314564Sdim 740321369Sdim void addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const; 741314564Sdim 742314564Sdim template <unsigned Bitwidth> 743314564Sdim void addKImmFPOperands(MCInst &Inst, unsigned N) const; 744314564Sdim 745314564Sdim void addKImmFP16Operands(MCInst &Inst, unsigned N) const { 746314564Sdim addKImmFPOperands<16>(Inst, N); 747309124Sdim } 748309124Sdim 749314564Sdim void addKImmFP32Operands(MCInst &Inst, unsigned N) const { 750314564Sdim addKImmFPOperands<32>(Inst, N); 751309124Sdim } 752309124Sdim 753314564Sdim void addRegOperands(MCInst &Inst, unsigned N) const; 754314564Sdim 755353358Sdim void addBoolRegOperands(MCInst &Inst, unsigned N) const { 756353358Sdim addRegOperands(Inst, N); 757353358Sdim } 758353358Sdim 759309124Sdim void addRegOrImmOperands(MCInst &Inst, unsigned N) const { 760309124Sdim if (isRegKind()) 761309124Sdim addRegOperands(Inst, N); 762309124Sdim else if (isExpr()) 763309124Sdim Inst.addOperand(MCOperand::createExpr(Expr)); 764309124Sdim else 765309124Sdim addImmOperands(Inst, N); 766309124Sdim } 767309124Sdim 768309124Sdim void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const { 769309124Sdim Modifiers Mods = getModifiers(); 770309124Sdim Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand())); 771309124Sdim if (isRegKind()) { 772309124Sdim addRegOperands(Inst, N); 773309124Sdim } else { 774309124Sdim addImmOperands(Inst, N, false); 775309124Sdim } 776309124Sdim } 777309124Sdim 778309124Sdim void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const { 779309124Sdim assert(!hasIntModifiers()); 780309124Sdim addRegOrImmWithInputModsOperands(Inst, N); 781309124Sdim } 782309124Sdim 783309124Sdim void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const { 784309124Sdim assert(!hasFPModifiers()); 785309124Sdim addRegOrImmWithInputModsOperands(Inst, N); 786309124Sdim } 787309124Sdim 788314564Sdim void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const { 789314564Sdim Modifiers Mods = getModifiers(); 790314564Sdim Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand())); 791314564Sdim assert(isRegKind()); 792314564Sdim addRegOperands(Inst, N); 793314564Sdim } 794314564Sdim 795314564Sdim void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const { 796314564Sdim assert(!hasIntModifiers()); 797314564Sdim addRegWithInputModsOperands(Inst, N); 798314564Sdim } 799314564Sdim 800314564Sdim void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const { 801314564Sdim assert(!hasFPModifiers()); 802314564Sdim addRegWithInputModsOperands(Inst, N); 803314564Sdim } 804314564Sdim 805309124Sdim void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const { 806309124Sdim if (isImm()) 807309124Sdim addImmOperands(Inst, N); 808309124Sdim else { 809309124Sdim assert(isExpr()); 810309124Sdim Inst.addOperand(MCOperand::createExpr(Expr)); 811309124Sdim } 812309124Sdim } 813309124Sdim 814314564Sdim static void printImmTy(raw_ostream& OS, ImmTy Type) { 815309124Sdim switch (Type) { 816309124Sdim case ImmTyNone: OS << "None"; break; 817309124Sdim case ImmTyGDS: OS << "GDS"; break; 818341825Sdim case ImmTyLDS: OS << "LDS"; break; 819309124Sdim case ImmTyOffen: OS << "Offen"; break; 820309124Sdim case ImmTyIdxen: OS << "Idxen"; break; 821309124Sdim case ImmTyAddr64: OS << "Addr64"; break; 822309124Sdim case ImmTyOffset: OS << "Offset"; break; 823327952Sdim case ImmTyInstOffset: OS << "InstOffset"; break; 824309124Sdim case ImmTyOffset0: OS << "Offset0"; break; 825309124Sdim case ImmTyOffset1: OS << "Offset1"; break; 826353358Sdim case ImmTyDLC: OS << "DLC"; break; 827309124Sdim case ImmTyGLC: OS << "GLC"; break; 828309124Sdim case ImmTySLC: OS << "SLC"; break; 829360784Sdim case ImmTySWZ: OS << "SWZ"; break; 830309124Sdim case ImmTyTFE: OS << "TFE"; break; 831341825Sdim case ImmTyD16: OS << "D16"; break; 832344779Sdim case ImmTyFORMAT: OS << "FORMAT"; break; 833309124Sdim case ImmTyClampSI: OS << "ClampSI"; break; 834309124Sdim case ImmTyOModSI: OS << "OModSI"; break; 835353358Sdim case ImmTyDPP8: OS << "DPP8"; break; 836309124Sdim case ImmTyDppCtrl: OS << "DppCtrl"; break; 837309124Sdim case ImmTyDppRowMask: OS << "DppRowMask"; break; 838309124Sdim case ImmTyDppBankMask: OS << "DppBankMask"; break; 839309124Sdim case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break; 840353358Sdim case ImmTyDppFi: OS << "FI"; break; 841309124Sdim case ImmTySdwaDstSel: OS << "SdwaDstSel"; break; 842309124Sdim case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break; 843309124Sdim case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break; 844309124Sdim case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break; 845309124Sdim case ImmTyDMask: OS << "DMask"; break; 846353358Sdim case ImmTyDim: OS << "Dim"; break; 847309124Sdim case ImmTyUNorm: OS << "UNorm"; break; 848309124Sdim case ImmTyDA: OS << "DA"; break; 849344779Sdim case ImmTyR128A16: OS << "R128A16"; break; 850309124Sdim case ImmTyLWE: OS << "LWE"; break; 851314564Sdim case ImmTyOff: OS << "Off"; break; 852314564Sdim case ImmTyExpTgt: OS << "ExpTgt"; break; 853314564Sdim case ImmTyExpCompr: OS << "ExpCompr"; break; 854314564Sdim case ImmTyExpVM: OS << "ExpVM"; break; 855309124Sdim case ImmTyHwreg: OS << "Hwreg"; break; 856309124Sdim case ImmTySendMsg: OS << "SendMsg"; break; 857314564Sdim case ImmTyInterpSlot: OS << "InterpSlot"; break; 858314564Sdim case ImmTyInterpAttr: OS << "InterpAttr"; break; 859314564Sdim case ImmTyAttrChan: OS << "AttrChan"; break; 860321369Sdim case ImmTyOpSel: OS << "OpSel"; break; 861321369Sdim case ImmTyOpSelHi: OS << "OpSelHi"; break; 862321369Sdim case ImmTyNegLo: OS << "NegLo"; break; 863321369Sdim case ImmTyNegHi: OS << "NegHi"; break; 864321369Sdim case ImmTySwizzle: OS << "Swizzle"; break; 865353358Sdim case ImmTyGprIdxMode: OS << "GprIdxMode"; break; 866327952Sdim case ImmTyHigh: OS << "High"; break; 867353358Sdim case ImmTyBLGP: OS << "BLGP"; break; 868353358Sdim case ImmTyCBSZ: OS << "CBSZ"; break; 869353358Sdim case ImmTyABID: OS << "ABID"; break; 870353358Sdim case ImmTyEndpgm: OS << "Endpgm"; break; 871309124Sdim } 872309124Sdim } 873309124Sdim 874296417Sdim void print(raw_ostream &OS) const override { 875296417Sdim switch (Kind) { 876296417Sdim case Register: 877309124Sdim OS << "<register " << getReg() << " mods: " << Reg.Mods << '>'; 878296417Sdim break; 879296417Sdim case Immediate: 880309124Sdim OS << '<' << getImm(); 881309124Sdim if (getImmTy() != ImmTyNone) { 882309124Sdim OS << " type: "; printImmTy(OS, getImmTy()); 883309124Sdim } 884309124Sdim OS << " mods: " << Imm.Mods << '>'; 885296417Sdim break; 886296417Sdim case Token: 887296417Sdim OS << '\'' << getToken() << '\''; 888296417Sdim break; 889296417Sdim case Expression: 890296417Sdim OS << "<expr " << *Expr << '>'; 891296417Sdim break; 892296417Sdim } 893296417Sdim } 894284677Sdim 895314564Sdim static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser, 896314564Sdim int64_t Val, SMLoc Loc, 897321369Sdim ImmTy Type = ImmTyNone, 898309124Sdim bool IsFPImm = false) { 899360784Sdim auto Op = std::make_unique<AMDGPUOperand>(Immediate, AsmParser); 900284677Sdim Op->Imm.Val = Val; 901284677Sdim Op->Imm.IsFPImm = IsFPImm; 902284677Sdim Op->Imm.Type = Type; 903314564Sdim Op->Imm.Mods = Modifiers(); 904284677Sdim Op->StartLoc = Loc; 905284677Sdim Op->EndLoc = Loc; 906284677Sdim return Op; 907284677Sdim } 908284677Sdim 909314564Sdim static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser, 910314564Sdim StringRef Str, SMLoc Loc, 911309124Sdim bool HasExplicitEncodingSize = true) { 912360784Sdim auto Res = std::make_unique<AMDGPUOperand>(Token, AsmParser); 913284677Sdim Res->Tok.Data = Str.data(); 914284677Sdim Res->Tok.Length = Str.size(); 915284677Sdim Res->StartLoc = Loc; 916284677Sdim Res->EndLoc = Loc; 917284677Sdim return Res; 918284677Sdim } 919284677Sdim 920314564Sdim static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser, 921314564Sdim unsigned RegNo, SMLoc S, 922353358Sdim SMLoc E) { 923360784Sdim auto Op = std::make_unique<AMDGPUOperand>(Register, AsmParser); 924284677Sdim Op->Reg.RegNo = RegNo; 925314564Sdim Op->Reg.Mods = Modifiers(); 926284677Sdim Op->StartLoc = S; 927284677Sdim Op->EndLoc = E; 928284677Sdim return Op; 929284677Sdim } 930284677Sdim 931314564Sdim static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser, 932314564Sdim const class MCExpr *Expr, SMLoc S) { 933360784Sdim auto Op = std::make_unique<AMDGPUOperand>(Expression, AsmParser); 934284677Sdim Op->Expr = Expr; 935284677Sdim Op->StartLoc = S; 936284677Sdim Op->EndLoc = S; 937284677Sdim return Op; 938284677Sdim } 939284677Sdim}; 940284677Sdim 941309124Sdimraw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) { 942309124Sdim OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext; 943309124Sdim return OS; 944309124Sdim} 945309124Sdim 946314564Sdim//===----------------------------------------------------------------------===// 947314564Sdim// AsmParser 948314564Sdim//===----------------------------------------------------------------------===// 949314564Sdim 950314564Sdim// Holds info related to the current kernel, e.g. count of SGPRs used. 951314564Sdim// Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next 952314564Sdim// .amdgpu_hsa_kernel or at EOF. 953314564Sdimclass KernelScopeInfo { 954321369Sdim int SgprIndexUnusedMin = -1; 955321369Sdim int VgprIndexUnusedMin = -1; 956321369Sdim MCContext *Ctx = nullptr; 957314564Sdim 958314564Sdim void usesSgprAt(int i) { 959314564Sdim if (i >= SgprIndexUnusedMin) { 960314564Sdim SgprIndexUnusedMin = ++i; 961314564Sdim if (Ctx) { 962314564Sdim MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count")); 963314564Sdim Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx)); 964314564Sdim } 965314564Sdim } 966314564Sdim } 967321369Sdim 968314564Sdim void usesVgprAt(int i) { 969314564Sdim if (i >= VgprIndexUnusedMin) { 970314564Sdim VgprIndexUnusedMin = ++i; 971314564Sdim if (Ctx) { 972314564Sdim MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count")); 973314564Sdim Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx)); 974314564Sdim } 975314564Sdim } 976314564Sdim } 977321369Sdim 978314564Sdimpublic: 979321369Sdim KernelScopeInfo() = default; 980321369Sdim 981314564Sdim void initialize(MCContext &Context) { 982314564Sdim Ctx = &Context; 983314564Sdim usesSgprAt(SgprIndexUnusedMin = -1); 984314564Sdim usesVgprAt(VgprIndexUnusedMin = -1); 985314564Sdim } 986321369Sdim 987314564Sdim void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) { 988314564Sdim switch (RegKind) { 989314564Sdim case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break; 990353358Sdim case IS_AGPR: // fall through 991314564Sdim case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break; 992314564Sdim default: break; 993314564Sdim } 994314564Sdim } 995314564Sdim}; 996314564Sdim 997284677Sdimclass AMDGPUAsmParser : public MCTargetAsmParser { 998284677Sdim MCAsmParser &Parser; 999284677Sdim 1000327952Sdim // Number of extra operands parsed after the first optional operand. 1001327952Sdim // This may be necessary to skip hardcoded mandatory operands. 1002341825Sdim static const unsigned MAX_OPR_LOOKAHEAD = 8; 1003327952Sdim 1004321369Sdim unsigned ForcedEncodingSize = 0; 1005321369Sdim bool ForcedDPP = false; 1006321369Sdim bool ForcedSDWA = false; 1007314564Sdim KernelScopeInfo KernelScope; 1008296417Sdim 1009284677Sdim /// @name Auto-generated Match Functions 1010284677Sdim /// { 1011284677Sdim 1012284677Sdim#define GET_ASSEMBLER_HEADER 1013284677Sdim#include "AMDGPUGenAsmMatcher.inc" 1014284677Sdim 1015284677Sdim /// } 1016284677Sdim 1017285181Sdimprivate: 1018314564Sdim bool ParseAsAbsoluteExpression(uint32_t &Ret); 1019341825Sdim bool OutOfRangeError(SMRange Range); 1020341825Sdim /// Calculate VGPR/SGPR blocks required for given target, reserved 1021341825Sdim /// registers, and user-specified NextFreeXGPR values. 1022341825Sdim /// 1023341825Sdim /// \param Features [in] Target features, used for bug corrections. 1024341825Sdim /// \param VCCUsed [in] Whether VCC special SGPR is reserved. 1025341825Sdim /// \param FlatScrUsed [in] Whether FLAT_SCRATCH special SGPR is reserved. 1026341825Sdim /// \param XNACKUsed [in] Whether XNACK_MASK special SGPR is reserved. 1027353358Sdim /// \param EnableWavefrontSize32 [in] Value of ENABLE_WAVEFRONT_SIZE32 kernel 1028353358Sdim /// descriptor field, if valid. 1029341825Sdim /// \param NextFreeVGPR [in] Max VGPR number referenced, plus one. 1030341825Sdim /// \param VGPRRange [in] Token range, used for VGPR diagnostics. 1031341825Sdim /// \param NextFreeSGPR [in] Max SGPR number referenced, plus one. 1032341825Sdim /// \param SGPRRange [in] Token range, used for SGPR diagnostics. 1033341825Sdim /// \param VGPRBlocks [out] Result VGPR block count. 1034341825Sdim /// \param SGPRBlocks [out] Result SGPR block count. 1035341825Sdim bool calculateGPRBlocks(const FeatureBitset &Features, bool VCCUsed, 1036341825Sdim bool FlatScrUsed, bool XNACKUsed, 1037353358Sdim Optional<bool> EnableWavefrontSize32, unsigned NextFreeVGPR, 1038353358Sdim SMRange VGPRRange, unsigned NextFreeSGPR, 1039353358Sdim SMRange SGPRRange, unsigned &VGPRBlocks, 1040353358Sdim unsigned &SGPRBlocks); 1041341825Sdim bool ParseDirectiveAMDGCNTarget(); 1042341825Sdim bool ParseDirectiveAMDHSAKernel(); 1043285181Sdim bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor); 1044285181Sdim bool ParseDirectiveHSACodeObjectVersion(); 1045285181Sdim bool ParseDirectiveHSACodeObjectISA(); 1046285181Sdim bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header); 1047285181Sdim bool ParseDirectiveAMDKernelCodeT(); 1048296417Sdim bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const; 1049296417Sdim bool ParseDirectiveAMDGPUHsaKernel(); 1050327952Sdim 1051327952Sdim bool ParseDirectiveISAVersion(); 1052327952Sdim bool ParseDirectiveHSAMetadata(); 1053353358Sdim bool ParseDirectivePALMetadataBegin(); 1054327952Sdim bool ParseDirectivePALMetadata(); 1055353358Sdim bool ParseDirectiveAMDGPULDS(); 1056327952Sdim 1057353358Sdim /// Common code to parse out a block of text (typically YAML) between start and 1058353358Sdim /// end directives. 1059353358Sdim bool ParseToEndDirective(const char *AssemblerDirectiveBegin, 1060353358Sdim const char *AssemblerDirectiveEnd, 1061353358Sdim std::string &CollectString); 1062353358Sdim 1063321369Sdim bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, 1064360784Sdim RegisterKind RegKind, unsigned Reg1); 1065321369Sdim bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, 1066360784Sdim unsigned& RegNum, unsigned& RegWidth); 1067360784Sdim unsigned ParseRegularReg(RegisterKind &RegKind, 1068360784Sdim unsigned &RegNum, 1069360784Sdim unsigned &RegWidth); 1070360784Sdim unsigned ParseSpecialReg(RegisterKind &RegKind, 1071360784Sdim unsigned &RegNum, 1072360784Sdim unsigned &RegWidth); 1073360784Sdim unsigned ParseRegList(RegisterKind &RegKind, 1074360784Sdim unsigned &RegNum, 1075360784Sdim unsigned &RegWidth); 1076360784Sdim bool ParseRegRange(unsigned& Num, unsigned& Width); 1077360784Sdim unsigned getRegularReg(RegisterKind RegKind, 1078360784Sdim unsigned RegNum, 1079360784Sdim unsigned RegWidth); 1080360784Sdim 1081353358Sdim bool isRegister(); 1082353358Sdim bool isRegister(const AsmToken &Token, const AsmToken &NextToken) const; 1083341825Sdim Optional<StringRef> getGprCountSymbolName(RegisterKind RegKind); 1084341825Sdim void initializeGprCountSymbol(RegisterKind RegKind); 1085341825Sdim bool updateGprCountSymbols(RegisterKind RegKind, unsigned DwordRegIndex, 1086341825Sdim unsigned RegWidth); 1087321369Sdim void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands, 1088341825Sdim bool IsAtomic, bool IsAtomicReturn, bool IsLds = false); 1089321369Sdim void cvtDSImpl(MCInst &Inst, const OperandVector &Operands, 1090321369Sdim bool IsGdsHardcoded); 1091285181Sdim 1092284677Sdimpublic: 1093296417Sdim enum AMDGPUMatchResultTy { 1094296417Sdim Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY 1095296417Sdim }; 1096353358Sdim enum OperandMode { 1097353358Sdim OperandMode_Default, 1098353358Sdim OperandMode_NSA, 1099353358Sdim }; 1100296417Sdim 1101327952Sdim using OptionalImmIndexMap = std::map<AMDGPUOperand::ImmTy, unsigned>; 1102321369Sdim 1103296417Sdim AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser, 1104284677Sdim const MCInstrInfo &MII, 1105284677Sdim const MCTargetOptions &Options) 1106327952Sdim : MCTargetAsmParser(Options, STI, MII), Parser(_Parser) { 1107296417Sdim MCAsmParserExtension::Initialize(Parser); 1108284677Sdim 1109321369Sdim if (getFeatureBits().none()) { 1110284677Sdim // Set default features. 1111353358Sdim copySTI().ToggleFeature("southern-islands"); 1112284677Sdim } 1113284677Sdim 1114321369Sdim setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits())); 1115309124Sdim 1116309124Sdim { 1117309124Sdim // TODO: make those pre-defined variables read-only. 1118309124Sdim // Currently there is none suitable machinery in the core llvm-mc for this. 1119309124Sdim // MCSymbol::isRedefinable is intended for another purpose, and 1120309124Sdim // AsmParser::parseDirectiveSet() cannot be specialized for specific target. 1121344779Sdim AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU()); 1122309124Sdim MCContext &Ctx = getContext(); 1123341825Sdim if (ISA.Major >= 6 && AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) { 1124341825Sdim MCSymbol *Sym = 1125341825Sdim Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_number")); 1126341825Sdim Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx)); 1127353358Sdim Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_minor")); 1128353358Sdim Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx)); 1129353358Sdim Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_stepping")); 1130353358Sdim Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx)); 1131341825Sdim } else { 1132341825Sdim MCSymbol *Sym = 1133341825Sdim Ctx.getOrCreateSymbol(Twine(".option.machine_version_major")); 1134341825Sdim Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx)); 1135341825Sdim Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor")); 1136341825Sdim Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx)); 1137341825Sdim Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping")); 1138341825Sdim Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx)); 1139341825Sdim } 1140341825Sdim if (ISA.Major >= 6 && AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) { 1141341825Sdim initializeGprCountSymbol(IS_VGPR); 1142341825Sdim initializeGprCountSymbol(IS_SGPR); 1143341825Sdim } else 1144341825Sdim KernelScope.initialize(getContext()); 1145309124Sdim } 1146284677Sdim } 1147284677Sdim 1148341825Sdim bool hasXNACK() const { 1149341825Sdim return AMDGPU::hasXNACK(getSTI()); 1150341825Sdim } 1151341825Sdim 1152341825Sdim bool hasMIMG_R128() const { 1153341825Sdim return AMDGPU::hasMIMG_R128(getSTI()); 1154341825Sdim } 1155341825Sdim 1156341825Sdim bool hasPackedD16() const { 1157341825Sdim return AMDGPU::hasPackedD16(getSTI()); 1158341825Sdim } 1159341825Sdim 1160314564Sdim bool isSI() const { 1161314564Sdim return AMDGPU::isSI(getSTI()); 1162314564Sdim } 1163314564Sdim 1164314564Sdim bool isCI() const { 1165314564Sdim return AMDGPU::isCI(getSTI()); 1166314564Sdim } 1167314564Sdim 1168314564Sdim bool isVI() const { 1169314564Sdim return AMDGPU::isVI(getSTI()); 1170314564Sdim } 1171314564Sdim 1172321369Sdim bool isGFX9() const { 1173321369Sdim return AMDGPU::isGFX9(getSTI()); 1174321369Sdim } 1175321369Sdim 1176353358Sdim bool isGFX10() const { 1177353358Sdim return AMDGPU::isGFX10(getSTI()); 1178353358Sdim } 1179353358Sdim 1180314564Sdim bool hasInv2PiInlineImm() const { 1181321369Sdim return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm]; 1182314564Sdim } 1183314564Sdim 1184321369Sdim bool hasFlatOffsets() const { 1185321369Sdim return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets]; 1186321369Sdim } 1187321369Sdim 1188314564Sdim bool hasSGPR102_SGPR103() const { 1189353358Sdim return !isVI() && !isGFX9(); 1190314564Sdim } 1191314564Sdim 1192353358Sdim bool hasSGPR104_SGPR105() const { 1193353358Sdim return isGFX10(); 1194353358Sdim } 1195353358Sdim 1196327952Sdim bool hasIntClamp() const { 1197327952Sdim return getFeatureBits()[AMDGPU::FeatureIntClamp]; 1198327952Sdim } 1199327952Sdim 1200285181Sdim AMDGPUTargetStreamer &getTargetStreamer() { 1201285181Sdim MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); 1202285181Sdim return static_cast<AMDGPUTargetStreamer &>(TS); 1203285181Sdim } 1204285181Sdim 1205314564Sdim const MCRegisterInfo *getMRI() const { 1206314564Sdim // We need this const_cast because for some reason getContext() is not const 1207314564Sdim // in MCAsmParser. 1208314564Sdim return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo(); 1209314564Sdim } 1210314564Sdim 1211314564Sdim const MCInstrInfo *getMII() const { 1212314564Sdim return &MII; 1213314564Sdim } 1214314564Sdim 1215321369Sdim const FeatureBitset &getFeatureBits() const { 1216321369Sdim return getSTI().getFeatureBits(); 1217321369Sdim } 1218321369Sdim 1219309124Sdim void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; } 1220309124Sdim void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; } 1221309124Sdim void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; } 1222284677Sdim 1223309124Sdim unsigned getForcedEncodingSize() const { return ForcedEncodingSize; } 1224309124Sdim bool isForcedVOP3() const { return ForcedEncodingSize == 64; } 1225309124Sdim bool isForcedDPP() const { return ForcedDPP; } 1226309124Sdim bool isForcedSDWA() const { return ForcedSDWA; } 1227314564Sdim ArrayRef<unsigned> getMatchedVariants() const; 1228284677Sdim 1229309124Sdim std::unique_ptr<AMDGPUOperand> parseRegister(); 1230284677Sdim bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; 1231284677Sdim unsigned checkTargetMatchPredicate(MCInst &Inst) override; 1232309124Sdim unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 1233309124Sdim unsigned Kind) override; 1234284677Sdim bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 1235284677Sdim OperandVector &Operands, MCStreamer &Out, 1236284677Sdim uint64_t &ErrorInfo, 1237284677Sdim bool MatchingInlineAsm) override; 1238284677Sdim bool ParseDirective(AsmToken DirectiveID) override; 1239353358Sdim OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic, 1240353358Sdim OperandMode Mode = OperandMode_Default); 1241309124Sdim StringRef parseMnemonicSuffix(StringRef Name); 1242284677Sdim bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 1243284677Sdim SMLoc NameLoc, OperandVector &Operands) override; 1244314564Sdim //bool ProcessInstruction(MCInst &Inst); 1245284677Sdim 1246309124Sdim OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int); 1247321369Sdim 1248314564Sdim OperandMatchResultTy 1249314564Sdim parseIntWithPrefix(const char *Prefix, OperandVector &Operands, 1250321369Sdim AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone, 1251314564Sdim bool (*ConvertResult)(int64_t &) = nullptr); 1252321369Sdim 1253353358Sdim OperandMatchResultTy 1254353358Sdim parseOperandArrayWithPrefix(const char *Prefix, 1255353358Sdim OperandVector &Operands, 1256353358Sdim AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone, 1257353358Sdim bool (*ConvertResult)(int64_t&) = nullptr); 1258321369Sdim 1259314564Sdim OperandMatchResultTy 1260314564Sdim parseNamedBit(const char *Name, OperandVector &Operands, 1261321369Sdim AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone); 1262314564Sdim OperandMatchResultTy parseStringWithPrefix(StringRef Prefix, 1263314564Sdim StringRef &Value); 1264284677Sdim 1265353358Sdim bool isModifier(); 1266353358Sdim bool isOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const; 1267353358Sdim bool isRegOrOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const; 1268353358Sdim bool isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const; 1269353358Sdim bool isOpcodeModifierWithVal(const AsmToken &Token, const AsmToken &NextToken) const; 1270353358Sdim bool parseSP3NegModifier(); 1271353358Sdim OperandMatchResultTy parseImm(OperandVector &Operands, bool HasSP3AbsModifier = false); 1272314564Sdim OperandMatchResultTy parseReg(OperandVector &Operands); 1273353358Sdim OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod = false); 1274314564Sdim OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true); 1275314564Sdim OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true); 1276314564Sdim OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands); 1277314564Sdim OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands); 1278314564Sdim OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands); 1279344779Sdim OperandMatchResultTy parseDfmtNfmt(OperandVector &Operands); 1280284677Sdim 1281284677Sdim void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands); 1282321369Sdim void cvtDS(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, false); } 1283321369Sdim void cvtDSGds(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, true); } 1284314564Sdim void cvtExp(MCInst &Inst, const OperandVector &Operands); 1285284677Sdim 1286284677Sdim bool parseCnt(int64_t &IntVal); 1287284677Sdim OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands); 1288309124Sdim OperandMatchResultTy parseHwreg(OperandVector &Operands); 1289309124Sdim 1290309124Sdimprivate: 1291309124Sdim struct OperandInfoTy { 1292309124Sdim int64_t Id; 1293327952Sdim bool IsSymbolic = false; 1294353358Sdim bool IsDefined = false; 1295327952Sdim 1296327952Sdim OperandInfoTy(int64_t Id_) : Id(Id_) {} 1297309124Sdim }; 1298309124Sdim 1299353358Sdim bool parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op, OperandInfoTy &Stream); 1300353358Sdim bool validateSendMsg(const OperandInfoTy &Msg, 1301353358Sdim const OperandInfoTy &Op, 1302353358Sdim const OperandInfoTy &Stream, 1303353358Sdim const SMLoc Loc); 1304314564Sdim 1305353358Sdim bool parseHwregBody(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width); 1306353358Sdim bool validateHwreg(const OperandInfoTy &HwReg, 1307353358Sdim const int64_t Offset, 1308353358Sdim const int64_t Width, 1309353358Sdim const SMLoc Loc); 1310353358Sdim 1311314564Sdim void errorExpTgt(); 1312314564Sdim OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val); 1313353358Sdim SMLoc getFlatOffsetLoc(const OperandVector &Operands) const; 1314314564Sdim 1315353358Sdim bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc, const OperandVector &Operands); 1316353358Sdim bool validateFlatOffset(const MCInst &Inst, const OperandVector &Operands); 1317353358Sdim bool validateSOPLiteral(const MCInst &Inst) const; 1318321369Sdim bool validateConstantBusLimitations(const MCInst &Inst); 1319321369Sdim bool validateEarlyClobberLimitations(const MCInst &Inst); 1320327952Sdim bool validateIntClampSupported(const MCInst &Inst); 1321341825Sdim bool validateMIMGAtomicDMask(const MCInst &Inst); 1322341825Sdim bool validateMIMGGatherDMask(const MCInst &Inst); 1323360784Sdim bool validateMovrels(const MCInst &Inst); 1324341825Sdim bool validateMIMGDataSize(const MCInst &Inst); 1325353358Sdim bool validateMIMGAddrSize(const MCInst &Inst); 1326341825Sdim bool validateMIMGD16(const MCInst &Inst); 1327353358Sdim bool validateMIMGDim(const MCInst &Inst); 1328353358Sdim bool validateLdsDirect(const MCInst &Inst); 1329353358Sdim bool validateOpSel(const MCInst &Inst); 1330353358Sdim bool validateVccOperand(unsigned Reg) const; 1331353358Sdim bool validateVOP3Literal(const MCInst &Inst) const; 1332360784Sdim unsigned getConstantBusLimit(unsigned Opcode) const; 1333321369Sdim bool usesConstantBus(const MCInst &Inst, unsigned OpIdx); 1334321369Sdim bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const; 1335321369Sdim unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const; 1336321369Sdim 1337353358Sdim bool isId(const StringRef Id) const; 1338353358Sdim bool isId(const AsmToken &Token, const StringRef Id) const; 1339353358Sdim bool isToken(const AsmToken::TokenKind Kind) const; 1340321369Sdim bool trySkipId(const StringRef Id); 1341353358Sdim bool trySkipId(const StringRef Id, const AsmToken::TokenKind Kind); 1342321369Sdim bool trySkipToken(const AsmToken::TokenKind Kind); 1343321369Sdim bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg); 1344321369Sdim bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string"); 1345353358Sdim void peekTokens(MutableArrayRef<AsmToken> Tokens); 1346353358Sdim AsmToken::TokenKind getTokenKind() const; 1347321369Sdim bool parseExpr(int64_t &Imm); 1348360784Sdim bool parseExpr(OperandVector &Operands); 1349353358Sdim StringRef getTokenStr() const; 1350353358Sdim AsmToken peekToken(); 1351353358Sdim AsmToken getToken() const; 1352353358Sdim SMLoc getLoc() const; 1353353358Sdim void lex(); 1354321369Sdim 1355309124Sdimpublic: 1356309124Sdim OperandMatchResultTy parseOptionalOperand(OperandVector &Operands); 1357327952Sdim OperandMatchResultTy parseOptionalOpr(OperandVector &Operands); 1358309124Sdim 1359314564Sdim OperandMatchResultTy parseExpTgt(OperandVector &Operands); 1360309124Sdim OperandMatchResultTy parseSendMsgOp(OperandVector &Operands); 1361314564Sdim OperandMatchResultTy parseInterpSlot(OperandVector &Operands); 1362314564Sdim OperandMatchResultTy parseInterpAttr(OperandVector &Operands); 1363284677Sdim OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands); 1364353358Sdim OperandMatchResultTy parseBoolReg(OperandVector &Operands); 1365284677Sdim 1366321369Sdim bool parseSwizzleOperands(const unsigned OpNum, int64_t* Op, 1367321369Sdim const unsigned MinVal, 1368321369Sdim const unsigned MaxVal, 1369321369Sdim const StringRef ErrMsg); 1370321369Sdim OperandMatchResultTy parseSwizzleOp(OperandVector &Operands); 1371321369Sdim bool parseSwizzleOffset(int64_t &Imm); 1372321369Sdim bool parseSwizzleMacro(int64_t &Imm); 1373321369Sdim bool parseSwizzleQuadPerm(int64_t &Imm); 1374321369Sdim bool parseSwizzleBitmaskPerm(int64_t &Imm); 1375321369Sdim bool parseSwizzleBroadcast(int64_t &Imm); 1376321369Sdim bool parseSwizzleSwap(int64_t &Imm); 1377321369Sdim bool parseSwizzleReverse(int64_t &Imm); 1378321369Sdim 1379353358Sdim OperandMatchResultTy parseGPRIdxMode(OperandVector &Operands); 1380353358Sdim int64_t parseGPRIdxMacro(); 1381353358Sdim 1382309124Sdim void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); } 1383309124Sdim void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); } 1384309124Sdim void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); } 1385341825Sdim void cvtMubufLds(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false, true); } 1386321369Sdim void cvtMtbuf(MCInst &Inst, const OperandVector &Operands); 1387321369Sdim 1388353358Sdim AMDGPUOperand::Ptr defaultDLC() const; 1389309124Sdim AMDGPUOperand::Ptr defaultGLC() const; 1390309124Sdim AMDGPUOperand::Ptr defaultSLC() const; 1391284677Sdim 1392314564Sdim AMDGPUOperand::Ptr defaultSMRDOffset8() const; 1393314564Sdim AMDGPUOperand::Ptr defaultSMRDOffset20() const; 1394309124Sdim AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const; 1395353358Sdim AMDGPUOperand::Ptr defaultFlatOffset() const; 1396284677Sdim 1397309124Sdim OperandMatchResultTy parseOModOperand(OperandVector &Operands); 1398284677Sdim 1399321369Sdim void cvtVOP3(MCInst &Inst, const OperandVector &Operands, 1400321369Sdim OptionalImmIndexMap &OptionalIdx); 1401327952Sdim void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands); 1402284677Sdim void cvtVOP3(MCInst &Inst, const OperandVector &Operands); 1403321369Sdim void cvtVOP3P(MCInst &Inst, const OperandVector &Operands); 1404309124Sdim 1405327952Sdim void cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands); 1406327952Sdim 1407321369Sdim void cvtMIMG(MCInst &Inst, const OperandVector &Operands, 1408321369Sdim bool IsAtomic = false); 1409309124Sdim void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands); 1410309124Sdim 1411353358Sdim OperandMatchResultTy parseDim(OperandVector &Operands); 1412353358Sdim OperandMatchResultTy parseDPP8(OperandVector &Operands); 1413309124Sdim OperandMatchResultTy parseDPPCtrl(OperandVector &Operands); 1414309124Sdim AMDGPUOperand::Ptr defaultRowMask() const; 1415309124Sdim AMDGPUOperand::Ptr defaultBankMask() const; 1416309124Sdim AMDGPUOperand::Ptr defaultBoundCtrl() const; 1417353358Sdim AMDGPUOperand::Ptr defaultFI() const; 1418353358Sdim void cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8 = false); 1419353358Sdim void cvtDPP8(MCInst &Inst, const OperandVector &Operands) { cvtDPP(Inst, Operands, true); } 1420309124Sdim 1421309124Sdim OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix, 1422309124Sdim AMDGPUOperand::ImmTy Type); 1423309124Sdim OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands); 1424309124Sdim void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands); 1425309124Sdim void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands); 1426321369Sdim void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands); 1427360784Sdim void cvtSdwaVOP2e(MCInst &Inst, const OperandVector &Operands); 1428309124Sdim void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands); 1429309124Sdim void cvtSDWA(MCInst &Inst, const OperandVector &Operands, 1430360784Sdim uint64_t BasicInstType, 1431360784Sdim bool SkipDstVcc = false, 1432360784Sdim bool SkipSrcVcc = false); 1433353358Sdim 1434353358Sdim AMDGPUOperand::Ptr defaultBLGP() const; 1435353358Sdim AMDGPUOperand::Ptr defaultCBSZ() const; 1436353358Sdim AMDGPUOperand::Ptr defaultABID() const; 1437353358Sdim 1438353358Sdim OperandMatchResultTy parseEndpgmOp(OperandVector &Operands); 1439353358Sdim AMDGPUOperand::Ptr defaultEndpgmImmOperands() const; 1440284677Sdim}; 1441284677Sdim 1442284677Sdimstruct OptionalOperand { 1443284677Sdim const char *Name; 1444284677Sdim AMDGPUOperand::ImmTy Type; 1445284677Sdim bool IsBit; 1446284677Sdim bool (*ConvertResult)(int64_t&); 1447284677Sdim}; 1448284677Sdim 1449314564Sdim} // end anonymous namespace 1450314564Sdim 1451314564Sdim// May be called with integer type with equivalent bitwidth. 1452314564Sdimstatic const fltSemantics *getFltSemantics(unsigned Size) { 1453314564Sdim switch (Size) { 1454314564Sdim case 4: 1455314564Sdim return &APFloat::IEEEsingle(); 1456314564Sdim case 8: 1457314564Sdim return &APFloat::IEEEdouble(); 1458314564Sdim case 2: 1459314564Sdim return &APFloat::IEEEhalf(); 1460314564Sdim default: 1461314564Sdim llvm_unreachable("unsupported fp type"); 1462314564Sdim } 1463285181Sdim} 1464284677Sdim 1465314564Sdimstatic const fltSemantics *getFltSemantics(MVT VT) { 1466314564Sdim return getFltSemantics(VT.getSizeInBits() / 8); 1467314564Sdim} 1468314564Sdim 1469321369Sdimstatic const fltSemantics *getOpFltSemantics(uint8_t OperandType) { 1470321369Sdim switch (OperandType) { 1471321369Sdim case AMDGPU::OPERAND_REG_IMM_INT32: 1472321369Sdim case AMDGPU::OPERAND_REG_IMM_FP32: 1473321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_INT32: 1474321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_FP32: 1475353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_INT32: 1476353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_FP32: 1477321369Sdim return &APFloat::IEEEsingle(); 1478321369Sdim case AMDGPU::OPERAND_REG_IMM_INT64: 1479321369Sdim case AMDGPU::OPERAND_REG_IMM_FP64: 1480321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_INT64: 1481321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_FP64: 1482321369Sdim return &APFloat::IEEEdouble(); 1483321369Sdim case AMDGPU::OPERAND_REG_IMM_INT16: 1484321369Sdim case AMDGPU::OPERAND_REG_IMM_FP16: 1485321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_INT16: 1486321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_FP16: 1487321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_V2INT16: 1488321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: 1489353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_INT16: 1490353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_FP16: 1491353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16: 1492353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: 1493353358Sdim case AMDGPU::OPERAND_REG_IMM_V2INT16: 1494353358Sdim case AMDGPU::OPERAND_REG_IMM_V2FP16: 1495321369Sdim return &APFloat::IEEEhalf(); 1496321369Sdim default: 1497321369Sdim llvm_unreachable("unsupported fp type"); 1498321369Sdim } 1499321369Sdim} 1500321369Sdim 1501314564Sdim//===----------------------------------------------------------------------===// 1502314564Sdim// Operand 1503314564Sdim//===----------------------------------------------------------------------===// 1504314564Sdim 1505314564Sdimstatic bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) { 1506314564Sdim bool Lost; 1507314564Sdim 1508314564Sdim // Convert literal to single precision 1509314564Sdim APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT), 1510314564Sdim APFloat::rmNearestTiesToEven, 1511314564Sdim &Lost); 1512314564Sdim // We allow precision lost but not overflow or underflow 1513314564Sdim if (Status != APFloat::opOK && 1514314564Sdim Lost && 1515314564Sdim ((Status & APFloat::opOverflow) != 0 || 1516314564Sdim (Status & APFloat::opUnderflow) != 0)) { 1517314564Sdim return false; 1518314564Sdim } 1519314564Sdim 1520314564Sdim return true; 1521314564Sdim} 1522314564Sdim 1523353358Sdimstatic bool isSafeTruncation(int64_t Val, unsigned Size) { 1524353358Sdim return isUIntN(Size, Val) || isIntN(Size, Val); 1525353358Sdim} 1526353358Sdim 1527314564Sdimbool AMDGPUOperand::isInlinableImm(MVT type) const { 1528353358Sdim 1529353358Sdim // This is a hack to enable named inline values like 1530353358Sdim // shared_base with both 32-bit and 64-bit operands. 1531353358Sdim // Note that these values are defined as 1532353358Sdim // 32-bit operands only. 1533353358Sdim if (isInlineValue()) { 1534353358Sdim return true; 1535353358Sdim } 1536353358Sdim 1537314564Sdim if (!isImmTy(ImmTyNone)) { 1538314564Sdim // Only plain immediates are inlinable (e.g. "clamp" attribute is not) 1539314564Sdim return false; 1540314564Sdim } 1541314564Sdim // TODO: We should avoid using host float here. It would be better to 1542314564Sdim // check the float bit values which is what a few other places do. 1543314564Sdim // We've had bot failures before due to weird NaN support on mips hosts. 1544314564Sdim 1545314564Sdim APInt Literal(64, Imm.Val); 1546314564Sdim 1547314564Sdim if (Imm.IsFPImm) { // We got fp literal token 1548314564Sdim if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand 1549314564Sdim return AMDGPU::isInlinableLiteral64(Imm.Val, 1550314564Sdim AsmParser->hasInv2PiInlineImm()); 1551314564Sdim } 1552314564Sdim 1553314564Sdim APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val)); 1554314564Sdim if (!canLosslesslyConvertToFPType(FPLiteral, type)) 1555314564Sdim return false; 1556314564Sdim 1557321369Sdim if (type.getScalarSizeInBits() == 16) { 1558321369Sdim return AMDGPU::isInlinableLiteral16( 1559321369Sdim static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()), 1560321369Sdim AsmParser->hasInv2PiInlineImm()); 1561321369Sdim } 1562321369Sdim 1563314564Sdim // Check if single precision literal is inlinable 1564314564Sdim return AMDGPU::isInlinableLiteral32( 1565314564Sdim static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()), 1566314564Sdim AsmParser->hasInv2PiInlineImm()); 1567314564Sdim } 1568314564Sdim 1569314564Sdim // We got int literal token. 1570314564Sdim if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand 1571314564Sdim return AMDGPU::isInlinableLiteral64(Imm.Val, 1572314564Sdim AsmParser->hasInv2PiInlineImm()); 1573314564Sdim } 1574314564Sdim 1575353358Sdim if (!isSafeTruncation(Imm.Val, type.getScalarSizeInBits())) { 1576353358Sdim return false; 1577353358Sdim } 1578353358Sdim 1579314564Sdim if (type.getScalarSizeInBits() == 16) { 1580314564Sdim return AMDGPU::isInlinableLiteral16( 1581314564Sdim static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()), 1582314564Sdim AsmParser->hasInv2PiInlineImm()); 1583314564Sdim } 1584314564Sdim 1585314564Sdim return AMDGPU::isInlinableLiteral32( 1586314564Sdim static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()), 1587314564Sdim AsmParser->hasInv2PiInlineImm()); 1588314564Sdim} 1589314564Sdim 1590314564Sdimbool AMDGPUOperand::isLiteralImm(MVT type) const { 1591321369Sdim // Check that this immediate can be added as literal 1592314564Sdim if (!isImmTy(ImmTyNone)) { 1593314564Sdim return false; 1594314564Sdim } 1595314564Sdim 1596314564Sdim if (!Imm.IsFPImm) { 1597314564Sdim // We got int literal token. 1598314564Sdim 1599321369Sdim if (type == MVT::f64 && hasFPModifiers()) { 1600321369Sdim // Cannot apply fp modifiers to int literals preserving the same semantics 1601321369Sdim // for VOP1/2/C and VOP3 because of integer truncation. To avoid ambiguity, 1602321369Sdim // disable these cases. 1603321369Sdim return false; 1604321369Sdim } 1605321369Sdim 1606314564Sdim unsigned Size = type.getSizeInBits(); 1607314564Sdim if (Size == 64) 1608314564Sdim Size = 32; 1609314564Sdim 1610314564Sdim // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP 1611314564Sdim // types. 1612353358Sdim return isSafeTruncation(Imm.Val, Size); 1613314564Sdim } 1614314564Sdim 1615314564Sdim // We got fp literal token 1616314564Sdim if (type == MVT::f64) { // Expected 64-bit fp operand 1617314564Sdim // We would set low 64-bits of literal to zeroes but we accept this literals 1618314564Sdim return true; 1619314564Sdim } 1620314564Sdim 1621314564Sdim if (type == MVT::i64) { // Expected 64-bit int operand 1622314564Sdim // We don't allow fp literals in 64-bit integer instructions. It is 1623314564Sdim // unclear how we should encode them. 1624314564Sdim return false; 1625314564Sdim } 1626314564Sdim 1627353358Sdim // We allow fp literals with f16x2 operands assuming that the specified 1628353358Sdim // literal goes into the lower half and the upper half is zero. We also 1629353358Sdim // require that the literal may be losslesly converted to f16. 1630353358Sdim MVT ExpectedType = (type == MVT::v2f16)? MVT::f16 : 1631353358Sdim (type == MVT::v2i16)? MVT::i16 : type; 1632353358Sdim 1633314564Sdim APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val)); 1634353358Sdim return canLosslesslyConvertToFPType(FPLiteral, ExpectedType); 1635314564Sdim} 1636314564Sdim 1637314564Sdimbool AMDGPUOperand::isRegClass(unsigned RCID) const { 1638314564Sdim return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg()); 1639314564Sdim} 1640314564Sdim 1641341825Sdimbool AMDGPUOperand::isSDWAOperand(MVT type) const { 1642321369Sdim if (AsmParser->isVI()) 1643353358Sdim return isVReg32(); 1644353358Sdim else if (AsmParser->isGFX9() || AsmParser->isGFX10()) 1645353358Sdim return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(type); 1646321369Sdim else 1647321369Sdim return false; 1648321369Sdim} 1649321369Sdim 1650341825Sdimbool AMDGPUOperand::isSDWAFP16Operand() const { 1651341825Sdim return isSDWAOperand(MVT::f16); 1652341825Sdim} 1653341825Sdim 1654341825Sdimbool AMDGPUOperand::isSDWAFP32Operand() const { 1655341825Sdim return isSDWAOperand(MVT::f32); 1656341825Sdim} 1657341825Sdim 1658341825Sdimbool AMDGPUOperand::isSDWAInt16Operand() const { 1659341825Sdim return isSDWAOperand(MVT::i16); 1660341825Sdim} 1661341825Sdim 1662341825Sdimbool AMDGPUOperand::isSDWAInt32Operand() const { 1663341825Sdim return isSDWAOperand(MVT::i32); 1664341825Sdim} 1665341825Sdim 1666353358Sdimbool AMDGPUOperand::isBoolReg() const { 1667360784Sdim return (AsmParser->getFeatureBits()[AMDGPU::FeatureWavefrontSize64] && isSCSrcB64()) || 1668360784Sdim (AsmParser->getFeatureBits()[AMDGPU::FeatureWavefrontSize32] && isSCSrcB32()); 1669353358Sdim} 1670353358Sdim 1671321369Sdimuint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val, unsigned Size) const 1672321369Sdim{ 1673321369Sdim assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers()); 1674321369Sdim assert(Size == 2 || Size == 4 || Size == 8); 1675321369Sdim 1676321369Sdim const uint64_t FpSignMask = (1ULL << (Size * 8 - 1)); 1677321369Sdim 1678321369Sdim if (Imm.Mods.Abs) { 1679321369Sdim Val &= ~FpSignMask; 1680314564Sdim } 1681321369Sdim if (Imm.Mods.Neg) { 1682321369Sdim Val ^= FpSignMask; 1683321369Sdim } 1684314564Sdim 1685321369Sdim return Val; 1686321369Sdim} 1687321369Sdim 1688321369Sdimvoid AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const { 1689314564Sdim if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()), 1690314564Sdim Inst.getNumOperands())) { 1691321369Sdim addLiteralImmOperand(Inst, Imm.Val, 1692321369Sdim ApplyModifiers & 1693321369Sdim isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers()); 1694314564Sdim } else { 1695321369Sdim assert(!isImmTy(ImmTyNone) || !hasModifiers()); 1696321369Sdim Inst.addOperand(MCOperand::createImm(Imm.Val)); 1697314564Sdim } 1698314564Sdim} 1699314564Sdim 1700321369Sdimvoid AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const { 1701314564Sdim const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode()); 1702314564Sdim auto OpNum = Inst.getNumOperands(); 1703314564Sdim // Check that this operand accepts literals 1704314564Sdim assert(AMDGPU::isSISrcOperand(InstDesc, OpNum)); 1705314564Sdim 1706321369Sdim if (ApplyModifiers) { 1707321369Sdim assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum)); 1708321369Sdim const unsigned Size = Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum); 1709321369Sdim Val = applyInputFPModifiers(Val, Size); 1710321369Sdim } 1711314564Sdim 1712321369Sdim APInt Literal(64, Val); 1713321369Sdim uint8_t OpTy = InstDesc.OpInfo[OpNum].OperandType; 1714321369Sdim 1715314564Sdim if (Imm.IsFPImm) { // We got fp literal token 1716321369Sdim switch (OpTy) { 1717321369Sdim case AMDGPU::OPERAND_REG_IMM_INT64: 1718321369Sdim case AMDGPU::OPERAND_REG_IMM_FP64: 1719321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_INT64: 1720327952Sdim case AMDGPU::OPERAND_REG_INLINE_C_FP64: 1721314564Sdim if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(), 1722314564Sdim AsmParser->hasInv2PiInlineImm())) { 1723314564Sdim Inst.addOperand(MCOperand::createImm(Literal.getZExtValue())); 1724314564Sdim return; 1725314564Sdim } 1726314564Sdim 1727314564Sdim // Non-inlineable 1728314564Sdim if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand 1729314564Sdim // For fp operands we check if low 32 bits are zeros 1730314564Sdim if (Literal.getLoBits(32) != 0) { 1731314564Sdim const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(), 1732314564Sdim "Can't encode literal as exact 64-bit floating-point operand. " 1733314564Sdim "Low 32-bits will be set to zero"); 1734314564Sdim } 1735314564Sdim 1736314564Sdim Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue())); 1737314564Sdim return; 1738314564Sdim } 1739314564Sdim 1740314564Sdim // We don't allow fp literals in 64-bit integer instructions. It is 1741314564Sdim // unclear how we should encode them. This case should be checked earlier 1742314564Sdim // in predicate methods (isLiteralImm()) 1743314564Sdim llvm_unreachable("fp literal in 64-bit integer instruction."); 1744327952Sdim 1745321369Sdim case AMDGPU::OPERAND_REG_IMM_INT32: 1746321369Sdim case AMDGPU::OPERAND_REG_IMM_FP32: 1747321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_INT32: 1748321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_FP32: 1749353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_INT32: 1750353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_FP32: 1751321369Sdim case AMDGPU::OPERAND_REG_IMM_INT16: 1752321369Sdim case AMDGPU::OPERAND_REG_IMM_FP16: 1753321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_INT16: 1754321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_FP16: 1755321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_V2INT16: 1756353358Sdim case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: 1757353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_INT16: 1758353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_FP16: 1759353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16: 1760353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: 1761353358Sdim case AMDGPU::OPERAND_REG_IMM_V2INT16: 1762353358Sdim case AMDGPU::OPERAND_REG_IMM_V2FP16: { 1763314564Sdim bool lost; 1764314564Sdim APFloat FPLiteral(APFloat::IEEEdouble(), Literal); 1765314564Sdim // Convert literal to single precision 1766321369Sdim FPLiteral.convert(*getOpFltSemantics(OpTy), 1767314564Sdim APFloat::rmNearestTiesToEven, &lost); 1768314564Sdim // We allow precision lost but not overflow or underflow. This should be 1769314564Sdim // checked earlier in isLiteralImm() 1770321369Sdim 1771321369Sdim uint64_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue(); 1772321369Sdim Inst.addOperand(MCOperand::createImm(ImmVal)); 1773314564Sdim return; 1774314564Sdim } 1775314564Sdim default: 1776314564Sdim llvm_unreachable("invalid operand size"); 1777314564Sdim } 1778314564Sdim 1779314564Sdim return; 1780314564Sdim } 1781314564Sdim 1782353358Sdim // We got int literal token. 1783314564Sdim // Only sign extend inline immediates. 1784321369Sdim switch (OpTy) { 1785321369Sdim case AMDGPU::OPERAND_REG_IMM_INT32: 1786321369Sdim case AMDGPU::OPERAND_REG_IMM_FP32: 1787321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_INT32: 1788327952Sdim case AMDGPU::OPERAND_REG_INLINE_C_FP32: 1789353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_INT32: 1790353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_FP32: 1791353358Sdim case AMDGPU::OPERAND_REG_IMM_V2INT16: 1792353358Sdim case AMDGPU::OPERAND_REG_IMM_V2FP16: 1793353358Sdim if (isSafeTruncation(Val, 32) && 1794314564Sdim AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val), 1795314564Sdim AsmParser->hasInv2PiInlineImm())) { 1796314564Sdim Inst.addOperand(MCOperand::createImm(Val)); 1797314564Sdim return; 1798314564Sdim } 1799314564Sdim 1800314564Sdim Inst.addOperand(MCOperand::createImm(Val & 0xffffffff)); 1801314564Sdim return; 1802327952Sdim 1803321369Sdim case AMDGPU::OPERAND_REG_IMM_INT64: 1804321369Sdim case AMDGPU::OPERAND_REG_IMM_FP64: 1805321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_INT64: 1806327952Sdim case AMDGPU::OPERAND_REG_INLINE_C_FP64: 1807321369Sdim if (AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) { 1808314564Sdim Inst.addOperand(MCOperand::createImm(Val)); 1809314564Sdim return; 1810314564Sdim } 1811314564Sdim 1812314564Sdim Inst.addOperand(MCOperand::createImm(Lo_32(Val))); 1813314564Sdim return; 1814327952Sdim 1815321369Sdim case AMDGPU::OPERAND_REG_IMM_INT16: 1816321369Sdim case AMDGPU::OPERAND_REG_IMM_FP16: 1817321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_INT16: 1818327952Sdim case AMDGPU::OPERAND_REG_INLINE_C_FP16: 1819353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_INT16: 1820353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_FP16: 1821353358Sdim if (isSafeTruncation(Val, 16) && 1822314564Sdim AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val), 1823314564Sdim AsmParser->hasInv2PiInlineImm())) { 1824314564Sdim Inst.addOperand(MCOperand::createImm(Val)); 1825314564Sdim return; 1826314564Sdim } 1827314564Sdim 1828314564Sdim Inst.addOperand(MCOperand::createImm(Val & 0xffff)); 1829314564Sdim return; 1830327952Sdim 1831321369Sdim case AMDGPU::OPERAND_REG_INLINE_C_V2INT16: 1832353358Sdim case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: 1833353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16: 1834353358Sdim case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: { 1835353358Sdim assert(isSafeTruncation(Val, 16)); 1836353358Sdim assert(AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val), 1837321369Sdim AsmParser->hasInv2PiInlineImm())); 1838321369Sdim 1839353358Sdim Inst.addOperand(MCOperand::createImm(Val)); 1840321369Sdim return; 1841321369Sdim } 1842314564Sdim default: 1843314564Sdim llvm_unreachable("invalid operand size"); 1844314564Sdim } 1845314564Sdim} 1846314564Sdim 1847314564Sdimtemplate <unsigned Bitwidth> 1848314564Sdimvoid AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const { 1849314564Sdim APInt Literal(64, Imm.Val); 1850314564Sdim 1851314564Sdim if (!Imm.IsFPImm) { 1852314564Sdim // We got int literal token. 1853314564Sdim Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue())); 1854314564Sdim return; 1855314564Sdim } 1856314564Sdim 1857314564Sdim bool Lost; 1858314564Sdim APFloat FPLiteral(APFloat::IEEEdouble(), Literal); 1859314564Sdim FPLiteral.convert(*getFltSemantics(Bitwidth / 8), 1860314564Sdim APFloat::rmNearestTiesToEven, &Lost); 1861314564Sdim Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue())); 1862314564Sdim} 1863314564Sdim 1864314564Sdimvoid AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const { 1865314564Sdim Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI()))); 1866314564Sdim} 1867314564Sdim 1868353358Sdimstatic bool isInlineValue(unsigned Reg) { 1869353358Sdim switch (Reg) { 1870353358Sdim case AMDGPU::SRC_SHARED_BASE: 1871353358Sdim case AMDGPU::SRC_SHARED_LIMIT: 1872353358Sdim case AMDGPU::SRC_PRIVATE_BASE: 1873353358Sdim case AMDGPU::SRC_PRIVATE_LIMIT: 1874353358Sdim case AMDGPU::SRC_POPS_EXITING_WAVE_ID: 1875353358Sdim return true; 1876353358Sdim case AMDGPU::SRC_VCCZ: 1877353358Sdim case AMDGPU::SRC_EXECZ: 1878353358Sdim case AMDGPU::SRC_SCC: 1879353358Sdim return true; 1880360784Sdim case AMDGPU::SGPR_NULL: 1881360784Sdim return true; 1882353358Sdim default: 1883353358Sdim return false; 1884353358Sdim } 1885353358Sdim} 1886353358Sdim 1887353358Sdimbool AMDGPUOperand::isInlineValue() const { 1888353358Sdim return isRegKind() && ::isInlineValue(getReg()); 1889353358Sdim} 1890353358Sdim 1891314564Sdim//===----------------------------------------------------------------------===// 1892314564Sdim// AsmParser 1893314564Sdim//===----------------------------------------------------------------------===// 1894314564Sdim 1895309124Sdimstatic int getRegClass(RegisterKind Is, unsigned RegWidth) { 1896309124Sdim if (Is == IS_VGPR) { 1897284677Sdim switch (RegWidth) { 1898296417Sdim default: return -1; 1899284677Sdim case 1: return AMDGPU::VGPR_32RegClassID; 1900284677Sdim case 2: return AMDGPU::VReg_64RegClassID; 1901284677Sdim case 3: return AMDGPU::VReg_96RegClassID; 1902284677Sdim case 4: return AMDGPU::VReg_128RegClassID; 1903360784Sdim case 5: return AMDGPU::VReg_160RegClassID; 1904284677Sdim case 8: return AMDGPU::VReg_256RegClassID; 1905284677Sdim case 16: return AMDGPU::VReg_512RegClassID; 1906360784Sdim case 32: return AMDGPU::VReg_1024RegClassID; 1907284677Sdim } 1908309124Sdim } else if (Is == IS_TTMP) { 1909309124Sdim switch (RegWidth) { 1910309124Sdim default: return -1; 1911309124Sdim case 1: return AMDGPU::TTMP_32RegClassID; 1912309124Sdim case 2: return AMDGPU::TTMP_64RegClassID; 1913309124Sdim case 4: return AMDGPU::TTMP_128RegClassID; 1914327952Sdim case 8: return AMDGPU::TTMP_256RegClassID; 1915327952Sdim case 16: return AMDGPU::TTMP_512RegClassID; 1916309124Sdim } 1917309124Sdim } else if (Is == IS_SGPR) { 1918309124Sdim switch (RegWidth) { 1919309124Sdim default: return -1; 1920309124Sdim case 1: return AMDGPU::SGPR_32RegClassID; 1921309124Sdim case 2: return AMDGPU::SGPR_64RegClassID; 1922309124Sdim case 4: return AMDGPU::SGPR_128RegClassID; 1923327952Sdim case 8: return AMDGPU::SGPR_256RegClassID; 1924327952Sdim case 16: return AMDGPU::SGPR_512RegClassID; 1925309124Sdim } 1926353358Sdim } else if (Is == IS_AGPR) { 1927353358Sdim switch (RegWidth) { 1928353358Sdim default: return -1; 1929353358Sdim case 1: return AMDGPU::AGPR_32RegClassID; 1930353358Sdim case 2: return AMDGPU::AReg_64RegClassID; 1931353358Sdim case 4: return AMDGPU::AReg_128RegClassID; 1932353358Sdim case 16: return AMDGPU::AReg_512RegClassID; 1933353358Sdim case 32: return AMDGPU::AReg_1024RegClassID; 1934353358Sdim } 1935284677Sdim } 1936309124Sdim return -1; 1937284677Sdim} 1938284677Sdim 1939309124Sdimstatic unsigned getSpecialRegForName(StringRef RegName) { 1940284677Sdim return StringSwitch<unsigned>(RegName) 1941284677Sdim .Case("exec", AMDGPU::EXEC) 1942284677Sdim .Case("vcc", AMDGPU::VCC) 1943296417Sdim .Case("flat_scratch", AMDGPU::FLAT_SCR) 1944341825Sdim .Case("xnack_mask", AMDGPU::XNACK_MASK) 1945353358Sdim .Case("shared_base", AMDGPU::SRC_SHARED_BASE) 1946353358Sdim .Case("src_shared_base", AMDGPU::SRC_SHARED_BASE) 1947353358Sdim .Case("shared_limit", AMDGPU::SRC_SHARED_LIMIT) 1948353358Sdim .Case("src_shared_limit", AMDGPU::SRC_SHARED_LIMIT) 1949353358Sdim .Case("private_base", AMDGPU::SRC_PRIVATE_BASE) 1950353358Sdim .Case("src_private_base", AMDGPU::SRC_PRIVATE_BASE) 1951353358Sdim .Case("private_limit", AMDGPU::SRC_PRIVATE_LIMIT) 1952353358Sdim .Case("src_private_limit", AMDGPU::SRC_PRIVATE_LIMIT) 1953353358Sdim .Case("pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID) 1954353358Sdim .Case("src_pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID) 1955353358Sdim .Case("lds_direct", AMDGPU::LDS_DIRECT) 1956353358Sdim .Case("src_lds_direct", AMDGPU::LDS_DIRECT) 1957284677Sdim .Case("m0", AMDGPU::M0) 1958353358Sdim .Case("vccz", AMDGPU::SRC_VCCZ) 1959353358Sdim .Case("src_vccz", AMDGPU::SRC_VCCZ) 1960353358Sdim .Case("execz", AMDGPU::SRC_EXECZ) 1961353358Sdim .Case("src_execz", AMDGPU::SRC_EXECZ) 1962353358Sdim .Case("scc", AMDGPU::SRC_SCC) 1963353358Sdim .Case("src_scc", AMDGPU::SRC_SCC) 1964309124Sdim .Case("tba", AMDGPU::TBA) 1965309124Sdim .Case("tma", AMDGPU::TMA) 1966296417Sdim .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO) 1967296417Sdim .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI) 1968341825Sdim .Case("xnack_mask_lo", AMDGPU::XNACK_MASK_LO) 1969341825Sdim .Case("xnack_mask_hi", AMDGPU::XNACK_MASK_HI) 1970284677Sdim .Case("vcc_lo", AMDGPU::VCC_LO) 1971284677Sdim .Case("vcc_hi", AMDGPU::VCC_HI) 1972284677Sdim .Case("exec_lo", AMDGPU::EXEC_LO) 1973284677Sdim .Case("exec_hi", AMDGPU::EXEC_HI) 1974309124Sdim .Case("tma_lo", AMDGPU::TMA_LO) 1975309124Sdim .Case("tma_hi", AMDGPU::TMA_HI) 1976309124Sdim .Case("tba_lo", AMDGPU::TBA_LO) 1977309124Sdim .Case("tba_hi", AMDGPU::TBA_HI) 1978353358Sdim .Case("null", AMDGPU::SGPR_NULL) 1979360784Sdim .Default(AMDGPU::NoRegister); 1980284677Sdim} 1981284677Sdim 1982321369Sdimbool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 1983321369Sdim SMLoc &EndLoc) { 1984309124Sdim auto R = parseRegister(); 1985309124Sdim if (!R) return true; 1986309124Sdim assert(R->isReg()); 1987309124Sdim RegNo = R->getReg(); 1988309124Sdim StartLoc = R->getStartLoc(); 1989309124Sdim EndLoc = R->getEndLoc(); 1990309124Sdim return false; 1991309124Sdim} 1992309124Sdim 1993321369Sdimbool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth, 1994360784Sdim RegisterKind RegKind, unsigned Reg1) { 1995309124Sdim switch (RegKind) { 1996309124Sdim case IS_SPECIAL: 1997321369Sdim if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) { 1998321369Sdim Reg = AMDGPU::EXEC; 1999321369Sdim RegWidth = 2; 2000321369Sdim return true; 2001321369Sdim } 2002321369Sdim if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) { 2003321369Sdim Reg = AMDGPU::FLAT_SCR; 2004321369Sdim RegWidth = 2; 2005321369Sdim return true; 2006321369Sdim } 2007341825Sdim if (Reg == AMDGPU::XNACK_MASK_LO && Reg1 == AMDGPU::XNACK_MASK_HI) { 2008341825Sdim Reg = AMDGPU::XNACK_MASK; 2009341825Sdim RegWidth = 2; 2010341825Sdim return true; 2011341825Sdim } 2012321369Sdim if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) { 2013321369Sdim Reg = AMDGPU::VCC; 2014321369Sdim RegWidth = 2; 2015321369Sdim return true; 2016321369Sdim } 2017321369Sdim if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) { 2018321369Sdim Reg = AMDGPU::TBA; 2019321369Sdim RegWidth = 2; 2020321369Sdim return true; 2021321369Sdim } 2022321369Sdim if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) { 2023321369Sdim Reg = AMDGPU::TMA; 2024321369Sdim RegWidth = 2; 2025321369Sdim return true; 2026321369Sdim } 2027309124Sdim return false; 2028309124Sdim case IS_VGPR: 2029309124Sdim case IS_SGPR: 2030353358Sdim case IS_AGPR: 2031309124Sdim case IS_TTMP: 2032321369Sdim if (Reg1 != Reg + RegWidth) { 2033321369Sdim return false; 2034321369Sdim } 2035309124Sdim RegWidth++; 2036309124Sdim return true; 2037309124Sdim default: 2038314564Sdim llvm_unreachable("unexpected register kind"); 2039309124Sdim } 2040309124Sdim} 2041309124Sdim 2042360784Sdimstruct RegInfo { 2043360784Sdim StringLiteral Name; 2044360784Sdim RegisterKind Kind; 2045353358Sdim}; 2046353358Sdim 2047360784Sdimstatic constexpr RegInfo RegularRegisters[] = { 2048360784Sdim {{"v"}, IS_VGPR}, 2049360784Sdim {{"s"}, IS_SGPR}, 2050360784Sdim {{"ttmp"}, IS_TTMP}, 2051360784Sdim {{"acc"}, IS_AGPR}, 2052360784Sdim {{"a"}, IS_AGPR}, 2053360784Sdim}; 2054360784Sdim 2055360784Sdimstatic bool isRegularReg(RegisterKind Kind) { 2056360784Sdim return Kind == IS_VGPR || 2057360784Sdim Kind == IS_SGPR || 2058360784Sdim Kind == IS_TTMP || 2059360784Sdim Kind == IS_AGPR; 2060360784Sdim} 2061360784Sdim 2062360784Sdimstatic const RegInfo* getRegularRegInfo(StringRef Str) { 2063360784Sdim for (const RegInfo &Reg : RegularRegisters) 2064360784Sdim if (Str.startswith(Reg.Name)) 2065360784Sdim return &Reg; 2066360784Sdim return nullptr; 2067360784Sdim} 2068360784Sdim 2069360784Sdimstatic bool getRegNum(StringRef Str, unsigned& Num) { 2070360784Sdim return !Str.getAsInteger(10, Num); 2071360784Sdim} 2072360784Sdim 2073353358Sdimbool 2074353358SdimAMDGPUAsmParser::isRegister(const AsmToken &Token, 2075353358Sdim const AsmToken &NextToken) const { 2076353358Sdim 2077353358Sdim // A list of consecutive registers: [s0,s1,s2,s3] 2078353358Sdim if (Token.is(AsmToken::LBrac)) 2079353358Sdim return true; 2080353358Sdim 2081353358Sdim if (!Token.is(AsmToken::Identifier)) 2082353358Sdim return false; 2083353358Sdim 2084353358Sdim // A single register like s0 or a range of registers like s[0:1] 2085353358Sdim 2086360784Sdim StringRef Str = Token.getString(); 2087360784Sdim const RegInfo *Reg = getRegularRegInfo(Str); 2088360784Sdim if (Reg) { 2089360784Sdim StringRef RegName = Reg->Name; 2090360784Sdim StringRef RegSuffix = Str.substr(RegName.size()); 2091360784Sdim if (!RegSuffix.empty()) { 2092360784Sdim unsigned Num; 2093360784Sdim // A single register with an index: rXX 2094360784Sdim if (getRegNum(RegSuffix, Num)) 2095360784Sdim return true; 2096360784Sdim } else { 2097360784Sdim // A range of registers: r[XX:YY]. 2098360784Sdim if (NextToken.is(AsmToken::LBrac)) 2099360784Sdim return true; 2100353358Sdim } 2101353358Sdim } 2102353358Sdim 2103360784Sdim return getSpecialRegForName(Str) != AMDGPU::NoRegister; 2104353358Sdim} 2105353358Sdim 2106353358Sdimbool 2107353358SdimAMDGPUAsmParser::isRegister() 2108353358Sdim{ 2109353358Sdim return isRegister(getToken(), peekToken()); 2110353358Sdim} 2111353358Sdim 2112360784Sdimunsigned 2113360784SdimAMDGPUAsmParser::getRegularReg(RegisterKind RegKind, 2114360784Sdim unsigned RegNum, 2115360784Sdim unsigned RegWidth) { 2116360784Sdim 2117360784Sdim assert(isRegularReg(RegKind)); 2118360784Sdim 2119360784Sdim unsigned AlignSize = 1; 2120360784Sdim if (RegKind == IS_SGPR || RegKind == IS_TTMP) { 2121360784Sdim // SGPR and TTMP registers must be aligned. 2122360784Sdim // Max required alignment is 4 dwords. 2123360784Sdim AlignSize = std::min(RegWidth, 4u); 2124360784Sdim } 2125360784Sdim 2126360784Sdim if (RegNum % AlignSize != 0) 2127360784Sdim return AMDGPU::NoRegister; 2128360784Sdim 2129360784Sdim unsigned RegIdx = RegNum / AlignSize; 2130360784Sdim int RCID = getRegClass(RegKind, RegWidth); 2131360784Sdim if (RCID == -1) 2132360784Sdim return AMDGPU::NoRegister; 2133360784Sdim 2134296417Sdim const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 2135360784Sdim const MCRegisterClass RC = TRI->getRegClass(RCID); 2136360784Sdim if (RegIdx >= RC.getNumRegs()) 2137360784Sdim return AMDGPU::NoRegister; 2138296417Sdim 2139360784Sdim return RC.getRegister(RegIdx); 2140360784Sdim} 2141284677Sdim 2142360784Sdimbool 2143360784SdimAMDGPUAsmParser::ParseRegRange(unsigned& Num, unsigned& Width) { 2144360784Sdim int64_t RegLo, RegHi; 2145360784Sdim if (!trySkipToken(AsmToken::LBrac)) 2146360784Sdim return false; 2147309124Sdim 2148360784Sdim if (!parseExpr(RegLo)) 2149360784Sdim return false; 2150309124Sdim 2151360784Sdim if (trySkipToken(AsmToken::Colon)) { 2152360784Sdim if (!parseExpr(RegHi)) 2153309124Sdim return false; 2154309124Sdim } else { 2155360784Sdim RegHi = RegLo; 2156360784Sdim } 2157360784Sdim 2158360784Sdim if (!trySkipToken(AsmToken::RBrac)) 2159309124Sdim return false; 2160360784Sdim 2161360784Sdim if (!isUInt<32>(RegLo) || !isUInt<32>(RegHi) || RegLo > RegHi) 2162360784Sdim return false; 2163360784Sdim 2164360784Sdim Num = static_cast<unsigned>(RegLo); 2165360784Sdim Width = (RegHi - RegLo) + 1; 2166360784Sdim return true; 2167360784Sdim} 2168360784Sdim 2169360784Sdimunsigned 2170360784SdimAMDGPUAsmParser::ParseSpecialReg(RegisterKind &RegKind, 2171360784Sdim unsigned &RegNum, 2172360784Sdim unsigned &RegWidth) { 2173360784Sdim assert(isToken(AsmToken::Identifier)); 2174360784Sdim unsigned Reg = getSpecialRegForName(getTokenStr()); 2175360784Sdim if (Reg) { 2176309124Sdim RegNum = 0; 2177309124Sdim RegWidth = 1; 2178360784Sdim RegKind = IS_SPECIAL; 2179360784Sdim lex(); // skip register name 2180309124Sdim } 2181360784Sdim return Reg; 2182360784Sdim} 2183284677Sdim 2184360784Sdimunsigned 2185360784SdimAMDGPUAsmParser::ParseRegularReg(RegisterKind &RegKind, 2186360784Sdim unsigned &RegNum, 2187360784Sdim unsigned &RegWidth) { 2188360784Sdim assert(isToken(AsmToken::Identifier)); 2189360784Sdim StringRef RegName = getTokenStr(); 2190360784Sdim 2191360784Sdim const RegInfo *RI = getRegularRegInfo(RegName); 2192360784Sdim if (!RI) 2193360784Sdim return AMDGPU::NoRegister; 2194360784Sdim lex(); // skip register name 2195360784Sdim 2196360784Sdim RegKind = RI->Kind; 2197360784Sdim StringRef RegSuffix = RegName.substr(RI->Name.size()); 2198360784Sdim if (!RegSuffix.empty()) { 2199360784Sdim // Single 32-bit register: vXX. 2200360784Sdim if (!getRegNum(RegSuffix, RegNum)) 2201360784Sdim return AMDGPU::NoRegister; 2202360784Sdim RegWidth = 1; 2203360784Sdim } else { 2204360784Sdim // Range of registers: v[XX:YY]. ":YY" is optional. 2205360784Sdim if (!ParseRegRange(RegNum, RegWidth)) 2206360784Sdim return AMDGPU::NoRegister; 2207309124Sdim } 2208284677Sdim 2209360784Sdim return getRegularReg(RegKind, RegNum, RegWidth); 2210309124Sdim} 2211309124Sdim 2212360784Sdimunsigned 2213360784SdimAMDGPUAsmParser::ParseRegList(RegisterKind &RegKind, 2214360784Sdim unsigned &RegNum, 2215360784Sdim unsigned &RegWidth) { 2216360784Sdim unsigned Reg = AMDGPU::NoRegister; 2217360784Sdim 2218360784Sdim if (!trySkipToken(AsmToken::LBrac)) 2219360784Sdim return AMDGPU::NoRegister; 2220360784Sdim 2221360784Sdim // List of consecutive registers, e.g.: [s0,s1,s2,s3] 2222360784Sdim 2223360784Sdim if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) 2224360784Sdim return AMDGPU::NoRegister; 2225360784Sdim if (RegWidth != 1) 2226360784Sdim return AMDGPU::NoRegister; 2227360784Sdim 2228360784Sdim for (; trySkipToken(AsmToken::Comma); ) { 2229360784Sdim RegisterKind NextRegKind; 2230360784Sdim unsigned NextReg, NextRegNum, NextRegWidth; 2231360784Sdim 2232360784Sdim if (!ParseAMDGPURegister(NextRegKind, NextReg, NextRegNum, NextRegWidth)) 2233360784Sdim return AMDGPU::NoRegister; 2234360784Sdim if (NextRegWidth != 1) 2235360784Sdim return AMDGPU::NoRegister; 2236360784Sdim if (NextRegKind != RegKind) 2237360784Sdim return AMDGPU::NoRegister; 2238360784Sdim if (!AddNextRegisterToList(Reg, RegWidth, RegKind, NextReg)) 2239360784Sdim return AMDGPU::NoRegister; 2240360784Sdim } 2241360784Sdim 2242360784Sdim if (!trySkipToken(AsmToken::RBrac)) 2243360784Sdim return AMDGPU::NoRegister; 2244360784Sdim 2245360784Sdim if (isRegularReg(RegKind)) 2246360784Sdim Reg = getRegularReg(RegKind, RegNum, RegWidth); 2247360784Sdim 2248360784Sdim return Reg; 2249360784Sdim} 2250360784Sdim 2251360784Sdimbool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, 2252360784Sdim unsigned &Reg, 2253360784Sdim unsigned &RegNum, 2254360784Sdim unsigned &RegWidth) { 2255360784Sdim Reg = AMDGPU::NoRegister; 2256360784Sdim 2257360784Sdim if (isToken(AsmToken::Identifier)) { 2258360784Sdim Reg = ParseSpecialReg(RegKind, RegNum, RegWidth); 2259360784Sdim if (Reg == AMDGPU::NoRegister) 2260360784Sdim Reg = ParseRegularReg(RegKind, RegNum, RegWidth); 2261360784Sdim } else { 2262360784Sdim Reg = ParseRegList(RegKind, RegNum, RegWidth); 2263360784Sdim } 2264360784Sdim 2265360784Sdim const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 2266360784Sdim return Reg != AMDGPU::NoRegister && subtargetHasRegister(*TRI, Reg); 2267360784Sdim} 2268360784Sdim 2269341825SdimOptional<StringRef> 2270341825SdimAMDGPUAsmParser::getGprCountSymbolName(RegisterKind RegKind) { 2271341825Sdim switch (RegKind) { 2272341825Sdim case IS_VGPR: 2273341825Sdim return StringRef(".amdgcn.next_free_vgpr"); 2274341825Sdim case IS_SGPR: 2275341825Sdim return StringRef(".amdgcn.next_free_sgpr"); 2276341825Sdim default: 2277341825Sdim return None; 2278341825Sdim } 2279341825Sdim} 2280341825Sdim 2281341825Sdimvoid AMDGPUAsmParser::initializeGprCountSymbol(RegisterKind RegKind) { 2282341825Sdim auto SymbolName = getGprCountSymbolName(RegKind); 2283341825Sdim assert(SymbolName && "initializing invalid register kind"); 2284341825Sdim MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName); 2285341825Sdim Sym->setVariableValue(MCConstantExpr::create(0, getContext())); 2286341825Sdim} 2287341825Sdim 2288341825Sdimbool AMDGPUAsmParser::updateGprCountSymbols(RegisterKind RegKind, 2289341825Sdim unsigned DwordRegIndex, 2290341825Sdim unsigned RegWidth) { 2291341825Sdim // Symbols are only defined for GCN targets 2292344779Sdim if (AMDGPU::getIsaVersion(getSTI().getCPU()).Major < 6) 2293341825Sdim return true; 2294341825Sdim 2295341825Sdim auto SymbolName = getGprCountSymbolName(RegKind); 2296341825Sdim if (!SymbolName) 2297341825Sdim return true; 2298341825Sdim MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName); 2299341825Sdim 2300341825Sdim int64_t NewMax = DwordRegIndex + RegWidth - 1; 2301341825Sdim int64_t OldCount; 2302341825Sdim 2303341825Sdim if (!Sym->isVariable()) 2304341825Sdim return !Error(getParser().getTok().getLoc(), 2305341825Sdim ".amdgcn.next_free_{v,s}gpr symbols must be variable"); 2306341825Sdim if (!Sym->getVariableValue(false)->evaluateAsAbsolute(OldCount)) 2307341825Sdim return !Error( 2308341825Sdim getParser().getTok().getLoc(), 2309341825Sdim ".amdgcn.next_free_{v,s}gpr symbols must be absolute expressions"); 2310341825Sdim 2311341825Sdim if (OldCount <= NewMax) 2312341825Sdim Sym->setVariableValue(MCConstantExpr::create(NewMax + 1, getContext())); 2313341825Sdim 2314341825Sdim return true; 2315341825Sdim} 2316341825Sdim 2317309124Sdimstd::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() { 2318309124Sdim const auto &Tok = Parser.getTok(); 2319309124Sdim SMLoc StartLoc = Tok.getLoc(); 2320309124Sdim SMLoc EndLoc = Tok.getEndLoc(); 2321309124Sdim RegisterKind RegKind; 2322360784Sdim unsigned Reg, RegNum, RegWidth; 2323309124Sdim 2324360784Sdim if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) { 2325353358Sdim //FIXME: improve error messages (bug 41303). 2326353358Sdim Error(StartLoc, "not a valid operand."); 2327309124Sdim return nullptr; 2328309124Sdim } 2329341825Sdim if (AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) { 2330360784Sdim if (!updateGprCountSymbols(RegKind, RegNum, RegWidth)) 2331341825Sdim return nullptr; 2332341825Sdim } else 2333360784Sdim KernelScope.usesRegister(RegKind, RegNum, RegWidth); 2334353358Sdim return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc); 2335309124Sdim} 2336309124Sdim 2337353358SdimOperandMatchResultTy 2338353358SdimAMDGPUAsmParser::parseImm(OperandVector &Operands, bool HasSP3AbsModifier) { 2339353358Sdim // TODO: add syntactic sugar for 1/(2*PI) 2340321369Sdim 2341353358Sdim assert(!isRegister()); 2342353358Sdim assert(!isModifier()); 2343321369Sdim 2344353358Sdim const auto& Tok = getToken(); 2345353358Sdim const auto& NextTok = peekToken(); 2346353358Sdim bool IsReal = Tok.is(AsmToken::Real); 2347353358Sdim SMLoc S = getLoc(); 2348353358Sdim bool Negate = false; 2349321369Sdim 2350353358Sdim if (!IsReal && Tok.is(AsmToken::Minus) && NextTok.is(AsmToken::Real)) { 2351353358Sdim lex(); 2352353358Sdim IsReal = true; 2353353358Sdim Negate = true; 2354321369Sdim } 2355321369Sdim 2356353358Sdim if (IsReal) { 2357353358Sdim // Floating-point expressions are not supported. 2358353358Sdim // Can only allow floating-point literals with an 2359353358Sdim // optional sign. 2360321369Sdim 2361353358Sdim StringRef Num = getTokenStr(); 2362353358Sdim lex(); 2363353358Sdim 2364353358Sdim APFloat RealVal(APFloat::IEEEdouble()); 2365353358Sdim auto roundMode = APFloat::rmNearestTiesToEven; 2366360784Sdim if (errorToBool(RealVal.convertFromString(Num, roundMode).takeError())) { 2367353358Sdim return MatchOperand_ParseFail; 2368327952Sdim } 2369353358Sdim if (Negate) 2370353358Sdim RealVal.changeSign(); 2371284677Sdim 2372353358Sdim Operands.push_back( 2373353358Sdim AMDGPUOperand::CreateImm(this, RealVal.bitcastToAPInt().getZExtValue(), S, 2374353358Sdim AMDGPUOperand::ImmTyNone, true)); 2375353358Sdim 2376309124Sdim return MatchOperand_Success; 2377353358Sdim 2378353358Sdim } else { 2379309124Sdim int64_t IntVal; 2380353358Sdim const MCExpr *Expr; 2381353358Sdim SMLoc S = getLoc(); 2382309124Sdim 2383353358Sdim if (HasSP3AbsModifier) { 2384353358Sdim // This is a workaround for handling expressions 2385353358Sdim // as arguments of SP3 'abs' modifier, for example: 2386353358Sdim // |1.0| 2387353358Sdim // |-1| 2388353358Sdim // |1+x| 2389353358Sdim // This syntax is not compatible with syntax of standard 2390353358Sdim // MC expressions (due to the trailing '|'). 2391353358Sdim SMLoc EndLoc; 2392353358Sdim if (getParser().parsePrimaryExpr(Expr, EndLoc)) 2393353358Sdim return MatchOperand_ParseFail; 2394353358Sdim } else { 2395353358Sdim if (Parser.parseExpression(Expr)) 2396353358Sdim return MatchOperand_ParseFail; 2397353358Sdim } 2398353358Sdim 2399353358Sdim if (Expr->evaluateAsAbsolute(IntVal)) { 2400353358Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S)); 2401353358Sdim } else { 2402353358Sdim Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S)); 2403353358Sdim } 2404353358Sdim 2405309124Sdim return MatchOperand_Success; 2406309124Sdim } 2407353358Sdim 2408353358Sdim return MatchOperand_NoMatch; 2409309124Sdim} 2410309124Sdim 2411314564SdimOperandMatchResultTy 2412314564SdimAMDGPUAsmParser::parseReg(OperandVector &Operands) { 2413353358Sdim if (!isRegister()) 2414353358Sdim return MatchOperand_NoMatch; 2415353358Sdim 2416309124Sdim if (auto R = parseRegister()) { 2417309124Sdim assert(R->isReg()); 2418309124Sdim Operands.push_back(std::move(R)); 2419309124Sdim return MatchOperand_Success; 2420309124Sdim } 2421353358Sdim return MatchOperand_ParseFail; 2422309124Sdim} 2423309124Sdim 2424314564SdimOperandMatchResultTy 2425353358SdimAMDGPUAsmParser::parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod) { 2426353358Sdim auto res = parseReg(Operands); 2427314564Sdim if (res != MatchOperand_NoMatch) { 2428314564Sdim return res; 2429353358Sdim } else if (isModifier()) { 2430353358Sdim return MatchOperand_NoMatch; 2431353358Sdim } else { 2432353358Sdim return parseImm(Operands, HasSP3AbsMod); 2433314564Sdim } 2434353358Sdim} 2435314564Sdim 2436353358Sdimbool 2437353358SdimAMDGPUAsmParser::isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const { 2438353358Sdim if (Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::LParen)) { 2439353358Sdim const auto &str = Token.getString(); 2440353358Sdim return str == "abs" || str == "neg" || str == "sext"; 2441353358Sdim } 2442353358Sdim return false; 2443314564Sdim} 2444314564Sdim 2445353358Sdimbool 2446353358SdimAMDGPUAsmParser::isOpcodeModifierWithVal(const AsmToken &Token, const AsmToken &NextToken) const { 2447353358Sdim return Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::Colon); 2448353358Sdim} 2449353358Sdim 2450353358Sdimbool 2451353358SdimAMDGPUAsmParser::isOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const { 2452353358Sdim return isNamedOperandModifier(Token, NextToken) || Token.is(AsmToken::Pipe); 2453353358Sdim} 2454353358Sdim 2455353358Sdimbool 2456353358SdimAMDGPUAsmParser::isRegOrOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const { 2457353358Sdim return isRegister(Token, NextToken) || isOperandModifier(Token, NextToken); 2458353358Sdim} 2459353358Sdim 2460353358Sdim// Check if this is an operand modifier or an opcode modifier 2461353358Sdim// which may look like an expression but it is not. We should 2462353358Sdim// avoid parsing these modifiers as expressions. Currently 2463353358Sdim// recognized sequences are: 2464353358Sdim// |...| 2465353358Sdim// abs(...) 2466353358Sdim// neg(...) 2467353358Sdim// sext(...) 2468353358Sdim// -reg 2469353358Sdim// -|...| 2470353358Sdim// -abs(...) 2471353358Sdim// name:... 2472353358Sdim// Note that simple opcode modifiers like 'gds' may be parsed as 2473353358Sdim// expressions; this is a special case. See getExpressionAsToken. 2474353358Sdim// 2475353358Sdimbool 2476353358SdimAMDGPUAsmParser::isModifier() { 2477353358Sdim 2478353358Sdim AsmToken Tok = getToken(); 2479353358Sdim AsmToken NextToken[2]; 2480353358Sdim peekTokens(NextToken); 2481353358Sdim 2482353358Sdim return isOperandModifier(Tok, NextToken[0]) || 2483353358Sdim (Tok.is(AsmToken::Minus) && isRegOrOperandModifier(NextToken[0], NextToken[1])) || 2484353358Sdim isOpcodeModifierWithVal(Tok, NextToken[0]); 2485353358Sdim} 2486353358Sdim 2487353358Sdim// Check if the current token is an SP3 'neg' modifier. 2488353358Sdim// Currently this modifier is allowed in the following context: 2489353358Sdim// 2490353358Sdim// 1. Before a register, e.g. "-v0", "-v[...]" or "-[v0,v1]". 2491353358Sdim// 2. Before an 'abs' modifier: -abs(...) 2492353358Sdim// 3. Before an SP3 'abs' modifier: -|...| 2493353358Sdim// 2494353358Sdim// In all other cases "-" is handled as a part 2495353358Sdim// of an expression that follows the sign. 2496353358Sdim// 2497353358Sdim// Note: When "-" is followed by an integer literal, 2498353358Sdim// this is interpreted as integer negation rather 2499353358Sdim// than a floating-point NEG modifier applied to N. 2500353358Sdim// Beside being contr-intuitive, such use of floating-point 2501353358Sdim// NEG modifier would have resulted in different meaning 2502353358Sdim// of integer literals used with VOP1/2/C and VOP3, 2503353358Sdim// for example: 2504353358Sdim// v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF 2505353358Sdim// v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001 2506353358Sdim// Negative fp literals with preceding "-" are 2507353358Sdim// handled likewise for unifomtity 2508353358Sdim// 2509353358Sdimbool 2510353358SdimAMDGPUAsmParser::parseSP3NegModifier() { 2511353358Sdim 2512353358Sdim AsmToken NextToken[2]; 2513353358Sdim peekTokens(NextToken); 2514353358Sdim 2515353358Sdim if (isToken(AsmToken::Minus) && 2516353358Sdim (isRegister(NextToken[0], NextToken[1]) || 2517353358Sdim NextToken[0].is(AsmToken::Pipe) || 2518353358Sdim isId(NextToken[0], "abs"))) { 2519353358Sdim lex(); 2520353358Sdim return true; 2521353358Sdim } 2522353358Sdim 2523353358Sdim return false; 2524353358Sdim} 2525353358Sdim 2526314564SdimOperandMatchResultTy 2527321369SdimAMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands, 2528321369Sdim bool AllowImm) { 2529353358Sdim bool Neg, SP3Neg; 2530353358Sdim bool Abs, SP3Abs; 2531353358Sdim SMLoc Loc; 2532309124Sdim 2533353358Sdim // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead. 2534353358Sdim if (isToken(AsmToken::Minus) && peekToken().is(AsmToken::Minus)) { 2535353358Sdim Error(getLoc(), "invalid syntax, expected 'neg' modifier"); 2536353358Sdim return MatchOperand_ParseFail; 2537353358Sdim } 2538321369Sdim 2539353358Sdim SP3Neg = parseSP3NegModifier(); 2540321369Sdim 2541353358Sdim Loc = getLoc(); 2542353358Sdim Neg = trySkipId("neg"); 2543353358Sdim if (Neg && SP3Neg) { 2544353358Sdim Error(Loc, "expected register or immediate"); 2545353358Sdim return MatchOperand_ParseFail; 2546321369Sdim } 2547353358Sdim if (Neg && !skipToken(AsmToken::LParen, "expected left paren after neg")) 2548353358Sdim return MatchOperand_ParseFail; 2549321369Sdim 2550353358Sdim Abs = trySkipId("abs"); 2551353358Sdim if (Abs && !skipToken(AsmToken::LParen, "expected left paren after abs")) 2552353358Sdim return MatchOperand_ParseFail; 2553284677Sdim 2554353358Sdim Loc = getLoc(); 2555353358Sdim SP3Abs = trySkipToken(AsmToken::Pipe); 2556353358Sdim if (Abs && SP3Abs) { 2557353358Sdim Error(Loc, "expected register or immediate"); 2558353358Sdim return MatchOperand_ParseFail; 2559309124Sdim } 2560284677Sdim 2561314564Sdim OperandMatchResultTy Res; 2562314564Sdim if (AllowImm) { 2563353358Sdim Res = parseRegOrImm(Operands, SP3Abs); 2564314564Sdim } else { 2565314564Sdim Res = parseReg(Operands); 2566314564Sdim } 2567309124Sdim if (Res != MatchOperand_Success) { 2568353358Sdim return (SP3Neg || Neg || SP3Abs || Abs)? MatchOperand_ParseFail : Res; 2569309124Sdim } 2570309124Sdim 2571353358Sdim if (SP3Abs && !skipToken(AsmToken::Pipe, "expected vertical bar")) 2572353358Sdim return MatchOperand_ParseFail; 2573353358Sdim if (Abs && !skipToken(AsmToken::RParen, "expected closing parentheses")) 2574353358Sdim return MatchOperand_ParseFail; 2575353358Sdim if (Neg && !skipToken(AsmToken::RParen, "expected closing parentheses")) 2576353358Sdim return MatchOperand_ParseFail; 2577353358Sdim 2578314564Sdim AMDGPUOperand::Modifiers Mods; 2579353358Sdim Mods.Abs = Abs || SP3Abs; 2580353358Sdim Mods.Neg = Neg || SP3Neg; 2581284677Sdim 2582353358Sdim if (Mods.hasFPModifiers()) { 2583353358Sdim AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back()); 2584353358Sdim if (Op.isExpr()) { 2585353358Sdim Error(Op.getStartLoc(), "expected an absolute expression"); 2586321369Sdim return MatchOperand_ParseFail; 2587321369Sdim } 2588309124Sdim Op.setModifiers(Mods); 2589309124Sdim } 2590309124Sdim return MatchOperand_Success; 2591309124Sdim} 2592284677Sdim 2593314564SdimOperandMatchResultTy 2594321369SdimAMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands, 2595321369Sdim bool AllowImm) { 2596353358Sdim bool Sext = trySkipId("sext"); 2597353358Sdim if (Sext && !skipToken(AsmToken::LParen, "expected left paren after sext")) 2598353358Sdim return MatchOperand_ParseFail; 2599309124Sdim 2600314564Sdim OperandMatchResultTy Res; 2601314564Sdim if (AllowImm) { 2602314564Sdim Res = parseRegOrImm(Operands); 2603314564Sdim } else { 2604314564Sdim Res = parseReg(Operands); 2605314564Sdim } 2606309124Sdim if (Res != MatchOperand_Success) { 2607353358Sdim return Sext? MatchOperand_ParseFail : Res; 2608309124Sdim } 2609296417Sdim 2610353358Sdim if (Sext && !skipToken(AsmToken::RParen, "expected closing parentheses")) 2611353358Sdim return MatchOperand_ParseFail; 2612353358Sdim 2613314564Sdim AMDGPUOperand::Modifiers Mods; 2614353358Sdim Mods.Sext = Sext; 2615314564Sdim 2616309124Sdim if (Mods.hasIntModifiers()) { 2617309124Sdim AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back()); 2618353358Sdim if (Op.isExpr()) { 2619353358Sdim Error(Op.getStartLoc(), "expected an absolute expression"); 2620353358Sdim return MatchOperand_ParseFail; 2621353358Sdim } 2622309124Sdim Op.setModifiers(Mods); 2623309124Sdim } 2624314564Sdim 2625309124Sdim return MatchOperand_Success; 2626284677Sdim} 2627284677Sdim 2628314564SdimOperandMatchResultTy 2629314564SdimAMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) { 2630314564Sdim return parseRegOrImmWithFPInputMods(Operands, false); 2631314564Sdim} 2632314564Sdim 2633314564SdimOperandMatchResultTy 2634314564SdimAMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) { 2635314564Sdim return parseRegOrImmWithIntInputMods(Operands, false); 2636314564Sdim} 2637314564Sdim 2638314564SdimOperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) { 2639353358Sdim auto Loc = getLoc(); 2640353358Sdim if (trySkipId("off")) { 2641353358Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Loc, 2642353358Sdim AMDGPUOperand::ImmTyOff, false)); 2643353358Sdim return MatchOperand_Success; 2644353358Sdim } 2645353358Sdim 2646353358Sdim if (!isRegister()) 2647353358Sdim return MatchOperand_NoMatch; 2648353358Sdim 2649314564Sdim std::unique_ptr<AMDGPUOperand> Reg = parseRegister(); 2650314564Sdim if (Reg) { 2651314564Sdim Operands.push_back(std::move(Reg)); 2652314564Sdim return MatchOperand_Success; 2653314564Sdim } 2654314564Sdim 2655353358Sdim return MatchOperand_ParseFail; 2656314564Sdim 2657314564Sdim} 2658314564Sdim 2659284677Sdimunsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 2660284677Sdim uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 2661284677Sdim 2662284677Sdim if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) || 2663309124Sdim (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) || 2664309124Sdim (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) || 2665309124Sdim (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) ) 2666284677Sdim return Match_InvalidOperand; 2667284677Sdim 2668296417Sdim if ((TSFlags & SIInstrFlags::VOP3) && 2669296417Sdim (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) && 2670296417Sdim getForcedEncodingSize() != 64) 2671296417Sdim return Match_PreferE32; 2672296417Sdim 2673314564Sdim if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi || 2674314564Sdim Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) { 2675314564Sdim // v_mac_f32/16 allow only dst_sel == DWORD; 2676314564Sdim auto OpNum = 2677314564Sdim AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel); 2678314564Sdim const auto &Op = Inst.getOperand(OpNum); 2679314564Sdim if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) { 2680314564Sdim return Match_InvalidOperand; 2681314564Sdim } 2682314564Sdim } 2683314564Sdim 2684284677Sdim return Match_Success; 2685284677Sdim} 2686284677Sdim 2687314564Sdim// What asm variants we should check 2688314564SdimArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const { 2689314564Sdim if (getForcedEncodingSize() == 32) { 2690314564Sdim static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT}; 2691314564Sdim return makeArrayRef(Variants); 2692314564Sdim } 2693314564Sdim 2694314564Sdim if (isForcedVOP3()) { 2695314564Sdim static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3}; 2696314564Sdim return makeArrayRef(Variants); 2697314564Sdim } 2698314564Sdim 2699314564Sdim if (isForcedSDWA()) { 2700321369Sdim static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA, 2701321369Sdim AMDGPUAsmVariants::SDWA9}; 2702314564Sdim return makeArrayRef(Variants); 2703314564Sdim } 2704314564Sdim 2705314564Sdim if (isForcedDPP()) { 2706314564Sdim static const unsigned Variants[] = {AMDGPUAsmVariants::DPP}; 2707314564Sdim return makeArrayRef(Variants); 2708314564Sdim } 2709314564Sdim 2710314564Sdim static const unsigned Variants[] = { 2711314564Sdim AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3, 2712321369Sdim AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP 2713314564Sdim }; 2714314564Sdim 2715314564Sdim return makeArrayRef(Variants); 2716314564Sdim} 2717314564Sdim 2718321369Sdimunsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const { 2719321369Sdim const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2720321369Sdim const unsigned Num = Desc.getNumImplicitUses(); 2721321369Sdim for (unsigned i = 0; i < Num; ++i) { 2722321369Sdim unsigned Reg = Desc.ImplicitUses[i]; 2723321369Sdim switch (Reg) { 2724321369Sdim case AMDGPU::FLAT_SCR: 2725321369Sdim case AMDGPU::VCC: 2726353358Sdim case AMDGPU::VCC_LO: 2727353358Sdim case AMDGPU::VCC_HI: 2728321369Sdim case AMDGPU::M0: 2729321369Sdim return Reg; 2730321369Sdim default: 2731321369Sdim break; 2732321369Sdim } 2733321369Sdim } 2734321369Sdim return AMDGPU::NoRegister; 2735321369Sdim} 2736321369Sdim 2737321369Sdim// NB: This code is correct only when used to check constant 2738321369Sdim// bus limitations because GFX7 support no f16 inline constants. 2739321369Sdim// Note that there are no cases when a GFX7 opcode violates 2740321369Sdim// constant bus limitations due to the use of an f16 constant. 2741321369Sdimbool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst, 2742321369Sdim unsigned OpIdx) const { 2743321369Sdim const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2744321369Sdim 2745321369Sdim if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) { 2746321369Sdim return false; 2747321369Sdim } 2748321369Sdim 2749321369Sdim const MCOperand &MO = Inst.getOperand(OpIdx); 2750321369Sdim 2751321369Sdim int64_t Val = MO.getImm(); 2752321369Sdim auto OpSize = AMDGPU::getOperandSize(Desc, OpIdx); 2753321369Sdim 2754321369Sdim switch (OpSize) { // expected operand size 2755321369Sdim case 8: 2756321369Sdim return AMDGPU::isInlinableLiteral64(Val, hasInv2PiInlineImm()); 2757321369Sdim case 4: 2758321369Sdim return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm()); 2759321369Sdim case 2: { 2760321369Sdim const unsigned OperandType = Desc.OpInfo[OpIdx].OperandType; 2761321369Sdim if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 || 2762353358Sdim OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16 || 2763353358Sdim OperandType == AMDGPU::OPERAND_REG_INLINE_AC_V2INT16 || 2764353358Sdim OperandType == AMDGPU::OPERAND_REG_INLINE_AC_V2FP16 || 2765353358Sdim OperandType == AMDGPU::OPERAND_REG_IMM_V2INT16 || 2766353358Sdim OperandType == AMDGPU::OPERAND_REG_IMM_V2FP16) { 2767321369Sdim return AMDGPU::isInlinableLiteralV216(Val, hasInv2PiInlineImm()); 2768321369Sdim } else { 2769321369Sdim return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm()); 2770321369Sdim } 2771321369Sdim } 2772321369Sdim default: 2773321369Sdim llvm_unreachable("invalid operand size"); 2774321369Sdim } 2775321369Sdim} 2776321369Sdim 2777360784Sdimunsigned AMDGPUAsmParser::getConstantBusLimit(unsigned Opcode) const { 2778360784Sdim if (!isGFX10()) 2779360784Sdim return 1; 2780360784Sdim 2781360784Sdim switch (Opcode) { 2782360784Sdim // 64-bit shift instructions can use only one scalar value input 2783360784Sdim case AMDGPU::V_LSHLREV_B64: 2784360784Sdim case AMDGPU::V_LSHLREV_B64_gfx10: 2785360784Sdim case AMDGPU::V_LSHL_B64: 2786360784Sdim case AMDGPU::V_LSHRREV_B64: 2787360784Sdim case AMDGPU::V_LSHRREV_B64_gfx10: 2788360784Sdim case AMDGPU::V_LSHR_B64: 2789360784Sdim case AMDGPU::V_ASHRREV_I64: 2790360784Sdim case AMDGPU::V_ASHRREV_I64_gfx10: 2791360784Sdim case AMDGPU::V_ASHR_I64: 2792360784Sdim return 1; 2793360784Sdim default: 2794360784Sdim return 2; 2795360784Sdim } 2796360784Sdim} 2797360784Sdim 2798321369Sdimbool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) { 2799321369Sdim const MCOperand &MO = Inst.getOperand(OpIdx); 2800321369Sdim if (MO.isImm()) { 2801321369Sdim return !isInlineConstant(Inst, OpIdx); 2802360784Sdim } else if (MO.isReg()) { 2803360784Sdim auto Reg = MO.getReg(); 2804360784Sdim const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 2805360784Sdim return isSGPR(mc2PseudoReg(Reg), TRI) && Reg != SGPR_NULL; 2806360784Sdim } else { 2807360784Sdim return true; 2808321369Sdim } 2809321369Sdim} 2810321369Sdim 2811321369Sdimbool AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst) { 2812321369Sdim const unsigned Opcode = Inst.getOpcode(); 2813321369Sdim const MCInstrDesc &Desc = MII.get(Opcode); 2814321369Sdim unsigned ConstantBusUseCount = 0; 2815353358Sdim unsigned NumLiterals = 0; 2816353358Sdim unsigned LiteralSize; 2817321369Sdim 2818321369Sdim if (Desc.TSFlags & 2819321369Sdim (SIInstrFlags::VOPC | 2820321369Sdim SIInstrFlags::VOP1 | SIInstrFlags::VOP2 | 2821321369Sdim SIInstrFlags::VOP3 | SIInstrFlags::VOP3P | 2822321369Sdim SIInstrFlags::SDWA)) { 2823321369Sdim // Check special imm operands (used by madmk, etc) 2824321369Sdim if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) { 2825321369Sdim ++ConstantBusUseCount; 2826321369Sdim } 2827321369Sdim 2828353358Sdim SmallDenseSet<unsigned> SGPRsUsed; 2829321369Sdim unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst); 2830321369Sdim if (SGPRUsed != AMDGPU::NoRegister) { 2831353358Sdim SGPRsUsed.insert(SGPRUsed); 2832321369Sdim ++ConstantBusUseCount; 2833321369Sdim } 2834321369Sdim 2835321369Sdim const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); 2836321369Sdim const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); 2837321369Sdim const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2); 2838321369Sdim 2839321369Sdim const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx }; 2840321369Sdim 2841321369Sdim for (int OpIdx : OpIndices) { 2842321369Sdim if (OpIdx == -1) break; 2843321369Sdim 2844321369Sdim const MCOperand &MO = Inst.getOperand(OpIdx); 2845321369Sdim if (usesConstantBus(Inst, OpIdx)) { 2846321369Sdim if (MO.isReg()) { 2847321369Sdim const unsigned Reg = mc2PseudoReg(MO.getReg()); 2848321369Sdim // Pairs of registers with a partial intersections like these 2849321369Sdim // s0, s[0:1] 2850321369Sdim // flat_scratch_lo, flat_scratch 2851321369Sdim // flat_scratch_lo, flat_scratch_hi 2852321369Sdim // are theoretically valid but they are disabled anyway. 2853321369Sdim // Note that this code mimics SIInstrInfo::verifyInstruction 2854353358Sdim if (!SGPRsUsed.count(Reg)) { 2855353358Sdim SGPRsUsed.insert(Reg); 2856321369Sdim ++ConstantBusUseCount; 2857321369Sdim } 2858321369Sdim } else { // Expression or a literal 2859353358Sdim 2860353358Sdim if (Desc.OpInfo[OpIdx].OperandType == MCOI::OPERAND_IMMEDIATE) 2861353358Sdim continue; // special operand like VINTERP attr_chan 2862353358Sdim 2863353358Sdim // An instruction may use only one literal. 2864353358Sdim // This has been validated on the previous step. 2865353358Sdim // See validateVOP3Literal. 2866353358Sdim // This literal may be used as more than one operand. 2867353358Sdim // If all these operands are of the same size, 2868353358Sdim // this literal counts as one scalar value. 2869353358Sdim // Otherwise it counts as 2 scalar values. 2870353358Sdim // See "GFX10 Shader Programming", section 3.6.2.3. 2871353358Sdim 2872353358Sdim unsigned Size = AMDGPU::getOperandSize(Desc, OpIdx); 2873353358Sdim if (Size < 4) Size = 4; 2874353358Sdim 2875353358Sdim if (NumLiterals == 0) { 2876353358Sdim NumLiterals = 1; 2877353358Sdim LiteralSize = Size; 2878353358Sdim } else if (LiteralSize != Size) { 2879353358Sdim NumLiterals = 2; 2880353358Sdim } 2881321369Sdim } 2882321369Sdim } 2883321369Sdim } 2884321369Sdim } 2885353358Sdim ConstantBusUseCount += NumLiterals; 2886321369Sdim 2887360784Sdim return ConstantBusUseCount <= getConstantBusLimit(Opcode); 2888321369Sdim} 2889321369Sdim 2890321369Sdimbool AMDGPUAsmParser::validateEarlyClobberLimitations(const MCInst &Inst) { 2891321369Sdim const unsigned Opcode = Inst.getOpcode(); 2892321369Sdim const MCInstrDesc &Desc = MII.get(Opcode); 2893321369Sdim 2894321369Sdim const int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst); 2895321369Sdim if (DstIdx == -1 || 2896321369Sdim Desc.getOperandConstraint(DstIdx, MCOI::EARLY_CLOBBER) == -1) { 2897321369Sdim return true; 2898321369Sdim } 2899321369Sdim 2900321369Sdim const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 2901321369Sdim 2902321369Sdim const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); 2903321369Sdim const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); 2904321369Sdim const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2); 2905321369Sdim 2906321369Sdim assert(DstIdx != -1); 2907321369Sdim const MCOperand &Dst = Inst.getOperand(DstIdx); 2908321369Sdim assert(Dst.isReg()); 2909321369Sdim const unsigned DstReg = mc2PseudoReg(Dst.getReg()); 2910321369Sdim 2911321369Sdim const int SrcIndices[] = { Src0Idx, Src1Idx, Src2Idx }; 2912321369Sdim 2913321369Sdim for (int SrcIdx : SrcIndices) { 2914321369Sdim if (SrcIdx == -1) break; 2915321369Sdim const MCOperand &Src = Inst.getOperand(SrcIdx); 2916321369Sdim if (Src.isReg()) { 2917321369Sdim const unsigned SrcReg = mc2PseudoReg(Src.getReg()); 2918321369Sdim if (isRegIntersect(DstReg, SrcReg, TRI)) { 2919321369Sdim return false; 2920321369Sdim } 2921321369Sdim } 2922321369Sdim } 2923321369Sdim 2924321369Sdim return true; 2925321369Sdim} 2926321369Sdim 2927327952Sdimbool AMDGPUAsmParser::validateIntClampSupported(const MCInst &Inst) { 2928327952Sdim 2929327952Sdim const unsigned Opc = Inst.getOpcode(); 2930327952Sdim const MCInstrDesc &Desc = MII.get(Opc); 2931327952Sdim 2932327952Sdim if ((Desc.TSFlags & SIInstrFlags::IntClamp) != 0 && !hasIntClamp()) { 2933327952Sdim int ClampIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp); 2934327952Sdim assert(ClampIdx != -1); 2935327952Sdim return Inst.getOperand(ClampIdx).getImm() == 0; 2936327952Sdim } 2937327952Sdim 2938327952Sdim return true; 2939327952Sdim} 2940327952Sdim 2941341825Sdimbool AMDGPUAsmParser::validateMIMGDataSize(const MCInst &Inst) { 2942341825Sdim 2943341825Sdim const unsigned Opc = Inst.getOpcode(); 2944341825Sdim const MCInstrDesc &Desc = MII.get(Opc); 2945341825Sdim 2946341825Sdim if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0) 2947341825Sdim return true; 2948341825Sdim 2949341825Sdim int VDataIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata); 2950341825Sdim int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask); 2951341825Sdim int TFEIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::tfe); 2952341825Sdim 2953341825Sdim assert(VDataIdx != -1); 2954341825Sdim assert(DMaskIdx != -1); 2955341825Sdim assert(TFEIdx != -1); 2956341825Sdim 2957341825Sdim unsigned VDataSize = AMDGPU::getRegOperandSize(getMRI(), Desc, VDataIdx); 2958341825Sdim unsigned TFESize = Inst.getOperand(TFEIdx).getImm()? 1 : 0; 2959341825Sdim unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf; 2960341825Sdim if (DMask == 0) 2961341825Sdim DMask = 1; 2962341825Sdim 2963341825Sdim unsigned DataSize = 2964341825Sdim (Desc.TSFlags & SIInstrFlags::Gather4) ? 4 : countPopulation(DMask); 2965341825Sdim if (hasPackedD16()) { 2966341825Sdim int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16); 2967341825Sdim if (D16Idx >= 0 && Inst.getOperand(D16Idx).getImm()) 2968341825Sdim DataSize = (DataSize + 1) / 2; 2969341825Sdim } 2970341825Sdim 2971341825Sdim return (VDataSize / 4) == DataSize + TFESize; 2972341825Sdim} 2973341825Sdim 2974353358Sdimbool AMDGPUAsmParser::validateMIMGAddrSize(const MCInst &Inst) { 2975353358Sdim const unsigned Opc = Inst.getOpcode(); 2976353358Sdim const MCInstrDesc &Desc = MII.get(Opc); 2977353358Sdim 2978353358Sdim if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0 || !isGFX10()) 2979353358Sdim return true; 2980353358Sdim 2981353358Sdim const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opc); 2982353358Sdim const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode = 2983353358Sdim AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode); 2984353358Sdim int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0); 2985353358Sdim int SrsrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc); 2986353358Sdim int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim); 2987353358Sdim 2988353358Sdim assert(VAddr0Idx != -1); 2989353358Sdim assert(SrsrcIdx != -1); 2990353358Sdim assert(DimIdx != -1); 2991353358Sdim assert(SrsrcIdx > VAddr0Idx); 2992353358Sdim 2993353358Sdim unsigned Dim = Inst.getOperand(DimIdx).getImm(); 2994353358Sdim const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByEncoding(Dim); 2995353358Sdim bool IsNSA = SrsrcIdx - VAddr0Idx > 1; 2996353358Sdim unsigned VAddrSize = 2997353358Sdim IsNSA ? SrsrcIdx - VAddr0Idx 2998353358Sdim : AMDGPU::getRegOperandSize(getMRI(), Desc, VAddr0Idx) / 4; 2999353358Sdim 3000353358Sdim unsigned AddrSize = BaseOpcode->NumExtraArgs + 3001353358Sdim (BaseOpcode->Gradients ? DimInfo->NumGradients : 0) + 3002353358Sdim (BaseOpcode->Coordinates ? DimInfo->NumCoords : 0) + 3003353358Sdim (BaseOpcode->LodOrClampOrMip ? 1 : 0); 3004353358Sdim if (!IsNSA) { 3005353358Sdim if (AddrSize > 8) 3006353358Sdim AddrSize = 16; 3007353358Sdim else if (AddrSize > 4) 3008353358Sdim AddrSize = 8; 3009353358Sdim } 3010353358Sdim 3011353358Sdim return VAddrSize == AddrSize; 3012353358Sdim} 3013353358Sdim 3014341825Sdimbool AMDGPUAsmParser::validateMIMGAtomicDMask(const MCInst &Inst) { 3015341825Sdim 3016341825Sdim const unsigned Opc = Inst.getOpcode(); 3017341825Sdim const MCInstrDesc &Desc = MII.get(Opc); 3018341825Sdim 3019341825Sdim if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0) 3020341825Sdim return true; 3021341825Sdim if (!Desc.mayLoad() || !Desc.mayStore()) 3022341825Sdim return true; // Not atomic 3023341825Sdim 3024341825Sdim int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask); 3025341825Sdim unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf; 3026341825Sdim 3027341825Sdim // This is an incomplete check because image_atomic_cmpswap 3028341825Sdim // may only use 0x3 and 0xf while other atomic operations 3029341825Sdim // may use 0x1 and 0x3. However these limitations are 3030341825Sdim // verified when we check that dmask matches dst size. 3031341825Sdim return DMask == 0x1 || DMask == 0x3 || DMask == 0xf; 3032341825Sdim} 3033341825Sdim 3034341825Sdimbool AMDGPUAsmParser::validateMIMGGatherDMask(const MCInst &Inst) { 3035341825Sdim 3036341825Sdim const unsigned Opc = Inst.getOpcode(); 3037341825Sdim const MCInstrDesc &Desc = MII.get(Opc); 3038341825Sdim 3039341825Sdim if ((Desc.TSFlags & SIInstrFlags::Gather4) == 0) 3040341825Sdim return true; 3041341825Sdim 3042341825Sdim int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask); 3043341825Sdim unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf; 3044341825Sdim 3045341825Sdim // GATHER4 instructions use dmask in a different fashion compared to 3046341825Sdim // other MIMG instructions. The only useful DMASK values are 3047341825Sdim // 1=red, 2=green, 4=blue, 8=alpha. (e.g. 1 returns 3048341825Sdim // (red,red,red,red) etc.) The ISA document doesn't mention 3049341825Sdim // this. 3050341825Sdim return DMask == 0x1 || DMask == 0x2 || DMask == 0x4 || DMask == 0x8; 3051341825Sdim} 3052341825Sdim 3053360784Sdimstatic bool IsMovrelsSDWAOpcode(const unsigned Opcode) 3054360784Sdim{ 3055360784Sdim switch (Opcode) { 3056360784Sdim case AMDGPU::V_MOVRELS_B32_sdwa_gfx10: 3057360784Sdim case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10: 3058360784Sdim case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10: 3059360784Sdim return true; 3060360784Sdim default: 3061360784Sdim return false; 3062360784Sdim } 3063360784Sdim} 3064360784Sdim 3065360784Sdim// movrels* opcodes should only allow VGPRS as src0. 3066360784Sdim// This is specified in .td description for vop1/vop3, 3067360784Sdim// but sdwa is handled differently. See isSDWAOperand. 3068360784Sdimbool AMDGPUAsmParser::validateMovrels(const MCInst &Inst) { 3069360784Sdim 3070360784Sdim const unsigned Opc = Inst.getOpcode(); 3071360784Sdim const MCInstrDesc &Desc = MII.get(Opc); 3072360784Sdim 3073360784Sdim if ((Desc.TSFlags & SIInstrFlags::SDWA) == 0 || !IsMovrelsSDWAOpcode(Opc)) 3074360784Sdim return true; 3075360784Sdim 3076360784Sdim const int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0); 3077360784Sdim assert(Src0Idx != -1); 3078360784Sdim 3079360784Sdim const MCOperand &Src0 = Inst.getOperand(Src0Idx); 3080360784Sdim if (!Src0.isReg()) 3081360784Sdim return false; 3082360784Sdim 3083360784Sdim auto Reg = Src0.getReg(); 3084360784Sdim const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 3085360784Sdim return !isSGPR(mc2PseudoReg(Reg), TRI); 3086360784Sdim} 3087360784Sdim 3088341825Sdimbool AMDGPUAsmParser::validateMIMGD16(const MCInst &Inst) { 3089341825Sdim 3090341825Sdim const unsigned Opc = Inst.getOpcode(); 3091341825Sdim const MCInstrDesc &Desc = MII.get(Opc); 3092341825Sdim 3093341825Sdim if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0) 3094341825Sdim return true; 3095341825Sdim 3096341825Sdim int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16); 3097341825Sdim if (D16Idx >= 0 && Inst.getOperand(D16Idx).getImm()) { 3098341825Sdim if (isCI() || isSI()) 3099341825Sdim return false; 3100341825Sdim } 3101341825Sdim 3102341825Sdim return true; 3103341825Sdim} 3104341825Sdim 3105353358Sdimbool AMDGPUAsmParser::validateMIMGDim(const MCInst &Inst) { 3106353358Sdim const unsigned Opc = Inst.getOpcode(); 3107353358Sdim const MCInstrDesc &Desc = MII.get(Opc); 3108353358Sdim 3109353358Sdim if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0) 3110353358Sdim return true; 3111353358Sdim 3112353358Sdim int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim); 3113353358Sdim if (DimIdx < 0) 3114353358Sdim return true; 3115353358Sdim 3116353358Sdim long Imm = Inst.getOperand(DimIdx).getImm(); 3117353358Sdim if (Imm < 0 || Imm >= 8) 3118353358Sdim return false; 3119353358Sdim 3120353358Sdim return true; 3121353358Sdim} 3122353358Sdim 3123353358Sdimstatic bool IsRevOpcode(const unsigned Opcode) 3124353358Sdim{ 3125353358Sdim switch (Opcode) { 3126353358Sdim case AMDGPU::V_SUBREV_F32_e32: 3127353358Sdim case AMDGPU::V_SUBREV_F32_e64: 3128353358Sdim case AMDGPU::V_SUBREV_F32_e32_gfx10: 3129353358Sdim case AMDGPU::V_SUBREV_F32_e32_gfx6_gfx7: 3130353358Sdim case AMDGPU::V_SUBREV_F32_e32_vi: 3131353358Sdim case AMDGPU::V_SUBREV_F32_e64_gfx10: 3132353358Sdim case AMDGPU::V_SUBREV_F32_e64_gfx6_gfx7: 3133353358Sdim case AMDGPU::V_SUBREV_F32_e64_vi: 3134353358Sdim 3135353358Sdim case AMDGPU::V_SUBREV_I32_e32: 3136353358Sdim case AMDGPU::V_SUBREV_I32_e64: 3137353358Sdim case AMDGPU::V_SUBREV_I32_e32_gfx6_gfx7: 3138353358Sdim case AMDGPU::V_SUBREV_I32_e64_gfx6_gfx7: 3139353358Sdim 3140353358Sdim case AMDGPU::V_SUBBREV_U32_e32: 3141353358Sdim case AMDGPU::V_SUBBREV_U32_e64: 3142353358Sdim case AMDGPU::V_SUBBREV_U32_e32_gfx6_gfx7: 3143353358Sdim case AMDGPU::V_SUBBREV_U32_e32_vi: 3144353358Sdim case AMDGPU::V_SUBBREV_U32_e64_gfx6_gfx7: 3145353358Sdim case AMDGPU::V_SUBBREV_U32_e64_vi: 3146353358Sdim 3147353358Sdim case AMDGPU::V_SUBREV_U32_e32: 3148353358Sdim case AMDGPU::V_SUBREV_U32_e64: 3149353358Sdim case AMDGPU::V_SUBREV_U32_e32_gfx9: 3150353358Sdim case AMDGPU::V_SUBREV_U32_e32_vi: 3151353358Sdim case AMDGPU::V_SUBREV_U32_e64_gfx9: 3152353358Sdim case AMDGPU::V_SUBREV_U32_e64_vi: 3153353358Sdim 3154353358Sdim case AMDGPU::V_SUBREV_F16_e32: 3155353358Sdim case AMDGPU::V_SUBREV_F16_e64: 3156353358Sdim case AMDGPU::V_SUBREV_F16_e32_gfx10: 3157353358Sdim case AMDGPU::V_SUBREV_F16_e32_vi: 3158353358Sdim case AMDGPU::V_SUBREV_F16_e64_gfx10: 3159353358Sdim case AMDGPU::V_SUBREV_F16_e64_vi: 3160353358Sdim 3161353358Sdim case AMDGPU::V_SUBREV_U16_e32: 3162353358Sdim case AMDGPU::V_SUBREV_U16_e64: 3163353358Sdim case AMDGPU::V_SUBREV_U16_e32_vi: 3164353358Sdim case AMDGPU::V_SUBREV_U16_e64_vi: 3165353358Sdim 3166353358Sdim case AMDGPU::V_SUBREV_CO_U32_e32_gfx9: 3167353358Sdim case AMDGPU::V_SUBREV_CO_U32_e64_gfx10: 3168353358Sdim case AMDGPU::V_SUBREV_CO_U32_e64_gfx9: 3169353358Sdim 3170353358Sdim case AMDGPU::V_SUBBREV_CO_U32_e32_gfx9: 3171353358Sdim case AMDGPU::V_SUBBREV_CO_U32_e64_gfx9: 3172353358Sdim 3173353358Sdim case AMDGPU::V_SUBREV_NC_U32_e32_gfx10: 3174353358Sdim case AMDGPU::V_SUBREV_NC_U32_e64_gfx10: 3175353358Sdim 3176353358Sdim case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx10: 3177353358Sdim case AMDGPU::V_SUBREV_CO_CI_U32_e64_gfx10: 3178353358Sdim 3179353358Sdim case AMDGPU::V_LSHRREV_B32_e32: 3180353358Sdim case AMDGPU::V_LSHRREV_B32_e64: 3181353358Sdim case AMDGPU::V_LSHRREV_B32_e32_gfx6_gfx7: 3182353358Sdim case AMDGPU::V_LSHRREV_B32_e64_gfx6_gfx7: 3183353358Sdim case AMDGPU::V_LSHRREV_B32_e32_vi: 3184353358Sdim case AMDGPU::V_LSHRREV_B32_e64_vi: 3185353358Sdim case AMDGPU::V_LSHRREV_B32_e32_gfx10: 3186353358Sdim case AMDGPU::V_LSHRREV_B32_e64_gfx10: 3187353358Sdim 3188353358Sdim case AMDGPU::V_ASHRREV_I32_e32: 3189353358Sdim case AMDGPU::V_ASHRREV_I32_e64: 3190353358Sdim case AMDGPU::V_ASHRREV_I32_e32_gfx10: 3191353358Sdim case AMDGPU::V_ASHRREV_I32_e32_gfx6_gfx7: 3192353358Sdim case AMDGPU::V_ASHRREV_I32_e32_vi: 3193353358Sdim case AMDGPU::V_ASHRREV_I32_e64_gfx10: 3194353358Sdim case AMDGPU::V_ASHRREV_I32_e64_gfx6_gfx7: 3195353358Sdim case AMDGPU::V_ASHRREV_I32_e64_vi: 3196353358Sdim 3197353358Sdim case AMDGPU::V_LSHLREV_B32_e32: 3198353358Sdim case AMDGPU::V_LSHLREV_B32_e64: 3199353358Sdim case AMDGPU::V_LSHLREV_B32_e32_gfx10: 3200353358Sdim case AMDGPU::V_LSHLREV_B32_e32_gfx6_gfx7: 3201353358Sdim case AMDGPU::V_LSHLREV_B32_e32_vi: 3202353358Sdim case AMDGPU::V_LSHLREV_B32_e64_gfx10: 3203353358Sdim case AMDGPU::V_LSHLREV_B32_e64_gfx6_gfx7: 3204353358Sdim case AMDGPU::V_LSHLREV_B32_e64_vi: 3205353358Sdim 3206353358Sdim case AMDGPU::V_LSHLREV_B16_e32: 3207353358Sdim case AMDGPU::V_LSHLREV_B16_e64: 3208353358Sdim case AMDGPU::V_LSHLREV_B16_e32_vi: 3209353358Sdim case AMDGPU::V_LSHLREV_B16_e64_vi: 3210353358Sdim case AMDGPU::V_LSHLREV_B16_gfx10: 3211353358Sdim 3212353358Sdim case AMDGPU::V_LSHRREV_B16_e32: 3213353358Sdim case AMDGPU::V_LSHRREV_B16_e64: 3214353358Sdim case AMDGPU::V_LSHRREV_B16_e32_vi: 3215353358Sdim case AMDGPU::V_LSHRREV_B16_e64_vi: 3216353358Sdim case AMDGPU::V_LSHRREV_B16_gfx10: 3217353358Sdim 3218353358Sdim case AMDGPU::V_ASHRREV_I16_e32: 3219353358Sdim case AMDGPU::V_ASHRREV_I16_e64: 3220353358Sdim case AMDGPU::V_ASHRREV_I16_e32_vi: 3221353358Sdim case AMDGPU::V_ASHRREV_I16_e64_vi: 3222353358Sdim case AMDGPU::V_ASHRREV_I16_gfx10: 3223353358Sdim 3224353358Sdim case AMDGPU::V_LSHLREV_B64: 3225353358Sdim case AMDGPU::V_LSHLREV_B64_gfx10: 3226353358Sdim case AMDGPU::V_LSHLREV_B64_vi: 3227353358Sdim 3228353358Sdim case AMDGPU::V_LSHRREV_B64: 3229353358Sdim case AMDGPU::V_LSHRREV_B64_gfx10: 3230353358Sdim case AMDGPU::V_LSHRREV_B64_vi: 3231353358Sdim 3232353358Sdim case AMDGPU::V_ASHRREV_I64: 3233353358Sdim case AMDGPU::V_ASHRREV_I64_gfx10: 3234353358Sdim case AMDGPU::V_ASHRREV_I64_vi: 3235353358Sdim 3236353358Sdim case AMDGPU::V_PK_LSHLREV_B16: 3237353358Sdim case AMDGPU::V_PK_LSHLREV_B16_gfx10: 3238353358Sdim case AMDGPU::V_PK_LSHLREV_B16_vi: 3239353358Sdim 3240353358Sdim case AMDGPU::V_PK_LSHRREV_B16: 3241353358Sdim case AMDGPU::V_PK_LSHRREV_B16_gfx10: 3242353358Sdim case AMDGPU::V_PK_LSHRREV_B16_vi: 3243353358Sdim case AMDGPU::V_PK_ASHRREV_I16: 3244353358Sdim case AMDGPU::V_PK_ASHRREV_I16_gfx10: 3245353358Sdim case AMDGPU::V_PK_ASHRREV_I16_vi: 3246353358Sdim return true; 3247353358Sdim default: 3248353358Sdim return false; 3249353358Sdim } 3250353358Sdim} 3251353358Sdim 3252353358Sdimbool AMDGPUAsmParser::validateLdsDirect(const MCInst &Inst) { 3253353358Sdim 3254353358Sdim using namespace SIInstrFlags; 3255353358Sdim const unsigned Opcode = Inst.getOpcode(); 3256353358Sdim const MCInstrDesc &Desc = MII.get(Opcode); 3257353358Sdim 3258353358Sdim // lds_direct register is defined so that it can be used 3259353358Sdim // with 9-bit operands only. Ignore encodings which do not accept these. 3260353358Sdim if ((Desc.TSFlags & (VOP1 | VOP2 | VOP3 | VOPC | VOP3P | SIInstrFlags::SDWA)) == 0) 3261353358Sdim return true; 3262353358Sdim 3263353358Sdim const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); 3264353358Sdim const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); 3265353358Sdim const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2); 3266353358Sdim 3267353358Sdim const int SrcIndices[] = { Src1Idx, Src2Idx }; 3268353358Sdim 3269353358Sdim // lds_direct cannot be specified as either src1 or src2. 3270353358Sdim for (int SrcIdx : SrcIndices) { 3271353358Sdim if (SrcIdx == -1) break; 3272353358Sdim const MCOperand &Src = Inst.getOperand(SrcIdx); 3273353358Sdim if (Src.isReg() && Src.getReg() == LDS_DIRECT) { 3274353358Sdim return false; 3275353358Sdim } 3276353358Sdim } 3277353358Sdim 3278353358Sdim if (Src0Idx == -1) 3279353358Sdim return true; 3280353358Sdim 3281353358Sdim const MCOperand &Src = Inst.getOperand(Src0Idx); 3282353358Sdim if (!Src.isReg() || Src.getReg() != LDS_DIRECT) 3283353358Sdim return true; 3284353358Sdim 3285353358Sdim // lds_direct is specified as src0. Check additional limitations. 3286353358Sdim return (Desc.TSFlags & SIInstrFlags::SDWA) == 0 && !IsRevOpcode(Opcode); 3287353358Sdim} 3288353358Sdim 3289353358SdimSMLoc AMDGPUAsmParser::getFlatOffsetLoc(const OperandVector &Operands) const { 3290353358Sdim for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 3291353358Sdim AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 3292353358Sdim if (Op.isFlatOffset()) 3293353358Sdim return Op.getStartLoc(); 3294353358Sdim } 3295353358Sdim return getLoc(); 3296353358Sdim} 3297353358Sdim 3298353358Sdimbool AMDGPUAsmParser::validateFlatOffset(const MCInst &Inst, 3299353358Sdim const OperandVector &Operands) { 3300353358Sdim uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 3301353358Sdim if ((TSFlags & SIInstrFlags::FLAT) == 0) 3302353358Sdim return true; 3303353358Sdim 3304353358Sdim auto Opcode = Inst.getOpcode(); 3305353358Sdim auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset); 3306353358Sdim assert(OpNum != -1); 3307353358Sdim 3308353358Sdim const auto &Op = Inst.getOperand(OpNum); 3309353358Sdim if (!hasFlatOffsets() && Op.getImm() != 0) { 3310353358Sdim Error(getFlatOffsetLoc(Operands), 3311353358Sdim "flat offset modifier is not supported on this GPU"); 3312353358Sdim return false; 3313353358Sdim } 3314353358Sdim 3315353358Sdim // Address offset is 12-bit signed for GFX10, 13-bit for GFX9. 3316353358Sdim // For FLAT segment the offset must be positive; 3317353358Sdim // MSB is ignored and forced to zero. 3318353358Sdim unsigned OffsetSize = isGFX9() ? 13 : 12; 3319353358Sdim if (TSFlags & SIInstrFlags::IsNonFlatSeg) { 3320353358Sdim if (!isIntN(OffsetSize, Op.getImm())) { 3321353358Sdim Error(getFlatOffsetLoc(Operands), 3322353358Sdim isGFX9() ? "expected a 13-bit signed offset" : 3323353358Sdim "expected a 12-bit signed offset"); 3324353358Sdim return false; 3325353358Sdim } 3326353358Sdim } else { 3327353358Sdim if (!isUIntN(OffsetSize - 1, Op.getImm())) { 3328353358Sdim Error(getFlatOffsetLoc(Operands), 3329353358Sdim isGFX9() ? "expected a 12-bit unsigned offset" : 3330353358Sdim "expected an 11-bit unsigned offset"); 3331353358Sdim return false; 3332353358Sdim } 3333353358Sdim } 3334353358Sdim 3335353358Sdim return true; 3336353358Sdim} 3337353358Sdim 3338353358Sdimbool AMDGPUAsmParser::validateSOPLiteral(const MCInst &Inst) const { 3339353358Sdim unsigned Opcode = Inst.getOpcode(); 3340353358Sdim const MCInstrDesc &Desc = MII.get(Opcode); 3341353358Sdim if (!(Desc.TSFlags & (SIInstrFlags::SOP2 | SIInstrFlags::SOPC))) 3342353358Sdim return true; 3343353358Sdim 3344353358Sdim const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); 3345353358Sdim const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); 3346353358Sdim 3347353358Sdim const int OpIndices[] = { Src0Idx, Src1Idx }; 3348353358Sdim 3349360784Sdim unsigned NumExprs = 0; 3350353358Sdim unsigned NumLiterals = 0; 3351353358Sdim uint32_t LiteralValue; 3352353358Sdim 3353353358Sdim for (int OpIdx : OpIndices) { 3354353358Sdim if (OpIdx == -1) break; 3355353358Sdim 3356353358Sdim const MCOperand &MO = Inst.getOperand(OpIdx); 3357360784Sdim // Exclude special imm operands (like that used by s_set_gpr_idx_on) 3358360784Sdim if (AMDGPU::isSISrcOperand(Desc, OpIdx)) { 3359360784Sdim if (MO.isImm() && !isInlineConstant(Inst, OpIdx)) { 3360360784Sdim uint32_t Value = static_cast<uint32_t>(MO.getImm()); 3361360784Sdim if (NumLiterals == 0 || LiteralValue != Value) { 3362360784Sdim LiteralValue = Value; 3363360784Sdim ++NumLiterals; 3364360784Sdim } 3365360784Sdim } else if (MO.isExpr()) { 3366360784Sdim ++NumExprs; 3367353358Sdim } 3368353358Sdim } 3369353358Sdim } 3370353358Sdim 3371360784Sdim return NumLiterals + NumExprs <= 1; 3372353358Sdim} 3373353358Sdim 3374353358Sdimbool AMDGPUAsmParser::validateOpSel(const MCInst &Inst) { 3375353358Sdim const unsigned Opc = Inst.getOpcode(); 3376353358Sdim if (Opc == AMDGPU::V_PERMLANE16_B32_gfx10 || 3377353358Sdim Opc == AMDGPU::V_PERMLANEX16_B32_gfx10) { 3378353358Sdim int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel); 3379353358Sdim unsigned OpSel = Inst.getOperand(OpSelIdx).getImm(); 3380353358Sdim 3381353358Sdim if (OpSel & ~3) 3382353358Sdim return false; 3383353358Sdim } 3384353358Sdim return true; 3385353358Sdim} 3386353358Sdim 3387353358Sdim// Check if VCC register matches wavefront size 3388353358Sdimbool AMDGPUAsmParser::validateVccOperand(unsigned Reg) const { 3389353358Sdim auto FB = getFeatureBits(); 3390353358Sdim return (FB[AMDGPU::FeatureWavefrontSize64] && Reg == AMDGPU::VCC) || 3391353358Sdim (FB[AMDGPU::FeatureWavefrontSize32] && Reg == AMDGPU::VCC_LO); 3392353358Sdim} 3393353358Sdim 3394353358Sdim// VOP3 literal is only allowed in GFX10+ and only one can be used 3395353358Sdimbool AMDGPUAsmParser::validateVOP3Literal(const MCInst &Inst) const { 3396353358Sdim unsigned Opcode = Inst.getOpcode(); 3397353358Sdim const MCInstrDesc &Desc = MII.get(Opcode); 3398353358Sdim if (!(Desc.TSFlags & (SIInstrFlags::VOP3 | SIInstrFlags::VOP3P))) 3399353358Sdim return true; 3400353358Sdim 3401353358Sdim const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); 3402353358Sdim const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); 3403353358Sdim const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2); 3404353358Sdim 3405353358Sdim const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx }; 3406353358Sdim 3407360784Sdim unsigned NumExprs = 0; 3408353358Sdim unsigned NumLiterals = 0; 3409353358Sdim uint32_t LiteralValue; 3410353358Sdim 3411353358Sdim for (int OpIdx : OpIndices) { 3412353358Sdim if (OpIdx == -1) break; 3413353358Sdim 3414353358Sdim const MCOperand &MO = Inst.getOperand(OpIdx); 3415360784Sdim if (!MO.isImm() && !MO.isExpr()) 3416353358Sdim continue; 3417360784Sdim if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) 3418360784Sdim continue; 3419353358Sdim 3420360784Sdim if (OpIdx == Src2Idx && (Desc.TSFlags & SIInstrFlags::IsMAI) && 3421360784Sdim getFeatureBits()[AMDGPU::FeatureMFMAInlineLiteralBug]) 3422360784Sdim return false; 3423360784Sdim 3424360784Sdim if (MO.isImm() && !isInlineConstant(Inst, OpIdx)) { 3425353358Sdim uint32_t Value = static_cast<uint32_t>(MO.getImm()); 3426353358Sdim if (NumLiterals == 0 || LiteralValue != Value) { 3427353358Sdim LiteralValue = Value; 3428353358Sdim ++NumLiterals; 3429353358Sdim } 3430360784Sdim } else if (MO.isExpr()) { 3431360784Sdim ++NumExprs; 3432353358Sdim } 3433353358Sdim } 3434360784Sdim NumLiterals += NumExprs; 3435353358Sdim 3436353358Sdim return !NumLiterals || 3437353358Sdim (NumLiterals == 1 && getFeatureBits()[AMDGPU::FeatureVOP3Literal]); 3438353358Sdim} 3439353358Sdim 3440321369Sdimbool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, 3441353358Sdim const SMLoc &IDLoc, 3442353358Sdim const OperandVector &Operands) { 3443353358Sdim if (!validateLdsDirect(Inst)) { 3444353358Sdim Error(IDLoc, 3445353358Sdim "invalid use of lds_direct"); 3446353358Sdim return false; 3447353358Sdim } 3448353358Sdim if (!validateSOPLiteral(Inst)) { 3449353358Sdim Error(IDLoc, 3450353358Sdim "only one literal operand is allowed"); 3451353358Sdim return false; 3452353358Sdim } 3453353358Sdim if (!validateVOP3Literal(Inst)) { 3454353358Sdim Error(IDLoc, 3455353358Sdim "invalid literal operand"); 3456353358Sdim return false; 3457353358Sdim } 3458321369Sdim if (!validateConstantBusLimitations(Inst)) { 3459321369Sdim Error(IDLoc, 3460321369Sdim "invalid operand (violates constant bus restrictions)"); 3461321369Sdim return false; 3462321369Sdim } 3463321369Sdim if (!validateEarlyClobberLimitations(Inst)) { 3464321369Sdim Error(IDLoc, 3465321369Sdim "destination must be different than all sources"); 3466321369Sdim return false; 3467321369Sdim } 3468327952Sdim if (!validateIntClampSupported(Inst)) { 3469327952Sdim Error(IDLoc, 3470327952Sdim "integer clamping is not supported on this GPU"); 3471327952Sdim return false; 3472327952Sdim } 3473353358Sdim if (!validateOpSel(Inst)) { 3474353358Sdim Error(IDLoc, 3475353358Sdim "invalid op_sel operand"); 3476353358Sdim return false; 3477353358Sdim } 3478341825Sdim // For MUBUF/MTBUF d16 is a part of opcode, so there is nothing to validate. 3479341825Sdim if (!validateMIMGD16(Inst)) { 3480341825Sdim Error(IDLoc, 3481341825Sdim "d16 modifier is not supported on this GPU"); 3482341825Sdim return false; 3483341825Sdim } 3484353358Sdim if (!validateMIMGDim(Inst)) { 3485353358Sdim Error(IDLoc, "dim modifier is required on this GPU"); 3486353358Sdim return false; 3487353358Sdim } 3488341825Sdim if (!validateMIMGDataSize(Inst)) { 3489341825Sdim Error(IDLoc, 3490341825Sdim "image data size does not match dmask and tfe"); 3491341825Sdim return false; 3492341825Sdim } 3493353358Sdim if (!validateMIMGAddrSize(Inst)) { 3494353358Sdim Error(IDLoc, 3495353358Sdim "image address size does not match dim and a16"); 3496353358Sdim return false; 3497353358Sdim } 3498341825Sdim if (!validateMIMGAtomicDMask(Inst)) { 3499341825Sdim Error(IDLoc, 3500341825Sdim "invalid atomic image dmask"); 3501341825Sdim return false; 3502341825Sdim } 3503341825Sdim if (!validateMIMGGatherDMask(Inst)) { 3504341825Sdim Error(IDLoc, 3505341825Sdim "invalid image_gather dmask: only one bit must be set"); 3506341825Sdim return false; 3507341825Sdim } 3508360784Sdim if (!validateMovrels(Inst)) { 3509360784Sdim Error(IDLoc, "source operand must be a VGPR"); 3510360784Sdim return false; 3511360784Sdim } 3512353358Sdim if (!validateFlatOffset(Inst, Operands)) { 3513353358Sdim return false; 3514353358Sdim } 3515321369Sdim 3516321369Sdim return true; 3517321369Sdim} 3518321369Sdim 3519353358Sdimstatic std::string AMDGPUMnemonicSpellCheck(StringRef S, 3520353358Sdim const FeatureBitset &FBS, 3521327952Sdim unsigned VariantID = 0); 3522327952Sdim 3523284677Sdimbool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 3524284677Sdim OperandVector &Operands, 3525284677Sdim MCStreamer &Out, 3526284677Sdim uint64_t &ErrorInfo, 3527284677Sdim bool MatchingInlineAsm) { 3528284677Sdim MCInst Inst; 3529314564Sdim unsigned Result = Match_Success; 3530314564Sdim for (auto Variant : getMatchedVariants()) { 3531314564Sdim uint64_t EI; 3532314564Sdim auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm, 3533314564Sdim Variant); 3534314564Sdim // We order match statuses from least to most specific. We use most specific 3535314564Sdim // status as resulting 3536314564Sdim // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32 3537314564Sdim if ((R == Match_Success) || 3538314564Sdim (R == Match_PreferE32) || 3539314564Sdim (R == Match_MissingFeature && Result != Match_PreferE32) || 3540314564Sdim (R == Match_InvalidOperand && Result != Match_MissingFeature 3541314564Sdim && Result != Match_PreferE32) || 3542314564Sdim (R == Match_MnemonicFail && Result != Match_InvalidOperand 3543314564Sdim && Result != Match_MissingFeature 3544314564Sdim && Result != Match_PreferE32)) { 3545314564Sdim Result = R; 3546314564Sdim ErrorInfo = EI; 3547314564Sdim } 3548314564Sdim if (R == Match_Success) 3549314564Sdim break; 3550314564Sdim } 3551284677Sdim 3552314564Sdim switch (Result) { 3553314564Sdim default: break; 3554314564Sdim case Match_Success: 3555353358Sdim if (!validateInstruction(Inst, IDLoc, Operands)) { 3556321369Sdim return true; 3557321369Sdim } 3558314564Sdim Inst.setLoc(IDLoc); 3559314564Sdim Out.EmitInstruction(Inst, getSTI()); 3560314564Sdim return false; 3561284677Sdim 3562314564Sdim case Match_MissingFeature: 3563314564Sdim return Error(IDLoc, "instruction not supported on this GPU"); 3564284677Sdim 3565327952Sdim case Match_MnemonicFail: { 3566353358Sdim FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); 3567327952Sdim std::string Suggestion = AMDGPUMnemonicSpellCheck( 3568327952Sdim ((AMDGPUOperand &)*Operands[0]).getToken(), FBS); 3569327952Sdim return Error(IDLoc, "invalid instruction" + Suggestion, 3570327952Sdim ((AMDGPUOperand &)*Operands[0]).getLocRange()); 3571327952Sdim } 3572314564Sdim 3573314564Sdim case Match_InvalidOperand: { 3574314564Sdim SMLoc ErrorLoc = IDLoc; 3575314564Sdim if (ErrorInfo != ~0ULL) { 3576314564Sdim if (ErrorInfo >= Operands.size()) { 3577314564Sdim return Error(IDLoc, "too few operands for instruction"); 3578284677Sdim } 3579314564Sdim ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc(); 3580314564Sdim if (ErrorLoc == SMLoc()) 3581314564Sdim ErrorLoc = IDLoc; 3582284677Sdim } 3583314564Sdim return Error(ErrorLoc, "invalid operand for instruction"); 3584284677Sdim } 3585314564Sdim 3586314564Sdim case Match_PreferE32: 3587314564Sdim return Error(IDLoc, "internal error: instruction without _e64 suffix " 3588314564Sdim "should be encoded as e32"); 3589314564Sdim } 3590284677Sdim llvm_unreachable("Implement any new match types added!"); 3591284677Sdim} 3592284677Sdim 3593314564Sdimbool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) { 3594314564Sdim int64_t Tmp = -1; 3595314564Sdim if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) { 3596314564Sdim return true; 3597314564Sdim } 3598314564Sdim if (getParser().parseAbsoluteExpression(Tmp)) { 3599314564Sdim return true; 3600314564Sdim } 3601314564Sdim Ret = static_cast<uint32_t>(Tmp); 3602314564Sdim return false; 3603314564Sdim} 3604314564Sdim 3605285181Sdimbool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major, 3606285181Sdim uint32_t &Minor) { 3607314564Sdim if (ParseAsAbsoluteExpression(Major)) 3608285181Sdim return TokError("invalid major version"); 3609285181Sdim 3610285181Sdim if (getLexer().isNot(AsmToken::Comma)) 3611285181Sdim return TokError("minor version number required, comma expected"); 3612285181Sdim Lex(); 3613285181Sdim 3614314564Sdim if (ParseAsAbsoluteExpression(Minor)) 3615285181Sdim return TokError("invalid minor version"); 3616285181Sdim 3617285181Sdim return false; 3618285181Sdim} 3619285181Sdim 3620341825Sdimbool AMDGPUAsmParser::ParseDirectiveAMDGCNTarget() { 3621341825Sdim if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) 3622341825Sdim return TokError("directive only supported for amdgcn architecture"); 3623341825Sdim 3624341825Sdim std::string Target; 3625341825Sdim 3626341825Sdim SMLoc TargetStart = getTok().getLoc(); 3627341825Sdim if (getParser().parseEscapedString(Target)) 3628341825Sdim return true; 3629341825Sdim SMRange TargetRange = SMRange(TargetStart, getTok().getLoc()); 3630341825Sdim 3631341825Sdim std::string ExpectedTarget; 3632341825Sdim raw_string_ostream ExpectedTargetOS(ExpectedTarget); 3633341825Sdim IsaInfo::streamIsaVersion(&getSTI(), ExpectedTargetOS); 3634341825Sdim 3635341825Sdim if (Target != ExpectedTargetOS.str()) 3636341825Sdim return getParser().Error(TargetRange.Start, "target must match options", 3637341825Sdim TargetRange); 3638341825Sdim 3639341825Sdim getTargetStreamer().EmitDirectiveAMDGCNTarget(Target); 3640341825Sdim return false; 3641341825Sdim} 3642341825Sdim 3643341825Sdimbool AMDGPUAsmParser::OutOfRangeError(SMRange Range) { 3644341825Sdim return getParser().Error(Range.Start, "value out of range", Range); 3645341825Sdim} 3646341825Sdim 3647341825Sdimbool AMDGPUAsmParser::calculateGPRBlocks( 3648341825Sdim const FeatureBitset &Features, bool VCCUsed, bool FlatScrUsed, 3649353358Sdim bool XNACKUsed, Optional<bool> EnableWavefrontSize32, unsigned NextFreeVGPR, 3650353358Sdim SMRange VGPRRange, unsigned NextFreeSGPR, SMRange SGPRRange, 3651353358Sdim unsigned &VGPRBlocks, unsigned &SGPRBlocks) { 3652341825Sdim // TODO(scott.linder): These calculations are duplicated from 3653341825Sdim // AMDGPUAsmPrinter::getSIProgramInfo and could be unified. 3654344779Sdim IsaVersion Version = getIsaVersion(getSTI().getCPU()); 3655341825Sdim 3656341825Sdim unsigned NumVGPRs = NextFreeVGPR; 3657341825Sdim unsigned NumSGPRs = NextFreeSGPR; 3658341825Sdim 3659353358Sdim if (Version.Major >= 10) 3660353358Sdim NumSGPRs = 0; 3661353358Sdim else { 3662353358Sdim unsigned MaxAddressableNumSGPRs = 3663353358Sdim IsaInfo::getAddressableNumSGPRs(&getSTI()); 3664341825Sdim 3665353358Sdim if (Version.Major >= 8 && !Features.test(FeatureSGPRInitBug) && 3666353358Sdim NumSGPRs > MaxAddressableNumSGPRs) 3667353358Sdim return OutOfRangeError(SGPRRange); 3668341825Sdim 3669353358Sdim NumSGPRs += 3670353358Sdim IsaInfo::getNumExtraSGPRs(&getSTI(), VCCUsed, FlatScrUsed, XNACKUsed); 3671341825Sdim 3672353358Sdim if ((Version.Major <= 7 || Features.test(FeatureSGPRInitBug)) && 3673353358Sdim NumSGPRs > MaxAddressableNumSGPRs) 3674353358Sdim return OutOfRangeError(SGPRRange); 3675341825Sdim 3676353358Sdim if (Features.test(FeatureSGPRInitBug)) 3677353358Sdim NumSGPRs = IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG; 3678353358Sdim } 3679353358Sdim 3680353358Sdim VGPRBlocks = 3681353358Sdim IsaInfo::getNumVGPRBlocks(&getSTI(), NumVGPRs, EnableWavefrontSize32); 3682344779Sdim SGPRBlocks = IsaInfo::getNumSGPRBlocks(&getSTI(), NumSGPRs); 3683341825Sdim 3684341825Sdim return false; 3685341825Sdim} 3686341825Sdim 3687341825Sdimbool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { 3688341825Sdim if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) 3689341825Sdim return TokError("directive only supported for amdgcn architecture"); 3690341825Sdim 3691341825Sdim if (getSTI().getTargetTriple().getOS() != Triple::AMDHSA) 3692341825Sdim return TokError("directive only supported for amdhsa OS"); 3693341825Sdim 3694341825Sdim StringRef KernelName; 3695341825Sdim if (getParser().parseIdentifier(KernelName)) 3696341825Sdim return true; 3697341825Sdim 3698353358Sdim kernel_descriptor_t KD = getDefaultAmdhsaKernelDescriptor(&getSTI()); 3699341825Sdim 3700341825Sdim StringSet<> Seen; 3701341825Sdim 3702344779Sdim IsaVersion IVersion = getIsaVersion(getSTI().getCPU()); 3703341825Sdim 3704341825Sdim SMRange VGPRRange; 3705341825Sdim uint64_t NextFreeVGPR = 0; 3706341825Sdim SMRange SGPRRange; 3707341825Sdim uint64_t NextFreeSGPR = 0; 3708341825Sdim unsigned UserSGPRCount = 0; 3709341825Sdim bool ReserveVCC = true; 3710341825Sdim bool ReserveFlatScr = true; 3711341825Sdim bool ReserveXNACK = hasXNACK(); 3712353358Sdim Optional<bool> EnableWavefrontSize32; 3713341825Sdim 3714341825Sdim while (true) { 3715341825Sdim while (getLexer().is(AsmToken::EndOfStatement)) 3716341825Sdim Lex(); 3717341825Sdim 3718341825Sdim if (getLexer().isNot(AsmToken::Identifier)) 3719341825Sdim return TokError("expected .amdhsa_ directive or .end_amdhsa_kernel"); 3720341825Sdim 3721341825Sdim StringRef ID = getTok().getIdentifier(); 3722341825Sdim SMRange IDRange = getTok().getLocRange(); 3723341825Sdim Lex(); 3724341825Sdim 3725341825Sdim if (ID == ".end_amdhsa_kernel") 3726341825Sdim break; 3727341825Sdim 3728341825Sdim if (Seen.find(ID) != Seen.end()) 3729341825Sdim return TokError(".amdhsa_ directives cannot be repeated"); 3730341825Sdim Seen.insert(ID); 3731341825Sdim 3732341825Sdim SMLoc ValStart = getTok().getLoc(); 3733341825Sdim int64_t IVal; 3734341825Sdim if (getParser().parseAbsoluteExpression(IVal)) 3735341825Sdim return true; 3736341825Sdim SMLoc ValEnd = getTok().getLoc(); 3737341825Sdim SMRange ValRange = SMRange(ValStart, ValEnd); 3738341825Sdim 3739341825Sdim if (IVal < 0) 3740341825Sdim return OutOfRangeError(ValRange); 3741341825Sdim 3742341825Sdim uint64_t Val = IVal; 3743341825Sdim 3744341825Sdim#define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE) \ 3745341825Sdim if (!isUInt<ENTRY##_WIDTH>(VALUE)) \ 3746341825Sdim return OutOfRangeError(RANGE); \ 3747341825Sdim AMDHSA_BITS_SET(FIELD, ENTRY, VALUE); 3748341825Sdim 3749341825Sdim if (ID == ".amdhsa_group_segment_fixed_size") { 3750341825Sdim if (!isUInt<sizeof(KD.group_segment_fixed_size) * CHAR_BIT>(Val)) 3751341825Sdim return OutOfRangeError(ValRange); 3752341825Sdim KD.group_segment_fixed_size = Val; 3753341825Sdim } else if (ID == ".amdhsa_private_segment_fixed_size") { 3754341825Sdim if (!isUInt<sizeof(KD.private_segment_fixed_size) * CHAR_BIT>(Val)) 3755341825Sdim return OutOfRangeError(ValRange); 3756341825Sdim KD.private_segment_fixed_size = Val; 3757341825Sdim } else if (ID == ".amdhsa_user_sgpr_private_segment_buffer") { 3758341825Sdim PARSE_BITS_ENTRY(KD.kernel_code_properties, 3759341825Sdim KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER, 3760341825Sdim Val, ValRange); 3761360784Sdim if (Val) 3762360784Sdim UserSGPRCount += 4; 3763341825Sdim } else if (ID == ".amdhsa_user_sgpr_dispatch_ptr") { 3764341825Sdim PARSE_BITS_ENTRY(KD.kernel_code_properties, 3765341825Sdim KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, Val, 3766341825Sdim ValRange); 3767360784Sdim if (Val) 3768360784Sdim UserSGPRCount += 2; 3769341825Sdim } else if (ID == ".amdhsa_user_sgpr_queue_ptr") { 3770341825Sdim PARSE_BITS_ENTRY(KD.kernel_code_properties, 3771341825Sdim KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, Val, 3772341825Sdim ValRange); 3773360784Sdim if (Val) 3774360784Sdim UserSGPRCount += 2; 3775341825Sdim } else if (ID == ".amdhsa_user_sgpr_kernarg_segment_ptr") { 3776341825Sdim PARSE_BITS_ENTRY(KD.kernel_code_properties, 3777341825Sdim KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR, 3778341825Sdim Val, ValRange); 3779360784Sdim if (Val) 3780360784Sdim UserSGPRCount += 2; 3781341825Sdim } else if (ID == ".amdhsa_user_sgpr_dispatch_id") { 3782341825Sdim PARSE_BITS_ENTRY(KD.kernel_code_properties, 3783341825Sdim KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, Val, 3784341825Sdim ValRange); 3785360784Sdim if (Val) 3786360784Sdim UserSGPRCount += 2; 3787341825Sdim } else if (ID == ".amdhsa_user_sgpr_flat_scratch_init") { 3788341825Sdim PARSE_BITS_ENTRY(KD.kernel_code_properties, 3789341825Sdim KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, Val, 3790341825Sdim ValRange); 3791360784Sdim if (Val) 3792360784Sdim UserSGPRCount += 2; 3793341825Sdim } else if (ID == ".amdhsa_user_sgpr_private_segment_size") { 3794341825Sdim PARSE_BITS_ENTRY(KD.kernel_code_properties, 3795341825Sdim KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE, 3796341825Sdim Val, ValRange); 3797360784Sdim if (Val) 3798360784Sdim UserSGPRCount += 1; 3799353358Sdim } else if (ID == ".amdhsa_wavefront_size32") { 3800353358Sdim if (IVersion.Major < 10) 3801353358Sdim return getParser().Error(IDRange.Start, "directive requires gfx10+", 3802353358Sdim IDRange); 3803353358Sdim EnableWavefrontSize32 = Val; 3804353358Sdim PARSE_BITS_ENTRY(KD.kernel_code_properties, 3805353358Sdim KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, 3806353358Sdim Val, ValRange); 3807341825Sdim } else if (ID == ".amdhsa_system_sgpr_private_segment_wavefront_offset") { 3808341825Sdim PARSE_BITS_ENTRY( 3809341825Sdim KD.compute_pgm_rsrc2, 3810341825Sdim COMPUTE_PGM_RSRC2_ENABLE_SGPR_PRIVATE_SEGMENT_WAVEFRONT_OFFSET, Val, 3811341825Sdim ValRange); 3812341825Sdim } else if (ID == ".amdhsa_system_sgpr_workgroup_id_x") { 3813341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 3814341825Sdim COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, Val, 3815341825Sdim ValRange); 3816341825Sdim } else if (ID == ".amdhsa_system_sgpr_workgroup_id_y") { 3817341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 3818341825Sdim COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, Val, 3819341825Sdim ValRange); 3820341825Sdim } else if (ID == ".amdhsa_system_sgpr_workgroup_id_z") { 3821341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 3822341825Sdim COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, Val, 3823341825Sdim ValRange); 3824341825Sdim } else if (ID == ".amdhsa_system_sgpr_workgroup_info") { 3825341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 3826341825Sdim COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, Val, 3827341825Sdim ValRange); 3828341825Sdim } else if (ID == ".amdhsa_system_vgpr_workitem_id") { 3829341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 3830341825Sdim COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, Val, 3831341825Sdim ValRange); 3832341825Sdim } else if (ID == ".amdhsa_next_free_vgpr") { 3833341825Sdim VGPRRange = ValRange; 3834341825Sdim NextFreeVGPR = Val; 3835341825Sdim } else if (ID == ".amdhsa_next_free_sgpr") { 3836341825Sdim SGPRRange = ValRange; 3837341825Sdim NextFreeSGPR = Val; 3838341825Sdim } else if (ID == ".amdhsa_reserve_vcc") { 3839341825Sdim if (!isUInt<1>(Val)) 3840341825Sdim return OutOfRangeError(ValRange); 3841341825Sdim ReserveVCC = Val; 3842341825Sdim } else if (ID == ".amdhsa_reserve_flat_scratch") { 3843341825Sdim if (IVersion.Major < 7) 3844341825Sdim return getParser().Error(IDRange.Start, "directive requires gfx7+", 3845341825Sdim IDRange); 3846341825Sdim if (!isUInt<1>(Val)) 3847341825Sdim return OutOfRangeError(ValRange); 3848341825Sdim ReserveFlatScr = Val; 3849341825Sdim } else if (ID == ".amdhsa_reserve_xnack_mask") { 3850341825Sdim if (IVersion.Major < 8) 3851341825Sdim return getParser().Error(IDRange.Start, "directive requires gfx8+", 3852341825Sdim IDRange); 3853341825Sdim if (!isUInt<1>(Val)) 3854341825Sdim return OutOfRangeError(ValRange); 3855341825Sdim ReserveXNACK = Val; 3856341825Sdim } else if (ID == ".amdhsa_float_round_mode_32") { 3857341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 3858341825Sdim COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, Val, ValRange); 3859341825Sdim } else if (ID == ".amdhsa_float_round_mode_16_64") { 3860341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 3861341825Sdim COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, Val, ValRange); 3862341825Sdim } else if (ID == ".amdhsa_float_denorm_mode_32") { 3863341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 3864341825Sdim COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, Val, ValRange); 3865341825Sdim } else if (ID == ".amdhsa_float_denorm_mode_16_64") { 3866341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 3867341825Sdim COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, Val, 3868341825Sdim ValRange); 3869341825Sdim } else if (ID == ".amdhsa_dx10_clamp") { 3870341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 3871341825Sdim COMPUTE_PGM_RSRC1_ENABLE_DX10_CLAMP, Val, ValRange); 3872341825Sdim } else if (ID == ".amdhsa_ieee_mode") { 3873341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_ENABLE_IEEE_MODE, 3874341825Sdim Val, ValRange); 3875341825Sdim } else if (ID == ".amdhsa_fp16_overflow") { 3876341825Sdim if (IVersion.Major < 9) 3877341825Sdim return getParser().Error(IDRange.Start, "directive requires gfx9+", 3878341825Sdim IDRange); 3879341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_FP16_OVFL, Val, 3880341825Sdim ValRange); 3881353358Sdim } else if (ID == ".amdhsa_workgroup_processor_mode") { 3882353358Sdim if (IVersion.Major < 10) 3883353358Sdim return getParser().Error(IDRange.Start, "directive requires gfx10+", 3884353358Sdim IDRange); 3885353358Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_WGP_MODE, Val, 3886353358Sdim ValRange); 3887353358Sdim } else if (ID == ".amdhsa_memory_ordered") { 3888353358Sdim if (IVersion.Major < 10) 3889353358Sdim return getParser().Error(IDRange.Start, "directive requires gfx10+", 3890353358Sdim IDRange); 3891353358Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_MEM_ORDERED, Val, 3892353358Sdim ValRange); 3893353358Sdim } else if (ID == ".amdhsa_forward_progress") { 3894353358Sdim if (IVersion.Major < 10) 3895353358Sdim return getParser().Error(IDRange.Start, "directive requires gfx10+", 3896353358Sdim IDRange); 3897353358Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_FWD_PROGRESS, Val, 3898353358Sdim ValRange); 3899341825Sdim } else if (ID == ".amdhsa_exception_fp_ieee_invalid_op") { 3900341825Sdim PARSE_BITS_ENTRY( 3901341825Sdim KD.compute_pgm_rsrc2, 3902341825Sdim COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, Val, 3903341825Sdim ValRange); 3904341825Sdim } else if (ID == ".amdhsa_exception_fp_denorm_src") { 3905341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 3906341825Sdim COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE, 3907341825Sdim Val, ValRange); 3908341825Sdim } else if (ID == ".amdhsa_exception_fp_ieee_div_zero") { 3909341825Sdim PARSE_BITS_ENTRY( 3910341825Sdim KD.compute_pgm_rsrc2, 3911341825Sdim COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, Val, 3912341825Sdim ValRange); 3913341825Sdim } else if (ID == ".amdhsa_exception_fp_ieee_overflow") { 3914341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 3915341825Sdim COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW, 3916341825Sdim Val, ValRange); 3917341825Sdim } else if (ID == ".amdhsa_exception_fp_ieee_underflow") { 3918341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 3919341825Sdim COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW, 3920341825Sdim Val, ValRange); 3921341825Sdim } else if (ID == ".amdhsa_exception_fp_ieee_inexact") { 3922341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 3923341825Sdim COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT, 3924341825Sdim Val, ValRange); 3925341825Sdim } else if (ID == ".amdhsa_exception_int_div_zero") { 3926341825Sdim PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 3927341825Sdim COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO, 3928341825Sdim Val, ValRange); 3929341825Sdim } else { 3930341825Sdim return getParser().Error(IDRange.Start, 3931341825Sdim "unknown .amdhsa_kernel directive", IDRange); 3932341825Sdim } 3933341825Sdim 3934341825Sdim#undef PARSE_BITS_ENTRY 3935341825Sdim } 3936341825Sdim 3937341825Sdim if (Seen.find(".amdhsa_next_free_vgpr") == Seen.end()) 3938341825Sdim return TokError(".amdhsa_next_free_vgpr directive is required"); 3939341825Sdim 3940341825Sdim if (Seen.find(".amdhsa_next_free_sgpr") == Seen.end()) 3941341825Sdim return TokError(".amdhsa_next_free_sgpr directive is required"); 3942341825Sdim 3943341825Sdim unsigned VGPRBlocks; 3944341825Sdim unsigned SGPRBlocks; 3945341825Sdim if (calculateGPRBlocks(getFeatureBits(), ReserveVCC, ReserveFlatScr, 3946353358Sdim ReserveXNACK, EnableWavefrontSize32, NextFreeVGPR, 3947353358Sdim VGPRRange, NextFreeSGPR, SGPRRange, VGPRBlocks, 3948353358Sdim SGPRBlocks)) 3949341825Sdim return true; 3950341825Sdim 3951341825Sdim if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_WIDTH>( 3952341825Sdim VGPRBlocks)) 3953341825Sdim return OutOfRangeError(VGPRRange); 3954341825Sdim AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, 3955341825Sdim COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, VGPRBlocks); 3956341825Sdim 3957341825Sdim if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_WIDTH>( 3958341825Sdim SGPRBlocks)) 3959341825Sdim return OutOfRangeError(SGPRRange); 3960341825Sdim AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, 3961341825Sdim COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT, 3962341825Sdim SGPRBlocks); 3963341825Sdim 3964341825Sdim if (!isUInt<COMPUTE_PGM_RSRC2_USER_SGPR_COUNT_WIDTH>(UserSGPRCount)) 3965341825Sdim return TokError("too many user SGPRs enabled"); 3966341825Sdim AMDHSA_BITS_SET(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_USER_SGPR_COUNT, 3967341825Sdim UserSGPRCount); 3968341825Sdim 3969341825Sdim getTargetStreamer().EmitAmdhsaKernelDescriptor( 3970341825Sdim getSTI(), KernelName, KD, NextFreeVGPR, NextFreeSGPR, ReserveVCC, 3971341825Sdim ReserveFlatScr, ReserveXNACK); 3972341825Sdim return false; 3973341825Sdim} 3974341825Sdim 3975285181Sdimbool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() { 3976285181Sdim uint32_t Major; 3977285181Sdim uint32_t Minor; 3978285181Sdim 3979285181Sdim if (ParseDirectiveMajorMinor(Major, Minor)) 3980285181Sdim return true; 3981285181Sdim 3982285181Sdim getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor); 3983285181Sdim return false; 3984285181Sdim} 3985285181Sdim 3986285181Sdimbool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() { 3987285181Sdim uint32_t Major; 3988285181Sdim uint32_t Minor; 3989285181Sdim uint32_t Stepping; 3990285181Sdim StringRef VendorName; 3991285181Sdim StringRef ArchName; 3992285181Sdim 3993285181Sdim // If this directive has no arguments, then use the ISA version for the 3994285181Sdim // targeted GPU. 3995285181Sdim if (getLexer().is(AsmToken::EndOfStatement)) { 3996344779Sdim AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU()); 3997321369Sdim getTargetStreamer().EmitDirectiveHSACodeObjectISA(ISA.Major, ISA.Minor, 3998321369Sdim ISA.Stepping, 3999285181Sdim "AMD", "AMDGPU"); 4000285181Sdim return false; 4001285181Sdim } 4002285181Sdim 4003285181Sdim if (ParseDirectiveMajorMinor(Major, Minor)) 4004285181Sdim return true; 4005285181Sdim 4006285181Sdim if (getLexer().isNot(AsmToken::Comma)) 4007285181Sdim return TokError("stepping version number required, comma expected"); 4008285181Sdim Lex(); 4009285181Sdim 4010314564Sdim if (ParseAsAbsoluteExpression(Stepping)) 4011285181Sdim return TokError("invalid stepping version"); 4012285181Sdim 4013285181Sdim if (getLexer().isNot(AsmToken::Comma)) 4014285181Sdim return TokError("vendor name required, comma expected"); 4015285181Sdim Lex(); 4016285181Sdim 4017285181Sdim if (getLexer().isNot(AsmToken::String)) 4018285181Sdim return TokError("invalid vendor name"); 4019285181Sdim 4020285181Sdim VendorName = getLexer().getTok().getStringContents(); 4021285181Sdim Lex(); 4022285181Sdim 4023285181Sdim if (getLexer().isNot(AsmToken::Comma)) 4024285181Sdim return TokError("arch name required, comma expected"); 4025285181Sdim Lex(); 4026285181Sdim 4027285181Sdim if (getLexer().isNot(AsmToken::String)) 4028285181Sdim return TokError("invalid arch name"); 4029285181Sdim 4030285181Sdim ArchName = getLexer().getTok().getStringContents(); 4031285181Sdim Lex(); 4032285181Sdim 4033285181Sdim getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping, 4034285181Sdim VendorName, ArchName); 4035285181Sdim return false; 4036285181Sdim} 4037285181Sdim 4038285181Sdimbool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID, 4039285181Sdim amd_kernel_code_t &Header) { 4040341825Sdim // max_scratch_backing_memory_byte_size is deprecated. Ignore it while parsing 4041341825Sdim // assembly for backwards compatibility. 4042341825Sdim if (ID == "max_scratch_backing_memory_byte_size") { 4043341825Sdim Parser.eatToEndOfStatement(); 4044341825Sdim return false; 4045341825Sdim } 4046341825Sdim 4047309124Sdim SmallString<40> ErrStr; 4048309124Sdim raw_svector_ostream Err(ErrStr); 4049309124Sdim if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) { 4050309124Sdim return TokError(Err.str()); 4051309124Sdim } 4052285181Sdim Lex(); 4053353358Sdim 4054353358Sdim if (ID == "enable_wavefront_size32") { 4055353358Sdim if (Header.code_properties & AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32) { 4056353358Sdim if (!isGFX10()) 4057353358Sdim return TokError("enable_wavefront_size32=1 is only allowed on GFX10+"); 4058353358Sdim if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize32]) 4059353358Sdim return TokError("enable_wavefront_size32=1 requires +WavefrontSize32"); 4060353358Sdim } else { 4061353358Sdim if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize64]) 4062353358Sdim return TokError("enable_wavefront_size32=0 requires +WavefrontSize64"); 4063353358Sdim } 4064353358Sdim } 4065353358Sdim 4066353358Sdim if (ID == "wavefront_size") { 4067353358Sdim if (Header.wavefront_size == 5) { 4068353358Sdim if (!isGFX10()) 4069353358Sdim return TokError("wavefront_size=5 is only allowed on GFX10+"); 4070353358Sdim if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize32]) 4071353358Sdim return TokError("wavefront_size=5 requires +WavefrontSize32"); 4072353358Sdim } else if (Header.wavefront_size == 6) { 4073353358Sdim if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize64]) 4074353358Sdim return TokError("wavefront_size=6 requires +WavefrontSize64"); 4075353358Sdim } 4076353358Sdim } 4077353358Sdim 4078353358Sdim if (ID == "enable_wgp_mode") { 4079353358Sdim if (G_00B848_WGP_MODE(Header.compute_pgm_resource_registers) && !isGFX10()) 4080353358Sdim return TokError("enable_wgp_mode=1 is only allowed on GFX10+"); 4081353358Sdim } 4082353358Sdim 4083353358Sdim if (ID == "enable_mem_ordered") { 4084353358Sdim if (G_00B848_MEM_ORDERED(Header.compute_pgm_resource_registers) && !isGFX10()) 4085353358Sdim return TokError("enable_mem_ordered=1 is only allowed on GFX10+"); 4086353358Sdim } 4087353358Sdim 4088353358Sdim if (ID == "enable_fwd_progress") { 4089353358Sdim if (G_00B848_FWD_PROGRESS(Header.compute_pgm_resource_registers) && !isGFX10()) 4090353358Sdim return TokError("enable_fwd_progress=1 is only allowed on GFX10+"); 4091353358Sdim } 4092353358Sdim 4093285181Sdim return false; 4094285181Sdim} 4095285181Sdim 4096285181Sdimbool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() { 4097285181Sdim amd_kernel_code_t Header; 4098344779Sdim AMDGPU::initDefaultAMDKernelCodeT(Header, &getSTI()); 4099285181Sdim 4100285181Sdim while (true) { 4101285181Sdim // Lex EndOfStatement. This is in a while loop, because lexing a comment 4102285181Sdim // will set the current token to EndOfStatement. 4103285181Sdim while(getLexer().is(AsmToken::EndOfStatement)) 4104285181Sdim Lex(); 4105285181Sdim 4106285181Sdim if (getLexer().isNot(AsmToken::Identifier)) 4107285181Sdim return TokError("expected value identifier or .end_amd_kernel_code_t"); 4108285181Sdim 4109285181Sdim StringRef ID = getLexer().getTok().getIdentifier(); 4110285181Sdim Lex(); 4111285181Sdim 4112285181Sdim if (ID == ".end_amd_kernel_code_t") 4113285181Sdim break; 4114285181Sdim 4115285181Sdim if (ParseAMDKernelCodeTValue(ID, Header)) 4116285181Sdim return true; 4117285181Sdim } 4118285181Sdim 4119285181Sdim getTargetStreamer().EmitAMDKernelCodeT(Header); 4120285181Sdim 4121285181Sdim return false; 4122285181Sdim} 4123285181Sdim 4124296417Sdimbool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() { 4125296417Sdim if (getLexer().isNot(AsmToken::Identifier)) 4126296417Sdim return TokError("expected symbol name"); 4127296417Sdim 4128296417Sdim StringRef KernelName = Parser.getTok().getString(); 4129296417Sdim 4130296417Sdim getTargetStreamer().EmitAMDGPUSymbolType(KernelName, 4131296417Sdim ELF::STT_AMDGPU_HSA_KERNEL); 4132296417Sdim Lex(); 4133341825Sdim if (!AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) 4134341825Sdim KernelScope.initialize(getContext()); 4135296417Sdim return false; 4136296417Sdim} 4137296417Sdim 4138327952Sdimbool AMDGPUAsmParser::ParseDirectiveISAVersion() { 4139327952Sdim if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) { 4140327952Sdim return Error(getParser().getTok().getLoc(), 4141327952Sdim ".amd_amdgpu_isa directive is not available on non-amdgcn " 4142327952Sdim "architectures"); 4143327952Sdim } 4144327952Sdim 4145327952Sdim auto ISAVersionStringFromASM = getLexer().getTok().getStringContents(); 4146327952Sdim 4147327952Sdim std::string ISAVersionStringFromSTI; 4148327952Sdim raw_string_ostream ISAVersionStreamFromSTI(ISAVersionStringFromSTI); 4149327952Sdim IsaInfo::streamIsaVersion(&getSTI(), ISAVersionStreamFromSTI); 4150327952Sdim 4151327952Sdim if (ISAVersionStringFromASM != ISAVersionStreamFromSTI.str()) { 4152327952Sdim return Error(getParser().getTok().getLoc(), 4153327952Sdim ".amd_amdgpu_isa directive does not match triple and/or mcpu " 4154327952Sdim "arguments specified through the command line"); 4155327952Sdim } 4156327952Sdim 4157327952Sdim getTargetStreamer().EmitISAVersion(ISAVersionStreamFromSTI.str()); 4158327952Sdim Lex(); 4159327952Sdim 4160327952Sdim return false; 4161327952Sdim} 4162327952Sdim 4163327952Sdimbool AMDGPUAsmParser::ParseDirectiveHSAMetadata() { 4164344779Sdim const char *AssemblerDirectiveBegin; 4165344779Sdim const char *AssemblerDirectiveEnd; 4166344779Sdim std::tie(AssemblerDirectiveBegin, AssemblerDirectiveEnd) = 4167344779Sdim AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI()) 4168344779Sdim ? std::make_tuple(HSAMD::V3::AssemblerDirectiveBegin, 4169344779Sdim HSAMD::V3::AssemblerDirectiveEnd) 4170344779Sdim : std::make_tuple(HSAMD::AssemblerDirectiveBegin, 4171344779Sdim HSAMD::AssemblerDirectiveEnd); 4172344779Sdim 4173327952Sdim if (getSTI().getTargetTriple().getOS() != Triple::AMDHSA) { 4174327952Sdim return Error(getParser().getTok().getLoc(), 4175344779Sdim (Twine(AssemblerDirectiveBegin) + Twine(" directive is " 4176327952Sdim "not available on non-amdhsa OSes")).str()); 4177327952Sdim } 4178327952Sdim 4179327952Sdim std::string HSAMetadataString; 4180353358Sdim if (ParseToEndDirective(AssemblerDirectiveBegin, AssemblerDirectiveEnd, 4181353358Sdim HSAMetadataString)) 4182353358Sdim return true; 4183327952Sdim 4184353358Sdim if (IsaInfo::hasCodeObjectV3(&getSTI())) { 4185353358Sdim if (!getTargetStreamer().EmitHSAMetadataV3(HSAMetadataString)) 4186353358Sdim return Error(getParser().getTok().getLoc(), "invalid HSA metadata"); 4187353358Sdim } else { 4188353358Sdim if (!getTargetStreamer().EmitHSAMetadataV2(HSAMetadataString)) 4189353358Sdim return Error(getParser().getTok().getLoc(), "invalid HSA metadata"); 4190353358Sdim } 4191353358Sdim 4192353358Sdim return false; 4193353358Sdim} 4194353358Sdim 4195353358Sdim/// Common code to parse out a block of text (typically YAML) between start and 4196353358Sdim/// end directives. 4197353358Sdimbool AMDGPUAsmParser::ParseToEndDirective(const char *AssemblerDirectiveBegin, 4198353358Sdim const char *AssemblerDirectiveEnd, 4199353358Sdim std::string &CollectString) { 4200353358Sdim 4201353358Sdim raw_string_ostream CollectStream(CollectString); 4202353358Sdim 4203327952Sdim getLexer().setSkipSpace(false); 4204327952Sdim 4205327952Sdim bool FoundEnd = false; 4206327952Sdim while (!getLexer().is(AsmToken::Eof)) { 4207327952Sdim while (getLexer().is(AsmToken::Space)) { 4208353358Sdim CollectStream << getLexer().getTok().getString(); 4209327952Sdim Lex(); 4210327952Sdim } 4211327952Sdim 4212327952Sdim if (getLexer().is(AsmToken::Identifier)) { 4213327952Sdim StringRef ID = getLexer().getTok().getIdentifier(); 4214344779Sdim if (ID == AssemblerDirectiveEnd) { 4215327952Sdim Lex(); 4216327952Sdim FoundEnd = true; 4217327952Sdim break; 4218327952Sdim } 4219327952Sdim } 4220327952Sdim 4221353358Sdim CollectStream << Parser.parseStringToEndOfStatement() 4222353358Sdim << getContext().getAsmInfo()->getSeparatorString(); 4223327952Sdim 4224327952Sdim Parser.eatToEndOfStatement(); 4225327952Sdim } 4226327952Sdim 4227327952Sdim getLexer().setSkipSpace(true); 4228327952Sdim 4229327952Sdim if (getLexer().is(AsmToken::Eof) && !FoundEnd) { 4230327952Sdim return TokError(Twine("expected directive ") + 4231353358Sdim Twine(AssemblerDirectiveEnd) + Twine(" not found")); 4232327952Sdim } 4233327952Sdim 4234353358Sdim CollectStream.flush(); 4235353358Sdim return false; 4236353358Sdim} 4237327952Sdim 4238353358Sdim/// Parse the assembler directive for new MsgPack-format PAL metadata. 4239353358Sdimbool AMDGPUAsmParser::ParseDirectivePALMetadataBegin() { 4240353358Sdim std::string String; 4241353358Sdim if (ParseToEndDirective(AMDGPU::PALMD::AssemblerDirectiveBegin, 4242353358Sdim AMDGPU::PALMD::AssemblerDirectiveEnd, String)) 4243353358Sdim return true; 4244327952Sdim 4245353358Sdim auto PALMetadata = getTargetStreamer().getPALMetadata(); 4246353358Sdim if (!PALMetadata->setFromString(String)) 4247353358Sdim return Error(getParser().getTok().getLoc(), "invalid PAL metadata"); 4248327952Sdim return false; 4249327952Sdim} 4250327952Sdim 4251353358Sdim/// Parse the assembler directive for old linear-format PAL metadata. 4252327952Sdimbool AMDGPUAsmParser::ParseDirectivePALMetadata() { 4253327952Sdim if (getSTI().getTargetTriple().getOS() != Triple::AMDPAL) { 4254327952Sdim return Error(getParser().getTok().getLoc(), 4255327952Sdim (Twine(PALMD::AssemblerDirective) + Twine(" directive is " 4256327952Sdim "not available on non-amdpal OSes")).str()); 4257327952Sdim } 4258327952Sdim 4259353358Sdim auto PALMetadata = getTargetStreamer().getPALMetadata(); 4260353358Sdim PALMetadata->setLegacy(); 4261327952Sdim for (;;) { 4262353358Sdim uint32_t Key, Value; 4263353358Sdim if (ParseAsAbsoluteExpression(Key)) { 4264353358Sdim return TokError(Twine("invalid value in ") + 4265353358Sdim Twine(PALMD::AssemblerDirective)); 4266353358Sdim } 4267353358Sdim if (getLexer().isNot(AsmToken::Comma)) { 4268353358Sdim return TokError(Twine("expected an even number of values in ") + 4269353358Sdim Twine(PALMD::AssemblerDirective)); 4270353358Sdim } 4271353358Sdim Lex(); 4272327952Sdim if (ParseAsAbsoluteExpression(Value)) { 4273327952Sdim return TokError(Twine("invalid value in ") + 4274327952Sdim Twine(PALMD::AssemblerDirective)); 4275327952Sdim } 4276353358Sdim PALMetadata->setRegister(Key, Value); 4277327952Sdim if (getLexer().isNot(AsmToken::Comma)) 4278327952Sdim break; 4279327952Sdim Lex(); 4280327952Sdim } 4281327952Sdim return false; 4282327952Sdim} 4283327952Sdim 4284353358Sdim/// ParseDirectiveAMDGPULDS 4285353358Sdim/// ::= .amdgpu_lds identifier ',' size_expression [',' align_expression] 4286353358Sdimbool AMDGPUAsmParser::ParseDirectiveAMDGPULDS() { 4287353358Sdim if (getParser().checkForValidSection()) 4288353358Sdim return true; 4289353358Sdim 4290353358Sdim StringRef Name; 4291353358Sdim SMLoc NameLoc = getLexer().getLoc(); 4292353358Sdim if (getParser().parseIdentifier(Name)) 4293353358Sdim return TokError("expected identifier in directive"); 4294353358Sdim 4295353358Sdim MCSymbol *Symbol = getContext().getOrCreateSymbol(Name); 4296353358Sdim if (parseToken(AsmToken::Comma, "expected ','")) 4297353358Sdim return true; 4298353358Sdim 4299353358Sdim unsigned LocalMemorySize = AMDGPU::IsaInfo::getLocalMemorySize(&getSTI()); 4300353358Sdim 4301353358Sdim int64_t Size; 4302353358Sdim SMLoc SizeLoc = getLexer().getLoc(); 4303353358Sdim if (getParser().parseAbsoluteExpression(Size)) 4304353358Sdim return true; 4305353358Sdim if (Size < 0) 4306353358Sdim return Error(SizeLoc, "size must be non-negative"); 4307353358Sdim if (Size > LocalMemorySize) 4308353358Sdim return Error(SizeLoc, "size is too large"); 4309353358Sdim 4310353358Sdim int64_t Align = 4; 4311353358Sdim if (getLexer().is(AsmToken::Comma)) { 4312353358Sdim Lex(); 4313353358Sdim SMLoc AlignLoc = getLexer().getLoc(); 4314353358Sdim if (getParser().parseAbsoluteExpression(Align)) 4315353358Sdim return true; 4316353358Sdim if (Align < 0 || !isPowerOf2_64(Align)) 4317353358Sdim return Error(AlignLoc, "alignment must be a power of two"); 4318353358Sdim 4319353358Sdim // Alignment larger than the size of LDS is possible in theory, as long 4320353358Sdim // as the linker manages to place to symbol at address 0, but we do want 4321353358Sdim // to make sure the alignment fits nicely into a 32-bit integer. 4322353358Sdim if (Align >= 1u << 31) 4323353358Sdim return Error(AlignLoc, "alignment is too large"); 4324353358Sdim } 4325353358Sdim 4326353358Sdim if (parseToken(AsmToken::EndOfStatement, 4327353358Sdim "unexpected token in '.amdgpu_lds' directive")) 4328353358Sdim return true; 4329353358Sdim 4330353358Sdim Symbol->redefineIfPossible(); 4331353358Sdim if (!Symbol->isUndefined()) 4332353358Sdim return Error(NameLoc, "invalid symbol redefinition"); 4333353358Sdim 4334353358Sdim getTargetStreamer().emitAMDGPULDS(Symbol, Size, Align); 4335353358Sdim return false; 4336353358Sdim} 4337353358Sdim 4338284677Sdimbool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) { 4339285181Sdim StringRef IDVal = DirectiveID.getString(); 4340285181Sdim 4341341825Sdim if (AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) { 4342341825Sdim if (IDVal == ".amdgcn_target") 4343341825Sdim return ParseDirectiveAMDGCNTarget(); 4344285181Sdim 4345341825Sdim if (IDVal == ".amdhsa_kernel") 4346341825Sdim return ParseDirectiveAMDHSAKernel(); 4347344779Sdim 4348344779Sdim // TODO: Restructure/combine with PAL metadata directive. 4349344779Sdim if (IDVal == AMDGPU::HSAMD::V3::AssemblerDirectiveBegin) 4350344779Sdim return ParseDirectiveHSAMetadata(); 4351341825Sdim } else { 4352341825Sdim if (IDVal == ".hsa_code_object_version") 4353341825Sdim return ParseDirectiveHSACodeObjectVersion(); 4354285181Sdim 4355341825Sdim if (IDVal == ".hsa_code_object_isa") 4356341825Sdim return ParseDirectiveHSACodeObjectISA(); 4357285181Sdim 4358341825Sdim if (IDVal == ".amd_kernel_code_t") 4359341825Sdim return ParseDirectiveAMDKernelCodeT(); 4360296417Sdim 4361341825Sdim if (IDVal == ".amdgpu_hsa_kernel") 4362341825Sdim return ParseDirectiveAMDGPUHsaKernel(); 4363327952Sdim 4364341825Sdim if (IDVal == ".amd_amdgpu_isa") 4365341825Sdim return ParseDirectiveISAVersion(); 4366344779Sdim 4367344779Sdim if (IDVal == AMDGPU::HSAMD::AssemblerDirectiveBegin) 4368344779Sdim return ParseDirectiveHSAMetadata(); 4369341825Sdim } 4370341825Sdim 4371353358Sdim if (IDVal == ".amdgpu_lds") 4372353358Sdim return ParseDirectiveAMDGPULDS(); 4373353358Sdim 4374353358Sdim if (IDVal == PALMD::AssemblerDirectiveBegin) 4375353358Sdim return ParseDirectivePALMetadataBegin(); 4376353358Sdim 4377327952Sdim if (IDVal == PALMD::AssemblerDirective) 4378327952Sdim return ParseDirectivePALMetadata(); 4379327952Sdim 4380284677Sdim return true; 4381284677Sdim} 4382284677Sdim 4383296417Sdimbool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI, 4384296417Sdim unsigned RegNo) const { 4385327952Sdim 4386327952Sdim for (MCRegAliasIterator R(AMDGPU::TTMP12_TTMP13_TTMP14_TTMP15, &MRI, true); 4387327952Sdim R.isValid(); ++R) { 4388327952Sdim if (*R == RegNo) 4389353358Sdim return isGFX9() || isGFX10(); 4390327952Sdim } 4391327952Sdim 4392353358Sdim // GFX10 has 2 more SGPRs 104 and 105. 4393353358Sdim for (MCRegAliasIterator R(AMDGPU::SGPR104_SGPR105, &MRI, true); 4394353358Sdim R.isValid(); ++R) { 4395353358Sdim if (*R == RegNo) 4396353358Sdim return hasSGPR104_SGPR105(); 4397353358Sdim } 4398353358Sdim 4399327952Sdim switch (RegNo) { 4400353358Sdim case AMDGPU::SRC_SHARED_BASE: 4401353358Sdim case AMDGPU::SRC_SHARED_LIMIT: 4402353358Sdim case AMDGPU::SRC_PRIVATE_BASE: 4403353358Sdim case AMDGPU::SRC_PRIVATE_LIMIT: 4404353358Sdim case AMDGPU::SRC_POPS_EXITING_WAVE_ID: 4405353358Sdim return !isCI() && !isSI() && !isVI(); 4406327952Sdim case AMDGPU::TBA: 4407327952Sdim case AMDGPU::TBA_LO: 4408327952Sdim case AMDGPU::TBA_HI: 4409327952Sdim case AMDGPU::TMA: 4410327952Sdim case AMDGPU::TMA_LO: 4411327952Sdim case AMDGPU::TMA_HI: 4412353358Sdim return !isGFX9() && !isGFX10(); 4413341825Sdim case AMDGPU::XNACK_MASK: 4414341825Sdim case AMDGPU::XNACK_MASK_LO: 4415341825Sdim case AMDGPU::XNACK_MASK_HI: 4416353358Sdim return !isCI() && !isSI() && !isGFX10() && hasXNACK(); 4417353358Sdim case AMDGPU::SGPR_NULL: 4418353358Sdim return isGFX10(); 4419327952Sdim default: 4420327952Sdim break; 4421327952Sdim } 4422327952Sdim 4423296417Sdim if (isCI()) 4424296417Sdim return true; 4425296417Sdim 4426353358Sdim if (isSI() || isGFX10()) { 4427353358Sdim // No flat_scr on SI. 4428353358Sdim // On GFX10 flat scratch is not a valid register operand and can only be 4429353358Sdim // accessed with s_setreg/s_getreg. 4430296417Sdim switch (RegNo) { 4431296417Sdim case AMDGPU::FLAT_SCR: 4432296417Sdim case AMDGPU::FLAT_SCR_LO: 4433296417Sdim case AMDGPU::FLAT_SCR_HI: 4434296417Sdim return false; 4435296417Sdim default: 4436296417Sdim return true; 4437296417Sdim } 4438296417Sdim } 4439296417Sdim 4440296417Sdim // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that 4441296417Sdim // SI/CI have. 4442296417Sdim for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true); 4443296417Sdim R.isValid(); ++R) { 4444296417Sdim if (*R == RegNo) 4445353358Sdim return hasSGPR102_SGPR103(); 4446296417Sdim } 4447296417Sdim 4448296417Sdim return true; 4449296417Sdim} 4450296417Sdim 4451314564SdimOperandMatchResultTy 4452353358SdimAMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic, 4453353358Sdim OperandMode Mode) { 4454284677Sdim // Try to parse with a custom parser 4455284677Sdim OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 4456284677Sdim 4457284677Sdim // If we successfully parsed the operand or if there as an error parsing, 4458284677Sdim // we are done. 4459284677Sdim // 4460284677Sdim // If we are parsing after we reach EndOfStatement then this means we 4461284677Sdim // are appending default values to the Operands list. This is only done 4462284677Sdim // by custom parser, so we shouldn't continue on to the generic parsing. 4463284677Sdim if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail || 4464284677Sdim getLexer().is(AsmToken::EndOfStatement)) 4465284677Sdim return ResTy; 4466284677Sdim 4467353358Sdim if (Mode == OperandMode_NSA && getLexer().is(AsmToken::LBrac)) { 4468353358Sdim unsigned Prefix = Operands.size(); 4469353358Sdim SMLoc LBraceLoc = getTok().getLoc(); 4470353358Sdim Parser.Lex(); // eat the '[' 4471284677Sdim 4472353358Sdim for (;;) { 4473353358Sdim ResTy = parseReg(Operands); 4474353358Sdim if (ResTy != MatchOperand_Success) 4475353358Sdim return ResTy; 4476284677Sdim 4477353358Sdim if (getLexer().is(AsmToken::RBrac)) 4478353358Sdim break; 4479284677Sdim 4480353358Sdim if (getLexer().isNot(AsmToken::Comma)) 4481353358Sdim return MatchOperand_ParseFail; 4482353358Sdim Parser.Lex(); 4483353358Sdim } 4484327952Sdim 4485353358Sdim if (Operands.size() - Prefix > 1) { 4486353358Sdim Operands.insert(Operands.begin() + Prefix, 4487353358Sdim AMDGPUOperand::CreateToken(this, "[", LBraceLoc)); 4488353358Sdim Operands.push_back(AMDGPUOperand::CreateToken(this, "]", 4489353358Sdim getTok().getLoc())); 4490353358Sdim } 4491353358Sdim 4492353358Sdim Parser.Lex(); // eat the ']' 4493309124Sdim return MatchOperand_Success; 4494284677Sdim } 4495327952Sdim 4496353358Sdim return parseRegOrImm(Operands); 4497284677Sdim} 4498284677Sdim 4499309124SdimStringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) { 4500284677Sdim // Clear any forced encodings from the previous instruction. 4501284677Sdim setForcedEncodingSize(0); 4502309124Sdim setForcedDPP(false); 4503309124Sdim setForcedSDWA(false); 4504284677Sdim 4505309124Sdim if (Name.endswith("_e64")) { 4506284677Sdim setForcedEncodingSize(64); 4507309124Sdim return Name.substr(0, Name.size() - 4); 4508309124Sdim } else if (Name.endswith("_e32")) { 4509284677Sdim setForcedEncodingSize(32); 4510309124Sdim return Name.substr(0, Name.size() - 4); 4511309124Sdim } else if (Name.endswith("_dpp")) { 4512309124Sdim setForcedDPP(true); 4513309124Sdim return Name.substr(0, Name.size() - 4); 4514309124Sdim } else if (Name.endswith("_sdwa")) { 4515309124Sdim setForcedSDWA(true); 4516309124Sdim return Name.substr(0, Name.size() - 5); 4517309124Sdim } 4518309124Sdim return Name; 4519309124Sdim} 4520284677Sdim 4521309124Sdimbool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info, 4522309124Sdim StringRef Name, 4523309124Sdim SMLoc NameLoc, OperandVector &Operands) { 4524284677Sdim // Add the instruction mnemonic 4525309124Sdim Name = parseMnemonicSuffix(Name); 4526314564Sdim Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc)); 4527284677Sdim 4528353358Sdim bool IsMIMG = Name.startswith("image_"); 4529353358Sdim 4530284677Sdim while (!getLexer().is(AsmToken::EndOfStatement)) { 4531353358Sdim OperandMode Mode = OperandMode_Default; 4532353358Sdim if (IsMIMG && isGFX10() && Operands.size() == 2) 4533353358Sdim Mode = OperandMode_NSA; 4534353358Sdim OperandMatchResultTy Res = parseOperand(Operands, Name, Mode); 4535284677Sdim 4536284677Sdim // Eat the comma or space if there is one. 4537284677Sdim if (getLexer().is(AsmToken::Comma)) 4538284677Sdim Parser.Lex(); 4539284677Sdim 4540284677Sdim switch (Res) { 4541284677Sdim case MatchOperand_Success: break; 4542309124Sdim case MatchOperand_ParseFail: 4543353358Sdim // FIXME: use real operand location rather than the current location. 4544309124Sdim Error(getLexer().getLoc(), "failed parsing operand."); 4545309124Sdim while (!getLexer().is(AsmToken::EndOfStatement)) { 4546309124Sdim Parser.Lex(); 4547309124Sdim } 4548309124Sdim return true; 4549309124Sdim case MatchOperand_NoMatch: 4550353358Sdim // FIXME: use real operand location rather than the current location. 4551309124Sdim Error(getLexer().getLoc(), "not a valid operand."); 4552309124Sdim while (!getLexer().is(AsmToken::EndOfStatement)) { 4553309124Sdim Parser.Lex(); 4554309124Sdim } 4555309124Sdim return true; 4556284677Sdim } 4557284677Sdim } 4558284677Sdim 4559284677Sdim return false; 4560284677Sdim} 4561284677Sdim 4562284677Sdim//===----------------------------------------------------------------------===// 4563284677Sdim// Utility functions 4564284677Sdim//===----------------------------------------------------------------------===// 4565284677Sdim 4566314564SdimOperandMatchResultTy 4567353358SdimAMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &IntVal) { 4568284677Sdim 4569353358Sdim if (!trySkipId(Prefix, AsmToken::Colon)) 4570353358Sdim return MatchOperand_NoMatch; 4571284677Sdim 4572353358Sdim return parseExpr(IntVal) ? MatchOperand_Success : MatchOperand_ParseFail; 4573284677Sdim} 4574284677Sdim 4575314564SdimOperandMatchResultTy 4576284677SdimAMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands, 4577321369Sdim AMDGPUOperand::ImmTy ImmTy, 4578309124Sdim bool (*ConvertResult)(int64_t&)) { 4579353358Sdim SMLoc S = getLoc(); 4580309124Sdim int64_t Value = 0; 4581284677Sdim 4582314564Sdim OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value); 4583284677Sdim if (Res != MatchOperand_Success) 4584284677Sdim return Res; 4585284677Sdim 4586309124Sdim if (ConvertResult && !ConvertResult(Value)) { 4587353358Sdim Error(S, "invalid " + StringRef(Prefix) + " value."); 4588309124Sdim } 4589309124Sdim 4590314564Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy)); 4591284677Sdim return MatchOperand_Success; 4592284677Sdim} 4593284677Sdim 4594353358SdimOperandMatchResultTy 4595353358SdimAMDGPUAsmParser::parseOperandArrayWithPrefix(const char *Prefix, 4596353358Sdim OperandVector &Operands, 4597353358Sdim AMDGPUOperand::ImmTy ImmTy, 4598353358Sdim bool (*ConvertResult)(int64_t&)) { 4599353358Sdim SMLoc S = getLoc(); 4600353358Sdim if (!trySkipId(Prefix, AsmToken::Colon)) 4601321369Sdim return MatchOperand_NoMatch; 4602321369Sdim 4603353358Sdim if (!skipToken(AsmToken::LBrac, "expected a left square bracket")) 4604321369Sdim return MatchOperand_ParseFail; 4605321369Sdim 4606321369Sdim unsigned Val = 0; 4607353358Sdim const unsigned MaxSize = 4; 4608321369Sdim 4609321369Sdim // FIXME: How to verify the number of elements matches the number of src 4610321369Sdim // operands? 4611353358Sdim for (int I = 0; ; ++I) { 4612353358Sdim int64_t Op; 4613353358Sdim SMLoc Loc = getLoc(); 4614353358Sdim if (!parseExpr(Op)) 4615353358Sdim return MatchOperand_ParseFail; 4616321369Sdim 4617353358Sdim if (Op != 0 && Op != 1) { 4618353358Sdim Error(Loc, "invalid " + StringRef(Prefix) + " value."); 4619353358Sdim return MatchOperand_ParseFail; 4620321369Sdim } 4621321369Sdim 4622353358Sdim Val |= (Op << I); 4623321369Sdim 4624353358Sdim if (trySkipToken(AsmToken::RBrac)) 4625353358Sdim break; 4626353358Sdim 4627353358Sdim if (I + 1 == MaxSize) { 4628353358Sdim Error(getLoc(), "expected a closing square bracket"); 4629321369Sdim return MatchOperand_ParseFail; 4630353358Sdim } 4631321369Sdim 4632353358Sdim if (!skipToken(AsmToken::Comma, "expected a comma")) 4633321369Sdim return MatchOperand_ParseFail; 4634321369Sdim } 4635321369Sdim 4636321369Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy)); 4637321369Sdim return MatchOperand_Success; 4638321369Sdim} 4639321369Sdim 4640314564SdimOperandMatchResultTy 4641284677SdimAMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands, 4642321369Sdim AMDGPUOperand::ImmTy ImmTy) { 4643284677Sdim int64_t Bit = 0; 4644284677Sdim SMLoc S = Parser.getTok().getLoc(); 4645284677Sdim 4646284677Sdim // We are at the end of the statement, and this is a default argument, so 4647284677Sdim // use a default value. 4648284677Sdim if (getLexer().isNot(AsmToken::EndOfStatement)) { 4649284677Sdim switch(getLexer().getKind()) { 4650284677Sdim case AsmToken::Identifier: { 4651284677Sdim StringRef Tok = Parser.getTok().getString(); 4652284677Sdim if (Tok == Name) { 4653344779Sdim if (Tok == "r128" && isGFX9()) 4654344779Sdim Error(S, "r128 modifier is not supported on this GPU"); 4655353358Sdim if (Tok == "a16" && !isGFX9() && !isGFX10()) 4656344779Sdim Error(S, "a16 modifier is not supported on this GPU"); 4657284677Sdim Bit = 1; 4658284677Sdim Parser.Lex(); 4659284677Sdim } else if (Tok.startswith("no") && Tok.endswith(Name)) { 4660284677Sdim Bit = 0; 4661284677Sdim Parser.Lex(); 4662284677Sdim } else { 4663284677Sdim return MatchOperand_NoMatch; 4664284677Sdim } 4665284677Sdim break; 4666284677Sdim } 4667284677Sdim default: 4668284677Sdim return MatchOperand_NoMatch; 4669284677Sdim } 4670284677Sdim } 4671284677Sdim 4672353358Sdim if (!isGFX10() && ImmTy == AMDGPUOperand::ImmTyDLC) 4673353358Sdim return MatchOperand_ParseFail; 4674353358Sdim 4675314564Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy)); 4676284677Sdim return MatchOperand_Success; 4677284677Sdim} 4678284677Sdim 4679321369Sdimstatic void addOptionalImmOperand( 4680321369Sdim MCInst& Inst, const OperandVector& Operands, 4681321369Sdim AMDGPUAsmParser::OptionalImmIndexMap& OptionalIdx, 4682321369Sdim AMDGPUOperand::ImmTy ImmT, 4683321369Sdim int64_t Default = 0) { 4684309124Sdim auto i = OptionalIdx.find(ImmT); 4685309124Sdim if (i != OptionalIdx.end()) { 4686309124Sdim unsigned Idx = i->second; 4687309124Sdim ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1); 4688309124Sdim } else { 4689309124Sdim Inst.addOperand(MCOperand::createImm(Default)); 4690284677Sdim } 4691284677Sdim} 4692284677Sdim 4693314564SdimOperandMatchResultTy 4694309124SdimAMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) { 4695309124Sdim if (getLexer().isNot(AsmToken::Identifier)) { 4696309124Sdim return MatchOperand_NoMatch; 4697309124Sdim } 4698309124Sdim StringRef Tok = Parser.getTok().getString(); 4699309124Sdim if (Tok != Prefix) { 4700309124Sdim return MatchOperand_NoMatch; 4701309124Sdim } 4702284677Sdim 4703309124Sdim Parser.Lex(); 4704309124Sdim if (getLexer().isNot(AsmToken::Colon)) { 4705309124Sdim return MatchOperand_ParseFail; 4706309124Sdim } 4707284677Sdim 4708309124Sdim Parser.Lex(); 4709309124Sdim if (getLexer().isNot(AsmToken::Identifier)) { 4710309124Sdim return MatchOperand_ParseFail; 4711309124Sdim } 4712284677Sdim 4713309124Sdim Value = Parser.getTok().getString(); 4714309124Sdim return MatchOperand_Success; 4715284677Sdim} 4716284677Sdim 4717344779Sdim// dfmt and nfmt (in a tbuffer instruction) are parsed as one to allow their 4718344779Sdim// values to live in a joint format operand in the MCInst encoding. 4719344779SdimOperandMatchResultTy 4720344779SdimAMDGPUAsmParser::parseDfmtNfmt(OperandVector &Operands) { 4721344779Sdim SMLoc S = Parser.getTok().getLoc(); 4722344779Sdim int64_t Dfmt = 0, Nfmt = 0; 4723344779Sdim // dfmt and nfmt can appear in either order, and each is optional. 4724344779Sdim bool GotDfmt = false, GotNfmt = false; 4725344779Sdim while (!GotDfmt || !GotNfmt) { 4726344779Sdim if (!GotDfmt) { 4727344779Sdim auto Res = parseIntWithPrefix("dfmt", Dfmt); 4728344779Sdim if (Res != MatchOperand_NoMatch) { 4729344779Sdim if (Res != MatchOperand_Success) 4730344779Sdim return Res; 4731344779Sdim if (Dfmt >= 16) { 4732344779Sdim Error(Parser.getTok().getLoc(), "out of range dfmt"); 4733344779Sdim return MatchOperand_ParseFail; 4734344779Sdim } 4735344779Sdim GotDfmt = true; 4736344779Sdim Parser.Lex(); 4737344779Sdim continue; 4738344779Sdim } 4739344779Sdim } 4740344779Sdim if (!GotNfmt) { 4741344779Sdim auto Res = parseIntWithPrefix("nfmt", Nfmt); 4742344779Sdim if (Res != MatchOperand_NoMatch) { 4743344779Sdim if (Res != MatchOperand_Success) 4744344779Sdim return Res; 4745344779Sdim if (Nfmt >= 8) { 4746344779Sdim Error(Parser.getTok().getLoc(), "out of range nfmt"); 4747344779Sdim return MatchOperand_ParseFail; 4748344779Sdim } 4749344779Sdim GotNfmt = true; 4750344779Sdim Parser.Lex(); 4751344779Sdim continue; 4752344779Sdim } 4753344779Sdim } 4754344779Sdim break; 4755344779Sdim } 4756344779Sdim if (!GotDfmt && !GotNfmt) 4757344779Sdim return MatchOperand_NoMatch; 4758344779Sdim auto Format = Dfmt | Nfmt << 4; 4759344779Sdim Operands.push_back( 4760344779Sdim AMDGPUOperand::CreateImm(this, Format, S, AMDGPUOperand::ImmTyFORMAT)); 4761344779Sdim return MatchOperand_Success; 4762344779Sdim} 4763344779Sdim 4764284677Sdim//===----------------------------------------------------------------------===// 4765284677Sdim// ds 4766284677Sdim//===----------------------------------------------------------------------===// 4767284677Sdim 4768284677Sdimvoid AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst, 4769284677Sdim const OperandVector &Operands) { 4770309124Sdim OptionalImmIndexMap OptionalIdx; 4771284677Sdim 4772284677Sdim for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 4773284677Sdim AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 4774284677Sdim 4775284677Sdim // Add the register arguments 4776284677Sdim if (Op.isReg()) { 4777284677Sdim Op.addRegOperands(Inst, 1); 4778284677Sdim continue; 4779284677Sdim } 4780284677Sdim 4781284677Sdim // Handle optional arguments 4782284677Sdim OptionalIdx[Op.getImmTy()] = i; 4783284677Sdim } 4784284677Sdim 4785309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0); 4786309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1); 4787309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 4788284677Sdim 4789284677Sdim Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 4790284677Sdim} 4791284677Sdim 4792321369Sdimvoid AMDGPUAsmParser::cvtDSImpl(MCInst &Inst, const OperandVector &Operands, 4793321369Sdim bool IsGdsHardcoded) { 4794321369Sdim OptionalImmIndexMap OptionalIdx; 4795284677Sdim 4796284677Sdim for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 4797284677Sdim AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 4798284677Sdim 4799284677Sdim // Add the register arguments 4800284677Sdim if (Op.isReg()) { 4801284677Sdim Op.addRegOperands(Inst, 1); 4802284677Sdim continue; 4803284677Sdim } 4804284677Sdim 4805284677Sdim if (Op.isToken() && Op.getToken() == "gds") { 4806321369Sdim IsGdsHardcoded = true; 4807284677Sdim continue; 4808284677Sdim } 4809284677Sdim 4810284677Sdim // Handle optional arguments 4811284677Sdim OptionalIdx[Op.getImmTy()] = i; 4812284677Sdim } 4813284677Sdim 4814321369Sdim AMDGPUOperand::ImmTy OffsetType = 4815353358Sdim (Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_gfx10 || 4816353358Sdim Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_gfx6_gfx7 || 4817321369Sdim Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_vi) ? AMDGPUOperand::ImmTySwizzle : 4818321369Sdim AMDGPUOperand::ImmTyOffset; 4819284677Sdim 4820321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, OffsetType); 4821321369Sdim 4822321369Sdim if (!IsGdsHardcoded) { 4823309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 4824284677Sdim } 4825284677Sdim Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 4826284677Sdim} 4827284677Sdim 4828314564Sdimvoid AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) { 4829314564Sdim OptionalImmIndexMap OptionalIdx; 4830284677Sdim 4831321369Sdim unsigned OperandIdx[4]; 4832314564Sdim unsigned EnMask = 0; 4833314564Sdim int SrcIdx = 0; 4834314564Sdim 4835314564Sdim for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 4836314564Sdim AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 4837314564Sdim 4838314564Sdim // Add the register arguments 4839314564Sdim if (Op.isReg()) { 4840321369Sdim assert(SrcIdx < 4); 4841321369Sdim OperandIdx[SrcIdx] = Inst.size(); 4842314564Sdim Op.addRegOperands(Inst, 1); 4843314564Sdim ++SrcIdx; 4844314564Sdim continue; 4845314564Sdim } 4846314564Sdim 4847314564Sdim if (Op.isOff()) { 4848321369Sdim assert(SrcIdx < 4); 4849321369Sdim OperandIdx[SrcIdx] = Inst.size(); 4850321369Sdim Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister)); 4851314564Sdim ++SrcIdx; 4852314564Sdim continue; 4853314564Sdim } 4854314564Sdim 4855314564Sdim if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) { 4856314564Sdim Op.addImmOperands(Inst, 1); 4857314564Sdim continue; 4858314564Sdim } 4859314564Sdim 4860314564Sdim if (Op.isToken() && Op.getToken() == "done") 4861314564Sdim continue; 4862314564Sdim 4863314564Sdim // Handle optional arguments 4864314564Sdim OptionalIdx[Op.getImmTy()] = i; 4865314564Sdim } 4866314564Sdim 4867321369Sdim assert(SrcIdx == 4); 4868321369Sdim 4869321369Sdim bool Compr = false; 4870321369Sdim if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) { 4871321369Sdim Compr = true; 4872321369Sdim Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]); 4873321369Sdim Inst.getOperand(OperandIdx[2]).setReg(AMDGPU::NoRegister); 4874321369Sdim Inst.getOperand(OperandIdx[3]).setReg(AMDGPU::NoRegister); 4875321369Sdim } 4876321369Sdim 4877321369Sdim for (auto i = 0; i < SrcIdx; ++i) { 4878321369Sdim if (Inst.getOperand(OperandIdx[i]).getReg() != AMDGPU::NoRegister) { 4879321369Sdim EnMask |= Compr? (0x3 << i * 2) : (0x1 << i); 4880321369Sdim } 4881321369Sdim } 4882321369Sdim 4883314564Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM); 4884314564Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr); 4885314564Sdim 4886314564Sdim Inst.addOperand(MCOperand::createImm(EnMask)); 4887314564Sdim} 4888314564Sdim 4889284677Sdim//===----------------------------------------------------------------------===// 4890284677Sdim// s_waitcnt 4891284677Sdim//===----------------------------------------------------------------------===// 4892284677Sdim 4893321369Sdimstatic bool 4894321369SdimencodeCnt( 4895344779Sdim const AMDGPU::IsaVersion ISA, 4896321369Sdim int64_t &IntVal, 4897321369Sdim int64_t CntVal, 4898321369Sdim bool Saturate, 4899344779Sdim unsigned (*encode)(const IsaVersion &Version, unsigned, unsigned), 4900344779Sdim unsigned (*decode)(const IsaVersion &Version, unsigned)) 4901321369Sdim{ 4902321369Sdim bool Failed = false; 4903321369Sdim 4904321369Sdim IntVal = encode(ISA, IntVal, CntVal); 4905321369Sdim if (CntVal != decode(ISA, IntVal)) { 4906321369Sdim if (Saturate) { 4907321369Sdim IntVal = encode(ISA, IntVal, -1); 4908321369Sdim } else { 4909321369Sdim Failed = true; 4910321369Sdim } 4911321369Sdim } 4912321369Sdim return Failed; 4913321369Sdim} 4914321369Sdim 4915284677Sdimbool AMDGPUAsmParser::parseCnt(int64_t &IntVal) { 4916284677Sdim 4917353358Sdim SMLoc CntLoc = getLoc(); 4918353358Sdim StringRef CntName = getTokenStr(); 4919284677Sdim 4920353358Sdim if (!skipToken(AsmToken::Identifier, "expected a counter name") || 4921353358Sdim !skipToken(AsmToken::LParen, "expected a left parenthesis")) 4922353358Sdim return false; 4923284677Sdim 4924353358Sdim int64_t CntVal; 4925353358Sdim SMLoc ValLoc = getLoc(); 4926353358Sdim if (!parseExpr(CntVal)) 4927353358Sdim return false; 4928284677Sdim 4929344779Sdim AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU()); 4930321369Sdim 4931321369Sdim bool Failed = true; 4932321369Sdim bool Sat = CntName.endswith("_sat"); 4933321369Sdim 4934321369Sdim if (CntName == "vmcnt" || CntName == "vmcnt_sat") { 4935321369Sdim Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt); 4936321369Sdim } else if (CntName == "expcnt" || CntName == "expcnt_sat") { 4937321369Sdim Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt); 4938321369Sdim } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") { 4939321369Sdim Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt); 4940353358Sdim } else { 4941353358Sdim Error(CntLoc, "invalid counter name " + CntName); 4942353358Sdim return false; 4943321369Sdim } 4944321369Sdim 4945321369Sdim if (Failed) { 4946321369Sdim Error(ValLoc, "too large value for " + CntName); 4947353358Sdim return false; 4948321369Sdim } 4949284677Sdim 4950353358Sdim if (!skipToken(AsmToken::RParen, "expected a closing parenthesis")) 4951353358Sdim return false; 4952321369Sdim 4953353358Sdim if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) { 4954353358Sdim if (isToken(AsmToken::EndOfStatement)) { 4955353358Sdim Error(getLoc(), "expected a counter name"); 4956353358Sdim return false; 4957321369Sdim } 4958321369Sdim } 4959284677Sdim 4960353358Sdim return true; 4961284677Sdim} 4962284677Sdim 4963314564SdimOperandMatchResultTy 4964284677SdimAMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) { 4965344779Sdim AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU()); 4966321369Sdim int64_t Waitcnt = getWaitcntBitMask(ISA); 4967353358Sdim SMLoc S = getLoc(); 4968284677Sdim 4969353358Sdim // If parse failed, do not return error code 4970353358Sdim // to avoid excessive error messages. 4971353358Sdim if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) { 4972353358Sdim while (parseCnt(Waitcnt) && !isToken(AsmToken::EndOfStatement)); 4973353358Sdim } else { 4974353358Sdim parseExpr(Waitcnt); 4975353358Sdim } 4976284677Sdim 4977314564Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S)); 4978284677Sdim return MatchOperand_Success; 4979284677Sdim} 4980284677Sdim 4981353358Sdimbool 4982353358SdimAMDGPUOperand::isSWaitCnt() const { 4983353358Sdim return isImm(); 4984353358Sdim} 4985309124Sdim 4986353358Sdim//===----------------------------------------------------------------------===// 4987353358Sdim// hwreg 4988353358Sdim//===----------------------------------------------------------------------===// 4989309124Sdim 4990353358Sdimbool 4991353358SdimAMDGPUAsmParser::parseHwregBody(OperandInfoTy &HwReg, 4992353358Sdim int64_t &Offset, 4993353358Sdim int64_t &Width) { 4994353358Sdim using namespace llvm::AMDGPU::Hwreg; 4995309124Sdim 4996353358Sdim // The register may be specified by name or using a numeric code 4997353358Sdim if (isToken(AsmToken::Identifier) && 4998353358Sdim (HwReg.Id = getHwregId(getTokenStr())) >= 0) { 4999309124Sdim HwReg.IsSymbolic = true; 5000353358Sdim lex(); // skip message name 5001353358Sdim } else if (!parseExpr(HwReg.Id)) { 5002309124Sdim return false; 5003309124Sdim } 5004309124Sdim 5005353358Sdim if (trySkipToken(AsmToken::RParen)) 5006309124Sdim return true; 5007309124Sdim 5008353358Sdim // parse optional params 5009353358Sdim return 5010353358Sdim skipToken(AsmToken::Comma, "expected a comma or a closing parenthesis") && 5011353358Sdim parseExpr(Offset) && 5012353358Sdim skipToken(AsmToken::Comma, "expected a comma") && 5013353358Sdim parseExpr(Width) && 5014353358Sdim skipToken(AsmToken::RParen, "expected a closing parenthesis"); 5015353358Sdim} 5016309124Sdim 5017353358Sdimbool 5018353358SdimAMDGPUAsmParser::validateHwreg(const OperandInfoTy &HwReg, 5019353358Sdim const int64_t Offset, 5020353358Sdim const int64_t Width, 5021353358Sdim const SMLoc Loc) { 5022309124Sdim 5023353358Sdim using namespace llvm::AMDGPU::Hwreg; 5024309124Sdim 5025353358Sdim if (HwReg.IsSymbolic && !isValidHwreg(HwReg.Id, getSTI())) { 5026353358Sdim Error(Loc, "specified hardware register is not supported on this GPU"); 5027353358Sdim return false; 5028353358Sdim } else if (!isValidHwreg(HwReg.Id)) { 5029353358Sdim Error(Loc, "invalid code of hardware register: only 6-bit values are legal"); 5030353358Sdim return false; 5031353358Sdim } else if (!isValidHwregOffset(Offset)) { 5032353358Sdim Error(Loc, "invalid bit offset: only 5-bit values are legal"); 5033353358Sdim return false; 5034353358Sdim } else if (!isValidHwregWidth(Width)) { 5035353358Sdim Error(Loc, "invalid bitfield width: only values from 1 to 32 are legal"); 5036353358Sdim return false; 5037353358Sdim } 5038353358Sdim return true; 5039309124Sdim} 5040309124Sdim 5041353358SdimOperandMatchResultTy 5042353358SdimAMDGPUAsmParser::parseHwreg(OperandVector &Operands) { 5043309124Sdim using namespace llvm::AMDGPU::Hwreg; 5044309124Sdim 5045353358Sdim int64_t ImmVal = 0; 5046353358Sdim SMLoc Loc = getLoc(); 5047309124Sdim 5048353358Sdim // If parse failed, do not return error code 5049353358Sdim // to avoid excessive error messages. 5050353358Sdim if (trySkipId("hwreg", AsmToken::LParen)) { 5051353358Sdim OperandInfoTy HwReg(ID_UNKNOWN_); 5052353358Sdim int64_t Offset = OFFSET_DEFAULT_; 5053353358Sdim int64_t Width = WIDTH_DEFAULT_; 5054353358Sdim if (parseHwregBody(HwReg, Offset, Width) && 5055353358Sdim validateHwreg(HwReg, Offset, Width, Loc)) { 5056353358Sdim ImmVal = encodeHwreg(HwReg.Id, Offset, Width); 5057353358Sdim } 5058353358Sdim } else if (parseExpr(ImmVal)) { 5059353358Sdim if (ImmVal < 0 || !isUInt<16>(ImmVal)) 5060353358Sdim Error(Loc, "invalid immediate: only 16-bit values are legal"); 5061353358Sdim } 5062309124Sdim 5063353358Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTyHwreg)); 5064309124Sdim return MatchOperand_Success; 5065309124Sdim} 5066309124Sdim 5067309124Sdimbool AMDGPUOperand::isHwreg() const { 5068309124Sdim return isImmTy(ImmTyHwreg); 5069309124Sdim} 5070309124Sdim 5071353358Sdim//===----------------------------------------------------------------------===// 5072353358Sdim// sendmsg 5073353358Sdim//===----------------------------------------------------------------------===// 5074353358Sdim 5075353358Sdimbool 5076353358SdimAMDGPUAsmParser::parseSendMsgBody(OperandInfoTy &Msg, 5077353358Sdim OperandInfoTy &Op, 5078353358Sdim OperandInfoTy &Stream) { 5079309124Sdim using namespace llvm::AMDGPU::SendMsg; 5080309124Sdim 5081353358Sdim if (isToken(AsmToken::Identifier) && (Msg.Id = getMsgId(getTokenStr())) >= 0) { 5082353358Sdim Msg.IsSymbolic = true; 5083353358Sdim lex(); // skip message name 5084353358Sdim } else if (!parseExpr(Msg.Id)) { 5085353358Sdim return false; 5086353358Sdim } 5087309124Sdim 5088353358Sdim if (trySkipToken(AsmToken::Comma)) { 5089353358Sdim Op.IsDefined = true; 5090353358Sdim if (isToken(AsmToken::Identifier) && 5091353358Sdim (Op.Id = getMsgOpId(Msg.Id, getTokenStr())) >= 0) { 5092353358Sdim lex(); // skip operation name 5093353358Sdim } else if (!parseExpr(Op.Id)) { 5094353358Sdim return false; 5095353358Sdim } 5096309124Sdim 5097353358Sdim if (trySkipToken(AsmToken::Comma)) { 5098353358Sdim Stream.IsDefined = true; 5099353358Sdim if (!parseExpr(Stream.Id)) 5100353358Sdim return false; 5101309124Sdim } 5102309124Sdim } 5103309124Sdim 5104353358Sdim return skipToken(AsmToken::RParen, "expected a closing parenthesis"); 5105353358Sdim} 5106353358Sdim 5107353358Sdimbool 5108353358SdimAMDGPUAsmParser::validateSendMsg(const OperandInfoTy &Msg, 5109353358Sdim const OperandInfoTy &Op, 5110353358Sdim const OperandInfoTy &Stream, 5111353358Sdim const SMLoc S) { 5112353358Sdim using namespace llvm::AMDGPU::SendMsg; 5113353358Sdim 5114353358Sdim // Validation strictness depends on whether message is specified 5115353358Sdim // in a symbolc or in a numeric form. In the latter case 5116353358Sdim // only encoding possibility is checked. 5117353358Sdim bool Strict = Msg.IsSymbolic; 5118353358Sdim 5119353358Sdim if (!isValidMsgId(Msg.Id, getSTI(), Strict)) { 5120353358Sdim Error(S, "invalid message id"); 5121309124Sdim return false; 5122353358Sdim } else if (Strict && (msgRequiresOp(Msg.Id) != Op.IsDefined)) { 5123353358Sdim Error(S, Op.IsDefined ? 5124353358Sdim "message does not support operations" : 5125353358Sdim "missing message operation"); 5126353358Sdim return false; 5127353358Sdim } else if (!isValidMsgOp(Msg.Id, Op.Id, Strict)) { 5128353358Sdim Error(S, "invalid operation id"); 5129353358Sdim return false; 5130353358Sdim } else if (Strict && !msgSupportsStream(Msg.Id, Op.Id) && Stream.IsDefined) { 5131353358Sdim Error(S, "message operation does not support streams"); 5132353358Sdim return false; 5133353358Sdim } else if (!isValidMsgStream(Msg.Id, Op.Id, Stream.Id, Strict)) { 5134353358Sdim Error(S, "invalid message stream id"); 5135353358Sdim return false; 5136309124Sdim } 5137353358Sdim return true; 5138353358Sdim} 5139309124Sdim 5140353358SdimOperandMatchResultTy 5141353358SdimAMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) { 5142353358Sdim using namespace llvm::AMDGPU::SendMsg; 5143309124Sdim 5144353358Sdim int64_t ImmVal = 0; 5145353358Sdim SMLoc Loc = getLoc(); 5146353358Sdim 5147353358Sdim // If parse failed, do not return error code 5148353358Sdim // to avoid excessive error messages. 5149353358Sdim if (trySkipId("sendmsg", AsmToken::LParen)) { 5150353358Sdim OperandInfoTy Msg(ID_UNKNOWN_); 5151353358Sdim OperandInfoTy Op(OP_NONE_); 5152353358Sdim OperandInfoTy Stream(STREAM_ID_NONE_); 5153353358Sdim if (parseSendMsgBody(Msg, Op, Stream) && 5154353358Sdim validateSendMsg(Msg, Op, Stream, Loc)) { 5155353358Sdim ImmVal = encodeMsg(Msg.Id, Op.Id, Stream.Id); 5156309124Sdim } 5157353358Sdim } else if (parseExpr(ImmVal)) { 5158353358Sdim if (ImmVal < 0 || !isUInt<16>(ImmVal)) 5159353358Sdim Error(Loc, "invalid immediate: only 16-bit values are legal"); 5160309124Sdim } 5161309124Sdim 5162353358Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTySendMsg)); 5163353358Sdim return MatchOperand_Success; 5164353358Sdim} 5165309124Sdim 5166353358Sdimbool AMDGPUOperand::isSendMsg() const { 5167353358Sdim return isImmTy(ImmTySendMsg); 5168353358Sdim} 5169309124Sdim 5170353358Sdim//===----------------------------------------------------------------------===// 5171353358Sdim// v_interp 5172353358Sdim//===----------------------------------------------------------------------===// 5173309124Sdim 5174314564SdimOperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) { 5175314564Sdim if (getLexer().getKind() != AsmToken::Identifier) 5176314564Sdim return MatchOperand_NoMatch; 5177314564Sdim 5178314564Sdim StringRef Str = Parser.getTok().getString(); 5179314564Sdim int Slot = StringSwitch<int>(Str) 5180314564Sdim .Case("p10", 0) 5181314564Sdim .Case("p20", 1) 5182314564Sdim .Case("p0", 2) 5183314564Sdim .Default(-1); 5184314564Sdim 5185314564Sdim SMLoc S = Parser.getTok().getLoc(); 5186314564Sdim if (Slot == -1) 5187314564Sdim return MatchOperand_ParseFail; 5188314564Sdim 5189314564Sdim Parser.Lex(); 5190314564Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S, 5191314564Sdim AMDGPUOperand::ImmTyInterpSlot)); 5192314564Sdim return MatchOperand_Success; 5193314564Sdim} 5194314564Sdim 5195314564SdimOperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) { 5196314564Sdim if (getLexer().getKind() != AsmToken::Identifier) 5197314564Sdim return MatchOperand_NoMatch; 5198314564Sdim 5199314564Sdim StringRef Str = Parser.getTok().getString(); 5200314564Sdim if (!Str.startswith("attr")) 5201314564Sdim return MatchOperand_NoMatch; 5202314564Sdim 5203314564Sdim StringRef Chan = Str.take_back(2); 5204314564Sdim int AttrChan = StringSwitch<int>(Chan) 5205314564Sdim .Case(".x", 0) 5206314564Sdim .Case(".y", 1) 5207314564Sdim .Case(".z", 2) 5208314564Sdim .Case(".w", 3) 5209314564Sdim .Default(-1); 5210314564Sdim if (AttrChan == -1) 5211314564Sdim return MatchOperand_ParseFail; 5212314564Sdim 5213314564Sdim Str = Str.drop_back(2).drop_front(4); 5214314564Sdim 5215314564Sdim uint8_t Attr; 5216314564Sdim if (Str.getAsInteger(10, Attr)) 5217314564Sdim return MatchOperand_ParseFail; 5218314564Sdim 5219314564Sdim SMLoc S = Parser.getTok().getLoc(); 5220314564Sdim Parser.Lex(); 5221314564Sdim if (Attr > 63) { 5222314564Sdim Error(S, "out of bounds attr"); 5223314564Sdim return MatchOperand_Success; 5224314564Sdim } 5225314564Sdim 5226314564Sdim SMLoc SChan = SMLoc::getFromPointer(Chan.data()); 5227314564Sdim 5228314564Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S, 5229314564Sdim AMDGPUOperand::ImmTyInterpAttr)); 5230314564Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan, 5231314564Sdim AMDGPUOperand::ImmTyAttrChan)); 5232314564Sdim return MatchOperand_Success; 5233314564Sdim} 5234314564Sdim 5235353358Sdim//===----------------------------------------------------------------------===// 5236353358Sdim// exp 5237353358Sdim//===----------------------------------------------------------------------===// 5238353358Sdim 5239314564Sdimvoid AMDGPUAsmParser::errorExpTgt() { 5240314564Sdim Error(Parser.getTok().getLoc(), "invalid exp target"); 5241314564Sdim} 5242314564Sdim 5243314564SdimOperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str, 5244314564Sdim uint8_t &Val) { 5245314564Sdim if (Str == "null") { 5246314564Sdim Val = 9; 5247314564Sdim return MatchOperand_Success; 5248314564Sdim } 5249314564Sdim 5250314564Sdim if (Str.startswith("mrt")) { 5251314564Sdim Str = Str.drop_front(3); 5252314564Sdim if (Str == "z") { // == mrtz 5253314564Sdim Val = 8; 5254314564Sdim return MatchOperand_Success; 5255314564Sdim } 5256314564Sdim 5257314564Sdim if (Str.getAsInteger(10, Val)) 5258314564Sdim return MatchOperand_ParseFail; 5259314564Sdim 5260314564Sdim if (Val > 7) 5261314564Sdim errorExpTgt(); 5262314564Sdim 5263314564Sdim return MatchOperand_Success; 5264314564Sdim } 5265314564Sdim 5266314564Sdim if (Str.startswith("pos")) { 5267314564Sdim Str = Str.drop_front(3); 5268314564Sdim if (Str.getAsInteger(10, Val)) 5269314564Sdim return MatchOperand_ParseFail; 5270314564Sdim 5271353358Sdim if (Val > 4 || (Val == 4 && !isGFX10())) 5272314564Sdim errorExpTgt(); 5273314564Sdim 5274314564Sdim Val += 12; 5275314564Sdim return MatchOperand_Success; 5276314564Sdim } 5277314564Sdim 5278353358Sdim if (isGFX10() && Str == "prim") { 5279353358Sdim Val = 20; 5280353358Sdim return MatchOperand_Success; 5281353358Sdim } 5282353358Sdim 5283314564Sdim if (Str.startswith("param")) { 5284314564Sdim Str = Str.drop_front(5); 5285314564Sdim if (Str.getAsInteger(10, Val)) 5286314564Sdim return MatchOperand_ParseFail; 5287314564Sdim 5288314564Sdim if (Val >= 32) 5289314564Sdim errorExpTgt(); 5290314564Sdim 5291314564Sdim Val += 32; 5292314564Sdim return MatchOperand_Success; 5293314564Sdim } 5294314564Sdim 5295314564Sdim if (Str.startswith("invalid_target_")) { 5296314564Sdim Str = Str.drop_front(15); 5297314564Sdim if (Str.getAsInteger(10, Val)) 5298314564Sdim return MatchOperand_ParseFail; 5299314564Sdim 5300314564Sdim errorExpTgt(); 5301314564Sdim return MatchOperand_Success; 5302314564Sdim } 5303314564Sdim 5304314564Sdim return MatchOperand_NoMatch; 5305314564Sdim} 5306314564Sdim 5307314564SdimOperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) { 5308314564Sdim uint8_t Val; 5309314564Sdim StringRef Str = Parser.getTok().getString(); 5310314564Sdim 5311314564Sdim auto Res = parseExpTgtImpl(Str, Val); 5312314564Sdim if (Res != MatchOperand_Success) 5313314564Sdim return Res; 5314314564Sdim 5315314564Sdim SMLoc S = Parser.getTok().getLoc(); 5316314564Sdim Parser.Lex(); 5317314564Sdim 5318314564Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, 5319314564Sdim AMDGPUOperand::ImmTyExpTgt)); 5320314564Sdim return MatchOperand_Success; 5321314564Sdim} 5322314564Sdim 5323353358Sdim//===----------------------------------------------------------------------===// 5324353358Sdim// parser helpers 5325353358Sdim//===----------------------------------------------------------------------===// 5326309124Sdim 5327353358Sdimbool 5328353358SdimAMDGPUAsmParser::isId(const AsmToken &Token, const StringRef Id) const { 5329353358Sdim return Token.is(AsmToken::Identifier) && Token.getString() == Id; 5330353358Sdim} 5331309124Sdim 5332353358Sdimbool 5333353358SdimAMDGPUAsmParser::isId(const StringRef Id) const { 5334353358Sdim return isId(getToken(), Id); 5335309124Sdim} 5336309124Sdim 5337353358Sdimbool 5338353358SdimAMDGPUAsmParser::isToken(const AsmToken::TokenKind Kind) const { 5339353358Sdim return getTokenKind() == Kind; 5340309124Sdim} 5341309124Sdim 5342321369Sdimbool 5343321369SdimAMDGPUAsmParser::trySkipId(const StringRef Id) { 5344353358Sdim if (isId(Id)) { 5345353358Sdim lex(); 5346321369Sdim return true; 5347321369Sdim } 5348321369Sdim return false; 5349321369Sdim} 5350321369Sdim 5351321369Sdimbool 5352353358SdimAMDGPUAsmParser::trySkipId(const StringRef Id, const AsmToken::TokenKind Kind) { 5353353358Sdim if (isId(Id) && peekToken().is(Kind)) { 5354353358Sdim lex(); 5355353358Sdim lex(); 5356353358Sdim return true; 5357353358Sdim } 5358353358Sdim return false; 5359353358Sdim} 5360353358Sdim 5361353358Sdimbool 5362321369SdimAMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) { 5363353358Sdim if (isToken(Kind)) { 5364353358Sdim lex(); 5365321369Sdim return true; 5366321369Sdim } 5367321369Sdim return false; 5368321369Sdim} 5369321369Sdim 5370321369Sdimbool 5371321369SdimAMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind, 5372321369Sdim const StringRef ErrMsg) { 5373321369Sdim if (!trySkipToken(Kind)) { 5374353358Sdim Error(getLoc(), ErrMsg); 5375321369Sdim return false; 5376321369Sdim } 5377321369Sdim return true; 5378321369Sdim} 5379321369Sdim 5380321369Sdimbool 5381321369SdimAMDGPUAsmParser::parseExpr(int64_t &Imm) { 5382321369Sdim return !getParser().parseAbsoluteExpression(Imm); 5383321369Sdim} 5384321369Sdim 5385321369Sdimbool 5386360784SdimAMDGPUAsmParser::parseExpr(OperandVector &Operands) { 5387360784Sdim SMLoc S = getLoc(); 5388360784Sdim 5389360784Sdim const MCExpr *Expr; 5390360784Sdim if (Parser.parseExpression(Expr)) 5391360784Sdim return false; 5392360784Sdim 5393360784Sdim int64_t IntVal; 5394360784Sdim if (Expr->evaluateAsAbsolute(IntVal)) { 5395360784Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S)); 5396360784Sdim } else { 5397360784Sdim Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S)); 5398360784Sdim } 5399360784Sdim return true; 5400360784Sdim} 5401360784Sdim 5402360784Sdimbool 5403321369SdimAMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) { 5404353358Sdim if (isToken(AsmToken::String)) { 5405353358Sdim Val = getToken().getStringContents(); 5406353358Sdim lex(); 5407321369Sdim return true; 5408321369Sdim } else { 5409353358Sdim Error(getLoc(), ErrMsg); 5410321369Sdim return false; 5411321369Sdim } 5412321369Sdim} 5413321369Sdim 5414353358SdimAsmToken 5415353358SdimAMDGPUAsmParser::getToken() const { 5416353358Sdim return Parser.getTok(); 5417353358Sdim} 5418353358Sdim 5419353358SdimAsmToken 5420353358SdimAMDGPUAsmParser::peekToken() { 5421353358Sdim return getLexer().peekTok(); 5422353358Sdim} 5423353358Sdim 5424353358Sdimvoid 5425353358SdimAMDGPUAsmParser::peekTokens(MutableArrayRef<AsmToken> Tokens) { 5426353358Sdim auto TokCount = getLexer().peekTokens(Tokens); 5427353358Sdim 5428353358Sdim for (auto Idx = TokCount; Idx < Tokens.size(); ++Idx) 5429353358Sdim Tokens[Idx] = AsmToken(AsmToken::Error, ""); 5430353358Sdim} 5431353358Sdim 5432353358SdimAsmToken::TokenKind 5433353358SdimAMDGPUAsmParser::getTokenKind() const { 5434353358Sdim return getLexer().getKind(); 5435353358Sdim} 5436353358Sdim 5437353358SdimSMLoc 5438353358SdimAMDGPUAsmParser::getLoc() const { 5439353358Sdim return getToken().getLoc(); 5440353358Sdim} 5441353358Sdim 5442353358SdimStringRef 5443353358SdimAMDGPUAsmParser::getTokenStr() const { 5444353358Sdim return getToken().getString(); 5445353358Sdim} 5446353358Sdim 5447353358Sdimvoid 5448353358SdimAMDGPUAsmParser::lex() { 5449353358Sdim Parser.Lex(); 5450353358Sdim} 5451353358Sdim 5452321369Sdim//===----------------------------------------------------------------------===// 5453321369Sdim// swizzle 5454321369Sdim//===----------------------------------------------------------------------===// 5455321369Sdim 5456321369SdimLLVM_READNONE 5457321369Sdimstatic unsigned 5458321369SdimencodeBitmaskPerm(const unsigned AndMask, 5459321369Sdim const unsigned OrMask, 5460321369Sdim const unsigned XorMask) { 5461321369Sdim using namespace llvm::AMDGPU::Swizzle; 5462321369Sdim 5463321369Sdim return BITMASK_PERM_ENC | 5464321369Sdim (AndMask << BITMASK_AND_SHIFT) | 5465321369Sdim (OrMask << BITMASK_OR_SHIFT) | 5466321369Sdim (XorMask << BITMASK_XOR_SHIFT); 5467321369Sdim} 5468321369Sdim 5469321369Sdimbool 5470321369SdimAMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t* Op, 5471321369Sdim const unsigned MinVal, 5472321369Sdim const unsigned MaxVal, 5473321369Sdim const StringRef ErrMsg) { 5474321369Sdim for (unsigned i = 0; i < OpNum; ++i) { 5475321369Sdim if (!skipToken(AsmToken::Comma, "expected a comma")){ 5476321369Sdim return false; 5477321369Sdim } 5478321369Sdim SMLoc ExprLoc = Parser.getTok().getLoc(); 5479321369Sdim if (!parseExpr(Op[i])) { 5480321369Sdim return false; 5481321369Sdim } 5482321369Sdim if (Op[i] < MinVal || Op[i] > MaxVal) { 5483321369Sdim Error(ExprLoc, ErrMsg); 5484321369Sdim return false; 5485321369Sdim } 5486321369Sdim } 5487321369Sdim 5488321369Sdim return true; 5489321369Sdim} 5490321369Sdim 5491321369Sdimbool 5492321369SdimAMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) { 5493321369Sdim using namespace llvm::AMDGPU::Swizzle; 5494321369Sdim 5495321369Sdim int64_t Lane[LANE_NUM]; 5496321369Sdim if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX, 5497321369Sdim "expected a 2-bit lane id")) { 5498321369Sdim Imm = QUAD_PERM_ENC; 5499353358Sdim for (unsigned I = 0; I < LANE_NUM; ++I) { 5500353358Sdim Imm |= Lane[I] << (LANE_SHIFT * I); 5501321369Sdim } 5502321369Sdim return true; 5503321369Sdim } 5504321369Sdim return false; 5505321369Sdim} 5506321369Sdim 5507321369Sdimbool 5508321369SdimAMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) { 5509321369Sdim using namespace llvm::AMDGPU::Swizzle; 5510321369Sdim 5511321369Sdim SMLoc S = Parser.getTok().getLoc(); 5512321369Sdim int64_t GroupSize; 5513321369Sdim int64_t LaneIdx; 5514321369Sdim 5515321369Sdim if (!parseSwizzleOperands(1, &GroupSize, 5516321369Sdim 2, 32, 5517321369Sdim "group size must be in the interval [2,32]")) { 5518321369Sdim return false; 5519321369Sdim } 5520321369Sdim if (!isPowerOf2_64(GroupSize)) { 5521321369Sdim Error(S, "group size must be a power of two"); 5522321369Sdim return false; 5523321369Sdim } 5524321369Sdim if (parseSwizzleOperands(1, &LaneIdx, 5525321369Sdim 0, GroupSize - 1, 5526321369Sdim "lane id must be in the interval [0,group size - 1]")) { 5527321369Sdim Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0); 5528321369Sdim return true; 5529321369Sdim } 5530321369Sdim return false; 5531321369Sdim} 5532321369Sdim 5533321369Sdimbool 5534321369SdimAMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) { 5535321369Sdim using namespace llvm::AMDGPU::Swizzle; 5536321369Sdim 5537321369Sdim SMLoc S = Parser.getTok().getLoc(); 5538321369Sdim int64_t GroupSize; 5539321369Sdim 5540321369Sdim if (!parseSwizzleOperands(1, &GroupSize, 5541321369Sdim 2, 32, "group size must be in the interval [2,32]")) { 5542321369Sdim return false; 5543321369Sdim } 5544321369Sdim if (!isPowerOf2_64(GroupSize)) { 5545321369Sdim Error(S, "group size must be a power of two"); 5546321369Sdim return false; 5547321369Sdim } 5548321369Sdim 5549321369Sdim Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1); 5550321369Sdim return true; 5551321369Sdim} 5552321369Sdim 5553321369Sdimbool 5554321369SdimAMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) { 5555321369Sdim using namespace llvm::AMDGPU::Swizzle; 5556321369Sdim 5557321369Sdim SMLoc S = Parser.getTok().getLoc(); 5558321369Sdim int64_t GroupSize; 5559321369Sdim 5560321369Sdim if (!parseSwizzleOperands(1, &GroupSize, 5561321369Sdim 1, 16, "group size must be in the interval [1,16]")) { 5562321369Sdim return false; 5563321369Sdim } 5564321369Sdim if (!isPowerOf2_64(GroupSize)) { 5565321369Sdim Error(S, "group size must be a power of two"); 5566321369Sdim return false; 5567321369Sdim } 5568321369Sdim 5569321369Sdim Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize); 5570321369Sdim return true; 5571321369Sdim} 5572321369Sdim 5573321369Sdimbool 5574321369SdimAMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) { 5575321369Sdim using namespace llvm::AMDGPU::Swizzle; 5576321369Sdim 5577321369Sdim if (!skipToken(AsmToken::Comma, "expected a comma")) { 5578321369Sdim return false; 5579321369Sdim } 5580321369Sdim 5581321369Sdim StringRef Ctl; 5582321369Sdim SMLoc StrLoc = Parser.getTok().getLoc(); 5583321369Sdim if (!parseString(Ctl)) { 5584321369Sdim return false; 5585321369Sdim } 5586321369Sdim if (Ctl.size() != BITMASK_WIDTH) { 5587321369Sdim Error(StrLoc, "expected a 5-character mask"); 5588321369Sdim return false; 5589321369Sdim } 5590321369Sdim 5591321369Sdim unsigned AndMask = 0; 5592321369Sdim unsigned OrMask = 0; 5593321369Sdim unsigned XorMask = 0; 5594321369Sdim 5595321369Sdim for (size_t i = 0; i < Ctl.size(); ++i) { 5596321369Sdim unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i); 5597321369Sdim switch(Ctl[i]) { 5598321369Sdim default: 5599321369Sdim Error(StrLoc, "invalid mask"); 5600321369Sdim return false; 5601321369Sdim case '0': 5602321369Sdim break; 5603321369Sdim case '1': 5604321369Sdim OrMask |= Mask; 5605321369Sdim break; 5606321369Sdim case 'p': 5607321369Sdim AndMask |= Mask; 5608321369Sdim break; 5609321369Sdim case 'i': 5610321369Sdim AndMask |= Mask; 5611321369Sdim XorMask |= Mask; 5612321369Sdim break; 5613321369Sdim } 5614321369Sdim } 5615321369Sdim 5616321369Sdim Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask); 5617321369Sdim return true; 5618321369Sdim} 5619321369Sdim 5620321369Sdimbool 5621321369SdimAMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) { 5622321369Sdim 5623321369Sdim SMLoc OffsetLoc = Parser.getTok().getLoc(); 5624321369Sdim 5625321369Sdim if (!parseExpr(Imm)) { 5626321369Sdim return false; 5627321369Sdim } 5628321369Sdim if (!isUInt<16>(Imm)) { 5629321369Sdim Error(OffsetLoc, "expected a 16-bit offset"); 5630321369Sdim return false; 5631321369Sdim } 5632321369Sdim return true; 5633321369Sdim} 5634321369Sdim 5635321369Sdimbool 5636321369SdimAMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) { 5637321369Sdim using namespace llvm::AMDGPU::Swizzle; 5638321369Sdim 5639321369Sdim if (skipToken(AsmToken::LParen, "expected a left parentheses")) { 5640321369Sdim 5641321369Sdim SMLoc ModeLoc = Parser.getTok().getLoc(); 5642321369Sdim bool Ok = false; 5643321369Sdim 5644321369Sdim if (trySkipId(IdSymbolic[ID_QUAD_PERM])) { 5645321369Sdim Ok = parseSwizzleQuadPerm(Imm); 5646321369Sdim } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) { 5647321369Sdim Ok = parseSwizzleBitmaskPerm(Imm); 5648321369Sdim } else if (trySkipId(IdSymbolic[ID_BROADCAST])) { 5649321369Sdim Ok = parseSwizzleBroadcast(Imm); 5650321369Sdim } else if (trySkipId(IdSymbolic[ID_SWAP])) { 5651321369Sdim Ok = parseSwizzleSwap(Imm); 5652321369Sdim } else if (trySkipId(IdSymbolic[ID_REVERSE])) { 5653321369Sdim Ok = parseSwizzleReverse(Imm); 5654321369Sdim } else { 5655321369Sdim Error(ModeLoc, "expected a swizzle mode"); 5656321369Sdim } 5657321369Sdim 5658321369Sdim return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses"); 5659321369Sdim } 5660321369Sdim 5661321369Sdim return false; 5662321369Sdim} 5663321369Sdim 5664321369SdimOperandMatchResultTy 5665321369SdimAMDGPUAsmParser::parseSwizzleOp(OperandVector &Operands) { 5666321369Sdim SMLoc S = Parser.getTok().getLoc(); 5667321369Sdim int64_t Imm = 0; 5668321369Sdim 5669321369Sdim if (trySkipId("offset")) { 5670321369Sdim 5671321369Sdim bool Ok = false; 5672321369Sdim if (skipToken(AsmToken::Colon, "expected a colon")) { 5673321369Sdim if (trySkipId("swizzle")) { 5674321369Sdim Ok = parseSwizzleMacro(Imm); 5675321369Sdim } else { 5676321369Sdim Ok = parseSwizzleOffset(Imm); 5677321369Sdim } 5678321369Sdim } 5679321369Sdim 5680321369Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle)); 5681321369Sdim 5682321369Sdim return Ok? MatchOperand_Success : MatchOperand_ParseFail; 5683321369Sdim } else { 5684327952Sdim // Swizzle "offset" operand is optional. 5685327952Sdim // If it is omitted, try parsing other optional operands. 5686327952Sdim return parseOptionalOpr(Operands); 5687321369Sdim } 5688321369Sdim} 5689321369Sdim 5690321369Sdimbool 5691321369SdimAMDGPUOperand::isSwizzle() const { 5692321369Sdim return isImmTy(ImmTySwizzle); 5693321369Sdim} 5694321369Sdim 5695321369Sdim//===----------------------------------------------------------------------===// 5696353358Sdim// VGPR Index Mode 5697353358Sdim//===----------------------------------------------------------------------===// 5698353358Sdim 5699353358Sdimint64_t AMDGPUAsmParser::parseGPRIdxMacro() { 5700353358Sdim 5701353358Sdim using namespace llvm::AMDGPU::VGPRIndexMode; 5702353358Sdim 5703353358Sdim if (trySkipToken(AsmToken::RParen)) { 5704353358Sdim return OFF; 5705353358Sdim } 5706353358Sdim 5707353358Sdim int64_t Imm = 0; 5708353358Sdim 5709353358Sdim while (true) { 5710353358Sdim unsigned Mode = 0; 5711353358Sdim SMLoc S = Parser.getTok().getLoc(); 5712353358Sdim 5713353358Sdim for (unsigned ModeId = ID_MIN; ModeId <= ID_MAX; ++ModeId) { 5714353358Sdim if (trySkipId(IdSymbolic[ModeId])) { 5715353358Sdim Mode = 1 << ModeId; 5716353358Sdim break; 5717353358Sdim } 5718353358Sdim } 5719353358Sdim 5720353358Sdim if (Mode == 0) { 5721353358Sdim Error(S, (Imm == 0)? 5722353358Sdim "expected a VGPR index mode or a closing parenthesis" : 5723353358Sdim "expected a VGPR index mode"); 5724353358Sdim break; 5725353358Sdim } 5726353358Sdim 5727353358Sdim if (Imm & Mode) { 5728353358Sdim Error(S, "duplicate VGPR index mode"); 5729353358Sdim break; 5730353358Sdim } 5731353358Sdim Imm |= Mode; 5732353358Sdim 5733353358Sdim if (trySkipToken(AsmToken::RParen)) 5734353358Sdim break; 5735353358Sdim if (!skipToken(AsmToken::Comma, 5736353358Sdim "expected a comma or a closing parenthesis")) 5737353358Sdim break; 5738353358Sdim } 5739353358Sdim 5740353358Sdim return Imm; 5741353358Sdim} 5742353358Sdim 5743353358SdimOperandMatchResultTy 5744353358SdimAMDGPUAsmParser::parseGPRIdxMode(OperandVector &Operands) { 5745353358Sdim 5746353358Sdim int64_t Imm = 0; 5747353358Sdim SMLoc S = Parser.getTok().getLoc(); 5748353358Sdim 5749353358Sdim if (getLexer().getKind() == AsmToken::Identifier && 5750353358Sdim Parser.getTok().getString() == "gpr_idx" && 5751353358Sdim getLexer().peekTok().is(AsmToken::LParen)) { 5752353358Sdim 5753353358Sdim Parser.Lex(); 5754353358Sdim Parser.Lex(); 5755353358Sdim 5756353358Sdim // If parse failed, trigger an error but do not return error code 5757353358Sdim // to avoid excessive error messages. 5758353358Sdim Imm = parseGPRIdxMacro(); 5759353358Sdim 5760353358Sdim } else { 5761353358Sdim if (getParser().parseAbsoluteExpression(Imm)) 5762353358Sdim return MatchOperand_NoMatch; 5763353358Sdim if (Imm < 0 || !isUInt<4>(Imm)) { 5764353358Sdim Error(S, "invalid immediate: only 4-bit values are legal"); 5765353358Sdim } 5766353358Sdim } 5767353358Sdim 5768353358Sdim Operands.push_back( 5769353358Sdim AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyGprIdxMode)); 5770353358Sdim return MatchOperand_Success; 5771353358Sdim} 5772353358Sdim 5773353358Sdimbool AMDGPUOperand::isGPRIdxMode() const { 5774353358Sdim return isImmTy(ImmTyGprIdxMode); 5775353358Sdim} 5776353358Sdim 5777353358Sdim//===----------------------------------------------------------------------===// 5778284677Sdim// sopp branch targets 5779284677Sdim//===----------------------------------------------------------------------===// 5780284677Sdim 5781314564SdimOperandMatchResultTy 5782284677SdimAMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) { 5783284677Sdim 5784360784Sdim // Make sure we are not parsing something 5785360784Sdim // that looks like a label or an expression but is not. 5786360784Sdim // This will improve error messages. 5787360784Sdim if (isRegister() || isModifier()) 5788360784Sdim return MatchOperand_NoMatch; 5789360784Sdim 5790360784Sdim if (parseExpr(Operands)) { 5791360784Sdim 5792360784Sdim AMDGPUOperand &Opr = ((AMDGPUOperand &)*Operands[Operands.size() - 1]); 5793360784Sdim assert(Opr.isImm() || Opr.isExpr()); 5794360784Sdim SMLoc Loc = Opr.getStartLoc(); 5795360784Sdim 5796360784Sdim // Currently we do not support arbitrary expressions as branch targets. 5797360784Sdim // Only labels and absolute expressions are accepted. 5798360784Sdim if (Opr.isExpr() && !Opr.isSymbolRefExpr()) { 5799360784Sdim Error(Loc, "expected an absolute expression or a label"); 5800360784Sdim } else if (Opr.isImm() && !Opr.isS16Imm()) { 5801360784Sdim Error(Loc, "expected a 16-bit signed jump offset"); 5802284677Sdim } 5803360784Sdim } 5804284677Sdim 5805360784Sdim return MatchOperand_Success; // avoid excessive error messages 5806284677Sdim} 5807284677Sdim 5808284677Sdim//===----------------------------------------------------------------------===// 5809353358Sdim// Boolean holding registers 5810353358Sdim//===----------------------------------------------------------------------===// 5811353358Sdim 5812353358SdimOperandMatchResultTy 5813353358SdimAMDGPUAsmParser::parseBoolReg(OperandVector &Operands) { 5814353358Sdim return parseReg(Operands); 5815353358Sdim} 5816353358Sdim 5817353358Sdim//===----------------------------------------------------------------------===// 5818309124Sdim// mubuf 5819284677Sdim//===----------------------------------------------------------------------===// 5820284677Sdim 5821353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultDLC() const { 5822353358Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDLC); 5823353358Sdim} 5824353358Sdim 5825309124SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const { 5826314564Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC); 5827309124Sdim} 5828284677Sdim 5829309124SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const { 5830314564Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC); 5831284677Sdim} 5832284677Sdim 5833309124Sdimvoid AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst, 5834309124Sdim const OperandVector &Operands, 5835341825Sdim bool IsAtomic, 5836341825Sdim bool IsAtomicReturn, 5837341825Sdim bool IsLds) { 5838341825Sdim bool IsLdsOpcode = IsLds; 5839341825Sdim bool HasLdsModifier = false; 5840309124Sdim OptionalImmIndexMap OptionalIdx; 5841309124Sdim assert(IsAtomicReturn ? IsAtomic : true); 5842353358Sdim unsigned FirstOperandIdx = 1; 5843284677Sdim 5844353358Sdim for (unsigned i = FirstOperandIdx, e = Operands.size(); i != e; ++i) { 5845284677Sdim AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 5846284677Sdim 5847284677Sdim // Add the register arguments 5848284677Sdim if (Op.isReg()) { 5849284677Sdim Op.addRegOperands(Inst, 1); 5850353358Sdim // Insert a tied src for atomic return dst. 5851353358Sdim // This cannot be postponed as subsequent calls to 5852353358Sdim // addImmOperands rely on correct number of MC operands. 5853353358Sdim if (IsAtomicReturn && i == FirstOperandIdx) 5854353358Sdim Op.addRegOperands(Inst, 1); 5855284677Sdim continue; 5856284677Sdim } 5857284677Sdim 5858309124Sdim // Handle the case where soffset is an immediate 5859309124Sdim if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) { 5860309124Sdim Op.addImmOperands(Inst, 1); 5861309124Sdim continue; 5862309124Sdim } 5863309124Sdim 5864353358Sdim HasLdsModifier |= Op.isLDS(); 5865341825Sdim 5866309124Sdim // Handle tokens like 'offen' which are sometimes hard-coded into the 5867284677Sdim // asm string. There are no MCInst operands for these. 5868309124Sdim if (Op.isToken()) { 5869284677Sdim continue; 5870309124Sdim } 5871309124Sdim assert(Op.isImm()); 5872284677Sdim 5873284677Sdim // Handle optional arguments 5874284677Sdim OptionalIdx[Op.getImmTy()] = i; 5875309124Sdim } 5876284677Sdim 5877341825Sdim // This is a workaround for an llvm quirk which may result in an 5878341825Sdim // incorrect instruction selection. Lds and non-lds versions of 5879341825Sdim // MUBUF instructions are identical except that lds versions 5880341825Sdim // have mandatory 'lds' modifier. However this modifier follows 5881341825Sdim // optional modifiers and llvm asm matcher regards this 'lds' 5882341825Sdim // modifier as an optional one. As a result, an lds version 5883341825Sdim // of opcode may be selected even if it has no 'lds' modifier. 5884341825Sdim if (IsLdsOpcode && !HasLdsModifier) { 5885341825Sdim int NoLdsOpcode = AMDGPU::getMUBUFNoLdsInst(Inst.getOpcode()); 5886341825Sdim if (NoLdsOpcode != -1) { // Got lds version - correct it. 5887341825Sdim Inst.setOpcode(NoLdsOpcode); 5888341825Sdim IsLdsOpcode = false; 5889341825Sdim } 5890341825Sdim } 5891341825Sdim 5892309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset); 5893309124Sdim if (!IsAtomic) { // glc is hard-coded. 5894309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 5895284677Sdim } 5896309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 5897341825Sdim 5898341825Sdim if (!IsLdsOpcode) { // tfe is not legal with lds opcodes 5899341825Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 5900341825Sdim } 5901353358Sdim 5902353358Sdim if (isGFX10()) 5903353358Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC); 5904284677Sdim} 5905284677Sdim 5906321369Sdimvoid AMDGPUAsmParser::cvtMtbuf(MCInst &Inst, const OperandVector &Operands) { 5907309124Sdim OptionalImmIndexMap OptionalIdx; 5908284677Sdim 5909321369Sdim for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 5910321369Sdim AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 5911284677Sdim 5912309124Sdim // Add the register arguments 5913321369Sdim if (Op.isReg()) { 5914321369Sdim Op.addRegOperands(Inst, 1); 5915309124Sdim continue; 5916309124Sdim } 5917321369Sdim 5918321369Sdim // Handle the case where soffset is an immediate 5919321369Sdim if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) { 5920321369Sdim Op.addImmOperands(Inst, 1); 5921321369Sdim continue; 5922321369Sdim } 5923321369Sdim 5924321369Sdim // Handle tokens like 'offen' which are sometimes hard-coded into the 5925321369Sdim // asm string. There are no MCInst operands for these. 5926321369Sdim if (Op.isToken()) { 5927321369Sdim continue; 5928321369Sdim } 5929321369Sdim assert(Op.isImm()); 5930321369Sdim 5931321369Sdim // Handle optional arguments 5932321369Sdim OptionalIdx[Op.getImmTy()] = i; 5933309124Sdim } 5934284677Sdim 5935321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, 5936321369Sdim AMDGPUOperand::ImmTyOffset); 5937344779Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyFORMAT); 5938309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 5939321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 5940309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 5941353358Sdim 5942353358Sdim if (isGFX10()) 5943353358Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC); 5944284677Sdim} 5945284677Sdim 5946321369Sdim//===----------------------------------------------------------------------===// 5947321369Sdim// mimg 5948321369Sdim//===----------------------------------------------------------------------===// 5949321369Sdim 5950321369Sdimvoid AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands, 5951321369Sdim bool IsAtomic) { 5952309124Sdim unsigned I = 1; 5953309124Sdim const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 5954309124Sdim for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 5955309124Sdim ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 5956309124Sdim } 5957284677Sdim 5958321369Sdim if (IsAtomic) { 5959321369Sdim // Add src, same as dst 5960341825Sdim assert(Desc.getNumDefs() == 1); 5961341825Sdim ((AMDGPUOperand &)*Operands[I - 1]).addRegOperands(Inst, 1); 5962321369Sdim } 5963284677Sdim 5964309124Sdim OptionalImmIndexMap OptionalIdx; 5965284677Sdim 5966309124Sdim for (unsigned E = Operands.size(); I != E; ++I) { 5967309124Sdim AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 5968284677Sdim 5969284677Sdim // Add the register arguments 5970341825Sdim if (Op.isReg()) { 5971341825Sdim Op.addRegOperands(Inst, 1); 5972309124Sdim } else if (Op.isImmModifier()) { 5973309124Sdim OptionalIdx[Op.getImmTy()] = I; 5974353358Sdim } else if (!Op.isToken()) { 5975314564Sdim llvm_unreachable("unexpected operand type"); 5976284677Sdim } 5977284677Sdim } 5978284677Sdim 5979353358Sdim bool IsGFX10 = isGFX10(); 5980353358Sdim 5981309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask); 5982353358Sdim if (IsGFX10) 5983353358Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDim, -1); 5984309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm); 5985353358Sdim if (IsGFX10) 5986353358Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC); 5987309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 5988341825Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 5989344779Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128A16); 5990309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 5991309124Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE); 5992353358Sdim if (!IsGFX10) 5993353358Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA); 5994341825Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyD16); 5995309124Sdim} 5996284677Sdim 5997321369Sdimvoid AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) { 5998321369Sdim cvtMIMG(Inst, Operands, true); 5999321369Sdim} 6000321369Sdim 6001284677Sdim//===----------------------------------------------------------------------===// 6002296417Sdim// smrd 6003296417Sdim//===----------------------------------------------------------------------===// 6004296417Sdim 6005314564Sdimbool AMDGPUOperand::isSMRDOffset8() const { 6006296417Sdim return isImm() && isUInt<8>(getImm()); 6007296417Sdim} 6008296417Sdim 6009314564Sdimbool AMDGPUOperand::isSMRDOffset20() const { 6010314564Sdim return isImm() && isUInt<20>(getImm()); 6011314564Sdim} 6012314564Sdim 6013296417Sdimbool AMDGPUOperand::isSMRDLiteralOffset() const { 6014296417Sdim // 32-bit literals are only supported on CI and we only want to use them 6015296417Sdim // when the offset is > 8-bits. 6016296417Sdim return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm()); 6017296417Sdim} 6018296417Sdim 6019314564SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const { 6020314564Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); 6021309124Sdim} 6022309124Sdim 6023314564SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const { 6024314564Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); 6025314564Sdim} 6026314564Sdim 6027309124SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const { 6028314564Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); 6029309124Sdim} 6030309124Sdim 6031353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultFlatOffset() const { 6032321369Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); 6033321369Sdim} 6034321369Sdim 6035296417Sdim//===----------------------------------------------------------------------===// 6036284677Sdim// vop3 6037284677Sdim//===----------------------------------------------------------------------===// 6038284677Sdim 6039284677Sdimstatic bool ConvertOmodMul(int64_t &Mul) { 6040284677Sdim if (Mul != 1 && Mul != 2 && Mul != 4) 6041284677Sdim return false; 6042284677Sdim 6043284677Sdim Mul >>= 1; 6044284677Sdim return true; 6045284677Sdim} 6046284677Sdim 6047284677Sdimstatic bool ConvertOmodDiv(int64_t &Div) { 6048284677Sdim if (Div == 1) { 6049284677Sdim Div = 0; 6050284677Sdim return true; 6051284677Sdim } 6052284677Sdim 6053284677Sdim if (Div == 2) { 6054284677Sdim Div = 3; 6055284677Sdim return true; 6056284677Sdim } 6057284677Sdim 6058284677Sdim return false; 6059284677Sdim} 6060284677Sdim 6061309124Sdimstatic bool ConvertBoundCtrl(int64_t &BoundCtrl) { 6062309124Sdim if (BoundCtrl == 0) { 6063309124Sdim BoundCtrl = 1; 6064309124Sdim return true; 6065314564Sdim } 6066314564Sdim 6067314564Sdim if (BoundCtrl == -1) { 6068309124Sdim BoundCtrl = 0; 6069309124Sdim return true; 6070309124Sdim } 6071314564Sdim 6072309124Sdim return false; 6073309124Sdim} 6074309124Sdim 6075309124Sdim// Note: the order in this table matches the order of operands in AsmString. 6076309124Sdimstatic const OptionalOperand AMDGPUOptionalOperandTable[] = { 6077309124Sdim {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr}, 6078309124Sdim {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr}, 6079309124Sdim {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr}, 6080309124Sdim {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr}, 6081309124Sdim {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr}, 6082309124Sdim {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr}, 6083341825Sdim {"lds", AMDGPUOperand::ImmTyLDS, true, nullptr}, 6084309124Sdim {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr}, 6085327952Sdim {"inst_offset", AMDGPUOperand::ImmTyInstOffset, false, nullptr}, 6086353358Sdim {"dlc", AMDGPUOperand::ImmTyDLC, true, nullptr}, 6087353358Sdim {"format", AMDGPUOperand::ImmTyFORMAT, false, nullptr}, 6088309124Sdim {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr}, 6089309124Sdim {"slc", AMDGPUOperand::ImmTySLC, true, nullptr}, 6090360784Sdim {"swz", AMDGPUOperand::ImmTySWZ, true, nullptr}, 6091309124Sdim {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr}, 6092341825Sdim {"d16", AMDGPUOperand::ImmTyD16, true, nullptr}, 6093327952Sdim {"high", AMDGPUOperand::ImmTyHigh, true, nullptr}, 6094309124Sdim {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr}, 6095309124Sdim {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul}, 6096309124Sdim {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr}, 6097309124Sdim {"da", AMDGPUOperand::ImmTyDA, true, nullptr}, 6098344779Sdim {"r128", AMDGPUOperand::ImmTyR128A16, true, nullptr}, 6099344779Sdim {"a16", AMDGPUOperand::ImmTyR128A16, true, nullptr}, 6100309124Sdim {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr}, 6101341825Sdim {"d16", AMDGPUOperand::ImmTyD16, true, nullptr}, 6102309124Sdim {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr}, 6103353358Sdim {"dim", AMDGPUOperand::ImmTyDim, false, nullptr}, 6104309124Sdim {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr}, 6105309124Sdim {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr}, 6106309124Sdim {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl}, 6107353358Sdim {"fi", AMDGPUOperand::ImmTyDppFi, false, nullptr}, 6108309124Sdim {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr}, 6109309124Sdim {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr}, 6110309124Sdim {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr}, 6111309124Sdim {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr}, 6112321369Sdim {"compr", AMDGPUOperand::ImmTyExpCompr, true, nullptr }, 6113314564Sdim {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr}, 6114321369Sdim {"op_sel", AMDGPUOperand::ImmTyOpSel, false, nullptr}, 6115321369Sdim {"op_sel_hi", AMDGPUOperand::ImmTyOpSelHi, false, nullptr}, 6116321369Sdim {"neg_lo", AMDGPUOperand::ImmTyNegLo, false, nullptr}, 6117353358Sdim {"neg_hi", AMDGPUOperand::ImmTyNegHi, false, nullptr}, 6118353358Sdim {"blgp", AMDGPUOperand::ImmTyBLGP, false, nullptr}, 6119353358Sdim {"cbsz", AMDGPUOperand::ImmTyCBSZ, false, nullptr}, 6120353358Sdim {"abid", AMDGPUOperand::ImmTyABID, false, nullptr} 6121284677Sdim}; 6122284677Sdim 6123314564SdimOperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) { 6124327952Sdim 6125327952Sdim OperandMatchResultTy res = parseOptionalOpr(Operands); 6126327952Sdim 6127327952Sdim // This is a hack to enable hardcoded mandatory operands which follow 6128327952Sdim // optional operands. 6129327952Sdim // 6130327952Sdim // Current design assumes that all operands after the first optional operand 6131327952Sdim // are also optional. However implementation of some instructions violates 6132327952Sdim // this rule (see e.g. flat/global atomic which have hardcoded 'glc' operands). 6133327952Sdim // 6134327952Sdim // To alleviate this problem, we have to (implicitly) parse extra operands 6135327952Sdim // to make sure autogenerated parser of custom operands never hit hardcoded 6136327952Sdim // mandatory operands. 6137327952Sdim 6138360784Sdim for (unsigned i = 0; i < MAX_OPR_LOOKAHEAD; ++i) { 6139360784Sdim if (res != MatchOperand_Success || 6140360784Sdim isToken(AsmToken::EndOfStatement)) 6141360784Sdim break; 6142327952Sdim 6143360784Sdim trySkipToken(AsmToken::Comma); 6144360784Sdim res = parseOptionalOpr(Operands); 6145327952Sdim } 6146327952Sdim 6147327952Sdim return res; 6148327952Sdim} 6149327952Sdim 6150327952SdimOperandMatchResultTy AMDGPUAsmParser::parseOptionalOpr(OperandVector &Operands) { 6151309124Sdim OperandMatchResultTy res; 6152309124Sdim for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) { 6153309124Sdim // try to parse any optional operand here 6154309124Sdim if (Op.IsBit) { 6155309124Sdim res = parseNamedBit(Op.Name, Operands, Op.Type); 6156309124Sdim } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) { 6157309124Sdim res = parseOModOperand(Operands); 6158309124Sdim } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel || 6159309124Sdim Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel || 6160309124Sdim Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) { 6161309124Sdim res = parseSDWASel(Operands, Op.Name, Op.Type); 6162309124Sdim } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) { 6163309124Sdim res = parseSDWADstUnused(Operands); 6164321369Sdim } else if (Op.Type == AMDGPUOperand::ImmTyOpSel || 6165321369Sdim Op.Type == AMDGPUOperand::ImmTyOpSelHi || 6166321369Sdim Op.Type == AMDGPUOperand::ImmTyNegLo || 6167321369Sdim Op.Type == AMDGPUOperand::ImmTyNegHi) { 6168321369Sdim res = parseOperandArrayWithPrefix(Op.Name, Operands, Op.Type, 6169321369Sdim Op.ConvertResult); 6170353358Sdim } else if (Op.Type == AMDGPUOperand::ImmTyDim) { 6171353358Sdim res = parseDim(Operands); 6172353358Sdim } else if (Op.Type == AMDGPUOperand::ImmTyFORMAT && !isGFX10()) { 6173344779Sdim res = parseDfmtNfmt(Operands); 6174309124Sdim } else { 6175309124Sdim res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult); 6176309124Sdim } 6177309124Sdim if (res != MatchOperand_NoMatch) { 6178309124Sdim return res; 6179309124Sdim } 6180309124Sdim } 6181309124Sdim return MatchOperand_NoMatch; 6182309124Sdim} 6183284677Sdim 6184314564SdimOperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) { 6185309124Sdim StringRef Name = Parser.getTok().getString(); 6186309124Sdim if (Name == "mul") { 6187314564Sdim return parseIntWithPrefix("mul", Operands, 6188314564Sdim AMDGPUOperand::ImmTyOModSI, ConvertOmodMul); 6189309124Sdim } 6190314564Sdim 6191314564Sdim if (Name == "div") { 6192314564Sdim return parseIntWithPrefix("div", Operands, 6193314564Sdim AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv); 6194314564Sdim } 6195314564Sdim 6196314564Sdim return MatchOperand_NoMatch; 6197309124Sdim} 6198284677Sdim 6199327952Sdimvoid AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands) { 6200327952Sdim cvtVOP3P(Inst, Operands); 6201327952Sdim 6202327952Sdim int Opc = Inst.getOpcode(); 6203327952Sdim 6204327952Sdim int SrcNum; 6205327952Sdim const int Ops[] = { AMDGPU::OpName::src0, 6206327952Sdim AMDGPU::OpName::src1, 6207327952Sdim AMDGPU::OpName::src2 }; 6208327952Sdim for (SrcNum = 0; 6209327952Sdim SrcNum < 3 && AMDGPU::getNamedOperandIdx(Opc, Ops[SrcNum]) != -1; 6210327952Sdim ++SrcNum); 6211327952Sdim assert(SrcNum > 0); 6212327952Sdim 6213327952Sdim int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel); 6214327952Sdim unsigned OpSel = Inst.getOperand(OpSelIdx).getImm(); 6215327952Sdim 6216327952Sdim if ((OpSel & (1 << SrcNum)) != 0) { 6217327952Sdim int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers); 6218327952Sdim uint32_t ModVal = Inst.getOperand(ModIdx).getImm(); 6219327952Sdim Inst.getOperand(ModIdx).setImm(ModVal | SISrcMods::DST_OP_SEL); 6220327952Sdim } 6221327952Sdim} 6222327952Sdim 6223314564Sdimstatic bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) { 6224314564Sdim // 1. This operand is input modifiers 6225314564Sdim return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS 6226314564Sdim // 2. This is not last operand 6227314564Sdim && Desc.NumOperands > (OpNum + 1) 6228314564Sdim // 3. Next operand is register class 6229314564Sdim && Desc.OpInfo[OpNum + 1].RegClass != -1 6230314564Sdim // 4. Next register is not tied to any other operand 6231314564Sdim && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1; 6232314564Sdim} 6233314564Sdim 6234327952Sdimvoid AMDGPUAsmParser::cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands) 6235327952Sdim{ 6236327952Sdim OptionalImmIndexMap OptionalIdx; 6237327952Sdim unsigned Opc = Inst.getOpcode(); 6238327952Sdim 6239327952Sdim unsigned I = 1; 6240327952Sdim const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 6241327952Sdim for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 6242327952Sdim ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 6243327952Sdim } 6244327952Sdim 6245327952Sdim for (unsigned E = Operands.size(); I != E; ++I) { 6246327952Sdim AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 6247327952Sdim if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 6248327952Sdim Op.addRegOrImmWithFPInputModsOperands(Inst, 2); 6249327952Sdim } else if (Op.isInterpSlot() || 6250327952Sdim Op.isInterpAttr() || 6251327952Sdim Op.isAttrChan()) { 6252353358Sdim Inst.addOperand(MCOperand::createImm(Op.getImm())); 6253327952Sdim } else if (Op.isImmModifier()) { 6254327952Sdim OptionalIdx[Op.getImmTy()] = I; 6255327952Sdim } else { 6256327952Sdim llvm_unreachable("unhandled operand type"); 6257327952Sdim } 6258327952Sdim } 6259327952Sdim 6260327952Sdim if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::high) != -1) { 6261327952Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyHigh); 6262327952Sdim } 6263327952Sdim 6264327952Sdim if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) { 6265327952Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI); 6266327952Sdim } 6267327952Sdim 6268327952Sdim if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) { 6269327952Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI); 6270327952Sdim } 6271327952Sdim} 6272327952Sdim 6273321369Sdimvoid AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands, 6274321369Sdim OptionalImmIndexMap &OptionalIdx) { 6275321369Sdim unsigned Opc = Inst.getOpcode(); 6276321369Sdim 6277309124Sdim unsigned I = 1; 6278309124Sdim const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 6279309124Sdim for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 6280309124Sdim ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 6281284677Sdim } 6282309124Sdim 6283321369Sdim if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers) != -1) { 6284321369Sdim // This instruction has src modifiers 6285321369Sdim for (unsigned E = Operands.size(); I != E; ++I) { 6286321369Sdim AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 6287321369Sdim if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 6288321369Sdim Op.addRegOrImmWithFPInputModsOperands(Inst, 2); 6289321369Sdim } else if (Op.isImmModifier()) { 6290321369Sdim OptionalIdx[Op.getImmTy()] = I; 6291321369Sdim } else if (Op.isRegOrImm()) { 6292321369Sdim Op.addRegOrImmOperands(Inst, 1); 6293321369Sdim } else { 6294321369Sdim llvm_unreachable("unhandled operand type"); 6295321369Sdim } 6296309124Sdim } 6297321369Sdim } else { 6298321369Sdim // No src modifiers 6299321369Sdim for (unsigned E = Operands.size(); I != E; ++I) { 6300321369Sdim AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 6301321369Sdim if (Op.isMod()) { 6302321369Sdim OptionalIdx[Op.getImmTy()] = I; 6303321369Sdim } else { 6304321369Sdim Op.addRegOrImmOperands(Inst, 1); 6305321369Sdim } 6306321369Sdim } 6307309124Sdim } 6308309124Sdim 6309321369Sdim if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) { 6310321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI); 6311321369Sdim } 6312314564Sdim 6313321369Sdim if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) { 6314321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI); 6315321369Sdim } 6316321369Sdim 6317353358Sdim // Special case v_mac_{f16, f32} and v_fmac_{f16, f32} (gfx906/gfx10+): 6318314564Sdim // it has src2 register operand that is tied to dst operand 6319314564Sdim // we don't allow modifiers for this operand in assembler so src2_modifiers 6320341825Sdim // should be 0. 6321353358Sdim if (Opc == AMDGPU::V_MAC_F32_e64_gfx6_gfx7 || 6322353358Sdim Opc == AMDGPU::V_MAC_F32_e64_gfx10 || 6323341825Sdim Opc == AMDGPU::V_MAC_F32_e64_vi || 6324341825Sdim Opc == AMDGPU::V_MAC_F16_e64_vi || 6325353358Sdim Opc == AMDGPU::V_FMAC_F32_e64_gfx10 || 6326353358Sdim Opc == AMDGPU::V_FMAC_F32_e64_vi || 6327353358Sdim Opc == AMDGPU::V_FMAC_F16_e64_gfx10) { 6328314564Sdim auto it = Inst.begin(); 6329321369Sdim std::advance(it, AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers)); 6330314564Sdim it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2 6331314564Sdim ++it; 6332314564Sdim Inst.insert(it, Inst.getOperand(0)); // src2 = dst 6333314564Sdim } 6334309124Sdim} 6335309124Sdim 6336321369Sdimvoid AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) { 6337321369Sdim OptionalImmIndexMap OptionalIdx; 6338321369Sdim cvtVOP3(Inst, Operands, OptionalIdx); 6339321369Sdim} 6340321369Sdim 6341327952Sdimvoid AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, 6342327952Sdim const OperandVector &Operands) { 6343321369Sdim OptionalImmIndexMap OptIdx; 6344327952Sdim const int Opc = Inst.getOpcode(); 6345327952Sdim const MCInstrDesc &Desc = MII.get(Opc); 6346321369Sdim 6347327952Sdim const bool IsPacked = (Desc.TSFlags & SIInstrFlags::IsPacked) != 0; 6348327952Sdim 6349321369Sdim cvtVOP3(Inst, Operands, OptIdx); 6350321369Sdim 6351327952Sdim if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in) != -1) { 6352327952Sdim assert(!IsPacked); 6353327952Sdim Inst.addOperand(Inst.getOperand(0)); 6354327952Sdim } 6355327952Sdim 6356321369Sdim // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3 6357321369Sdim // instruction, and then figure out where to actually put the modifiers 6358321369Sdim 6359321369Sdim addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel); 6360321369Sdim 6361327952Sdim int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi); 6362327952Sdim if (OpSelHiIdx != -1) { 6363327952Sdim int DefaultVal = IsPacked ? -1 : 0; 6364327952Sdim addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi, 6365327952Sdim DefaultVal); 6366327952Sdim } 6367327952Sdim 6368321369Sdim int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo); 6369321369Sdim if (NegLoIdx != -1) { 6370327952Sdim assert(IsPacked); 6371321369Sdim addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo); 6372321369Sdim addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi); 6373321369Sdim } 6374321369Sdim 6375321369Sdim const int Ops[] = { AMDGPU::OpName::src0, 6376321369Sdim AMDGPU::OpName::src1, 6377321369Sdim AMDGPU::OpName::src2 }; 6378321369Sdim const int ModOps[] = { AMDGPU::OpName::src0_modifiers, 6379321369Sdim AMDGPU::OpName::src1_modifiers, 6380321369Sdim AMDGPU::OpName::src2_modifiers }; 6381321369Sdim 6382321369Sdim int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel); 6383321369Sdim 6384321369Sdim unsigned OpSel = Inst.getOperand(OpSelIdx).getImm(); 6385327952Sdim unsigned OpSelHi = 0; 6386321369Sdim unsigned NegLo = 0; 6387321369Sdim unsigned NegHi = 0; 6388321369Sdim 6389327952Sdim if (OpSelHiIdx != -1) { 6390327952Sdim OpSelHi = Inst.getOperand(OpSelHiIdx).getImm(); 6391327952Sdim } 6392327952Sdim 6393321369Sdim if (NegLoIdx != -1) { 6394321369Sdim int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi); 6395321369Sdim NegLo = Inst.getOperand(NegLoIdx).getImm(); 6396321369Sdim NegHi = Inst.getOperand(NegHiIdx).getImm(); 6397321369Sdim } 6398321369Sdim 6399321369Sdim for (int J = 0; J < 3; ++J) { 6400321369Sdim int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]); 6401321369Sdim if (OpIdx == -1) 6402321369Sdim break; 6403321369Sdim 6404321369Sdim uint32_t ModVal = 0; 6405321369Sdim 6406321369Sdim if ((OpSel & (1 << J)) != 0) 6407321369Sdim ModVal |= SISrcMods::OP_SEL_0; 6408321369Sdim 6409321369Sdim if ((OpSelHi & (1 << J)) != 0) 6410321369Sdim ModVal |= SISrcMods::OP_SEL_1; 6411321369Sdim 6412321369Sdim if ((NegLo & (1 << J)) != 0) 6413321369Sdim ModVal |= SISrcMods::NEG; 6414321369Sdim 6415321369Sdim if ((NegHi & (1 << J)) != 0) 6416321369Sdim ModVal |= SISrcMods::NEG_HI; 6417321369Sdim 6418321369Sdim int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]); 6419321369Sdim 6420321369Sdim Inst.getOperand(ModIdx).setImm(Inst.getOperand(ModIdx).getImm() | ModVal); 6421321369Sdim } 6422321369Sdim} 6423321369Sdim 6424309124Sdim//===----------------------------------------------------------------------===// 6425309124Sdim// dpp 6426309124Sdim//===----------------------------------------------------------------------===// 6427309124Sdim 6428353358Sdimbool AMDGPUOperand::isDPP8() const { 6429353358Sdim return isImmTy(ImmTyDPP8); 6430353358Sdim} 6431353358Sdim 6432309124Sdimbool AMDGPUOperand::isDPPCtrl() const { 6433341825Sdim using namespace AMDGPU::DPP; 6434341825Sdim 6435309124Sdim bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm()); 6436309124Sdim if (result) { 6437309124Sdim int64_t Imm = getImm(); 6438341825Sdim return (Imm >= DppCtrl::QUAD_PERM_FIRST && Imm <= DppCtrl::QUAD_PERM_LAST) || 6439341825Sdim (Imm >= DppCtrl::ROW_SHL_FIRST && Imm <= DppCtrl::ROW_SHL_LAST) || 6440341825Sdim (Imm >= DppCtrl::ROW_SHR_FIRST && Imm <= DppCtrl::ROW_SHR_LAST) || 6441341825Sdim (Imm >= DppCtrl::ROW_ROR_FIRST && Imm <= DppCtrl::ROW_ROR_LAST) || 6442341825Sdim (Imm == DppCtrl::WAVE_SHL1) || 6443341825Sdim (Imm == DppCtrl::WAVE_ROL1) || 6444341825Sdim (Imm == DppCtrl::WAVE_SHR1) || 6445341825Sdim (Imm == DppCtrl::WAVE_ROR1) || 6446341825Sdim (Imm == DppCtrl::ROW_MIRROR) || 6447341825Sdim (Imm == DppCtrl::ROW_HALF_MIRROR) || 6448341825Sdim (Imm == DppCtrl::BCAST15) || 6449353358Sdim (Imm == DppCtrl::BCAST31) || 6450353358Sdim (Imm >= DppCtrl::ROW_SHARE_FIRST && Imm <= DppCtrl::ROW_SHARE_LAST) || 6451353358Sdim (Imm >= DppCtrl::ROW_XMASK_FIRST && Imm <= DppCtrl::ROW_XMASK_LAST); 6452309124Sdim } 6453284677Sdim return false; 6454284677Sdim} 6455284677Sdim 6456353358Sdim//===----------------------------------------------------------------------===// 6457353358Sdim// mAI 6458353358Sdim//===----------------------------------------------------------------------===// 6459353358Sdim 6460353358Sdimbool AMDGPUOperand::isBLGP() const { 6461353358Sdim return isImm() && getImmTy() == ImmTyBLGP && isUInt<3>(getImm()); 6462314564Sdim} 6463314564Sdim 6464353358Sdimbool AMDGPUOperand::isCBSZ() const { 6465353358Sdim return isImm() && getImmTy() == ImmTyCBSZ && isUInt<3>(getImm()); 6466353358Sdim} 6467353358Sdim 6468353358Sdimbool AMDGPUOperand::isABID() const { 6469353358Sdim return isImm() && getImmTy() == ImmTyABID && isUInt<4>(getImm()); 6470353358Sdim} 6471353358Sdim 6472321369Sdimbool AMDGPUOperand::isS16Imm() const { 6473321369Sdim return isImm() && (isInt<16>(getImm()) || isUInt<16>(getImm())); 6474321369Sdim} 6475321369Sdim 6476321369Sdimbool AMDGPUOperand::isU16Imm() const { 6477321369Sdim return isImm() && isUInt<16>(getImm()); 6478321369Sdim} 6479321369Sdim 6480353358SdimOperandMatchResultTy AMDGPUAsmParser::parseDim(OperandVector &Operands) { 6481353358Sdim if (!isGFX10()) 6482353358Sdim return MatchOperand_NoMatch; 6483353358Sdim 6484353358Sdim SMLoc S = Parser.getTok().getLoc(); 6485353358Sdim 6486353358Sdim if (getLexer().isNot(AsmToken::Identifier)) 6487353358Sdim return MatchOperand_NoMatch; 6488353358Sdim if (getLexer().getTok().getString() != "dim") 6489353358Sdim return MatchOperand_NoMatch; 6490353358Sdim 6491353358Sdim Parser.Lex(); 6492353358Sdim if (getLexer().isNot(AsmToken::Colon)) 6493353358Sdim return MatchOperand_ParseFail; 6494353358Sdim 6495353358Sdim Parser.Lex(); 6496353358Sdim 6497353358Sdim // We want to allow "dim:1D" etc., but the initial 1 is tokenized as an 6498353358Sdim // integer. 6499353358Sdim std::string Token; 6500353358Sdim if (getLexer().is(AsmToken::Integer)) { 6501353358Sdim SMLoc Loc = getLexer().getTok().getEndLoc(); 6502353358Sdim Token = getLexer().getTok().getString(); 6503353358Sdim Parser.Lex(); 6504353358Sdim if (getLexer().getTok().getLoc() != Loc) 6505353358Sdim return MatchOperand_ParseFail; 6506353358Sdim } 6507353358Sdim if (getLexer().isNot(AsmToken::Identifier)) 6508353358Sdim return MatchOperand_ParseFail; 6509353358Sdim Token += getLexer().getTok().getString(); 6510353358Sdim 6511353358Sdim StringRef DimId = Token; 6512353358Sdim if (DimId.startswith("SQ_RSRC_IMG_")) 6513353358Sdim DimId = DimId.substr(12); 6514353358Sdim 6515353358Sdim const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByAsmSuffix(DimId); 6516353358Sdim if (!DimInfo) 6517353358Sdim return MatchOperand_ParseFail; 6518353358Sdim 6519353358Sdim Parser.Lex(); 6520353358Sdim 6521353358Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, DimInfo->Encoding, S, 6522353358Sdim AMDGPUOperand::ImmTyDim)); 6523353358Sdim return MatchOperand_Success; 6524353358Sdim} 6525353358Sdim 6526353358SdimOperandMatchResultTy AMDGPUAsmParser::parseDPP8(OperandVector &Operands) { 6527353358Sdim SMLoc S = Parser.getTok().getLoc(); 6528353358Sdim StringRef Prefix; 6529353358Sdim 6530353358Sdim if (getLexer().getKind() == AsmToken::Identifier) { 6531353358Sdim Prefix = Parser.getTok().getString(); 6532353358Sdim } else { 6533353358Sdim return MatchOperand_NoMatch; 6534353358Sdim } 6535353358Sdim 6536353358Sdim if (Prefix != "dpp8") 6537353358Sdim return parseDPPCtrl(Operands); 6538353358Sdim if (!isGFX10()) 6539353358Sdim return MatchOperand_NoMatch; 6540353358Sdim 6541353358Sdim // dpp8:[%d,%d,%d,%d,%d,%d,%d,%d] 6542353358Sdim 6543353358Sdim int64_t Sels[8]; 6544353358Sdim 6545353358Sdim Parser.Lex(); 6546353358Sdim if (getLexer().isNot(AsmToken::Colon)) 6547353358Sdim return MatchOperand_ParseFail; 6548353358Sdim 6549353358Sdim Parser.Lex(); 6550353358Sdim if (getLexer().isNot(AsmToken::LBrac)) 6551353358Sdim return MatchOperand_ParseFail; 6552353358Sdim 6553353358Sdim Parser.Lex(); 6554353358Sdim if (getParser().parseAbsoluteExpression(Sels[0])) 6555353358Sdim return MatchOperand_ParseFail; 6556353358Sdim if (0 > Sels[0] || 7 < Sels[0]) 6557353358Sdim return MatchOperand_ParseFail; 6558353358Sdim 6559353358Sdim for (size_t i = 1; i < 8; ++i) { 6560353358Sdim if (getLexer().isNot(AsmToken::Comma)) 6561353358Sdim return MatchOperand_ParseFail; 6562353358Sdim 6563353358Sdim Parser.Lex(); 6564353358Sdim if (getParser().parseAbsoluteExpression(Sels[i])) 6565353358Sdim return MatchOperand_ParseFail; 6566353358Sdim if (0 > Sels[i] || 7 < Sels[i]) 6567353358Sdim return MatchOperand_ParseFail; 6568353358Sdim } 6569353358Sdim 6570353358Sdim if (getLexer().isNot(AsmToken::RBrac)) 6571353358Sdim return MatchOperand_ParseFail; 6572353358Sdim Parser.Lex(); 6573353358Sdim 6574353358Sdim unsigned DPP8 = 0; 6575353358Sdim for (size_t i = 0; i < 8; ++i) 6576353358Sdim DPP8 |= (Sels[i] << (i * 3)); 6577353358Sdim 6578353358Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, DPP8, S, AMDGPUOperand::ImmTyDPP8)); 6579353358Sdim return MatchOperand_Success; 6580353358Sdim} 6581353358Sdim 6582314564SdimOperandMatchResultTy 6583309124SdimAMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) { 6584341825Sdim using namespace AMDGPU::DPP; 6585341825Sdim 6586309124Sdim SMLoc S = Parser.getTok().getLoc(); 6587309124Sdim StringRef Prefix; 6588309124Sdim int64_t Int; 6589284677Sdim 6590309124Sdim if (getLexer().getKind() == AsmToken::Identifier) { 6591309124Sdim Prefix = Parser.getTok().getString(); 6592309124Sdim } else { 6593309124Sdim return MatchOperand_NoMatch; 6594309124Sdim } 6595284677Sdim 6596309124Sdim if (Prefix == "row_mirror") { 6597341825Sdim Int = DppCtrl::ROW_MIRROR; 6598314564Sdim Parser.Lex(); 6599309124Sdim } else if (Prefix == "row_half_mirror") { 6600341825Sdim Int = DppCtrl::ROW_HALF_MIRROR; 6601314564Sdim Parser.Lex(); 6602309124Sdim } else { 6603309124Sdim // Check to prevent parseDPPCtrlOps from eating invalid tokens 6604309124Sdim if (Prefix != "quad_perm" 6605309124Sdim && Prefix != "row_shl" 6606309124Sdim && Prefix != "row_shr" 6607309124Sdim && Prefix != "row_ror" 6608309124Sdim && Prefix != "wave_shl" 6609309124Sdim && Prefix != "wave_rol" 6610309124Sdim && Prefix != "wave_shr" 6611309124Sdim && Prefix != "wave_ror" 6612353358Sdim && Prefix != "row_bcast" 6613353358Sdim && Prefix != "row_share" 6614353358Sdim && Prefix != "row_xmask") { 6615309124Sdim return MatchOperand_NoMatch; 6616309124Sdim } 6617284677Sdim 6618353358Sdim if (!isGFX10() && (Prefix == "row_share" || Prefix == "row_xmask")) 6619353358Sdim return MatchOperand_NoMatch; 6620353358Sdim 6621353358Sdim if (!isVI() && !isGFX9() && 6622353358Sdim (Prefix == "wave_shl" || Prefix == "wave_shr" || 6623353358Sdim Prefix == "wave_rol" || Prefix == "wave_ror" || 6624353358Sdim Prefix == "row_bcast")) 6625353358Sdim return MatchOperand_NoMatch; 6626353358Sdim 6627309124Sdim Parser.Lex(); 6628309124Sdim if (getLexer().isNot(AsmToken::Colon)) 6629309124Sdim return MatchOperand_ParseFail; 6630284677Sdim 6631309124Sdim if (Prefix == "quad_perm") { 6632309124Sdim // quad_perm:[%d,%d,%d,%d] 6633309124Sdim Parser.Lex(); 6634309124Sdim if (getLexer().isNot(AsmToken::LBrac)) 6635309124Sdim return MatchOperand_ParseFail; 6636309124Sdim Parser.Lex(); 6637309124Sdim 6638314564Sdim if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3)) 6639309124Sdim return MatchOperand_ParseFail; 6640309124Sdim 6641314564Sdim for (int i = 0; i < 3; ++i) { 6642314564Sdim if (getLexer().isNot(AsmToken::Comma)) 6643314564Sdim return MatchOperand_ParseFail; 6644314564Sdim Parser.Lex(); 6645309124Sdim 6646314564Sdim int64_t Temp; 6647314564Sdim if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3)) 6648314564Sdim return MatchOperand_ParseFail; 6649314564Sdim const int shift = i*2 + 2; 6650314564Sdim Int += (Temp << shift); 6651314564Sdim } 6652309124Sdim 6653309124Sdim if (getLexer().isNot(AsmToken::RBrac)) 6654309124Sdim return MatchOperand_ParseFail; 6655314564Sdim Parser.Lex(); 6656309124Sdim } else { 6657309124Sdim // sel:%d 6658309124Sdim Parser.Lex(); 6659314564Sdim if (getParser().parseAbsoluteExpression(Int)) 6660309124Sdim return MatchOperand_ParseFail; 6661309124Sdim 6662314564Sdim if (Prefix == "row_shl" && 1 <= Int && Int <= 15) { 6663341825Sdim Int |= DppCtrl::ROW_SHL0; 6664314564Sdim } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) { 6665341825Sdim Int |= DppCtrl::ROW_SHR0; 6666314564Sdim } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) { 6667341825Sdim Int |= DppCtrl::ROW_ROR0; 6668314564Sdim } else if (Prefix == "wave_shl" && 1 == Int) { 6669341825Sdim Int = DppCtrl::WAVE_SHL1; 6670314564Sdim } else if (Prefix == "wave_rol" && 1 == Int) { 6671341825Sdim Int = DppCtrl::WAVE_ROL1; 6672314564Sdim } else if (Prefix == "wave_shr" && 1 == Int) { 6673341825Sdim Int = DppCtrl::WAVE_SHR1; 6674314564Sdim } else if (Prefix == "wave_ror" && 1 == Int) { 6675341825Sdim Int = DppCtrl::WAVE_ROR1; 6676309124Sdim } else if (Prefix == "row_bcast") { 6677309124Sdim if (Int == 15) { 6678341825Sdim Int = DppCtrl::BCAST15; 6679309124Sdim } else if (Int == 31) { 6680341825Sdim Int = DppCtrl::BCAST31; 6681309124Sdim } else { 6682309124Sdim return MatchOperand_ParseFail; 6683309124Sdim } 6684353358Sdim } else if (Prefix == "row_share" && 0 <= Int && Int <= 15) { 6685353358Sdim Int |= DppCtrl::ROW_SHARE_FIRST; 6686353358Sdim } else if (Prefix == "row_xmask" && 0 <= Int && Int <= 15) { 6687353358Sdim Int |= DppCtrl::ROW_XMASK_FIRST; 6688309124Sdim } else { 6689309124Sdim return MatchOperand_ParseFail; 6690284677Sdim } 6691284677Sdim } 6692284677Sdim } 6693309124Sdim 6694314564Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl)); 6695309124Sdim return MatchOperand_Success; 6696284677Sdim} 6697284677Sdim 6698309124SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const { 6699314564Sdim return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask); 6700309124Sdim} 6701284677Sdim 6702353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultEndpgmImmOperands() const { 6703353358Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyEndpgm); 6704353358Sdim} 6705353358Sdim 6706309124SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const { 6707314564Sdim return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask); 6708309124Sdim} 6709309124Sdim 6710309124SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const { 6711314564Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl); 6712309124Sdim} 6713309124Sdim 6714353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultFI() const { 6715353358Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppFi); 6716353358Sdim} 6717353358Sdim 6718353358Sdimvoid AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8) { 6719309124Sdim OptionalImmIndexMap OptionalIdx; 6720309124Sdim 6721309124Sdim unsigned I = 1; 6722296417Sdim const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 6723309124Sdim for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 6724309124Sdim ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 6725296417Sdim } 6726296417Sdim 6727353358Sdim int Fi = 0; 6728309124Sdim for (unsigned E = Operands.size(); I != E; ++I) { 6729344779Sdim auto TiedTo = Desc.getOperandConstraint(Inst.getNumOperands(), 6730344779Sdim MCOI::TIED_TO); 6731344779Sdim if (TiedTo != -1) { 6732344779Sdim assert((unsigned)TiedTo < Inst.getNumOperands()); 6733344779Sdim // handle tied old or src2 for MAC instructions 6734344779Sdim Inst.addOperand(Inst.getOperand(TiedTo)); 6735344779Sdim } 6736309124Sdim AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 6737309124Sdim // Add the register arguments 6738353358Sdim if (Op.isReg() && validateVccOperand(Op.getReg())) { 6739321369Sdim // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token. 6740314564Sdim // Skip it. 6741314564Sdim continue; 6742353358Sdim } 6743353358Sdim 6744353358Sdim if (IsDPP8) { 6745353358Sdim if (Op.isDPP8()) { 6746353358Sdim Op.addImmOperands(Inst, 1); 6747353358Sdim } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 6748353358Sdim Op.addRegWithFPInputModsOperands(Inst, 2); 6749353358Sdim } else if (Op.isFI()) { 6750353358Sdim Fi = Op.getImm(); 6751353358Sdim } else if (Op.isReg()) { 6752353358Sdim Op.addRegOperands(Inst, 1); 6753353358Sdim } else { 6754353358Sdim llvm_unreachable("Invalid operand type"); 6755353358Sdim } 6756309124Sdim } else { 6757353358Sdim if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 6758353358Sdim Op.addRegWithFPInputModsOperands(Inst, 2); 6759353358Sdim } else if (Op.isDPPCtrl()) { 6760353358Sdim Op.addImmOperands(Inst, 1); 6761353358Sdim } else if (Op.isImm()) { 6762353358Sdim // Handle optional arguments 6763353358Sdim OptionalIdx[Op.getImmTy()] = I; 6764353358Sdim } else { 6765353358Sdim llvm_unreachable("Invalid operand type"); 6766353358Sdim } 6767309124Sdim } 6768309124Sdim } 6769284677Sdim 6770353358Sdim if (IsDPP8) { 6771353358Sdim using namespace llvm::AMDGPU::DPP; 6772353358Sdim Inst.addOperand(MCOperand::createImm(Fi? DPP8_FI_1 : DPP8_FI_0)); 6773353358Sdim } else { 6774353358Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf); 6775353358Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf); 6776353358Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl); 6777353358Sdim if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::fi) != -1) { 6778353358Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppFi); 6779353358Sdim } 6780353358Sdim } 6781309124Sdim} 6782284677Sdim 6783309124Sdim//===----------------------------------------------------------------------===// 6784309124Sdim// sdwa 6785309124Sdim//===----------------------------------------------------------------------===// 6786284677Sdim 6787314564SdimOperandMatchResultTy 6788309124SdimAMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix, 6789309124Sdim AMDGPUOperand::ImmTy Type) { 6790314564Sdim using namespace llvm::AMDGPU::SDWA; 6791314564Sdim 6792309124Sdim SMLoc S = Parser.getTok().getLoc(); 6793309124Sdim StringRef Value; 6794314564Sdim OperandMatchResultTy res; 6795284677Sdim 6796309124Sdim res = parseStringWithPrefix(Prefix, Value); 6797309124Sdim if (res != MatchOperand_Success) { 6798309124Sdim return res; 6799284677Sdim } 6800309124Sdim 6801309124Sdim int64_t Int; 6802309124Sdim Int = StringSwitch<int64_t>(Value) 6803314564Sdim .Case("BYTE_0", SdwaSel::BYTE_0) 6804314564Sdim .Case("BYTE_1", SdwaSel::BYTE_1) 6805314564Sdim .Case("BYTE_2", SdwaSel::BYTE_2) 6806314564Sdim .Case("BYTE_3", SdwaSel::BYTE_3) 6807314564Sdim .Case("WORD_0", SdwaSel::WORD_0) 6808314564Sdim .Case("WORD_1", SdwaSel::WORD_1) 6809314564Sdim .Case("DWORD", SdwaSel::DWORD) 6810309124Sdim .Default(0xffffffff); 6811309124Sdim Parser.Lex(); // eat last token 6812309124Sdim 6813309124Sdim if (Int == 0xffffffff) { 6814309124Sdim return MatchOperand_ParseFail; 6815309124Sdim } 6816309124Sdim 6817314564Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type)); 6818309124Sdim return MatchOperand_Success; 6819284677Sdim} 6820284677Sdim 6821314564SdimOperandMatchResultTy 6822309124SdimAMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) { 6823314564Sdim using namespace llvm::AMDGPU::SDWA; 6824314564Sdim 6825309124Sdim SMLoc S = Parser.getTok().getLoc(); 6826309124Sdim StringRef Value; 6827314564Sdim OperandMatchResultTy res; 6828309124Sdim 6829309124Sdim res = parseStringWithPrefix("dst_unused", Value); 6830309124Sdim if (res != MatchOperand_Success) { 6831309124Sdim return res; 6832309124Sdim } 6833309124Sdim 6834309124Sdim int64_t Int; 6835309124Sdim Int = StringSwitch<int64_t>(Value) 6836314564Sdim .Case("UNUSED_PAD", DstUnused::UNUSED_PAD) 6837314564Sdim .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT) 6838314564Sdim .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE) 6839309124Sdim .Default(0xffffffff); 6840309124Sdim Parser.Lex(); // eat last token 6841309124Sdim 6842309124Sdim if (Int == 0xffffffff) { 6843309124Sdim return MatchOperand_ParseFail; 6844309124Sdim } 6845309124Sdim 6846314564Sdim Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused)); 6847309124Sdim return MatchOperand_Success; 6848309124Sdim} 6849309124Sdim 6850309124Sdimvoid AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) { 6851309124Sdim cvtSDWA(Inst, Operands, SIInstrFlags::VOP1); 6852309124Sdim} 6853309124Sdim 6854309124Sdimvoid AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) { 6855309124Sdim cvtSDWA(Inst, Operands, SIInstrFlags::VOP2); 6856309124Sdim} 6857309124Sdim 6858321369Sdimvoid AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands) { 6859360784Sdim cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, true, true); 6860321369Sdim} 6861321369Sdim 6862360784Sdimvoid AMDGPUAsmParser::cvtSdwaVOP2e(MCInst &Inst, const OperandVector &Operands) { 6863360784Sdim cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, false, true); 6864360784Sdim} 6865360784Sdim 6866309124Sdimvoid AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) { 6867321369Sdim cvtSDWA(Inst, Operands, SIInstrFlags::VOPC, isVI()); 6868309124Sdim} 6869309124Sdim 6870309124Sdimvoid AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands, 6871360784Sdim uint64_t BasicInstType, 6872360784Sdim bool SkipDstVcc, 6873360784Sdim bool SkipSrcVcc) { 6874321369Sdim using namespace llvm::AMDGPU::SDWA; 6875327952Sdim 6876309124Sdim OptionalImmIndexMap OptionalIdx; 6877360784Sdim bool SkipVcc = SkipDstVcc || SkipSrcVcc; 6878360784Sdim bool SkippedVcc = false; 6879309124Sdim 6880309124Sdim unsigned I = 1; 6881309124Sdim const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 6882309124Sdim for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 6883309124Sdim ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 6884309124Sdim } 6885309124Sdim 6886309124Sdim for (unsigned E = Operands.size(); I != E; ++I) { 6887309124Sdim AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 6888360784Sdim if (SkipVcc && !SkippedVcc && Op.isReg() && 6889353358Sdim (Op.getReg() == AMDGPU::VCC || Op.getReg() == AMDGPU::VCC_LO)) { 6890321369Sdim // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst. 6891321369Sdim // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3) 6892321369Sdim // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand. 6893321369Sdim // Skip VCC only if we didn't skip it on previous iteration. 6894360784Sdim // Note that src0 and src1 occupy 2 slots each because of modifiers. 6895321369Sdim if (BasicInstType == SIInstrFlags::VOP2 && 6896360784Sdim ((SkipDstVcc && Inst.getNumOperands() == 1) || 6897360784Sdim (SkipSrcVcc && Inst.getNumOperands() == 5))) { 6898360784Sdim SkippedVcc = true; 6899321369Sdim continue; 6900321369Sdim } else if (BasicInstType == SIInstrFlags::VOPC && 6901321369Sdim Inst.getNumOperands() == 0) { 6902360784Sdim SkippedVcc = true; 6903321369Sdim continue; 6904321369Sdim } 6905321369Sdim } 6906321369Sdim if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 6907341825Sdim Op.addRegOrImmWithInputModsOperands(Inst, 2); 6908309124Sdim } else if (Op.isImm()) { 6909309124Sdim // Handle optional arguments 6910309124Sdim OptionalIdx[Op.getImmTy()] = I; 6911309124Sdim } else { 6912309124Sdim llvm_unreachable("Invalid operand type"); 6913309124Sdim } 6914360784Sdim SkippedVcc = false; 6915309124Sdim } 6916309124Sdim 6917353358Sdim if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx10 && 6918353358Sdim Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx9 && 6919321369Sdim Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) { 6920321369Sdim // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments 6921314564Sdim switch (BasicInstType) { 6922314564Sdim case SIInstrFlags::VOP1: 6923321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); 6924321369Sdim if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) { 6925321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0); 6926321369Sdim } 6927321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD); 6928321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE); 6929321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD); 6930314564Sdim break; 6931314564Sdim 6932314564Sdim case SIInstrFlags::VOP2: 6933321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); 6934321369Sdim if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) { 6935321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0); 6936321369Sdim } 6937321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD); 6938321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE); 6939321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD); 6940321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD); 6941314564Sdim break; 6942314564Sdim 6943314564Sdim case SIInstrFlags::VOPC: 6944353358Sdim if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::clamp) != -1) 6945353358Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); 6946321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD); 6947321369Sdim addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD); 6948314564Sdim break; 6949314564Sdim 6950314564Sdim default: 6951314564Sdim llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed"); 6952314564Sdim } 6953309124Sdim } 6954314564Sdim 6955314564Sdim // special case v_mac_{f16, f32}: 6956314564Sdim // it has src2 register operand that is tied to dst operand 6957314564Sdim if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi || 6958314564Sdim Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) { 6959314564Sdim auto it = Inst.begin(); 6960314564Sdim std::advance( 6961321369Sdim it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2)); 6962314564Sdim Inst.insert(it, Inst.getOperand(0)); // src2 = dst 6963309124Sdim } 6964309124Sdim} 6965309124Sdim 6966353358Sdim//===----------------------------------------------------------------------===// 6967353358Sdim// mAI 6968353358Sdim//===----------------------------------------------------------------------===// 6969353358Sdim 6970353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultBLGP() const { 6971353358Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyBLGP); 6972353358Sdim} 6973353358Sdim 6974353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultCBSZ() const { 6975353358Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyCBSZ); 6976353358Sdim} 6977353358Sdim 6978353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultABID() const { 6979353358Sdim return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyABID); 6980353358Sdim} 6981353358Sdim 6982284677Sdim/// Force static initialization. 6983360784Sdimextern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUAsmParser() { 6984314564Sdim RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget()); 6985314564Sdim RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget()); 6986284677Sdim} 6987284677Sdim 6988284677Sdim#define GET_REGISTER_MATCHER 6989284677Sdim#define GET_MATCHER_IMPLEMENTATION 6990327952Sdim#define GET_MNEMONIC_SPELL_CHECKER 6991284677Sdim#include "AMDGPUGenAsmMatcher.inc" 6992284677Sdim 6993309124Sdim// This fuction should be defined after auto-generated include so that we have 6994309124Sdim// MatchClassKind enum defined 6995309124Sdimunsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op, 6996309124Sdim unsigned Kind) { 6997309124Sdim // Tokens like "glc" would be parsed as immediate operands in ParseOperand(). 6998309124Sdim // But MatchInstructionImpl() expects to meet token and fails to validate 6999309124Sdim // operand. This method checks if we are given immediate operand but expect to 7000309124Sdim // get corresponding token. 7001309124Sdim AMDGPUOperand &Operand = (AMDGPUOperand&)Op; 7002309124Sdim switch (Kind) { 7003309124Sdim case MCK_addr64: 7004309124Sdim return Operand.isAddr64() ? Match_Success : Match_InvalidOperand; 7005309124Sdim case MCK_gds: 7006309124Sdim return Operand.isGDS() ? Match_Success : Match_InvalidOperand; 7007341825Sdim case MCK_lds: 7008341825Sdim return Operand.isLDS() ? Match_Success : Match_InvalidOperand; 7009309124Sdim case MCK_glc: 7010309124Sdim return Operand.isGLC() ? Match_Success : Match_InvalidOperand; 7011309124Sdim case MCK_idxen: 7012309124Sdim return Operand.isIdxen() ? Match_Success : Match_InvalidOperand; 7013309124Sdim case MCK_offen: 7014309124Sdim return Operand.isOffen() ? Match_Success : Match_InvalidOperand; 7015314564Sdim case MCK_SSrcB32: 7016309124Sdim // When operands have expression values, they will return true for isToken, 7017309124Sdim // because it is not possible to distinguish between a token and an 7018309124Sdim // expression at parse time. MatchInstructionImpl() will always try to 7019309124Sdim // match an operand as a token, when isToken returns true, and when the 7020309124Sdim // name of the expression is not a valid token, the match will fail, 7021309124Sdim // so we need to handle it here. 7022314564Sdim return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand; 7023314564Sdim case MCK_SSrcF32: 7024314564Sdim return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand; 7025309124Sdim case MCK_SoppBrTarget: 7026309124Sdim return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand; 7027314564Sdim case MCK_VReg32OrOff: 7028314564Sdim return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand; 7029314564Sdim case MCK_InterpSlot: 7030314564Sdim return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand; 7031314564Sdim case MCK_Attr: 7032314564Sdim return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand; 7033314564Sdim case MCK_AttrChan: 7034314564Sdim return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand; 7035360784Sdim case MCK_SReg_64: 7036360784Sdim case MCK_SReg_64_XEXEC: 7037360784Sdim // Null is defined as a 32-bit register but 7038360784Sdim // it should also be enabled with 64-bit operands. 7039360784Sdim // The following code enables it for SReg_64 operands 7040360784Sdim // used as source and destination. Remaining source 7041360784Sdim // operands are handled in isInlinableImm. 7042360784Sdim return Operand.isNull() ? Match_Success : Match_InvalidOperand; 7043314564Sdim default: 7044314564Sdim return Match_InvalidOperand; 7045309124Sdim } 7046309124Sdim} 7047353358Sdim 7048353358Sdim//===----------------------------------------------------------------------===// 7049353358Sdim// endpgm 7050353358Sdim//===----------------------------------------------------------------------===// 7051353358Sdim 7052353358SdimOperandMatchResultTy AMDGPUAsmParser::parseEndpgmOp(OperandVector &Operands) { 7053353358Sdim SMLoc S = Parser.getTok().getLoc(); 7054353358Sdim int64_t Imm = 0; 7055353358Sdim 7056353358Sdim if (!parseExpr(Imm)) { 7057353358Sdim // The operand is optional, if not present default to 0 7058353358Sdim Imm = 0; 7059353358Sdim } 7060353358Sdim 7061353358Sdim if (!isUInt<16>(Imm)) { 7062353358Sdim Error(S, "expected a 16-bit value"); 7063353358Sdim return MatchOperand_ParseFail; 7064353358Sdim } 7065353358Sdim 7066353358Sdim Operands.push_back( 7067353358Sdim AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyEndpgm)); 7068353358Sdim return MatchOperand_Success; 7069353358Sdim} 7070353358Sdim 7071353358Sdimbool AMDGPUOperand::isEndpgm() const { return isImmTy(ImmTyEndpgm); } 7072