s37proc.c

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

C
724
字号

static void OSSaveRegs( hwins_op_any *savearea )
/**********************************************/
{
    hwins_op_any        sp_op;
    hwins_op_any        sa_op;
    hwins_op_any        hwop;
    hwins_op_any        hwop2;

    sp_op.r = CurrProc->state.regs.SP;
    GetOSSTMOps( &hwop, &hwop2, &sa_op );
    RegOffset( savearea, SA_FIRST_REG, sa_op.r );
    /*
        STM     Rx,Ry,SA_FIRST_REG(SA)          - save all regs
    */
    HWInsGen( HWOP_STM, &hwop, savearea, &hwop2 );
    SwitchBase();
    if( CurrProc->state.attr & ROUTINE_ENTRY ) {
        MakeStack( &hwop );
        /*
            L   SP,=A(STACKAREA)
        */
        HWInsGen( HWOP_L, &sp_op, &hwop, NULL );
    } else {
        if( CurrProc->state.attr & ROUTINE_FUNC ) {
            BranchAndLinkTo( RT_OSPROL );
        }
        if( NeedStackCheck() ) {
            StackCheck( RT_OSSTKCHK );
        }
    }
    RegOffset( savearea, SA_FWD_LINK, sa_op.r );
    /*
        ST   SP,SA_FWD_LINK(SA)         - link the save areas
    */
    HWInsGen( HWOP_ST, &sp_op, savearea, NULL );
    RegOffset( savearea, SA_BACK_LINK, sp_op.r );
    /*
        ST   SA,SA_BACK_LINK(SP)                - link the save areas
    */
    HWInsGen( HWOP_ST, &sa_op, savearea, NULL );
    /*
        LR   SA,SP                      - load up a new save area reg
    */
    HWInsGen( HWOP_LR, &sa_op, &sp_op, NULL );
    savearea->sx.disp = CurrProc->targ.save_area + MAX_SA_WORDS*WORD_SIZE;
    if( CurrProc->state.parm.offset != 0 ) {
        hwop.r = CurrProc->state.regs.PA;
        hwop2.r = CurrProc->state.regs.PR;
        /*
            LR  PA,PR                   - save a permanent pointer to parms
        */
        HWInsGen( HWOP_LR, &hwop, &hwop2, NULL );
    }
}


static void CLinkSaveRegs( hwins_op_any *savearea )
/*************************************************/
{
    hw_reg_set          regs;
    hw_reg_set          tmp;
    int                 first_save_reg;
    int                 last_save_reg;
    hwins_op_any        hwop;
    hwins_op_any        hwop2;

    regs = SaveRegs();
    tmp = FixedRegs();
    HW_TurnOff( regs, tmp );
    tmp = LNReg();
    HW_TurnOff( regs, tmp );
    HW_CTurnOff( regs, HW_FLTS );

    first_save_reg = CurrProc->state.regs.SP;
    if( CurrProc->state.regs.AR < first_save_reg ) {
        first_save_reg = CurrProc->state.regs.AR;
    }
    if( CurrProc->state.regs.RA < first_save_reg ) {
        first_save_reg = CurrProc->state.regs.RA;
    }
    if( CurrProc->state.regs.BR < first_save_reg ) {
        first_save_reg = CurrProc->state.regs.BR;
    }
    if( CurrProc->state.regs.PA < first_save_reg ) {
        first_save_reg = CurrProc->state.regs.PA;
    }
    if( CurrProc->state.regs.SA < first_save_reg ) {
        first_save_reg = CurrProc->state.regs.SA;
    }
    last_save_reg = first_save_reg - 1;
    if( last_save_reg < 0 ) last_save_reg = 15;
    while( last_save_reg >= 0 ) {
        if( HW_Ovlap( regs, RegNames[last_save_reg] ) ) break;
        last_save_reg--;
    }
    if( last_save_reg < 0 ) last_save_reg = 15;
    CurrProc->targ.first_save_reg = first_save_reg;
    CurrProc->targ.last_save_reg  = last_save_reg;
    hwop.r = CurrProc->targ.first_save_reg;
    RegOffset( savearea, CurrProc->targ.save_area, CurrProc->state.regs.SP );
    hwop2.r = CurrProc->targ.last_save_reg;
    /*
        STM     SP,**,SAVE_OFFSET(SP)           - save all used regs
    */
    HWInsGen( HWOP_STM, &hwop, savearea, &hwop2 );
    SwitchBase();
    if( NeedStackCheck() ) {
        StackCheck( RT_STKCHK );
    }
    savearea->sx.disp += WORD_SIZE*( ( ( last_save_reg + 1 ) & 0xF ) )
                     +  WORD_SIZE*( 16 - first_save_reg );
}


static void SaveFPRs( hwins_op_any * savearea )
/*********************************************/
{
    float_save          *flt_save;
    hw_reg_set          regs;
    hwins_op_any        fp_reg;

    regs = SaveRegs();
    HW_COnlyOn( regs, HW_FLTS );
    flt_save = FloatSave;
    while( !HW_CEqual( regs, HW_EMPTY ) ) {
        if( HW_Ovlap( regs, flt_save->reg ) ) {
            fp_reg.r = flt_save->i;
            if( HW_Subset( regs, flt_save->reg ) ) {
                HWInsGen( HWOP_STD, &fp_reg, savearea, NULL );
                savearea->sx.disp += DWORD_SIZE;
            } else {
                HWInsGen( HWOP_STE, &fp_reg, savearea, NULL );
                savearea->sx.disp += WORD_SIZE;
            }
            HW_TurnOff( regs, flt_save->reg );
        }
        ++flt_save;
    }
}


static void RestoreFPRs()
/***********************/
{
    float_save          *flt_save;
    hw_reg_set          regs;
    hwins_op_any        fp_reg;
    hwins_op_any        savearea;

    RegOffset( &savearea,
               CurrProc->targ.save_area + CurrProc->targ.flt_save_area,
               CurrProc->state.regs.AR );
    regs = SaveRegs();
    HW_COnlyOn( regs, HW_FLTS );
    flt_save = FloatSave;
    while( !HW_CEqual( flt_save->reg, HW_EMPTY ) ) {
        ++flt_save;
    }
    while( !HW_CEqual( regs, HW_EMPTY ) ) {
        --flt_save;
        if( HW_Ovlap( regs, flt_save->reg ) ) {
            fp_reg.r = flt_save->i;
            if( HW_Subset( regs, flt_save->reg ) ) {
                savearea.sx.disp -= DWORD_SIZE;
                HWInsGen( HWOP_LD, &fp_reg, &savearea, NULL );
            } else {
                savearea.sx.disp -= WORD_SIZE;
                HWInsGen( HWOP_LE, &fp_reg, &savearea, NULL );
            }
            HW_TurnOff( regs, flt_save->reg );
        }
    }
}


static void SetUpAR( hwins_op_any *savearea, bool sp_bumped )
/***********************************************************/
{
    hwins_op_any        ar_op;
    hwins_op_any        sp_op;
    hwins_op_any        hwop;
    long                savesize;

    ar_op.r = CurrProc->state.regs.AR;
    sp_op.r = CurrProc->state.regs.SP;
    savesize = savearea->sx.disp - CurrProc->targ.save_area;
    AdjustNearLocals( savesize );
    AdjustFarLocals( savearea->sx.disp+CurrProc->locals.size );
    /*
        LR      AR,SP                   - set up pointer to local vars
    */
    HWInsGen( HWOP_LR, &ar_op, &sp_op, NULL );
    if( sp_bumped ) {
        RefInt( &hwop, CurrProc->parms.size );
        /*
            S   SP,CurrProc->parms.size - bump SP back down
        */
        HWInsGen( HWOP_S, &sp_op, &hwop, NULL );
        RegOffset( &hwop,
                   ( RegPosCLink( sp_op.r, CurrProc->targ.first_save_reg ) +
                     CurrProc->targ.save_area ),
                   ar_op.r );
        /*
            ST  SP,SP_OFFSET(AR)        - save the orignal SP value
        */
        HWInsGen( HWOP_ST, &sp_op, &hwop, NULL );
        if( !( CurrProc->state.attr & ROUTINE_ALTERNATE_AR ) ) {
            /*
                LR      AR,SP                   - set up pointer to local vars
            */
            HWInsGen( HWOP_LR, &ar_op, &sp_op, NULL );
            CurrProc->targ.save_area += CurrProc->parms.size;
        }
    }
    AddTo( &sp_op, DWord( CurrProc->parms.size + CurrProc->locals.size
                        + FarLocalSize() + savesize ) );
}


static void SwitchBase()
/**********************/
{
    hwins_op_any        ln_op;
    hwins_op_any        br_op;

    ln_op.r = CurrProc->state.regs.LN;
    br_op.r = CurrProc->state.regs.BR;
    /*
        LR      BR,LN                   - set up a new base register
    */
    HWInsGen( HWOP_LR, &br_op, &ln_op, NULL ); /* set BR */
    HWDrop( ln_op.r );
    HWUsing( CurrProc->targ.using_label, br_op.r );
}


static void MakeSaveArea() {
/**********************/

    hwins_op_any        savearea;
    bool                sp_bumped;


    HWUsing( CurrProc->targ.using_label, CurrProc->state.regs.LN );
    CurrProc->targ.save_area = CurrProc->parms.size;
    if( CurrProc->state.attr & ROUTINE_OS ) {
        OSSaveRegs( &savearea );
    } else {
        sp_bumped = SkipOverParms();
        CLinkSaveRegs( &savearea );
    }
    SaveFPRs( &savearea );
    CurrProc->targ.flt_save_area = savearea.sx.disp - CurrProc->targ.save_area;
    SetUpAR( &savearea, sp_bumped );
}


static void OSRestoreRegs()
/*************************/
{
    hwins_op_any        first_reg;
    hwins_op_any        last_reg;
    hwins_op_any        sa_op;
    hwins_op_any        ln_op;
    hwins_op_any        savearea;

    GetOSSTMOps( &first_reg, &last_reg, &sa_op );
    RegOffset( &savearea, SA_BACK_LINK, sa_op.r );
    /*
        L       SA,SA_BACK_LINK(SA)             - restore ptr to original save area
    */
    HWInsGen( HWOP_L, &sa_op, &savearea, NULL );
    ln_op.r = CurrProc->state.regs.LN;
    RegOffset( &savearea, RegPosOS( ln_op.r, first_reg.r ), sa_op.r );
    /*
        ST      LN,LN_OFFSET(SA)        - save LN in original save area
    */
    HWInsGen( HWOP_ST, &ln_op, &savearea, NULL );
    if( CurrProc->state.attr & ROUTINE_FUNC ) {
        BranchAndLinkTo( RT_OSEPIL );
    }
    HWEpilogue();
    HWDrop( CurrProc->state.regs.BR );
    RegOffset( &savearea, SA_FIRST_REG, CurrProc->state.regs.SA );
    /*
        LM      Rx,Ry,SA_FIRST_REG(SA)          - restore all regs (except LN)
    */
    HWInsGen( HWOP_LM, &first_reg, &savearea, &last_reg );
}


static void CLinkRestoreRegs()
/***************************/
{
    hwins_op_any        first_reg;
    hwins_op_any        last_reg;
    hwins_op_any        savearea;

    first_reg.r = CurrProc->targ.first_save_reg;
    last_reg.r = CurrProc->targ.last_save_reg;
    RegOffset( &savearea, CurrProc->targ.save_area, CurrProc->state.regs.AR );
    HWEpilogue();
    HWDrop( CurrProc->state.regs.BR );
    /*
        LM      SP,xxx,0(AR)            - restore all regs
    */
    HWInsGen( HWOP_LM, &first_reg, &savearea, &last_reg );
}


static void DoReturn()
/********************/
{
    hwins_op_any        hwop1;
    hwins_op_any        hwop2;

    hwop1.r = 15;/* always */
    hwop2.r = CurrProc->state.regs.RA;
    /*
        BR      RA                      - return to caller
    */
    HWInsGen( HWOP_BCR, &hwop1, &hwop2, NULL );
}


extern  void    GenEpilog() {
/***************************/
    seg_id      old;

    old = SetOP( AskCodeSeg() );
    RestoreFPRs();
    if( CurrProc->state.attr & ROUTINE_OS ) {
        OSRestoreRegs();
    } else {
        CLinkRestoreRegs();
    }
    DoReturn();
    HWEndProc();
    CurrProc->prolog_state |= GENERATED_EPILOG;
    if( CurrProc->state.attr & ROUTINE_WANTS_DEBUGGING ) {
        EmitRtnEnd();
    }
    SetOP( old );
}


extern  int     AskDisplaySize( int level ) {
/*******************************************/

    level=level;
    return( 0 );
}


extern  type_length     PushSize( type_length len ) {
/*******************************************/

    if( len < WORD_SIZE ) return( WORD_SIZE );
    return( ( len + (WORD_SIZE-1) ) & ~(WORD_SIZE-1) );
}

⌨️ 快捷键说明

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