summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/shader_bytecode.h8
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp24
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp65
-rw-r--r--src/video_core/shader/decode/memory.cpp100
-rw-r--r--src/video_core/shader/node.h14
5 files changed, 141 insertions, 70 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 430ee86ba..5e9cfba22 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -1006,6 +1006,12 @@ union Instruction {
1006 } stg; 1006 } stg;
1007 1007
1008 union { 1008 union {
1009 BitField<23, 3, AtomicOp> operation;
1010 BitField<48, 1, u64> extended;
1011 BitField<20, 3, GlobalAtomicType> type;
1012 } red;
1013
1014 union {
1009 BitField<52, 4, AtomicOp> operation; 1015 BitField<52, 4, AtomicOp> operation;
1010 BitField<49, 3, GlobalAtomicType> type; 1016 BitField<49, 3, GlobalAtomicType> type;
1011 BitField<28, 20, s64> offset; 1017 BitField<28, 20, s64> offset;
@@ -1787,6 +1793,7 @@ public:
1787 ST_S, 1793 ST_S,
1788 ST, // Store in generic memory 1794 ST, // Store in generic memory
1789 STG, // Store in global memory 1795 STG, // Store in global memory
1796 RED, // Reduction operation
1790 ATOM, // Atomic operation on global memory 1797 ATOM, // Atomic operation on global memory
1791 ATOMS, // Atomic operation on shared memory 1798 ATOMS, // Atomic operation on shared memory
1792 AL2P, // Transforms attribute memory into physical memory 1799 AL2P, // Transforms attribute memory into physical memory
@@ -2097,6 +2104,7 @@ private:
2097 INST("1110111101010---", Id::ST_L, Type::Memory, "ST_L"), 2104 INST("1110111101010---", Id::ST_L, Type::Memory, "ST_L"),
2098 INST("101-------------", Id::ST, Type::Memory, "ST"), 2105 INST("101-------------", Id::ST, Type::Memory, "ST"),
2099 INST("1110111011011---", Id::STG, Type::Memory, "STG"), 2106 INST("1110111011011---", Id::STG, Type::Memory, "STG"),
2107 INST("1110101111111---", Id::RED, Type::Memory, "RED"),
2100 INST("11101101--------", Id::ATOM, Type::Memory, "ATOM"), 2108 INST("11101101--------", Id::ATOM, Type::Memory, "ATOM"),
2101 INST("11101100--------", Id::ATOMS, Type::Memory, "ATOMS"), 2109 INST("11101100--------", Id::ATOMS, Type::Memory, "ATOMS"),
2102 INST("1110111110100---", Id::AL2P, Type::Memory, "AL2P"), 2110 INST("1110111110100---", Id::AL2P, Type::Memory, "AL2P"),
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 59bbd1211..b1804e9ea 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -2119,8 +2119,14 @@ private:
2119 return {}; 2119 return {};
2120 } 2120 }
2121 return {fmt::format("atomic{}({}, {})", opname, Visit(operation[0]).GetCode(), 2121 return {fmt::format("atomic{}({}, {})", opname, Visit(operation[0]).GetCode(),
2122 Visit(operation[1]).As(type)), 2122 Visit(operation[1]).AsUint()),
2123 type}; 2123 Type::Uint};
2124 }
2125
2126 template <const std::string_view& opname, Type type>
2127 Expression Reduce(Operation operation) {
2128 code.AddLine("{};", Atomic<opname, type>(operation).GetCode());
2129 return {};
2124 } 2130 }
2125 2131
2126 Expression Branch(Operation operation) { 2132 Expression Branch(Operation operation) {
@@ -2479,6 +2485,20 @@ private:
2479 &GLSLDecompiler::Atomic<Func::Or, Type::Int>, 2485 &GLSLDecompiler::Atomic<Func::Or, Type::Int>,
2480 &GLSLDecompiler::Atomic<Func::Xor, Type::Int>, 2486 &GLSLDecompiler::Atomic<Func::Xor, Type::Int>,
2481 2487
2488 &GLSLDecompiler::Reduce<Func::Add, Type::Uint>,
2489 &GLSLDecompiler::Reduce<Func::Min, Type::Uint>,
2490 &GLSLDecompiler::Reduce<Func::Max, Type::Uint>,
2491 &GLSLDecompiler::Reduce<Func::And, Type::Uint>,
2492 &GLSLDecompiler::Reduce<Func::Or, Type::Uint>,
2493 &GLSLDecompiler::Reduce<Func::Xor, Type::Uint>,
2494
2495 &GLSLDecompiler::Reduce<Func::Add, Type::Int>,
2496 &GLSLDecompiler::Reduce<Func::Min, Type::Int>,
2497 &GLSLDecompiler::Reduce<Func::Max, Type::Int>,
2498 &GLSLDecompiler::Reduce<Func::And, Type::Int>,
2499 &GLSLDecompiler::Reduce<Func::Or, Type::Int>,
2500 &GLSLDecompiler::Reduce<Func::Xor, Type::Int>,
2501
2482 &GLSLDecompiler::Branch, 2502 &GLSLDecompiler::Branch,
2483 &GLSLDecompiler::BranchIndirect, 2503 &GLSLDecompiler::BranchIndirect,
2484 &GLSLDecompiler::PushFlowStack, 2504 &GLSLDecompiler::PushFlowStack,
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 62e4ca488..aaa138f52 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -1938,11 +1938,8 @@ private:
1938 return {}; 1938 return {};
1939 } 1939 }
1940 1940
1941 template <Id (Module::*func)(Id, Id, Id, Id, Id), Type result_type, 1941 template <Id (Module::*func)(Id, Id, Id, Id, Id)>
1942 Type value_type = result_type>
1943 Expression Atomic(Operation operation) { 1942 Expression Atomic(Operation operation) {
1944 const Id type_def = GetTypeDefinition(result_type);
1945
1946 Id pointer; 1943 Id pointer;
1947 if (const auto smem = std::get_if<SmemNode>(&*operation[0])) { 1944 if (const auto smem = std::get_if<SmemNode>(&*operation[0])) {
1948 pointer = GetSharedMemoryPointer(*smem); 1945 pointer = GetSharedMemoryPointer(*smem);
@@ -1950,15 +1947,19 @@ private:
1950 pointer = GetGlobalMemoryPointer(*gmem); 1947 pointer = GetGlobalMemoryPointer(*gmem);
1951 } else { 1948 } else {
1952 UNREACHABLE(); 1949 UNREACHABLE();
1953 return {Constant(type_def, 0), result_type}; 1950 return {v_float_zero, Type::Float};
1954 } 1951 }
1955
1956 const Id value = As(Visit(operation[1]), value_type);
1957
1958 const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device)); 1952 const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device));
1959 const Id semantics = Constant(type_def, 0); 1953 const Id semantics = Constant(t_uint, 0);
1954 const Id value = AsUint(Visit(operation[1]));
1955
1956 return {(this->*func)(t_uint, pointer, scope, semantics, value), Type::Uint};
1957 }
1960 1958
1961 return {(this->*func)(type_def, pointer, scope, semantics, value), result_type}; 1959 template <Id (Module::*func)(Id, Id, Id, Id, Id)>
1960 Expression Reduce(Operation operation) {
1961 Atomic<func>(operation);
1962 return {};
1962 } 1963 }
1963 1964
1964 Expression Branch(Operation operation) { 1965 Expression Branch(Operation operation) {
@@ -2547,21 +2548,35 @@ private:
2547 &SPIRVDecompiler::AtomicImageXor, 2548 &SPIRVDecompiler::AtomicImageXor,
2548 &SPIRVDecompiler::AtomicImageExchange, 2549 &SPIRVDecompiler::AtomicImageExchange,
2549 2550
2550 &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange, Type::Uint>, 2551 &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange>,
2551 &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd, Type::Uint>, 2552 &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd>,
2552 &SPIRVDecompiler::Atomic<&Module::OpAtomicUMin, Type::Uint>, 2553 &SPIRVDecompiler::Atomic<&Module::OpAtomicUMin>,
2553 &SPIRVDecompiler::Atomic<&Module::OpAtomicUMax, Type::Uint>, 2554 &SPIRVDecompiler::Atomic<&Module::OpAtomicUMax>,
2554 &SPIRVDecompiler::Atomic<&Module::OpAtomicAnd, Type::Uint>, 2555 &SPIRVDecompiler::Atomic<&Module::OpAtomicAnd>,
2555 &SPIRVDecompiler::Atomic<&Module::OpAtomicOr, Type::Uint>, 2556 &SPIRVDecompiler::Atomic<&Module::OpAtomicOr>,
2556 &SPIRVDecompiler::Atomic<&Module::OpAtomicXor, Type::Uint>, 2557 &SPIRVDecompiler::Atomic<&Module::OpAtomicXor>,
2557 2558
2558 &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange, Type::Int>, 2559 &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange>,
2559 &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd, Type::Int>, 2560 &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd>,
2560 &SPIRVDecompiler::Atomic<&Module::OpAtomicSMin, Type::Int>, 2561 &SPIRVDecompiler::Atomic<&Module::OpAtomicSMin>,
2561 &SPIRVDecompiler::Atomic<&Module::OpAtomicSMax, Type::Int>, 2562 &SPIRVDecompiler::Atomic<&Module::OpAtomicSMax>,
2562 &SPIRVDecompiler::Atomic<&Module::OpAtomicAnd, Type::Int>, 2563 &SPIRVDecompiler::Atomic<&Module::OpAtomicAnd>,
2563 &SPIRVDecompiler::Atomic<&Module::OpAtomicOr, Type::Int>, 2564 &SPIRVDecompiler::Atomic<&Module::OpAtomicOr>,
2564 &SPIRVDecompiler::Atomic<&Module::OpAtomicXor, Type::Int>, 2565 &SPIRVDecompiler::Atomic<&Module::OpAtomicXor>,
2566
2567 &SPIRVDecompiler::Reduce<&Module::OpAtomicIAdd>,
2568 &SPIRVDecompiler::Reduce<&Module::OpAtomicUMin>,
2569 &SPIRVDecompiler::Reduce<&Module::OpAtomicUMax>,
2570 &SPIRVDecompiler::Reduce<&Module::OpAtomicAnd>,
2571 &SPIRVDecompiler::Reduce<&Module::OpAtomicOr>,
2572 &SPIRVDecompiler::Reduce<&Module::OpAtomicXor>,
2573
2574 &SPIRVDecompiler::Reduce<&Module::OpAtomicIAdd>,
2575 &SPIRVDecompiler::Reduce<&Module::OpAtomicSMin>,
2576 &SPIRVDecompiler::Reduce<&Module::OpAtomicSMax>,
2577 &SPIRVDecompiler::Reduce<&Module::OpAtomicAnd>,
2578 &SPIRVDecompiler::Reduce<&Module::OpAtomicOr>,
2579 &SPIRVDecompiler::Reduce<&Module::OpAtomicXor>,
2565 2580
2566 &SPIRVDecompiler::Branch, 2581 &SPIRVDecompiler::Branch,
2567 &SPIRVDecompiler::BranchIndirect, 2582 &SPIRVDecompiler::BranchIndirect,
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index b8f63922f..8112ead3e 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -3,7 +3,9 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include <utility>
6#include <vector> 7#include <vector>
8
7#include <fmt/format.h> 9#include <fmt/format.h>
8 10
9#include "common/alignment.h" 11#include "common/alignment.h"
@@ -16,6 +18,7 @@
16 18
17namespace VideoCommon::Shader { 19namespace VideoCommon::Shader {
18 20
21using std::move;
19using Tegra::Shader::AtomicOp; 22using Tegra::Shader::AtomicOp;
20using Tegra::Shader::AtomicType; 23using Tegra::Shader::AtomicType;
21using Tegra::Shader::Attribute; 24using Tegra::Shader::Attribute;
@@ -27,29 +30,26 @@ using Tegra::Shader::StoreType;
27 30
28namespace { 31namespace {
29 32
30Node GetAtomOperation(AtomicOp op, bool is_signed, Node memory, Node data) { 33OperationCode GetAtomOperation(AtomicOp op) {
31 const OperationCode operation_code = [op] { 34 switch (op) {
32 switch (op) { 35 case AtomicOp::Add:
33 case AtomicOp::Add: 36 return OperationCode::AtomicIAdd;
34 return OperationCode::AtomicIAdd; 37 case AtomicOp::Min:
35 case AtomicOp::Min: 38 return OperationCode::AtomicIMin;
36 return OperationCode::AtomicIMin; 39 case AtomicOp::Max:
37 case AtomicOp::Max: 40 return OperationCode::AtomicIMax;
38 return OperationCode::AtomicIMax; 41 case AtomicOp::And:
39 case AtomicOp::And: 42 return OperationCode::AtomicIAnd;
40 return OperationCode::AtomicIAnd; 43 case AtomicOp::Or:
41 case AtomicOp::Or: 44 return OperationCode::AtomicIOr;
42 return OperationCode::AtomicIOr; 45 case AtomicOp::Xor:
43 case AtomicOp::Xor: 46 return OperationCode::AtomicIXor;
44 return OperationCode::AtomicIXor; 47 case AtomicOp::Exch:
45 case AtomicOp::Exch: 48 return OperationCode::AtomicIExchange;
46 return OperationCode::AtomicIExchange; 49 default:
47 default: 50 UNIMPLEMENTED_MSG("op={}", static_cast<int>(op));
48 UNIMPLEMENTED_MSG("op={}", static_cast<int>(op)); 51 return OperationCode::AtomicIAdd;
49 return OperationCode::AtomicIAdd; 52 }
50 }
51 }();
52 return SignedOperation(operation_code, is_signed, std::move(memory), std::move(data));
53} 53}
54 54
55bool IsUnaligned(Tegra::Shader::UniformType uniform_type) { 55bool IsUnaligned(Tegra::Shader::UniformType uniform_type) {
@@ -90,23 +90,22 @@ u32 GetMemorySize(Tegra::Shader::UniformType uniform_type) {
90 90
91Node ExtractUnaligned(Node value, Node address, u32 mask, u32 size) { 91Node ExtractUnaligned(Node value, Node address, u32 mask, u32 size) {
92 Node offset = Operation(OperationCode::UBitwiseAnd, address, Immediate(mask)); 92 Node offset = Operation(OperationCode::UBitwiseAnd, address, Immediate(mask));
93 offset = Operation(OperationCode::ULogicalShiftLeft, std::move(offset), Immediate(3)); 93 offset = Operation(OperationCode::ULogicalShiftLeft, move(offset), Immediate(3));
94 return Operation(OperationCode::UBitfieldExtract, std::move(value), std::move(offset), 94 return Operation(OperationCode::UBitfieldExtract, move(value), move(offset), Immediate(size));
95 Immediate(size));
96} 95}
97 96
98Node InsertUnaligned(Node dest, Node value, Node address, u32 mask, u32 size) { 97Node InsertUnaligned(Node dest, Node value, Node address, u32 mask, u32 size) {
99 Node offset = Operation(OperationCode::UBitwiseAnd, std::move(address), Immediate(mask)); 98 Node offset = Operation(OperationCode::UBitwiseAnd, move(address), Immediate(mask));
100 offset = Operation(OperationCode::ULogicalShiftLeft, std::move(offset), Immediate(3)); 99 offset = Operation(OperationCode::ULogicalShiftLeft, move(offset), Immediate(3));
101 return Operation(OperationCode::UBitfieldInsert, std::move(dest), std::move(value), 100 return Operation(OperationCode::UBitfieldInsert, move(dest), move(value), move(offset),
102 std::move(offset), Immediate(size)); 101 Immediate(size));
103} 102}
104 103
105Node Sign16Extend(Node value) { 104Node Sign16Extend(Node value) {
106 Node sign = Operation(OperationCode::UBitwiseAnd, value, Immediate(1U << 15)); 105 Node sign = Operation(OperationCode::UBitwiseAnd, value, Immediate(1U << 15));
107 Node is_sign = Operation(OperationCode::LogicalUEqual, std::move(sign), Immediate(1U << 15)); 106 Node is_sign = Operation(OperationCode::LogicalUEqual, move(sign), Immediate(1U << 15));
108 Node extend = Operation(OperationCode::Select, is_sign, Immediate(0xFFFF0000), Immediate(0)); 107 Node extend = Operation(OperationCode::Select, is_sign, Immediate(0xFFFF0000), Immediate(0));
109 return Operation(OperationCode::UBitwiseOr, std::move(value), std::move(extend)); 108 return Operation(OperationCode::UBitwiseOr, move(value), move(extend));
110} 109}
111 110
112} // Anonymous namespace 111} // Anonymous namespace
@@ -379,20 +378,36 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
379 378
380 if (IsUnaligned(type)) { 379 if (IsUnaligned(type)) {
381 const u32 mask = GetUnalignedMask(type); 380 const u32 mask = GetUnalignedMask(type);
382 value = InsertUnaligned(gmem, std::move(value), real_address, mask, size); 381 value = InsertUnaligned(gmem, move(value), real_address, mask, size);
383 } 382 }
384 383
385 bb.push_back(Operation(OperationCode::Assign, gmem, value)); 384 bb.push_back(Operation(OperationCode::Assign, gmem, value));
386 } 385 }
387 break; 386 break;
388 } 387 }
388 case OpCode::Id::RED: {
389 UNIMPLEMENTED_IF_MSG(instr.red.type != GlobalAtomicType::U32);
390 UNIMPLEMENTED_IF_MSG(instr.red.operation != AtomicOp::Add);
391 const auto [real_address, base_address, descriptor] =
392 TrackGlobalMemory(bb, instr, true, true);
393 if (!real_address || !base_address) {
394 // Tracking failed, skip atomic.
395 break;
396 }
397 Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
398 Node value = GetRegister(instr.gpr0);
399 bb.push_back(Operation(OperationCode::ReduceIAdd, move(gmem), move(value)));
400 break;
401 }
389 case OpCode::Id::ATOM: { 402 case OpCode::Id::ATOM: {
390 UNIMPLEMENTED_IF_MSG(instr.atom.operation == AtomicOp::Inc || 403 UNIMPLEMENTED_IF_MSG(instr.atom.operation == AtomicOp::Inc ||
391 instr.atom.operation == AtomicOp::Dec || 404 instr.atom.operation == AtomicOp::Dec ||
392 instr.atom.operation == AtomicOp::SafeAdd, 405 instr.atom.operation == AtomicOp::SafeAdd,
393 "operation={}", static_cast<int>(instr.atom.operation.Value())); 406 "operation={}", static_cast<int>(instr.atom.operation.Value()));
394 UNIMPLEMENTED_IF_MSG(instr.atom.type == GlobalAtomicType::S64 || 407 UNIMPLEMENTED_IF_MSG(instr.atom.type == GlobalAtomicType::S64 ||
395 instr.atom.type == GlobalAtomicType::U64, 408 instr.atom.type == GlobalAtomicType::U64 ||
409 instr.atom.type == GlobalAtomicType::F16x2_FTZ_RN ||
410 instr.atom.type == GlobalAtomicType::F32_FTZ_RN,
396 "type={}", static_cast<int>(instr.atom.type.Value())); 411 "type={}", static_cast<int>(instr.atom.type.Value()));
397 412
398 const auto [real_address, base_address, descriptor] = 413 const auto [real_address, base_address, descriptor] =
@@ -403,11 +418,11 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
403 } 418 }
404 419
405 const bool is_signed = 420 const bool is_signed =
406 instr.atoms.type == AtomicType::S32 || instr.atoms.type == AtomicType::S64; 421 instr.atom.type == GlobalAtomicType::S32 || instr.atom.type == GlobalAtomicType::S64;
407 Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); 422 Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
408 Node value = GetAtomOperation(static_cast<AtomicOp>(instr.atom.operation), is_signed, gmem, 423 SetRegister(bb, instr.gpr0,
409 GetRegister(instr.gpr20)); 424 SignedOperation(GetAtomOperation(instr.atom.operation), is_signed, gmem,
410 SetRegister(bb, instr.gpr0, std::move(value)); 425 GetRegister(instr.gpr20)));
411 break; 426 break;
412 } 427 }
413 case OpCode::Id::ATOMS: { 428 case OpCode::Id::ATOMS: {
@@ -421,11 +436,10 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
421 instr.atoms.type == AtomicType::S32 || instr.atoms.type == AtomicType::S64; 436 instr.atoms.type == AtomicType::S32 || instr.atoms.type == AtomicType::S64;
422 const s32 offset = instr.atoms.GetImmediateOffset(); 437 const s32 offset = instr.atoms.GetImmediateOffset();
423 Node address = GetRegister(instr.gpr8); 438 Node address = GetRegister(instr.gpr8);
424 address = Operation(OperationCode::IAdd, std::move(address), Immediate(offset)); 439 address = Operation(OperationCode::IAdd, move(address), Immediate(offset));
425 Node value = 440 SetRegister(bb, instr.gpr0,
426 GetAtomOperation(static_cast<AtomicOp>(instr.atoms.operation), is_signed, 441 SignedOperation(GetAtomOperation(instr.atoms.operation), is_signed,
427 GetSharedMemory(std::move(address)), GetRegister(instr.gpr20)); 442 GetSharedMemory(move(address)), GetRegister(instr.gpr20)));
428 SetRegister(bb, instr.gpr0, std::move(value));
429 break; 443 break;
430 } 444 }
431 case OpCode::Id::AL2P: { 445 case OpCode::Id::AL2P: {
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index 5fcc9da60..3eee961f5 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -178,6 +178,20 @@ enum class OperationCode {
178 AtomicIOr, /// (memory, int) -> int 178 AtomicIOr, /// (memory, int) -> int
179 AtomicIXor, /// (memory, int) -> int 179 AtomicIXor, /// (memory, int) -> int
180 180
181 ReduceUAdd, /// (memory, uint) -> void
182 ReduceUMin, /// (memory, uint) -> void
183 ReduceUMax, /// (memory, uint) -> void
184 ReduceUAnd, /// (memory, uint) -> void
185 ReduceUOr, /// (memory, uint) -> void
186 ReduceUXor, /// (memory, uint) -> void
187
188 ReduceIAdd, /// (memory, int) -> void
189 ReduceIMin, /// (memory, int) -> void
190 ReduceIMax, /// (memory, int) -> void
191 ReduceIAnd, /// (memory, int) -> void
192 ReduceIOr, /// (memory, int) -> void
193 ReduceIXor, /// (memory, int) -> void
194
181 Branch, /// (uint branch_target) -> void 195 Branch, /// (uint branch_target) -> void
182 BranchIndirect, /// (uint branch_target) -> void 196 BranchIndirect, /// (uint branch_target) -> void
183 PushFlowStack, /// (uint branch_target) -> void 197 PushFlowStack, /// (uint branch_target) -> void