i86enc32.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,002 行 · 第 1/3 页
C
1,002 行
&& (lea || (_IsntTargetModel(FLOATING_DS)&&_IsntTargetModel(FLOATING_SS)))
) {
/*
flip base & index registers so that we might avoid
having to output a byte displacement (can't have a
zero sized displacement with [E]BP as the base
register)
*/
base = index;
HW_CAsgn( index, HW_BP );
}
Inst[ RMR ] |= DoScaleIndex( base, index, scale );
}
Inst[ RMR ] |= DoDisp( val, base, mem_loc );
}
}
/*
* 2004-11-05 RomanT
*
* Check that following instruction is addition or substraction with constant,
* and this instruction is safe to delete (ALU flags not generated).
* If yes, return constant's value and delete instruction.
* If no, return 0.
* Caller must embed returned constant into current opcode.
*/
static signed_32 GetNextAddConstant( instruction *ins )
/*******************************************************/
{
instruction *next;
int neg;
signed_32 disp;
next = ins->head.next;
neg = 1;
disp = 0;
switch( next->head.opcode ) {
case OP_SUB:
neg = -1;
/* fall through */
case OP_ADD:
if( next->operands[0] != ins->result ) break;
if( next->result != ins->result ) break;
if( next->operands[1]->n.class != N_CONSTANT ) break;
if( next->operands[1]->c.const_type != CONS_ABSOLUTE ) break;
/* we should not remove the ADD if its flags are used! */
if( next->ins_flags & INS_CC_USED ) break;
/*
we've got something like:
LEA EAX, [ECX+EDX]
ADD EAX, 3
turn it into:
LEA EAX, 3[ECX+EDX]
*/
disp = neg*next->operands[1]->c.int_value,
DoNothing( next );
break;
}
return disp;
}
extern void LayLeaRegOp( instruction *ins )
/*********************************************/
{
name *left;
name *right;
int shift;
int neg;
signed_32 disp;
left = ins->operands[ 0 ];
right = ins->operands[ 1 ];
neg = 1;
switch( ins->head.opcode ) { /* add/sub/mul/shift transformed into lea */
case OP_SUB:
neg = -1;
/* fall through */
case OP_ADD:
if( right->n.class == N_CONSTANT ) {
if( right->c.const_type == CONS_ABSOLUTE ) {
EA( HW_EMPTY, left->r.reg, 0, neg*right->c.int_value,
NULL, TRUE );
} else {
EA( HW_EMPTY, left->r.reg, 0, 0, right, TRUE );
}
} else if( right->n.class == N_REGISTER ) {
disp = GetNextAddConstant( ins );
EA( left->r.reg, right->r.reg, 0, disp, NULL, TRUE );
}
break;
case OP_MUL:
switch( right->c.int_value ) {
case 3: shift = 1; break;
case 5: shift = 2; break;
case 9: shift = 3; break;
}
disp = GetNextAddConstant( ins ); /* 2004-11-05 RomanT */
EA( left->r.reg, left->r.reg, shift, disp, NULL, TRUE );
break;
case OP_LSHIFT:
disp = GetNextAddConstant( ins ); /* 2004-11-05 RomanT */
switch( right->c.int_value ) {
case 1:
if( _CPULevel( CPU_586 ) ) {
// want to avoid the extra big-fat 0 on 586's
// but two base registers is slower on a 486
EA( left->r.reg, left->r.reg, 0, disp, NULL, TRUE );
break;
}
/* fall through */
default:
EA( HW_EMPTY, left->r.reg, right->c.int_value, disp, NULL, TRUE );
}
break;
}
}
static void CheckSize( void )
/*******************************/
{
if( _IsntTargetModel( USE_32 ) ) {
AddToTemp( M_ADDR_SIZE );
}
}
extern void LayModRM( name *op )
/**********************************/
{
name *base;
switch( op->n.class ) {
case N_MEMORY:
CheckSize();
EA( HW_EMPTY, HW_EMPTY, 0, 0, op, FALSE );
break;
case N_TEMP:
CheckSize();
base = DeAlias( op );
if( base->t.location == NO_LOCATION ) {
_Zoiks( ZOIKS_030 );
}
if( BaseIsSP( base ) ) {
EA( HW_SP, HW_EMPTY, 0, TmpLoc( base, op ), NULL, FALSE );
} else {
EA( HW_BP, HW_EMPTY, 0, TmpLoc( base, op ), NULL, FALSE );
}
break;
case N_INDEXED:
LayIdxModRM( op );
break;
case N_REGISTER:
LayRMRegOp( op );
break;
}
}
static void LayIdxModRM( name *op )
/*************************************/
{
hw_reg_set base_reg;
hw_reg_set idx_reg;
name *mem_loc;
CheckSize();
if( HW_COvlap( op->i.index->r.reg, HW_SEGS ) ) {
/* check for seg override*/
GenSeg( op->i.index->r.reg );
}
idx_reg = op->i.index->r.reg;
HW_CTurnOff( idx_reg, HW_SEGS );
HW_CAsgn( base_reg, HW_EMPTY );
if( HasTrueBase( op ) ) {
if( op->i.base->n.class == N_TEMP ) {
if( BaseIsSP( op->i.base ) ) {
HW_CAsgn( base_reg, HW_SP );
} else {
HW_CAsgn( base_reg, HW_BP );
}
} else if( op->i.base->n.class == N_MEMORY ) {
GenSeg( CalcSegment( op->i.base->v.symbol,
op->i.base->m.memory_type ) );
}
mem_loc = op->i.base;
} else {
mem_loc = NULL;
}
if( op->i.index_flags & X_BASE ) {
if( op->i.index_flags & X_HIGH_BASE ) {
base_reg = High64Reg( idx_reg );
} else {
base_reg = Low64Reg( idx_reg );
}
}
HW_TurnOff( idx_reg, base_reg );
if( HW_CEqual( idx_reg, HW_SP ) && HW_CEqual( base_reg, HW_EMPTY ) ) {
HW_CAsgn( base_reg, HW_SP );
HW_CAsgn( idx_reg, HW_EMPTY );
}
EA( base_reg, idx_reg, op->i.scale, op->i.constant, mem_loc, FALSE );
}
static void Add32Displacement( signed_32 val )
/************************************************/
{
AddByte( val );
AddByte( val >> 8 );
AddByte( val >> 16 );
AddByte( val >> 24 );
}
extern void DoMAddr( name *op )
/*********************************/
{
ILen += 4;
if( op->n.class == N_CONSTANT ) {
_Zoiks( ZOIKS_035 );
} else { /* assume global name*/
DoSymRef( op, op->v.offset, FALSE );
}
}
extern void DoRelocConst( name *op, type_class_def kind )
/***********************************************************/
{
if( op->c.const_type == CONS_OFFSET ) {
ILen += 4;
DoSymRef( op->c.value, ((var_name *)op->c.value)->offset, FALSE );
} else if( op->c.const_type == CONS_SEGMENT ) {
ILen += 2;
if( op->c.value == NULL ) {
DoSegRef( op->c.int_value );
} else {
DoSymRef( op->c.value, 0, TRUE );
}
if( kind == U4 || kind == I4 ) { /* as in PUSH seg _x */
AddByte( 0 );
AddByte( 0 );
}
} else if( op->c.const_type == CONS_ADDRESS ) {
_Zoiks( ZOIKS_045 );
}
}
extern void GenUnkPush( pointer value )
/*****************************************/
{
_Code;
LayOpbyte( M_PUSHI );
OpndSizeIf( FALSE );
ILen += 4;
DoAbsPatch( value, 4 );
_Emit;
}
extern void GenPushC( signed_32 value )
/*****************************************/
{
_Code;
LayOpbyte( M_PUSHI );
OpndSizeIf( FALSE );
AddSData( value, I4 );
_Emit;
}
extern void GenUnkLea( pointer value )
/****************************************/
{
LayOpword( M_LEA );
OpndSize( HW_SP );
LayReg( HW_SP );
Inst[ RMR ] |= D32;
ILen += 4;
DoAbsPatch( value, 4 );
Inst[ RMR ] |= DoIndex( HW_BP );
}
extern void GenLeaSP( long offset )
/**************************************
LEA sp,offset[bp]
*/
{
_Code;
LayOpword( M_LEA );
OpndSize( HW_SP );
LayReg( HW_SP );
EA( HW_EMPTY, HW_BP, 0, offset, NULL, FALSE );
_Emit;
}
extern void CodeLabel( label_handle, unsigned );
extern unsigned DepthAlign( unsigned );
extern label_handle AskForNewLabel( void );
extern void TellOptimizerByPassed( void );
extern void SetUpObj( bool );
extern void OutDataByte( byte );
extern void OutDataInt( int );
extern void OutDataLong(long);
extern void OutDBytes(unsigned_32,byte*);
extern void OutRTImport( int, fix_class );
extern void TellKeepLabel( label_handle );
extern void OutReloc( seg_id, fix_class, bool );
extern void TellByPassOver( void );
extern seg_id SetOP( seg_id );
extern seg_id AskCodeSeg( void );
extern void OutLblPatch( label_handle, fix_class, offset );
extern void OutLabel( label_handle );
extern pointer GenFar16Thunk( pointer label, unsigned_16 parms_size, bool remove_parms )
/***************************************************************************************/
{
seg_id old;
pointer code_32;
old = SetOP( AskCode16Seg() );
// CodeLabel( label, DepthAlign( PROC_ALIGN ) );
code_32 = AskForNewLabel();
TellOptimizerByPassed();
SetUpObj( FALSE );
OutLabel( label );
OutDataByte( 0xb9 ); /* mov cx,# */
OutDataInt( parms_size );
OutDataByte( 0x9a );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?