i86split.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,100 行 · 第 1/3 页

C
1,100
字号
/**********************************************/

    constant_defn       *defn;
    unsigned_32         *low;
    unsigned_32         *high;

    defn = GetFloat( name, FD );
    low  = (unsigned_32 *)&defn->value[ 0 ];
    high = (unsigned_32 *)&defn->value[ 2 ];
    return( AllocU64Const( *low, *high ) );
}

extern instruction      *rFSCONSCMP( instruction *ins ) {
/******************************************************/

    name                *name1;

    name1 = ins->operands[ 1 ];
    if( CFTest( name1->c.value ) > 0 ) {
        ChangeType( ins, I4 );
    } else {
        ChangeType( ins, U4 );
        RevCond( ins );
    }
    ins->operands[ 1 ] = IntEquivalent( name1 );
    ins->table = NULL;
    return( ins );
}


extern instruction      *rHIGHLOWMOVE( instruction *ins ) {
/********************************************************/

    instruction         *new_ins;

/* for moving constants such as 0xabcdabcd*/
    new_ins = MakeMove( LowPart( ins->result, U2 ),
                            HighPart( ins->result, U2 ),
                                    U2 );
    ins->result = LowPart( ins->result, U2 );
    ChangeType( ins, U2 );
    DupSegRes( ins, new_ins );
    SuffixIns( ins, new_ins );
    return( ins );
}

#if _TARGET & _TARG_80386
    #define     CX              HW_ECX
    #define     DI              HW_EDI
    #define     ES_DI           HW_ES_EDI
    #define     SI              HW_ESI
    #define     DS_SI           HW_DS_ESI
    #define     LP              CP
    #define     MOV_SIZE        5
#else
    #define     CX              HW_CX
    #define     DI              HW_DI
    #define     ES_DI           HW_ES_DI
    #define     SI              HW_SI
    #define     DS_SI           HW_DS_SI
    #define     LP              PT
    #define     MOV_SIZE        3
#endif

#define hw( x ) x

bool UseRepForm( unsigned size )
/*************************************
    Do we want to use "rep movs{w|d}", or string out multiple "movs{w|d}"
*/
{
    unsigned    count;
    unsigned    extra = 0;
    unsigned    rep_startup;
    unsigned    rep_iter;
    unsigned    movs_cost;

    count = size / WORD_SIZE;
    /* if move than 10 movs, then always use rep form */
    if( count > 10 ) return( TRUE );
    if( OptForSize > 50 ) {
        switch( size % WORD_SIZE ) {
        case 0: extra = 0;      break;
        case 1: extra = 1;      break;
        case 2: extra = 1;      break;
        case 3: extra = 2;      break;
        }
        return( count + extra > MOV_SIZE + 2 );
    }
    if( _CPULevel( CPU_586 ) ) {
        rep_startup = 11;
        rep_iter    = 1;
        movs_cost   = 4;
    } else if( _CPULevel( CPU_486 ) ) {
        rep_startup = 12;
        rep_iter    = 3;
        movs_cost   = 7;
    } else if( _CPULevel( CPU_386 ) ) {
        rep_startup = 8;
        rep_iter    = 4;
        movs_cost   = 8;
    } else if( _CPULevel( CPU_286 ) ) {
        rep_startup = 5;
        rep_iter    = 4;
        movs_cost   = 5;
    } else {
        rep_startup = 9;
        rep_iter    = 17;
        movs_cost   = 18;
    }
    /* The "+ 4" is to account for the "MOV [E]CX, const" clocks and some
        slop for larger instructions (cache effects) */
    return( rep_startup + (count * rep_iter) + 4 < movs_cost * count );
}

static  bool    CanLoadStringOps( instruction *ins ) {
/****************************************************/

    hw_reg_set  needs;

    if( UseRepForm( ins->operands[ 0 ]->n.size ) ) {
        needs = CX;
    } else {
        HW_CAsgn( needs, HW_EMPTY );
    }
    HW_CAsgn( needs, hw( SI ) );
    HW_CTurnOn( needs, hw( DI ) );
    if( _IsTargetModel( FLOATING_DS ) ) {
        HW_CTurnOn( needs, HW_DS );
    }
    if( _IsTargetModel( FLOATING_ES ) ) {
       HW_CTurnOn( needs, HW_ES );
    }
    return( !HW_Ovlap( needs, ins->head.live.regs ) );
}

static name *FakeIndex( name *op, hw_reg_set index ) {
/****************************************************/

    name                *base;
    i_flags             flags;

    if( op->n.class==N_TEMP || op->n.class==N_MEMORY ) {
        base = op;
        flags = X_FAKE_BASE;
    } else {
        base = NULL;
        flags = EMPTY;
    }
    return( ScaleIndex( AllocRegName( index ), base, 0,
                                op->n.name_class, op->n.size, 0, flags ) );
}

static  bool    SegmentFloats( name *op ) {
/***************************************/

    name        *segname;

    segname = SegName( op );
    if( segname->n.class != N_REGISTER ) return( TRUE );
    if( HW_COvlap( segname->r.reg, HW_DS ) ) return( _IsTargetModel( FLOATING_DS ) );
    if( HW_COvlap( segname->r.reg, HW_SS ) ) return( _IsTargetModel( FLOATING_SS ) );
    return( TRUE );
}

static  instruction     *LoadStringOps( instruction *ins,
                                        name **op1, name **op2 ) {
/****************************************************************/


    instruction         *load_op1;
    instruction         *load_op2;
    instruction         *load_len;
    instruction         *first_ins;
    instruction         *pop;
    name                *ds_reg;
    name                *es_reg;
    hw_reg_set          new_op1;
    bool                ds_needs_save;
    bool                es_needs_save;

    if( ins->head.opcode == OP_MOV && !UseRepForm( (*op1)->n.size ) ) {
        load_len = NULL;
        HW_CAsgn( new_op1, HW_EMPTY );
    } else {
        if( ( (*op1)->n.size & (WORD_SIZE-1) ) == 0
          || ( OptForSize <= 50 && ins->head.opcode == OP_MOV ) ) {
            load_len = MoveConst((*op1)->n.size/WORD_SIZE,AllocRegName(CX),WD);
            PrefixIns( ins, load_len );
        } else {
            load_len = MoveConst( (*op1)->n.size, AllocRegName(CX), WD );
            PrefixIns( ins, load_len );
        }
        new_op1 = CX;
    }
    /* careful here. Make sure we load DS last*/
    if( ins->num_operands > NumOperands( ins ) ) {
        if( (*op1)->n.class == N_INDEXED || (*op1)->n.class == N_MEMORY ) {
            load_op1 = MakeUnary( OP_LA, *op2, AllocRegName(ES_DI), LP );
            PrefixIns( ins, load_op1 );
            load_op2 = MakeUnary( OP_LA, *op1, AllocRegName( SI ), WD );
            PrefixIns( ins, load_op2 );
            load_op2 = MakeMove( ins->operands[ ins->num_operands-1 ],
                                  AllocRegName( HW_DS ), U2 );
            PrefixIns( ins, load_op2 );
            es_needs_save = SegmentFloats( *op2 );
            ds_needs_save = TRUE;
        } else {
            load_op1 = MakeMove( ins->operands[ ins->num_operands-1 ],
                                  AllocRegName( HW_ES ), U2 );
            PrefixIns( ins, load_op1 );
            load_op2 = MakeUnary( OP_LA, *op2, AllocRegName( DI ), WD );
            PrefixIns( ins, load_op2 );
            load_op2 = MakeUnary( OP_LA, *op1, AllocRegName(DS_SI), LP );
            PrefixIns( ins, load_op2 );
            ds_needs_save = SegmentFloats( *op1 );
            es_needs_save = TRUE;
        }
        DelSeg( ins );
    } else if( _IsTargetModel( FLAT_MODEL ) &&
               !SegmentFloats( *op1 ) && !SegmentFloats( *op2 ) ) {
        load_op1 = MakeUnary( OP_LA, *op2, AllocRegName( DI ), WD );
        PrefixIns( ins, load_op1 );
        load_op2 = MakeUnary( OP_LA, *op1, AllocRegName( SI ), WD );
        PrefixIns( ins, load_op2 );
        ds_needs_save = es_needs_save = FALSE;
    } else {
        load_op1 = MakeUnary( OP_LA, *op2, AllocRegName( ES_DI ), LP );
        PrefixIns( ins, load_op1 );
        load_op2 = MakeUnary( OP_LA, *op1, AllocRegName( DS_SI ), LP );
        PrefixIns( ins, load_op2 );
        ds_needs_save = SegmentFloats( *op1 );
        es_needs_save = SegmentFloats( *op2 );
    }
    if( _IsntTargetModel( FLOATING_DS ) && ds_needs_save ) { /* restore DS*/
        ds_reg = AllocRegName( HW_DS );
        pop = MakeUnary( OP_POP, NULL, ds_reg, U2 );
        pop->num_operands = 0;
        SuffixIns( ins, pop );
        PrefixIns( load_op2, MakeUnary( OP_PUSH, ds_reg, NULL, U2 ) );
    }
    if( _IsntTargetModel( FLOATING_ES ) && es_needs_save ) { /* restore ES */
        es_reg = AllocRegName( HW_ES );
        pop = MakeUnary( OP_POP, NULL, es_reg, U2 );
        pop->num_operands = 0;
        SuffixIns( ins, pop );
        PrefixIns( load_op1, MakeUnary( OP_PUSH, es_reg, NULL, U2 ) );
        load_op1 = load_op1->head.prev;
    }
    HW_CTurnOn( new_op1, hw( DS_SI ) );
    HW_CTurnOn( new_op1, hw( ES_DI ) );
    ins->table = String;
    ins->head.state = INS_NEEDS_WORK;
    *op1 = FakeIndex( ins->operands[0], new_op1 );
    ins->operands[ 1 ] = ins->operands[ 0 ];
    HW_CTurnOff( new_op1, HW_SS );
    HW_CTurnOff( new_op1, HW_SP );
    HW_CTurnOff( new_op1, HW_ES );
    HW_CTurnOff( new_op1, HW_DS );
    ins->zap = &AllocRegName( new_op1 )->r;
    if( ins->head.opcode == OP_MOV ) {
        ins->result = FakeIndex( ins->result, ES_DI );
    } else {
        ins->result = NULL;
    }
    if( load_len != NULL ) {
        first_ins = load_len;
    } else {
        first_ins = load_op1;
    }
    UpdateLive( first_ins, ins );
    return( first_ins );
}


extern instruction      *rMAKESTRCMP( instruction *ins ) {
/*******************************************************/

    return( LoadStringOps( ins, &ins->operands[ 0 ], &ins->operands[ 1 ] ) );
}


extern instruction      *rMAKESTRMOVE( instruction *ins ) {
/********************************************************/

    return( LoadStringOps( ins, &ins->operands[ 0 ], &ins->result ) );
}


extern instruction      *rMAYBSTRMOVE( instruction *ins ) {
/********************************************************/

    if( CanLoadStringOps( ins ) ) {
        return( LoadStringOps( ins, &ins->operands[ 0 ], &ins->result ) );
    } else {
        return( rSPLIT8( ins ) );
    }
}


extern instruction      *rEXT_PUSHC( instruction *ins ) {
/******************************************************/

    CnvOpToInt( ins, 0 );
    ChangeType( ins, WD );
    return( ins );
}


extern instruction      *rMOVELOW( instruction *ins ) {
/****************************************************/


/* e.g. convert U2==>U1*/
    ins->head.opcode = OP_MOV;
    ins->operands[ 0 ] = LowPart( ins->operands[ 0 ], ins->type_class );
    ins->table = NULL;
    return( ins );
}


extern instruction      *rSPLITUNARY( instruction *ins ) {
/*******************************************************/

    instruction         *new_ins;

    CnvOpToInt( ins, 0 );
    new_ins = SplitUnary( ins );
    return( new_ins );
}


extern instruction      *rMOVRESMEM( instruction *ins ) {
/******************************************************/

    instruction         *new_ins;
    name                *name_flt;
    name                *name_int;
    type_class_def      class;

    class = ins->type_class;
    name_flt = AllocTemp( class );
    if( class == FD || class == FL ) {
        name_int = name_flt;
    } else {
        name_int = TempOffset( name_flt, 0, U4 );
    }
    name_flt->v.usage |= USE_MEMORY | NEEDS_MEMORY;
    new_ins = MakeMove( name_int, ins->result, name_int->n.name_class);
    ins->result = name_flt;
    MoveSegRes( ins, new_ins );
    SuffixIns( ins, new_ins );
    return( ins );
}


extern instruction      *rMOVOP1MEM( instruction *ins ) {
/******************************************************/

    instruction         *new_ins;
    name                *name_flt;
    name                *name_int;
    type_class_def      class;

    class = ins->type_class;
    name_flt = AllocTemp( class );
    if( class == FD || class == FL ) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?