/* 
 ************************************************************************************************ 
 *
 * M32C Instruction Decoder
 * State: Working
 *
 * Copyright 2009/2010 Jochen Karrer. All rights reserved.
 * 
 * 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.
 * 
 * THIS SOFTWARE IS PROVIDED BY Jochen Karrer ``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 <COPYRIGHT HOLDER> OR
 * CONTRIBUTORS 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.
 * 
 * The views and conclusions contained in the software and documentation are those of the
 * authors and should not be interpreted as representing official policies, either expressed
 * or implied, of Jochen Karrer.
 *
 ************************************************************************************************ 
 */
#include <idecode_m32c.h>
#include "instructions_m32c.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "sgstring.h"
#include "sglib.h"
#include "compiler_extensions.h"

#if 0
#define dbgprintf(x...) { fprintf(stderr,x); }
#else
#define dbgprintf(x...)
#endif

M32C_Instruction     **m32c_iTab;

/**
 ***********************************************************************
 * \fn bool M32C_CheckGAMHigh(M32C_Instruction *instr,uint32_t icode)
 * Check if addressing mode in upper bits of the icode  exists 
 ***********************************************************************
 */
static bool 
M32C_CheckGAMHigh(M32C_Instruction *instr,uint32_t icode)
{
	uint32_t gam;
	if(instr->len == 2) {
		icode = icode >> 8;
	} else if(instr->len == 1) {
		fprintf(stderr,"Bug: GAMH check for one byte instruction %s\n",instr->name);
		exit(1);
	}
	gam = ((icode >> 4) & 3) | ((icode >> 10) & 0x1c);
	if(gam < 20) {
		dbgprintf("GAMH %d exists  for %s(%06x)\n",gam,instr->name,icode);
		return true;
	} else {
		dbgprintf("GAMH %d does not exist for %s\n",gam,instr->name);
		return false;
	}
}

/**
 ***********************************************************************
 * \fn bool M32C_CheckGAMLow(M32C_Instruction *instr,uint32_t icode)
 * Check if addressing mode in lower bits of the icode  exists 
 ***********************************************************************
 */
static bool 
M32C_CheckGAMLow(M32C_Instruction *instr,uint32_t icode)
{
	uint32_t gam;
	if(instr->len == 2) {
		icode = icode >> 8;
	} else if(instr->len == 1) {
		fprintf(stderr,"Bug: GAML check for one byte instruction %s\n",instr->name);
		exit(1);
	}
	gam = ((icode >> 6) & 3) | ((icode >> 7) & 0x1c);
	if(gam < 20) {
		dbgprintf("GAML %d exists  for %s(%06x)\n",gam,instr->name,icode);
		return true;
	} else {
		dbgprintf(stderr,"GAML %d does not exist for %s\n",gam,instr->name);
		return false;
	}
}

static inline bool 
M32C_CheckBitaddrLow(M32C_Instruction *instr,uint32_t icode)
{
	return M32C_CheckGAMLow(instr,icode);
}

static bool 
M32C_CheckGAMBoth(M32C_Instruction *instr,uint32_t icode)
{
	if(M32C_CheckGAMHigh(instr,icode) == false) {
		return false;
	} else if(M32C_CheckGAMLow(instr,icode) == false) {
		return false;
	} else {
		return true;
	}	
	
}


/*
 *******************************************************************
 * The instruction list
 * v0
 *******************************************************************
 */
static M32C_Instruction instrlist[] = {
{0x00f03f,0x00a01f,"abs.size_dst",2		,m32c_abs_size_dst,M32C_CheckGAMLow},
{0xfff03f,0x09a01f,"abs.size_idst",3		,m32c_abs_size_idst,M32C_CheckGAMLow},
{0xfff03f,0x01802e,"adc.size_immdst",3		,m32c_adc_size_immdst,M32C_CheckGAMLow},
{0xff800f,0x018004,"adc.size_srcdst",3		,m32c_adc_size_srcdst,M32C_CheckGAMBoth},
{0x00f03f,0x00b01e,"adcf.size_dst",2		,m32c_adcf_size_dst,M32C_CheckGAMLow},
{0xfff03f,0x09b01e,"adcf.size_idst",3		,m32c_adcf_size_idst,M32C_CheckGAMLow},
{0x00f03f,0x00802e,"add.size:g_immdst",2        ,m32c_add_size_g_immdst,M32C_CheckGAMLow},
{0xfff03f,0x09802e,"add.size:g_immidst",3       ,m32c_add_size_g_immidst,M32C_CheckGAMLow},
{0x00f13f,0x008031,"add.l:g_immdst",2		,m32c_add_l_g_immdst,M32C_CheckGAMLow},
{0xfff13f,0x098031,"add.l:g_immidst",3		,m32c_add_l_g_immidst,M32C_CheckGAMLow},
{0x00f030,0x00e030,"add.size:q_immdst",2        ,m32c_add_size_q_immdst,M32C_CheckGAMLow},
{0x00f030,0x00f030,"add.size:q_immdst",2        ,m32c_add_size_q_immdst,M32C_CheckGAMLow},
{0xfff030,0x09e030,"add.size:q_immidst",3       ,m32c_add_size_q_immidst,M32C_CheckGAMLow},
{0xfff030,0x09f030,"add.size:q_immidst",3       ,m32c_add_size_q_immidst,M32C_CheckGAMLow},
{0x0000ce,0x000006,"add.size:s_immdst",1       	,m32c_add_size_s_immdst},
{0x00ffce,0x000906,"add.size:s_immidst",2      	,m32c_add_size_s_immidst},
{0x0000de,0x00008c,"add.l:s_imm_a0a1",1		,m32c_add_l_s_imm_a0a1},
{0x00800f,0x008008,"add.size:g_srcdst",2	,m32c_add_size_g_srcdst,M32C_CheckGAMBoth},
{0xff800f,0x418008,"add.size:g_isrcdst",3	,m32c_add_size_g_isrcdst,M32C_CheckGAMBoth},
{0xff800f,0x098008,"add.size:g_srcidst",3	,m32c_add_size_g_srcidst,M32C_CheckGAMBoth},
{0xff800f,0x498008,"add.size:g_isrcidst",3	,m32c_add_size_g_isrcidst},
{0x00810f,0x008102,"add.l:g:srcdst",2		,m32c_add_l_g_srcdst,M32C_CheckGAMBoth},
{0xff810f,0x418102,"add.l:g:isrcdst",3		,m32c_add_l_g_isrcdst,M32C_CheckGAMBoth},
{0xff810f,0x098102,"add.l:g:srcidst",3		,m32c_add_l_g_srcidst,M32C_CheckGAMBoth},
{0xff810f,0x498102,"add.l:g:isrcidst",3		,m32c_add_l_g_isrcidst,M32C_CheckGAMBoth},
{0x00ffff,0x00b613,"add.l:g:imm16sp",2		,m32c_add_l_g_imm16sp},	
{0x0000ce,0x000042,"add.l:q:imm3sp",1		,m32c_add_l_q_imm3sp},
{0x00ffff,0x00b603,"add.l:s:imm8sp",2		,m32c_add_l_s_imm8sp},
{0x00f13f,0x008011,"addx:immdst",2		,m32c_addx_immdst,M32C_CheckGAMLow},
{0xfff13f,0x098011,"addx:immidst",3		,m32c_addx_immidst,M32C_CheckGAMLow},
{0x00810f,0x008002,"addx:srcdst",2		,m32c_addx_srcdst,M32C_CheckGAMBoth},
{0xff810f,0x418002,"addx:isrcdst",3		,m32c_addx_isrcdst,M32C_CheckGAMBoth},
{0xff810f,0x098002,"addx:srcidst",3		,m32c_addx_srcidst,M32C_CheckGAMBoth},
{0xff810f,0x498002,"addx:isrcidst",3		,m32c_addx_isrcidst,M32C_CheckGAMBoth},
{0x00f030,0x00f010,"adjnz.size:immdstlbl",2	,m32c_adjnz_size_immdstlbl,M32C_CheckGAMLow},
{0x00f03f,0x00803f,"and.size_immdst",2		,m32c_and_size_immdst,M32C_CheckGAMLow},
{0xfff03f,0x09803f,"and.size_immidst",3		,m32c_and_size_immidst,M32C_CheckGAMLow},
{0x0000ce,0x00004c,"and.size:s_immdst",1	,m32c_and_size_s_immdst},
{0x00ffce,0x00094c,"and.size:s_immidst",2	,m32c_and_size_s_immidst},
{0x00800f,0x00800d,"and.size:g:srcdst",2	,m32c_and_size_g_srcdst,M32C_CheckGAMBoth},
{0xff800f,0x41800d,"and.size:g:isrcdst",3	,m32c_and_size_g_isrcdst,M32C_CheckGAMBoth},
{0xff800f,0x09800d,"and.size:g:srcidst",3	,m32c_and_size_g_srcidst,M32C_CheckGAMBoth},
{0xff800f,0x49800d,"and.size:g:isrcidst",3	,m32c_and_size_g_isrcidst},
{0xfff138,0x01d008,"band_src",3			,m32c_band_src,M32C_CheckBitaddrLow},
{0x00f138,0x00d030,"bclr_dst",2			,m32c_bclr,M32C_CheckBitaddrLow},
{0x00f03f,0x00c02e,"bitindex.src",2		,m32c_bitindex,M32C_CheckGAMLow},
{0x00f138,0x00d010,"bmcnd_dst",2		,m32c_bmcnd_dst,M32C_CheckBitaddrLow},
{0x00ffb8,0x00d928,"bmcnd_c",2			,m32c_bmcnd_c},
{0xfff138,0x01d018,"bnand_src",3		,m32c_bnand_src,M32C_CheckBitaddrLow},
{0xfff138,0x01d030,"bnor_src",3			,m32c_bnor_src0,M32C_CheckBitaddrLow},
{0x00f138,0x00d018,"bnot_dst",2			,m32c_bnot_dst,M32C_CheckBitaddrLow},
{0xfff138,0x01d000,"bntst_src",3		,m32c_bntst_src,M32C_CheckBitaddrLow},
{0xfff138,0x01d038,"bnxor_src",3		,m32c_bnxor_src,M32C_CheckBitaddrLow},
{0xfff138,0x01d020,"bor_src",3			,m32c_bor_src,M32C_CheckBitaddrLow},
{0x0000ff,0x000000,"brk",1			,m32c_brk},
{0x0000ff,0x000008,"brk2",1			,m32c_brk2},
{0x00f138,0x00d038,"bset_dst",2			,m32c_bset_dst,M32C_CheckGAMLow},
{0x00f138,0x00d000,"btst:g:src",2		,m32c_btst_g_src,M32C_CheckGAMLow},
{0x0000ce,0x00000a,"btst:s:src",1		,m32c_btst_s_src},
{0x00f138,0x00d020,"btstc_dst",2		,m32c_btstc_dst,M32C_CheckBitaddrLow},
{0x00f138,0x00d028,"btsts_dst",2		,m32c_btsts_dst,M32C_CheckBitaddrLow},
{0xfff138,0x01d028,"bxor_dst",3			,m32c_bxor_src,M32C_CheckBitaddrLow},
{0xfff03f,0x01803e,"clip_size",3		,m32c_clip,M32C_CheckGAMLow},
{0x00f03f,0x00902e,"cmp_size:g_immdst",2	,m32c_cmp_size_g_immdst,M32C_CheckGAMLow},
{0xfff03f,0x09902e,"cmp_size:g_immidst",3	,m32c_cmp_size_g_immidst,M32C_CheckGAMLow},
{0x00f13f,0x00a031,"cmp_l_g_imm32dst",2		,m32c_cmp_l_g_imm32dst,M32C_CheckGAMLow},
{0xfff13f,0x09a031,"cmp_l_g_imm32idst",3	,m32c_cmp_l_g_imm32idst,M32C_CheckGAMLow},
{0x00f030,0x00e010,"cmp_size_q_immdst",2	,m32c_cmp_size_q_immdst,M32C_CheckGAMLow},
{0xfff030,0x09e010,"cmp_size_q_immidst",3	,m32c_cmp_size_q_immidst,M32C_CheckGAMLow},
{0x0000ce,0x000046,"cmp_size_s_immdst",1	,m32c_cmp_size_s_immdst},
{0x00ffce,0x000946,"cmp_size_s_immidst",2	,m32c_cmp_size_s_immidst},
{0x00800f,0x008006,"cmp_size_g_srcdst",2	,m32c_cmp_size_g_srcdst,M32C_CheckGAMBoth},
{0xff800f,0x418006,"cmp_size_g_isrcdst",3	,m32c_cmp_size_g_isrcdst,M32C_CheckGAMBoth},
{0xff800f,0x098006,"cmp_size_g_srcidst",3	,m32c_cmp_size_g_srcidst,M32C_CheckGAMBoth},
{0xff800f,0x498006,"cmp_size_g_isrcidst",3	,m32c_cmp_size_g_isrcidst,M32C_CheckGAMBoth},
{0x00810f,0x008101,"cmp_l_g_srcdst",2		,m32c_cmp_l_g_srcdst,M32C_CheckGAMBoth},
{0xff810f,0x418101,"cmp_l_g_isrcdst",3		,m32c_cmp_l_g_isrcdst,M32C_CheckGAMBoth},
{0xff810f,0x098101,"cmp_l_g_srcidst",3		,m32c_cmp_l_g_srcidst,M32C_CheckGAMBoth},
{0xff810f,0x498101,"cmp_l_g_isrcidst",3		,m32c_cmp_l_g_isrcidst,M32C_CheckGAMBoth},
{0x0000fe,0x000050,"cmp_size_s_srcr0",1		,m32c_cmp_size_s_srcr0},
{0x0000fe,0x000060,"cmp_size_s_srcr0",1		,m32c_cmp_size_s_srcr0},
{0x0000fe,0x000070,"cmp_size_s_srcr0",1		,m32c_cmp_size_s_srcr0},
{0x00fffe,0x000950,"cmp_size_s_isrcr0",2	,m32c_cmp_size_s_isrcr0},
{0x00fffe,0x000960,"cmp_size_s_isrcr0",2	,m32c_cmp_size_s_isrcr0},
{0x00fffe,0x000970,"cmp_size_s_isrcr0",2	,m32c_cmp_size_s_isrcr0},
{0x00f13f,0x00a011,"cmpx_immdst",2		,m32c_cmpx_immdst,M32C_CheckGAMLow},
{0xfff13f,0x09a011,"cmpx_immidst",3		,m32c_cmpx_immidst,M32C_CheckGAMLow},
{0xfff03f,0x01800e,"dadc_size_immdst",3		,m32c_dadc_size_immdst,M32C_CheckGAMLow},
{0xff800f,0x018008,"dadc_size_srcdst",3		,m32c_dadc_size_srcdst,M32C_CheckGAMBoth},
{0xfff03f,0x01801e,"dadd_size_immdst",3		,m32c_dadd_size_immdst,M32C_CheckGAMLow},
{0xff800f,0x018000,"dadd_size_srcdst",3		,m32c_dadd_size_srcdst,M32C_CheckGAMBoth},
{0x00f03f,0x00b00e,"dec_size_dst",2		,m32c_dec_size_dst,M32C_CheckGAMLow},
{0xfff03f,0x09b00e,"dec_size_idst",3		,m32c_dec_size_idst,M32C_CheckGAMLow},
{0x00ffef,0x00b043,"div_size_imm",2		,m32c_div_size_imm},
{0x00f03f,0x00801e,"div_size_src",2		,m32c_div_size_src,M32C_CheckGAMLow},
{0xfff03f,0x09801e,"div_size_isrc",3		,m32c_div_size_isrc,M32C_CheckGAMLow},
{0xfff13f,0x01a11f,"div_l_src",3		,m32c_div_l_src,M32C_CheckGAMLow},
{0x00ffef,0x00b003,"divu_size_imm",2		,m32c_divu_size_imm},
{0x00f03f,0x00800e,"divu_size_src",2		,m32c_divu_size_src,M32C_CheckGAMLow},
{0xfff03f,0x09800e,"divu_size_isrc",3		,m32c_divu_size_isrc,M32C_CheckGAMLow},
{0xfff13f,0x01a10f,"divu_l_src",3		,m32c_divu_l_src,M32C_CheckGAMLow},
{0x00ffef,0x00b243,"divx_size_imm",2		,m32c_divx_size_imm},
{0x00f03f,0x00901e,"divx_size_src",2		,m32c_divx_size_src,M32C_CheckGAMLow},
{0xfff03f,0x09901e,"divx_size_isrc",3		,m32c_divx_size_isrc,M32C_CheckGAMLow},
{0xfff13f,0x01a12f,"divx_l_src",3		,m32c_divx_l_src,M32C_CheckGAMLow},
{0xfff03f,0x01900e,"dsbb_size_immdst",3		,m32c_dsbb_size_immdst,M32C_CheckGAMLow},
{0xff800f,0x01800a,"dsbb_size_srcdst",3		,m32c_dsbb_size_srcdst,M32C_CheckGAMBoth},
{0xfff03f,0x01901e,"dsub_size_immdst",3		,m32c_dsub_size_immdst,M32C_CheckGAMLow},
{0xff800f,0x018002,"dsub_size_srcdst",3		,m32c_dsub_size_srcdst,M32C_CheckGAMBoth},
{0x0000ff,0x0000ec,"enter_imm",1		,m32c_enter_imm},
{0x0000ff,0x0000fc,"exitd",1			,m32c_exitd},
{0x00f03f,0x00c01e,"exts_size_dst",2		,m32c_exts_size_dst,M32C_CheckGAMLow},
{0xff810f,0x018007,"exts_b_src_dst",3		,m32c_exts_b_src_dst,M32C_CheckGAMBoth},
{0xff810f,0x01800b,"extz_src_dst",3		,m32c_extz_src_dst,M32C_CheckGAMBoth},
{0x00fff8,0x00d3e8,"fclr_dst",2			,m32c_fclr},
{0x0000ff,0x00009f,"freit",1			,m32c_freit},
{0x00fff8,0x00d1e8,"fset",2			,m32c_fset},
{0x00f03f,0x00a00e,"inc_size_dst",2		,m32c_inc_size_dst,M32C_CheckGAMLow},
{0xfff03f,0x09a00e,"inc_size_idst",3		,m32c_inc_size_idst,M32C_CheckGAMLow},
{0x00f12f,0x008003,"indexb_size_src",2		,m32c_indexb_size_src,M32C_CheckGAMLow},
{0x00f12f,0x00a003,"indexbd_size_src",2		,m32c_indexbd_size_src,M32C_CheckGAMLow},
{0x00f12f,0x00c003,"indexbs_size_src",2		,m32c_indexbs_size_src,M32C_CheckGAMLow},
{0x00f12f,0x009023,"indexl_size_src",2		,m32c_indexl_size_src,M32C_CheckGAMLow},
{0x00f12f,0x00b023,"indexld_size_src",2		,m32c_indexld_size_src,M32C_CheckGAMLow},
{0x00f12f,0x009003,"indexls_size_src",2		,m32c_indexls_size_src,M32C_CheckGAMLow},
{0x00f12f,0x008023,"indexw_size_src",2		,m32c_indexw_size_src,M32C_CheckGAMLow},
{0x00f12f,0x00a023,"indexwd_size_src",2		,m32c_indexwd_size_src,M32C_CheckGAMLow},
{0x00f12f,0x00c023,"indexws_size_src",2		,m32c_indexws_size_src,M32C_CheckGAMLow},
{0x0000ff,0x0000be,"int_imm",1			,m32c_int_imm},
{0x0000ff,0x0000bf,"into",1			,m32c_into},
{0x00008e,0x00008a,"jcnd",1			,m32c_jcnd},
{0x0000ce,0x00004a,"jmp_s_label",1		,m32c_jmp_s},
{0x0000ff,0x0000ce,"jmp_w_label",1		,m32c_jmp_w},
{0x0000ff,0x0000cc,"jmp_a_label",1		,m32c_jmp_a},
{0x00f13f,0x00c10f,"jmpi_w_src",2		,m32c_jmpi_w_src,M32C_CheckGAMLow},
{0x00f13f,0x008001,"jmpi_a_src",2		,m32c_jmpi_a_src,M32C_CheckGAMLow},
{0x0000ff,0x0000dc,"jmps_imm8",1		,m32c_jmps_imm8},
{0x0000ff,0x0000cf,"jsr_w_label",1		,m32c_jsr_w_label},
{0x0000ff,0x0000cd,"jsr_a_label",1		,m32c_jsr_a_label},
{0x00f13f,0x00c11f,"jsri_w_src",2		,m32c_jsri_w_src,M32C_CheckGAMLow},
{0x00f13f,0x009001,"jsri_a_src",2		,m32c_jsri_a_src,M32C_CheckGAMLow},
{0x0000ff,0x0000dd,"jsrs_imm8",1		,m32c_jsrs_imm8},
{0x00fff8,0x00d5a8,"ldc_imm16_dst",2		,m32c_ldc_imm16_dst},
{0x00fff8,0x00d528,"ldc_imm24_dst",2		,m32c_ldc_imm24_dst},
{0x00fff8,0x00d568,"ldc_imm24_dst2",2		,m32c_ldc_imm24_dst2},
{0xfff138,0x01d108,"ldc_src_dst",3		,m32c_ldc_src_dst,M32C_CheckGAMLow},
{0x00f138,0x00d100,"ldc_src_dst2",2		,m32c_ldc_src_dst2,M32C_CheckGAMLow},
{0xfff138,0x01d100,"ldc_src_dst3",3		,m32c_ldc_src_dst3,M32C_CheckGAMLow},
{0x00ffff,0x00b6c3,"ldctx_abs16_abs24",2	,m32c_ldctx},
{0x00fff8,0x00d5e8,"ldipl_imm",2		,m32c_ldipl_imm},
{0xfff03f,0x01803f,"max_size_immdst",3		,m32c_max_size_immdst,M32C_CheckGAMLow},
{0xff800f,0x01800d,"max_size_srcdst",3		,m32c_max_size_srcdst,M32C_CheckGAMBoth},
{0xfff03f,0x01802f,"min_size_immdst",3		,m32c_min_size_immdst,M32C_CheckGAMLow},
{0xff800f,0x01800c,"min_size_srcdst",3		,m32c_min_size_srcdst,M32C_CheckGAMBoth},
{0x00f03f,0x00902f,"mov_size_g_immdst",2	,m32c_mov_size_g_immdst,M32C_CheckGAMLow},
{0xfff03f,0x09902f,"mov_size_g_immidst",3	,m32c_mov_size_g_immidst,M32C_CheckGAMLow},
{0x00f13f,0x00b031,"mov_l_g_immdst",2		,m32c_mov_l_g_immdst,M32C_CheckGAMLow},
{0xfff13f,0x09b031,"mov_l_g_immidst",3		,m32c_mov_l_g_immidst,M32C_CheckGAMLow},
{0x00f030,0x00f020,"mov_size_q_imm4dst",2	,m32c_mov_size_q_imm4dst,M32C_CheckGAMLow},
{0xfff030,0x09f020,"mov_size_q_imm4idst",3	,m32c_mov_size_q_imm4idst,M32C_CheckGAMLow},
{0x0000ce,0x000004,"mov_size_s_immdst",1	,m32c_mov_size_s_immdst},
{0x00ffce,0x000904,"mov_size_s_immidst",2	,m32c_mov_size_s_immidst},
{0x0000de,0x00009c,"mov_size_s_imma0a1",1	,m32c_mov_size_s_imma0a1},
{0x0000ce,0x000002,"mov_size_z_0dst",1		,m32c_mov_size_z_0dst},
{0x00ffce,0x000902,"mov_size_z_0idst",2		,m32c_mov_size_z_0idst},
{0x00800f,0x00800b,"mov_size_g_srcdst",2	,m32c_mov_size_g_srcdst,M32C_CheckGAMBoth},
{0xff800f,0x41800b,"mov_size_g_isrcdst",3	,m32c_mov_size_g_isrcdst,M32C_CheckGAMBoth},
{0xff800f,0x09800b,"mov_size_g_srcidst",3	,m32c_mov_size_g_srcidst,M32C_CheckGAMBoth},
{0xff800f,0x49800b,"mov_size_g_isrcidst",3	,m32c_mov_size_g_isrcidst,M32C_CheckGAMBoth},
{0x00810f,0x008103,"mov_l_g_srcdst",2		,m32c_mov_l_g_srcdst,M32C_CheckGAMBoth},
{0xff810f,0x418103,"mov_l_g_isrcdst",3		,m32c_mov_l_g_isrcdst,M32C_CheckGAMBoth},
{0xff810f,0x098103,"mov_l_g_srcidst",3		,m32c_mov_l_g_srcidst,M32C_CheckGAMBoth},
{0xff810f,0x498103,"mov_l_g_isrcidst",3		,m32c_mov_l_g_isrcidst,M32C_CheckGAMBoth},
{0x0000fe,0x000018,"mov_size_s_srcr0",1		,m32c_mov_size_src_r0},
{0x0000fe,0x000028,"mov_size_s_srcr0",1		,m32c_mov_size_src_r0},
{0x0000fe,0x000038,"mov_size_s_srcr0",1		,m32c_mov_size_src_r0},
{0x00fffe,0x000918,"mov_size_s_isrcr0",2	,m32c_mov_size_isrc_r0},
{0x00fffe,0x000928,"mov_size_s_isrcr0",2	,m32c_mov_size_isrc_r0},
{0x00fffe,0x000938,"mov_size_s_isrcr0",2	,m32c_mov_size_isrc_r0},
{0x0000ce,0x00004e,"mov_size_s_srcr1",1		,m32c_mov_size_src_r1},
{0x00ffce,0x00094e,"mov_size_s_isrcr1",2	,m32c_mov_size_isrc_r1},
{0x0000fe,0x000010,"mov_size_s_r0dst",1		,m32c_mov_size_r0dst},
{0x0000fe,0x000020,"mov_size_s_r0dst",1		,m32c_mov_size_r0dst},
{0x0000fe,0x000030,"mov_size_s_r0dst",1		,m32c_mov_size_r0dst},
{0x00fffe,0x000910,"mov_size_s_r0idst",2	,m32c_mov_size_r0idst},
{0x00fffe,0x000920,"mov_size_s_r0idst",2	,m32c_mov_size_r0idst},
{0x00fffe,0x000930,"mov_size_s_r0idst",2	,m32c_mov_size_r0idst},
{0x0000fe,0x000058,"mov_l_s_srca0a1",1		,m32c_mov_l_s_srca0a1},
{0x0000fe,0x000068,"mov_l_s_srca0a1",1		,m32c_mov_l_s_srca0a1},
{0x0000fe,0x000078,"mov_l_s_srca0a1",1		,m32c_mov_l_s_srca0a1},
/* Wrong in Manual ! Not srcia0a1 ! */
{0x00fffe,0x000958,"mov_l_s_isrca0a1",2		,m32c_mov_l_s_isrca0a1},
{0x00fffe,0x000968,"mov_l_s_isrca0a1",2		,m32c_mov_l_s_isrca0a1},
{0x00fffe,0x000978,"mov_l_s_isrca0a1",2		,m32c_mov_l_s_isrca0a1},
{0x00f03f,0x00b00f,"mov_size_g_dsp8spdst",2	,m32c_mov_size_g_dsp8spdst,M32C_CheckGAMLow},
{0x00f03f,0x00a00f,"mov_size_g_srcdsp8sp",2	,m32c_mov_size_g_srcdsp8sp,M32C_CheckGAMLow},
{0x00f138,0x00d118,"mova_srcdst",2		,m32c_mova_srcdst,M32C_CheckGAMLow},
{0xfff10e,0x01b00e,"movdir_r0ldst",3		,m32c_movdir_r0ldst,M32C_CheckGAMLow},
{0xfff10e,0x01a00e,"movdir_srcr0l",3		,m32c_movdir_srcr0l,M32C_CheckGAMLow},
{0x00f13f,0x00b011,"movx_immdst",2		,m32c_movx_immdst,M32C_CheckGAMLow},
{0xfff13f,0x09b011,"movx_immidst",3		,m32c_movx_immidst,M32C_CheckGAMLow},
{0x00f03f,0x00801f,"mul_size_immdst",2		,m32c_mul_size_immdst,M32C_CheckGAMLow},
{0xfff03f,0x09801f,"mul_size_immidst",3		,m32c_mul_size_immidst,M32C_CheckGAMLow},
{0x00800f,0x00800c,"mul_size_srcdst",2		,m32c_mul_size_srcdst,M32C_CheckGAMBoth},
{0xff800f,0x41800c,"mul_size_isrcdst",3		,m32c_mul_size_isrcdst,M32C_CheckGAMBoth},
{0xff800f,0x09800c,"mul_size_srcidst",3		,m32c_mul_size_srcidst,M32C_CheckGAMBoth},
{0xff800f,0x49800c,"mul_size_isrcidst",3	,m32c_mul_size_isrcidst},
{0xfff13f,0x01811f,"mul_l_srcr2r0",3		,m32c_mul_l_srcr2r0,M32C_CheckGAMLow},
{0x00f13f,0x00c13e,"mulex_src",2		,m32c_mulex_src,M32C_CheckGAMLow},
{0xfff13f,0x09c13e,"mulex_isrc",3		,m32c_mulex_isrc,M32C_CheckGAMLow},
{0x00f03f,0x00800f,"mulu_size_immdst",2		,m32c_mulu_size_immdst,M32C_CheckGAMLow},
{0xfff03f,0x09800f,"mulu_size_immidst",3	,m32c_mulu_size_immidst,M32C_CheckGAMLow},
{0x00800f,0x008004,"mulu_size_srcdst",2		,m32c_mulu_size_srcdst,M32C_CheckGAMBoth},
{0xff800f,0x418004,"mulu_size_isrcdst",3	,m32c_mulu_size_isrcdst,M32C_CheckGAMBoth},
{0xff800f,0x098004,"mulu_size_srcidst",3	,m32c_mulu_size_srcidst,M32C_CheckGAMBoth},
{0xff800f,0x498004,"mulu_size_isrcidst",3	,m32c_mulu_size_isrcidst,M32C_CheckGAMBoth},
{0xfff13f,0x01810f,"mulu_l_srcr2r0",3		,m32c_mulu_l_srcr2r0,M32C_CheckGAMLow},
{0x00f03f,0x00a02f,"neg_size_dst",2		,m32c_neg_size_dst,M32C_CheckGAMLow},
{0xfff03f,0x09a02f,"neg_size_idst",3		,m32c_neg_size_idst,M32C_CheckGAMLow},
{0x0000ff,0x0000de,"nop",1			,m32c_nop},
{0x00f03f,0x00a01e,"not_size_dst",2		,m32c_not_size_dst,M32C_CheckGAMLow},
{0xfff03f,0x09a01e,"not_size_idst",3		,m32c_not_size_idst,M32C_CheckGAMLow},
{0x00f03f,0x00802f,"or_size_g_immdst",2		,m32c_or_size_g_immdst,M32C_CheckGAMLow},
{0xfff03f,0x09802f,"or_size_g_immidst",3	,m32c_or_size_g_immidst,M32C_CheckGAMLow},
{0x0000ce,0x000044,"or_size_s_immdst",1		,m32c_or_size_s_immdst},
{0x00ffce,0x000944,"or_size_s_immidst",2	,m32c_or_size_s_immidst},
{0x00800f,0x008005,"or_size_g_srcdst",2		,m32c_or_size_srcdst,M32C_CheckGAMBoth},
{0xff800f,0x418005,"or_size_g_isrcdst",3	,m32c_or_size_isrcdst,M32C_CheckGAMBoth},
{0xff800f,0x098005,"or_size_g_srcidst",3	,m32c_or_size_srcidst,M32C_CheckGAMBoth},
{0xff800f,0x498005,"or_size_g_isrcidst",3	,m32c_or_size_isrcidst,M32C_CheckGAMBoth},
{0x00f03f,0x00b02f,"pop_size_dst",2		,m32c_pop_size_dst,M32C_CheckGAMLow},
{0xfff03f,0x09b02f,"pop_size_idst",3		,m32c_pop_size_idst,M32C_CheckGAMLow},
{0x00fff8,0x00d3a8,"popc_dst1",2		,m32c_popc_dst1},
{0x00fff8,0x00d328,"popc_dst2",2		,m32c_popc_dst2},
{0x0000ff,0x00008e,"popm_dst",1			,m32c_popm_dst},
{0x0000fe,0x0000ae,"push_size_imm",1		,m32c_push_size_imm},
{0x00f03f,0x00c00e,"push_size_src",2		,m32c_push_size_src,M32C_CheckGAMLow},
{0xfff03f,0x09c00e,"push_size_isrc",3		,m32c_push_size_isrc,M32C_CheckGAMLow},
{0x00ffff,0x00b653,"push_l_imm32",2		,m32c_push_l_imm32},
{0x00f13f,0x00a001,"push_l_src",2		,m32c_push_l_src,M32C_CheckGAMLow},
{0xfff13f,0x09a001,"push_l_isrc",3		,m32c_push_l_isrc,M32C_CheckGAMLow},
{0x00f13f,0x00b001,"pusha_src",2		,m32c_pusha_src,M32C_CheckGAMLow},
{0x00fff8,0x00d1a8,"pushc_src1",2		,m32c_pushc_src1},
{0x00fff8,0x00d128,"pushc_src2",2		,m32c_pushc_src2},
{0x0000ff,0x00008f,"pushm_src",1		,m32c_pushm_src},
{0x0000ff,0x00009e,"reit",1			,m32c_reit},
{0x00ffef,0x00b843,"rmpa_size",2		,m32c_rmpa_size},
{0x00f03f,0x00b02e,"rolc_size_dst",2		,m32c_rolc_size_dst,M32C_CheckGAMLow},
{0xfff03f,0x09b02e,"rolc_size_idst",3		,m32c_rolc_size_idst,M32C_CheckGAMLow},
{0x00f03f,0x00a02e,"rorc_size_dst",2		,m32c_rorc_size_dst,M32C_CheckGAMLow},
{0xfff03f,0x09a02e,"rorc_size_idst",3		,m32c_rorc_size_idst,M32C_CheckGAMLow},
{0x00f030,0x00e020,"rot_size_immdst",2		,m32c_rot_size_immdst,M32C_CheckGAMLow},
{0xfff030,0x09e020,"rot_size_immidst",3		,m32c_rot_size_immidst,M32C_CheckGAMLow},
{0x00f03f,0x00a03f,"rot_size_r1hdst",2		,m32c_rot_size_r1hdst,M32C_CheckGAMLow},
{0xfff03f,0x09a03f,"rot_size_r1hidst",3		,m32c_rot_size_r1hidst,M32C_CheckGAMLow},
{0x0000ff,0x0000df,"rts",1			,m32c_rts},
{0xfff03f,0x01902e,"sbb_size_immdst",3		,m32c_sbb_size_immdst,M32C_CheckGAMLow},
{0xff800f,0x018006,"sbb_size_srcdst",3		,m32c_sbb_size_srcdst,M32C_CheckGAMBoth},
/* sbjnz is the same as adjnz */
{0x00f130,0x00d130,"sccnd_dst",2		,m32c_sccnd_dst,M32C_CheckGAMLow},
{0xfff130,0x09d130,"sccnd_idst",3		,m32c_sccnd_idst,M32C_CheckGAMLow},
{0x00ffef,0x00b8c3,"scmpu_size",2		,m32c_scmpu_size},
{0x00f030,0x00f000,"sha_size_immdst",2		,m32c_sha_size_immdst,M32C_CheckGAMLow},
{0xfff030,0x09f000,"sha_size_immidst",3		,m32c_sha_size_immidst,M32C_CheckGAMLow},
{0x00f13f,0x00a021,"sha_l_immdst",2		,m32c_sha_l_immdst,M32C_CheckGAMLow},
{0xfff13f,0x09a021,"sha_l_immidst",3		,m32c_sha_l_immidst,M32C_CheckGAMLow},
{0x00f03f,0x00b03e,"sha_size_r1hdst",2		,m32c_sha_size_r1hdst,M32C_CheckGAMLow},
{0xfff03f,0x09b03e,"sha_size_r1hidst",3		,m32c_sha_size_r1hidst,M32C_CheckGAMLow},
{0x00f13f,0x00c011,"sha_l_r1hdst",2		,m32c_sha_l_r1hdst,M32C_CheckGAMLow},
{0xfff13f,0x09c011,"sha_l_r1hidst",3		,m32c_sha_l_r1hidst,M32C_CheckGAMLow},
{0x00f13f,0x00c021,"shanc_l_immdst",2		,m32c_shanc_l_immdst,M32C_CheckGAMLow},
{0xfff13f,0x09c021,"shanc_l_immidst",3		,m32c_shanc_l_immidst,M32C_CheckGAMLow},
{0x00f030,0x00e000,"shl_size_immdst",2		,m32c_shl_size_immdst,M32C_CheckGAMLow},
{0xfff030,0x09e000,"shl_size_immidst",3		,m32c_shl_size_immidst,M32C_CheckGAMLow},
{0x00f13f,0x009021,"shl_l_immdst",2		,m32c_shl_l_immdst,M32C_CheckGAMLow},
{0xfff13f,0x099021,"shl_l_immidst",3		,m32c_shl_l_immidst,M32C_CheckGAMLow},
{0x00f03f,0x00a03e,"shl_size_r1hdst",2		,m32c_shl_size_r1hdst,M32C_CheckGAMLow},
{0xfff03f,0x09a03e,"shl_size_r1hidst",3		,m32c_shl_size_r1hidst,M32C_CheckGAMLow},
{0x00f13f,0x00c001,"shl_l_r1hdst",2		,m32c_shl_l_r1hdst,M32C_CheckGAMLow},
{0xfff13f,0x09c001,"shl_l_r1hidst",3		,m32c_shl_l_r1hidst,M32C_CheckGAMLow},
{0x00f13f,0x008021,"shlnc_l_immdst",2		,m32c_shlnc_l_immdst,M32C_CheckGAMLow},
{0xfff13f,0x098021,"shlnc_l_immidst",3		,m32c_shlnc_l_immidst,M32C_CheckGAMLow},
{0x00ffef,0x00b283,"sin_size",2			,m32c_sin_size},
{0x00ffef,0x00b683,"smovb_size",2		,m32c_smovb_size},
{0x00ffef,0x00b083,"smovf_size",2		,m32c_smovf_size},
{0x00ffef,0x00b883,"smovu_size",2		,m32c_smovu_size},
{0x00ffef,0x00b483,"sout_size",2		,m32c_sout_size},
{0x00ffef,0x00b803,"sstr_size",2		,m32c_sstr_size},
{0xfff138,0x01d110,"stc_srcdst1",3		,m32c_stc_srcdst1,M32C_CheckGAMLow},
{0xfff138,0x01d118,"stc_srcdst2",3		,m32c_stc_srcdst2,M32C_CheckGAMLow},
{0x00f138,0x00d110,"stc_srcdst3",2		,m32c_stc_srcdst3,M32C_CheckGAMLow},
{0x00ffff,0x00b6d3,"stctx_abs16abs24",2		,m32c_stctx_abs16abs24},
{0x00f03f,0x00901f,"stnz_size_immdst",2		,m32c_stnz_size_immdst,M32C_CheckGAMLow},
{0xfff03f,0x09901f,"stnz_size_immidst",3	,m32c_stnz_size_immidst,M32C_CheckGAMLow},
{0x00f03f,0x00900f,"stz_size_immdst",2		,m32c_stz_size_immdst,M32C_CheckGAMLow},
{0xfff03f,0x09900f,"stz_size_immidst",3		,m32c_stz_size_immidst,M32C_CheckGAMLow},
{0x00f03f,0x00903f,"stzx_size_imm1imm2dst",2	,m32c_stzx_size_imm1imm2dst,M32C_CheckGAMLow},
{0xfff03f,0x09903f,"stzx_size_imm1imm2idst",3	,m32c_stzx_size_imm1imm2idst,M32C_CheckGAMLow},
{0x00f03f,0x00803e,"sub_size_g_immdst",2	,m32c_sub_size_g_immdst,M32C_CheckGAMLow},
{0xfff03f,0x09803e,"sub_size_g_immidst",3	,m32c_sub_size_g_immidst,M32C_CheckGAMLow},
{0x00f13f,0x009031,"sub_l_g_immdst",2		,m32c_sub_l_g_immdst,M32C_CheckGAMLow},
{0xfff13f,0x099031,"sub_l_g_immidst",3		,m32c_sub_l_g_immidst,M32C_CheckGAMLow},
{0x0000ce,0x00000e,"sub_size_s_immdst",1	,m32c_sub_size_s_immdst},
{0x00ffce,0x00090e,"sub_size_s_immidst",2	,m32c_sub_size_s_immidst},
{0x00800f,0x00800a,"sub_size_g_srcdst",2	,m32c_sub_size_g_srcdst,M32C_CheckGAMBoth},
{0xff800f,0x41800a,"sub_size_g_isrcdst",3	,m32c_sub_size_g_isrcdst,M32C_CheckGAMBoth},
{0xff800f,0x09800a,"sub_size_g_srcidst",3	,m32c_sub_size_g_srcidst,M32C_CheckGAMBoth},
{0xff800f,0x49800a,"sub_size_g_isrcidst",3	,m32c_sub_size_g_isrcidst,M32C_CheckGAMBoth},
{0x00810f,0x008100,"sub_l_g_srcdst",2		,m32c_sub_l_g_srcdst,M32C_CheckGAMBoth},
{0xff810f,0x418100,"sub_l_g_isrcdst",3		,m32c_sub_l_g_isrcdst,M32C_CheckGAMBoth},
{0xff810f,0x098100,"sub_l_g_srcidst",3		,m32c_sub_l_g_srcidst,M32C_CheckGAMBoth},
{0xff810f,0x498100,"sub_l_g_isrcidst",3		,m32c_sub_l_g_isrcidst},
{0x00f13f,0x009011,"subx_immdst",2		,m32c_subx_immdst,M32C_CheckGAMLow},
{0xfff13f,0x099011,"subx_immidst",3		,m32c_subx_immidst,M32C_CheckGAMLow},
{0x00810f,0x008000,"subx_srcdst",2		,m32c_subx_srcdst,M32C_CheckGAMBoth},
{0xff810f,0x418000,"subx_isrcdst",3		,m32c_subx_isrcdst,M32C_CheckGAMBoth},
{0xff810f,0x098000,"subx_srcidst",3		,m32c_subx_srcidst,M32C_CheckGAMBoth},
{0xff810f,0x498000,"subx_isrcidst",3		,m32c_subx_isrcidst,M32C_CheckGAMBoth},
{0x00f03f,0x00903e,"tst_size_g_immdst",2	,m32c_tst_size_g_immdst,M32C_CheckGAMLow},
{0x0000ce,0x00000c,"tst_size_s_immdst",1	,m32c_tst_size_s_immdst},
{0xff800f,0x018009,"tst_size_g_srcdst",3	,m32c_tst_size_g_srcdst,M32C_CheckGAMBoth},
{0x0000ff,0x0000ff,"und",1			,m32c_und},
{0x00ffff,0x00b203,"wait",2			,m32c_wait},
{0x00f038,0x00d008,"xchg_srcdst",2		,m32c_xchg_srcdst,M32C_CheckGAMLow},
{0xfff038,0x09d008,"xchg_srcidst",3		,m32c_xchg_srcidst,M32C_CheckGAMLow},
{0x00f03f,0x00900e,"xor_size_immdst",2		,m32c_xor_immdst,M32C_CheckGAMLow},
{0x00800f,0x008009,"xor_size_srcdst",2		,m32c_xor_srcdst,M32C_CheckGAMBoth},
{0xff800f,0x418009,"xor_size_isrcdst",3		,m32c_xor_isrcdst,M32C_CheckGAMBoth},
{0xff800f,0x098009,"xor_size_srcidst",3		,m32c_xor_srcidst,M32C_CheckGAMBoth},
{0xff800f,0x498009,"xor_size_isrcidst",3	,m32c_xor_isrcidst,M32C_CheckGAMBoth},
};

static M32C_Instruction instr_und = {0x0000ff,0x0000ff,"und",1			,m32c_und};

/**
 *************************************************************************
 * \fn static void Verify_InstrList(void) 
 * Do some consistency checks on instruction list
 *************************************************************************
 */
static void
Verify_InstrList(void) {
	M32C_Instruction *instr;
	M32C_Instruction *instr2;
	int instrcnt;
	int instrlen;
	int i,j;
	instrcnt = array_size(instrlist);
	for(i = 0; i < instrcnt; i++) {
		instr = &instrlist[i];
		if((instr->icode & instr->mask) != instr->icode) {
			fprintf(stderr,"Bad instruction in list: %s\n",instr->name);
			exit(1);
		}
		instrlen = 0;
		if(instr->mask & 0xff) {
			instrlen++;
		}
		if(instr->mask & 0xff00) {
			instrlen++;
		}
		if(instr->mask & 0xff0000) {
			instrlen++;
		}
		if(instr->len != instrlen) {
			fprintf(stderr,"Bad Instruction len in list: %s\n",instr->name);
			fprintf(stderr,"bad %s, %d %d\n",instr->name,instr->len,instrlen);
			exit(1);
		}
	
	}
	/* Cross instruction check */
	for(i = 0; i < instrcnt; i++) {
		instr = &instrlist[i];
		for(j = 0; j < instrcnt; j++) {
			if(i == j) {
				continue;
			}
			instr2 = &instrlist[j];
			if((instr->icode & instr2->mask) == instr2->icode) {
				if((instr2->icode & instr->mask) == instr->icode) {
					fprintf(stderr,"Cross match %s(%06x) and %s(%06x)\n",instr->name,instr->icode,instr2->name,instr2->icode);
					exit(1);
				}
			}
		}
	}
	fprintf(stderr,"Verification of Instruction list successful\n");
}


/**
 **************************************************************************
 * Do a instruction decoding by walking through the complete table
 **************************************************************************
 */
M32C_Instruction *
idecode_slow(uint32_t icode) 
{
	M32C_Instruction *cursor,*instr = NULL;
	int debug = 0;
	int i;
	int instrcnt = array_size(instrlist);
#if 0
	if(icode == 0x01e00e) {
		debug = 1;
	} else {
		debug = 0;
	}
#endif
	for(i=0;i<instrcnt;i++) {
		cursor = &instrlist[i];	
		if((icode & cursor->mask) == cursor->icode) {
			if(debug) {
				fprintf(stderr,"Match %s\n",cursor->name);
			}
			if(cursor->existCheckProc) {
				bool exists = cursor->existCheckProc(cursor,icode);
				if(!exists) {
					continue;
				}
			}
			if(instr) {
				fprintf(stderr,"Instruction already exists for icode 0x%06x %s, %s\n",
					icode,instr->name,cursor->name);
				exit(1);
			}
			instr = cursor;
		} 
	}
	if(!instr) {
		return &instr_und;
	}
	return instr;	
}

static __UNUSED__ void
Find_Dont_MatterBits(void) 
{
	int i,j;
	M32C_Instruction *instr1,*instr2;
	for(j=0;j<24;j++) {
		int matter = 0;
		for(i=0;i<16777216;i++) {
			instr1 = idecode_slow(i);
			instr2 = idecode_slow(i ^ (1 << j)); 
			if(instr1 != instr2) {
				matter++;
				//break;
			}
		}
		if(matter) {
			fprintf(stderr,"%d matters because of %d\n",j,matter);	
		} else {
			fprintf(stderr,"%d doesn't matter\n",j);	
		}
	}
}

static __UNUSED__ void
TestIdecoder(void) {
	int i;
	M32C_Instruction *instr;
	for(i=0;i< 16777216;i++) {
		instr = M32C_InstructionFind(i); 	
		if(idecode_slow(i) != instr) {
			fprintf(stderr,"Shit at %s, %s, icode %06x\n",instr->name,idecode_slow(i)->name,i);
			exit(1);
		}
	}
	fprintf(stderr,"Idecoder good\n");
}

void
M32C_IDecoderNew(void) 
{
	int i,j;
	int instrcnt = array_size(instrlist);
	M32C_Instruction *instr;
	Verify_InstrList();
	for(i = 0;i < instrcnt;i++) {
		instr = &instrlist[i];
		if(instr->len == 1) {
			instr->icode  <<= 16;
			instr->mask <<= 16;
		}
		if(instr->len == 2) {
			instr->icode  <<= 8;
			instr->mask <<= 8;
		}
	}
#if 0
	for(i = 0;i < instrcnt;i++) {
		instr = &instrlist[i];
		instr->icode = ((instr->icode & 0xff) << 16) 
			| ((instr->icode & 0xff00)) 
			| ((instr->icode & 0xff0000) >> 16);
		instr->mask = ((instr->mask & 0xff) << 16) 
			| ((instr->mask & 0xff00)) 
			| ((instr->mask & 0xff0000) >> 16);
	}
#endif
	m32c_iTab=sg_calloc(0x10000*sizeof(M32C_Instruction*));
	for(i = 0;i < 65536;i++) {
		int icode = i << 8;	
		int twolevel = 0;
		instr = idecode_slow(icode);
		if((instr->mask & 0xff) != 0) {
			for(j = 0;j < 8; j++) {
				icode = (i << 8) | (1 << j);	
				if(instr != idecode_slow(icode)) {
					twolevel = 1;
					break;
				}
			}
		}
		if(!twolevel) {
			m32c_iTab[i] = instr;
		} else {
			m32c_iTab[i] = NULL;
			m32c_iTab[i] = sg_new(M32C_Instruction);
			m32c_iTab[i]->iTab = sg_calloc(256 * sizeof(M32C_Instruction *));
			for(j = 0; j < 256;j++) {
				icode = (i << 8) | j;	
				instr = idecode_slow(icode);
				m32c_iTab[i]->iTab[j] = instr;	
			}
		}
	}
	fprintf(stderr,"M32C Instruction decoder initialized\n");
#if 0
	TestIdecoder(); 
	exit(1);
#endif
}
