/* OpenIDA - Outil d'analyse de fichiers binaires
 * processor.c - gestion de l'architecture x86
 *
 * Copyright (C) 2008-2010 Cyrille Bagard
 *
 *  This file is part of OpenIDA.
 *
 *  OpenIDA 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 3 of the License, or
 *  (at your option) any later version.
 *
 *  OpenIDA 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
 */


#include "processor.h"


#include "opcodes/opcodes.h"
#include "../processor-int.h"



/* Définition du processeur de la x86 (instance) */
struct _GX86Processor
{
    GArchProcessor parent;                  /* Instance parente            */

};


/* Définition du processeur de la x86 (classe) */
struct _GX86ProcessorClass
{
    GArchProcessorClass parent;             /* Classe parente              */

};


/* Initialise la classe des lignes de descriptions initiales. */
static void g_x86_processor_class_init(GX86ProcessorClass *);

/* Initialise la classe des lignes de descriptions initiales. */
static void g_x86_processor_init(GX86Processor *);

/* Décode une instruction dans un flux de données. */
static GArchInstruction *g_x86_processor_decode_instruction(const GX86Processor *, const bin_t *, off_t *, off_t, vmpa_t);


/* Indique le type défini par la GLib pour le processeur x86. */
G_DEFINE_TYPE(GX86Processor, g_x86_processor, G_TYPE_ARCH_PROCESSOR);



/******************************************************************************
*                                                                             *
*  Paramètres  : klass = classe à initialiser.                                *
*                                                                             *
*  Description : Initialise la classe des lignes de descriptions initiales.   *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_x86_processor_class_init(GX86ProcessorClass *klass)
{

}


/******************************************************************************
*                                                                             *
*  Paramètres  : proc = instance à initialiser.                               *
*                                                                             *
*  Description : Initialise la classe des lignes de descriptions initiales.   *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_x86_processor_init(GX86Processor *proc)
{
    GArchProcessor *parent;                 /* Instance parente            */

    parent = G_ARCH_PROCESSOR(proc);

    parent->endianness = SRE_BIG;
    parent->memsize = MDS_32_BITS;
    parent->inssize = MDS_8_BITS;

    parent->decode = (decode_instruction_fc)g_x86_processor_decode_instruction;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : -                                                            *
*                                                                             *
*  Description : Crée le support de l'architecture x86.                       *
*                                                                             *
*  Retour      : Architecture mise en place.                                  *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GArchProcessor *g_x86_processor_new(void)
{
    GArchProcessor *result;                 /* Structure à retourner       */

    result = g_object_new(G_TYPE_X86_PROCESSOR, NULL);

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : proc   = architecture visée par la consultation.             *
*                prefix = bascule à consulter.                                *
*                                                                             *
*  Description : Fournit la taille supplantée des opérandes pour x86.         *
*                                                                             *
*  Retour      : Taille d'opérande (16 ou 32 bits).                           *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

MemoryDataSize g_x86_processor_get_operand_size(const GX86Processor *proc, X86Prefix prefix)
{
    MemoryDataSize result;                  /* Taille à renvoyer           */

    /* FIXME */

    if (prefix & XPX_OPERAND_SIZE_OVERRIDE)
        result = (MDS_32_BITS/*proc->operand_size*/ == MDS_32_BITS ? MDS_16_BITS : MDS_32_BITS);
 
    else result = MDS_32_BITS/*proc->operand_size*/;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : proc = architecture visée par la procédure.                  *
*                data = flux de données à analyser.                           *
*                pos  = position courante dans ce flux. [OUT]                 *
*                len  = taille totale des données à analyser.                 *
*                addr = adresse virtuelle de l'instruction.                   *
*                                                                             *
*  Description : Décode une instruction dans un flux de données.              *
*                                                                             *
*  Retour      : Instruction mise en place.                                   *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static GArchInstruction *g_x86_processor_decode_instruction(const GX86Processor *proc, const bin_t *data, off_t *pos, off_t len, vmpa_t addr)
{
    GArchInstruction *result;               /* Instruction à renvoyer      */
    X86Prefix prefix;                       /* Préfixes avec l'instr.      */
    bool care;                              /* Traitement des opcodes      */
    X86Opcodes id;                          /* Identifiant d'instruction   */

    static const x86_read_instr decodings[XOP_COUNT] = {

        /* Instructions avec opcode sur un octet */

        [XOP_ADD_RM8_R8]                = x86_read_instr_add_rm8_r8,
        [XOP_ADD_RM1632_R1632]          = x86_read_instr_add_rm1632_r1632,
        [XOP_ADD_R8_RM8]                = x86_read_instr_add_r8_rm8,
        [XOP_ADD_R1632_RM1632]          = x86_read_instr_add_r1632_rm1632,
        [XOP_ADD_AL_IMM8]               = x86_read_instr_add_al_imm8,
        [XOP_ADD_E_AX_IMM1632]          = x86_read_instr_add_e_ax_imm1632,
        [XOP_OR_RM8_R8]                 = x86_read_instr_or_rm8_r8,
        [XOP_OR_RM1632_R1632]           = x86_read_instr_or_rm1632_r1632,
        [XOP_OR_R8_RM8]                 = x86_read_instr_or_r8_rm8,
        [XOP_OR_R1632_RM1632]           = x86_read_instr_or_r1632_rm1632,
        [XOP_OR_AL_IMM8]                = x86_read_instr_or_al_imm8,
        [XOP_ADC_RM8_R8]                = x86_read_instr_adc_rm8_r8,
        [XOP_SBB_RM1632_R1632]          = x86_read_instr_sbb_rm1632_r1632,
        [XOP_AND_RM8_R8]                = x86_read_instr_and_rm8_r8,
        [XOP_AND_RM1632_R1632]          = x86_read_instr_and_rm1632_r1632,
        [XOP_AND_AL_IMM8]               = x86_read_instr_and_al_imm8,
        [XOP_AND_E_AX_IMM1632]          = x86_read_instr_and_e_ax_imm1632,
        [XOP_SUB_RM1632_R1632]          = x86_read_instr_sub_rm1632_r1632,
        [XOP_SUB_R8_RM8]                = x86_read_instr_sub_r8_rm8,
        [XOP_SUB_R1632_RM1632]          = x86_read_instr_sub_r1632_rm1632,
        [XOP_SUB_AL_IMM8]               = x86_read_instr_sub_al_imm8,
        [XOP_SUB_E_AX_IMM1632]          = x86_read_instr_sub_e_ax_imm1632,
        [XOP_XOR_RM8_R8]                = x86_read_instr_xor_rm8_r8,
        [XOP_XOR_RM1632_R1632]          = x86_read_instr_xor_rm1632_r1632,
        [XOP_XOR_R8_RM8]                = x86_read_instr_xor_r8_rm8,
        [XOP_XOR_R1632_RM1632]          = x86_read_instr_xor_r1632_rm1632,
        [XOP_XOR_AL_IMM8]               = x86_read_instr_xor_al_imm8,
        [XOP_XOR_E_AX_IMM1632]          = x86_read_instr_xor_e_ax_imm1632,
        [XOP_CMP_RM8_R8]                = x86_read_instr_cmp_rm8_r8,
        [XOP_CMP_RM1632_R1632]          = x86_read_instr_cmp_rm1632_r1632,
        [XOP_CMP_R8_RM8]                = x86_read_instr_cmp_r8_rm8,
        [XOP_CMP_R1632_RM1632]          = x86_read_instr_cmp_r1632_rm1632,
        [XOP_CMP_AL_IMM8]               = x86_read_instr_cmp_al_imm8,
        [XOP_CMP_E_AX_IMM1632]          = x86_read_instr_cmp_e_ax_imm1632,
        [XOP_INC_E_AX]                  = x86_read_instr_inc_r1632,
        [XOP_INC_E_CX]                  = x86_read_instr_inc_r1632,
        [XOP_INC_E_DX]                  = x86_read_instr_inc_r1632,
        [XOP_INC_E_BX]                  = x86_read_instr_inc_r1632,
        [XOP_INC_E_SP]                  = x86_read_instr_inc_r1632,
        [XOP_INC_E_BP]                  = x86_read_instr_inc_r1632,
        [XOP_INC_E_SI]                  = x86_read_instr_inc_r1632,
        [XOP_INC_E_DI]                  = x86_read_instr_inc_r1632,
        [XOP_DEC_E_AX]                  = x86_read_instr_dec_r1632,
        [XOP_DEC_E_CX]                  = x86_read_instr_dec_r1632,
        [XOP_DEC_E_DX]                  = x86_read_instr_dec_r1632,
        [XOP_DEC_E_BX]                  = x86_read_instr_dec_r1632,
        [XOP_DEC_E_SP]                  = x86_read_instr_dec_r1632,
        [XOP_DEC_E_BP]                  = x86_read_instr_dec_r1632,
        [XOP_DEC_E_SI]                  = x86_read_instr_dec_r1632,
        [XOP_DEC_E_DI]                  = x86_read_instr_dec_r1632,
        [XOP_PUSH_E_AX]                 = x86_read_instr_push_r1632,
        [XOP_PUSH_E_CX]                 = x86_read_instr_push_r1632,
        [XOP_PUSH_E_DX]                 = x86_read_instr_push_r1632,
        [XOP_PUSH_E_BX]                 = x86_read_instr_push_r1632,
        [XOP_PUSH_E_SP]                 = x86_read_instr_push_r1632,
        [XOP_PUSH_E_BP]                 = x86_read_instr_push_r1632,
        [XOP_PUSH_E_SI]                 = x86_read_instr_push_r1632,
        [XOP_PUSH_E_DI]                 = x86_read_instr_push_r1632,
        [XOP_POP_E_AX]                  = x86_read_instr_pop_r1632,
        [XOP_POP_E_CX]                  = x86_read_instr_pop_r1632,
        [XOP_POP_E_DX]                  = x86_read_instr_pop_r1632,
        [XOP_POP_E_BX]                  = x86_read_instr_pop_r1632,
        [XOP_POP_E_SP]                  = x86_read_instr_pop_r1632,
        [XOP_POP_E_BP]                  = x86_read_instr_pop_r1632,
        [XOP_POP_E_SI]                  = x86_read_instr_pop_r1632,
        [XOP_POP_E_DI]                  = x86_read_instr_pop_r1632,
        [XOP_POPA]                      = x86_read_instr_popa,
        [XOP_ARPL_RM16_R16]             = x86_read_instr_arpl_rm16_r16,
        [XOP_PUSH_IMM1632]              = x86_read_instr_push_imm1632,
        [XOP_IMUL_R1632_RM1632_IMM1632] = x86_read_instr_imul_r1632_rm1632_imm1632,
        [XOP_IMUL_RM1632_IMM8]          = x86_read_instr_imul_rm1632_imm8,
        [XOP_JO_REL8]                   = x86_read_instr_jo_rel8,
        [XOP_JNO_REL8]                  = x86_read_instr_jno_rel8,
        [XOP_JB_REL8]                   = x86_read_instr_jb_rel8,
        [XOP_JNB_REL8]                  = x86_read_instr_jnb_rel8,
        [XOP_JE_REL8]                   = x86_read_instr_je_rel8,
        [XOP_JNE_REL8]                  = x86_read_instr_jne_rel8,
        [XOP_JNA_REL8]                  = x86_read_instr_jna_rel8,
        [XOP_JA_REL8]                   = x86_read_instr_ja_rel8,
        [XOP_JS_REL8]                   = x86_read_instr_js_rel8,
        [XOP_JNS_REL8]                  = x86_read_instr_jns_rel8,
        [XOP_JP_REL8]                   = x86_read_instr_jp_rel8,
        [XOP_JNP_REL8]                  = x86_read_instr_jnp_rel8,
        [XOP_JL_REL8]                   = x86_read_instr_jl_rel8,
        [XOP_JNL_REL8]                  = x86_read_instr_jnl_rel8,
        [XOP_JNG_REL8]                  = x86_read_instr_jng_rel8,
        [XOP_JG_REL8]                   = x86_read_instr_jg_rel8,
        [XOP_ADD_RM8_IMM8]              = x86_read_instr_add_rm8_imm8,
        [XOP_OR_RM8_IMM8]               = x86_read_instr_or_rm8_imm8,
        [XOP_ADC_RM8_IMM8]              = x86_read_instr_adc_rm8_imm8,
        [XOP_SBB_RM8_IMM8]              = x86_read_instr_sbb_rm8_imm8,
        [XOP_AND_RM8_IMM8]              = x86_read_instr_and_rm8_imm8,
        [XOP_SUB_RM8_IMM8]              = x86_read_instr_sub_rm8_imm8,
        [XOP_XOR_RM8_IMM8]              = x86_read_instr_xor_rm8_imm8,
        [XOP_CMP_RM8_IMM8]              = x86_read_instr_cmp_rm8_imm8,
        [XOP_ADD_RM1632_IMM1632]        = x86_read_instr_add_rm1632_imm1632,
        [XOP_OR_RM1632_IMM1632]         = x86_read_instr_or_rm1632_imm1632,
        [XOP_ADC_RM1632_IMM1632]        = x86_read_instr_adc_rm1632_imm1632,
        [XOP_SBB_RM1632_IMM1632]        = x86_read_instr_sbb_rm1632_imm1632,
        [XOP_AND_RM1632_IMM1632]        = x86_read_instr_and_rm1632_imm1632,
        [XOP_SUB_RM1632_IMM1632]        = x86_read_instr_sub_rm1632_imm1632,
        [XOP_XOR_RM1632_IMM1632]        = x86_read_instr_xor_rm1632_imm1632,
        [XOP_CMP_RM1632_IMM1632]        = x86_read_instr_cmp_rm1632_imm1632,
        [XOP_ADD_RM1632_IMM8]           = x86_read_instr_add_rm1632_imm8,
        [XOP_OR_RM1632_IMM8]            = x86_read_instr_or_rm1632_imm8,
        [XOP_ADC_RM1632_IMM8]           = x86_read_instr_adc_rm1632_imm8,
        [XOP_SBB_RM1632_IMM8]           = x86_read_instr_sbb_rm1632_imm8,
        [XOP_AND_RM1632_IMM8]           = x86_read_instr_and_rm1632_imm8,
        [XOP_SUB_RM1632_IMM8]           = x86_read_instr_sub_rm1632_imm8,
        [XOP_XOR_RM1632_IMM8]           = x86_read_instr_xor_rm1632_imm8,
        [XOP_CMP_RM1632_IMM8]           = x86_read_instr_cmp_rm1632_imm8,
        [XOP_TEST_RM8_R8]               = x86_read_instr_test_rm8_r8,
        [XOP_TEST_RM1632_R1632]         = x86_read_instr_test_rm1632_r1632,
        [XOP_MOV_RM8_R8]                = x86_read_instr_mov_rm8_r8,
        [XOP_MOV_RM1632_R1632]          = x86_read_instr_mov_rm1632_r1632,
        [XOP_MOV_R1632_RM1632]          = x86_read_instr_mov_r1632_rm1632,
        [XOP_LEA_R1632_M]               = x86_read_instr_lea_r1632_m,
        [XOP_NOP]                       = x86_read_instr_nop,
        [XOP_XCHG_R1632_E_AX]           = x86_read_instr_xchg_r1632_e_ax,
        [XOP_XCHG_R1632_E_CX]           = x86_read_instr_xchg_r1632_e_ax,
        [XOP_XCHG_R1632_E_DX]           = x86_read_instr_xchg_r1632_e_ax,
        [XOP_XCHG_R1632_E_BX]           = x86_read_instr_xchg_r1632_e_ax,
        [XOP_XCHG_R1632_E_SP]           = x86_read_instr_xchg_r1632_e_ax,
        [XOP_XCHG_R1632_E_BP]           = x86_read_instr_xchg_r1632_e_ax,
        [XOP_XCHG_R1632_E_SI]           = x86_read_instr_xchg_r1632_e_ax,
        [XOP_XCHG_R1632_E_DI]           = x86_read_instr_xchg_r1632_e_ax,
        [XOP_MOV_AL_MOFFS8]             = x86_read_instr_mov_al_moffs8,
        [XOP_MOV_E_AX_MOFFS1632]        = x86_read_instr_mov_e_ax_moffs1632,
        [XOP_MOV_MOFFS8_AL]             = x86_read_instr_mov_moffs8_al,
        [XOP_MOV_MOFFS1632_E_AX]        = x86_read_instr_mov_moffs1632_e_ax,
        [XOP_MOVS_M1632_M1632]          = x86_read_instr_movs_m1632_m1632,
        [XOP_CMPS_M8_M8]                = x86_read_instr_cmps_m8_m8,
        [XOP_TEST_AL_IMM8]              = x86_read_instr_test_al_imm8,
        [XOP_TEST_E_AX_IMM1632]         = x86_read_instr_test_e_ax_imm1632,
        [XOP_STOS_M1632_E_AX]           = x86_read_instr_stos_m1632_e_ax,
        [XOP_SCAS_AL_M8]                = x86_read_instr_scas_al_m8,
        [XOP_MOV_AL_IMM8]               = x86_read_instr_mov_r8_imm8,
        [XOP_MOV_CL_IMM8]               = x86_read_instr_mov_r8_imm8,
        [XOP_MOV_DL_IMM8]               = x86_read_instr_mov_r8_imm8,
        [XOP_MOV_BL_IMM8]               = x86_read_instr_mov_r8_imm8,
        [XOP_MOV_AH_IMM8]               = x86_read_instr_mov_r8_imm8,
        [XOP_MOV_CH_IMM8]               = x86_read_instr_mov_r8_imm8,
        [XOP_MOV_DH_IMM8]               = x86_read_instr_mov_r8_imm8,
        [XOP_MOV_BH_IMM8]               = x86_read_instr_mov_r8_imm8,
        [XOP_MOV_E_AX_IMM1632]          = x86_read_instr_mov_r1632_imm1632,
        [XOP_MOV_E_CX_IMM1632]          = x86_read_instr_mov_r1632_imm1632,
        [XOP_MOV_E_DX_IMM1632]          = x86_read_instr_mov_r1632_imm1632,
        [XOP_MOV_E_BX_IMM1632]          = x86_read_instr_mov_r1632_imm1632,
        [XOP_MOV_E_SP_IMM1632]          = x86_read_instr_mov_r1632_imm1632,
        [XOP_MOV_E_BP_IMM1632]          = x86_read_instr_mov_r1632_imm1632,
        [XOP_MOV_E_SI_IMM1632]          = x86_read_instr_mov_r1632_imm1632,
        [XOP_MOV_E_DI_IMM1632]          = x86_read_instr_mov_r1632_imm1632,
        [XOP_ROL_RM8_IMM8]              = x86_read_instr_rol_rm8_imm8,
        [XOP_ROR_RM8_IMM8]              = x86_read_instr_ror_rm8_imm8,
        [XOP_RCL_RM8_IMM8]              = x86_read_instr_rcl_rm8_imm8,
        [XOP_RCR_RM8_IMM8]              = x86_read_instr_rcr_rm8_imm8,
        [XOP_SHL_RM8_IMM8]              = x86_read_instr_shl_rm8_imm8,
        [XOP_SHR_RM8_IMM8]              = x86_read_instr_shr_rm8_imm8,
        [XOP_SAL_RM8_IMM8]              = x86_read_instr_sal_rm8_imm8,
        [XOP_SAR_RM8_IMM8]              = x86_read_instr_sar_rm8_imm8,
        [XOP_ROL_RM1632_IMM8]           = x86_read_instr_rol_rm1632_imm8,
        [XOP_ROR_RM1632_IMM8]           = x86_read_instr_ror_rm1632_imm8,
        [XOP_RCL_RM1632_IMM8]           = x86_read_instr_rcl_rm1632_imm8,
        [XOP_RCR_RM1632_IMM8]           = x86_read_instr_rcr_rm1632_imm8,
        [XOP_SHL_RM1632_IMM8]           = x86_read_instr_shl_rm1632_imm8,
        [XOP_SHR_RM1632_IMM8]           = x86_read_instr_shr_rm1632_imm8,
        [XOP_SAL_RM1632_IMM8]           = x86_read_instr_sal_rm1632_imm8,
        [XOP_SAR_RM1632_IMM8]           = x86_read_instr_sar_rm1632_imm8,
        [XOP_RETN_IMM16]                = x86_read_instr_retn_imm16,
        [XOP_RETN]                      = x86_read_instr_retn,
        [XOP_MOV_RM8_IMM8]              = x86_read_instr_mov_rm8_imm8,
        [XOP_MOV_RM1632_IMM1632]        = x86_read_instr_mov_rm1632_imm1632,
        [XOP_LEAVE]                     = x86_read_instr_leave,
        [XOP_RETF_IMM16]                = x86_read_instr_retf_imm16,
        [XOP_RETF]                      = x86_read_instr_retf,
        [XOP_INT_3]                     = x86_read_instr_int_3,
        [XOP_INT]                       = x86_read_instr_int_imm8,
        [XOP_ROL_RM8_1]                 = x86_read_instr_rol_rm8_1,
        [XOP_ROR_RM8_1]                 = x86_read_instr_ror_rm8_1,
        [XOP_RCL_RM8_1]                 = x86_read_instr_rcl_rm8_1,
        [XOP_RCR_RM8_1]                 = x86_read_instr_rcr_rm8_1,
        [XOP_SHL_RM8_1]                 = x86_read_instr_shl_rm8_1,
        [XOP_SHR_RM8_1]                 = x86_read_instr_shr_rm8_1,
        [XOP_SAL_RM8_1]                 = x86_read_instr_sal_rm8_1,
        [XOP_SAR_RM8_1]                 = x86_read_instr_sar_rm8_1,
        [XOP_ROL_RM1632_1]              = x86_read_instr_rol_rm1632_1,
        [XOP_ROR_RM1632_1]              = x86_read_instr_ror_rm1632_1,
        [XOP_RCL_RM1632_1]              = x86_read_instr_rcl_rm1632_1,
        [XOP_RCR_RM1632_1]              = x86_read_instr_rcr_rm1632_1,
        [XOP_SHL_RM1632_1]              = x86_read_instr_shl_rm1632_1,
        [XOP_SHR_RM1632_1]              = x86_read_instr_shr_rm1632_1,
        [XOP_SAL_RM1632_1]              = x86_read_instr_sal_rm1632_1,
        [XOP_SAR_RM1632_1]              = x86_read_instr_sar_rm1632_1,
        [XOP_ROL_RM8_CL]                = x86_read_instr_rol_rm8_cl,
        [XOP_ROR_RM8_CL]                = x86_read_instr_ror_rm8_cl,
        [XOP_RCL_RM8_CL]                = x86_read_instr_rcl_rm8_cl,
        [XOP_RCR_RM8_CL]                = x86_read_instr_rcr_rm8_cl,
        [XOP_SHL_RM8_CL]                = x86_read_instr_shl_rm8_cl,
        [XOP_SHR_RM8_CL]                = x86_read_instr_shr_rm8_cl,
        [XOP_SAL_RM8_CL]                = x86_read_instr_sal_rm8_cl,
        [XOP_SAR_RM8_CL]                = x86_read_instr_sar_rm8_cl,
        [XOP_ROL_RM1632_CL]             = x86_read_instr_rol_rm1632_cl,
        [XOP_ROR_RM1632_CL]             = x86_read_instr_ror_rm1632_cl,
        [XOP_RCL_RM1632_CL]             = x86_read_instr_rcl_rm1632_cl,
        [XOP_RCR_RM1632_CL]             = x86_read_instr_rcr_rm1632_cl,
        [XOP_SHL_RM1632_CL]             = x86_read_instr_shl_rm1632_cl,
        [XOP_SHR_RM1632_CL]             = x86_read_instr_shr_rm1632_cl,
        [XOP_SAL_RM1632_CL]             = x86_read_instr_sal_rm1632_cl,
        [XOP_SAR_RM1632_CL]             = x86_read_instr_sar_rm1632_cl,
        [XOP_CALL_REL1632]              = x86_read_instr_call_rel1632,
        [XOP_JMP_REL1632]               = x86_read_instr_jmp_rel1632,
        [XOP_JMP_REL8]                  = x86_read_instr_jmp_rel8,
        [XOP_HLT]                       = x86_read_instr_hlt,
        [XOP_TEST_RM8_IMM8]             = x86_read_instr_test_rm8_imm8,
        [XOP_TEST_RM8_IMM8_BIS]         = x86_read_instr_test_rm8_imm8,
        [XOP_NOT_RM8]                   = x86_read_instr_not_rm8,
        [XOP_TEST_RM1632_IMM1632]       = x86_read_instr_test_rm1632_imm1632,
        [XOP_TEST_RM1632_IMM1632_BIS]   = x86_read_instr_test_rm1632_imm1632,
        [XOP_NOT_RM1632]                = x86_read_instr_not_rm1632,
        [XOP_IMUL_RM1632]               = x86_read_instr_imul_rm1632,
        [XOP_CLD]                       = x86_read_instr_cld,
        [XOP_INC_RM8]                   = x86_read_instr_inc_rm8,
        [XOP_DEC_RM8]                   = x86_read_instr_dec_rm8,
        [XOP_INC_RM1632]                = x86_read_instr_inc_rm1632,
        [XOP_DEC_RM1632]                = x86_read_instr_dec_rm1632,
        [XOP_CALL_RM1632]               = x86_read_instr_call_rm1632,
        [XOP_JMP_RM1632]                = x86_read_instr_jmp_rm1632,
        [XOP_PUSH_RM1632]               = x86_read_instr_push_rm1632,

        /* Instructions avec opcode sur deux octets */

        [XOP_JO_REL1632]                = x86_read_instr_jo_rel1632,
        [XOP_JNO_REL1632]               = x86_read_instr_jno_rel1632,
        [XOP_JB_REL1632]                = x86_read_instr_jb_rel1632,
        [XOP_JNB_REL1632]               = x86_read_instr_jnb_rel1632,
        [XOP_JE_REL1632]                = x86_read_instr_je_rel1632,
        [XOP_JNE_REL1632]               = x86_read_instr_jne_rel1632,
        [XOP_JNA_REL1632]               = x86_read_instr_jna_rel1632,
        [XOP_JA_REL1632]                = x86_read_instr_ja_rel1632,
        [XOP_JS_REL1632]                = x86_read_instr_js_rel1632,
        [XOP_JNS_REL1632]               = x86_read_instr_jns_rel1632,
        [XOP_JP_REL1632]                = x86_read_instr_jp_rel1632,
        [XOP_JNP_REL1632]               = x86_read_instr_jnp_rel1632,
        [XOP_JL_REL1632]                = x86_read_instr_jl_rel1632,
        [XOP_JNL_REL1632]               = x86_read_instr_jnl_rel1632,
        [XOP_JNG_REL1632]               = x86_read_instr_jng_rel1632,
        [XOP_JG_REL1632]                = x86_read_instr_jg_rel1632,
        [XOP_SETO_RM8]                  = x86_read_instr_seto_rm8,
        [XOP_SETNO_RM8]                 = x86_read_instr_setno_rm8,
        [XOP_SETB_RM8]                  = x86_read_instr_setb_rm8,
        [XOP_SETNB_RM8]                 = x86_read_instr_setnb_rm8,
        [XOP_SETE_RM8]                  = x86_read_instr_sete_rm8,
        [XOP_SETNE_RM8]                 = x86_read_instr_setne_rm8,
        [XOP_SETNA_RM8]                 = x86_read_instr_setna_rm8,
        [XOP_SETA_RM8]                  = x86_read_instr_seta_rm8,
        [XOP_SETS_RM8]                  = x86_read_instr_sets_rm8,
        [XOP_SETNS_RM8]                 = x86_read_instr_setns_rm8,
        [XOP_SETP_RM8]                  = x86_read_instr_setp_rm8,
        [XOP_SETNP_RM8]                 = x86_read_instr_setnp_rm8,
        [XOP_SETL_RM8]                  = x86_read_instr_setl_rm8,
        [XOP_SETNL_RM8]                 = x86_read_instr_setnl_rm8,
        [XOP_SETNG_RM8]                 = x86_read_instr_setng_rm8,
        [XOP_SETG_RM8]                  = x86_read_instr_setg_rm8,
        [XOP_MOVZX_R1632_RM8]           = x86_read_instr_movzx_r1632_rm8,
        [XOP_MOVZX_R1632_RM16]          = x86_read_instr_movzx_r1632_rm16,
        [XOP_MOVSX_R1632_RM8]           = x86_read_instr_movsx_r1632_rm8,
        [XOP_MOVSX_R1632_RM1632]        = x86_read_instr_movsx_r1632_rm1632

    };

    id = x86_guess_next_instruction(data, *pos, len, &prefix, &care);

    if (prefix & XPX_TWO_BYTES)
    {
        (*pos)++;
        addr++;
    }
    if (prefix & XPX_OPERAND_SIZE_OVERRIDE) (*pos)++;
    if (prefix & XPX_REPEAT_STR_OPERATION_F2) (*pos)++;
    if (prefix & XPX_REPEAT_STR_OPERATION_F3) (*pos)++;

    if (id != XOP_COUNT && !care) (*pos)++;

    if (id == XOP_COUNT) result = NULL;
    else result = decodings[id](data, pos, len, addr, prefix, proc);

    if (result != NULL)
        g_x86_instruction_set_prefixes(G_X86_INSTRUCTION(result), prefix);

    return result;

}