docode.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,247 行 · 第 1/3 页
C
1,247 行
static void MMModRM( int direction )
{
D_Bit = direction;
W_Bit = 0;
DoOTModRM();
CurrIns.modifier = MOD_NONE;
if( CurrIns.op[ OP_1 ].mode == ADDR_REG ) {
if( !(CurrIns.opcode == I_MOVD && direction == 0) ) {
CurrIns.op[ OP_1 ].base += FIRST_MM_REG - FIRST_BYTE_REG;
} else {
CurrIns.op[ OP_1 ].base += FIRST_DWORD_REG - FIRST_BYTE_REG;
}
}
if( CurrIns.op[ OP_2 ].mode == ADDR_REG ) {
if( !(CurrIns.opcode == I_MOVD && direction == 1) ) {
CurrIns.op[ OP_2 ].base += FIRST_MM_REG - FIRST_BYTE_REG;
} else {
CurrIns.op[ OP_2 ].base += FIRST_DWORD_REG - FIRST_BYTE_REG;
}
}
}
static void Opcode0F( char use_32 ) {
/***************************************/
int index;
unsigned char second;
GetDataByte();
second = SecondByte;
SecondByte = GetNextByte();
W_Bit = second & 1;
D_Bit = 0;
switch( ( second >> 4 ) & 0x0F ) {
case 0x00:
index = _RegField( SecondByte );
switch( second ) {
case 0:
CurrIns.opcode = S00Ops[ index ];
GetOperands( OT_RMW, use_32 );
CurrIns.mem_ref_size = 2;
break;
case 1:
CurrIns.opcode = S01Ops[ index ];
if( index == 7 ) { // INVLPG
GetOperands( OT_M, use_32 );
CurrIns.modifier = MOD_NONE;
CurrIns.mem_ref_size = 1;
} else {
GetOperands( OT_RMW, use_32 );
if( index <= 3 ) { // SIDT SGDT LGDT LIDT
CurrIns.mem_ref_size = 6;
} else {
CurrIns.mem_ref_size = 2;
}
}
break;
case 2:
CurrIns.opcode = I_LAR;
GetOperands( OT_RV_RMW, use_32 );
break;
case 3:
CurrIns.opcode = I_LSL;
GetOperands( OT_RV_RMW, use_32 );
break;
case 6:
CurrIns.opcode = I_CLTS;
break;
case 8:
CurrIns.opcode = I_INVD;
break;
case 9:
CurrIns.opcode = I_WBINVD;
break;
default:
CurrIns.opcode = I_INVALID;
}
break;
case 0x02:
CurrIns.opcode = I_MOV;
D_Bit = second & 2;
GetOperands( S2xOpType[ second & 0x0f ], use_32 );
break;
case 0x03:
switch( second & 0x0f ) {
case 0x00:
CurrIns.opcode = I_WRMSR;
break;
case 0x01:
CurrIns.opcode = I_RDTSC;
break;
case 0x02:
CurrIns.opcode = I_RDMSR;
break;
case 0x03:
CurrIns.opcode = I_RDMPC;
break;
default:
CurrIns.opcode = I_INVALID;
break;
}
break;
case 0x04:
CurrIns.opcode = S4xInsTab[ second & 0x0f ].name;
GetOperands( S4xInsTab[ second & 0x0f ].op_type, use_32 );
break;
case 0x08:
CurrIns.opcode = S8xOps[ second & 0x0f ];
GetOperands( OT_IP_INC16, use_32 );
break;
case 0x09:
CurrIns.opcode = S9xOps[ second & 0x0f ];
GetOperands( OT_RMB, use_32 );
break;
case 0x0A:
CurrIns.opcode = SAxOps[ second & 0x0f ];
if( CurrIns.opcode == I_IMUL ) {
D_Bit = 1;
}
GetOperands( SAxOpType[ second & 0x0f ], use_32 );
break;
case 0x0B:
CurrIns.opcode = SBxOps[ second & 0x0f ];
if( CurrIns.opcode == I_BSF || CurrIns.opcode == I_BSR ) D_Bit = 1;
if( CurrIns.opcode == I_BTx ) {
W_Bit = 1;
CurrIns.opcode = SBAOps[ _RegField( SecondByte ) ];
}
GetOperands( SBxOpType[ second & 0x0f ], use_32 );
break;
case 0x0C:
if( second & 0x08 ) {
CurrIns.opcode = I_BSWAP;
CurrIns.num_oper = 1;
CurrIns.op[ OP_1 ].mode = ADDR_REG;
CurrIns.op[ OP_1 ].base = VarReg( FIRST_WORD_REG + ( second & 7 ) );
} else if( (second & 0x0f) == 0x07 ) {
/* group 9 */
if( (SecondByte & 0x38) == 0x08 ) {
CurrIns.opcode = I_CMPXCHG8B;
CurrIns.num_oper = 1;
ModRMOp( OP_1, FALSE );
} else {
CurrIns.opcode = I_INVALID;
}
} else {
CurrIns.opcode = SCxOps[ second & 0x07 ];
GetOperands( SCxOpType[ second & 0x07 ], use_32 );
}
break;
case 0x06:
CurrIns.opcode = S6xInsTab[ second & 0x0f ].name;
GetOperands( S6xInsTab[ second & 0x0f ].op_type, use_32 );
break;
case 0x07:
CurrIns.opcode = S7xInsTab[ second & 0x0f ].name;
switch( second & 0x0f ) {
case 0x1:
case 0x2:
case 0x3:
/* a shift immediate opcode */
switch( SecondByte & 0xf8 ) {
case 0xF0: /* PSLL */
break;
case 0xD0: /* PSRL */
CurrIns.opcode += 1;
break;
case 0xE0: /* PSRA */
CurrIns.opcode += 2;
if( CurrIns.opcode == I_PSRAQ ) {
/* doesn't exist */
CurrIns.opcode = I_INVALID;
return;
}
break;
default:
CurrIns.opcode = I_INVALID;
return;
}
GetDataByte(); /* get set up for grabbing the immediate */
}
GetOperands( S7xInsTab[ second & 0x0f ].op_type, use_32 );
break;
case 0x0d:
CurrIns.opcode = SDxInsTab[ second & 0x0f ].name;
GetOperands( SDxInsTab[ second & 0x0f ].op_type, use_32 );
break;
case 0x0e:
CurrIns.opcode = SExInsTab[ second & 0x0f ].name;
GetOperands( SExInsTab[ second & 0x0f ].op_type, use_32 );
break;
case 0x0f:
CurrIns.opcode = SFxInsTab[ second & 0x0f ].name;
GetOperands( SFxInsTab[ second & 0x0f ].op_type, use_32 );
break;
default:
CurrIns.opcode = I_INVALID;
break;
}
}
static void ConstByteOp( int op )
/*********************************/
{
operand *opnd;
opnd = &CurrIns.op[ op ];
opnd->mode = ADDR_CONST;
opnd->size = 1;
opnd->offset = InsOffset();
opnd->disp = GetDataByte();
}
static void ConstSexOp( int op )
/******************************/
{
ConstByteOp( op );
CurrIns.op[ op ].size = ( CurrIns.pref & OPND_LONG ) ? 4 : 2;
}
static void ConstWordOp( int op )
/*********************************/
{
operand *opnd;
opnd = &CurrIns.op[ op ];
opnd->mode = ADDR_CONST;
opnd->size = 2;
opnd->offset = InsOffset();
opnd->disp = GetDataWord();
}
static void ConstLongOp( int op )
/*********************************/
{
operand *opnd;
opnd = &CurrIns.op[ op ];
opnd->mode = ADDR_CONST;
opnd->size = 4;
opnd->offset = InsOffset();
opnd->disp = GetDataLong();
}
static void ConstVarOp( int op )
/*********************************/
{
if( CurrIns.pref & OPND_LONG ) {
ConstLongOp( op );
} else {
ConstWordOp( op );
}
}
static void AccumOp( int op )
/*****************************/
{
CurrIns.op[ op ].mode = ADDR_REG;
if( W_Bit ) {
CurrIns.op[ op ].base = VarReg( AX_REG );
} else {
CurrIns.op[ op ].base = AL_REG;
}
}
static void GetOperands( operand_type op_type, char use_32 )
#define _FixDisp( x ) ( use_32 ? (x) : (x) & 0xFFFF )
/************************************************************/
{
int op1;
int op2;
int reg;
uint_32 disp;
address_mode mode;
prefix save_pref;
op1 = OP_1;
op2 = OP_2;
switch( op_type ) {
case OT_NULL:
break;
case OT_ES_DI: /* stos, scas */
if( CurrIns.seg_used == NULL_REG ) {
CurrIns.seg_used = ES_REG;
}
/* fall through */
case OT_DS_SI: /* lods */
case OT_DS_SI_ES_DI: /* movs */
CurrIns.mem_ref_op = OP_1;
mode = ADDR_DS_SI + ( op_type - OT_DS_SI );
if( CurrIns.pref & ADDR_LONG ) ++mode; /* DS_SI -> DS_ESI */
CurrIns.op[ OP_1 ].mode = mode;
break;
case OT_THREE: /* int 3 */
CurrIns.num_oper = 1;
CurrIns.op[ OP_1 ].mode = ADDR_CONST;
CurrIns.op[ OP_1 ].disp = 3;
break;
case OT_ENTER: /* enter locals,level */
CurrIns.num_oper = 2;
ConstWordOp( OP_1 );
ConstByteOp( OP_2 );
break;
case OT_DX_ACCUM: /* out DX,AL */
op1 = OP_2;
op2 = OP_1;
/* fall through */
case OT_ACCUM_DX: /* in AL,DX */
CurrIns.num_oper = 2;
AccumOp( op1 );
CurrIns.op[ op2 ].mode = ADDR_REG;
CurrIns.op[ op2 ].base = DX_REG;
break;
case OT_IMMED8_ACCUM: /* out 10,AX */
op1 = OP_2;
op2 = OP_1;
/* fall through */
case OT_ACCUM_IMMED8: /* in AL,10 */
CurrIns.num_oper = 2;
AccumOp( op1 );
ConstByteOp( op2 );
break;
case OT_ACCUM_IMMED: /* mov AL,7 */
CurrIns.num_oper = 2;
AccumOp( OP_1 );
if( W_Bit ) {
ConstVarOp( OP_2 );
} else {
ConstByteOp( OP_2 );
}
break;
case OT_ACCUM_MEM: /* mov AX,[a000] */
if( D_Bit ) {
op1 = OP_2;
op2 = OP_1;
}
CurrIns.num_oper = 2;
AccumOp( op1 );
CurrIns.mem_ref_op = op2;
if( CurrIns.pref & ADDR_LONG ) {
ConstLongOp( op2 );
} else {
ConstWordOp( op2 );
}
CurrIns.op[ op2 ].mode = ADDR_ABS;
#if defined( O2A )
if( Options & FORM_ASSEMBLER ) {
if( W_Bit == 0 ) {
CurrIns.modifier = MOD_BYTE;
} else if( CurrIns.pref & OPND_LONG ) {
CurrIns.modifier = MOD_LINT;
} else {
CurrIns.modifier = MOD_WORD;
}
}
#endif
break;
case OT_ACCUM_REG16: /* xchg AX,CX */
CurrIns.num_oper = 2;
CurrIns.op[ OP_1 ].mode = ADDR_REG;
CurrIns.op[ OP_1 ].base = VarReg( AX_REG );
CurrIns.op[ OP_2 ].mode = ADDR_REG;
CurrIns.op[ OP_2 ].base = VarReg( FIRST_WORD_REG + ( Opcode & 7 ) );
break;
case OT_ESC: /* float instructions */
GetFppOp();
break;
case OT_IMMED: /* push $12 */
CurrIns.num_oper = 1;
ConstSexOp( OP_1 );
break;
case OT_IMMED8: /* int $21 */
CurrIns.num_oper = 1;
ConstByteOp( OP_1 );
break;
case OT_IMMED_WORD: /* ret 2 */
CurrIns.num_oper = 1;
ConstWordOp( OP_1 );
break;
case OT_IMMED16: /* ret 2 */
CurrIns.num_oper = 1;
ConstVarOp( OP_1 );
break;
case OT_IP_INC8: /* je L1 */
case OT_IP_INC16: /* call/jmp L2 */
CurrIns.num_oper = 1;
CurrIns.op[ OP_1 ].mode = ADDR_LABEL;
CurrIns.op[ OP_1 ].offset = InsOffset();
if( op_type == OT_IP_INC8 ) {
CurrIns.op[ OP_1 ].size = 1;
disp = GetDataByte();
} else if ( CurrIns.pref & OPND_LONG ) {
CurrIns.op[ OP_1 ].size = 4;
disp = GetDataLong();
} else {
CurrIns.op[ OP_1 ].size = 2;
disp = GetDataWord();
}
disp += GetOffset();
CurrIns.op[ OP_1 ].disp = _FixDisp( disp );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?