diff --git a/src/Neo.VM/JumpTable/JumpTable.Compound.cs b/src/Neo.VM/JumpTable/JumpTable.Compound.cs index aeb2047825..197cc1952a 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Compound.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Compound.cs @@ -239,6 +239,7 @@ public virtual void NewMap(ExecutionEngine engine, Instruction instruction) [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void Size(ExecutionEngine engine, Instruction instruction) { + // TODO: we should be able to optimize by using peek instead of dup and pop var x = engine.Pop(); switch (x) { @@ -410,7 +411,7 @@ public virtual void PickItem(ExecutionEngine engine, Instruction instruction) /// /// The execution engine. /// The instruction being executed. - /// Pop 1, Push 1 + /// Pop 2, Push 0 [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void Append(ExecutionEngine engine, Instruction instruction) { diff --git a/src/Neo.VM/JumpTable/JumpTable.Numeric.cs b/src/Neo.VM/JumpTable/JumpTable.Numeric.cs index 989991a07c..06533e293a 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Numeric.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Numeric.cs @@ -155,7 +155,7 @@ public virtual void Div(ExecutionEngine engine, Instruction instruction) } /// - /// Computes the result of raising a number to the specified power. + /// Computes the remainder after dividing a by b. /// /// /// The execution engine. @@ -170,7 +170,7 @@ public virtual void Mod(ExecutionEngine engine, Instruction instruction) } /// - /// Computes the square root of the specified integer. + /// Computes the result of raising a number to the specified power. /// /// /// The execution engine. @@ -186,7 +186,7 @@ public virtual void Pow(ExecutionEngine engine, Instruction instruction) } /// - /// + /// Returns the square root of a specified number. /// /// /// The execution engine. diff --git a/src/Neo.VM/JumpTable/JumpTable.Splice.cs b/src/Neo.VM/JumpTable/JumpTable.Splice.cs index 2f49ea0107..f04d045988 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Splice.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Splice.cs @@ -59,6 +59,7 @@ public virtual void Memcpy(ExecutionEngine engine, Instruction instruction) Types.Buffer dst = engine.Pop(); if (checked(di + count) > dst.Size) throw new InvalidOperationException($"The value {count} is out of range."); + // TODO: check if we can optimize the memcpy by using peek instead of dup then pop src.Slice(si, count).CopyTo(dst.InnerBuffer.Span[di..]); } diff --git a/src/Neo.VM/JumpTable/JumpTable.Stack.cs b/src/Neo.VM/JumpTable/JumpTable.Stack.cs index 45ee5565a7..68094470fe 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Stack.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Stack.cs @@ -47,7 +47,7 @@ public virtual void Drop(ExecutionEngine engine, Instruction instruction) } /// - /// + /// Removes the second-to-top stack item. /// /// /// The execution engine. @@ -59,7 +59,7 @@ public virtual void Nip(ExecutionEngine engine, Instruction instruction) } /// - /// Removes the nth item from the top of the evaluation stack. + /// Removes the n-th item from the top of the evaluation stack. /// /// /// The execution engine. diff --git a/src/Neo.VM/OpCode.cs b/src/Neo.VM/OpCode.cs index dd5f1574ea..8ef5c0e538 100644 --- a/src/Neo.VM/OpCode.cs +++ b/src/Neo.VM/OpCode.cs @@ -22,136 +22,321 @@ public enum OpCode : byte /// /// Pushes a 1-byte signed integer onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 1)] PUSHINT8 = 0x00, + /// /// Pushes a 2-bytes signed integer onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 2)] PUSHINT16 = 0x01, + /// /// Pushes a 4-bytes signed integer onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 4)] PUSHINT32 = 0x02, + /// - /// Pushes a 8-bytes signed integer onto the stack. + /// Pushes an 8-bytes signed integer onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 8)] PUSHINT64 = 0x03, + /// /// Pushes a 16-bytes signed integer onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 16)] PUSHINT128 = 0x04, + /// /// Pushes a 32-bytes signed integer onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 32)] PUSHINT256 = 0x05, + /// /// Pushes the boolean value onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSHT = 0x08, + /// /// Pushes the boolean value onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSHF = 0x09, + /// /// Converts the 4-bytes offset to an , and pushes it onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 4)] PUSHA = 0x0A, + /// /// The item is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSHNULL = 0x0B, + /// /// The next byte contains the number of bytes to be pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(SizePrefix = 1)] PUSHDATA1 = 0x0C, + /// /// The next two bytes contain the number of bytes to be pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(SizePrefix = 2)] PUSHDATA2 = 0x0D, + /// /// The next four bytes contain the number of bytes to be pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(SizePrefix = 4)] PUSHDATA4 = 0x0E, + /// /// The number -1 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSHM1 = 0x0F, + /// /// The number 0 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH0 = 0x10, + /// /// The number 1 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH1 = 0x11, + /// /// The number 2 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH2 = 0x12, + /// /// The number 3 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH3 = 0x13, + /// /// The number 4 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH4 = 0x14, + /// /// The number 5 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH5 = 0x15, + /// /// The number 6 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH6 = 0x16, + /// /// The number 7 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH7 = 0x17, + /// /// The number 8 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH8 = 0x18, + /// /// The number 9 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH9 = 0x19, + /// /// The number 10 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH10 = 0x1A, + /// /// The number 11 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH11 = 0x1B, + /// /// The number 12 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH12 = 0x1C, + /// /// The number 13 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH13 = 0x1D, + /// /// The number 14 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH14 = 0x1E, + /// /// The number 15 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH15 = 0x1F, + /// /// The number 16 is pushed onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PUSH16 = 0x20, @@ -161,157 +346,299 @@ public enum OpCode : byte /// /// The operation does nothing. It is intended to fill in space if opcodes are patched. + /// + /// + /// Push: 0 item(s) + /// Pop: 0 item(s) + /// /// NOP = 0x21, + /// /// Unconditionally transfers control to a target instruction. The target instruction is represented as a 1-byte signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 1)] JMP = 0x22, + /// /// Unconditionally transfers control to a target instruction. The target instruction is represented as a 4-bytes signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 4)] JMP_L = 0x23, + /// /// Transfers control to a target instruction if the value is , not , or non-zero. The target instruction is represented as a 1-byte signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// [OperandSize(Size = 1)] JMPIF = 0x24, + /// /// Transfers control to a target instruction if the value is , not , or non-zero. The target instruction is represented as a 4-bytes signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// [OperandSize(Size = 4)] JMPIF_L = 0x25, + /// /// Transfers control to a target instruction if the value is , a reference, or zero. The target instruction is represented as a 1-byte signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// [OperandSize(Size = 1)] JMPIFNOT = 0x26, + /// /// Transfers control to a target instruction if the value is , a reference, or zero. The target instruction is represented as a 4-bytes signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// [OperandSize(Size = 4)] JMPIFNOT_L = 0x27, + /// /// Transfers control to a target instruction if two values are equal. The target instruction is represented as a 1-byte signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// [OperandSize(Size = 1)] JMPEQ = 0x28, + /// /// Transfers control to a target instruction if two values are equal. The target instruction is represented as a 4-bytes signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// [OperandSize(Size = 4)] JMPEQ_L = 0x29, + /// /// Transfers control to a target instruction when two values are not equal. The target instruction is represented as a 1-byte signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// [OperandSize(Size = 1)] JMPNE = 0x2A, + /// /// Transfers control to a target instruction when two values are not equal. The target instruction is represented as a 4-bytes signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// [OperandSize(Size = 4)] JMPNE_L = 0x2B, + /// /// Transfers control to a target instruction if the first value is greater than the second value. The target instruction is represented as a 1-byte signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// [OperandSize(Size = 1)] JMPGT = 0x2C, + /// /// Transfers control to a target instruction if the first value is greater than the second value. The target instruction is represented as a 4-bytes signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// [OperandSize(Size = 4)] JMPGT_L = 0x2D, + /// /// Transfers control to a target instruction if the first value is greater than or equal to the second value. The target instruction is represented as a 1-byte signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// [OperandSize(Size = 1)] JMPGE = 0x2E, + /// /// Transfers control to a target instruction if the first value is greater than or equal to the second value. The target instruction is represented as a 4-bytes signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// [OperandSize(Size = 4)] JMPGE_L = 0x2F, + /// /// Transfers control to a target instruction if the first value is less than the second value. The target instruction is represented as a 1-byte signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// [OperandSize(Size = 1)] JMPLT = 0x30, + /// /// Transfers control to a target instruction if the first value is less than the second value. The target instruction is represented as a 4-bytes signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// [OperandSize(Size = 4)] JMPLT_L = 0x31, + /// /// Transfers control to a target instruction if the first value is less than or equal to the second value. The target instruction is represented as a 1-byte signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// [OperandSize(Size = 1)] JMPLE = 0x32, + /// /// Transfers control to a target instruction if the first value is less than or equal to the second value. The target instruction is represented as a 4-bytes signed offset from the beginning of the current instruction. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// [OperandSize(Size = 4)] JMPLE_L = 0x33, + /// /// Calls the function at the target address which is represented as a 1-byte signed offset from the beginning of the current instruction. /// [OperandSize(Size = 1)] CALL = 0x34, + /// /// Calls the function at the target address which is represented as a 4-bytes signed offset from the beginning of the current instruction. /// [OperandSize(Size = 4)] CALL_L = 0x35, + /// /// Pop the address of a function from the stack, and call the function. /// CALLA = 0x36, + /// /// Calls the function which is described by the token. /// [OperandSize(Size = 2)] CALLT = 0x37, + /// /// It turns the vm state to FAULT immediately, and cannot be caught. + /// + /// + /// Push: 0 item(s) + /// Pop: 0 item(s) + /// /// ABORT = 0x38, + /// /// Pop the top value of the stack. If it's false, exit vm execution and set vm state to FAULT. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// ASSERT = 0x39, + /// /// Pop the top value of the stack, and throw it. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// THROW = 0x3A, + /// /// TRY CatchOffset(sbyte) FinallyOffset(sbyte). If there's no catch body, set CatchOffset 0. If there's no finally body, set FinallyOffset 0. /// [OperandSize(Size = 2)] TRY = 0x3B, + /// /// TRY_L CatchOffset(int) FinallyOffset(int). If there's no catch body, set CatchOffset 0. If there's no finally body, set FinallyOffset 0. /// [OperandSize(Size = 8)] TRY_L = 0x3C, + /// /// Ensures that the appropriate surrounding finally blocks are executed. And then unconditionally transfers control to the specific target instruction, represented as a 1-byte signed offset from the beginning of the current instruction. /// [OperandSize(Size = 1)] ENDTRY = 0x3D, + /// /// Ensures that the appropriate surrounding finally blocks are executed. And then unconditionally transfers control to the specific target instruction, represented as a 4-byte signed offset from the beginning of the current instruction. /// [OperandSize(Size = 4)] ENDTRY_L = 0x3E, + /// - /// End finally, If no exception happen or be catched, vm will jump to the target instruction of ENDTRY/ENDTRY_L. Otherwise vm will rethrow the exception to upper layer. + /// End finally, If no exception happen or be catched, vm will jump to the target instruction of ENDTRY/ENDTRY_L. Otherwise, vm will rethrow the exception to upper layer. /// ENDFINALLY = 0x3F, + /// /// Returns from the current method. /// RET = 0x40, + /// /// Calls to an interop service. /// @@ -324,62 +651,164 @@ public enum OpCode : byte /// /// Puts the number of stack items onto the stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// DEPTH = 0x43, + /// /// Removes the top stack item. + /// + /// a b c -> a b + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// DROP = 0x45, + /// /// Removes the second-to-top stack item. + /// + /// a b c -> a c + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// NIP = 0x46, + /// /// The item n back in the main stack is removed. + /// + /// + /// Push: 0 item(s) + /// Pop: n+1 item(s) + /// /// XDROP = 0x48, + /// /// Clear the stack /// CLEAR = 0x49, + /// /// Duplicates the top stack item. + /// + /// a b c -> a b c c + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// DUP = 0x4A, + /// /// Copies the second-to-top stack item to the top. + /// + /// a b c -> a b c b + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// OVER = 0x4B, + /// /// The item n back in the stack is copied to the top. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// PICK = 0x4D, + /// /// The item at the top of the stack is copied and inserted before the second-to-top item. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// TUCK = 0x4E, + /// /// The top two items on the stack are swapped. + /// + /// a b -> b a + /// + /// + /// Push: 0 item(s) + /// Pop: 0 item(s) + /// /// SWAP = 0x50, + /// /// The top three items on the stack are rotated to the left. + /// + /// a b c -> b c a + /// + /// + /// Push: 0 item(s) + /// Pop: 0 item(s) + /// /// ROT = 0x51, + /// /// The item n back in the stack is moved to the top. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// ROLL = 0x52, + /// /// Reverse the order of the top 3 items on the stack. + /// + /// a b c -> c b a + /// + /// + /// Push: 0 item(s) + /// Pop: 0 item(s) + /// /// REVERSE3 = 0x53, + /// /// Reverse the order of the top 4 items on the stack. + /// + /// a b c d -> d c b a + /// + /// + /// + /// Push: 0 item(s) + /// Pop: 0 item(s) + /// /// REVERSE4 = 0x54, + /// /// Pop the number N on the stack, and reverse the order of the top N items on the stack. + /// + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// REVERSEN = 0x55, @@ -389,209 +818,503 @@ public enum OpCode : byte /// /// Initialize the static field list for the current execution context. + /// + /// + /// Push: 0 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 1)] INITSSLOT = 0x56, + /// /// Initialize the argument slot and the local variable list for the current execution context. /// [OperandSize(Size = 2)] INITSLOT = 0x57, + /// /// Loads the static field at index 0 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDSFLD0 = 0x58, + /// /// Loads the static field at index 1 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDSFLD1 = 0x59, + /// /// Loads the static field at index 2 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDSFLD2 = 0x5A, + /// /// Loads the static field at index 3 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDSFLD3 = 0x5B, + /// /// Loads the static field at index 4 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDSFLD4 = 0x5C, + /// /// Loads the static field at index 5 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDSFLD5 = 0x5D, + /// /// Loads the static field at index 6 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDSFLD6 = 0x5E, + /// /// Loads the static field at a specified index onto the evaluation stack. The index is represented as a 1-byte unsigned integer. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 1)] LDSFLD = 0x5F, + /// /// Stores the value on top of the evaluation stack in the static field list at index 0. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STSFLD0 = 0x60, + /// /// Stores the value on top of the evaluation stack in the static field list at index 1. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STSFLD1 = 0x61, + /// /// Stores the value on top of the evaluation stack in the static field list at index 2. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STSFLD2 = 0x62, + /// /// Stores the value on top of the evaluation stack in the static field list at index 3. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STSFLD3 = 0x63, + /// /// Stores the value on top of the evaluation stack in the static field list at index 4. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STSFLD4 = 0x64, + /// /// Stores the value on top of the evaluation stack in the static field list at index 5. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STSFLD5 = 0x65, + /// /// Stores the value on top of the evaluation stack in the static field list at index 6. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STSFLD6 = 0x66, + /// /// Stores the value on top of the evaluation stack in the static field list at a specified index. The index is represented as a 1-byte unsigned integer. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// [OperandSize(Size = 1)] STSFLD = 0x67, + /// /// Loads the local variable at index 0 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDLOC0 = 0x68, + /// /// Loads the local variable at index 1 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDLOC1 = 0x69, + /// /// Loads the local variable at index 2 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDLOC2 = 0x6A, + /// /// Loads the local variable at index 3 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDLOC3 = 0x6B, + /// /// Loads the local variable at index 4 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDLOC4 = 0x6C, + /// /// Loads the local variable at index 5 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDLOC5 = 0x6D, + /// /// Loads the local variable at index 6 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDLOC6 = 0x6E, + /// /// Loads the local variable at a specified index onto the evaluation stack. The index is represented as a 1-byte unsigned integer. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 1)] LDLOC = 0x6F, + /// /// Stores the value on top of the evaluation stack in the local variable list at index 0. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STLOC0 = 0x70, + /// /// Stores the value on top of the evaluation stack in the local variable list at index 1. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STLOC1 = 0x71, + /// /// Stores the value on top of the evaluation stack in the local variable list at index 2. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STLOC2 = 0x72, + /// /// Stores the value on top of the evaluation stack in the local variable list at index 3. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STLOC3 = 0x73, + /// /// Stores the value on top of the evaluation stack in the local variable list at index 4. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STLOC4 = 0x74, + /// /// Stores the value on top of the evaluation stack in the local variable list at index 5. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STLOC5 = 0x75, + /// /// Stores the value on top of the evaluation stack in the local variable list at index 6. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STLOC6 = 0x76, + /// /// Stores the value on top of the evaluation stack in the local variable list at a specified index. The index is represented as a 1-byte unsigned integer. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// [OperandSize(Size = 1)] STLOC = 0x77, + /// /// Loads the argument at index 0 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDARG0 = 0x78, + /// /// Loads the argument at index 1 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDARG1 = 0x79, + /// /// Loads the argument at index 2 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDARG2 = 0x7A, + /// /// Loads the argument at index 3 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDARG3 = 0x7B, + /// /// Loads the argument at index 4 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDARG4 = 0x7C, + /// /// Loads the argument at index 5 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDARG5 = 0x7D, + /// /// Loads the argument at index 6 onto the evaluation stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// LDARG6 = 0x7E, + /// /// Loads the argument at a specified index onto the evaluation stack. The index is represented as a 1-byte unsigned integer. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// [OperandSize(Size = 1)] LDARG = 0x7F, + /// /// Stores the value on top of the evaluation stack in the argument slot at index 0. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STARG0 = 0x80, + /// /// Stores the value on top of the evaluation stack in the argument slot at index 1. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STARG1 = 0x81, + /// /// Stores the value on top of the evaluation stack in the argument slot at index 2. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STARG2 = 0x82, + /// /// Stores the value on top of the evaluation stack in the argument slot at index 3. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STARG3 = 0x83, + /// /// Stores the value on top of the evaluation stack in the argument slot at index 4. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STARG4 = 0x84, + /// /// Stores the value on top of the evaluation stack in the argument slot at index 5. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STARG5 = 0x85, + /// /// Stores the value on top of the evaluation stack in the argument slot at index 6. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// STARG6 = 0x86, + /// /// Stores the value on top of the evaluation stack in the argument slot at a specified index. The index is represented as a 1-byte unsigned integer. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// [OperandSize(Size = 1)] STARG = 0x87, @@ -602,26 +1325,74 @@ public enum OpCode : byte /// /// Creates a new and pushes it onto the stack. + /// + /// new Buffer(a) + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// NEWBUFFER = 0x88, + /// /// Copies a range of bytes from one to another. + /// Using this opcode will require to dup the destination buffer. + /// + /// c.Slice(d, e).CopyTo(a.InnerBuffer.Span[b..]); + /// + /// + /// Push: 0 item(s) + /// Pop: 5 item(s) + /// /// MEMCPY = 0x89, + /// /// Concatenates two strings. + /// + /// a.concat(b) + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// CAT = 0x8B, + /// /// Returns a section of a string. + /// + /// a.Slice(b, c) + /// + /// + /// Push: 1 item(s) + /// Pop: 3 item(s) + /// /// SUBSTR = 0x8C, + /// /// Keeps only characters left of the specified point in a string. + /// + /// a[..b] + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// LEFT = 0x8D, + /// /// Keeps only characters right of the specified point in a string. + /// + /// a[^b..^0] + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// RIGHT = 0x8E, @@ -630,27 +1401,74 @@ public enum OpCode : byte #region Bitwise logic /// - /// Flips all of the bits in the input. + /// Flips all the bits in the input. + /// + /// ~a + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// INVERT = 0x90, + /// /// Boolean and between each bit in the inputs. + /// + /// a&b + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// AND = 0x91, + /// /// Boolean or between each bit in the inputs. + /// + /// a|b + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// OR = 0x92, + /// /// Boolean exclusive or between each bit in the inputs. + /// + /// a^b + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// XOR = 0x93, + /// /// Returns 1 if the inputs are exactly equal, 0 otherwise. + /// + /// a.Equals(b) + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// EQUAL = 0x97, + /// /// Returns 1 if the inputs are not equal, 0 otherwise. + /// + /// !a.Equals(b) + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// NOTEQUAL = 0x98, @@ -660,118 +1478,339 @@ public enum OpCode : byte /// /// Puts the sign of top stack item on top of the main stack. If value is negative, put -1; if positive, put 1; if value is zero, put 0. + /// + /// a.Sign + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// SIGN = 0x99, + /// /// The input is made positive. + /// + /// abs(a) + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// ABS = 0x9A, + /// /// The sign of the input is flipped. + /// + /// -a + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// NEGATE = 0x9B, + /// /// 1 is added to the input. + /// + /// a+1 + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// INC = 0x9C, + /// /// 1 is subtracted from the input. + /// + /// a-1 + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// DEC = 0x9D, + /// /// a is added to b. + /// + /// a+b + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// ADD = 0x9E, + /// /// b is subtracted from a. + /// + /// a-b + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// SUB = 0x9F, + /// /// a is multiplied by b. + /// + /// a*b + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// MUL = 0xA0, + /// /// a is divided by b. + /// + /// a/b + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// DIV = 0xA1, + /// /// Returns the remainder after dividing a by b. + /// + /// a%b + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// MOD = 0xA2, + /// /// The result of raising value to the exponent power. + /// + /// a^b + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// POW = 0xA3, + /// /// Returns the square root of a specified number. + /// + /// sqrt(a) + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// SQRT = 0xA4, + /// /// Performs modulus division on a number multiplied by another number. + /// + /// a*b%c + /// + /// + /// Push: 1 item(s) + /// Pop: 3 item(s) + /// /// MODMUL = 0xA5, + /// /// Performs modulus division on a number raised to the power of another number. If the exponent is -1, it will have the calculation of the modular inverse. + /// + /// modpow(a, b, c) + /// + /// + /// Push: 1 item(s) + /// Pop: 3 item(s) + /// /// MODPOW = 0xA6, + /// /// Shifts a left b bits, preserving sign. + /// + /// a<<b + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// SHL = 0xA8, + /// /// Shifts a right b bits, preserving sign. + /// + /// a>>b + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// SHR = 0xA9, + /// - /// If the input is 0 or 1, it is flipped. Otherwise the output will be 0. + /// If the input is 0 or 1, it is flipped. Otherwise, the output will be 0. + /// + /// !a + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// NOT = 0xAA, + /// - /// If both a and b are not 0, the output is 1. Otherwise 0. + /// If both a and b are not 0, the output is 1. Otherwise, 0. + /// + /// b && a + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// BOOLAND = 0xAB, + /// - /// If a or b is not 0, the output is 1. Otherwise 0. + /// If a or b is not 0, the output is 1. Otherwise, 0. + /// + /// b || a + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// BOOLOR = 0xAC, + /// /// Returns 0 if the input is 0. 1 otherwise. + /// + /// a != 0 + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// NZ = 0xB1, + /// /// Returns 1 if the numbers are equal, 0 otherwise. + /// + /// b == a + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// NUMEQUAL = 0xB3, + /// /// Returns 1 if the numbers are not equal, 0 otherwise. + /// + /// b != a + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// NUMNOTEQUAL = 0xB4, + /// /// Returns 1 if a is less than b, 0 otherwise. + /// + /// b>a + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// LT = 0xB5, + /// /// Returns 1 if a is less than or equal to b, 0 otherwise. + /// + /// b>=a + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// LE = 0xB6, + /// /// Returns 1 if a is greater than b, 0 otherwise. + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// GT = 0xB7, + /// /// Returns 1 if a is greater than or equal to b, 0 otherwise. + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// GE = 0xB8, + /// - /// Returns the smaller of a and b. + /// Returns the smallest of a and b. + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// MIN = 0xB9, + /// - /// Returns the larger of a and b. + /// Returns the largest of a and b. + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// MAX = 0xBA, + /// /// Returns 1 if x is within the specified range (left-inclusive), 0 otherwise. + /// + /// + /// Push: 1 item(s) + /// Pop: 3 item(s) + /// /// WITHIN = 0xBB, @@ -781,87 +1820,217 @@ public enum OpCode : byte /// /// A value n is taken from top of main stack. The next n*2 items on main stack are removed, put inside n-sized map and this map is put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 2n+1 item(s) + /// /// PACKMAP = 0xBE, + /// /// A value n is taken from top of main stack. The next n items on main stack are removed, put inside n-sized struct and this struct is put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: n+1 item(s) + /// /// PACKSTRUCT = 0xBF, + /// /// A value n is taken from top of main stack. The next n items on main stack are removed, put inside n-sized array and this array is put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: n+1 item(s) + /// /// PACK = 0xC0, + /// /// A collection is removed from top of the main stack. Its elements are put on top of the main stack (in reverse order) and the collection size is also put on main stack. + /// + /// + /// Push: 2n+1 or n+1 item(s) + /// Pop: 1 item(s) + /// /// UNPACK = 0xC1, + /// /// An empty array (with size 0) is put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// NEWARRAY0 = 0xC2, + /// /// A value n is taken from top of main stack. A null-filled array with size n is put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// NEWARRAY = 0xC3, + /// /// A value n is taken from top of main stack. An array of type T with size n is put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// [OperandSize(Size = 1)] NEWARRAY_T = 0xC4, + /// /// An empty struct (with size 0) is put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// NEWSTRUCT0 = 0xC5, + /// /// A value n is taken from top of main stack. A zero-filled struct with size n is put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// NEWSTRUCT = 0xC6, + /// /// A Map is created and put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 0 item(s) + /// /// NEWMAP = 0xC8, + /// /// An array is removed from top of the main stack. Its size is put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// SIZE = 0xCA, + /// /// An input index n (or key) and an array (or map) are removed from the top of the main stack. Puts True on top of main stack if array[n] (or map[n]) exist, and False otherwise. + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// HASKEY = 0xCB, + /// /// A map is taken from top of the main stack. The keys of this map are put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// KEYS = 0xCC, + /// /// A map is taken from top of the main stack. The values of this map are put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// VALUES = 0xCD, + /// /// An input index n (or key) and an array (or map) are taken from main stack. Element array[n] (or map[n]) is put on top of the main stack. + /// + /// + /// Push: 1 item(s) + /// Pop: 2 item(s) + /// /// PICKITEM = 0xCE, + /// /// The item on top of main stack is removed and appended to the second item on top of the main stack. + /// When we use this opcode, we should dup the second item on top of the main stack before using it. + /// + /// a a b -> a.concat(b) + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// APPEND = 0xCF, + /// /// A value v, index n (or key) and an array (or map) are taken from main stack. Attribution array[n]=v (or map[n]=v) is performed. + /// + /// + /// Push: 1 item(s) + /// Pop: 3 item(s) + /// /// SETITEM = 0xD0, + /// /// An array is removed from the top of the main stack and its elements are reversed. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// REVERSEITEMS = 0xD1, + /// /// An input index n (or key) and an array (or map) are removed from the top of the main stack. Element array[n] (or map[n]) is removed. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// REMOVE = 0xD2, + /// /// Remove all the items from the compound-type. + /// Using this opcode will need to dup the compound-type before using it. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// CLEARITEMS = 0xD3, + /// /// Remove the last element from an array, and push it onto the stack. + /// Using this opcode will need to dup the array before using it. + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// POPITEM = 0xD4, @@ -872,16 +2041,33 @@ public enum OpCode : byte /// /// Returns if the input is ; /// otherwise. + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// ISNULL = 0xD8, + /// /// Returns if the top item of the stack is of the specified type; /// otherwise. + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// [OperandSize(Size = 1)] ISTYPE = 0xD9, + /// /// Converts the top item of the stack to the specified type. + /// + /// + /// Push: 1 item(s) + /// Pop: 1 item(s) + /// /// [OperandSize(Size = 1)] CONVERT = 0xDB, @@ -893,11 +2079,24 @@ public enum OpCode : byte /// /// Pops the top stack item. Then, turns the vm state to FAULT immediately, and cannot be caught. The top stack /// value is used as reason. + /// + /// new Exception(a) + /// + /// + /// Push: 0 item(s) + /// Pop: 1 item(s) + /// /// ABORTMSG = 0xE0, + /// /// Pops the top two stack items. If the second-to-top stack value is false, exits the vm execution and sets the /// vm state to FAULT. In this case, the top stack value is used as reason for the exit. Otherwise, it is ignored. + /// + /// + /// Push: 0 item(s) + /// Pop: 2 item(s) + /// /// ASSERTMSG = 0xE1