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