extern void BGProcDecl( cg_sym_handle sym, type_def *tipe ) { /************************************************************/ hw_reg_set reg; name *temp; type_class_def class; segment_id old; label_handle lbl; SaveTargetModel = TargetModel; class = AddCallBlock( sym, tipe ); if( tipe != TypeNone ) { if( class == XX ) { if( CurrProc->state.attr & ROUTINE_ALLOCS_RETURN ) { old = 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 ); } 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( _RoutineIsInterrupt( CurrProc->state.attr ) ) { TargetModel |= FLOATING_SS; } }
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 ) ); }