i86proc.c

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

C
1,286
字号
        + CurrProc->targ.push_local_size + StackDepth );
}


static  int PushAll( void )
/*************************/
/* Save all registers and establish somewhat sane environment.
 * Used for __interrupt routines only.
 */
{
    if( _CPULevel( CPU_186 ) ) {
        Gpusha();
    } else {
        QuickSave( HW_AX, OP_PUSH );
        QuickSave( HW_CX, OP_PUSH );
        QuickSave( HW_DX, OP_PUSH );
        QuickSave( HW_BX, OP_PUSH );
        QuickSave( HW_SP, OP_PUSH );
        QuickSave( HW_BP, OP_PUSH );
        QuickSave( HW_SI, OP_PUSH );
        QuickSave( HW_DI, OP_PUSH );
    }
        QuickSave( HW_DS, OP_PUSH );
        QuickSave( HW_ES, OP_PUSH );
    if( _CPULevel( CPU_386 ) ) {
        QuickSave( HW_FS, OP_PUSH );
        QuickSave( HW_GS, OP_PUSH );
    } else {
        QuickSave( HW_AX, OP_PUSH );
        QuickSave( HW_AX, OP_PUSH );
    }
    GenRegMove( HW_SP, HW_BP );
    AllocStack();
    Gcld();
    if( HW_COvlap( CurrProc->state.unalterable, HW_DS ) ) {
        DoLoadDS();
        // If ES is also unalterable, copy DS to ES; else things
        // like memcpy() are likely to blow up
        if( HW_COvlap( CurrProc->state.unalterable, HW_ES ) ) {
            QuickSave( HW_DS, OP_PUSH );
            QuickSave( HW_ES, OP_POP );
        }
    }
    return( ALL_REG_SIZE );
}


static  void    PopAll( void ) {
/************************/

    if( CurrProc->locals.size != 0 ) {
        GenRegMove( HW_BP, HW_SP );
    }
    if( _CPULevel( CPU_386 ) ) {
        QuickSave( HW_GS, OP_POP );
        QuickSave( HW_FS, OP_POP );
    } else {
        QuickSave( HW_AX, OP_POP );
        QuickSave( HW_AX, OP_POP );
    }
        QuickSave( HW_ES, OP_POP );
        QuickSave( HW_DS, OP_POP );
    if( _CPULevel( CPU_186 ) ) {
        Gpopa();
    } else {
        QuickSave( HW_DI, OP_POP );
        QuickSave( HW_SI, OP_POP );
        QuickSave( HW_BP, OP_POP );
        QuickSave( HW_BX, OP_POP );
        QuickSave( HW_BX, OP_POP );
        QuickSave( HW_DX, OP_POP );
        QuickSave( HW_CX, OP_POP );
        QuickSave( HW_AX, OP_POP );
    }
}


static  void    Enter( void ) {
/***********************/

    int     lex_level;
    int     i;

    lex_level = CurrProc->lex_level;
    if( !CurrProc->targ.sp_frame && _CPULevel( CPU_186 ) &&
    #if _TARGET & _TARG_80386
     CurrProc->locals.size <= 65535 &&
    #endif
     ( lex_level != 0 || ( CurrProc->locals.size != 0 && OptForSize > 50 ) ) ) {
        DoEnter( lex_level );
        HW_CTurnOn( CurrProc->state.used, HW_BP );
        CurrProc->state.attr |= ROUTINE_NEEDS_PROLOG;
    } else {
        if( NeedBPProlog() ) {
            if( !CurrProc->targ.sp_frame || CurrProc->targ.sp_align ) {
                HW_CTurnOn( CurrProc->state.used, HW_BP );
                CurrProc->parms.base += WORD_SIZE;
                QuickSave( HW_BP, OP_PUSH );
                i = 0;
                while( --lex_level > 0 ) {
                    i -= 2;
                    GenPushOffset( i );
                }
                GenRegMove( HW_SP, HW_BP );
                if( CurrProc->lex_level > 1 ) {
                    GenRegAdd( HW_BP, ( CurrProc->lex_level - 1 ) * WORD_SIZE );
                }
                if( CurrProc->lex_level != 0 ) {
                    QuickSave( HW_BP, OP_PUSH );
                }
            }
            CurrProc->state.attr |= ROUTINE_NEEDS_PROLOG;
        }
        AllocStack();
    }
}


static  void    CalcUsedRegs( void ) {
/******************************/

    block   *blk;
    instruction *ins;
    name    *result;
    hw_reg_set  used;

    HW_CAsgn( used, HW_EMPTY );
    blk = HeadBlock;
    while( blk != NULL ) {
        ins = blk->ins.hd.next;
        while( ins->head.opcode != OP_BLOCK ) {
            result = ins->result;
            if( result != NULL && result->n.class == N_REGISTER ) {
                HW_TurnOn( used, result->r.reg );
            }
            /* place holder for big label doesn't really zap anything */
            if( ins->head.opcode != OP_NOP ) {
                HW_TurnOn( used, ins->zap->reg );
                if( HW_COvlap( ins->zap->reg, HW_SP ) ) {
                    CurrProc->prolog_state |= GENERATE_RESET_SP;
                }
            }
            ins = ins->head.next;
        }
        blk = blk->next_block;
    }
    if( !CurrProc->targ.sp_frame || CurrProc->targ.sp_align ) {
        HW_CTurnOff( used, HW_BP );
    }
    HW_TurnOn( CurrProc->state.used, used );
}


static  int Push( hw_reg_set to_push ) {
/******************************************/

    hw_reg_set  *curr_push;
    int     size;

    size = 0;
    if( _IsntModel( NO_OPTIMIZATION ) && CurrProc->targ.sp_frame && !CurrProc->targ.sp_align ) {
        FlowSave( &to_push );
    }
    curr_push = PushRegs;
    while( !HW_CEqual( to_push, HW_EMPTY ) ) {
        if( HW_Ovlap( *curr_push, to_push ) ) {
            QuickSave( *curr_push, OP_PUSH );
            size += WORD_SIZE;
            HW_TurnOff( to_push, *curr_push );
        }
        ++ curr_push;
        if( HW_CEqual( *curr_push, HW_EMPTY ) )
            break;
    }
    return( size );
}

static  void        Pop( hw_reg_set to_pop ) {
/************************************************/
    hw_reg_set  *curr_pop;

    if( _IsntModel( NO_OPTIMIZATION ) && CurrProc->targ.sp_frame && !CurrProc->targ.sp_align ) {
        FlowRestore( &to_pop );
    }
    curr_pop = PushRegs;
    while( !HW_CEqual( *curr_pop, HW_EMPTY ) ) {
        ++ curr_pop;
    }
    while( !HW_CEqual( to_pop, HW_EMPTY ) ) {
        -- curr_pop;
        if( HW_Ovlap( *curr_pop, to_pop ) ) {
            QuickSave( *curr_pop, OP_POP );
            HW_TurnOff( to_pop, *curr_pop );
        }
    }
}

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

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


static  void    AllocStack( void ) {
/****************************/

    type_length     size;

    /* keep stack aligned */
    size = ( CurrProc->locals.size + (WORD_SIZE-1) ) & ~(WORD_SIZE-1);
    CurrProc->locals.size = size;
    if( BlockByBlock ) {
        GenUnkSub( HW_SP, &CurrProc->targ.prolog_loc );
        if( CurrProc->prolog_state & GENERATE_TOUCH_STACK ) {
            GenTouchStack( TRUE );
        }
    } else if( size <= 2*WORD_SIZE && OptForSize > 50 ) {
        while( size > 0 ) {
            #if _TARGET & _TARG_80386
            QuickSave( HW_EAX, OP_PUSH );
            #else
            QuickSave( HW_AX, OP_PUSH );
            #endif
            size -= WORD_SIZE;
        }
    } else if( size != 0 ) {
        GenRegSub( HW_SP, size );
        if( CurrProc->prolog_state & GENERATE_TOUCH_STACK ) {
            GenTouchStack( FALSE );
        }
    }
    if( CurrProc->targ.sp_align ) {
        GenRegAnd( HW_SP, -( 2*WORD_SIZE ) );
        CurrProc->prolog_state |= GENERATE_RESET_SP;
    }
}


static  void    DoEnter( int level ) {
/************************************/

    type_length size;

    /* keep stack aligned */
    size = ( CurrProc->locals.size + (WORD_SIZE-1) ) & ~(WORD_SIZE-1);
    CurrProc->locals.size = size;

    CurrProc->parms.base += WORD_SIZE;
    if( BlockByBlock ) {
        GenUnkEnter( &CurrProc->targ.prolog_loc, level );
        if( CurrProc->prolog_state & GENERATE_TOUCH_STACK ) {
            GenTouchStack( TRUE );
        }
    } else {
        GenEnter( size, level );
        if( size != 0 && ( CurrProc->prolog_state & GENERATE_TOUCH_STACK ) ) {
            GenTouchStack( FALSE );
        }
    }
}


extern  void    GenEpilog( void ) {
/***************************/

    type_length stack;
    fe_attr attr;

    attr = FEAttr( AskForLblSym( CurrProc->label ) );

    stack = - CurrProc->locals.size - CurrProc->locals.base
         - CurrProc->targ.push_local_size;
    PatchBigLabels( stack );

    if( _IsModel( DBG_LOCALS ) ){  // d1+ or d2
        EmitEpiBeg();
    }

    if( ( attr & FE_NAKED ) == EMPTY ) {
        if( (CurrProc->state.attr & ROUTINE_NEVER_RETURNS) == 0 ) {
            DoEpilog();
        }

        if( BlockByBlock ) {
            AbsPatch( CurrProc->targ.prolog_loc, CurrProc->locals.size );
        }

        if( CurrProc->targ.stack_check != NULL ) {
            AbsPatch( CurrProc->targ.stack_check,
                  CurrProc->locals.size +
                  CurrProc->parms.base  +
                  WORD_SIZE*CurrProc->lex_level +
                  CurrProc->targ.push_local_size +
                  MaxStack );
        }
    }


    CurrProc->prolog_state |= GENERATED_EPILOG;
    if( _IsModel( DBG_LOCALS ) ){  // d1+ or d2
        EmitRtnEnd();
    }
}


static  void    DoEpilog( void ) {
/**************************/

    hw_reg_set  to_pop;
    bool    is_long;
    type_length size;

    if( _RoutineIsInterrupt( CurrProc->state.attr ) ) {
        PopAll();
    } else {
        to_pop = SaveRegs();
        HW_CTurnOff( to_pop, HW_FLTS );
        if( CHAIN_FRAME ) {
            if( ( CurrProc->state.attr & ROUTINE_NEEDS_PROLOG ) != 0
             || CurrProc->locals.size+CurrProc->targ.push_local_size != 0 ) {
                if( CurrProc->targ.base_adjust == 0 ) {
                    GenRegMove( HW_BP, HW_SP );
                } else {
                    GenLeaSP( -CurrProc->targ.base_adjust );
                }
            }
            HW_CTurnOff( to_pop, HW_BP );
        } else {
            if( CurrProc->state.attr & ROUTINE_NEEDS_PROLOG ) {
                size = CurrProc->locals.size + CurrProc->targ.push_local_size;
                if( (CurrProc->prolog_state & GENERATE_RESET_SP) || size!=0 ) {
                    /* sp is not pointing at saved registers already */
                    if( CurrProc->targ.sp_frame ) {
                        if( CurrProc->targ.sp_align ) {
                            GenRegMove( HW_BP, HW_SP );
                            QuickSave( HW_BP, OP_POP );
                        } else if( size != 0 ) {
                            GenRegAdd( HW_SP, size );
                        }
                    } else if( CurrProc->targ.base_adjust != 0 ) {
                        GenLeaSP( -CurrProc->targ.base_adjust );
                    } else if( _CPULevel( CPU_186 ) && (!_CPULevel( CPU_486 ) ||
                        OptForSize > 50) ) {
                        GenLeave();
                        HW_CTurnOff( to_pop, HW_BP );
                    } else {
                        GenRegMove( HW_BP, HW_SP );
                    }
                }
            }
        }
        Pop( to_pop );
        UnloadDS();
        if( CHAIN_FRAME ) {
            if( NeedBPProlog() ) {
                EpilogHook();
                if( FAR_RET_ON_STACK ) {
                    if( CHEAP_FRAME ) {
                      GenCypWindowsEpilog();
                    } else {
                        GenWindowsEpilog();
                    }
                } else {
                    QuickSave( HW_BP, OP_POP );
                }
            }
        }
    }

    is_long = _RoutineIsLong( CurrProc->state.attr ) ||
        _RoutineIsFar16( CurrProc->state.attr );
    #if _TARGET & _TARG_80386
    if( CurrProc->prolog_state & GENERATE_THUNK_PROLOG ) {
        QuickSave( HW_SP, OP_POP );
    }
    if( _IsTargetModel( NEW_P5_PROFILING|P5_PROFILING ) ) {
        GenP5ProfilingEpilog( CurrProc->label );
    }
    #endif

    if( _RoutineIsInterrupt( CurrProc->state.attr ) ) {
        GenReturn( 0, FALSE, TRUE );
    } else if( CurrProc->state.attr & ROUTINE_REMOVES_PARMS ) {
        GenReturn( CurrProc->parms.size, is_long, FALSE );
    } else {
        GenReturn( 0, is_long, FALSE );
    }
}


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

    return( level*WORD_SIZE );
}

extern  int ParmsAtPrologue( void ) {
/***************************/

    unsigned    ret_size;
    unsigned    parms_off_sp;

    parms_off_sp= 0;

    #if _TARGET & _TARG_80386
    if( CurrProc->prolog_state & GENERATE_THUNK_PROLOG ) {
        parms_off_sp += WORD_SIZE;
    }
    #endif

    if( _RoutineIsInterrupt( CurrProc->state.attr ) ||
       ( CurrProc->state.attr & ROUTINE_NEVER_RETURNS ) ) {
        ret_size = 0;
    } else if( _RoutineIsLong( CurrProc->state.attr ) ) {
        ret_size = 2 * WORD_SIZE;
    } else if( _RoutineIsFar16( CurrProc->state.attr ) ) {
        ret_size = 2 * WORD_SIZE;
    } else {
        ret_size = WORD_SIZE;
    }

    parms_off_sp += ret_size;
    return( parms_off_sp );
}

⌨️ 快捷键说明

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