Index: lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1126,11 +1126,17 @@ struct OperandInfoTy { int64_t Id; bool IsSymbolic = false; + bool IsDefined = false; OperandInfoTy(int64_t Id_) : Id(Id_) {} }; - bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId); + bool parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op, OperandInfoTy &Stream); + void validateSendMsg(const OperandInfoTy &Msg, + const OperandInfoTy &Op, + const OperandInfoTy &Stream, + const SMLoc Loc); + bool parseHwregBody(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width); void validateHwreg(const OperandInfoTy &HwReg, const int64_t Offset, @@ -4556,107 +4562,100 @@ // sendmsg //===----------------------------------------------------------------------===// -bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) { +bool +AMDGPUAsmParser::parseSendMsgBody(OperandInfoTy &Msg, + OperandInfoTy &Op, + OperandInfoTy &Stream) { using namespace llvm::AMDGPU::SendMsg; - if (Parser.getTok().getString() != "sendmsg") - return true; - Parser.Lex(); + if (isToken(AsmToken::Identifier) && (Msg.Id = getMsgId(getTokenStr())) >= 0) { + Msg.IsSymbolic = true; + lex(); // skip message name + } else if (!parseExpr(Msg.Id)) { + return false; + } - if (getLexer().isNot(AsmToken::LParen)) - return true; - Parser.Lex(); + if (trySkipToken(AsmToken::Comma)) { + Op.IsDefined = true; + if (isToken(AsmToken::Identifier) && + (Op.Id = getMsgOpId(Msg.Id, getTokenStr())) >= 0) { + lex(); // skip operation name + } else if (!parseExpr(Op.Id)) { + return false; + } - if (getLexer().is(AsmToken::Identifier)) { - Msg.IsSymbolic = true; - Msg.Id = ID_UNKNOWN_; - const std::string tok = Parser.getTok().getString(); - for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) { - switch(i) { - default: continue; // Omit gaps. - case ID_GS_ALLOC_REQ: - if (isSI() || isCI() || isVI()) - continue; - break; - case ID_INTERRUPT: case ID_GS: case ID_GS_DONE: - case ID_SYSMSG: break; - } - if (tok == IdSymbolic[i]) { - Msg.Id = i; - break; - } + if (trySkipToken(AsmToken::Comma)) { + Stream.IsDefined = true; + if (!parseExpr(Stream.Id)) + return false; } - Parser.Lex(); - } else { - Msg.IsSymbolic = false; - if (getLexer().isNot(AsmToken::Integer)) - return true; - if (getParser().parseAbsoluteExpression(Msg.Id)) - return true; - if (getLexer().is(AsmToken::Integer)) - if (getParser().parseAbsoluteExpression(Msg.Id)) - Msg.Id = ID_UNKNOWN_; } - if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest. - return false; - if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) { - if (getLexer().isNot(AsmToken::RParen)) - return true; - Parser.Lex(); - return false; - } + return skipToken(AsmToken::RParen, "expected a closing parenthesis"); +} - if (getLexer().isNot(AsmToken::Comma)) - return true; - Parser.Lex(); +void +AMDGPUAsmParser::validateSendMsg(const OperandInfoTy &Msg, + const OperandInfoTy &Op, + const OperandInfoTy &Stream, + const SMLoc S) { + using namespace llvm::AMDGPU::SendMsg; + AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU()); - assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG); - Operation.Id = ID_UNKNOWN_; - if (getLexer().is(AsmToken::Identifier)) { - Operation.IsSymbolic = true; - const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic; - const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_; - const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_; - const StringRef Tok = Parser.getTok().getString(); - for (int i = F; i < L; ++i) { - if (Tok == S[i]) { - Operation.Id = i; - break; - } - } - Parser.Lex(); - } else { - Operation.IsSymbolic = false; - if (getLexer().isNot(AsmToken::Integer)) - return true; - if (getParser().parseAbsoluteExpression(Operation.Id)) - return true; + // Validation strictness depends on whether message is specified + // in a symbolc or in a numeric form. In the latter case + // only encoding possibility is checked. + bool Strict = Msg.IsSymbolic; + + if (!isValidMsgId(Msg.Id, ISA, Strict)) { + Error(S, "invalid message id"); + } else if (Strict && (msgRequiresOp(Msg.Id) != Op.IsDefined)) { + Error(S, Op.IsDefined ? + "message does not support operations" : + "missing message operation"); + } else if (!isValidMsgOp(Msg.Id, Op.Id, Strict)) { + Error(S, "invalid operation id"); + } else if (Strict && !msgSupportsStream(Msg.Id, Op.Id) && Stream.IsDefined) { + Error(S, "message operation does not support streams"); + } else if (!isValidMsgStream(Msg.Id, Op.Id, Stream.Id, Strict)) { + Error(S, "invalid message stream id"); } +} - if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) { - // Stream id is optional. - if (getLexer().is(AsmToken::RParen)) { - Parser.Lex(); - return false; - } +OperandMatchResultTy +AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) { + using namespace llvm::AMDGPU::SendMsg; - if (getLexer().isNot(AsmToken::Comma)) - return true; - Parser.Lex(); + int64_t ImmVal = 0; + SMLoc Loc = getLoc(); - if (getLexer().isNot(AsmToken::Integer)) - return true; - if (getParser().parseAbsoluteExpression(StreamId)) - return true; + // If parse failed, do not return error code + // to avoid excessive error messages. + if (trySkipId("sendmsg", AsmToken::LParen)) { + OperandInfoTy Msg(ID_UNKNOWN_); + OperandInfoTy Op(OP_NONE_); + OperandInfoTy Stream(STREAM_ID_NONE_); + if (parseSendMsgBody(Msg, Op, Stream)) { + validateSendMsg(Msg, Op, Stream, Loc); + ImmVal = encodeMsg(Msg.Id, Op.Id, Stream.Id); + } + } else if (parseExpr(ImmVal)) { + if (ImmVal < 0 || !isUInt<16>(ImmVal)) + Error(Loc, "invalid immediate: only 16-bit values are legal"); } - if (getLexer().isNot(AsmToken::RParen)) - return true; - Parser.Lex(); - return false; + Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTySendMsg)); + return MatchOperand_Success; } +bool AMDGPUOperand::isSendMsg() const { + return isImmTy(ImmTySendMsg); +} + +//===----------------------------------------------------------------------===// +// v_interp +//===----------------------------------------------------------------------===// + OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) { if (getLexer().getKind() != AsmToken::Identifier) return MatchOperand_NoMatch; @@ -4718,6 +4717,10 @@ return MatchOperand_Success; } +//===----------------------------------------------------------------------===// +// exp +//===----------------------------------------------------------------------===// + void AMDGPUAsmParser::errorExpTgt() { Error(Parser.getTok().getLoc(), "invalid exp target"); } @@ -4802,90 +4805,6 @@ return MatchOperand_Success; } -OperandMatchResultTy -AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) { - using namespace llvm::AMDGPU::SendMsg; - - int64_t Imm16Val = 0; - SMLoc S = Parser.getTok().getLoc(); - - switch(getLexer().getKind()) { - default: - return MatchOperand_NoMatch; - case AsmToken::Integer: - // The operand can be an integer value. - if (getParser().parseAbsoluteExpression(Imm16Val)) - return MatchOperand_NoMatch; - if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) { - Error(S, "invalid immediate: only 16-bit values are legal"); - // Do not return error code, but create an imm operand anyway and proceed - // to the next operand, if any. That avoids unneccessary error messages. - } - break; - case AsmToken::Identifier: { - OperandInfoTy Msg(ID_UNKNOWN_); - OperandInfoTy Operation(OP_UNKNOWN_); - int64_t StreamId = STREAM_ID_DEFAULT_; - if (parseSendMsgConstruct(Msg, Operation, StreamId)) - return MatchOperand_ParseFail; - do { - // Validate and encode message ID. - if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE) - || (Msg.Id == ID_GS_ALLOC_REQ && !isSI() && !isCI() && !isVI()) - || Msg.Id == ID_SYSMSG)) { - if (Msg.IsSymbolic) - Error(S, "invalid/unsupported symbolic name of message"); - else - Error(S, "invalid/unsupported code of message"); - break; - } - Imm16Val = (Msg.Id << ID_SHIFT_); - // Validate and encode operation ID. - if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) { - if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) { - if (Operation.IsSymbolic) - Error(S, "invalid symbolic name of GS_OP"); - else - Error(S, "invalid code of GS_OP: only 2-bit values are legal"); - break; - } - if (Operation.Id == OP_GS_NOP - && Msg.Id != ID_GS_DONE) { - Error(S, "invalid GS_OP: NOP is for GS_DONE only"); - break; - } - Imm16Val |= (Operation.Id << OP_SHIFT_); - } - if (Msg.Id == ID_SYSMSG) { - if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) { - if (Operation.IsSymbolic) - Error(S, "invalid/unsupported symbolic name of SYSMSG_OP"); - else - Error(S, "invalid/unsupported code of SYSMSG_OP"); - break; - } - Imm16Val |= (Operation.Id << OP_SHIFT_); - } - // Validate and encode stream ID. - if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) { - if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) { - Error(S, "invalid stream id: only 2-bit values are legal"); - break; - } - Imm16Val |= (StreamId << STREAM_ID_SHIFT_); - } - } while (false); - } - break; - } - Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTySendMsg)); - return MatchOperand_Success; -} - -bool AMDGPUOperand::isSendMsg() const { - return isImmTy(ImmTySendMsg); -} - //===----------------------------------------------------------------------===// // parser helpers //===----------------------------------------------------------------------===// Index: lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp =================================================================== --- lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp +++ lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp @@ -1133,42 +1133,30 @@ raw_ostream &O) { using namespace llvm::AMDGPU::SendMsg; - const unsigned SImm16 = MI->getOperand(OpNo).getImm(); - const unsigned Id = SImm16 & ID_MASK_; - do { - if (Id == ID_INTERRUPT || - (Id == ID_GS_ALLOC_REQ && !AMDGPU::isSI(STI) && !AMDGPU::isCI(STI) && - !AMDGPU::isVI(STI))) { - if ((SImm16 & ~ID_MASK_) != 0) // Unused/unknown bits must be 0. - break; - O << "sendmsg(" << IdSymbolic[Id] << ')'; - return; - } - if (Id == ID_GS || Id == ID_GS_DONE) { - if ((SImm16 & ~(ID_MASK_|OP_GS_MASK_|STREAM_ID_MASK_)) != 0) // Unused/unknown bits must be 0. - break; - const unsigned OpGs = (SImm16 & OP_GS_MASK_) >> OP_SHIFT_; - const unsigned StreamId = (SImm16 & STREAM_ID_MASK_) >> STREAM_ID_SHIFT_; - if (OpGs == OP_GS_NOP && Id != ID_GS_DONE) // NOP to be used for GS_DONE only. - break; - if (OpGs == OP_GS_NOP && StreamId != 0) // NOP does not use/define stream id bits. - break; - O << "sendmsg(" << IdSymbolic[Id] << ", " << OpGsSymbolic[OpGs]; - if (OpGs != OP_GS_NOP) { O << ", " << StreamId; } - O << ')'; - return; - } - if (Id == ID_SYSMSG) { - if ((SImm16 & ~(ID_MASK_|OP_SYS_MASK_)) != 0) // Unused/unknown bits must be 0. - break; - const unsigned OpSys = (SImm16 & OP_SYS_MASK_) >> OP_SHIFT_; - if (! (OP_SYS_FIRST_ <= OpSys && OpSys < OP_SYS_LAST_)) // Unused/unknown. - break; - O << "sendmsg(" << IdSymbolic[Id] << ", " << OpSysSymbolic[OpSys] << ')'; - return; + AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(STI.getCPU()); + const unsigned Imm16 = MI->getOperand(OpNo).getImm(); + + uint16_t MsgId; + uint16_t OpId; + uint16_t StreamId; + decodeMsg(Imm16, MsgId, OpId, StreamId); + + if (isValidMsgId(MsgId, ISA) && + isValidMsgOp(MsgId, OpId) && + isValidMsgStream(MsgId, OpId, StreamId)) { + O << "sendmsg(" << getMsgName(MsgId); + if (msgRequiresOp(MsgId)) { + O << ", " << getMsgOpName(MsgId, OpId); + if (msgSupportsStream(MsgId, OpId)) { + O << ", " << StreamId; + } } - } while (false); - O << SImm16; // Unknown simm16 code. + O << ')'; + } else if (encodeMsg(MsgId, OpId, StreamId) == Imm16) { + O << "sendmsg(" << MsgId << ", " << OpId << ", " << StreamId << ')'; + } else { + O << Imm16; // Unknown imm16 code. + } } static void printSwizzleBitmask(const uint16_t AndMask, Index: lib/Target/AMDGPU/SIDefines.h =================================================================== --- lib/Target/AMDGPU/SIDefines.h +++ lib/Target/AMDGPU/SIDefines.h @@ -264,27 +264,28 @@ enum Op { // Both GS and SYS operation IDs. OP_UNKNOWN_ = -1, OP_SHIFT_ = 4, - // width(2) [5:4] + OP_NONE_ = 0, + // Bits used for operation encoding + OP_WIDTH_ = 3, + OP_MASK_ = (((1 << OP_WIDTH_) - 1) << OP_SHIFT_), + // GS operations are encoded in bits 5:4 OP_GS_NOP = 0, OP_GS_CUT, OP_GS_EMIT, OP_GS_EMIT_CUT, OP_GS_LAST_, OP_GS_FIRST_ = OP_GS_NOP, - OP_GS_WIDTH_ = 2, - OP_GS_MASK_ = (((1 << OP_GS_WIDTH_) - 1) << OP_SHIFT_), - // width(3) [6:4] + // SYS operations are encoded in bits 6:4 OP_SYS_ECC_ERR_INTERRUPT = 1, OP_SYS_REG_RD, OP_SYS_HOST_TRAP_ACK, OP_SYS_TTRACE_PC, OP_SYS_LAST_, OP_SYS_FIRST_ = OP_SYS_ECC_ERR_INTERRUPT, - OP_SYS_WIDTH_ = 3, - OP_SYS_MASK_ = (((1 << OP_SYS_WIDTH_) - 1) << OP_SHIFT_) }; enum StreamId : unsigned { // Stream ID, (2) [9:8]. + STREAM_ID_NONE_ = 0, STREAM_ID_DEFAULT_ = 0, STREAM_ID_LAST_ = 4, STREAM_ID_FIRST_ = STREAM_ID_DEFAULT_, Index: lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h =================================================================== --- lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -425,6 +425,49 @@ } // namespace Hwreg +namespace SendMsg { + +LLVM_READNONE +int64_t getMsgId(const StringRef Name); + +LLVM_READNONE +int64_t getMsgOpId(int64_t MsgId, const StringRef Name); + +LLVM_READNONE +StringRef getMsgName(int64_t MsgId); + +LLVM_READNONE +StringRef getMsgOpName(int64_t MsgId, int64_t OpId); + +LLVM_READNONE +bool isValidMsgId(int64_t MsgId, const IsaVersion &Version, bool Strict = true); + +LLVM_READNONE +bool isValidMsgOp(int64_t MsgId, int64_t OpId, bool Strict = true); + +LLVM_READNONE +bool isValidMsgStream(int64_t MsgId, int64_t OpId, int64_t StreamId, bool Strict = true); + +LLVM_READNONE +bool msgRequiresOp(int64_t MsgId); + +LLVM_READNONE +bool msgSupportsStream(int64_t MsgId, int64_t OpId); + +LLVM_READNONE +void decodeMsg(unsigned Val, + uint16_t &MsgId, + uint16_t &OpId, + uint16_t &StreamId); + +LLVM_READNONE +int64_t encodeMsg(int64_t MsgId, + int64_t OpId, + int64_t StreamId); + +} // namespace SendMsg + + unsigned getInitialPSInputAddr(const Function &F); LLVM_READNONE Index: lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp =================================================================== --- lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -696,6 +696,114 @@ } // namespace Hwreg //===----------------------------------------------------------------------===// +// SendMsg +//===----------------------------------------------------------------------===// + +namespace SendMsg { + +int64_t getMsgId(const StringRef Name) { + for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) { + if (IdSymbolic[i] && Name == IdSymbolic[i]) + return i; + } + return ID_UNKNOWN_; +} + +static bool isValidMsgId(int64_t MsgId) { + return (ID_GAPS_FIRST_ <= MsgId && MsgId < ID_GAPS_LAST_) && IdSymbolic[MsgId]; +} + +bool isValidMsgId(int64_t MsgId, const IsaVersion &Version, bool Strict) { + return Strict ? + isValidMsgId(MsgId) && (MsgId != ID_GS_ALLOC_REQ || Version.Major >= 9) : + 0 <= MsgId && isUInt(MsgId); +} + +StringRef getMsgName(int64_t MsgId) { + return isValidMsgId(MsgId)? IdSymbolic[MsgId] : ""; +} + +int64_t getMsgOpId(int64_t MsgId, const StringRef Name) { + const char* const *S = (MsgId == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic; + const int F = (MsgId == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_; + const int L = (MsgId == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_; + for (int i = F; i < L; ++i) { + if (Name == S[i]) { + return i; + } + } + return OP_UNKNOWN_; +} + +bool isValidMsgOp(int64_t MsgId, int64_t OpId, bool Strict) { + + if (!Strict) + return 0 <= OpId && isUInt(OpId); + + switch(MsgId) + { + case ID_GS: + return (OP_GS_FIRST_ <= OpId && OpId < OP_GS_LAST_) && OpId != OP_GS_NOP; + case ID_GS_DONE: + return OP_GS_FIRST_ <= OpId && OpId < OP_GS_LAST_; + case ID_SYSMSG: + return OP_SYS_FIRST_ <= OpId && OpId < OP_SYS_LAST_; + default: + return OpId == OP_NONE_; + } +} + +StringRef getMsgOpName(int64_t MsgId, int64_t OpId) { + assert(msgRequiresOp(MsgId)); + return (MsgId == ID_SYSMSG)? OpSysSymbolic[OpId] : OpGsSymbolic[OpId]; +} + +bool isValidMsgStream(int64_t MsgId, int64_t OpId, int64_t StreamId, bool Strict) { + + if (!Strict) + return 0 <= StreamId && isUInt(StreamId); + + switch(MsgId) + { + case ID_GS: + return STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_; + case ID_GS_DONE: + return (OpId == OP_GS_NOP)? + (StreamId == STREAM_ID_NONE_) : + (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_); + default: + return StreamId == STREAM_ID_NONE_; + } +} + +bool msgRequiresOp(int64_t MsgId) { + return MsgId == ID_GS || MsgId == ID_GS_DONE || MsgId == ID_SYSMSG; +} + +bool msgSupportsStream(int64_t MsgId, int64_t OpId) { + return (MsgId == ID_GS || MsgId == ID_GS_DONE) && OpId != OP_GS_NOP; +} + +void decodeMsg(unsigned Val, + uint16_t &MsgId, + uint16_t &OpId, + uint16_t &StreamId) { + MsgId = Val & ID_MASK_; + OpId = (Val & OP_MASK_) >> OP_SHIFT_; + StreamId = (Val & STREAM_ID_MASK_) >> STREAM_ID_SHIFT_; +} + +int64_t encodeMsg(int64_t MsgId, + int64_t OpId, + int64_t StreamId) { + return (MsgId << ID_SHIFT_) | + (OpId << OP_SHIFT_) | + (StreamId << STREAM_ID_SHIFT_); +} + +} // namespace SendMsg + +//===----------------------------------------------------------------------===// // //===----------------------------------------------------------------------===// Index: test/CodeGen/AMDGPU/llvm.amdgcn.sendmsg.ll =================================================================== --- test/CodeGen/AMDGPU/llvm.amdgcn.sendmsg.ll +++ test/CodeGen/AMDGPU/llvm.amdgcn.sendmsg.ll @@ -56,7 +56,7 @@ ; GCN: s_mov_b32 m0, s0 ; GCN-NOT: s_mov_b32 m0 ; VIPLUS-NEXT: s_nop 0 -; SIVI: s_sendmsg 9 +; SIVI: s_sendmsg sendmsg(9, 0, 0) ; GFX9: s_sendmsg sendmsg(MSG_GS_ALLOC_REQ) define amdgpu_kernel void @test_gs_alloc_req(i32 inreg %a) { body: Index: test/MC/AMDGPU/sopp-err.s =================================================================== --- test/MC/AMDGPU/sopp-err.s +++ test/MC/AMDGPU/sopp-err.s @@ -3,83 +3,112 @@ // RUN: not llvm-mc -arch=amdgcn -mcpu=fiji -show-encoding %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=VI --check-prefix=SICIVI %s // RUN: not llvm-mc -arch=amdgcn -mcpu=gfx1010 -show-encoding %s 2>&1 | FileCheck --check-prefix=GCN %s -s_sendmsg sendmsg(11) -// GCN: error: invalid/unsupported code of message +//===----------------------------------------------------------------------===// +// sendmsg +//===----------------------------------------------------------------------===// s_sendmsg sendmsg(MSG_INTERRUPTX) -// GCN: error: invalid/unsupported symbolic name of message +// GCN: error: expected absolute expression + +s_sendmsg sendmsg(1 -) +// GCN: error: unknown token in expression s_sendmsg sendmsg(MSG_INTERRUPT, 0) -// GCN: error: failed parsing operand +// GCN: error: message does not support operations + +s_sendmsg sendmsg(MSG_INTERRUPT, 0, 0) +// GCN: error: message does not support operations s_sendmsg sendmsg(MSG_GS) -// GCN: error: failed parsing operand +// GCN: error: missing message operation s_sendmsg sendmsg(MSG_GS, GS_OP_NOP) -// GCN: error: invalid GS_OP: NOP is for GS_DONE only +// GCN: error: invalid operation id + +s_sendmsg sendmsg(MSG_GS, SYSMSG_OP_ECC_ERR_INTERRUPT) +// GCN: error: expected absolute expression + +s_sendmsg sendmsg(MSG_GS, 0) +// GCN: error: invalid operation id + +s_sendmsg sendmsg(MSG_GS, -1) +// GCN: error: invalid operation id + +s_sendmsg sendmsg(MSG_GS, 4) +// GCN: error: invalid operation id + +s_sendmsg sendmsg(MSG_GS, 8) +// GCN: error: invalid operation id + +s_sendmsg sendmsg(15, -1) +// GCN: error: invalid operation id + +s_sendmsg sendmsg(15, 8) +// GCN: error: invalid operation id s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0, 0) -// GCN: error: failed parsing operand +// GCN: error: expected a closing parenthesis s_sendmsg sendmsg(MSG_GSX, GS_OP_CUT, 0) -// GCN: error: invalid/unsupported symbolic name of message +// GCN: error: expected absolute expression s_sendmsg sendmsg(MSG_GS, GS_OP_CUTX, 0) -// GCN: error: invalid symbolic name of GS_OP +// GCN: error: expected absolute expression -s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 4) -// GCN: error: invalid stream id: only 2-bit values are legal +s_sendmsg sendmsg(MSG_GS, 1 -) +// GCN: error: unknown token in expression -s_sendmsg sendmsg(2) -// GCN: error: failed parsing operand +s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 4) +// GCN: error: invalid message stream id -s_sendmsg sendmsg(2, 0) -// GCN: error: invalid GS_OP: NOP is for GS_DONE only +s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 1 -) +// GCN: error: unknown token in expression s_sendmsg sendmsg(2, 3, 0, 0) -// GCN: error: failed parsing operand +// GCN: error: expected a closing parenthesis -s_sendmsg sendmsg(2, 4, 1) -// GCN: error: invalid code of GS_OP: only 2-bit values are legal +s_sendmsg sendmsg(2, 2, -1) +// GCN: error: invalid message stream id s_sendmsg sendmsg(2, 2, 4) -// GCN: error: invalid stream id: only 2-bit values are legal +// GCN: error: invalid message stream id s_sendmsg sendmsg(2, 2, 0, 0) -// GCN: error: failed parsing operand +// GCN: error: expected a closing parenthesis s_sendmsg sendmsg(MSG_GS_DONE, GS_OP_NOP, 0) -// GCN: error: failed parsing operand +// GCN: error: message operation does not support streams + +s_sendmsg sendmsg(MSG_GS_DONE, 0, 0) +// GCN: error: message operation does not support streams s_sendmsg sendmsg(MSG_GS_ALLOC_REQ) -// SICIVI: error: invalid/unsupported symbolic name of message +// SICIVI: error: invalid message id s_sendmsg sendmsg(MSG_GS_ALLOC_REQ, 0) -// SICIVI: error: invalid/unsupported symbolic name of message - -s_sendmsg sendmsg(15) -// GCN: error: failed parsing operand +// SICIVI: error: invalid message id -s_sendmsg sendmsg(15, 1, 0) -// GCN: error: failed parsing operand +s_sendmsg sendmsg(-1) +// SICIVI: error: invalid message id -s_sendmsg sendmsg(15, 0) -// GCN: error: invalid/unsupported code of SYSMSG_OP - -s_sendmsg sendmsg(15, 5) -// GCN: error: invalid/unsupported code of SYSMSG_OP +s_sendmsg sendmsg(16) +// SICIVI: error: invalid message id s_sendmsg sendmsg(MSG_SYSMSG) -// GCN: error: failed parsing operand +// GCN: error: missing message operation s_sendmsg sendmsg(MSG_SYSMSG, SYSMSG_OP_ECC_ERR_INTERRUPT, 0) -// GCN: error: failed parsing operand +// GCN: error: message operation does not support streams s_sendmsg sendmsg(MSG_SYSMSG, 0) -// GCN: error: invalid/unsupported code of SYSMSG_OP +// GCN: error: invalid operation id s_sendmsg sendmsg(MSG_SYSMSG, 5) -// GCN: error: invalid/unsupported code of SYSMSG_OP +// GCN: error: invalid operation id + +//===----------------------------------------------------------------------===// +// waitcnt +//===----------------------------------------------------------------------===// s_waitcnt lgkmcnt(16) // SICIVI: error: too large value for lgkmcnt Index: test/MC/AMDGPU/sopp.s =================================================================== --- test/MC/AMDGPU/sopp.s +++ test/MC/AMDGPU/sopp.s @@ -167,8 +167,9 @@ s_setprio 1 // GCN: s_setprio 1 ; encoding: [0x01,0x00,0x8f,0xbf] -s_sendmsg 2 -// GCN: s_sendmsg 2 ; encoding: [0x02,0x00,0x90,0xbf] +//===----------------------------------------------------------------------===// +// s_sendmsg +//===----------------------------------------------------------------------===// s_sendmsg 0x1 // GCN: s_sendmsg sendmsg(MSG_INTERRUPT) ; encoding: [0x01,0x00,0x90,0xbf] @@ -185,9 +186,21 @@ s_sendmsg sendmsg(2, 1) // GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0) ; encoding: [0x12,0x00,0x90,0xbf] +s_sendmsg sendmsg(2, GS_OP_CUT) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0) ; encoding: [0x12,0x00,0x90,0xbf] + +s_sendmsg sendmsg(MSG_GS, GS_OP_CUT) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0) ; encoding: [0x12,0x00,0x90,0xbf] + s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0) // GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0) ; encoding: [0x12,0x00,0x90,0xbf] +s_sendmsg sendmsg(MSG_GS, 1) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0) ; encoding: [0x12,0x00,0x90,0xbf] + +s_sendmsg sendmsg(MSG_GS, 1, 1) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 1) ; encoding: [0x12,0x01,0x90,0xbf] + s_sendmsg 0x122 // GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT, 1) ; encoding: [0x22,0x01,0x90,0xbf] @@ -215,15 +228,6 @@ s_sendmsg sendmsg(MSG_GS_DONE, GS_OP_NOP) // GCN: s_sendmsg sendmsg(MSG_GS_DONE, GS_OP_NOP) ; encoding: [0x03,0x00,0x90,0xbf] -s_sendmsg 0x4 -// GCN: s_sendmsg 4 ; encoding: [0x04,0x00,0x90,0xbf] - -s_sendmsg 9 -// GCN: s_sendmsg 9 ; encoding: [0x09,0x00,0x90,0xbf] - -s_sendmsg 11 -// GCN: s_sendmsg 11 ; encoding: [0x0b,0x00,0x90,0xbf] - s_sendmsg 0x1f // GCN: s_sendmsg sendmsg(MSG_SYSMSG, SYSMSG_OP_ECC_ERR_INTERRUPT) ; encoding: [0x1f,0x00,0x90,0xbf] @@ -233,15 +237,109 @@ s_sendmsg sendmsg(MSG_SYSMSG, SYSMSG_OP_ECC_ERR_INTERRUPT) // GCN: s_sendmsg sendmsg(MSG_SYSMSG, SYSMSG_OP_ECC_ERR_INTERRUPT) ; encoding: [0x1f,0x00,0x90,0xbf] -s_sendmsg 0x6f -// GCN: s_sendmsg 111 ; encoding: [0x6f,0x00,0x90,0xbf] - s_sendmsghalt 3 // GCN: s_sendmsghalt sendmsg(MSG_GS_DONE, GS_OP_NOP) ; encoding: [0x03,0x00,0x91,0xbf] s_sendmsghalt sendmsg(MSG_GS, GS_OP_EMIT, 1) // GCN: s_sendmsghalt sendmsg(MSG_GS, GS_OP_EMIT, 1) ; encoding: [0x22,0x01,0x91,0xbf] +//===----------------------------------------------------------------------===// +// s_sendmsg with a numeric message id (no validation) +//===----------------------------------------------------------------------===// + +s_sendmsg 2 +// GCN: s_sendmsg sendmsg(2, 0, 0) ; encoding: [0x02,0x00,0x90,0xbf] + +s_sendmsg 0x4 +// GCN: s_sendmsg sendmsg(4, 0, 0) ; encoding: [0x04,0x00,0x90,0xbf] + +s_sendmsg 9 +// GCN: s_sendmsg sendmsg(9, 0, 0) ; encoding: [0x09,0x00,0x90,0xbf] + +s_sendmsg 11 +// GCN: s_sendmsg sendmsg(11, 0, 0) ; encoding: [0x0b,0x00,0x90,0xbf] + +s_sendmsg 0x6f +// GCN: s_sendmsg sendmsg(15, 6, 0) ; encoding: [0x6f,0x00,0x90,0xbf] + +s_sendmsg sendmsg(1, 3) +// GCN: s_sendmsg sendmsg(1, 3, 0) ; encoding: [0x31,0x00,0x90,0xbf] + +s_sendmsg sendmsg(1, 3, 2) +// GCN: s_sendmsg sendmsg(1, 3, 2) ; encoding: [0x31,0x02,0x90,0xbf] + +s_sendmsg sendmsg(2, 0, 1) +// GCN: s_sendmsg sendmsg(2, 0, 1) ; encoding: [0x02,0x01,0x90,0xbf] + +s_sendmsg sendmsg(15, 7, 3) +// GCN: s_sendmsg sendmsg(15, 7, 3) ; encoding: [0x7f,0x03,0x90,0xbf] + +s_sendmsg 4567 +// GCN: s_sendmsg 4567 ; encoding: [0xd7,0x11,0x90,0xbf] + +//===----------------------------------------------------------------------===// +// s_sendmsg with expressions +//===----------------------------------------------------------------------===// + +sendmsg=2 +s_sendmsg sendmsg +// GCN: s_sendmsg sendmsg(2, 0, 0) ; encoding: [0x02,0x00,0x90,0xbf] + +sendmsg=1 +s_sendmsg sendmsg+1 +// GCN: s_sendmsg sendmsg(2, 0, 0) ; encoding: [0x02,0x00,0x90,0xbf] + +s_sendmsg 1+sendmsg +// GCN: s_sendmsg sendmsg(2, 0, 0) ; encoding: [0x02,0x00,0x90,0xbf] + +msg=1 +s_sendmsg sendmsg(msg) +// GCN: s_sendmsg sendmsg(MSG_INTERRUPT) ; encoding: [0x01,0x00,0x90,0xbf] + +msg=0 +s_sendmsg sendmsg(msg+1) +// GCN: s_sendmsg sendmsg(MSG_INTERRUPT) ; encoding: [0x01,0x00,0x90,0xbf] + +msg=0 +s_sendmsg sendmsg(1+msg) +// GCN: s_sendmsg sendmsg(MSG_INTERRUPT) ; encoding: [0x01,0x00,0x90,0xbf] + +msg=2 +op=1 +s_sendmsg sendmsg(msg, op) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0) ; encoding: [0x12,0x00,0x90,0xbf] + +msg=1 +op=0 +s_sendmsg sendmsg(msg+1, op+1) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0) ; encoding: [0x12,0x00,0x90,0xbf] + +msg=1 +op=0 +s_sendmsg sendmsg(1+msg, 1+op) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0) ; encoding: [0x12,0x00,0x90,0xbf] + +msg=1 +op=2 +stream=1 +s_sendmsg sendmsg(msg+1, op+1, stream+1) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT_CUT, 2) ; encoding: [0x32,0x02,0x90,0xbf] + +msg=1 +op=2 +stream=1 +s_sendmsg sendmsg(1+msg, 1+op, 1+stream) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT_CUT, 2) ; encoding: [0x32,0x02,0x90,0xbf] + +MSG_GS=-1 +GS_OP_EMIT=-1 +s_sendmsghalt sendmsg(MSG_GS, GS_OP_EMIT, 1) +// GCN: s_sendmsghalt sendmsg(MSG_GS, GS_OP_EMIT, 1) ; encoding: [0x22,0x01,0x91,0xbf] + +//===----------------------------------------------------------------------===// +// misc sopp instructions +//===----------------------------------------------------------------------===// + s_trap 4 // GCN: s_trap 4 ; encoding: [0x04,0x00,0x92,0xbf] Index: test/MC/Disassembler/AMDGPU/sopp_vi.txt =================================================================== --- test/MC/Disassembler/AMDGPU/sopp_vi.txt +++ test/MC/Disassembler/AMDGPU/sopp_vi.txt @@ -75,7 +75,7 @@ # GCN: s_setprio 1 ; encoding: [0x01,0x00,0x8f,0xbf] 0x01 0x00 0x8f 0xbf -# GCN: s_sendmsg 2 ; encoding: [0x02,0x00,0x90,0xbf] +# GCN: s_sendmsg sendmsg(2, 0, 0) ; encoding: [0x02,0x00,0x90,0xbf] 0x02 0x00 0x90 0xbf # GCN: s_sendmsg sendmsg(MSG_INTERRUPT) ; encoding: [0x01,0x00,0x90,0xbf] @@ -93,13 +93,13 @@ # GCN: s_sendmsg sendmsg(MSG_GS_DONE, GS_OP_NOP) ; encoding: [0x03,0x00,0x90,0xbf] 0x03 0x00 0x90 0xbf -# GCN: s_sendmsg 11 ; encoding: [0x0b,0x00,0x90,0xbf] +# GCN: s_sendmsg sendmsg(11, 0, 0) ; encoding: [0x0b,0x00,0x90,0xbf] 0x0b 0x00 0x90 0xbf # GCN: s_sendmsg sendmsg(MSG_SYSMSG, SYSMSG_OP_ECC_ERR_INTERRUPT) ; encoding: [0x1f,0x00,0x90,0xbf] 0x1f 0x00 0x90 0xbf -# GCN: s_sendmsg 111 ; encoding: [0x6f,0x00,0x90,0xbf] +# GCN: s_sendmsg sendmsg(15, 6, 0) ; encoding: [0x6f,0x00,0x90,0xbf] 0x6f 0x00 0x90 0xbf # GCN: s_sendmsghalt sendmsg(MSG_GS_DONE, GS_OP_NOP) ; encoding: [0x03,0x00,0x91,0xbf] @@ -108,9 +108,24 @@ # GCN: s_sendmsghalt sendmsg(MSG_GS, GS_OP_EMIT, 1) ; encoding: [0x22,0x01,0x91,0xbf] 0x22 0x01 0x91 0xbf -# GCN: s_sendmsghalt 111 ; encoding: [0x6f,0x00,0x91,0xbf] +# GCN: s_sendmsghalt sendmsg(15, 6, 0) ; encoding: [0x6f,0x00,0x91,0xbf] 0x6f 0x00 0x91 0xbf +# GCN: s_sendmsg sendmsg(1, 3, 0) ; encoding: [0x31,0x00,0x90,0xbf] +0x31 0x00 0x90 0xbf + +# GCN: s_sendmsg sendmsg(1, 3, 2) ; encoding: [0x31,0x02,0x90,0xbf] +0x31 0x02 0x90 0xbf + +# GCN: s_sendmsg sendmsg(2, 0, 1) ; encoding: [0x02,0x01,0x90,0xbf] +0x02 0x01 0x90 0xbf + +# GCN: s_sendmsg sendmsg(15, 7, 3) ; encoding: [0x7f,0x03,0x90,0xbf] +0x7f 0x03 0x90 0xbf + +# GCN: s_sendmsg 4567 ; encoding: [0xd7,0x11,0x90,0xbf] +0xd7 0x11 0x90 0xbf + # GCN: s_trap 4 ; encoding: [0x04,0x00,0x92,0xbf] 0x04 0x00 0x92 0xbf