コード例 #1
0
ファイル: x86call.c プロジェクト: ArmstrongJ/open-watcom-v2
name    *StReturn( an retval, type_def *tipe, instruction **pins )
/****************************************************************/
{
    name        *retp;
    name        *ptr;
    name        *off;
    name        *seg;
    hw_reg_set  reg;

    if( CurrProc->state.attr & ROUTINE_ALLOCS_RETURN ) {
        retp = CurrProc->targ.return_points;
        AddIns( MakeUnary( OP_LA, retp, AllocRegName( CurrProc->state.return_reg ), WD ) );
        *pins = NULL;
    } else {
        if( _IsTargetModel( FLOATING_SS ) || _IsTargetModel( FLOATING_DS ) ) {
            ptr = AllocTemp( CP );
            off = OffsetPart( ptr );
            seg = SegmentPart( ptr );
            AddIns( MakeMove( AllocRegName( HW_SS ), seg, U2 ) );
        } else {
            ptr = AllocTemp( WD );
            off = ptr;
        }
        AddIns( MakeMove( CurrProc->targ.return_points, off, WD ) );
        retp = SAllocIndex( ptr, NULL, 0, TypeClass( retval->tipe ), tipe->length );
        reg = ReturnReg( WD, false );
        *pins = MakeMove( CurrProc->targ.return_points, AllocRegName( reg ), WD );
        CurrProc->state.return_reg = reg;
    }
    return( retp );
}
コード例 #2
0
ファイル: 386score.c プロジェクト: ArmstrongJ/open-watcom-v2
void    AddRegs( void )
/******************************
    Add some registers to the N_REGISTER list, so that we can do
    scoreboarding on them
*/
{
    AllocRegName( HW_DS );
    AllocRegName( HW_ES );
    AllocRegName( HW_SS );
}
コード例 #3
0
ファイル: mpscall.c プロジェクト: ABratovic/open-watcom-v2
extern an BGCall( cn call, bool use_return, bool in_line )
/********************************************************/
{
    instruction         *call_ins;
    instruction         *conv_ins;
    call_state          *state;
    name                *result;
    hw_reg_set          ret_addr;
    instruction         *ins;


    call_ins = call->ins;
    state = call->state;

    if( state->attr & ROUTINE_MODIFIES_NO_MEMORY ) {
        call_ins->flags.call_flags |= CALL_WRITES_NO_MEMORY;
    }
    if( state->attr & ROUTINE_READS_NO_MEMORY ) {
        call_ins->flags.call_flags |= CALL_READS_NO_MEMORY;
    }
    if( state->attr & ROUTINE_IS_SETJMP ) {
        call_ins->flags.call_flags |= CALL_IS_SETJMP;
    }
    if( use_return == FALSE ) {
        call_ins->flags.call_flags |= CALL_IGNORES_RETURN;
    }

    result = BGNewTemp( call->tipe );
    if( call_ins->type_class == XX ) {
        call_ins->result = result;
        ret_addr = ParmReg( CP, 4, 8, state );
        ins = MakeUnary( OP_LA, result, AllocRegName( ret_addr ), CP );
        AddIns( ins );
    } else {
        call_ins->result = AllocRegName( state->return_reg );
    }
    AssgnParms( call, in_line );
    AddCallIns( call_ins, call );
    if( use_return ) {
        if( call_ins->type_class != XX ) {
            conv_ins = MakeConvert( call_ins->result, result, TypeClass( call->tipe ), ReturnClass( call->tipe, call->state->attr ) );
            AddIns( conv_ins );
        } else {
            // conv_ins = MakeMove( call_result, result, XX );
        }
    }
    return( MakeTempAddr( result ) );
}
コード例 #4
0
void    ScInitRegs( score *sc )
/**************************************
    Add some register equality "truths" to the scoreboard "sc"
*/
{
    int     ss;
    int     ds;

    if( _IsntTargetModel( FLOATING_DS | FLOATING_SS ) ) {
        ss = AllocRegName(HW_SS)->r.reg_index;
        ds = AllocRegName(HW_DS)->r.reg_index;
        if( RegsEqual( sc, ss, ds ) == false ) {
            RegInsert( sc, ss, ds );
        }
    }
}
コード例 #5
0
ファイル: mpscall.c プロジェクト: ABratovic/open-watcom-v2
extern void BGProcDecl( cg_sym_handle sym, type_def *tipe )
/******************************************************/
{
    type_class_def      class;
    name                *temp;
    hw_reg_set          reg;

    class = AddCallBlock( sym, tipe );
    SaveTargetModel = TargetModel;
    if( tipe != TypeNone ) {
        if( class == XX ) {
            // Handle structure returns - we need to "eat up" the first
            // register used for argument passing here, so that it isn't
            // used for passing actual arguments. NB: Must also bump
            // parm.offset here so that arguments end up in the right
            // locations.
            reg = HW_D4;
            temp = AllocTemp( WD );
            temp->v.usage |= USE_IN_ANOTHER_BLOCK;
            AddIns( MakeMove( AllocRegName( reg ), temp, WD ) );
            HW_TurnOn( CurrProc->state.parm.used, reg );
// TODO: need to do anything here?
//            HW_CTurnOn( CurrProc->state.parm.used, HW_F16 );
            CurrProc->targ.return_points = temp;
            CurrProc->state.parm.offset += REG_SIZE;
        }
    }
}
コード例 #6
0
ファイル: display.c プロジェクト: XVilka/owp4v1copy
extern  bool    AskIsFrameIndex( name *op ) {
/*********************************************/

    name        *bp;

    bp = AllocRegName( DisplayReg() );
    return( op == AllocIndex( bp, NULL, -1, bp->n.name_class ) );
}
コード例 #7
0
ファイル: display.c プロジェクト: XVilka/owp4v1copy
extern  void    SaveDisplay( opcode_defs op ) {
/*********************************************/

    name        *reg;

    reg = AllocRegName( DisplayReg() );
    AddIns( MakeUnary( op, reg, NULL, reg->n.name_class ) );
}
コード例 #8
0
ファイル: display.c プロジェクト: XVilka/owp4v1copy
static  name    *DisplayField( int level )
/****************************************/
{
    name        *reg;

    reg = AllocRegName( DisplayReg() );
    return( AllocIndex( reg, NULL, (-2) * level, reg->n.name_class ) );
}
コード例 #9
0
static  void    AddSegOverride( instruction *ins, hw_reg_set reg )
/****************************************************************/
{
    name                *reg_name;

    reg_name = AllocRegName( reg );
    ins->operands[ ins->num_operands++ ] = reg_name;
}
コード例 #10
0
void    AddRegs( void )
/******************************
    Add some registers to the N_REGISTER list, so that we can do
    scoreboarding on them
*/
{
    hw_reg_set  lo_part;
    name        *reg_name;
    int         i;
    int         j;

    DS = AllocRegName( HW_DS );
    SS = AllocRegName( HW_SS );
    /*      89-01-03*/
    ES = AllocRegName( HW_ES );
    for( i = S_MAX; i-- > 0; ) {
        for( j = I_MAX; j-- > 0; ) {
            PtrRegs[i][j] = NULL;
        }
    }
    for( reg_name = Names[N_REGISTER]; reg_name != NULL; reg_name = reg_name->n.next_name ) {
        if( IsIndexReg( reg_name->r.reg, CP, false ) ) {
            if( HW_COvlap( reg_name->r.reg, HW_DS )
                    || HW_COvlap( reg_name->r.reg, HW_ES )
                    || HW_COvlap( reg_name->r.reg, HW_SS ) ) {
                lo_part = LowReg( reg_name->r.reg );
                if( HW_COvlap( lo_part, HW_BX ) ) {
                    PtrRegs[S_DS][I_BX] = NewRegName( HW_DS_BX );
                    PtrRegs[S_SS][I_BX] = NewRegName( HW_SS_BX );
                    PtrRegs[S_ES][I_BX] = NewRegName( HW_ES_BX );
                } else if( HW_COvlap( lo_part, HW_SI ) ) {
                    PtrRegs[S_DS][I_SI] = NewRegName( HW_DS_SI );
                    PtrRegs[S_SS][I_SI] = NewRegName( HW_SS_SI );
                    PtrRegs[S_ES][I_SI] = NewRegName( HW_ES_SI );
                } else if( HW_COvlap( lo_part, HW_DI ) ) {
                    PtrRegs[S_DS][I_DI] = NewRegName( HW_DS_DI );
                    PtrRegs[S_SS][I_DI] = NewRegName( HW_SS_DI );
                    PtrRegs[S_ES][I_DI] = NewRegName( HW_ES_DI );
                }
            }
        }
    }
    /*      89-01-03*/
}
コード例 #11
0
ファイル: display.c プロジェクト: XVilka/owp4v1copy
extern  void    SetDisplay( name *temp ) {
/****************************************/

    name        *reg;

    reg = AllocRegName( DisplayReg() );
    AddIns( MakeMove( TempOffset( temp, TypePtr->length,
                                  reg->n.name_class ),
                      reg, reg->n.name_class ) );
}
コード例 #12
0
ファイル: display.c プロジェクト: XVilka/owp4v1copy
extern  void    BigGoto( int level )
/**********************************/
{
    name        *reg;

    if( level != 0 ) {
        reg = AllocRegName( DisplayReg() );
        AddIns( MakeMove( DisplayField( level ), reg, reg->n.name_class ) );
    }
}
コード例 #13
0
ファイル: split.c プロジェクト: joncampbell123/open-watcom-v2
instruction      *rOP1RESREG( instruction *ins )
/**********************************************/
{
    instruction         *new_ins;
    instruction         *ins2;
    name                *name1;
    name                *name2;

    name1 = AllocRegName( Op1Reg( ins ) );
    new_ins = MakeMove( ins->operands[0], name1, _OpClass( ins ) );
    ins->operands[0] = name1;
    MoveSegOp( ins, new_ins, 0 );
    PrefixIns( ins, new_ins );
    name2 = AllocRegName( ResultReg( ins ) );
    ins2 = MakeMove( name2, ins->result, ins->type_class );
    ins->result = name2;
    MoveSegRes( ins, ins2 );
    SuffixIns( ins, ins2 );
    return( new_ins );
}
コード例 #14
0
ファイル: display.c プロジェクト: XVilka/owp4v1copy
extern  void    BigLabel( void )
/******************************/
{
    instruction *ins;
    name        *bp;
    name        *sp;

    if( CurrProc->lex_level != 0 ) {
        bp = AllocRegName( DisplayReg() );
        sp = AllocRegName( StackReg() );
        ins = MakeUnary( OP_LA,
                          AllocIndex( bp, NULL, -1, bp->n.name_class ),
                          sp, sp->n.name_class );
    } else {
        ins = MakeNop();
    }
    ins->zap = (register_name *) AllocRegName( AllCacheRegs() );
    ins->flags.nop_flags |= NOP_ZAP_INFO;
    AddIns( ins );
}
コード例 #15
0
static  name    *NewRegName( hw_reg_set reg )
/********************************************
    Allocate a new "far pointer" register an set its class
*/
{
    name        *reg_name;

    reg_name = AllocRegName( reg );
    reg_name->n.name_class = CP;
    return( reg_name );
}
コード例 #16
0
ファイル: display.c プロジェクト: XVilka/owp4v1copy
extern  name    *MakeDisplay( name *op, int level )
/*************************************************/
{
    name        *temp;
    name        *reg;

    reg = AllocRegName( DisplayReg() );
    temp = AllocTemp( U2 );
    AddIns( MakeMove( DisplayField( level ), temp, reg->n.name_class ) );
    op = AllocIndex( temp, NULL, op->t.location, op->n.name_class );
    return( op );
}
コード例 #17
0
static  void    DropCall( instruction *ins, name *temp )
/******************************************************/
{
    name                *eax_name;
    name                *null_name;
    instruction         *new_ins;

    null_name = AllocRegName( HW_EMPTY );
    eax_name = AllocRegName( HW_EAX );
    new_ins = NewIns( 3 );
    new_ins->head.opcode = OP_CALL;
    new_ins->type_class = WD;
    new_ins->operands[ CALL_OP_USED ] = null_name;
    new_ins->operands[ CALL_OP_USED2 ] = null_name;
    new_ins->operands[ CALL_OP_ADDR ]= RTMemRef( RT_TLS_REGION );
    new_ins->result = eax_name;
    new_ins->zap = &eax_name->r;
    new_ins->num_operands = 2;         /* special case for OP_CALL*/
    PrefixIns( ins, new_ins );
    new_ins = MakeMove( eax_name, temp, WD );
    PrefixIns( ins, new_ins );
}
コード例 #18
0
ファイル: 386score.c プロジェクト: ArmstrongJ/open-watcom-v2
void    ScInitRegs( score *scoreboard )
/**************************************
    Add some register equality "truths" to the scoreboard "sc"
*/
{
    int xs;
    int ds;

    ds = AllocRegName( HW_DS )->r.reg_index;
    if( _IsntTargetModel( FLOATING_DS ) ) {
        if( _IsntTargetModel( FLOATING_ES ) ) {
            xs = AllocRegName( HW_ES )->r.reg_index;
            if( !RegsEqual( scoreboard, xs, ds ) ) {
                RegInsert( scoreboard, xs, ds );
            }
        }
        if( _IsntTargetModel( FLOATING_SS ) ) {
            xs = AllocRegName( HW_SS )->r.reg_index;
            if( !RegsEqual( scoreboard, xs, ds ) ) {
                RegInsert( scoreboard, xs, ds );
            }
        }
    }
}
コード例 #19
0
ファイル: s37temps.c プロジェクト: ABratovic/open-watcom-v2
static  void    CheckOp( name **offsets, instruction *ins, name **pop ) {
/************************************************************************
    used by FixFarLocalRefs to change one far local reference to
    an index, using the appropriate multiple of 4K constant to get
    at the temporary. The constant values are adjusted after the
    prolog is generated.
*/

    name        *op;
    name        *base;
    name        *temp;
    unsigned_32 place;
    int         i;
    instruction *new_ins;

    op = *pop;
    if( op->n.class == N_INDEXED ) {
        temp = op->i.index;
        if( temp->n.class != N_TEMP ) return;
        if( !( temp->t.temp_flags & FAR_LOCAL ) ) return;
        new_ins = MakeMove( temp, AllocTemp( temp->n.name_class ), temp->n.name_class );
        *pop = ScaleIndex( new_ins->result, op->i.base,
                          op->i.constant, op->n.class, op->n.size,
                          op->i.scale, op->i.index_flags );
        PrefixIns( ins, new_ins );
        CheckOp( offsets, new_ins, &new_ins->operands[ 0 ] );
    }
    if( op->n.class != N_TEMP ) return;
    if( !( op->t.temp_flags & FAR_LOCAL ) ) return;
    base = DeAlias( op );
    place = base->t.location + ( op->v.offset - base->v.offset );
    i = place/_4K;
    if( offsets[ i ] == NULL ) {
        /*set the symbol field in the AddrConst to non-NULL for score-boarder*/
        new_ins = MakeMove( AllocAddrConst( (name *)&CurrProc, i,
                                            CONS_OFFSET, WD ),
                        AllocTemp( WD ), WD );
        offsets[ i ] = new_ins->result;
        PrefixIns( HeadBlock->ins.hd.next, new_ins );
    }
    temp = AllocTemp( WD ),
    new_ins = MakeMove( offsets[ i ], temp, WD );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_ADD, temp, AllocRegName( DisplayReg() ), temp, WD);
    PrefixIns( ins, new_ins );
    *pop = ScaleIndex( temp, op, place%_4K,
                        op->n.name_class, op->n.size, 0, X_FAKE_BASE );
}
コード例 #20
0
ファイル: display.c プロジェクト: XVilka/owp4v1copy
extern  an      PassProcParm( an rtn ) {
/**************************************/

    name        *op;
    name        *reg;

    op = AllocTemp( XX );
    op->n.size = TypePtr->length + SizeDisplayReg();
    reg = AllocRegName( DisplayReg() );
    AddIns( MakeMove( GenIns( rtn ),
            TempOffset( op, 0, ClassPointer ),
            ClassPointer ) );
    AddIns( MakeMove( reg, TempOffset( op, TypePtr->length,
                                       reg->n.name_class ),
                      reg->n.name_class ) );
    return( AddrName( op, TypeProcParm ) );
}
コード例 #21
0
ファイル: x86call.c プロジェクト: ArmstrongJ/open-watcom-v2
static  void    AddCall( instruction *ins, cn call ) {
/****************************************************/

    name        *proc_name;

    if( _IsTargetModel(FLOATING_DS) && (call->state->attr&ROUTINE_NEEDS_DS_LOADED) ) {
        AddIns( MakeMove( NearSegment(), AllocRegName( HW_DS ), U2 ) );
    }
    if( call->name->tipe == TypeProcParm ) {
        proc_name = AllocTemp( ClassPointer );
/* what to do?        proc_name->usage |= USE_REGISTER;*/
        AddIns( MakeMove( ins->operands[CALL_OP_ADDR], proc_name, ClassPointer ));
        ins->operands[CALL_OP_ADDR] = proc_name;
        SetDisplay( GenIns( call->name ) );
        AddIns( ins );
        SaveDisplay( OP_POP );
    } else {
        AddCallIns( ins, call );
    }
}
コード例 #22
0
void    BGProcDecl( cg_sym_handle sym, type_def *tipe )
/*****************************************************/
{
    type_class_def      class;
    name                *temp;
    hw_reg_set          reg;

    class = AddCallBlock( sym, tipe );
    SaveTargetModel = TargetModel;
    if( tipe != TypeNone ) {
        if( class == XX ) {
            reg = HW_D3;
            temp = AllocTemp( WD );
            temp->v.usage |= USE_IN_ANOTHER_BLOCK;
            AddIns( MakeMove( AllocRegName( reg ), temp, WD ) );
            HW_TurnOn( CurrProc->state.parm.used, reg );
            CurrProc->targ.return_points = temp;
        }
    }
}
コード例 #23
0
ファイル: x86call.c プロジェクト: ArmstrongJ/open-watcom-v2
void    BGProcDecl( cg_sym_handle sym, type_def *tipe )
/*****************************************************/
{
    hw_reg_set          reg;
    name                *temp;
    type_class_def      type_class;
    segment_id          old_segid;
    label_handle        lbl;

    SaveTargetModel = TargetModel;
    type_class = AddCallBlock( sym, tipe );
    if( tipe != TypeNone ) {
        if( type_class == XX ) {
            if( CurrProc->state.attr & ROUTINE_ALLOCS_RETURN ) {
                old_segid = SetOP( AskBackSeg() );
                lbl = AskForNewLabel();
                DataLabel( lbl );
                DGUBytes( tipe->length );
                CurrProc->targ.return_points = (name *)SAllocMemory( lbl, 0, CG_LBL, TypeClass( tipe ), tipe->length );
                SetOP( old_segid );
            } else {
                reg = CurrProc->state.return_reg;
                if( HW_CEqual( reg, HW_EMPTY ) ) {
                    temp = DoParmDecl( NULL, TypeInteger, HW_EMPTY );
                } else {
                    temp = AllocTemp( WD );
                    temp->v.usage |= USE_IN_ANOTHER_BLOCK;
                    AddIns( MakeMove( AllocRegName( reg ), temp, WD ) );
                    HW_TurnOn( CurrProc->state.parm.used, reg );
                }
                CurrProc->targ.return_points = temp;
            }
        }
    }
    if( CurrProc->state.attr & ROUTINE_FARSS ) {
        TargetModel |= FLOATING_SS;
    }
}
コード例 #24
0
ファイル: 386opseg.c プロジェクト: ArmstrongJ/open-watcom-v2
*/
{
    name        *op;
    i_flags     flags;
    name        *index;
    hw_reg_set  tmp;

    op = *pop;
    if( op->n.class == N_MEMORY && !SegIsCS( op ) ) {
        *pop = SAllocIndex( gblreg, op, op->v.offset, op->n.type_class, op->n.size );
    } else if( op->n.class == N_INDEXED ) {
        if( op->i.base != NULL && op->i.base->n.class == N_MEMORY &&
            !SegIsCS( op->i.base ) ) {
            tmp =  gblreg->r.reg;
            HW_TurnOn( tmp, op->i.index->r.reg );
            index = AllocRegName( tmp );
            tmp = High64Reg( index->r.reg );
            if( HW_Equal( tmp, gblreg->r.reg ) ) {
                flags = X_HIGH_BASE;
            } else {
                flags = X_LOW_BASE;
            }
            *pop = ScaleIndex( index, op->i.base, op->i.constant,
            op->n.type_class, op->n.size, op->i.scale, op->i.index_flags|flags);
        }
    }
}


static  void    AddGlobalIndex( void )
/*************************************
コード例 #25
0
ファイル: rtcall.c プロジェクト: ArmstrongJ/open-watcom-v2
instruction     *rMAKECALL( instruction *ins )
/*********************************************
    Using the table RTInfo[], do all the necessary stuff to turn
    instruction "ins" into a call to a runtime support routine.  Move
    the parms into registers, and move the return register of the
    runtime routine into the result. Used for 386 and 370 versions
*/
{
    rtn_info            *info;
    label_handle        lbl;
    instruction         *left_ins;
    instruction         *new_ins;
    instruction         *last_ins;
    name                *reg_name;
    hw_reg_set          regs;
    hw_reg_set          all_regs;
    hw_reg_set          tmp;
    rt_class            rtindex;

    if( !_IsConvert( ins ) ) {
        rtindex = LookupRoutine( ins );
    } else { /* look it up again in case we ran out of memory during expansion*/
        rtindex = LookupConvertRoutine( ins );
    }
    info = &RTInfo[rtindex];
    regs = _ParmReg( info->left );
    all_regs = regs;
    left_ins = MakeMove( ins->operands[0], AllocRegName( regs ),
                          info->operand_class );
    ins->operands[0] = left_ins->result;
    MoveSegOp( ins, left_ins, 0 );
    PrefixIns( ins, left_ins );
    regs = _ParmReg( info->right );
    if( !HW_CEqual( regs, HW_EMPTY ) ) {
        new_ins = MakeMove( ins->operands[1], AllocRegName( regs ),
                                info->operand_class );
        ins->operands[1] = new_ins->result;
        MoveSegOp( ins, new_ins, 0 );
        HW_TurnOn( all_regs, regs );
        PrefixIns( ins, new_ins );
    }
#if _TARGET & _TARG_370
    tmp = RAReg();
    HW_TurnOn( all_regs, tmp );
    tmp = LNReg();
    HW_TurnOn( all_regs, tmp );
#elif _TARGET & _TARG_80386
    {
    tmp = ReturnReg( WD, false );
    HW_TurnOn( all_regs, tmp );
    }
#endif
    reg_name = AllocRegName( all_regs );
    lbl = RTLabel( rtindex );
    new_ins = NewIns( 3 );
    new_ins->head.opcode = OP_CALL;
    new_ins->type_class = ins->type_class;
    new_ins->operands[CALL_OP_USED] = reg_name;
    new_ins->operands[CALL_OP_USED2] = reg_name;
    new_ins->operands[CALL_OP_ADDR] = AllocMemory( lbl, 0, CG_LBL, ins->type_class );
    new_ins->result = NULL;
    new_ins->num_operands = 2;         /* special case for OP_CALL*/
#if _TARGET & _TARG_AXP
    {
    HW_CTurnOn( all_regs, HW_FULL );
    HW_TurnOff( all_regs, SavedRegs() );
    HW_CTurnOff( all_regs, HW_UNUSED );
    HW_TurnOn( all_regs, ReturnAddrReg() );
    }
#endif
    new_ins->zap = (register_name *)AllocRegName( all_regs );   /* all parm regs could be zapped*/
    last_ins = new_ins;
    if( ins->result == NULL || _OpIsCondition( ins->head.opcode ) ) {
        /* comparison, still need conditional jumps*/
        ins->operands[0] = AllocIntConst( 0 );
        ins->operands[1] = AllocIntConst( 1 );
        DelSeg( ins );
        DoNothing( ins );               /* just conditional jumps for ins*/
        PrefixIns( ins, new_ins );
        new_ins->ins_flags |= INS_CC_USED;
        last_ins = ins;
    } else {
        regs = _ParmReg( info->result );
        tmp = regs;
        HW_TurnOn( tmp, new_ins->zap->reg );
        new_ins->zap = (register_name *)AllocRegName( tmp );
        reg_name = AllocRegName( regs );
        new_ins->result = reg_name;
        last_ins = MakeMove( reg_name, ins->result, ins->type_class );
        ins->result = last_ins->operands[0];
        MoveSegRes( ins, last_ins );
        SuffixIns( ins, last_ins );
        ReplIns( ins, new_ins );
    }
    FixCallIns( new_ins );
    UpdateLive( left_ins, last_ins );
    return( left_ins );
}
コード例 #26
0
void    ScoreCalcList( void )
/***************************/
{
    score_reg   *curr;
    name        *reg_name;
    int         i;
    hw_reg_set  reg;

    ScoreCount = 0;
    AddRegs();
    for( reg_name = Names[N_REGISTER]; reg_name != NULL; reg_name = reg_name->n.next_name ) {
        if( ScRealRegister( reg_name ) ) {
            reg = HighOffsetReg( reg_name->r.reg );
            if( !HW_CEqual( reg, HW_EMPTY ) ) {
                AllocRegName( reg );
            }
            reg = LowOffsetReg( reg_name->r.reg );
            if( !HW_CEqual( reg, HW_EMPTY ) ) {
                AllocRegName( reg );
            }
        }
    }
    for( reg_name = Names[N_REGISTER]; reg_name != NULL; reg_name = reg_name->n.next_name ) {
        if( ScRealRegister( reg_name ) ) {
            ++ScoreCount;
        }
    }
    if( ScoreCount != 0 ) {
        ScoreList = ScAlloc( ScoreCount * ( sizeof( pointer ) + sizeof( score_reg ) ) );
        curr = (score_reg *)&ScoreList[ScoreCount];
        i = 0;
        for( reg_name = Names[N_REGISTER]; reg_name != NULL; reg_name = reg_name->n.next_name ) {
            if( ScRealRegister( reg_name ) ) {
                curr->reg_name = reg_name;
                curr->reg = reg_name->r.reg;
                curr->type_class = reg_name->n.type_class;
                curr->size  = reg_name->n.size;
                curr->high_of = NO_INDEX;
                curr->low_of = NO_INDEX;
                reg_name->r.reg_index = i;
                ScoreList[i] = curr; /*% This avoids MANY multiplies!*/
                ++curr;
                ++i;
            }
        }
        i = ScoreCount;
        while( curr != ScoreList[0] ) {
            --curr;
            --i;
            reg = HighOffsetReg( curr->reg );
            if( !HW_CEqual( reg, HW_EMPTY ) ) {
                reg_name = AllocRegName( reg );
                if( !ScRealRegister( reg_name )
                 || reg_name->r.reg_index == NO_INDEX ) {
                    curr->high = NO_INDEX;
                } else {
                    curr->high = reg_name->r.reg_index;
                    ScoreList[curr->high]->high_of = i;
                }
            } else {
                curr->high = NO_INDEX;
            }
            reg = LowOffsetReg( curr->reg );
            if( !HW_CEqual( reg, HW_EMPTY ) ) {
                reg_name = AllocRegName( reg );
                if( !ScRealRegister( reg_name )
                 || reg_name->r.reg_index == NO_INDEX ) {
                    curr->low = NO_INDEX;
                } else {
                    curr->low = reg_name->r.reg_index;
                    ScoreList[curr->low]->low_of = i;
                }
            } else {
                curr->low = NO_INDEX;
            }
        }
    }
}
コード例 #27
0
ファイル: flowsave.c プロジェクト: Azarien/open-watcom-v2
void FlowSave( hw_reg_set *preg )
/*******************************/
{
    int                 score;
    int                 i, j;
    int                 best;
    int                 num_blocks;
    int                 num_regs;
    int                 curr_reg;
    hw_reg_set          *curr_push;
    reg_flow_info       *reg_info;
    block               *save;
    block               *restore;
    instruction         *ins;
    type_class_def      reg_type;

    HW_CAsgn( flowedRegs, HW_EMPTY );
    if( _IsntModel( FLOW_REG_SAVES ) ) return;
    if( !HaveDominatorInfo ) return;
    // we can't do this if we have push's which are 'live' at the end of a block
    // - this flag is set when we see a push being generated for a call in a different
    //   block
#if _TARGET & _TARG_INTEL
    if( CurrProc->targ.never_sp_frame ) return;
#endif
    num_regs = CountRegs( *preg );
    if( num_regs == 0 ) return;
    reg_info = CGAlloc( num_regs * sizeof( reg_flow_info ) );
    num_blocks = CountBlocks();
    InitBlockArray();
    curr_push = PushRegs;
    for( curr_reg = 0; curr_reg < num_regs; curr_reg++ ) {
        while( !HW_Ovlap( *curr_push, *preg ) ) curr_push++;
        HW_Asgn( reg_info[curr_reg].reg, *curr_push );
        reg_info[curr_reg].save = NULL;
        reg_info[curr_reg].restore = NULL;
    #if _TARGET & _TARG_INTEL
        if( HW_COvlap( *curr_push, HW_BP ) ) continue;  // don't mess with BP - it's magical
    #endif
        GetRegUsage( &reg_info[curr_reg] );
        best = 0;
        for( i = 0; i < num_blocks; i++ ) {
            for( j = 0; j < num_blocks; j++ ) {
                if( PairOk( blockArray[i], blockArray[j], &reg_info[0], curr_reg ) ) {
                    // we use the number of blocks dominated by the save block plus
                    // the number of blocks post-dominated by the restore block as a
                    // rough metric for determining how much we like a given (valid)
                    // pair of blocks - the more blocks dominated, the further 'in'
                    // we have pushed the save, which should be good
                    score =  CountDomBits( &blockArray[i]->dom.dominator );
                    score += CountDomBits( &blockArray[j]->dom.post_dominator );
                    if( score > best ) {
                        best = score;
                        reg_info[curr_reg].save    = blockArray[i];
                        reg_info[curr_reg].restore = blockArray[j];
                    }
                }
            }
        }
        // so now we know where we are going to save and restore the register
        // emit the instructions to do so, and remove reg from the set to push
        // in the normal prolog sequence
        save = reg_info[curr_reg].save;
        restore = reg_info[curr_reg].restore;
        if( ( save != NULL && save != HeadBlock ) && ( restore != NULL && !_IsBlkAttr( restore, BLK_RETURN ) ) ) {
            reg_type = WD;
        #if _TARGET & _TARG_INTEL
            if( IsSegReg( reg_info[curr_reg].reg ) ) {
                reg_type = U2;
            }
        #endif
            ins = MakeUnary( OP_PUSH, AllocRegName( reg_info[curr_reg].reg ), NULL, reg_type );
            ResetGenEntry( ins );
            PrefixIns( save->ins.hd.next, ins );
            ins = MakeUnary( OP_POP, NULL, AllocRegName( reg_info[curr_reg].reg ), reg_type );
            ins->num_operands = 0;
            ResetGenEntry( ins );
            SuffixIns( restore->ins.hd.prev, ins );
            HW_TurnOff( *preg, reg_info[curr_reg].reg );
            HW_TurnOn( flowedRegs, reg_info[curr_reg].reg );
            FixStackDepth( save, restore );
        }
        curr_push++;
    }
    CGFree( reg_info );
}
コード例 #28
0
ファイル: x86call.c プロジェクト: ArmstrongJ/open-watcom-v2
an      BGCall( cn call, bool use_return, bool in_line )
/******************************************************/
{
    instruction         *call_ins;
    call_state          *state;
    name                *ret_ptr = NULL;
    name                *result;
    name                *temp;
    name                *reg_name;
    instruction         *ret_ins = NULL;
    hw_reg_set          return_reg;
    hw_reg_set          zap_reg;

    if( call->name->tipe == TypeProcParm ) {
        SaveDisplay( OP_PUSH );
    }

    state = call->state;
    result = BGNewTemp( call->tipe );
    call_ins = call->ins;

/*   If we have a return value that won't fit in a register*/
/*   pass a pointer to result as the first parm*/

    if( call_ins->type_class == XX ) {
        if( _RoutineIsFar16( state->attr ) ) {
            if( state->attr & ROUTINE_ALLOCS_RETURN ) {
                HW_CAsgn( state->return_reg, HW_EAX );
            } else {
                HW_CAsgn( state->return_reg, HW_EBX );
            }
        }
        if( ( state->attr & ROUTINE_ALLOCS_RETURN ) == 0 ) {
            if( HW_CEqual( state->return_reg, HW_EMPTY ) ) {
                ret_ptr = AllocTemp( WD );
            } else {
                ret_ptr = AllocRegName( state->return_reg );
            }
            ret_ins = MakeUnary( OP_LA, result, ret_ptr, WD );
            HW_TurnOn( state->parm.used, state->return_reg );
            call_ins->flags.call_flags |= CALL_RETURNS_STRUCT;
        }
    }
    if( _IsTargetModel(FLOATING_DS) && (state->attr&ROUTINE_NEEDS_DS_LOADED) ) {
        HW_CTurnOn( state->parm.used, HW_DS );
    }
    if( _RoutineIsFar16( state->attr ) ) {
#if _TARGET & _TARG_80386
        Far16Parms( call );
#endif
    } else {
        if( AssgnParms( call, in_line ) ) {
            if( state->attr & ROUTINE_REMOVES_PARMS ) {
                call_ins->flags.call_flags |= CALL_POPS_PARMS;
            }
        }
    }

    if( state->attr & (ROUTINE_MODIFIES_NO_MEMORY | ROUTINE_NEVER_RETURNS) ) {
        /* a routine that never returns can not write any memory as far
            as this routine is concerned */
        call_ins->flags.call_flags |= CALL_WRITES_NO_MEMORY;
    }
    if( state->attr & ROUTINE_READS_NO_MEMORY ) {
        call_ins->flags.call_flags |= CALL_READS_NO_MEMORY;
    }
    if( state->attr & ROUTINE_NEVER_RETURNS ) {
        call_ins->flags.call_flags |= CALL_ABORTS;
    }
    if( _RoutineIsInterrupt( state->attr ) ) {
        call_ins->flags.call_flags |= CALL_INTERRUPT | CALL_POPS_PARMS;
    }
    if( !use_return ) {
        call_ins->flags.call_flags |= CALL_IGNORES_RETURN;
    }
    if( call_ins->type_class == XX ) {
        reg_name = AllocRegName( state->return_reg );
        if( state->attr & ROUTINE_ALLOCS_RETURN ) {
            call_ins->result = reg_name;
            AddCall( call_ins, call );
            if( use_return ) {
                temp = AllocTemp( WD ); /* assume near pointer*/
                AddIns( MakeMove( reg_name, temp, WD ) );
                temp = SAllocIndex( temp, NULL, 0,
                                    result->n.type_class, call->tipe->length );
                AddIns( MakeMove( temp, result, result->n.type_class ) );
            }
        } else {
            call_ins->result = result;
            AddIns( ret_ins );
            if( HW_CEqual( state->return_reg, HW_EMPTY ) ) {
                AddIns( MakeUnary( OP_PUSH, ret_ptr, NULL, WD ) );
                state->parm.offset += TypeClassSize[WD];
                call_ins->operands[CALL_OP_POPS] =
                        AllocS32Const( call_ins->operands[CALL_OP_POPS]->c.lo.int_value + TypeClassSize[WD] );
                if( state->attr & ROUTINE_REMOVES_PARMS ) {
                    call_ins->flags.call_flags |= CALL_POPS_PARMS;
                }
            }
            AddCall( call_ins, call );
        }
    } else {
        return_reg = state->return_reg;
        zap_reg = call_ins->zap->reg;
        HW_CTurnOn( zap_reg, HW_FLTS );
        HW_OnlyOn( return_reg, zap_reg );
        call_ins->result = AllocRegName( return_reg );
        reg_name = AllocRegName( state->return_reg );
        AddCall( call_ins, call );
        if( use_return ) {
            ret_ins = MakeMove( reg_name, result, result->n.type_class );
            if( HW_COvlap( reg_name->r.reg, HW_FLTS ) ) {
                ret_ins->stk_entry = 1;
                ret_ins->stk_exit = 0;
            }
            AddIns( ret_ins );
        }
    }
    if( state->parm.offset != 0 && ( state->attr & ROUTINE_REMOVES_PARMS ) == 0 ) {
        reg_name = AllocRegName( HW_SP );
        AddIns( MakeBinary( OP_ADD, reg_name,
                AllocS32Const( state->parm.offset ), reg_name, WD ) );
    }
    return( MakeTempAddr( result ) );
}
コード例 #29
0
ファイル: x86call.c プロジェクト: ArmstrongJ/open-watcom-v2
static  void    Far16Parms( cn call ) {
/*************************************/

    instruction         *ins;
    type_length         parm_size;
    pn                  parm, next;
    instruction         *call_ins;
    name                *eax;
    name                *ecx;
    name                *esi;
    label_handle        lbl;
    type_length         offset;
    name                *parmlist;
    call_state          *state;
    rt_class            rtindex;

    call_ins = call->ins;
    parm_size = 0;
    state = call->state;
    for( parm = call->parms; parm != NULL; parm = parm->next ) {
        parm_size += _RoundUp( parm->name->tipe->length, 2 );
    }
    parmlist = SAllocTemp( XX, parm_size );
    parmlist->v.usage |= NEEDS_MEMORY | USE_IN_ANOTHER_BLOCK | USE_ADDRESS;
    offset = 0;
    for( parm = call->parms; parm != NULL; parm = parm->next ) {
        parm->name->u.i.ins->result = STempOffset( parmlist, offset,
                                                 TypeClass( parm->name->tipe ),
                                                 parm->name->tipe->length );
        offset += _RoundUp( parm->name->tipe->length, 2 );
    }
    for( parm = call->parms; parm != NULL; parm = next ) {
        next = parm->next;
        parm->name->format = NF_ADDR;   /* so instruction doesn't get freed! */
        BGDone( parm->name );
        CGFree( parm );
    }
    eax = AllocRegName( HW_EAX );
    ecx = AllocRegName( HW_ECX );
    esi = AllocRegName( HW_ESI );
    HW_TurnOn( state->parm.used, eax->r.reg );
    HW_TurnOn( state->parm.used, ecx->r.reg );
    HW_TurnOn( state->parm.used, esi->r.reg );
    ins = MakeMove( AllocS32Const( parm_size ), ecx, WD );
    AddIns( ins );
    ins = MakeUnary( OP_LA, parmlist, esi, WD );
    AddIns( ins );
    if( ins->head.opcode == OP_CALL ) {
        ins = MakeUnary( OP_LA, call->name->u.n.name, eax, WD );
    } else {
        ins = MakeMove( GenIns( call->name ), eax, WD );
        call_ins->head.opcode = OP_CALL;
    }
    call_ins->num_operands = 2;
    AddIns( ins );
    if( call_ins->type_class == XX ) {
        if( state->attr & ROUTINE_ALLOCS_RETURN ) {
            rtindex = RT_Far16Cdecl;
        } else {
            rtindex = RT_Far16Pascal;
        }
    } else {
        rtindex = RT_Far16Func;
    }
    lbl = RTLabel( rtindex );
    call->name->u.n.name = AllocMemory( lbl, 0, CG_LBL, WD );
    call_ins->flags.call_flags |= CALL_FAR16 | CALL_POPS_PARMS;
    call_ins->operands[CALL_OP_USED] = AllocRegName( state->parm.used );
    call_ins->operands[CALL_OP_POPS] = AllocS32Const( 0 );
    call_ins->zap = &call_ins->operands[CALL_OP_USED]->r;
}