docode.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,247 行 · 第 1/3 页
C
1,247 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <string.h>
#include "disasm.h"
instruction CurrIns;
static char W_Bit;
static char D_Bit;
static const address_mode RMMode[] = {
ADDR_BASE_INDEX, /* [BX+SI] */
ADDR_BASE_INDEX, /* [BX+DI] */
ADDR_BASE_INDEX, /* [BP+SI] */
ADDR_BASE_INDEX, /* [BP+DI] */
ADDR_INDEX, /* [SI] */
ADDR_INDEX, /* [DI] */
ADDR_BASE, /* [BP] */
ADDR_BASE /* [BX] */
};
static const processor_reg RMBase[] = {
BX_REG, /* [BX+SI] */
BX_REG, /* [BX+DI] */
BP_REG, /* [BP+SI] */
BP_REG, /* [BP+DI] */
0, /* [SI] */
0, /* [DI] */
BP_REG, /* [BP] */
BX_REG /* [BX] */
};
static const processor_reg RMIndex[] = {
SI_REG, /* [BX+SI] */
DI_REG, /* [BX+DI] */
SI_REG, /* [BP+SI] */
DI_REG, /* [BP+DI] */
SI_REG, /* [SI] */
DI_REG, /* [DI] */
0, /* [BP] */
0, /* [BX] */
};
static const processor_reg RMSeg[] = {
DS_REG, /* [BX+SI] */
DS_REG, /* [BX+DI] */
SS_REG, /* [BP+SI] */
SS_REG, /* [BP+DI] */
DS_REG, /* [SI] */
DS_REG, /* [DI] */
SS_REG, /* [BP] */
DS_REG, /* [BX] */
};
static const processor_reg RM32Reg[] = {
EAX_REG,
ECX_REG,
EDX_REG,
EBX_REG,
ESP_REG,
EBP_REG,
ESI_REG,
EDI_REG
};
static const processor_reg RM32Seg[] = {
DS_REG,
DS_REG,
DS_REG,
DS_REG,
SS_REG,
SS_REG,
DS_REG,
DS_REG
};
/*
* Static function prototypes
*/
static void GetOperands( operand_type, char );
static ins_name GetInsName( ins_name );
static processor_reg VarReg( processor_reg reg )
/**********************************************/
{
if( CurrIns.pref & OPND_LONG ) {
reg += FIRST_DWORD_REG - FIRST_WORD_REG;
}
return( reg );
}
static uint_8 InsOffset( void )
/*****************************/
{
return( GetOffset() - InsAddr );
}
#if !defined( O2A )
static int LookFor87Emulation( void )
/************************************/
{
char second_byte;
int inssize;
int seg_reg;
inssize = 0;
if( Opcode == 0xCD ) {
second_byte = GetNextByte();
if( second_byte >= 0x34 && second_byte <= 0x3d ) {
CurrIns.pref |= EMU_INTERRUPT;
CurrIns.op[ OP_3 ].disp = second_byte;
if( second_byte <= 0x3b ) {
Opcode = GetDataByte() + 0xA4;
++inssize;
} else if ( second_byte == 0x3D ) {
GetDataByte();
Opcode = 0x90;
inssize++;
} else { /* 0x3C */
GetDataByte();
Opcode = GetDataByte();
seg_reg = ( ~Opcode >> 6 ) & 3;
CurrIns.pref |= SegPrefixTab[ seg_reg ];
CurrIns.seg_used = FIRST_SEG_REG + seg_reg;
inssize += 2;
Opcode |= 0xC0;
}
}
}
return( inssize );
}
#endif
static void SetOperands( char opcode )
/****************************************/
{
W_Bit = opcode & 1;
if( CurrIns.opcode == I_BOUND ) {
W_Bit = 1;
}
if( W_Bit ) {
if( CurrIns.pref & OPND_LONG ) {
CurrIns.mem_ref_size = 4;
} else {
CurrIns.mem_ref_size = 2;
}
} else {
CurrIns.mem_ref_size = 1;
}
if( CurrIns.opcode == I_ARPL ) {
D_Bit = 0;
} else {
D_Bit = opcode & 2;
}
}
void DoCode( instruction *curr, char use_32 )
/*******************************************/
{
operand_type op_type;
ins_name instr_name;
int seg_reg;
#if defined( O2A )
int i;
operand *op;
#endif
memset( &CurrIns, 0, sizeof( instruction ) );
CurrIns.modifier = MOD_NONE;
CurrIns.mem_ref_op = NULL_OP;
for( ;; ) { /* collect prefix */
if( EndOfSegment() ) {
if( instr_name == I_WAIT ) {
instr_name = I_NULL;
} else {
instr_name = I_INVALID;
}
break;
}
Opcode = GetDataByte();
#if !defined( O2A )
LookFor87Emulation();
#endif
instr_name = InsTab[ Opcode ].name;
op_type = InsTab[ Opcode ].op_type;
if( op_type == OT_PREFIX ) {
if( CurrIns.pref & PrefixTab[ Opcode - 0xf0 ] ) {
break;
}
CurrIns.pref |= PrefixTab[ Opcode - 0xf0 ]; /* 0xf0 == LOCK */
} else if( op_type == OT_SEG_REG ) {
seg_reg = _SegReg2Field( Opcode );
if( CurrIns.pref & SegPrefixTab[ seg_reg ] ) {
break;
}
CurrIns.pref |= SegPrefixTab[ seg_reg ];
CurrIns.seg_used = FIRST_SEG_REG + seg_reg;
} else if( op_type == OT_FS ) {
CurrIns.pref |= PREF_FS;
CurrIns.seg_used = FS_REG;
} else if( op_type == OT_GS ) {
CurrIns.pref |= PREF_GS;
CurrIns.seg_used = GS_REG;
} else if( op_type == OT_OPND_SIZE ) {
CurrIns.pref |= PREF_OPND_SIZE;
} else if( op_type == OT_ADDR_SIZE ) {
CurrIns.pref |= PREF_ADDR_SIZE;
} else if( instr_name == I_WAIT ) {
/* any prefixes collected so far will apply to the WAIT instruction
so decode it separately */
if( CurrIns.pref != 0 ) {
break;
}
CurrIns.pref |= PREF_FWAIT;
} else {
break;
}
}
if( CurrIns.pref & PREF_OPND_SIZE ) {
if( !use_32 ) CurrIns.pref |= OPND_LONG;
} else {
if( use_32 ) CurrIns.pref |= OPND_LONG;
}
if( CurrIns.pref & PREF_ADDR_SIZE ) {
if( !use_32 ) CurrIns.pref |= ADDR_LONG;
} else {
if( use_32 ) CurrIns.pref |= ADDR_LONG;
}
SecondByte = GetNextByte();
CurrIns.opcode = GetInsName( instr_name );
if( CurrIns.opcode != I_INVALID ) {
SetOperands( Opcode );
GetOperands( op_type, use_32 );
if( CurrIns.opcode != I_INVALID ) {
if( CurrIns.seg_used == NULL_REG ) {
CurrIns.seg_used = DS_REG;
}
#if defined( O2A )
if( CurrIns.opcode == I_RET_FAR ) {
RetFarUsed = TRUE;
}
for( i = 0; i < CurrIns.num_oper; ++i ) { /* locate labels */
op = &CurrIns.op[ i ];
if( op->mode == ADDR_LABEL ) {
FindLabel( InsAddr + op->offset, op->disp, Segment );
} else if( op->mode == ADDR_SEG_OFFSET ) {
FindSymbol( InsAddr + op->offset );
} else if( op->offset != 0 ) {
FindSymbol( InsAddr + op->offset );
}
}
#endif
}
}
if( IsWtk( &CurrIns ) ) {
DoWtk( /*&CurrIns*/ );
}
CurrIns.ins_size = InsOffset();
*curr = CurrIns;
}
static ins_name GetInsName( ins_name instr_name )
/***********************************************/
{
int index;
index = _RegField( SecondByte );
switch( instr_name ) {
case I_IMMED:
instr_name = ImmedTable[ index ];
break;
case I_SHIFT:
instr_name = ShiftTable[ index ];
break;
case I_GROUP1:
instr_name = Group1Table[ index ];
break;
case I_GROUP2:
instr_name = Group2Table[ index ];
break;
case I_GROUP3:
instr_name = Group3Table[ index ];
break;
case I_ESC:
instr_name = GetFppCode();
if( instr_name != I_INVALID ) CurrIns.pref |= FP_INS;
break;
default:
if( CurrIns.pref & OPND_LONG ) {
switch( instr_name ) {
case I_RET_FAR:
/* change retf to retd only in use16 segment */
if( !(CurrIns.pref & PREF_OPND_SIZE) ) break;
/* fall through */
case I_PUSHF:
case I_POPF:
case I_PUSHA:
case I_POPA:
case I_INSW:
case I_OUTSW:
case I_MOVSW:
case I_CMPSW:
case I_STOSW:
case I_LODSW:
case I_SCASW:
case I_IRET:
case I_CBW:
case I_CWD:
++instr_name; /* ie: INSW -> INSD */
}
}
}
return( instr_name );
}
void DoControl( int base )
/************************/
{
int op1,op2;
if( D_Bit ) {
op1 = OP_2;
op2 = OP_1;
} else {
op1 = OP_1;
op2 = OP_2;
}
CurrIns.op[ op1 ].mode = ADDR_REG;
CurrIns.op[ op1 ].base = FIRST_DWORD_REG + ( SecondByte & 7 );
CurrIns.op[ op2 ].mode = ADDR_REG;
CurrIns.op[ op2 ].base = base + ( ( SecondByte >> 3 ) & 7 );
CurrIns.num_oper = 2;
GetDataByte();
}
void DoOTModRM( void )
/********************/
{
int reg;
int op1;
int op2;
if( D_Bit ) {
op1 = OP_2;
op2 = OP_1;
} else {
op1 = OP_1;
op2 = OP_2;
}
CurrIns.num_oper = 2;
ModRMOp( op1, FALSE );
CurrIns.op[ op2 ].mode = ADDR_REG;
reg = _RegField( SecondByte );
if( W_Bit ) {
CurrIns.op[ op2 ].base = VarReg( FIRST_WORD_REG + reg );
} else {
CurrIns.op[ op2 ].base = FIRST_BYTE_REG + reg;
}
}
static void SetPWord( void )
/**************************/
{
if( CurrIns.pref & OPND_LONG ) {
CurrIns.modifier = MOD_PWORD;
CurrIns.mem_ref_size = 6;
} else {
CurrIns.modifier = MOD_LINT;
CurrIns.mem_ref_size = 4;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?