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