// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package runtime

import (
	"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/gas"
	"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/mm"
	"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/params"
)

type (
	// ExecutionFunc 指令执行函数，每个操作指令对应一个实现，它实现了指令的具体操作逻辑
	ExecutionFunc func(pc *uint64, env *EVM, contract *Contract, memory *mm.Memory, stack *mm.Stack) ([]byte, error)
)

// Operation 定义指令操作的结构提
type Operation struct {
	// Execute 指令的具体操作逻辑
	Execute ExecutionFunc

	// GasCost 计算当前指令执行所需消耗的Gas
	GasCost gas.CalcGasFunc

	// ValidateStack 检查内存栈中的数据是否满足本操作执行的要求
	ValidateStack mm.StackValidationFunc

	// MemorySize 计算本次操作所需要的内存大小
	MemorySize mm.MemorySizeFunc

	// Halts   是否需要暂停（将会结束本合约后面操作的执行）
	Halts bool
	// Jumps   是否需要执行跳转（此种情况下PC不递增）
	Jumps bool
	// Writes  是否涉及到修改状态操作（在合约委托调用的情况下，此操作非法，将会抛异常）
	Writes bool
	// Valid   是否为有效操作
	Valid bool
	// Reverts 是否恢复原始状态（强制暂停，将会结束本合约后面操作的执行）
	Reverts bool
	// Returns 是否返回
	Returns bool
}

var (
	// ConstantinopleInstructionSet 对应EVM不同版本的指令集，从上往下，从旧版本到新版本，
	// 新版本包含旧版本的指令集（目前直接使用康士坦丁堡指令集）
	ConstantinopleInstructionSet = NewConstantinopleInstructionSet()
)

// NewConstantinopleInstructionSet 康士坦丁堡 版本支持的指令集
func NewConstantinopleInstructionSet() [256]Operation {
	instructionSet := NewByzantiumInstructionSet()
	instructionSet[SHL] = Operation{
		Execute:       opSHL,
		GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
		ValidateStack: mm.MakeStackFunc(2, 1),
		Valid:         true,
	}
	instructionSet[SHR] = Operation{
		Execute:       opSHR,
		GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
		ValidateStack: mm.MakeStackFunc(2, 1),
		Valid:         true,
	}
	instructionSet[SAR] = Operation{
		Execute:       opSAR,
		GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
		ValidateStack: mm.MakeStackFunc(2, 1),
		Valid:         true,
	}
	return instructionSet
}

// NewByzantiumInstructionSet 拜占庭 版本支持的指令集
func NewByzantiumInstructionSet() [256]Operation {
	instructionSet := NewHomesteadInstructionSet()
	instructionSet[STATICCALL] = Operation{
		Execute:       opStaticCall,
		GasCost:       gas.StaticCall,
		ValidateStack: mm.MakeStackFunc(6, 1),
		MemorySize:    mm.MemoryStaticCall,
		Valid:         true,
		Returns:       true,
	}
	instructionSet[RETURNDATASIZE] = Operation{
		Execute:       opReturnDataSize,
		GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
		ValidateStack: mm.MakeStackFunc(0, 1),
		Valid:         true,
	}
	instructionSet[RETURNDATACOPY] = Operation{
		Execute:       opReturnDataCopy,
		GasCost:       gas.ReturnDataCopy,
		ValidateStack: mm.MakeStackFunc(3, 0),
		MemorySize:    mm.MemoryReturnDataCopy,
		Valid:         true,
	}
	instructionSet[REVERT] = Operation{
		Execute:       opRevert,
		GasCost:       gas.Revert,
		ValidateStack: mm.MakeStackFunc(2, 0),
		MemorySize:    mm.MemoryRevert,
		Valid:         true,
		Reverts:       true,
		Returns:       true,
	}
	return instructionSet
}

// NewHomesteadInstructionSet 家园 版本支持的指令集
func NewHomesteadInstructionSet() [256]Operation {
	instructionSet := NewFrontierInstructionSet()
	instructionSet[DELEGATECALL] = Operation{
		Execute:       opDelegateCall,
		GasCost:       gas.DelegateCall,
		ValidateStack: mm.MakeStackFunc(6, 1),
		MemorySize:    mm.MemoryDelegateCall,
		Valid:         true,
		Returns:       true,
	}
	return instructionSet
}

// NewFrontierInstructionSet 边境 版本支持的指令集
func NewFrontierInstructionSet() [256]Operation {
	return [256]Operation{
		STOP: {
			Execute:       opStop,
			GasCost:       gas.ConstGasFunc(0),
			ValidateStack: mm.MakeStackFunc(0, 0),
			Halts:         true,
			Valid:         true,
		},
		ADD: {
			Execute:       opAdd,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		MUL: {
			Execute:       opMul,
			GasCost:       gas.ConstGasFunc(gas.GasFastStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		SUB: {
			Execute:       opSub,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		DIV: {
			Execute:       opDiv,
			GasCost:       gas.ConstGasFunc(gas.GasFastStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		SDIV: {
			Execute:       opSdiv,
			GasCost:       gas.ConstGasFunc(gas.GasFastStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		MOD: {
			Execute:       opMod,
			GasCost:       gas.ConstGasFunc(gas.GasFastStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		SMOD: {
			Execute:       opSmod,
			GasCost:       gas.ConstGasFunc(gas.GasFastStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		ADDMOD: {
			Execute:       opAddmod,
			GasCost:       gas.ConstGasFunc(gas.GasMidStep),
			ValidateStack: mm.MakeStackFunc(3, 1),
			Valid:         true,
		},
		MULMOD: {
			Execute:       opMulmod,
			GasCost:       gas.ConstGasFunc(gas.GasMidStep),
			ValidateStack: mm.MakeStackFunc(3, 1),
			Valid:         true,
		},
		EXP: {
			Execute:       opExp,
			GasCost:       gas.Exp,
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		SIGNEXTEND: {
			Execute:       opSignExtend,
			GasCost:       gas.ConstGasFunc(gas.GasFastStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		LT: {
			Execute:       opLt,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		GT: {
			Execute:       opGt,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		SLT: {
			Execute:       opSlt,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		SGT: {
			Execute:       opSgt,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		EQ: {
			Execute:       opEq,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		ISZERO: {
			Execute:       opIszero,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(1, 1),
			Valid:         true,
		},
		AND: {
			Execute:       opAnd,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		XOR: {
			Execute:       opXor,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		OR: {
			Execute:       opOr,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		NOT: {
			Execute:       opNot,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(1, 1),
			Valid:         true,
		},
		BYTE: {
			Execute:       opByte,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(2, 1),
			Valid:         true,
		},
		SHA3: {
			Execute:       opSha3,
			GasCost:       gas.Sha3,
			ValidateStack: mm.MakeStackFunc(2, 1),
			MemorySize:    mm.MemorySha3,
			Valid:         true,
		},
		ADDRESS: {
			Execute:       opAddress,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		BALANCE: {
			Execute:       opBalance,
			GasCost:       gas.Balance,
			ValidateStack: mm.MakeStackFunc(1, 1),
			Valid:         true,
		},
		ORIGIN: {
			Execute:       opOrigin,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		CALLER: {
			Execute:       opCaller,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		CALLVALUE: {
			Execute:       opCallValue,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		CALLDATALOAD: {
			Execute:       opCallDataLoad,
			GasCost:       gas.ConstGasFunc(gas.GasFastestStep),
			ValidateStack: mm.MakeStackFunc(1, 1),
			Valid:         true,
		},
		CALLDATASIZE: {
			Execute:       opCallDataSize,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		CALLDATACOPY: {
			Execute:       opCallDataCopy,
			GasCost:       gas.CallDataCopy,
			ValidateStack: mm.MakeStackFunc(3, 0),
			MemorySize:    mm.MemoryCallDataCopy,
			Valid:         true,
		},
		CODESIZE: {
			Execute:       opCodeSize,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		CODECOPY: {
			Execute:       opCodeCopy,
			GasCost:       gas.CodeCopy,
			ValidateStack: mm.MakeStackFunc(3, 0),
			MemorySize:    mm.MemoryCodeCopy,
			Valid:         true,
		},
		GASPRICE: {
			Execute:       opGasprice,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		EXTCODESIZE: {
			Execute:       opExtCodeSize,
			GasCost:       gas.ExtCodeSize,
			ValidateStack: mm.MakeStackFunc(1, 1),
			Valid:         true,
		},
		EXTCODECOPY: {
			Execute:       opExtCodeCopy,
			GasCost:       gas.ExtCodeCopy,
			ValidateStack: mm.MakeStackFunc(4, 0),
			MemorySize:    mm.MemoryExtCodeCopy,
			Valid:         true,
		},
		BLOCKHASH: {
			Execute:       opBlockhash,
			GasCost:       gas.ConstGasFunc(gas.GasExtStep),
			ValidateStack: mm.MakeStackFunc(1, 1),
			Valid:         true,
		},
		COINBASE: {
			Execute:       opCoinbase,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		TIMESTAMP: {
			Execute:       opTimestamp,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		NUMBER: {
			Execute:       opNumber,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		DIFFICULTY: {
			Execute:       opDifficulty,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		GASLIMIT: {
			Execute:       opGasLimit,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		POP: {
			Execute:       opPop,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(1, 0),
			Valid:         true,
		},
		MLOAD: {
			Execute:       opMload,
			GasCost:       gas.MLoad,
			ValidateStack: mm.MakeStackFunc(1, 1),
			MemorySize:    mm.MemoryMLoad,
			Valid:         true,
		},
		MSTORE: {
			Execute:       opMstore,
			GasCost:       gas.MStore,
			ValidateStack: mm.MakeStackFunc(2, 0),
			MemorySize:    mm.MemoryMStore,
			Valid:         true,
		},
		MSTORE8: {
			Execute:       opMstore8,
			GasCost:       gas.MStore8,
			MemorySize:    mm.MemoryMStore8,
			ValidateStack: mm.MakeStackFunc(2, 0),

			Valid: true,
		},
		SLOAD: {
			Execute:       opSload,
			GasCost:       gas.SLoad,
			ValidateStack: mm.MakeStackFunc(1, 1),
			Valid:         true,
		},
		SSTORE: {
			Execute:       opSstore,
			GasCost:       gas.SStore,
			ValidateStack: mm.MakeStackFunc(2, 0),
			Valid:         true,
			Writes:        true,
		},
		JUMP: {
			Execute:       opJump,
			GasCost:       gas.ConstGasFunc(gas.GasMidStep),
			ValidateStack: mm.MakeStackFunc(1, 0),
			Jumps:         true,
			Valid:         true,
		},
		JUMPI: {
			Execute:       opJumpi,
			GasCost:       gas.ConstGasFunc(gas.GasSlowStep),
			ValidateStack: mm.MakeStackFunc(2, 0),
			Jumps:         true,
			Valid:         true,
		},
		PC: {
			Execute:       opPc,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		MSIZE: {
			Execute:       opMsize,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		GAS: {
			Execute:       opGas,
			GasCost:       gas.ConstGasFunc(gas.GasQuickStep),
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		JUMPDEST: {
			Execute:       opJumpdest,
			GasCost:       gas.ConstGasFunc(params.JumpdestGas),
			ValidateStack: mm.MakeStackFunc(0, 0),
			Valid:         true,
		},
		PUSH1: {
			Execute:       makePush(1, 1),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH2: {
			Execute:       makePush(2, 2),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH3: {
			Execute:       makePush(3, 3),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH4: {
			Execute:       makePush(4, 4),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH5: {
			Execute:       makePush(5, 5),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH6: {
			Execute:       makePush(6, 6),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH7: {
			Execute:       makePush(7, 7),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH8: {
			Execute:       makePush(8, 8),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH9: {
			Execute:       makePush(9, 9),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH10: {
			Execute:       makePush(10, 10),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH11: {
			Execute:       makePush(11, 11),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH12: {
			Execute:       makePush(12, 12),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH13: {
			Execute:       makePush(13, 13),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH14: {
			Execute:       makePush(14, 14),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH15: {
			Execute:       makePush(15, 15),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH16: {
			Execute:       makePush(16, 16),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH17: {
			Execute:       makePush(17, 17),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH18: {
			Execute:       makePush(18, 18),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH19: {
			Execute:       makePush(19, 19),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH20: {
			Execute:       makePush(20, 20),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH21: {
			Execute:       makePush(21, 21),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH22: {
			Execute:       makePush(22, 22),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH23: {
			Execute:       makePush(23, 23),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH24: {
			Execute:       makePush(24, 24),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH25: {
			Execute:       makePush(25, 25),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH26: {
			Execute:       makePush(26, 26),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH27: {
			Execute:       makePush(27, 27),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH28: {
			Execute:       makePush(28, 28),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH29: {
			Execute:       makePush(29, 29),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH30: {
			Execute:       makePush(30, 30),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH31: {
			Execute:       makePush(31, 31),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		PUSH32: {
			Execute:       makePush(32, 32),
			GasCost:       gas.Push,
			ValidateStack: mm.MakeStackFunc(0, 1),
			Valid:         true,
		},
		DUP1: {
			Execute:       makeDup(1),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(1),
			Valid:         true,
		},
		DUP2: {
			Execute:       makeDup(2),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(2),
			Valid:         true,
		},
		DUP3: {
			Execute:       makeDup(3),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(3),
			Valid:         true,
		},
		DUP4: {
			Execute:       makeDup(4),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(4),
			Valid:         true,
		},
		DUP5: {
			Execute:       makeDup(5),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(5),
			Valid:         true,
		},
		DUP6: {
			Execute:       makeDup(6),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(6),
			Valid:         true,
		},
		DUP7: {
			Execute:       makeDup(7),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(7),
			Valid:         true,
		},
		DUP8: {
			Execute:       makeDup(8),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(8),
			Valid:         true,
		},
		DUP9: {
			Execute:       makeDup(9),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(9),
			Valid:         true,
		},
		DUP10: {
			Execute:       makeDup(10),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(10),
			Valid:         true,
		},
		DUP11: {
			Execute:       makeDup(11),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(11),
			Valid:         true,
		},
		DUP12: {
			Execute:       makeDup(12),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(12),
			Valid:         true,
		},
		DUP13: {
			Execute:       makeDup(13),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(13),
			Valid:         true,
		},
		DUP14: {
			Execute:       makeDup(14),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(14),
			Valid:         true,
		},
		DUP15: {
			Execute:       makeDup(15),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(15),
			Valid:         true,
		},
		DUP16: {
			Execute:       makeDup(16),
			GasCost:       gas.Dup,
			ValidateStack: mm.MakeDupStackFunc(16),
			Valid:         true,
		},
		SWAP1: {
			Execute:       makeSwap(1),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(2),
			Valid:         true,
		},
		SWAP2: {
			Execute:       makeSwap(2),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(3),
			Valid:         true,
		},
		SWAP3: {
			Execute:       makeSwap(3),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(4),
			Valid:         true,
		},
		SWAP4: {
			Execute:       makeSwap(4),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(5),
			Valid:         true,
		},
		SWAP5: {
			Execute:       makeSwap(5),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(6),
			Valid:         true,
		},
		SWAP6: {
			Execute:       makeSwap(6),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(7),
			Valid:         true,
		},
		SWAP7: {
			Execute:       makeSwap(7),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(8),
			Valid:         true,
		},
		SWAP8: {
			Execute:       makeSwap(8),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(9),
			Valid:         true,
		},
		SWAP9: {
			Execute:       makeSwap(9),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(10),
			Valid:         true,
		},
		SWAP10: {
			Execute:       makeSwap(10),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(11),
			Valid:         true,
		},
		SWAP11: {
			Execute:       makeSwap(11),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(12),
			Valid:         true,
		},
		SWAP12: {
			Execute:       makeSwap(12),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(13),
			Valid:         true,
		},
		SWAP13: {
			Execute:       makeSwap(13),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(14),
			Valid:         true,
		},
		SWAP14: {
			Execute:       makeSwap(14),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(15),
			Valid:         true,
		},
		SWAP15: {
			Execute:       makeSwap(15),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(16),
			Valid:         true,
		},
		SWAP16: {
			Execute:       makeSwap(16),
			GasCost:       gas.Swap,
			ValidateStack: mm.MakeSwapStackFunc(17),
			Valid:         true,
		},
		LOG0: {
			Execute:       makeLog(0),
			GasCost:       gas.MakeGasLog(0),
			ValidateStack: mm.MakeStackFunc(2, 0),
			MemorySize:    mm.MemoryLog,
			Valid:         true,
			Writes:        true,
		},
		LOG1: {
			Execute:       makeLog(1),
			GasCost:       gas.MakeGasLog(1),
			ValidateStack: mm.MakeStackFunc(3, 0),
			MemorySize:    mm.MemoryLog,
			Valid:         true,
			Writes:        true,
		},
		LOG2: {
			Execute:       makeLog(2),
			GasCost:       gas.MakeGasLog(2),
			ValidateStack: mm.MakeStackFunc(4, 0),
			MemorySize:    mm.MemoryLog,
			Valid:         true,
			Writes:        true,
		},
		LOG3: {
			Execute:       makeLog(3),
			GasCost:       gas.MakeGasLog(3),
			ValidateStack: mm.MakeStackFunc(5, 0),
			MemorySize:    mm.MemoryLog,
			Valid:         true,
			Writes:        true,
		},
		LOG4: {
			Execute:       makeLog(4),
			GasCost:       gas.MakeGasLog(4),
			ValidateStack: mm.MakeStackFunc(6, 0),
			MemorySize:    mm.MemoryLog,
			Valid:         true,
			Writes:        true,
		},
		CREATE: {
			Execute:       opCreate,
			GasCost:       gas.Create,
			ValidateStack: mm.MakeStackFunc(3, 1),
			MemorySize:    mm.MemoryCreate,
			Valid:         true,
			Writes:        true,
			Returns:       true,
		},
		CALL: {
			Execute:       opCall,
			GasCost:       gas.Call,
			ValidateStack: mm.MakeStackFunc(7, 1),
			MemorySize:    mm.MemoryCall,
			Valid:         true,
			Returns:       true,
		},
		CALLCODE: {
			Execute:       opCallCode,
			GasCost:       gas.CallCode,
			ValidateStack: mm.MakeStackFunc(7, 1),
			MemorySize:    mm.MemoryCall,
			Valid:         true,
			Returns:       true,
		},
		RETURN: {
			Execute:       opReturn,
			GasCost:       gas.Return,
			ValidateStack: mm.MakeStackFunc(2, 0),
			MemorySize:    mm.MemoryReturn,
			Halts:         true,
			Valid:         true,
		},
		SELFDESTRUCT: {
			Execute:       opSuicide,
			GasCost:       gas.Suicide,
			ValidateStack: mm.MakeStackFunc(1, 0),
			Halts:         true,
			Valid:         true,
			Writes:        true,
		},
	}
}
