Code/Wasm/Interpret/OperatorImpls.cs
using System;
using WasmBox.Wasm.Instructions;
using WasmBox.Wasm.Optimize;
namespace WasmBox.Wasm.Interpret {
/// <summary>
/// A class that defines operator implementations.
/// </summary>
public static class OperatorImpls {
/// <summary>
/// Executes a 'unreachable' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Unreachable( Instruction value, InterpreterContext context ) {
throw new TrapException( "An 'unreachable' instruction was reached.", TrapException.SpecMessages.Unreachable );
}
/// <summary>
/// Executes a 'nop' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Nop( Instruction value, InterpreterContext context ) {
}
/// <summary>
/// Executes a 'block' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Block( Instruction value, InterpreterContext context ) {
var instruction = Operators.Block.CastInstruction( value );
var contents = instruction.Contents;
var interpreter = context.Module.Interpreter;
var outerStack = context.Stack;
var innerStack = context.Stack = context.CreateStack();
for ( int i = 0; i < contents.Count; i++ ) {
interpreter.Interpret( contents[i], context );
if ( context.BreakRequested ) {
// Restore the outer stack.
context.Stack = outerStack;
if ( context.BreakDepth == 0 ) {
// The buck stops here. Push the topmost n items of the
// inner stack onto the outer stack, where n is the block
// instruction's arity.
context.Push( innerStack, instruction.Arity );
}
else {
// Otherwise, push the entire inner stack onto the outer stack and
// make the issue of figuring out how many elements to pop the next
// block's problem.
context.Push( innerStack );
}
context.BreakDepth--;
return;
}
}
// Restore the outer stack.
context.Stack = outerStack;
// Push the inner stack onto the outer stack.
context.Push( innerStack );
}
/// <summary>
/// Executes a 'loop' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Loop( Instruction value, InterpreterContext context ) {
var contents = Operators.Loop.CastInstruction( value ).Contents;
var interpreter = context.Module.Interpreter;
for ( int i = 0; i < contents.Count; ) {
interpreter.Interpret( contents[i], context );
if ( context.BreakRequested ) {
if ( context.BreakDepth == 0 ) {
// This loop is the break's target. We should decrement the
// break depth to terminate the break request and then re-start
// the loop.
context.BreakDepth--;
i = 0;
}
else {
// This loop is not the break's target. We should terminate the loop.
context.BreakDepth--;
return;
}
}
else {
i++;
}
}
}
/// <summary>
/// Executes an 'if' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void If( Instruction value, InterpreterContext context ) {
// Determine which branch we should take.
var instr = Operators.If.CastInstruction( value );
var condVal = context.Pop<int>();
var bodyToRun = condVal != 0
? instr.IfBranch
: instr.ElseBranch;
if ( bodyToRun != null ) {
// Create a block and run it.
var block = Operators.Block.Create( instr.Type, bodyToRun );
Block( block, context );
}
}
/// <summary>
/// Executes a 'br' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Br( Instruction value, InterpreterContext context ) {
var instr = Operators.Br.CastInstruction( value );
context.BreakDepth = (int)instr.Immediate;
}
/// <summary>
/// Executes a 'br_if' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void BrIf( Instruction value, InterpreterContext context ) {
var instr = Operators.BrIf.CastInstruction( value );
if ( context.Pop<int>() != 0 ) {
context.BreakDepth = (int)instr.Immediate;
}
}
/// <summary>
/// Executes a 'br_table' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void BrTable( Instruction value, InterpreterContext context ) {
var instr = Operators.BrTable.CastInstruction( value );
int index = context.Pop<int>();
if ( index < 0 || index >= instr.TargetTable.Count ) {
context.BreakDepth = (int)instr.DefaultTarget;
}
else {
context.BreakDepth = (int)instr.TargetTable[index];
}
}
/// <summary>
/// Executes a 'return' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Return( Instruction value, InterpreterContext context ) {
Return( context );
}
/// <summary>
/// Executes a 'return' instruction.
/// </summary>
/// <param name="context">The interpreter's context.</param>
public static void Return( InterpreterContext context ) {
// Remove excess values from the evaluation stack.
var oldStack = context.Stack;
context.Stack = context.CreateStack();
context.Push( oldStack, context.ReturnTypes.Count );
context.Return();
}
/// <summary>
/// Executes a 'drop' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Drop( Instruction value, InterpreterContext context ) {
context.Pop<object>();
}
/// <summary>
/// Executes a 'select' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Select( Instruction value, InterpreterContext context ) {
// Stack layout:
//
// lhs (any type)
// rhs (same type as `lhs`)
// condition (i32)
//
// Pop operands from the stack.
int condVal = context.Pop<int>();
var rhs = context.Pop<object>();
var lhs = context.Pop<object>();
// Push the lhs onto the stack if the condition
// is truthy; otherwise, push the rhs onto the
// stack.
context.Push( condVal != 0 ? lhs : rhs );
}
/// <summary>
/// Executes a 'call' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Call( Instruction value, InterpreterContext context ) {
var instr = Operators.Call.CastInstruction( value );
var funcDef = context.Module.Functions[(int)instr.Immediate];
var args = context.Pop<object>( funcDef.ParameterTypes.Count );
CheckForStackOverflow( context );
var results = funcDef.Invoke( args, context );
context.Push<object>( results );
}
private static void CheckForStackOverflow( InterpreterContext context ) {
if ( context.CallStackDepth >= context.Policy.MaxCallStackDepth ) {
throw new TrapException(
"A stack overflow occurred: the max call stack depth was exceeded.",
TrapException.SpecMessages.CallStackExhausted );
}
}
/// <summary>
/// Executes a 'call_indirect' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void CallIndirect( Instruction value, InterpreterContext context ) {
var funcDefIndex = context.Pop<int>();
var funcDef = context.Module.Tables[0][(uint)funcDefIndex];
if ( !(funcDef is ThrowFunctionDefinition) ) {
var funcType = new FunctionType( funcDef.ParameterTypes, funcDef.ReturnTypes );
var instruction = Operators.CallIndirect.CastInstruction( value );
var expectedFuncType = context.Module.Types[(int)instruction.TypeIndex];
if ( !ConstFunctionTypeComparer.Instance.Equals( funcType, expectedFuncType ) ) {
throw new TrapException(
$"Indirect function call expected to refer to a function with signature '{funcType}' but " +
$"instead found a function with signature '{expectedFuncType}'",
TrapException.SpecMessages.IndirectCallTypeMismatch );
}
}
var args = context.Pop<object>( funcDef.ParameterTypes.Count );
CheckForStackOverflow( context );
var results = funcDef.Invoke( args, context );
context.Push<object>( results );
}
/// <summary>
/// Executes a 'get_local' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void GetLocal( Instruction value, InterpreterContext context ) {
var instr = Operators.GetLocal.CastInstruction( value );
context.Push( context.Locals[(int)instr.Immediate].Get<object>() );
}
/// <summary>
/// Executes a 'set_local' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void SetLocal( Instruction value, InterpreterContext context ) {
var instr = Operators.SetLocal.CastInstruction( value );
context.Locals[(int)instr.Immediate].Set( context.Pop<object>() );
}
/// <summary>
/// Executes a 'tee_local' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void TeeLocal( Instruction value, InterpreterContext context ) {
var instr = Operators.TeeLocal.CastInstruction( value );
context.Locals[(int)instr.Immediate].Set( context.Peek<object>() );
}
/// <summary>
/// Executes a 'get_global' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void GetGlobal( Instruction value, InterpreterContext context ) {
var instr = Operators.GetGlobal.CastInstruction( value );
context.Push( context.Module.Globals[(int)instr.Immediate].Get<object>() );
}
/// <summary>
/// Executes a 'set_global' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void SetGlobal( Instruction value, InterpreterContext context ) {
var instr = Operators.SetGlobal.CastInstruction( value );
context.Module.Globals[(int)instr.Immediate].Set( context.Pop<object>() );
}
/// <summary>
/// Executes an 'i32.load' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Load( Instruction value, InterpreterContext context ) {
var instr = Operators.Int32Load.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = context.Module.Memories[0].Int32[pointer];
context.Push( result );
}
/// <summary>
/// Executes an 'i64.load' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Load( Instruction value, InterpreterContext context ) {
var instr = Operators.Int64Load.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = context.Module.Memories[0].Int64[pointer];
context.Push( result );
}
/// <summary>
/// Executes an 'i32.load8_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Load8S( Instruction value, InterpreterContext context ) {
var instr = Operators.Int32Load8S.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = context.Module.Memories[0].Int8[pointer];
context.Push<int>( result );
}
/// <summary>
/// Executes an 'i32.load8_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Load8U( Instruction value, InterpreterContext context ) {
var instr = Operators.Int32Load8U.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = (byte)context.Module.Memories[0].Int8[pointer];
context.Push<int>( result );
}
/// <summary>
/// Executes an 'i32.load16_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Load16S( Instruction value, InterpreterContext context ) {
var instr = Operators.Int32Load16S.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = context.Module.Memories[0].Int16[pointer];
context.Push<int>( result );
}
/// <summary>
/// Executes an 'i32.load16_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Load16U( Instruction value, InterpreterContext context ) {
var instr = Operators.Int32Load16U.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = (ushort)context.Module.Memories[0].Int16[pointer];
context.Push<int>( result );
}
/// <summary>
/// Executes an 'i64.load8_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Load8S( Instruction value, InterpreterContext context ) {
var instr = Operators.Int64Load8S.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = context.Module.Memories[0].Int8[pointer];
context.Push<long>( result );
}
/// <summary>
/// Executes an 'i64.load8_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Load8U( Instruction value, InterpreterContext context ) {
var instr = Operators.Int64Load8U.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = (byte)context.Module.Memories[0].Int8[pointer];
context.Push<long>( result );
}
/// <summary>
/// Executes an 'i64.load16_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Load16S( Instruction value, InterpreterContext context ) {
var instr = Operators.Int64Load16S.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = context.Module.Memories[0].Int16[pointer];
context.Push<long>( result );
}
/// <summary>
/// Executes an 'i64.load16_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Load16U( Instruction value, InterpreterContext context ) {
var instr = Operators.Int64Load16U.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = (ushort)context.Module.Memories[0].Int16[pointer];
context.Push<long>( result );
}
/// <summary>
/// Executes an 'i64.load32_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Load32S( Instruction value, InterpreterContext context ) {
var instr = Operators.Int64Load32S.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = context.Module.Memories[0].Int32[pointer];
context.Push<long>( result );
}
/// <summary>
/// Executes an 'i64.load32_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Load32U( Instruction value, InterpreterContext context ) {
var instr = Operators.Int64Load32U.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = (uint)context.Module.Memories[0].Int32[pointer];
context.Push<long>( result );
}
/// <summary>
/// Executes an 'f32.load' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Load( Instruction value, InterpreterContext context ) {
var instr = Operators.Float32Load.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = context.Module.Memories[0].Float32[pointer];
context.Push( result );
}
/// <summary>
/// Executes an 'f64.load' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Load( Instruction value, InterpreterContext context ) {
var instr = Operators.Float64Load.CastInstruction( value );
var pointer = PopAlignedPointer( instr, context );
var result = context.Module.Memories[0].Float64[pointer];
context.Push( result );
}
/// <summary>
/// Executes an 'i32.store8' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Store8( Instruction value, InterpreterContext context ) {
var instr = Operators.Int32Store8.CastInstruction( value );
var result = context.Pop<int>();
var pointer = PopAlignedPointer( instr, context );
var memView = context.Module.Memories[0].Int8;
memView[pointer] = (sbyte)result;
}
/// <summary>
/// Executes an 'i32.store16' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Store16( Instruction value, InterpreterContext context ) {
var instr = Operators.Int32Store16.CastInstruction( value );
var result = context.Pop<int>();
var pointer = PopAlignedPointer( instr, context );
var memView = context.Module.Memories[0].Int16;
memView[pointer] = (short)result;
}
/// <summary>
/// Executes an 'i32.store' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Store( Instruction value, InterpreterContext context ) {
var instr = Operators.Int32Store.CastInstruction( value );
var result = context.Pop<int>();
var pointer = PopAlignedPointer( instr, context );
var memView = context.Module.Memories[0].Int32;
memView[pointer] = result;
}
/// <summary>
/// Executes an 'i64.store8' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Store8( Instruction value, InterpreterContext context ) {
var instr = Operators.Int64Store8.CastInstruction( value );
var result = context.Pop<long>();
var pointer = PopAlignedPointer( instr, context );
var memView = context.Module.Memories[0].Int8;
memView[pointer] = (sbyte)result;
}
/// <summary>
/// Executes an 'i32.store16' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Store16( Instruction value, InterpreterContext context ) {
var instr = Operators.Int64Store16.CastInstruction( value );
var result = context.Pop<long>();
var pointer = PopAlignedPointer( instr, context );
var memView = context.Module.Memories[0].Int16;
memView[pointer] = (short)result;
}
/// <summary>
/// Executes an 'i64.store32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Store32( Instruction value, InterpreterContext context ) {
var instr = Operators.Int64Store32.CastInstruction( value );
var result = context.Pop<long>();
var pointer = PopAlignedPointer( instr, context );
var memView = context.Module.Memories[0].Int32;
memView[pointer] = (int)result;
}
/// <summary>
/// Executes an 'i64.store' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Store( Instruction value, InterpreterContext context ) {
var instr = Operators.Int64Store.CastInstruction( value );
var result = context.Pop<long>();
var pointer = PopAlignedPointer( instr, context );
var memView = context.Module.Memories[0].Int64;
memView[pointer] = result;
}
/// <summary>
/// Executes an 'f32.store' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Store( Instruction value, InterpreterContext context ) {
var instr = Operators.Float32Store.CastInstruction( value );
var result = context.Pop<float>();
var pointer = PopAlignedPointer( instr, context );
var memView = context.Module.Memories[0].Float32;
memView[pointer] = result;
}
/// <summary>
/// Executes an 'f64.store' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Store( Instruction value, InterpreterContext context ) {
var instr = Operators.Float64Store.CastInstruction( value );
var result = context.Pop<double>();
var pointer = PopAlignedPointer( instr, context );
var memView = context.Module.Memories[0].Float64;
memView[pointer] = result;
}
private static uint PopAlignedPointer( MemoryInstruction Instruction, InterpreterContext context ) {
var longPtr = (ulong)(uint)context.Pop<int>() + Instruction.Offset;
if ( longPtr > uint.MaxValue ) {
throw new TrapException(
"Memory address overflow.",
TrapException.SpecMessages.OutOfBoundsMemoryAccess );
}
var pointer = (uint)longPtr;
if ( context.Policy.EnforceAlignment ) {
CheckAlignment( pointer, Instruction );
}
return pointer;
}
private static void CheckAlignment( uint Pointer, MemoryInstruction Instruction ) {
if ( Pointer % Instruction.Alignment != 0 ) {
throw new TrapException(
string.Format(
"Misaligned memory access at {0}. (alignment: {1})",
DumpHelpers.FormatHex( Pointer ),
Instruction.Alignment ),
TrapException.SpecMessages.MisalignedMemoryAccess );
}
}
/// <summary>
/// Executes a 'size_memory' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void SizeMemory( Instruction value, InterpreterContext context ) {
var instr = Operators.SizeMemory.CastInstruction( value );
var result = context.Module.Memories[(int)instr.Immediate].Size;
context.Push( (int)result );
}
/// <summary>
/// Executes a 'grow_memory' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void GrowMemory( Instruction value, InterpreterContext context ) {
var instr = Operators.SizeMemory.CastInstruction( value );
var amount = (uint)context.Pop<int>();
var result = context.Module.Memories[(int)instr.Immediate].Grow( amount );
context.Push( result );
}
/// <summary>
/// Executes a 'init_memory' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void InitMemory( Instruction value, InterpreterContext context ) {
var instr = Operators.InitMemory.CastInstruction( value );
var data = context.Module.DataSegments[(int)instr.Immediate1];
var memory = context.Module.Memories[(int)instr.Immediate2];
var length = context.Pop<int>(); // n
var src = context.Pop<int>(); // s
var dst = context.Pop<int>(); // d
if ( src + length >= data.Data.Length )
throw new TrapException( "Out of bounds data read", TrapException.SpecMessages.OutOfBoundsMemoryAccess );
if ( dst + length >= memory.Length )
throw new TrapException( "Out of bounds memory write", TrapException.SpecMessages.OutOfBoundsMemoryAccess );
if ( length == 0 )
return;
// for ( int i = 0; i < length; i++ )
// memory[(uint)(dst + i)] = data.Data[src + i];
memory[dst..(dst + length)] = data.Data[src..(src + length)];
}
/// <summary>
/// Executes a 'drop_data' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void DropData( Instruction value, InterpreterContext context ) {
var instr = Operators.DropData.CastInstruction( value );
var data = context.Module.DataSegments[(int)instr.Immediate];
data.Data = [];
}
/// <summary>
/// Executes a 'copy_memory' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void CopyMemory( Instruction value, InterpreterContext context ) {
var instr = Operators.CopyMemory.CastInstruction( value );
var memory1 = context.Module.Memories[(int)instr.Immediate1];
var memory2 = context.Module.Memories[(int)instr.Immediate2];
var length = context.Pop<int>(); // n
var src = context.Pop<int>(); // s
var dst = context.Pop<int>(); // d
if ( src + length > memory1.Length )
throw new TrapException( "Out of bounds src memory read", TrapException.SpecMessages.OutOfBoundsMemoryAccess );
if ( dst + length > memory2.Length )
throw new TrapException( "Out of bounds dst memory write", TrapException.SpecMessages.OutOfBoundsMemoryAccess );
if ( length == 0 )
return;
// for ( int i = 0; i < length; i++ )
// memory2[(uint)(dst + i)] = memory1[(uint)(src + i)];
memory2[dst..(dst + length)] = memory1[src..(src + length)];
}
/// <summary>
/// Executes a 'fill_memory' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void FillMemory( Instruction value, InterpreterContext context ) {
var instr = Operators.FillMemory.CastInstruction( value );
var memory = context.Module.Memories[(int)instr.Immediate];
var length = context.Pop<int>(); // n
var val = context.Pop<object>(); // val
var dst = context.Pop<int>(); // d
if ( dst + length > memory.Length )
throw new TrapException( "Out of bounds memory write", TrapException.SpecMessages.OutOfBoundsMemoryAccess );
if ( length == 0 )
return;
byte b;
if ( val is byte b_ )
b = b_;
else if ( val is int i )
b = (byte)i;
else if ( val is long l )
b = (byte)l;
else if ( val is float f )
b = (byte)BitConverter.SingleToUInt32Bits( f );
else if ( val is double d )
b = (byte)BitConverter.DoubleToUInt64Bits( d );
else
throw new NotImplementedException( "Weird" );
for ( int i = 0; i < length; i++ )
memory[(uint)(dst + i)] = b;
}
/// <summary>
/// Executes an 'i32.const' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Const( Instruction value, InterpreterContext context ) {
var instr = Operators.Int32Const.CastInstruction( value );
context.Push( instr.Immediate );
}
/// <summary>
/// Executes an 'i64.const' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Const( Instruction value, InterpreterContext context ) {
var instr = Operators.Int64Const.CastInstruction( value );
context.Push( instr.Immediate );
}
/// <summary>
/// Executes an 'f32.const' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Const( Instruction value, InterpreterContext context ) {
var instr = Operators.Float32Const.CastInstruction( value );
context.Push( instr.Immediate );
}
/// <summary>
/// Executes an 'f64.const' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Const( Instruction value, InterpreterContext context ) {
var instr = Operators.Float64Const.CastInstruction( value );
context.Push( instr.Immediate );
}
#region Int32 nullaries
/// <summary>
/// Executes an 'i32.add' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Add( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs + rhs );
}
/// <summary>
/// Executes an 'i32.sub' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Sub( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs - rhs );
}
/// <summary>
/// Executes an 'i32.mul' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Mul( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs * rhs );
}
/// <summary>
/// Executes an 'i32.div_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32DivS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs / rhs );
}
/// <summary>
/// Executes an 'i32.div_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32DivU( Instruction value, InterpreterContext context ) {
var rhs = (uint)context.Pop<int>();
var lhs = (uint)context.Pop<int>();
context.Push( (int)(lhs / rhs) );
}
/// <summary>
/// Executes an 'i32.rem_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32RemS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( ValueHelpers.RemS( lhs, rhs ) );
}
/// <summary>
/// Executes an 'i32.rem_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32RemU( Instruction value, InterpreterContext context ) {
var rhs = (uint)context.Pop<int>();
var lhs = (uint)context.Pop<int>();
context.Push( (int)(lhs % rhs) );
}
/// <summary>
/// Executes an 'i32.and' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32And( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs & rhs );
}
/// <summary>
/// Executes an 'i32.or' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Or( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs | rhs );
}
/// <summary>
/// Executes an 'i32.xor' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Xor( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs ^ rhs );
}
/// <summary>
/// Executes an 'i32.shr_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32ShrS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs >> rhs );
}
/// <summary>
/// Executes an 'i32.shr_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32ShrU( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = (uint)context.Pop<int>();
context.Push( (int)(lhs >> rhs) );
}
/// <summary>
/// Executes an 'i32.shl' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Shl( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs << rhs );
}
/// <summary>
/// Executes an 'i32.rotl' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Rotl( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( ValueHelpers.RotateLeft( lhs, rhs ) );
}
/// <summary>
/// Executes an 'i32.rotr' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Rotr( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( ValueHelpers.RotateRight( lhs, rhs ) );
}
/// <summary>
/// Executes an 'i32.clz' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Clz( Instruction value, InterpreterContext context ) {
context.Push( ValueHelpers.CountLeadingZeros( context.Pop<int>() ) );
}
/// <summary>
/// Executes an 'i32.ctz' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Ctz( Instruction value, InterpreterContext context ) {
context.Push( ValueHelpers.CountTrailingZeros( context.Pop<int>() ) );
}
/// <summary>
/// Executes an 'i32.popcnt' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Popcnt( Instruction value, InterpreterContext context ) {
context.Push( ValueHelpers.PopCount( context.Pop<int>() ) );
}
/// <summary>
/// Executes an 'i32.eq' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Eq( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs == rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i32.ne' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Ne( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs != rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i32.lt_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32LtS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs < rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i32.lt_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32LtU( Instruction value, InterpreterContext context ) {
var rhs = (uint)context.Pop<int>();
var lhs = (uint)context.Pop<int>();
context.Push( lhs < rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i32.le_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32LeS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs <= rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i32.le_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32LeU( Instruction value, InterpreterContext context ) {
var rhs = (uint)context.Pop<int>();
var lhs = (uint)context.Pop<int>();
context.Push( lhs <= rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i32.gt_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32GtS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs > rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i32.gt_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32GtU( Instruction value, InterpreterContext context ) {
var rhs = (uint)context.Pop<int>();
var lhs = (uint)context.Pop<int>();
context.Push( lhs > rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i32.ge_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32GeS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<int>();
var lhs = context.Pop<int>();
context.Push( lhs >= rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i32.ge_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32GeU( Instruction value, InterpreterContext context ) {
var rhs = (uint)context.Pop<int>();
var lhs = (uint)context.Pop<int>();
context.Push( lhs >= rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i32.eqz' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32Eqz( Instruction value, InterpreterContext context ) {
context.Push( context.Pop<int>() == 0 ? 1 : 0 );
}
/// <summary>
/// Executes an 'i32.trunc_s/f32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32TruncSFloat32( Instruction value, InterpreterContext context ) {
context.Push( ValueHelpers.TruncateToInt32( context.Pop<float>() ) );
}
/// <summary>
/// Executes an 'i32.trunc_u/f32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32TruncUFloat32( Instruction value, InterpreterContext context ) {
context.Push( (int)ValueHelpers.TruncateToUInt32( context.Pop<float>() ) );
}
/// <summary>
/// Executes an 'i32.trunc_s/f64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32TruncSFloat64( Instruction value, InterpreterContext context ) {
context.Push( ValueHelpers.TruncateToInt32( context.Pop<double>() ) );
}
/// <summary>
/// Executes an 'i32.trunc_u/f64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32TruncUFloat64( Instruction value, InterpreterContext context ) {
context.Push( (int)ValueHelpers.TruncateToUInt32( context.Pop<double>() ) );
}
/// <summary>
/// Executes an 'i32.wrap/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32WrapInt64( Instruction value, InterpreterContext context ) {
context.Push( (int)context.Pop<long>() );
}
/// <summary>
/// Executes an 'i32.reinterpret/f32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32ReinterpretFloat32( Instruction value, InterpreterContext context ) {
context.Push( ValueHelpers.ReinterpretAsInt32( context.Pop<float>() ) );
}
#endregion
#region Int64 nullaries
/// <summary>
/// Executes an 'i64.add' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Add( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs + rhs );
}
/// <summary>
/// Executes an 'i64.sub' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Sub( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs - rhs );
}
/// <summary>
/// Executes an 'i64.mul' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Mul( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs * rhs );
}
/// <summary>
/// Executes an 'i64.div_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64DivS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs / rhs );
}
/// <summary>
/// Executes an 'i64.div_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64DivU( Instruction value, InterpreterContext context ) {
var rhs = (ulong)context.Pop<long>();
var lhs = (ulong)context.Pop<long>();
context.Push( (long)(lhs / rhs) );
}
/// <summary>
/// Executes an 'i64.rem_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64RemS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( ValueHelpers.RemS( lhs, rhs ) );
}
/// <summary>
/// Executes an 'i64.rem_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64RemU( Instruction value, InterpreterContext context ) {
var rhs = (ulong)context.Pop<long>();
var lhs = (ulong)context.Pop<long>();
context.Push( (long)(lhs % rhs) );
}
/// <summary>
/// Executes an 'i64.and' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64And( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs & rhs );
}
/// <summary>
/// Executes an 'i64.or' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Or( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs | rhs );
}
/// <summary>
/// Executes an 'i64.xor' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Xor( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs ^ rhs );
}
/// <summary>
/// Executes an 'i64.shr_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64ShrS( Instruction value, InterpreterContext context ) {
var rhs = (int)context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs >> rhs );
}
/// <summary>
/// Executes an 'i64.shr_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64ShrU( Instruction value, InterpreterContext context ) {
var rhs = (int)context.Pop<long>();
var lhs = (ulong)context.Pop<long>();
context.Push( (long)(lhs >> rhs) );
}
/// <summary>
/// Executes an 'i64.shl' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Shl( Instruction value, InterpreterContext context ) {
var rhs = (int)context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs << rhs );
}
/// <summary>
/// Executes an 'i64.rotl' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Rotl( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( ValueHelpers.RotateLeft( lhs, rhs ) );
}
/// <summary>
/// Executes an 'i64.rotr' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Rotr( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( ValueHelpers.RotateRight( lhs, rhs ) );
}
/// <summary>
/// Executes an 'i64.clz' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Clz( Instruction value, InterpreterContext context ) {
context.Push<long>( ValueHelpers.CountLeadingZeros( context.Pop<long>() ) );
}
/// <summary>
/// Executes an 'i64.ctz' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Ctz( Instruction value, InterpreterContext context ) {
context.Push<long>( ValueHelpers.CountTrailingZeros( context.Pop<long>() ) );
}
/// <summary>
/// Executes an 'i64.popcnt' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Popcnt( Instruction value, InterpreterContext context ) {
context.Push<long>( ValueHelpers.PopCount( context.Pop<long>() ) );
}
/// <summary>
/// Executes an 'i64.eq' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Eq( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs == rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i64.ne' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Ne( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs != rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i64.lt_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64LtS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs < rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i64.lt_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64LtU( Instruction value, InterpreterContext context ) {
var rhs = (ulong)context.Pop<long>();
var lhs = (ulong)context.Pop<long>();
context.Push( lhs < rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i64.le_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64LeS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs <= rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i64.le_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64LeU( Instruction value, InterpreterContext context ) {
var rhs = (ulong)context.Pop<long>();
var lhs = (ulong)context.Pop<long>();
context.Push( lhs <= rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i64.gt_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64GtS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs > rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i64.gt_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64GtU( Instruction value, InterpreterContext context ) {
var rhs = (ulong)context.Pop<long>();
var lhs = (ulong)context.Pop<long>();
context.Push( lhs > rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i64.ge_s' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64GeS( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<long>();
var lhs = context.Pop<long>();
context.Push( lhs >= rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i64.ge_u' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64GeU( Instruction value, InterpreterContext context ) {
var rhs = (ulong)context.Pop<long>();
var lhs = (ulong)context.Pop<long>();
context.Push( lhs >= rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'i64.eqz' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64Eqz( Instruction value, InterpreterContext context ) {
context.Push( context.Pop<long>() == 0 ? 1 : 0 );
}
/// <summary>
/// Executes an 'i64.trunc_s/f32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64TruncSFloat32( Instruction value, InterpreterContext context ) {
context.Push( ValueHelpers.TruncateToInt64( context.Pop<float>() ) );
}
/// <summary>
/// Executes an 'i64.trunc_u/f32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64TruncUFloat32( Instruction value, InterpreterContext context ) {
context.Push( (long)ValueHelpers.TruncateToUInt64( context.Pop<float>() ) );
}
/// <summary>
/// Executes an 'i64.trunc_s/f64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64TruncSFloat64( Instruction value, InterpreterContext context ) {
context.Push( ValueHelpers.TruncateToInt64( context.Pop<double>() ) );
}
/// <summary>
/// Executes an 'i64.trunc_u/f64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64TruncUFloat64( Instruction value, InterpreterContext context ) {
context.Push( (long)ValueHelpers.TruncateToUInt64( context.Pop<double>() ) );
}
/// <summary>
/// Executes an 'i64.reinterpret/f32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64ReinterpretFloat64( Instruction value, InterpreterContext context ) {
context.Push( ValueHelpers.ReinterpretAsInt64( context.Pop<double>() ) );
}
/// <summary>
/// Executes an 'i64.extend_s/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64ExtendSInt32( Instruction value, InterpreterContext context ) {
context.Push<long>( context.Pop<int>() );
}
/// <summary>
/// Executes an 'i64.extend_u/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64ExtendUInt32( Instruction value, InterpreterContext context ) {
context.Push<long>( (uint)context.Pop<int>() );
}
#endregion
#region Float32 nullaries
/// <summary>
/// Executes an 'f32.abs' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Abs( Instruction value, InterpreterContext context ) {
context.Push( Math.Abs( context.Pop<float>() ) );
}
/// <summary>
/// Executes an 'f32.add' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Add( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( lhs + rhs );
}
/// <summary>
/// Executes an 'f32.ceil' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Ceil( Instruction value, InterpreterContext context ) {
context.Push( (float)Math.Ceiling( context.Pop<float>() ) );
}
/// <summary>
/// Executes an 'f32.copysign' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Copysign( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( ValueHelpers.Copysign( lhs, rhs ) );
}
/// <summary>
/// Executes an 'f32.div' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Div( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( lhs / rhs );
}
/// <summary>
/// Executes an 'f32.eq' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Eq( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( lhs == rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'f32.floor' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Floor( Instruction value, InterpreterContext context ) {
context.Push( (float)Math.Floor( context.Pop<float>() ) );
}
/// <summary>
/// Executes an 'f32.ge' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Ge( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( lhs >= rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'f32.gt' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Gt( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( lhs > rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'f32.le' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Le( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( lhs <= rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'f32.lt' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Lt( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( lhs < rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'f32.max' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Max( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( Math.Max( lhs, rhs ) );
}
/// <summary>
/// Executes an 'f32.min' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Min( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( Math.Min( lhs, rhs ) );
}
/// <summary>
/// Executes an 'f32.mul' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Mul( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( lhs * rhs );
}
/// <summary>
/// Executes an 'f32.ne' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Ne( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( lhs != rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'f32.nearest' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Nearest( Instruction value, InterpreterContext context ) {
context.Push( (float)Math.Round( context.Pop<float>(), MidpointRounding.ToEven ) );
}
/// <summary>
/// Executes an 'f32.neg' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Neg( Instruction value, InterpreterContext context ) {
context.Push( -context.Pop<float>() );
}
/// <summary>
/// Executes an 'f32.sub' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Sub( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<float>();
var lhs = context.Pop<float>();
context.Push( lhs - rhs );
}
/// <summary>
/// Executes an 'f32.sqrt' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Sqrt( Instruction value, InterpreterContext context ) {
context.Push( (float)Math.Sqrt( context.Pop<float>() ) );
}
/// <summary>
/// Executes an 'f32.trunc' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32Trunc( Instruction value, InterpreterContext context ) {
context.Push( (float)Math.Truncate( context.Pop<float>() ) );
}
/// <summary>
/// Executes an 'f32.convert_s/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32ConvertSInt32( Instruction value, InterpreterContext context ) {
context.Push<float>( context.Pop<int>() );
}
/// <summary>
/// Executes an 'f32.convert_u/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32ConvertUInt32( Instruction value, InterpreterContext context ) {
context.Push<float>( (uint)context.Pop<int>() );
}
/// <summary>
/// Executes an 'f32.convert_s/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32ConvertSInt64( Instruction value, InterpreterContext context ) {
context.Push<float>( context.Pop<long>() );
}
/// <summary>
/// Executes an 'f32.convert_u/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32ConvertUInt64( Instruction value, InterpreterContext context ) {
context.Push<float>( (ulong)context.Pop<long>() );
}
/// <summary>
/// Executes an 'f32.demote/f64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32DemoteFloat64( Instruction value, InterpreterContext context ) {
context.Push( (float)context.Pop<double>() );
}
/// <summary>
/// Executes an 'f32.reinterpret/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float32ReinterpretInt32( Instruction value, InterpreterContext context ) {
context.Push( ValueHelpers.ReinterpretAsFloat32( context.Pop<int>() ) );
}
#endregion
#region Float64 nullaries
/// <summary>
/// Executes an 'f64.abs' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Abs( Instruction value, InterpreterContext context ) {
context.Push( Math.Abs( context.Pop<double>() ) );
}
/// <summary>
/// Executes an 'f64.add' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Add( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( lhs + rhs );
}
/// <summary>
/// Executes an 'f64.ceil' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Ceil( Instruction value, InterpreterContext context ) {
context.Push( Math.Ceiling( context.Pop<double>() ) );
}
/// <summary>
/// Executes an 'f64.copysign' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Copysign( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( ValueHelpers.Copysign( lhs, rhs ) );
}
/// <summary>
/// Executes an 'f64.div' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Div( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( lhs / rhs );
}
/// <summary>
/// Executes an 'f64.eq' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Eq( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( lhs == rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'f64.floor' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Floor( Instruction value, InterpreterContext context ) {
context.Push( Math.Floor( context.Pop<double>() ) );
}
/// <summary>
/// Executes an 'f64.ge' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Ge( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( lhs >= rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'f64.gt' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Gt( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( lhs > rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'f64.le' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Le( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( lhs <= rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'f64.lt' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Lt( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( lhs < rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'f64.max' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Max( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( Math.Max( lhs, rhs ) );
}
/// <summary>
/// Executes an 'f64.min' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Min( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( Math.Min( lhs, rhs ) );
}
/// <summary>
/// Executes an 'f64.mul' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Mul( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( lhs * rhs );
}
/// <summary>
/// Executes an 'f64.ne' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Ne( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( lhs != rhs ? 1 : 0 );
}
/// <summary>
/// Executes an 'f64.nearest' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Nearest( Instruction value, InterpreterContext context ) {
context.Push( Math.Round( context.Pop<double>(), MidpointRounding.ToEven ) );
}
/// <summary>
/// Executes an 'f64.neg' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Neg( Instruction value, InterpreterContext context ) {
context.Push( -context.Pop<double>() );
}
/// <summary>
/// Executes an 'f64.sub' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Sub( Instruction value, InterpreterContext context ) {
var rhs = context.Pop<double>();
var lhs = context.Pop<double>();
context.Push( lhs - rhs );
}
/// <summary>
/// Executes an 'f64.sqrt' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Sqrt( Instruction value, InterpreterContext context ) {
context.Push( Math.Sqrt( context.Pop<double>() ) );
}
/// <summary>
/// Executes an 'f64.trunc' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64Trunc( Instruction value, InterpreterContext context ) {
context.Push( Math.Truncate( context.Pop<double>() ) );
}
/// <summary>
/// Executes an 'f64.convert_s/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64ConvertSInt32( Instruction value, InterpreterContext context ) {
context.Push<double>( context.Pop<int>() );
}
/// <summary>
/// Executes an 'f64.convert_u/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64ConvertUInt32( Instruction value, InterpreterContext context ) {
context.Push<double>( (uint)context.Pop<int>() );
}
/// <summary>
/// Executes an 'f64.convert_s/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64ConvertSInt64( Instruction value, InterpreterContext context ) {
context.Push<double>( context.Pop<long>() );
}
/// <summary>
/// Executes an 'f64.convert_u/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64ConvertUInt64( Instruction value, InterpreterContext context ) {
context.Push<double>( (ulong)context.Pop<long>() );
}
/// <summary>
/// Executes an 'f64.promote/f32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64PromoteFloat32( Instruction value, InterpreterContext context ) {
context.Push<double>( context.Pop<float>() );
}
/// <summary>
/// Executes an 'f64.reinterpret/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Float64ReinterpretInt64( Instruction value, InterpreterContext context ) {
context.Push( ValueHelpers.ReinterpretAsFloat64( context.Pop<long>() ) );
}
#endregion
/// <summary>
/// Executes a 'extend8_s/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32ExtendByteS( Instruction value, InterpreterContext context )
=> context.Push( ValueHelpers.SignExtend8ToInt32( context.Pop<int>() ) );
/// <summary>
/// Executes a 'extend16_s/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32ExtendInt16S( Instruction value, InterpreterContext context )
=> context.Push( ValueHelpers.SignExtend16ToInt32( context.Pop<int>() ) );
/// <summary>
/// Executes a 'extend8_s/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64ExtendByteS( Instruction value, InterpreterContext context )
=> context.Push( ValueHelpers.SignExtend8ToInt64( context.Pop<long>() ) );
/// <summary>
/// Executes a 'extend16_s/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64ExtendInt16S( Instruction value, InterpreterContext context )
=> context.Push( ValueHelpers.SignExtend16ToInt64( context.Pop<long>() ) );
/// <summary>
/// Executes a 'extend32_s/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64ExtendInt32S( Instruction value, InterpreterContext context )
=> context.Push( ValueHelpers.SignExtend32ToInt64( context.Pop<long>() ) );
/// <summary>
/// Executes a 'trunc_sat_f32_s/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32TruncSatSFloat32( Instruction value, InterpreterContext context )
=> context.Push(ValueHelpers.TruncateToInt32Saturate(context.Pop<float>()));
/// <summary>
/// Executes a 'trunc_sat_f32_u/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32TruncSatUFloat32( Instruction value, InterpreterContext context )
=> context.Push(ValueHelpers.TruncateToUInt32Saturate(context.Pop<float>()));
/// <summary>
/// Executes a 'trunc_sat_f64_s/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32TruncSatSFloat64( Instruction value, InterpreterContext context )
=> context.Push(ValueHelpers.TruncateToInt32Saturate(context.Pop<double>()));
/// <summary>
/// Executes a 'trunc_sat_f64_u/i32' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int32TruncSatUFloat64( Instruction value, InterpreterContext context )
=> context.Push(ValueHelpers.TruncateToUInt32Saturate(context.Pop<double>()));
/// <summary>
/// Executes a 'trunc_sat_f32_s/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64TruncSatSFloat32( Instruction value, InterpreterContext context )
=> context.Push(ValueHelpers.TruncateToInt64Saturate(context.Pop<float>()));
/// <summary>
/// Executes a 'trunc_sat_f32_u/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64TruncSatUFloat32( Instruction value, InterpreterContext context )
=> context.Push(ValueHelpers.TruncateToUInt64Saturate(context.Pop<float>()));
/// <summary>
/// Executes a 'trunc_sat_f64_s/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64TruncSatSFloat64( Instruction value, InterpreterContext context )
=> context.Push(ValueHelpers.TruncateToInt64Saturate(context.Pop<double>()));
/// <summary>
/// Executes a 'trunc_sat_f64_u/i64' instruction.
/// </summary>
/// <param name="value">The instruction to interpret.</param>
/// <param name="context">The interpreter's context.</param>
public static void Int64TruncSatUFloat64( Instruction value, InterpreterContext context )
=> context.Push(ValueHelpers.TruncateToUInt64Saturate(context.Pop<double>()));
}
}