disx86.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,201 行 · 第 1/5 页
C
2,201 行
*/
{
if( DIF_X86_ADDR_LONG & ins->flags ) {
X86GetModRM_L( w, mod, rm, d ,ins, ref_type, X86GetXMMReg );
} else {
X86GetModRM_S( w, mod, rm, d ,ins, ref_type, X86GetXMMReg );
}
}
/*=====================================================================*/
/* Get Register as Operands */
/*=====================================================================*/
static dis_ref_type X86RegRefType( dis_register reg )
{
if( reg <= DR_X86_bl ) return( DRT_X86_BYTE );
if( reg <= DR_X86_di ) return( DRT_X86_WORD );
if( reg <= DR_X86_edi ) return( DRT_X86_DWORD );
if( reg <= DR_X86_st7 ) return( DRT_X86_TBYTE );
if( reg <= DR_X86_mm7 ) return( DRT_X86_MM64 );
if( reg <= DR_X86_xmm7 ) return( DRT_X86_XMM128 );
if( reg <= DR_X86_dr7 ) return( DRT_X86_DWORD );
return( DRT_X86_WORD );
}
static void X86FGetST( RM reg, dis_dec_ins *ins )
/**********************************************************************
* Get ST - Floating Point Stack Register
*/
{
int oper;
oper = ins->num_ops;
ins->op[oper].type = DO_REG;
ins->op[oper].base = X86FGetSTReg( W_DEFAULT, reg, ins );
ins->op[oper].ref_type = DRT_X86_TBYTE;
++ins->num_ops;
}
static void X86GetMM( RM reg, dis_dec_ins *ins )
/**********************************************************************
* Get MM Register
*/
{
int oper;
oper = ins->num_ops;
ins->op[oper].type = DO_REG;
ins->op[oper].base = X86GetMMReg( W_DEFAULT, reg, ins );
ins->op[oper].ref_type = DRT_X86_MM64;
++ins->num_ops;
}
static void X86GetXMM( RM reg, dis_dec_ins *ins )
/**********************************************************************
* Get XMM Register
*/
{
int oper;
oper = ins->num_ops;
ins->op[oper].type = DO_REG;
ins->op[oper].base = X86GetXMMReg( W_DEFAULT, reg, ins );
ins->op[oper].ref_type = DRT_X86_XMM128;
++ins->num_ops;
}
static void X86GetReg( WBIT w, RM reg, dis_dec_ins *ins )
/**********************************************************************
* Get Register
*/
{
int oper;
oper = ins->num_ops;
ins->op[oper].type = DO_REG;
ins->op[oper].base = X86GetRegister( w, reg, ins );
ins->op[oper].ref_type = X86RegRefType( ins->op[oper].base );
++ins->num_ops;
}
static void X86GetReg32( WBIT w, RM reg, dis_dec_ins *ins )
/**********************************************************************
* Get Register
*/
{
int oper;
oper = ins->num_ops;
ins->op[oper].type = DO_REG;
ins->op[oper].base = X86GetRegister_D( w, reg, ins );
ins->op[oper].ref_type = DRT_X86_DWORD;
++ins->num_ops;
}
static void X86GetSReg( WBIT w, RM reg, dis_dec_ins *ins )
/**********************************************************************
* Get S Registers
*/
{
int oper;
oper = ins->num_ops;
ins->op[oper].type = DO_REG;
ins->op[oper].base = X86GetSRegister( w, reg, ins );
ins->op[oper].ref_type = DRT_X86_WORD;
++ins->num_ops;
}
/*=====================================================================*/
/* Get Immediate Value */
/*=====================================================================*/
static void X86GetImmedVal( SBIT s, WBIT w, void *d, dis_dec_ins *ins )
/*********************************************************************
* Get Immediate Value
* s = 0 (S_FULL / S_DEFAULT)
* s = 1 (S_BYTE)
*/
{
int oper;
oper = ins->num_ops;
ins->op[oper].op_position = ins->size;
ins->op[oper].type = DO_IMMED;
++ins->num_ops;
if( w == W_FULL && s == S_FULL ) {
if( ins->flags & DIF_X86_OPND_LONG ) {
ins->op[oper].value = GetULong( d, ins->size );
ins->op[oper].ref_type = DRT_X86_DWORD;
ins->size += 4;
} else {
ins->op[oper].value = GetSShort( d, ins->size );
ins->op[oper].ref_type = DRT_X86_WORD;
ins->size += 2;
}
} else {
ins->op[oper].value = GetSByte( d, ins->size );
if( w == W_BYTE ) {
ins->op[oper].ref_type = DRT_X86_BYTE;
} else if( ins->flags & DIF_X86_OPND_LONG ) {
ins->op[oper].ref_type = DRT_X86_DWORD;
} else {
ins->op[oper].ref_type = DRT_X86_WORD;
}
ins->size += 1;
}
}
/*=====================================================================*/
/* Get Absolute Value */
/*=====================================================================*/
static void X86GetAbsVal( void *d, dis_dec_ins *ins )
/*********************************************************************
* Get Absolute Value
*/
{
int oper;
oper = ins->num_ops;
ins->op[oper].op_position = ins->size;
ins->op[oper].type = DO_ABSOLUTE;
++ins->num_ops;
if( ins->flags & DIF_X86_OPND_LONG ) {
ins->op[oper].value = GetULong( d, ins->size );
ins->size += 4;
} else {
ins->op[oper].value = GetUShort( d, ins->size );
ins->size += 2;
}
// Get Segment Value
ins->op[oper].extra = GetUShort( d, ins->size );
ins->size += 2;
ins->op[oper].type |= DO_EXTRA;
}
/*=====================================================================*/
/* Get Relative Value */
/*=====================================================================*/
static void X86GetRelVal_8( void *d, dis_dec_ins *ins )
/*********************************************************************
* Get Relative Value - 1 byte
*/
{
int oper;
oper = ins->num_ops;
ins->op[oper].op_position = ins->size;
ins->op[oper].type = DO_RELATIVE;
++ins->num_ops;
ins->op[oper].value = GetSByte( d, ins->size );
ins->size += 1;
ins->op[oper].value += ins->size;
}
static void X86GetRelVal( void *d, dis_dec_ins *ins )
/*********************************************************************
* Get Relative Value
*/
{
int oper;
oper = ins->num_ops;
ins->op[oper].op_position = ins->size;
ins->op[oper].type = DO_RELATIVE;
++ins->num_ops;
if( ins->flags & DIF_X86_ADDR_LONG ) {
ins->op[oper].value = GetULong( d, ins->size );
ins->size += 4;
} else {
ins->op[oper].value = GetSShort( d, ins->size );
ins->size += 2;
}
ins->op[oper].value += ins->size;
}
/*=====================================================================*/
/* Get Reference Type */
/*=====================================================================*/
dis_ref_type X86GetRefType( WBIT w, dis_dec_ins *ins )
/*********************************************************************
* Get Reference Type
*/
{
// Instructions that have default ref type
switch( ins->type ) {
case DI_X86_lldt:
case DI_X86_sldt:
case DI_X86_ltr:
case DI_X86_lmsw:
case DI_X86_smsw:
case DI_X86_str:
case DI_X86_invlpg:
case DI_X86_verr:
case DI_X86_verw:
case DI_X86_arpl:
return( DRT_X86_WORD );
case DI_X86_cmpxchg8b:
return( DRT_X86_QWORD );
case DI_X86_fxsave00:
case DI_X86_fxsave01:
case DI_X86_fxsave10:
case DI_X86_fxrstor00:
case DI_X86_fxrstor01:
case DI_X86_fxrstor10:
return( DRT_X86_BYTE512 );
case DI_X86_prefetch:
case DI_X86_prefetchw:
case DI_X86_prefetcht000:
case DI_X86_prefetcht001:
case DI_X86_prefetcht010:
case DI_X86_prefetcht100:
case DI_X86_prefetcht101:
case DI_X86_prefetcht110:
case DI_X86_prefetcht200:
case DI_X86_prefetcht201:
case DI_X86_prefetcht210:
case DI_X86_prefetchnta00:
case DI_X86_prefetchnta01:
case DI_X86_prefetchnta10:
case DI_X86_clflush00:
case DI_X86_clflush01:
case DI_X86_clflush10:
return( DRT_X86_BYTEX );
case DI_X86_ldmxcsr00:
case DI_X86_ldmxcsr01:
case DI_X86_ldmxcsr10:
case DI_X86_stmxcsr00:
case DI_X86_stmxcsr01:
case DI_X86_stmxcsr10:
return( DRT_X86_XMM32 );
default:
break;
}
if( w == W_FULL ) {
if( ins->flags & DIF_X86_OPND_LONG ) {
switch( ins->type ) {
case DI_X86_lds:
case DI_X86_les:
case DI_X86_lfs:
case DI_X86_lgs:
case DI_X86_lss:
case DI_X86_call4:
case DI_X86_jmp4:
return( DRT_X86_FARPTR48 );
#if 0
case DI_X86_bound:
return( DRT_X86_QWORD );
#endif
case DI_X86_lgdt:
case DI_X86_lidt:
case DI_X86_sgdt:
case DI_X86_sidt00:
case DI_X86_sidt01:
case DI_X86_sidt10:
return( DRT_X86_MEM1632 );
default:
return( DRT_X86_DWORD );
}
} else {
switch( ins->type ) {
case DI_X86_lds:
case DI_X86_les:
case DI_X86_lfs:
case DI_X86_lgs:
case DI_X86_lss:
case DI_X86_call4:
case DI_X86_jmp4:
return( DRT_X86_FARPTR32 );
#if 0
case DI_X86_bound:
return( DRT_X86_DWORD );
#endif
case DI_X86_lgdt:
case DI_X86_lidt:
case DI_X86_sgdt:
case DI_X86_sidt00:
case DI_X86_sidt01:
case DI_X86_sidt10:
return( DRT_X86_MEM1624 );
default:
return( DRT_X86_WORD );
}
}
}
return( DRT_X86_BYTE );
}
dis_ref_type X86FGetRefType( MF_BITS mf, dis_dec_ins * ins )
/*********************************************************************
* Get Reference Type - Floating Point Instructions
*/
{
switch( mf ) {
case MF_0: return( DRT_X86_DWORDF );
case MF_1: return( DRT_X86_DWORD );
case MF_2: return( DRT_X86_QWORDF );
case MF_3: return( DRT_X86_WORD );
default: return( DRT_X86_WORD );
}
}
dis_ref_type X86FGetRefTypeEnv( dis_dec_ins * ins )
/*********************************************************************
* Get Reference Type - Floating Point Environment Instructions
*/
{
if( ins->flags & DIF_X86_OPND_LONG ) {
switch( ins->type ) {
case DI_X86_fnsave00:
case DI_X86_fnsave01:
case DI_X86_fnsave10:
case DI_X86_frstor00:
case DI_X86_frstor01:
case DI_X86_frstor10:
return( DRT_X86_BYTE108 );
case DI_X86_fnstenv00:
case DI_X86_fnstenv01:
case DI_X86_fldenv00:
case DI_X86_fldenv01:
case DI_X86_fldenv10:
return( DRT_X86_BYTE28 );
default:
return( DRT_X86_DWORD );
}
} else {
switch( ins->type ) {
case DI_X86_fnsave00:
case DI_X86_fnsave01:
case DI_X86_fnsave10:
case DI_X86_frstor00:
case DI_X86_frstor01:
case DI_X86_frstor10:
return( DRT_X86_BYTE94 );
case DI_X86_fnstenv00:
case DI_X86_fnstenv01:
case DI_X86_fnstenv10:
case DI_X86_fldenv00:
case DI_X86_fldenv01:
case DI_X86_fldenv10:
return( DRT_X86_BYTE14 );
default:
return( DRT_X86_WORD );
}
}
}
/*=====================================================================*/
/* GET REGISTER AND MOD/RM FUNCTIONS */
/*=====================================================================*/
static void X86GetRegModRM( DBIT dir, WBIT w, MOD mod, RM rm, RM reg,
void * d, dis_dec_ins *ins )
/**********************************************************************/
// dir 1 0
// Destination Reg MODRM
// Source MODRM Reg
{
if( dir ) {
X86GetReg( w, reg, ins );
X86GetModRM( w, mod, rm, d, ins, X86GetRefType( w,ins ) );
} else {
X86GetModRM( w, mod, rm, d, ins, X86GetRefType( w,ins ) );
X86GetReg( w, reg, ins );
}
}
static void X86GetMMRegModRM( DBIT dir, WBIT w, MOD mod, RM rm, RM reg,
dis_ref_type ref_type, void * d, dis_dec_ins *ins )
/**********************************************************************/
// dir 1 0
// Destination Reg MODRM
// Source MODRM Reg
{
if( dir ) {
X86GetMM( reg, ins );
X86MMGetModRM( w, mod, rm, d, ins, ref_type );
} else {
X86MMGetModRM( w, mod, rm, d, ins, ref_type );
X86GetMM( reg, ins );
}
}
static void X86GetXMMRegModRM( DBIT dir, WBIT w, MOD mod, RM rm, RM reg,
dis_ref_type ref_type, void * d, dis_dec_ins *ins )
/**********************************************************************/
// dir 1 0
// Destination Reg MODRM
// Source MODRM Reg
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?