/* ILEngineer - Crummy .NET Decompiler
 * Copyright (C) 2001-2002  Jay Freeman (saurik)
*/

/*
 *        Redistribution and use in source and binary
 * forms, with or without modification, are permitted
 * provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer in the documentation
 *    and/or other materials provided with the
 *    distribution.
 * 3. The name of the author may not be used to endorse
 *    or promote products derived from this software
 *    without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef _OPERATIONS_H
#define _OPERATIONS_H

#pragma once

namespace ILEngineer {
namespace Data {

	struct OpCode {
		uint32_t mask;
		uint32_t code;
		OpCode *table;
		wcstr_t name;
	};

	static OpCode Prefix1Table[] = {
		{0xffff,	0xfe00,	NULL,			L"arglist"},
		{0xffff,	0xfe01,	NULL,			L"ceq"},
		{0xffff,	0xfe02,	NULL,			L"cgt"},
		{0xffff,	0xfe03,	NULL,			L"cgt.un"},
		{0xffff,	0xfe04,	NULL,			L"clt"},
		{0xffff,	0xfe05,	NULL,			L"clt.un"},
		{0xffff,	0xfe06,	NULL,			L"ldftn"},
		{0xffff,	0xfe07,	NULL,			L"ldvirtfn"},
		{0xffff,	0xfe08,	NULL,			NULL},
		{0xffff,	0xfe09,	NULL,			L"ldarg"},
		{0xffff,	0xfe0a,	NULL,			L"ldarga"},
		{0xffff,	0xfe0b,	NULL,			L"starg"},
		{0xffff,	0xfe0c,	NULL,			L"ldloc"},
		{0xffff,	0xfe0d,	NULL,			L"ldloca"},
		{0xffff,	0xfe0e,	NULL,			L"stloc"},
		{0xffff,	0xfe0f,	NULL,			L"localloc"},
		{0xffff,	0xfe10,	NULL,			NULL},
		{0xffff,	0xfe11,	NULL,			L"endfilter"},
		{0xffff,	0xfe12,	NULL,			L"unaligned."},
		{0xffff,	0xfe13,	NULL,			L"volatile."},
		{0xffff,	0xfe14,	NULL,			L"tail."},
		{0xffff,	0xfe15,	NULL,			L"initobj"},
		{0xffff,	0xfe16,	NULL,			NULL},
		{0xffff,	0xfe17,	NULL,			L"cpblk"},
		{0xffff,	0xfe18,	NULL,			L"initblk"},
		{0xffff,	0xfe19,	NULL,			NULL},
		{0xffff,	0xfe1a,	NULL,			L"rethrow"},
		{0xffff,	0xfe1b,	NULL,			NULL},
		{0xffff,	0xfe1c,	NULL,			L"sizeof"},
		{0xffff,	0xfe1d,	NULL,			L"refanytype"}
	};

	static OpCode GlobalTable[] = {
		// 0x00
		{0xff,		0x00,	NULL,			L"nop"},
		{0xff,		0x01,	NULL,			L"break"},
		{0xff,		0x02,	NULL,			L"ldarg.0"},
		{0xff,		0x03,	NULL,			L"ldarg.1"},
		{0xff,		0x04,	NULL,			L"ldarg.2"},
		{0xff,		0x05,	NULL,			L"ldarg.3"},
		{0xff,		0x06,	NULL,			L"ldloc.0"},
		{0xff,		0x07,	NULL,			L"ldloc.1"},
		{0xff,		0x08,	NULL,			L"ldloc.2"},
		{0xff,		0x09,	NULL,			L"ldloc.3"},
		{0xff,		0x0a,	NULL,			L"stloc.0"},
		{0xff,		0x0b,	NULL,			L"stloc.1"},
		{0xff,		0x0c,	NULL,			L"stloc.2"},
		{0xff,		0x0d,	NULL,			L"stloc.3"},
		{0xff,		0x0e,	NULL,			L"ldarg.s"},
		{0xff,		0x0f,	NULL,			L"ldarga.s"},
		// 0x10
		{0xff,		0x10,	NULL,			L"starg.s"},
		{0xff,		0x11,	NULL,			L"ldloc.s"},
		{0xff,		0x12,	NULL,			L"ldloca.s"},
		{0xff,		0x13,	NULL,			L"stloc.s"},
		{0xff,		0x14,	NULL,			L"ldnull"},
		{0xff,		0x15,	NULL,			L"ldc.i4.m1"},
		{0xff,		0x16,	NULL,			L"ldc.i4.0"},
		{0xff,		0x17,	NULL,			L"ldc.i4.1"},
		{0xff,		0x18,	NULL,			L"ldc.i4.2"},
		{0xff,		0x19,	NULL,			L"ldc.i4.3"},
		{0xff,		0x1a,	NULL,			L"ldc.i4.4"},
		{0xff,		0x1b,	NULL,			L"ldc.i4.5"},
		{0xff,		0x1c,	NULL,			L"ldc.i4.6"},
		{0xff,		0x1d,	NULL,			L"ldc.i4.7"},
		{0xff,		0x1e,	NULL,			L"ldc.i4.8"},
		{0xff,		0x1f,	NULL,			L"ldc.i4.s"},
		// 0x20
		{0xff,		0x20,	NULL,			L"ldc.i4"},
		{0xff,		0x21,	NULL,			L"ldc.i8"},
		{0xff,		0x22,	NULL,			L"ldc.r4"},
		{0xff,		0x23,	NULL,			L"ldc.r8"},
		{0xff,		0x24,	NULL,			NULL},
		{0xff,		0x25,	NULL,			L"dup"},
		{0xff,		0x26,	NULL,			L"pop"},
		{0xff,		0x27,	NULL,			L"jmp"},
		{0xff,		0x28,	NULL,			L"call"},
		{0xff,		0x29,	NULL,			L"calli"},
		{0xff,		0x2a,	NULL,			L"ret"},
		{0xff,		0x2b,	NULL,			L"br.s"},
		{0xff,		0x2c,	NULL,			L"brfalse.s"},
		{0xff,		0x2d,	NULL,			L"brtrue.s"},
		{0xff,		0x2e,	NULL,			L"beq.s"},
		{0xff,		0x2f,	NULL,			L"bge.s"},
		// 0x30
		{0xff,		0x30,	NULL,			L"bgt.s"},
		{0xff,		0x31,	NULL,			L"ble.s"},
		{0xff,		0x32,	NULL,			L"blt.s"},
		{0xff,		0x33,	NULL,			L"bne.un.s"},
		{0xff,		0x34,	NULL,			L"bge.un.s"},
		{0xff,		0x35,	NULL,			L"bgt.un.s"},
		{0xff,		0x36,	NULL,			L"ble.un.s"},
		{0xff,		0x37,	NULL,			L"blt.un.s"},
		{0xff,		0x38,	NULL,			L"br"},
		{0xff,		0x39,	NULL,			L"brfalse"},
		{0xff,		0x3a,	NULL,			L"brtrue"},
		{0xff,		0x3b,	NULL,			L"beq"},
		{0xff,		0x3c,	NULL,			L"bge"},
		{0xff,		0x3d,	NULL,			L"bgt"},
		{0xff,		0x3e,	NULL,			L"ble"},
		{0xff,		0x3f,	NULL,			L"blt"},
		// 0x40
		{0xff,		0x40,	NULL,			L"bne.un"},
		{0xff,		0x41,	NULL,			L"bge.un"},
		{0xff,		0x42,	NULL,			L"bgt.un"},
		{0xff,		0x43,	NULL,			L"ble.un"},
		{0xff,		0x44,	NULL,			L"blt.un"},
		{0xff,		0x45,	NULL,			L"switch"},
		{0xff,		0x46,	NULL,			L"ldind.i1"},
		{0xff,		0x47,	NULL,			L"ldind.u1"},
		{0xff,		0x48,	NULL,			L"ldind.i2"},
		{0xff,		0x49,	NULL,			L"ldind.u2"},
		{0xff,		0x4a,	NULL,			L"ldind.i4"},
		{0xff,		0x4b,	NULL,			L"ldind.u4"},
		{0xff,		0x4c,	NULL,			L"ldind.i8"},
		{0xff,		0x4d,	NULL,			L"ldind.i"},
		{0xff,		0x4e,	NULL,			L"ldind.r4"},
		{0xff,		0x4f,	NULL,			L"ldind.r8"},
		// 0x50
		{0xff,		0x50,	NULL,			L"ldind.ref"},
		{0xff,		0x51,	NULL,			L"stind.ref"},
		{0xff,		0x52,	NULL,			L"stind.i1"},
		{0xff,		0x53,	NULL,			L"stind.i2"},
		{0xff,		0x54,	NULL,			L"stind.i4"},
		{0xff,		0x55,	NULL,			L"stind.i8"},
		{0xff,		0x56,	NULL,			L"stind.r4"},
		{0xff,		0x57,	NULL,			L"stind.r8"},
		{0xff,		0x58,	NULL,			L"add"},
		{0xff,		0x59,	NULL,			L"sub"},
		{0xff,		0x5a,	NULL,			L"mul"},
		{0xff,		0x5b,	NULL,			L"div"},
		{0xff,		0x5c,	NULL,			L"div.un"},
		{0xff,		0x5d,	NULL,			L"rem"},
		{0xff,		0x5e,	NULL,			L"rem.un"},
		{0xff,		0x5f,	NULL,			L"and"},
		// 0x60
		{0xff,		0x60,	NULL,			L"or"},
		{0xff,		0x61,	NULL,			L"xor"},
		{0xff,		0x62,	NULL,			L"shl"},
		{0xff,		0x63,	NULL,			L"shr"},
		{0xff,		0x64,	NULL,			L"shr.un"},
		{0xff,		0x65,	NULL,			L"neg"},
		{0xff,		0x66,	NULL,			L"not"},
		{0xff,		0x67,	NULL,			L"conv.i1"},
		{0xff,		0x68,	NULL,			L"conv.i2"},
		{0xff,		0x69,	NULL,			L"conv.i4"},
		{0xff,		0x6a,	NULL,			L"conf.i8"},
		{0xff,		0x6b,	NULL,			L"conv.r4"},
		{0xff,		0x6c,	NULL,			L"conv.r8"},
		{0xff,		0x6d,	NULL,			L"conv.u4"},
		{0xff,		0x6e,	NULL,			L"conv.u8"},
		{0xff,		0x6f,	NULL,			L"callvirt"},
		// 0x70
		{0xff,		0x70,	NULL,			L"cpobj"},
		{0xff,		0x71,	NULL,			L"ldobj"},
		{0xff,		0x72,	NULL,			L"ldstr"},
		{0xff,		0x73,	NULL,			L"newobj"},
		{0xff,		0x74,	NULL,			L"castclass"},
		{0xff,		0x75,	NULL,			L"isinst"},
		{0xff,		0x76,	NULL,			L"conv.r.un"},
		{0xff,		0x77,	NULL,			NULL},
		{0xff,		0x78,	NULL,			NULL},
		{0xff,		0x79,	NULL,			L"unbox"},
		{0xff,		0x7a,	NULL,			L"throw"},
		{0xff,		0x7b,	NULL,			L"ldfld"},
		{0xff,		0x7c,	NULL,			L"ldflda"},
		{0xff,		0x7d,	NULL,			L"stfld"},
		{0xff,		0x7e,	NULL,			L"ldsfld"},
		{0xff,		0x7f,	NULL,			L"ldsflda"},
		// 0x80
		{0xff,		0x80,	NULL,			L"stsfld"},
		{0xff,		0x81,	NULL,			L"stobj"},
		{0xff,		0x82,	NULL,			L"conv.ovf.i1.un"},
		{0xff,		0x83,	NULL,			L"conv.ovf.i2.un"},
		{0xff,		0x84,	NULL,			L"conv.ovf.i4.un"},
		{0xff,		0x85,	NULL,			L"conv.ovf.i8.un"},
		{0xff,		0x86,	NULL,			L"conv.ovf.u1.un"},
		{0xff,		0x87,	NULL,			L"conv.ovf.u2.un"},
		{0xff,		0x88,	NULL,			L"conv.ovf.u4.un"},
		{0xff,		0x89,	NULL,			L"conv.ovf.u8.un"},
		{0xff,		0x8a,	NULL,			L"conv.ovf.i.un"},
		{0xff,		0x8b,	NULL,			L"conv.ovf.u.un"},
		{0xff,		0x8c,	NULL,			L"box"},
		{0xff,		0x8d,	NULL,			L"newarr"},
		{0xff,		0x8e,	NULL,			L"ldlen"},
		{0xff,		0x8f,	NULL,			L"ldelema"},
		// 0x90
		{0xff,		0x90,	NULL,			L"ldelem.i1"},
		{0xff,		0x91,	NULL,			L"ldelem.u1"},
		{0xff,		0x92,	NULL,			L"ldelem.i2"},
		{0xff,		0x93,	NULL,			L"ldelem.u2"},
		{0xff,		0x94,	NULL,			L"ldelem.i4"},
		{0xff,		0x95,	NULL,			L"ldelem.u4"},
		{0xff,		0x96,	NULL,			L"ldelem.i8"},
		{0xff,		0x97,	NULL,			L"ldelem.i"},
		{0xff,		0x98,	NULL,			L"ldelem.r4"},
		{0xff,		0x99,	NULL,			L"ldelem.r8"},
		{0xff,		0x9a,	NULL,			L"ldelem.ref"},
		{0xff,		0x9b,	NULL,			L"stelem.i"},
		{0xff,		0x9c,	NULL,			L"stelem.i1"},
		{0xff,		0x9d,	NULL,			L"stelem.i2"},
		{0xff,		0x9e,	NULL,			L"stelem.i4"},
		{0xff,		0x9f,	NULL,			L"stelem.i8"},
		// 0xA0
		{0xff,		0xa0,	NULL,			L"stelem.r4"},
		{0xff,		0xa1,	NULL,			L"stelem.r8"},
		{0xff,		0xa2,	NULL,			L"stelem.ref"},
		{0xff,		0xa3,	NULL,			NULL},
		{0xff,		0xa4,	NULL,			NULL},
		{0xff,		0xa5,	NULL,			NULL},
		{0xff,		0xa6,	NULL,			NULL},
		{0xff,		0xa7,	NULL,			NULL},
		{0xff,		0xa8,	NULL,			NULL},
		{0xff,		0xa9,	NULL,			NULL},
		{0xff,		0xaa,	NULL,			NULL},
		{0xff,		0xab,	NULL,			NULL},
		{0xff,		0xac,	NULL,			NULL},
		{0xff,		0xad,	NULL,			NULL},
		{0xff,		0xae,	NULL,			NULL},
		{0xff,		0xaf,	NULL,			NULL},
		// 0xB0
		{0xff,		0xb0,	NULL,			NULL},
		{0xff,		0xb1,	NULL,			NULL},
		{0xff,		0xb2,	NULL,			NULL},
		{0xff,		0xb3,	NULL,			L"conv.ovf.i1"},
		{0xff,		0xb4,	NULL,			L"conv.ovf.u1"},
		{0xff,		0xb5,	NULL,			L"conv.ovf.i2"},
		{0xff,		0xb6,	NULL,			L"conv.ovf.u2"},
		{0xff,		0xb7,	NULL,			L"conv.ovf.i4"},
		{0xff,		0xb8,	NULL,			L"conv.ovf.u4"},
		{0xff,		0xb9,	NULL,			L"conv.ovf.i8"},
		{0xff,		0xba,	NULL,			L"conv.ovf.u8"},
		{0xff,		0xbb,	NULL,			NULL},
		{0xff,		0xbc,	NULL,			NULL},
		{0xff,		0xbd,	NULL,			NULL},
		{0xff,		0xbe,	NULL,			NULL},
		{0xff,		0xbf,	NULL,			NULL},
		// 0xC0
		{0xff,		0xc0,	NULL,			NULL},
		{0xff,		0xc1,	NULL,			NULL},
		{0xff,		0xc2,	NULL,			L"refanyval"},
		{0xff,		0xc3,	NULL,			L"ckfinite"},
		{0xff,		0xc4,	NULL,			NULL},
		{0xff,		0xc5,	NULL,			NULL},
		{0xff,		0xc6,	NULL,			L"mkrefany"},
		{0xff,		0xc7,	NULL,			NULL},
		{0xff,		0xc8,	NULL,			NULL},
		{0xff,		0xc9,	NULL,			NULL},
		{0xff,		0xca,	NULL,			NULL},
		{0xff,		0xcb,	NULL,			NULL},
		{0xff,		0xcc,	NULL,			NULL},
		{0xff,		0xcd,	NULL,			NULL},
		{0xff,		0xce,	NULL,			NULL},
		{0xff,		0xcf,	NULL,			NULL},
		// 0xD0
		{0xff,		0xd0,	NULL,			L"ldtoken"},
		{0xff,		0xd1,	NULL,			L"conv.u2"},
		{0xff,		0xd2,	NULL,			L"conv.u1"},
		{0xff,		0xd3,	NULL,			L"conv.i"},
		{0xff,		0xd4,	NULL,			L"conv.ovf.i"},
		{0xff,		0xd5,	NULL,			L"conv.ovf.u"},
		{0xff,		0xd6,	NULL,			L"add.ovf"},
		{0xff,		0xd7,	NULL,			L"add.ovf.un"},
		{0xff,		0xd8,	NULL,			L"mul.ovf"},
		{0xff,		0xd9,	NULL,			L"mul.ovf.un"},
		{0xff,		0xda,	NULL,			L"sub.ovf"},
		{0xff,		0xdb,	NULL,			L"sub.ovf.un"},
		{0xff,		0xdc,	NULL,			L"endfinally"},
		{0xff,		0xdd,	NULL,			L"leave"},
		{0xff,		0xde,	NULL,			L"leave.s"},
		{0xff,		0xdf,	NULL,			L"stind.i"},
		// 0xE0
		{0xff,		0xe0,	NULL,			L"conv.u"},
		{0xff,		0xe1,	NULL,			NULL},
		{0xff,		0xe2,	NULL,			NULL},
		{0xff,		0xe3,	NULL,			NULL},
		{0xff,		0xe4,	NULL,			NULL},
		{0xff,		0xe5,	NULL,			NULL},
		{0xff,		0xe6,	NULL,			NULL},
		{0xff,		0xe7,	NULL,			NULL},
		{0xff,		0xe8,	NULL,			NULL},
		{0xff,		0xe9,	NULL,			NULL},
		{0xff,		0xea,	NULL,			NULL},
		{0xff,		0xeb,	NULL,			NULL},
		{0xff,		0xec,	NULL,			NULL},
		{0xff,		0xed,	NULL,			NULL},
		{0xff,		0xee,	NULL,			NULL},
		{0xff,		0xef,	NULL,			NULL},
		// 0xF0
		{0xff,		0xf0,	NULL,			NULL},
		{0xff,		0xf1,	NULL,			NULL},
		{0xff,		0xf2,	NULL,			NULL},
		{0xff,		0xf3,	NULL,			NULL},
		{0xff,		0xf4,	NULL,			NULL},
		{0xff,		0xf5,	NULL,			NULL},
		{0xff,		0xf6,	NULL,			NULL},
		{0xff,		0xf7,	NULL,			NULL},

		{0xff,		0xf8,	NULL,			L"prefix7"},
		{0xff,		0xf9,	NULL,			L"prefix6"},
		{0xff,		0xfa,	NULL,			L"prefix5"},
		{0xff,		0xfb,	NULL,			L"prefix4"},
		{0xff,		0xfc,	NULL,			L"prefix3"},
		{0xff,		0xfd,	NULL,			L"prefix2"},
		{0xff,		0xfe,	Prefix1Table,	L"prefix1"},
		{0xff,		0xff,	NULL,			L"prefixref"}
	};

} }

#endif//_OPERATIONS_H