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