/*
Copyright (C) 2006 Evan Teran
                   eteran@alum.rit.edu

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#ifndef OPTABLE_1BYTE_TCC_H_
#define OPTABLE_1BYTE_TCC_H_

const Instruction::OpcodeEntry Instruction::m_Opcodes[0x100] = {

	/* 0x00 - 0x0f */
	{ "add", &Instruction::decode_Eb_Gb, OP_ADD },
	{ "add", &Instruction::decode_Ev_Gv, OP_ADD },
	{ "add", &Instruction::decode_Gb_Eb, OP_ADD },
	{ "add", &Instruction::decode_Gv_Ev, OP_ADD },
	{ "add", &Instruction::decode_AL_Ib, OP_ADD },
	{ "add", &Instruction::decode_rAX_Iz, OP_ADD },
	{ "push", &Instruction::decode_Reg<Operand::REG_ES>, OP_PUSH },	// ia-32 only
	{ "pop", &Instruction::decode_Reg<Operand::REG_ES>, OP_POP },	// ia-32 only
	{ "or", &Instruction::decode_Eb_Gb, OP_OR },
	{ "or", &Instruction::decode_Ev_Gv, OP_OR },
	{ "or", &Instruction::decode_Gb_Eb, OP_OR },
	{ "or", &Instruction::decode_Gv_Ev, OP_OR },
	{ "or", &Instruction::decode_AL_Ib, OP_OR },
	{ "or", &Instruction::decode_rAX_Iz, OP_OR },
	{ "push", &Instruction::decode_Reg<Operand::REG_CS>, OP_PUSH },	// ia-32 only
	{ "2byte", &Instruction::decode_2byte, OP_2BYTE },
	
	/* 0x10 - 0x1f */
	{ "adc", &Instruction::decode_Eb_Gb, OP_ADC },
	{ "adc", &Instruction::decode_Ev_Gv, OP_ADC },
	{ "adc", &Instruction::decode_Gb_Eb, OP_ADC },
	{ "adc", &Instruction::decode_Gv_Ev, OP_ADC },
	{ "adc", &Instruction::decode_AL_Ib, OP_ADC },
	{ "adc", &Instruction::decode_rAX_Iz, OP_ADC },
	{ "push", &Instruction::decode_Reg<Operand::REG_SS>, OP_PUSH },	// ia-32 only
	{ "pop", &Instruction::decode_Reg<Operand::REG_SS>, OP_POP },	// ia-32 only
	{ "sbb", &Instruction::decode_Eb_Gb, OP_SBB },
	{ "sbb", &Instruction::decode_Ev_Gv, OP_SBB },
	{ "sbb", &Instruction::decode_Gb_Eb, OP_SBB },
	{ "sbb", &Instruction::decode_Gv_Ev, OP_SBB },
	{ "sbb", &Instruction::decode_AL_Ib, OP_SBB },
	{ "sbb", &Instruction::decode_rAX_Iz, OP_SBB },
	{ "push", &Instruction::decode_Reg<Operand::REG_DS>, OP_PUSH },	// ia-32 only
	{ "pop", &Instruction::decode_Reg<Operand::REG_DS>, OP_POP },	// ia-32 only
	
	/* 0x20 - 0x2f */
	{ "and", &Instruction::decode_Eb_Gb, OP_AND }, 
	{ "and", &Instruction::decode_Ev_Gv, OP_AND }, 
	{ "and", &Instruction::decode_Gb_Eb, OP_AND }, 
	{ "and", &Instruction::decode_Gv_Ev, OP_AND }, 
	{ "and", &Instruction::decode_AL_Ib, OP_AND }, 
	{ "and", &Instruction::decode_rAX_Iz, OP_AND }, 
	{ "prefix es", &Instruction::decode_invalid, OP_PREFIX },
	{ "daa", &Instruction::decode, OP_DAA }, 						// ia-32 only
	{ "sub", &Instruction::decode_Eb_Gb, OP_SUB }, 
	{ "sub", &Instruction::decode_Ev_Gv, OP_SUB }, 
	{ "sub", &Instruction::decode_Gb_Eb, OP_SUB }, 
	{ "sub", &Instruction::decode_Gv_Ev, OP_SUB }, 
	{ "sub", &Instruction::decode_AL_Ib, OP_SUB }, 
	{ "sub", &Instruction::decode_rAX_Iz, OP_SUB }, 
	{ "prefix cs", &Instruction::decode_invalid, OP_PREFIX },
	{ "das", &Instruction::decode, OP_DAS },						// ia-32 only
	
	/* 0x30 - 0x3f */
	{ "xor", &Instruction::decode_Eb_Gb, OP_XOR },
	{ "xor", &Instruction::decode_Ev_Gv, OP_XOR },
	{ "xor", &Instruction::decode_Gb_Eb, OP_XOR },
	{ "xor", &Instruction::decode_Gv_Ev, OP_XOR },
	{ "xor", &Instruction::decode_AL_Ib, OP_XOR },
	{ "xor", &Instruction::decode_rAX_Iz, OP_XOR },
	{ "prefix ss", &Instruction::decode_invalid, OP_PREFIX },
	{ "aaa", &Instruction::decode, OP_AAA },						// ia-32 only
	{ "cmp", &Instruction::decode_Eb_Gb, OP_CMP },
	{ "cmp", &Instruction::decode_Ev_Gv, OP_CMP },
	{ "cmp", &Instruction::decode_Gb_Eb, OP_CMP },
	{ "cmp", &Instruction::decode_Gv_Ev, OP_CMP },
	{ "cmp", &Instruction::decode_AL_Ib, OP_CMP },
	{ "cmp", &Instruction::decode_rAX_Iz, OP_CMP },
	{ "prefix ds", &Instruction::decode_invalid, OP_PREFIX },
	{ "aas", &Instruction::decode, OP_AAS },						// ia-32 only
	
	/* 0x40 - 0x4f */
	{ "inc", &Instruction::decode_rAX, OP_INC },
	{ "inc", &Instruction::decode_rCX, OP_INC },
	{ "inc", &Instruction::decode_rDX, OP_INC },
	{ "inc", &Instruction::decode_rBX, OP_INC },
	{ "inc", &Instruction::decode_rSP, OP_INC },
	{ "inc", &Instruction::decode_rBP, OP_INC },
	{ "inc", &Instruction::decode_rSI, OP_INC },
	{ "inc", &Instruction::decode_rDI, OP_INC },
	{ "dec", &Instruction::decode_rAX, OP_DEC },
	{ "dec", &Instruction::decode_rCX, OP_DEC },
	{ "dec", &Instruction::decode_rDX, OP_DEC },
	{ "dec", &Instruction::decode_rBX, OP_DEC },
	{ "dec", &Instruction::decode_rSP, OP_DEC },
	{ "dec", &Instruction::decode_rBP, OP_DEC },
	{ "dec", &Instruction::decode_rSI, OP_DEC },
	{ "dec", &Instruction::decode_rDI, OP_DEC },

	/* 0x50 - 0x5f */
	{ "push", &Instruction::decode_rAX, OP_PUSH },
	{ "push", &Instruction::decode_rCX, OP_PUSH },
	{ "push", &Instruction::decode_rDX, OP_PUSH },
	{ "push", &Instruction::decode_rBX, OP_PUSH },
	{ "push", &Instruction::decode_rSP, OP_PUSH },
	{ "push", &Instruction::decode_rBP, OP_PUSH },
	{ "push", &Instruction::decode_rSI, OP_PUSH },
	{ "push", &Instruction::decode_rDI, OP_PUSH },
	{ "pop", &Instruction::decode_rAX, OP_POP },
	{ "pop", &Instruction::decode_rCX, OP_POP },
	{ "pop", &Instruction::decode_rDX, OP_POP },
	{ "pop", &Instruction::decode_rBX, OP_POP },
	{ "pop", &Instruction::decode_rSP, OP_POP },
	{ "pop", &Instruction::decode_rBP, OP_POP },
	{ "pop", &Instruction::decode_rSI, OP_POP },
	{ "pop", &Instruction::decode_rDI, OP_POP },
	
	/* 0x60 - 0x6f */
	{ "pushaw/pushad",  &Instruction::decode_pushad_pushaw, OP_PUSHA },					// ia-32 only
	{ "popaw/popad",  &Instruction::decode_popad_popaw, OP_POPA },						// ia-32 only
	{ "bound",  &Instruction::decode_Gv_Ma, OP_BOUND },				// ia-32 only
	{ "arpl", &Instruction::decode_Ew_Gw, OP_ARPL },				// movsxd Gv,Ev in ia-64
	{ "prefix fs", &Instruction::decode_invalid, OP_PREFIX },
	{ "prefix gs", &Instruction::decode_invalid, OP_PREFIX },
	{ "prefix data16", &Instruction::decode_invalid, OP_PREFIX },
	{ "prefix addr16", &Instruction::decode_invalid, OP_PREFIX },
	{ "push", &Instruction::decode_Iz, OP_PUSH },
	{ "imul", &Instruction::decode_Gv_Ev_Iz, OP_IMUL },
	{ "push", &Instruction::decode_Ib, OP_PUSH },
	{ "imul", &Instruction::decode_Gv_Ev_Ib, OP_IMUL },
	{ "insb",  &Instruction::decode, OP_INS },
	{ "insw/insd",  &Instruction::decode_insd_insw, OP_INS },
	{ "outsb",  &Instruction::decode, OP_OUTS },
	{ "outsw/outsd",  &Instruction::decode_outsd_outsw, OP_OUTS },
		
	/* 0x70 - 0x7f */
	{ "jo", &Instruction::decode_Jb, OP_JCC },
	{ "jno", &Instruction::decode_Jb, OP_JCC },
	{ "jb", &Instruction::decode_Jb, OP_JCC },
	{ "jnb", &Instruction::decode_Jb, OP_JCC },
	{ "jz", &Instruction::decode_Jb, OP_JCC },
	{ "jnz", &Instruction::decode_Jb, OP_JCC },
	{ "jbe", &Instruction::decode_Jb, OP_JCC },
	{ "jnbe", &Instruction::decode_Jb, OP_JCC },
	{ "js", &Instruction::decode_Jb, OP_JCC },
	{ "jns", &Instruction::decode_Jb, OP_JCC },
	{ "jp", &Instruction::decode_Jb, OP_JCC },
	{ "jnp", &Instruction::decode_Jb, OP_JCC },
	{ "jl", &Instruction::decode_Jb, OP_JCC },
	{ "jnl", &Instruction::decode_Jb, OP_JCC },
	{ "jle", &Instruction::decode_Jb, OP_JCC },
	{ "jnle", &Instruction::decode_Jb, OP_JCC },
	
	/* 0x80 - 0x8f */
	{ "group1", &Instruction::decode_group1, OP_GROUP1 },
	{ "group1", &Instruction::decode_group1, OP_GROUP1 },
	{ "group1", &Instruction::decode_group1, OP_GROUP1 },
	{ "group1", &Instruction::decode_group1, OP_GROUP1 },
	{ "test",  &Instruction::decode_Eb_Gb, OP_TEST },
	{ "test",  &Instruction::decode_Ev_Gv, OP_TEST },
	{ "xchg", &Instruction::decode_Gb_Eb, OP_XCHG },
	{ "xchg", &Instruction::decode_Gv_Ev, OP_XCHG },
	{ "mov", &Instruction::decode_Eb_Gb, OP_MOV },
	{ "mov", &Instruction::decode_Ev_Gv, OP_MOV },
	{ "mov", &Instruction::decode_Gb_Eb, OP_MOV },
	{ "mov", &Instruction::decode_Gv_Ev, OP_MOV },
	{ "mov", &Instruction::decode_Ev_Sw, OP_MOV },
	{ "lea", &Instruction::decode_Gv_M, OP_LEA },
	{ "mov", &Instruction::decode_Sw_Ew, OP_MOV },
	{ "group10", &Instruction::decode_group10, OP_GROUP10 },
	
	/* 0x90 - 0x9f */
	{ "nop/pause",  &Instruction::decode_nop_pause, OP_NOP },
	{ "xchg",  &Instruction::decode_rCX_rAX, OP_XCHG },
	{ "xchg",  &Instruction::decode_rDX_rAX, OP_XCHG },
	{ "xchg",  &Instruction::decode_rBX_rAX, OP_XCHG },
	{ "xchg",  &Instruction::decode_rSP_rAX, OP_XCHG },
	{ "xchg",  &Instruction::decode_rBP_rAX, OP_XCHG },
	{ "xchg",  &Instruction::decode_rSI_rAX, OP_XCHG },
	{ "xchg",  &Instruction::decode_rDI_rAX, OP_XCHG },
	{ "cwde/cbw",  &Instruction::decode_cwde_cbw, OP_CWDE },
	{ "cdq/cwd",  &Instruction::decode_cdq_cwd, OP_CDQ },
	{ "callf", &Instruction::decode_Ap, OP_CALL },		// ia-32 only
	{ "wait", &Instruction::decode, OP_WAIT },
	{ "pushfd/pushfw", &Instruction::decode_pushfd_pushfw, OP_PUSHF },
	{ "popfd/popfw", &Instruction::decode_popfd_popfw, OP_POPF },
	{ "sahf", &Instruction::decode, OP_SAHF },
	{ "lahf", &Instruction::decode, OP_LAHF },
	
	/* 0xa0 - 0xaf */
	{ "mov", &Instruction::decode_AL_Ob, OP_MOV },
	{ "mov", &Instruction::decode_rAX_Ov, OP_MOV },
	{ "mov", &Instruction::decode_Ob_AL, OP_MOV },
	{ "mov", &Instruction::decode_Ov_rAX, OP_MOV },
	{ "movsb", &Instruction::decode, OP_MOVS },
	{ "movsd/movsw", &Instruction::decode_movsd_movsw, OP_MOVS },
	{ "cmpsb/cmpsw", &Instruction::decode_cmpsd_cmpsw, OP_CMPS },
	{ "cmpsd/cmpsw", &Instruction::decode_cmpsd_cmpsw, OP_CMPS },
	{ "test", &Instruction::decode_AL_Ib, OP_TEST },
	{ "test", &Instruction::decode_rAX_Iz, OP_TEST },
	{ "stosb", &Instruction::decode, OP_STOS },
	{ "stosd/stosw", &Instruction::decode_stosd_stosw, OP_STOS },
	{ "lodsb", &Instruction::decode, OP_LODS },
	{ "lodsd/lodsw", &Instruction::decode_lodsd_lodsw, OP_LODS },
	{ "scasb", &Instruction::decode, OP_SCAS },
	{ "scasd/scasw", &Instruction::decode_scasd_scasw, OP_SCAS },
	
	/* 0xb0 - 0xbf */
	{ "mov", &Instruction::decode_AL_Ib, OP_MOV },
	{ "mov", &Instruction::decode_CL_Ib, OP_MOV },
	{ "mov", &Instruction::decode_DL_Ib, OP_MOV },
	{ "mov", &Instruction::decode_BL_Ib, OP_MOV },
	{ "mov", &Instruction::decode_AH_Ib, OP_MOV },
	{ "mov", &Instruction::decode_CH_Ib, OP_MOV },
	{ "mov", &Instruction::decode_DH_Ib, OP_MOV },
	{ "mov", &Instruction::decode_BH_Ib, OP_MOV },
	{ "mov", &Instruction::decode_rAX_Iv, OP_MOV },
	{ "mov", &Instruction::decode_rCX_Iv, OP_MOV },
	{ "mov", &Instruction::decode_rDX_Iv, OP_MOV },
	{ "mov", &Instruction::decode_rBX_Iv, OP_MOV },
	{ "mov", &Instruction::decode_rSP_Iv, OP_MOV },
	{ "mov", &Instruction::decode_rBP_Iv, OP_MOV },
	{ "mov", &Instruction::decode_rSI_Iv, OP_MOV },
	{ "mov", &Instruction::decode_rDI_Iv, OP_MOV },
	
	/* 0xc0 - 0xcf */
	{ "group2", &Instruction::decode_group2, OP_GROUP2 },
	{ "group2", &Instruction::decode_group2, OP_GROUP2 },
	{ "ret", &Instruction::decode_Iw, OP_RET },
	{ "ret", &Instruction::decode, OP_RET },
	{ "les", &Instruction::decode_Gz_Mp, OP_LES },		// ia-32 only
	{ "lds", &Instruction::decode_Gz_Mp, OP_LDS },		// ia-32 only
	{ "group12", &Instruction::decode_group12, OP_GROUP12 },
	{ "group12", &Instruction::decode_group12, OP_GROUP12 },
	{ "enter", &Instruction::decode_Iw_Ib, OP_ENTER },
	{ "leave", &Instruction::decode, OP_LEAVE },
	{ "retf", &Instruction::decode_Iw, OP_RET },
	{ "retf", &Instruction::decode, OP_RET },
	{ "int3", &Instruction::decode, OP_INT3 },
	{ "int", &Instruction::decode_Ib, OP_INT },
	{ "into", &Instruction::decode, OP_INTO },			// ia-32 only
	{ "iret/iretw", &Instruction::decode_iret_iretw, OP_IRET },
	
	/* 0xd0 - 0xdf */
	{ "group2", &Instruction::decode_group2D, OP_GROUP2 },
	{ "group2", &Instruction::decode_group2D, OP_GROUP2 },
	{ "group2", &Instruction::decode_group2D, OP_GROUP2 },
	{ "group2", &Instruction::decode_group2D, OP_GROUP2 },
	{ "aam", &Instruction::decode_Ib, OP_AAM },			// ia-32 only
	{ "aad", &Instruction::decode_Ib, OP_AAD },			// ia-32 only
	{ "invalid", &Instruction::decode_invalid, OP_INVALID },
	{ "xlat", &Instruction::decode, OP_XLAT },
	{ "esc0", &Instruction::decode_x87, OP_FPU },
	{ "esc1", &Instruction::decode_x87, OP_FPU },
	{ "esc2", &Instruction::decode_x87, OP_FPU },
	{ "esc3", &Instruction::decode_x87, OP_FPU },
	{ "esc4", &Instruction::decode_x87, OP_FPU },
	{ "esc5", &Instruction::decode_x87, OP_FPU },
	{ "esc6", &Instruction::decode_x87, OP_FPU },
	{ "esc7", &Instruction::decode_x87, OP_FPU },
	
	/* 0xe0 - 0xef */
	{ "loopne", &Instruction::decode_Jb, OP_LOOPNE },
	{ "loope", &Instruction::decode_Jb, OP_LOOPE },
	{ "loop", &Instruction::decode_Jb, OP_LOOP },
	{ "jcez", &Instruction::decode_Jb, OP_JCC },
	{ "in", &Instruction::decode_AL_Ib, OP_IN },
	{ "in", &Instruction::decode_rAX_Ib, OP_IN },
	{ "out", &Instruction::decode_Ib_AL, OP_OUT },
	{ "out", &Instruction::decode_Ib_rAX, OP_OUT },
	{ "call", &Instruction::decode_Jz, OP_CALL },
	{ "jmp", &Instruction::decode_Jz, OP_JMP },
	{ "jmp", &Instruction::decode_Ap, OP_JMP },
	{ "jmp", &Instruction::decode_Jb, OP_JMP },
	{ "in", &Instruction::decode_AL_DX, OP_IN },
	{ "in", &Instruction::decode_rAX_DX, OP_IN },
	{ "out", &Instruction::decode_DX_AL, OP_OUT },
	{ "out", &Instruction::decode_DX_rAX, OP_OUT },
	
	/* 0xf0 - 0xff */
	{ "prefix lock", &Instruction::decode_invalid, OP_PREFIX },
	{ "invalid", &Instruction::decode_invalid, OP_INVALID },
	{ "prefix repne", &Instruction::decode_invalid, OP_PREFIX },
	{ "prefix rep", &Instruction::decode_invalid, OP_PREFIX },
	{ "hlt", &Instruction::decode, OP_HLT },
	{ "cmc", &Instruction::decode, OP_CMC },
	{ "group3", &Instruction::decode_group3, OP_GROUP3 },
	{ "group3", &Instruction::decode_group3, OP_GROUP3 },
	{ "clc", &Instruction::decode, OP_CLC },
	{ "stc", &Instruction::decode, OP_STC },
	{ "cli", &Instruction::decode, OP_CLI },
	{ "sti", &Instruction::decode, OP_STI },
	{ "cld", &Instruction::decode, OP_CLD },
	{ "std", &Instruction::decode, OP_STD },
	{ "group4", &Instruction::decode_group4, OP_GROUP4 },
	{ "group5", &Instruction::decode_group5, OP_GROUP5 }
};

#endif
