i86enc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,335 行 · 第 1/5 页
C
2,335 行
if( ins->ins_flags & INS_CC_USED ) return( TRUE );
if( ins->result == NULL ) return( TRUE );
switch( ins->result->n.class ) {
case N_TEMP:
/* it's OK to store a DWORD into a WORD temp because there's always
two bytes of slack on the stack */
if( ins->result->t.alias != ins->result ) return( TRUE );
break;
case N_REGISTER:
/* check that it's OK to trash high word of register */
next = ins->head.next;
if( next == NULL ) return( TRUE );
result_reg = ins->result->r.reg;
full_reg = FullReg( result_reg );
HW_TurnOff( full_reg, result_reg );
if( HW_Ovlap( full_reg, next->head.live.regs ) ) return( TRUE );
break;
default:
return( TRUE );
}
for( i = ins->num_operands-1; i >= 0; --i ) {
/* Could be smarter here and allow N_MEMORY,N_INDEXED if
they're in DGROUP */
switch( ins->operands[i]->n.class ) {
case N_TEMP:
case N_REGISTER:
case N_CONSTANT:
break;
default:
return( TRUE );
}
}
ins->type_class = U4; /* get correct size of constants */
return( FALSE );
}
#endif
static bool LayOpndSize( instruction *ins, gentype gen ) {
/*************************************************************
Generate an operand size prefix if the instruction needs it
(Eg: MOV AX,DX need it in a USE32 segment)
*/
#if _TARGET & _TARG_80386
switch( ins->head.opcode ) {
case OP_CONVERT: /* these ones handle themselves */
case OP_CALL:
case OP_CALL_INDIRECT:
case OP_SELECT:
return( FALSE );
break;
default:
switch( gen ) {
#if _TARGET & _TARG_IAPX86
case G_POW2DIV_286:
#endif
case G_SR:
case G_RS:
case G_MS1:
case G_SM1:
case G_SEG_SEG:
case G_SEGR1:
case G_POW2DIV:
case G_DIV2:
return( FALSE );
default:
break;
}
if( _IsTargetModel( USE_32 ) ) {
if( ins->type_class == U2 || ins->type_class == I2 ) {
if( NeedOpndSize( ins ) ) {
AddToTemp( M_OPND_SIZE );
return( TRUE );
}
}
} else {
if( ins->type_class == U4
|| ins->type_class == I4
|| ins->type_class == FS ) {
AddToTemp( M_OPND_SIZE );
return( TRUE );
}
}
return( FALSE );
}
#else
gen = gen;
switch( ins->head.opcode ) {
case OP_PUSH:
if( ( gen == G_C1 || gen == G_M1 ) && ins->type_class == I4 ) {
AddToTemp( M_OPND_SIZE );
return( TRUE );
}
break;
case OP_MOV:
if( ins->type_class == U4 || ins->type_class == I4 ) {
if( ( gen == G_MOVMC ) ) {
AddToTemp( M_OPND_SIZE );
return( TRUE );
}
}
break;
default:
break;
}
return( FALSE );
#endif
}
#if 1
static void DoP5RegisterDivide( instruction *ins ) {
/******************************************************/
int i;
byte reverse;
byte pop;
byte dest;
int ins_key;
label_handle lbl;
label_handle lbl_2;
oc_jcond temp;
lbl = AskForNewLabel();
lbl_2 = AskForNewLabel();
temp.op.class = OC_JCOND;
temp.op.class |= ATTR_SHORT;
temp.op.objlen = OptInsSize( OC_JCOND, OC_DEST_NEAR );
temp.op.reclen = sizeof( oc_jcond );
temp.cond = 4;
temp.handle = lbl;
InputOC( (any_oc *)&temp );
i = FPRegTrans( ins->operands[ 0 ]->r.reg );
reverse = FALSE;
pop = FALSE;
dest = FALSE;
switch( ins->u.gen_table->generate ) {
case G_RRFBIN:
reverse = TRUE;
break;
case G_RNFBIN:
break;
case G_RRFBINP:
reverse = TRUE;
pop = TRUE;
dest = TRUE;
break;
case G_RNFBINP:
pop = TRUE;
dest = TRUE;
break;
case G_RRFBIND:
reverse = TRUE;
dest = TRUE;
break;
case G_RNFBIND:
dest = TRUE;
break;
}
ins_key = ( pop & 1 ) | ( ( reverse & 1 ) << 1 ) | ( ( dest & 1 ) << 2 );
ins_key |= ( i & 0x07 ) << 3;
// je ok
_Code;
_Next;
// push [e]ax
LayOpbyte( 0x50 );
_Next;
// mov #cons -> [e]ax
LayOpbyte( 0xb8 );
#if _TARGET & _TARG_80386
AddWData( ins_key, U4 );
#else
AddWData( ins_key, U2 );
#endif
_Emit;
// call __fdiv_fpr
RTCall( RT_FDIV_FPREG, 0 );
_Code;
// pop [e]ax
LayOpbyte( 0x58 );
_Emit;
GenJumpLabel( lbl_2 );
CodeLabel( lbl, 0 );
_Code;
LayInitial( ins, ins->u.gen_table->generate );
LayOpndSize( ins, ins->u.gen_table->generate );
LayST( ins->operands[ 0 ] );
_Emit;
CodeLabel( lbl_2, 0 );
GenKillLabel( lbl );
GenKillLabel( lbl_2 );
}
#if _TARGET & _TARG_80386
extern type_length StackDepth;
#endif
static void DoP5MemoryDivide( instruction *ins ) {
/****************************************************/
oc_jcond temp;
int rtindex;
label_handle lbl;
label_handle lbl_2;
name *high;
name *low;
#if !(_TARGET & _TARG_80386)
name *h;
name *l;
#endif
name *seg;
lbl = AskForNewLabel();
lbl_2 = AskForNewLabel();
temp.op.class = OC_JCOND;
temp.op.class |= ATTR_SHORT;
temp.op.objlen = OptInsSize( OC_JCOND, OC_DEST_NEAR );
temp.op.reclen = sizeof( oc_jcond );
temp.cond = 4;
temp.handle = lbl;
InputOC( (any_oc *)&temp );
seg = NULL;
if( ins->num_operands > NumOperands( ins ) ) {
seg = ins->operands[ ins->num_operands - 1 ];
}
_Code;
switch( ins->operands[ 0 ]->n.name_class ) {
case FS:
#if _TARGET & _TARG_80386
if( seg != NULL ) GenSeg( seg->r.reg );
LayOpword( 0x30ff );
LayModRM( ins->operands[ 0 ] );
#else
high = HighPart( ins->operands[ 0 ], U2 );
low = LowPart( ins->operands[ 0 ], U2 );
if( seg != NULL ) GenSeg( seg->r.reg );
LayOpword( 0x30ff );
LayModRM( high );
_Next;
if( seg != NULL ) GenSeg( seg->r.reg );
LayOpword( 0x30ff );
LayModRM( low );
#endif
if( ins->u.gen_table->generate == G_MRFBIN ) {
rtindex = RT_FDIV_MEM32R;
} else {
rtindex = RT_FDIV_MEM32;
}
break;
case FD:
high = HighPart( ins->operands[ 0 ], U4 );
low = LowPart( ins->operands[ 0 ], U4 );
#if _TARGET & _TARG_80386
if( seg != NULL ) GenSeg( seg->r.reg );
LayOpword( 0x30ff );
LayModRM( high );
_Next;
StackDepth += WORD_SIZE;
if( seg != NULL ) GenSeg( seg->r.reg );
LayOpword( 0x30ff );
LayModRM( low );
StackDepth -= WORD_SIZE;
#else
h = HighPart( high, U2 );
l = LowPart( high, U2 );
if( seg != NULL ) GenSeg( seg->r.reg );
LayOpword( 0x30ff );
LayModRM( h );
_Next;
if( seg != NULL ) GenSeg( seg->r.reg );
LayOpword( 0x30ff );
LayModRM( l );
_Next;
h = HighPart( low, U2 );
l = LowPart( low, U2 );
if( seg != NULL ) GenSeg( seg->r.reg );
LayOpword( 0x30ff );
LayModRM( h );
_Next;
if( seg != NULL ) GenSeg( seg->r.reg );
LayOpword( 0x30ff );
LayModRM( l );
_Next;
#endif
if( ins->u.gen_table->generate == G_MRFBIN ) {
rtindex = RT_FDIV_MEM64R;
} else {
rtindex = RT_FDIV_MEM64;
}
break;
default:
rtindex = RT_FDIV_MEM64;
_Zoiks( ZOIKS_114 );
}
_Emit;
RTCall( rtindex, 0 );
GenJumpLabel( lbl_2 );
CodeLabel( lbl, 0 );
_Code;
if( seg != NULL ) {
GenSeg( seg->r.reg );
}
LayInitial( ins, ins->u.gen_table->generate );
LayOpndSize( ins, ins->u.gen_table->generate );
LayMF( ins->operands[ 0 ] );
LayModRM( ins->operands[ 0 ] );
_Emit;
CodeLabel( lbl_2, 0 );
GenKillLabel( lbl );
GenKillLabel( lbl_2 );
}
static void DoP5Divide( instruction *ins ) {
/***********************************************
Emit a most disgusting sequence of code to
test for the Pentium FDIV bug and call a
runtime routine to correct it.
*/
bool used_ds = FALSE;
_Code;
LayOpbyte( 0x9c ); /* pushf */
_Emit;
#if _TARGET & _TARG_80386
StackDepth += WORD_SIZE;
#endif
_Code;
if( _IsTargetModel( FLOATING_DS ) ) {
if( _IsTargetModel( FLOATING_SS ) ) {
LayOpbyte( 0x1e ); // push ds
AddByte( 0x50 ); // push ax
_Emit;
GenLoadDS();
_Code;
used_ds = TRUE;
} else {
AddToTemp( 0x36 );
}
}
#if ( _TARGET & _TARG_80386 )
LayOpword( 0x05f6 );
#else
LayOpword( 0x06f6 );
#endif
ILen += WORD_SIZE;
DoLblRef( RTLabel( RT_BUGLIST - BEG_RTNS ), AskBackSeg(), 0, F_OFFSET );
AddWData( 1, U1 );
_Emit;
if( used_ds ) {
_Code;
LayOpbyte( 0x58 ); // pop ax
AddByte( 0x1f ); // pop ds
_Emit;
}
switch( ins->u.gen_table->generate ) {
case G_RRFBIN:
case G_RNFBIN:
case G_RRFBIND:
case G_RNFBIND:
case G_RRFBINP:
case G_RNFBINP:
// assuming G_RXFBINZ means
// X -> R (reverse) and N (normal)
// Z -> D (destination is argument)
// -> P (argument is popped)
DoP5RegisterDivide( ins );
break;
case G_MRFBIN:
case G_MNFBIN:
DoP5MemoryDivide( ins );
}
_Code;
LayOpbyte( 0x9d ); /* popf */
_Emit;
#if _TARGET & _TARG_80386
StackDepth -= WORD_SIZE;
#endif
}
#endif
extern void GenObjCode( instruction *ins ) {
/***********************************************
Generate object code for the instruction "ins" based on gen_table->generate
*/
gentype gen;
name *result;
name *left = NULL;
name *right = NULL;
int i;
bool opnd_size;
gen = ins->u.gen_table->generate;
if( gen != G_NO ) {
#if 1
// fixme - should be _IsTargetModel
if( _IsTargetModel( P5_DIVIDE_CHECK ) ) {
if( ins->head.opcode == OP_DIV && _IsFloating( ins->type_class ) ) {
DoP5Divide( ins );
return;
}
}
#endif
result = ins->result;
if( ins->num_operands != 0 ) {
left = ins->operands[ 0 ];
if( ins->num_operands != 1 ) {
right = ins->operands[ 1 ];
}
}
if (gen == G_MFSTRND)
{
/*
68 3F 0C 00 00 push 0x00000c3f
D9 7C 24 02 fnstcw word ptr 0x2[esp]
D9 2C 24 fldcw word ptr [esp]
*/
_Code;
AddByte(0x68);
AddByte(0x3f);
AddByte(0x0c);
AddByte(0x00);
AddByte(0x00);
_Emit;
_Code;
AddByte(0xd9);
AddByte(0x7c);
AddByte(0x24);
AddByte(0x02);
_Emit;
_Code;
AddByte(0xd9);
AddByte(0x2c);
AddByte(0x24);
_Emit;
}
_Code;
LayInitial( ins, gen );
i = ins->num_operands;
--i;
if( i >= NumOperands( ins ) ) {
if( ins->operands[ i ]->n.class == N_REGISTER ) {
GenSeg( ins->operands[ i ]->r.reg );
} else {
_Zoiks( ZOIKS_027 );
}
}
opnd_size = LayOpndSize( ins, gen );
switch( gen ) {
case G_RC:
LayRMRegOp( left );
AddSWCons( ins->head.opcode, right, ins->type_class );
break;
case G_AC:
ICur--;
ILen--;
IEsc--;
AddWCons( right, ins->type_class );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?