Index: llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -2838,6 +2838,28 @@ // s_waitcnt //===----------------------------------------------------------------------===// +static bool +encodeCnt( + const AMDGPU::IsaInfo::IsaVersion ISA, + int64_t &IntVal, + int64_t CntVal, + bool Saturate, + unsigned (*encode)(const IsaInfo::IsaVersion &Version, unsigned, unsigned), + unsigned (*decode)(const IsaInfo::IsaVersion &Version, unsigned)) +{ + bool Failed = false; + + IntVal = encode(ISA, IntVal, CntVal); + if (CntVal != decode(ISA, IntVal)) { + if (Saturate) { + IntVal = encode(ISA, IntVal, -1); + } else { + Failed = true; + } + } + return Failed; +} + bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) { StringRef CntName = Parser.getTok().getString(); int64_t CntVal; @@ -2853,25 +2875,35 @@ if (getParser().parseAbsoluteExpression(CntVal)) return true; - if (getLexer().isNot(AsmToken::RParen)) - return true; - - Parser.Lex(); - if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) - Parser.Lex(); - AMDGPU::IsaInfo::IsaVersion ISA = AMDGPU::IsaInfo::getIsaVersion(getFeatureBits()); - if (CntName == "vmcnt") - IntVal = encodeVmcnt(ISA, IntVal, CntVal); - else if (CntName == "expcnt") - IntVal = encodeExpcnt(ISA, IntVal, CntVal); - else if (CntName == "lgkmcnt") - IntVal = encodeLgkmcnt(ISA, IntVal, CntVal); - else - return true; - return false; + bool Failed = true; + bool Sat = CntName.endswith("_sat"); + + if (CntName == "vmcnt" || CntName == "vmcnt_sat") { + Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt); + } else if (CntName == "expcnt" || CntName == "expcnt_sat") { + Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt); + } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") { + Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt); + } + + // To improve diagnostics, do not skip delimiters on errors + if (!Failed) { + if (getLexer().isNot(AsmToken::RParen)) { + return true; + } + Parser.Lex(); + if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) { + const AsmToken NextToken = getLexer().peekTok(); + if (NextToken.is(AsmToken::Identifier)) { + Parser.Lex(); + } + } + } + + return Failed; } OperandMatchResultTy Index: llvm/trunk/test/MC/AMDGPU/sopp-err.s =================================================================== --- llvm/trunk/test/MC/AMDGPU/sopp-err.s +++ llvm/trunk/test/MC/AMDGPU/sopp-err.s @@ -73,3 +73,21 @@ s_sendmsg sendmsg(MSG_SYSMSG, 5) // GCN: error: invalid/unsupported code of SYSMSG_OP + +s_waitcnt lgkmcnt(16) +// GCN: error: failed parsing operand + +s_waitcnt expcnt(8) +// GCN: error: failed parsing operand + +s_waitcnt vmcnt(16) +// GCN: error: failed parsing operand + +s_waitcnt vmcnt(0xFFFFFFFFFFFF0000) +// GCN: error: failed parsing operand + +s_waitcnt vmcnt(0), expcnt(0), lgkmcnt(0), +// GCN: error: failed parsing operand + +s_waitcnt vmcnt(0) & expcnt(0) & lgkmcnt(0)& +// GCN: error: failed parsing operand Index: llvm/trunk/test/MC/AMDGPU/sopp.s =================================================================== --- llvm/trunk/test/MC/AMDGPU/sopp.s +++ llvm/trunk/test/MC/AMDGPU/sopp.s @@ -80,18 +80,56 @@ s_waitcnt vmcnt(9) // GCN: s_waitcnt vmcnt(9) ; encoding: [0x79,0x0f,0x8c,0xbf] +s_waitcnt vmcnt(15) +// GCN: s_waitcnt ; encoding: [0x7f,0x0f,0x8c,0xbf] + +s_waitcnt vmcnt_sat(9) +// GCN: s_waitcnt vmcnt(9) ; encoding: [0x79,0x0f,0x8c,0xbf] + +s_waitcnt vmcnt_sat(15) +// GCN: s_waitcnt ; encoding: [0x7f,0x0f,0x8c,0xbf] + +s_waitcnt vmcnt_sat(16) +// GCN: s_waitcnt ; encoding: [0x7f,0x0f,0x8c,0xbf] + s_waitcnt expcnt(2) // GCN: s_waitcnt expcnt(2) ; encoding: [0x2f,0x0f,0x8c,0xbf] +s_waitcnt expcnt(7) +// GCN: s_waitcnt ; encoding: [0x7f,0x0f,0x8c,0xbf] + +s_waitcnt expcnt_sat(2) +// GCN: s_waitcnt expcnt(2) ; encoding: [0x2f,0x0f,0x8c,0xbf] + +s_waitcnt expcnt_sat(7) +// GCN: s_waitcnt ; encoding: [0x7f,0x0f,0x8c,0xbf] + +s_waitcnt expcnt_sat(0xFFFF0000) +// GCN: s_waitcnt ; encoding: [0x7f,0x0f,0x8c,0xbf] + s_waitcnt lgkmcnt(3) // GCN: s_waitcnt lgkmcnt(3) ; encoding: [0x7f,0x03,0x8c,0xbf] s_waitcnt lgkmcnt(9) // GCN: s_waitcnt lgkmcnt(9) ; encoding: [0x7f,0x09,0x8c,0xbf] +s_waitcnt lgkmcnt(15) +// GCN: s_waitcnt ; encoding: [0x7f,0x0f,0x8c,0xbf] + s_waitcnt vmcnt(0), expcnt(0) // GCN: s_waitcnt vmcnt(0) expcnt(0) ; encoding: [0x00,0x0f,0x8c,0xbf] +s_waitcnt lgkmcnt_sat(3) +// GCN: s_waitcnt lgkmcnt(3) ; encoding: [0x7f,0x03,0x8c,0xbf] + +s_waitcnt lgkmcnt_sat(9) +// GCN: s_waitcnt lgkmcnt(9) ; encoding: [0x7f,0x09,0x8c,0xbf] + +s_waitcnt lgkmcnt_sat(15) +// GCN: s_waitcnt ; encoding: [0x7f,0x0f,0x8c,0xbf] + +s_waitcnt lgkmcnt_sat(16) +// GCN: s_waitcnt ; encoding: [0x7f,0x0f,0x8c,0xbf] s_sethalt 9 // GCN: s_sethalt 9 ; encoding: [0x09,0x00,0x8d,0xbf]