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 + -
显示快捷键?