disx86.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,201 行 · 第 1/5 页

C
2,201
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Instruction decoding for x86 architecture.
*
****************************************************************************/


#include <string.h>
#include <ctype.h>
#include "distypes.h"
#include "dis.h"

extern long SEX( unsigned long v, unsigned bit );

extern const dis_range          X86RangeTable[];
extern const int                X86RangeTablePos[];
extern const unsigned char      X86MaxInsName;
extern const dis_ins_descript   DisInstructionTable[];
extern const unsigned short     DisRefTypeTable[];

typedef union {
    unsigned_8 full;
    struct {
        unsigned_8  base  : 3;
        unsigned_8  index : 3;
        unsigned_8  scale : 2;
    } split;
} SIB;

#define PREFIX_MASK ( DIF_X86_REPNE | DIF_X86_REPE | DIF_X86_OPND_SIZE )

#define X86XMMResetPrefixes() ins->flags &= ~PREFIX_MASK


/*=====================================================================*/
/*                        ENUMERATED TYPES                             */
/*=====================================================================*/
typedef enum {
    MOD_0 = 0x0,
    MOD_1 = 0x1,
    MOD_2 = 0X2,
    MOD_3 = 0X3
} MOD;

typedef enum {
    RM_0 = 0x0,
    RM_1 = 0x1,
    RM_2 = 0X2,
    RM_3 = 0X3,
    RM_4 = 0x4,
    RM_5 = 0X5,
    RM_6 = 0X6,
    RM_7 = 0X7,
    REG_AX = 0x0,
    REG_CX = 0X1,
    REG_DX = 0x2,
    REG_BX = 0x3,
    REG_SP = 0x4,
    REG_AH = 0x4,
    REG_BP = 0x5,
    REG_CH = 0x5,
    REG_SI = 0X6,
    REG_DH = 0x6,
    REG_DI = 0x7,
    REG_BH = 0x7,
    REG_CR0 = 0x0,
    REG_CR2 = 0X2,
    REG_CR3 = 0X3,
    REG_CR4 = 0X4,
    REG_DR0 = 0X0,
    REG_DR1 = 0x1,
    REG_DR2 = 0x2,
    REG_DR3 = 0x3,
    REG_DR6 = 0x6,
    REG_DR7 = 0x7,
    REG_TR3 = 0x3,
    REG_TR4 = 0x4,
    REG_TR5 = 0x5,
    REG_TR6 = 0x6,
    REG_TR7 = 0x7,
    REG_ES  = 0x0,
    REG_CS  = 0x1,
    REG_SS  = 0x2,
    REG_DS  = 0x3,
    REG_FS  = 0x4,
    REG_GS  = 0x5
} RM;

typedef enum {
    SC_0 = 0x0,
    SC_1 = 0x1,
    SC_2 = 0X2,
    SC_3 = 0X3
} SCALE;

typedef enum {
    W_DEFAULT = 0x1,
    W_FULL    = 0x1,    // Full Size Operand
    W_BYTE    = 0x0     // Byte Size Operand
} WBIT;

typedef enum {
    S_DEFAULT = 0x0,
    S_FULL    = 0x0,    // Full Mode for Immediate Value Fetch
    S_BYTE    = 0x1     // Byte Mode for Immediate Value Fetch
} SBIT;

typedef enum {
    D_RM_REG = 0x0,     // normal operand order r/m is first and reg is second
    D_REG_RM = 0x1      // reverse operand order reg is first and r/m is second
} DBIT;

typedef enum {
    MF_0 = 0x0,
    MF_1 = 0x1,
    MF_2 = 0x2,
    MF_3 = 0X3
} MF_BITS;

typedef enum {
    FB    = 0x0,
    FE    = 0x1,
    FBE   = 0x2,
    FU    = 0x3,
} COND;

/*=====================================================================*/
/*                FUNCTIONS TO FETCH BYTE/WORD/DWORD                   */
/*=====================================================================*/



static unsigned_8 GetUByte( void *d, unsigned off )
/**************************************************
 * Get Unsigned Byte
 */
{
    unsigned_8  data;

    //NYI: have to error check return code
    DisCliGetData( d, off, sizeof( data ), &data );
    return( data );
}

static unsigned_16 GetUShort( void *d, unsigned off )
/****************************************************
 * Get Unsigned Word ( 2 bytes )
 */
{
    struct {
        unsigned_8 lo;
        unsigned_8 hi;
    }   data;

    //NYI: have to error check return code
    DisCliGetData( d, off, sizeof( data ), &data );
    return( ( data.hi << 8 ) | data.lo );
}

static unsigned_32 GetULong( void *d, unsigned off )
/***************************************************
 * Get Double Word
 */
{
    struct {
        unsigned_8 lo;
        unsigned_8 mid_lo;
        unsigned_8 mid_hi;
        unsigned_8 hi;
    }   data;

    //NYI: have to error check return code
    DisCliGetData( d, off, sizeof( data ), &data );
    return( ( (unsigned long)data.hi << 24 )
        |   ( (unsigned long)data.mid_hi << 16 )
        |   ( data.mid_lo << 8 )
        |    data.lo );
}


static int GetSByte( void *d, unsigned off )
/*******************************************
 * Get Signed Byte
 */
{
    return( SEX( GetUByte( d, off ), 7 ) );
}

static int GetSShort( void *d, unsigned off )
/********************************************
 * Get Signed Word
 */
{
    return( SEX( GetUShort( d, off ), 15 ) );
}



/*=====================================================================*/
/*                PREFIX HANDLERS                                      */
/*=====================================================================*/



dis_handler_return X86PrefixFwait( dis_handle *h, void *d, dis_dec_ins *ins )
/****************************************************************************
 * FWait
 */
{
    unsigned    code;
    unsigned    instruct_size;

    ins->size += 1;
    instruct_size = ins->size;

    for( ;; ) {
        code = GetUByte( d, instruct_size );
        if( ( code & 0xf8 ) == 0xd8 ) break;
        // Look Ahead for Prefixes
        switch( code ) {
        case 0x67:
        case 0x66:
        case 0x2e:
        case 0x3e:
        case 0x26:
        case 0x64:
        case 0x65:
        case 0x36:
            break;
        default:
            // A non-floating point instruction is found so quit
            ins->num_ops = 0;
            ins->type = DI_X86_fwait;
            return( DHR_DONE );
        }
        ++instruct_size;
    }
    ins->flags ^= DIF_X86_FWAIT;
    return( DHR_CONTINUE );
}

dis_handler_return X86PrefixOpnd( dis_handle *h, void *d, dis_dec_ins *ins )
/***************************************************************************
 * Operand Size Override
 */
{
    ins->size += 1;
    if( ( ins->flags & DIF_X86_OPND_SIZE ) == 0 ) {
        ins->flags ^= DIF_X86_OPND_LONG;
        ins->flags |= DIF_X86_OPND_SIZE;
    }
    return( DHR_CONTINUE );
}

dis_handler_return X86PrefixAddr( dis_handle *h, void *d, dis_dec_ins *ins )
/***************************************************************************
 * Address Size Override
 */
{
    ins->size += 1;
    if( ( ins->flags & DIF_X86_ADDR_SIZE ) == 0 ) {
        ins->flags ^= DIF_X86_ADDR_LONG;
        ins->flags |= DIF_X86_ADDR_SIZE;
    }
    return( DHR_CONTINUE );
}

dis_handler_return X86PrefixRepe( dis_handle *h, void *d, dis_dec_ins *ins )
/***************************************************************************
 * REP/REPE/REPZ Override
 */
{
    ins->size += 1;
    ins->flags |= DIF_X86_REPE;
    return( DHR_CONTINUE );
}

dis_handler_return X86PrefixRepne( dis_handle *h, void *d, dis_dec_ins *ins )
/****************************************************************************
 * REPNE/REPNZ
 */
{
    ins->size += 1;
    ins->flags |= DIF_X86_REPNE;
    return( DHR_CONTINUE );
}

dis_handler_return X86PrefixLock( dis_handle *h, void *d, dis_dec_ins *ins )
/***************************************************************************
 * Lock Prefix
 */
{
    ins->size += 1;
    ins->flags |= DIF_X86_LOCK;
    return( DHR_CONTINUE );
}

dis_handler_return X86PrefixCS( dis_handle *h, void *d, dis_dec_ins *ins )
/*************************************************************************
 * CS Segment Override
 */
{
    ins->size += 1;
    ins->flags |= DIF_X86_CS;
    return( DHR_CONTINUE );
}

dis_handler_return X86PrefixSS( dis_handle *h, void *d, dis_dec_ins *ins )
/*************************************************************************
 * SS Segment Override
 */
{
    ins->size += 1;
    ins->flags |= DIF_X86_SS;
    return( DHR_CONTINUE );
}

dis_handler_return X86PrefixDS( dis_handle *h, void *d, dis_dec_ins *ins )
/*************************************************************************
 * DS Segment Override
 */
{
    ins->size += 1;
    ins->flags |= DIF_X86_DS;
    return( DHR_CONTINUE );
}

dis_handler_return X86PrefixES( dis_handle *h, void *d, dis_dec_ins *ins )
/*************************************************************************
 * ES Segment Override
 */
{
    ins->size += 1;
    ins->flags |= DIF_X86_ES;
    return( DHR_CONTINUE );
}

dis_handler_return X86PrefixFS( dis_handle *h, void *d, dis_dec_ins *ins )
/*************************************************************************
 * FS Segment Override
 */
{
    ins->size += 1;
    ins->flags |= DIF_X86_FS;
    return( DHR_CONTINUE );
}

dis_handler_return X86PrefixGS( dis_handle *h, void *d , dis_dec_ins *ins )
/**************************************************************************
 * GS Segment Override
 */
{
    ins->size += 1;
    ins->flags |= DIF_X86_GS;
    return( DHR_CONTINUE );
}



/*=====================================================================*/
/*                UTILITY FUNCTIONS                                    */
/*=====================================================================*/



/*
 * Returns true if a segment override prefix has been encountered
 */
#define SEGOVER ( DIF_X86_CS|DIF_X86_DS|DIF_X86_ES|DIF_X86_FS|DIF_X86_GS|DIF_X86_SS )
#define X86SegmentOverride( ins )       ( (ins)->flags & SEGOVER )

dis_register X86GetRegister_D( WBIT w, RM reg, dis_dec_ins *ins )
{
    switch( reg ) {
    case REG_AX: return( DR_X86_eax );
    case REG_CX: return( DR_X86_ecx );
    case REG_DX: return( DR_X86_edx );
    case REG_BX: return( DR_X86_ebx );
    case REG_SP: return( DR_X86_esp );
    case REG_BP: return( DR_X86_ebp );
    case REG_SI: return( DR_X86_esi );
    case REG_DI: return( DR_X86_edi );
    default:     return( DR_NONE );
    }
}

dis_register X86GetRegister_W( WBIT w, RM reg, dis_dec_ins *ins )
{
    switch( reg ) {
    case REG_AX: return( DR_X86_ax );
    case REG_CX: return( DR_X86_cx );
    case REG_DX: return( DR_X86_dx );
    case REG_BX: return( DR_X86_bx );
    case REG_SP: return( DR_X86_sp );
    case REG_BP: return( DR_X86_bp );
    case REG_SI: return( DR_X86_si );
    case REG_DI: return( DR_X86_di );
    default:     return( DR_NONE );
    }
}

dis_register X86GetRegister_B( WBIT w, RM reg, dis_dec_ins *ins )
{
    switch( reg ) {
    case REG_AX: return( DR_X86_al );
    case REG_CX: return( DR_X86_cl );
    case REG_DX: return( DR_X86_dl );
    case REG_BX: return( DR_X86_bl );
    case REG_AH: return( DR_X86_ah );
    case REG_CH: return( DR_X86_ch );
    case REG_DH: return( DR_X86_dh );
    case REG_BH: return( DR_X86_bh );
    default:     return( DR_NONE );
    }
}

dis_register X86FGetSTReg(WBIT w, RM reg, dis_dec_ins *ins )

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?