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 + -
显示快捷键?