Index: lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -82,6 +82,7 @@ ImmTyR128, ImmTyLWE, ImmTyHwreg, + ImmTySendMsg, }; struct TokOp { @@ -418,6 +419,7 @@ bool isDSOffset01() const; bool isSWaitCnt() const; bool isHwreg() const; + bool isSendMsg() const; bool isMubufOffset() const; bool isSMRDOffset() const; bool isSMRDLiteralOffset() const; @@ -545,6 +547,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 +1737,179 @@ return isImmTy(ImmTyHwreg); } +bool AMDGPUAsmParser::parseSendMsg(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) { + 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 = StringSwitch(Parser.getTok().getString()) + .Case("MSG_INTERRUPT" , 1) + .Case("MSG_GS" , 2) + .Case("MSG_GS_DONE" , 3) + .Case("MSG_SYSMSG" , 15) + .Default(-1); + 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 = -1; + } + if (Msg.Id < 0) // Don't know how to parse the rest. + return false; + + if (!(Msg.Id == 2 || Msg.Id == 3 || Msg.Id == 15)) { + if (getLexer().isNot(AsmToken::RParen)) + return true; + Parser.Lex(); + return false; + } + + if (getLexer().isNot(AsmToken::Comma)) + return true; + Parser.Lex(); + + if (getLexer().is(AsmToken::Identifier)) { + Operation.IsSymbolic = true; + if (Msg.Id == 15) { + Operation.Id = StringSwitch(Parser.getTok().getString()) + .Case("SYSMSG_OP_ECC_ERR_INTERRUPT" , 1) + .Case("SYSMSG_OP_REG_RD" , 2) + .Case("SYSMSG_OP_HOST_TRAP_ACK" , 3) + .Case("SYSMSG_OP_TTRACE_PC" , 4) + .Default(-1); + } else { + Operation.Id = StringSwitch(Parser.getTok().getString()) + .Case("GS_OP_NOP" , 0) + .Case("GS_OP_CUT" , 1) + .Case("GS_OP_EMIT" , 2) + .Case("GS_OP_EMIT_CUT", 3) + .Default(-1); + } + Parser.Lex(); + } else { + Operation.IsSymbolic = false; + if (getLexer().isNot(AsmToken::Integer)) + return true; + if (getParser().parseAbsoluteExpression(Operation.Id)) + return true; + } + + // stream id + if ((Msg.Id == 2 || Msg.Id == 3) && Operation.Id != 0) { + // 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) { + 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(-1); + OperandInfoTy Operation(-1); + int64_t StreamId = 0; // default + if (parseSendMsg(Msg, Operation, StreamId)) + return MatchOperand_ParseFail; + // validate and encode + do { + // validate and encode message ID + if (! ((1 <= Msg.Id && Msg.Id <= 3) + || (Msg.Id == 15))) { + if (Msg.IsSymbolic) + Error(S, "invalid/unsupported symbolic name of message"); + else + Error(S, "invalid/unsupported code of message"); + break; + } + Imm16Val = Msg.Id; // Msg (3) [3:0] + // validate and encode operation ID + if (Msg.Id == 2 || Msg.Id == 3) { + if (Operation.Id < 0 || Operation.Id > 3) { + 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 == 0 && Msg.Id != 3) { + Error(S, "invalid GS_OP: NOP is for GS_DONE only"); + break; + } + Imm16Val |= (Operation.Id << 4); // GsOp (2) [5:4] + } + if (Msg.Id == 15) { + if (! (1 <= Operation.Id && Operation.Id <= 4)) { + 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 << 4); // SysOp (3) [6:4] + } + // validate and encode stream ID + if ((Msg.Id == 2 || Msg.Id == 3) && Operation.Id != 0) { + if (StreamId < 0 || StreamId > 3) { + Error(S, "invalid stream id: only 2-bit values are legal"); + break; + } + Imm16Val |= (StreamId << 8); // StreamId (2) [9:8] + } + } 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 @@ -753,33 +753,62 @@ 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; + const unsigned SImm16 = MI->getOperand(OpNo).getImm(); + const unsigned MsgId = SImm16 & 0xF; // [3:0] = message + do { + if (MsgId == 1) { + if ((SImm16 & 0xfff0) != 0) // [15:4] are unused/unknown and must be 0 + break; + O << "sendmsg(MSG_INTERRUPT)"; + return; } - O << "), [m0] "; - } else if (Msg == 1) - O << "interrupt "; - else if (Msg == 15) - O << "system "; - else - O << "unknown(" << Msg << ") "; + if (MsgId == 2 || MsgId == 3) { + if ((SImm16 & 0xfcc0) != 0) // [15:10], [7:6] are unused/unknown and must be 0 + break; + const unsigned GsOpId = (SImm16 >> 4) & 0x3; // [5:4] = gs operation + const unsigned StreamId = (SImm16 >> 8) & 0x3; // [9:8] = stream id + if (GsOpId == 0 && MsgId != 3) // NOP to be used for GS_DONE only + break; + if (GsOpId == 0 && StreamId != 0) // NOP does not use/define stream id bits + break; + O << "sendmsg("; + switch(MsgId) { + case 2: O << "MSG_GS"; break; + case 3: O << "MSG_GS_DONE"; break; + default: assert(0); + } + O << ", "; + switch(GsOpId) { + case 0: O << "GS_OP_NOP"; break; + case 1: O << "GS_OP_CUT"; break; + case 2: O << "GS_OP_EMIT"; break; + case 3: O << "GS_OP_EMIT_CUT"; break; + default: assert(0); + } + if (GsOpId != 0) + O << ", " << StreamId; + O << ")"; + return; + } + if (MsgId == 15) { + if ((SImm16 & 0xff80) != 0) // [15:7] are unused/unknown and must be 0 + break; + const unsigned SysOpId = (SImm16 >> 4) & 0x7; // [6:4] = sys operation + if (! (1 <= SysOpId && SysOpId <= 4)) // unused/unknown + break; + O << "sendmsg(MSG_SYSMSG, "; + switch(SysOpId) { + case 1: O << "SYSMSG_OP_ECC_ERR_INTERRUPT"; break; + case 2: O << "SYSMSG_OP_REG_RD"; break; + case 3: O << "SYSMSG_OP_HOST_TRAP_ACK"; break; + case 4: O << "SYSMSG_OP_TTRACE_PC"; break; + default: assert(0); + } + O << ")"; + return; + } + } while (0); + O << SImm16; // unknown simm16 code } void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo, 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