Index: lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -36,6 +36,54 @@ #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" +// FIXME ODR: Move this to some common place for AsmParser and InstPrinter +namespace llvm { +namespace AMDGPU { +namespace SendMsg { + +// This must be in sync with llvm::AMDGPU::SendMsg::Id enum members. +static +const char* const IdSymbolic[] = { + nullptr, + "MSG_INTERRUPT", + "MSG_GS", + "MSG_GS_DONE", + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + "MSG_SYSMSG" +}; + +// These two must be in sync with llvm::AMDGPU::SendMsg::Op enum members. +static +const char* const OpSysSymbolic[] = { + nullptr, + "SYSMSG_OP_ECC_ERR_INTERRUPT", + "SYSMSG_OP_REG_RD", + "SYSMSG_OP_HOST_TRAP_ACK", + "SYSMSG_OP_TTRACE_PC" +}; + +static +const char* const OpGsSymbolic[] = { + "GS_OP_NOP", + "GS_OP_CUT", + "GS_OP_EMIT", + "GS_OP_EMIT_CUT" +}; + +} // namespace SendMsg +} // namespace AMDGPU +} // namespace llvm + using namespace llvm; namespace { @@ -82,6 +130,7 @@ ImmTyR128, ImmTyLWE, ImmTyHwreg, + ImmTySendMsg, }; struct TokOp { @@ -418,6 +467,7 @@ bool isDSOffset01() const; bool isSWaitCnt() const; bool isHwreg() const; + bool isSendMsg() const; bool isMubufOffset() const; bool isSMRDOffset() const; bool isSMRDLiteralOffset() const; @@ -545,6 +595,15 @@ OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands); bool parseHwreg(int64_t &HwRegCode, int64_t &Offset, int64_t &Width, bool &IsIdentifier); OperandMatchResultTy parseHwregOp(OperandVector &Operands); +private: + struct OperandInfoTy { + int64_t Id; + bool IsSymbolic; + OperandInfoTy(int64_t Id_) : Id(Id_), IsSymbolic(false) { } + }; + bool parseSendMsg(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId); +public: + OperandMatchResultTy parseSendMsgOp(OperandVector &Operands); OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands); OperandMatchResultTy parseFlatOptionalOps(OperandVector &Operands); @@ -1726,6 +1785,185 @@ return isImmTy(ImmTyHwreg); } +bool AMDGPUAsmParser::parseSendMsg(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) { + using namespace llvm::AMDGPU::SendMsg; + + if (Parser.getTok().getString() != "sendmsg") + return true; + Parser.Lex(); + + if (getLexer().isNot(AsmToken::LParen)) + return true; + Parser.Lex(); + + 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_INTERRUPT: case ID_GS: case ID_GS_DONE: case ID_SYSMSG: break; + } + if (tok == IdSymbolic[i]) { + Msg.Id = i; + break; + } + } + 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; + } + + if (getLexer().isNot(AsmToken::Comma)) + return true; + Parser.Lex(); + + 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 std::string 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; + } + + 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; + } + + if (getLexer().isNot(AsmToken::Comma)) + return true; + Parser.Lex(); + + if (getLexer().isNot(AsmToken::Integer)) + return true; + if (getParser().parseAbsoluteExpression(StreamId)) + return true; + } + + if (getLexer().isNot(AsmToken::RParen)) + return true; + Parser.Lex(); + return false; +} + +AMDGPUAsmParser::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_ParseFail; + case AsmToken::Integer: + // The operand can be an integer value. + if (getParser().parseAbsoluteExpression(Imm16Val)) + return MatchOperand_ParseFail; + if (!isInt<16>(Imm16Val) && !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 (parseSendMsg(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_SYSMSG)) { + if (Msg.IsSymbolic) + Error(S, "invalid/unsupported symbolic name of message"); + else + Error(S, "invalid/unsupported code of message"); + break; + } + Imm16Val = Msg.Id; + // 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 (0); + } + break; + } + Operands.push_back(AMDGPUOperand::CreateImm(Imm16Val, S, AMDGPUOperand::ImmTySendMsg)); + return MatchOperand_Success; +} + +bool AMDGPUOperand::isSendMsg() const { + return isImmTy(ImmTySendMsg); +} + //===----------------------------------------------------------------------===// // sopp branch targets //===----------------------------------------------------------------------===// Index: lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp =================================================================== --- lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp +++ lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp @@ -20,6 +20,54 @@ #include +// FIXME ODR: Move this to some common place for AsmParser and InstPrinter +namespace llvm { +namespace AMDGPU { +namespace SendMsg { + +// This must be in sync with llvm::AMDGPU::SendMsg::Id enum members. +static +const char* const IdSymbolic[] = { + nullptr, + "MSG_INTERRUPT", + "MSG_GS", + "MSG_GS_DONE", + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + "MSG_SYSMSG" +}; + +// These two must be in sync with llvm::AMDGPU::SendMsg::Op enum members. +static +const char* const OpSysSymbolic[] = { + nullptr, + "SYSMSG_OP_ECC_ERR_INTERRUPT", + "SYSMSG_OP_REG_RD", + "SYSMSG_OP_HOST_TRAP_ACK", + "SYSMSG_OP_TTRACE_PC" +}; + +static +const char* const OpGsSymbolic[] = { + "GS_OP_NOP", + "GS_OP_CUT", + "GS_OP_EMIT", + "GS_OP_EMIT_CUT" +}; + +} // namespace SendMsg +} // namespace AMDGPU +} // namespace llvm + using namespace llvm; void AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, @@ -750,33 +798,42 @@ void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo, raw_ostream &O) { - unsigned SImm16 = MI->getOperand(OpNo).getImm(); - unsigned Msg = SImm16 & 0xF; - if (Msg == 2 || Msg == 3) { - unsigned Op = (SImm16 >> 4) & 0xF; - if (Msg == 3) - O << "Gs_done("; - else - O << "Gs("; - if (Op == 0) { - O << "nop"; - } else { - unsigned Stream = (SImm16 >> 8) & 0x3; - if (Op == 1) - O << "cut"; - else if (Op == 2) - O << "emit"; - else if (Op == 3) - O << "emit-cut"; - O << " stream " << Stream; + using namespace llvm::AMDGPU::SendMsg; + + const unsigned SImm16 = MI->getOperand(OpNo).getImm(); + const unsigned Id = SImm16 & ID_MASK_; + do { + if (Id == ID_INTERRUPT) { + if ((SImm16 & ~ID_MASK_) != 0) // Unused/unknown bits must be 0. + break; + O << "sendmsg(" << IdSymbolic[Id] << ')'; + return; } - O << "), [m0] "; - } else if (Msg == 1) - O << "interrupt "; - else if (Msg == 15) - O << "system "; - else - O << "unknown(" << Msg << ") "; + 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; + } + } while (0); + O << SImm16; // Unknown simm16 code. } void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo, Index: lib/Target/AMDGPU/SIDefines.h =================================================================== --- lib/Target/AMDGPU/SIDefines.h +++ lib/Target/AMDGPU/SIDefines.h @@ -95,6 +95,54 @@ }; } +namespace llvm { +namespace AMDGPU { +namespace SendMsg { // Encoding of SIMM16 used in s_sendmsg* insns. + +enum Id { // Message ID, width(3) [3:0]. + ID_UNKNOWN_ = -1, + ID_INTERRUPT = 1, + ID_GS, + ID_GS_DONE, + ID_SYSMSG = 15, + ID_GAPS_LAST_, // Indicate that sequence has gaps. + ID_GAPS_FIRST_ = ID_INTERRUPT, + ID_MASK_ = 0xf +}; + +enum Op { // Both GS and SYS operation IDs. + OP_UNKNOWN_ = -1, + // width(2) [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_MASK_ = (0x3 << 4), + // width(3) [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_MASK_ = (0x7 << 4), + OP_SHIFT_ = 4 +}; + +enum StreamId { // Stream ID, (2) [9:8]. + STREAM_ID_DEFAULT = 0, + STREAM_ID_LAST_ = 4, + STREAM_ID_FIRST_ = STREAM_ID_DEFAULT, + STREAM_ID_MASK_ = (0x3 << 8), + STREAM_ID_SHIFT_ = 8 +}; + +} // namespace SendMsg +} // namespace AMDGPU +} // namespace llvm + #define R_00B028_SPI_SHADER_PGM_RSRC1_PS 0x00B028 #define R_00B02C_SPI_SHADER_PGM_RSRC2_PS 0x00B02C #define S_00B02C_EXTRA_LDS_SIZE(x) (((x) & 0xFF) << 8) Index: lib/Target/AMDGPU/SIInstrInfo.td =================================================================== --- lib/Target/AMDGPU/SIInstrInfo.td +++ lib/Target/AMDGPU/SIInstrInfo.td @@ -626,6 +626,13 @@ let RenderMethod = "addImmOperands"; } +def SendMsgMatchClass : AsmOperandClass { + let Name = "SendMsg"; + let PredicateMethod = "isSendMsg"; + let ParserMethod = "parseSendMsgOp"; + let RenderMethod = "addImmOperands"; +} + let OperandType = "OPERAND_IMMEDIATE" in { def offen : Operand { Index: lib/Target/AMDGPU/SIInstructions.td =================================================================== --- lib/Target/AMDGPU/SIInstructions.td +++ lib/Target/AMDGPU/SIInstructions.td @@ -24,6 +24,7 @@ def SendMsgImm : Operand { let PrintMethod = "printSendMsg"; + let ParserMatchClass = SendMsgMatchClass; } def isGCN : Predicate<"Subtarget->getGeneration() " @@ -531,7 +532,7 @@ >; } // End Uses = [EXEC, M0] -def S_SENDMSGHALT : SOPP <0x00000011, (ins i16imm:$simm16), "s_sendmsghalt $simm16">; +def S_SENDMSGHALT : SOPP <0x00000011, (ins SendMsgImm:$simm16), "s_sendmsghalt $simm16">; def S_TRAP : SOPP <0x00000012, (ins i16imm:$simm16), "s_trap $simm16">; def S_ICACHE_INV : SOPP <0x00000013, (ins), "s_icache_inv"> { let simm16 = 0; Index: test/CodeGen/AMDGPU/llvm.SI.sendmsg-m0.ll =================================================================== --- test/CodeGen/AMDGPU/llvm.SI.sendmsg-m0.ll +++ test/CodeGen/AMDGPU/llvm.SI.sendmsg-m0.ll @@ -4,7 +4,7 @@ ; BOTH-LABEL: {{^}}main: ; BOTH: s_mov_b32 m0, s0 ; VI-NEXT: s_nop 0 -; BOTH-NEXT: s_sendmsg Gs_done(nop) +; BOTH-NEXT: sendmsg(MSG_GS_DONE, GS_OP_NOP) ; BOTH-NEXT: s_endpgm define amdgpu_gs void @main(i32 inreg %a) #0 { Index: test/CodeGen/AMDGPU/llvm.SI.sendmsg.ll =================================================================== --- test/CodeGen/AMDGPU/llvm.SI.sendmsg.ll +++ test/CodeGen/AMDGPU/llvm.SI.sendmsg.ll @@ -4,10 +4,10 @@ ; CHECK-LABEL: {{^}}main: ; CHECK: s_mov_b32 m0, 0 ; CHECK-NOT: s_mov_b32 m0 -; CHECK: s_sendmsg Gs(emit stream 0) -; CHECK: s_sendmsg Gs(cut stream 1) -; CHECK: s_sendmsg Gs(emit-cut stream 2) -; CHECK: s_sendmsg Gs_done(nop) +; CHECK: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT, 0) +; CHECK: s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 1) +; CHECK: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT_CUT, 2) +; CHECK: s_sendmsg sendmsg(MSG_GS_DONE, GS_OP_NOP) define void @main() { main_body: Index: test/MC/AMDGPU/sopp-err.s =================================================================== --- /dev/null +++ test/MC/AMDGPU/sopp-err.s @@ -0,0 +1,75 @@ +// RUN: not llvm-mc -arch=amdgcn -show-encoding %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=SICI %s +// RUN: not llvm-mc -arch=amdgcn -mcpu=SI -show-encoding %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=SICI %s +// RUN: not llvm-mc -arch=amdgcn -mcpu=fiji -show-encoding %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=VI %s + +s_sendmsg sendmsg(11) +// GCN: error: invalid/unsupported code of message + +s_sendmsg sendmsg(MSG_INTERRUPTX) +// GCN: error: invalid/unsupported symbolic name of message + +s_sendmsg sendmsg(MSG_INTERRUPT, 0) +// GCN: error: failed parsing operand + +s_sendmsg sendmsg(MSG_GS) +// GCN: error: failed parsing operand + +s_sendmsg sendmsg(MSG_GS, GS_OP_NOP) +// GCN: error: invalid GS_OP: NOP is for GS_DONE only + +s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0, 0) +// GCN: error: failed parsing operand + +s_sendmsg sendmsg(MSG_GSX, GS_OP_CUT, 0) +// GCN: error: invalid/unsupported symbolic name of message + +s_sendmsg sendmsg(MSG_GS, GS_OP_CUTX, 0) +// GCN: error: invalid symbolic name of GS_OP + +s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 4) +// GCN: error: invalid stream id: only 2-bit values are legal + +s_sendmsg sendmsg(2) +// GCN: error: failed parsing operand + +s_sendmsg sendmsg(2, 0) +// GCN: error: invalid GS_OP: NOP is for GS_DONE only + +s_sendmsg sendmsg(2, 3, 0, 0) +// GCN: error: failed parsing operand + +s_sendmsg sendmsg(2, 4, 1) +// GCN: error: invalid code of GS_OP: only 2-bit values are legal + +s_sendmsg sendmsg(2, 2, 4) +// GCN: error: invalid stream id: only 2-bit values are legal + +s_sendmsg sendmsg(2, 2, 0, 0) +// GCN: error: failed parsing operand + +s_sendmsg sendmsg(MSG_GS_DONE, GS_OP_NOP, 0) +// GCN: error: failed parsing operand + +s_sendmsg sendmsg(15) +// GCN: error: failed parsing operand + +s_sendmsg sendmsg(15, 1, 0) +// GCN: error: failed parsing operand + +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(MSG_SYSMSG) +// GCN: error: failed parsing operand + +s_sendmsg sendmsg(MSG_SYSMSG, SYSMSG_OP_ECC_ERR_INTERRUPT, 0) +// GCN: error: failed parsing operand + +s_sendmsg sendmsg(MSG_SYSMSG, 0) +// GCN: error: invalid/unsupported code of SYSMSG_OP + +s_sendmsg sendmsg(MSG_SYSMSG, 5) +// GCN: error: invalid/unsupported code of SYSMSG_OP Index: test/MC/AMDGPU/sopp.s =================================================================== --- test/MC/AMDGPU/sopp.s +++ test/MC/AMDGPU/sopp.s @@ -91,10 +91,76 @@ // GCN: s_setprio 1 ; encoding: [0x01,0x00,0x8f,0xbf] s_sendmsg 2 -// GCN: s_sendmsg Gs(nop), [m0] ; encoding: [0x02,0x00,0x90,0xbf] +// GCN: s_sendmsg 2 ; encoding: [0x02,0x00,0x90,0xbf] + +s_sendmsg 0x1 +// GCN: s_sendmsg sendmsg(MSG_INTERRUPT) ; encoding: [0x01,0x00,0x90,0xbf] + +s_sendmsg sendmsg(1) +// GCN: s_sendmsg sendmsg(MSG_INTERRUPT) ; encoding: [0x01,0x00,0x90,0xbf] + +s_sendmsg sendmsg(MSG_INTERRUPT) +// GCN: s_sendmsg sendmsg(MSG_INTERRUPT) ; encoding: [0x01,0x00,0x90,0xbf] + +s_sendmsg 0x12 +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0) ; encoding: [0x12,0x00,0x90,0xbf] + +s_sendmsg sendmsg(2, 1) +// 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 0x122 +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT, 1) ; encoding: [0x22,0x01,0x90,0xbf] + +s_sendmsg sendmsg(2, 2, 1) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT, 1) ; encoding: [0x22,0x01,0x90,0xbf] + +s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT, 1) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT, 1) ; encoding: [0x22,0x01,0x90,0xbf] + +s_sendmsg 0x232 +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT_CUT, 2) ; encoding: [0x32,0x02,0x90,0xbf] + +s_sendmsg sendmsg(2, 3, 2) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT_CUT, 2) ; encoding: [0x32,0x02,0x90,0xbf] + +s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT_CUT, 2) +// GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT_CUT, 2) ; encoding: [0x32,0x02,0x90,0xbf] + +s_sendmsg 0x3 +// GCN: s_sendmsg sendmsg(MSG_GS_DONE, GS_OP_NOP) ; encoding: [0x03,0x00,0x90,0xbf] + +s_sendmsg sendmsg(3, 0) +// GCN: s_sendmsg sendmsg(MSG_GS_DONE, GS_OP_NOP) ; encoding: [0x03,0x00,0x90,0xbf] + +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 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] + +s_sendmsg sendmsg(15, 1) +// GCN: s_sendmsg sendmsg(MSG_SYSMSG, SYSMSG_OP_ECC_ERR_INTERRUPT) ; encoding: [0x1f,0x00,0x90,0xbf] + +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 3 ; encoding: [0x03,0x00,0x91,0xbf] +// 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_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,12 +75,42 @@ # GCN: s_setprio 1 ; encoding: [0x01,0x00,0x8f,0xbf] 0x01 0x00 0x8f 0xbf -# GCN: s_sendmsg Gs(nop), [m0] ; encoding: [0x02,0x00,0x90,0xbf] +# GCN: s_sendmsg 2 ; encoding: [0x02,0x00,0x90,0xbf] 0x02 0x00 0x90 0xbf -# GCN: s_sendmsghalt 3 ; encoding: [0x03,0x00,0x91,0xbf] +# GCN: s_sendmsg sendmsg(MSG_INTERRUPT) ; encoding: [0x01,0x00,0x90,0xbf] +0x01 0x00 0x90 0xbf + +# GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0) ; encoding: [0x12,0x00,0x90,0xbf] +0x12 0x00 0x90 0xbf + +# GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT, 1) ; encoding: [0x22,0x01,0x90,0xbf] +0x22 0x01 0x90 0xbf + +# GCN: s_sendmsg sendmsg(MSG_GS, GS_OP_EMIT_CUT, 2) ; encoding: [0x32,0x02,0x90,0xbf] +0x32 0x02 0x90 0xbf + +# 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] +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] +0x6f 0x00 0x90 0xbf + +# GCN: s_sendmsghalt sendmsg(MSG_GS_DONE, GS_OP_NOP) ; encoding: [0x03,0x00,0x91,0xbf] 0x03 0x00 0x91 0xbf +# 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] +0x6f 0x00 0x91 0xbf + # GCN: s_trap 4 ; encoding: [0x04,0x00,0x92,0xbf] 0x04 0x00 0x92 0xbf