disx64.c

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

C
2,184
字号
/****************************************************************************
*
*                            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 AMD64 architecture.
*
****************************************************************************/


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

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

extern const dis_range          X64RangeTable[];
extern const int                X64RangeTablePos[];
extern const unsigned char      X64MaxInsName;
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;

typedef union {
    unsigned_8 full;
    struct{
        unsigned_8  b     : 1;
        unsigned_8  x     : 1;
        unsigned_8  r     : 1;
        unsigned_8  w     : 1;
        unsigned_8  pr    : 4;
    } split;
} REX;

//#define PREFIX_MASK ( DIF_X64_REPNE | DIF_X64_REPE | DIF_X64_OPND_SIZE | DIF_X64_REX_B | DIF_X64_REX_R | DIF_X64_REX_W | DIF_X64_REX_X )

#define PREFIX_MASK ( DIF_X64_OPND_SIZE | DIF_X64_ADDR_SIZE | DIF_X64_REX_B | DIF_X64_REX_R | DIF_X64_REX_W | DIF_X64_REX_X | DIF_X64_PEX_PR )

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

// for REX prefix decoding
#define X64_EXTENDED_REG_OFFSET     8

/*=====================================================================*/
/*                        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,
    RM_8 = 0x8,
    RM_9 = 0x9,
    RM_A = 0xA,
    RM_B = 0xB,
    RM_C = 0xC,
    RM_D = 0xD,
    RM_E = 0xE,
    RM_F = 0xF,

    REG_RAX = 0x0,
    REG_RCX = 0x1,
    REG_RDX = 0x2,
    REG_RBX = 0x3,
    REG_RSP = 0x4,
    REG_RBP = 0x5,
    REG_RSI = 0x6,
    REG_RDI = 0x7,
    REG_R8  = 0x8,
    REG_R9  = 0x9,
    REG_R10 = 0xA,
    REG_R11 = 0xB,
    REG_R12 = 0xC,
    REG_R13 = 0xD,
    REG_R14 = 0xE,
    REG_R15 = 0xF,
    REG_RIP = 0x10,     // Special value for RIP-Relative addresing

    REG_ES  = 0x0,
    REG_CS  = 0x1,
    REG_SS  = 0x2,
    REG_DS  = 0x3,
    REG_FS  = 0x4,
    REG_GS  = 0x5,

    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,
} 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 {
    RW_64BIT     = 0x0,
    RW_32BIT     = 0x1,
    RW_16BIT     = 0x2,
    RW_8BIT      = 0x3,
    RW_DEFAULT   = RW_64BIT
} REGWIDTH;

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 X64PrefixOpnd( dis_handle *h, void *d, dis_dec_ins *ins )
/***************************************************************************
 * Operand Size Override
 */
{
    ins->size += 1;

    // if REX.W set then ignore 66h prefix
    // if REX.W clear then instruction size is 16-Bit!
    if( (ins->flags & DIF_X64_REX_W) == 0)
        ins->flags |= DIF_X64_OPND_SIZE;

    return( DHR_CONTINUE );
}

dis_handler_return X64PrefixRex( dis_handle *h, void *d, dis_dec_ins *ins )
/***************************************************************************
 * Extended Register Override
 */
{
    REX rex_pr;

    rex_pr.full = GetUByte( d, ins->size );
    ins->size += 1;


    // Clear all REX stuff (to be sure)
    ins->flags &= ~( DIF_X64_REX_B | DIF_X64_REX_X | DIF_X64_REX_R | DIF_X64_REX_W | DIF_X64_PEX_PR );

    // REX.B is an extension to the ModRM's SIB base field
    if(rex_pr.split.b)
        ins->flags |= DIF_X64_REX_B;

    // REX.X is an extension to the ModRM's SIB index field
    if(rex_pr.split.x)
        ins->flags |= DIF_X64_REX_X;

    // REX.R is an extension to the ModRM's Register field
    if(rex_pr.split.r)
        ins->flags |= DIF_X64_REX_R;

    // REX.W is an operand size prefix (like 66h)
    //  if 1 then use 64-Bit operand size
    //  if 0 then use default operand size
    if(rex_pr.split.w)
        ins->flags |= DIF_X64_REX_W;

    // Flag REX prefix, sometime useful...
    ins->flags |= DIF_X64_PEX_PR;

    return( DHR_CONTINUE );
}

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

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


//dis_handler_return X64PrefixFwait( 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_X64_fwait;
            return( DHR_DONE );
        }
        ++instruct_size;
    }
    ins->flags ^= DIF_X64_FWAIT;
    return( DHR_CONTINUE );
}*/

dis_handler_return X64PrefixAddr( dis_handle *h, void *d, dis_dec_ins *ins )
/***************************************************************************
 * Address Size Override
 */
{
    ins->size += 1;

    if( ( ins->flags & DIF_X64_ADDR_SIZE ) == 0 )
        ins->flags |= DIF_X64_ADDR_SIZE;

    return( DHR_CONTINUE );
}

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

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

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


dis_handler_return X64PrefixSS( dis_handle *h, void *d, dis_dec_ins *ins )
/*************************************************************************
 * SS Segment Override
 */

⌨️ 快捷键说明

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