name *StReturn( an retval, type_def *tipe, instruction **pins ) /****************************************************************/ { name *retp; name *ptr; name *off; name *seg; hw_reg_set reg; if( CurrProc->state.attr & ROUTINE_ALLOCS_RETURN ) { retp = CurrProc->targ.return_points; AddIns( MakeUnary( OP_LA, retp, AllocRegName( CurrProc->state.return_reg ), WD ) ); *pins = NULL; } else { if( _IsTargetModel( FLOATING_SS ) || _IsTargetModel( FLOATING_DS ) ) { ptr = AllocTemp( CP ); off = OffsetPart( ptr ); seg = SegmentPart( ptr ); AddIns( MakeMove( AllocRegName( HW_SS ), seg, U2 ) ); } else { ptr = AllocTemp( WD ); off = ptr; } AddIns( MakeMove( CurrProc->targ.return_points, off, WD ) ); retp = SAllocIndex( ptr, NULL, 0, TypeClass( retval->tipe ), tipe->length ); reg = ReturnReg( WD, false ); *pins = MakeMove( CurrProc->targ.return_points, AllocRegName( reg ), WD ); CurrProc->state.return_reg = reg; } return( retp ); }
void AddRegs( void ) /****************************** Add some registers to the N_REGISTER list, so that we can do scoreboarding on them */ { AllocRegName( HW_DS ); AllocRegName( HW_ES ); AllocRegName( HW_SS ); }
extern an BGCall( cn call, bool use_return, bool in_line ) /********************************************************/ { instruction *call_ins; instruction *conv_ins; call_state *state; name *result; hw_reg_set ret_addr; instruction *ins; call_ins = call->ins; state = call->state; if( state->attr & ROUTINE_MODIFIES_NO_MEMORY ) { 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_IS_SETJMP ) { call_ins->flags.call_flags |= CALL_IS_SETJMP; } if( use_return == FALSE ) { call_ins->flags.call_flags |= CALL_IGNORES_RETURN; } result = BGNewTemp( call->tipe ); if( call_ins->type_class == XX ) { call_ins->result = result; ret_addr = ParmReg( CP, 4, 8, state ); ins = MakeUnary( OP_LA, result, AllocRegName( ret_addr ), CP ); AddIns( ins ); } else { call_ins->result = AllocRegName( state->return_reg ); } AssgnParms( call, in_line ); AddCallIns( call_ins, call ); if( use_return ) { if( call_ins->type_class != XX ) { conv_ins = MakeConvert( call_ins->result, result, TypeClass( call->tipe ), ReturnClass( call->tipe, call->state->attr ) ); AddIns( conv_ins ); } else { // conv_ins = MakeMove( call_result, result, XX ); } } return( MakeTempAddr( result ) ); }
void ScInitRegs( score *sc ) /************************************** Add some register equality "truths" to the scoreboard "sc" */ { int ss; int ds; if( _IsntTargetModel( FLOATING_DS | FLOATING_SS ) ) { ss = AllocRegName(HW_SS)->r.reg_index; ds = AllocRegName(HW_DS)->r.reg_index; if( RegsEqual( sc, ss, ds ) == false ) { RegInsert( sc, ss, ds ); } } }
extern void BGProcDecl( cg_sym_handle sym, type_def *tipe ) /******************************************************/ { type_class_def class; name *temp; hw_reg_set reg; class = AddCallBlock( sym, tipe ); SaveTargetModel = TargetModel; if( tipe != TypeNone ) { if( class == XX ) { // Handle structure returns - we need to "eat up" the first // register used for argument passing here, so that it isn't // used for passing actual arguments. NB: Must also bump // parm.offset here so that arguments end up in the right // locations. reg = HW_D4; temp = AllocTemp( WD ); temp->v.usage |= USE_IN_ANOTHER_BLOCK; AddIns( MakeMove( AllocRegName( reg ), temp, WD ) ); HW_TurnOn( CurrProc->state.parm.used, reg ); // TODO: need to do anything here? // HW_CTurnOn( CurrProc->state.parm.used, HW_F16 ); CurrProc->targ.return_points = temp; CurrProc->state.parm.offset += REG_SIZE; } } }
extern bool AskIsFrameIndex( name *op ) { /*********************************************/ name *bp; bp = AllocRegName( DisplayReg() ); return( op == AllocIndex( bp, NULL, -1, bp->n.name_class ) ); }
extern void SaveDisplay( opcode_defs op ) { /*********************************************/ name *reg; reg = AllocRegName( DisplayReg() ); AddIns( MakeUnary( op, reg, NULL, reg->n.name_class ) ); }
static name *DisplayField( int level ) /****************************************/ { name *reg; reg = AllocRegName( DisplayReg() ); return( AllocIndex( reg, NULL, (-2) * level, reg->n.name_class ) ); }
static void AddSegOverride( instruction *ins, hw_reg_set reg ) /****************************************************************/ { name *reg_name; reg_name = AllocRegName( reg ); ins->operands[ ins->num_operands++ ] = reg_name; }
void AddRegs( void ) /****************************** Add some registers to the N_REGISTER list, so that we can do scoreboarding on them */ { hw_reg_set lo_part; name *reg_name; int i; int j; DS = AllocRegName( HW_DS ); SS = AllocRegName( HW_SS ); /* 89-01-03*/ ES = AllocRegName( HW_ES ); for( i = S_MAX; i-- > 0; ) { for( j = I_MAX; j-- > 0; ) { PtrRegs[i][j] = NULL; } } for( reg_name = Names[N_REGISTER]; reg_name != NULL; reg_name = reg_name->n.next_name ) { if( IsIndexReg( reg_name->r.reg, CP, false ) ) { if( HW_COvlap( reg_name->r.reg, HW_DS ) || HW_COvlap( reg_name->r.reg, HW_ES ) || HW_COvlap( reg_name->r.reg, HW_SS ) ) { lo_part = LowReg( reg_name->r.reg ); if( HW_COvlap( lo_part, HW_BX ) ) { PtrRegs[S_DS][I_BX] = NewRegName( HW_DS_BX ); PtrRegs[S_SS][I_BX] = NewRegName( HW_SS_BX ); PtrRegs[S_ES][I_BX] = NewRegName( HW_ES_BX ); } else if( HW_COvlap( lo_part, HW_SI ) ) { PtrRegs[S_DS][I_SI] = NewRegName( HW_DS_SI ); PtrRegs[S_SS][I_SI] = NewRegName( HW_SS_SI ); PtrRegs[S_ES][I_SI] = NewRegName( HW_ES_SI ); } else if( HW_COvlap( lo_part, HW_DI ) ) { PtrRegs[S_DS][I_DI] = NewRegName( HW_DS_DI ); PtrRegs[S_SS][I_DI] = NewRegName( HW_SS_DI ); PtrRegs[S_ES][I_DI] = NewRegName( HW_ES_DI ); } } } } /* 89-01-03*/ }
extern void SetDisplay( name *temp ) { /****************************************/ name *reg; reg = AllocRegName( DisplayReg() ); AddIns( MakeMove( TempOffset( temp, TypePtr->length, reg->n.name_class ), reg, reg->n.name_class ) ); }
extern void BigGoto( int level ) /**********************************/ { name *reg; if( level != 0 ) { reg = AllocRegName( DisplayReg() ); AddIns( MakeMove( DisplayField( level ), reg, reg->n.name_class ) ); } }
instruction *rOP1RESREG( instruction *ins ) /**********************************************/ { instruction *new_ins; instruction *ins2; name *name1; name *name2; name1 = AllocRegName( Op1Reg( ins ) ); new_ins = MakeMove( ins->operands[0], name1, _OpClass( ins ) ); ins->operands[0] = name1; MoveSegOp( ins, new_ins, 0 ); PrefixIns( ins, new_ins ); name2 = AllocRegName( ResultReg( ins ) ); ins2 = MakeMove( name2, ins->result, ins->type_class ); ins->result = name2; MoveSegRes( ins, ins2 ); SuffixIns( ins, ins2 ); return( new_ins ); }
extern void BigLabel( void ) /******************************/ { instruction *ins; name *bp; name *sp; if( CurrProc->lex_level != 0 ) { bp = AllocRegName( DisplayReg() ); sp = AllocRegName( StackReg() ); ins = MakeUnary( OP_LA, AllocIndex( bp, NULL, -1, bp->n.name_class ), sp, sp->n.name_class ); } else { ins = MakeNop(); } ins->zap = (register_name *) AllocRegName( AllCacheRegs() ); ins->flags.nop_flags |= NOP_ZAP_INFO; AddIns( ins ); }
static name *NewRegName( hw_reg_set reg ) /******************************************** Allocate a new "far pointer" register an set its class */ { name *reg_name; reg_name = AllocRegName( reg ); reg_name->n.name_class = CP; return( reg_name ); }
extern name *MakeDisplay( name *op, int level ) /*************************************************/ { name *temp; name *reg; reg = AllocRegName( DisplayReg() ); temp = AllocTemp( U2 ); AddIns( MakeMove( DisplayField( level ), temp, reg->n.name_class ) ); op = AllocIndex( temp, NULL, op->t.location, op->n.name_class ); return( op ); }
static void DropCall( instruction *ins, name *temp ) /******************************************************/ { name *eax_name; name *null_name; instruction *new_ins; null_name = AllocRegName( HW_EMPTY ); eax_name = AllocRegName( HW_EAX ); new_ins = NewIns( 3 ); new_ins->head.opcode = OP_CALL; new_ins->type_class = WD; new_ins->operands[ CALL_OP_USED ] = null_name; new_ins->operands[ CALL_OP_USED2 ] = null_name; new_ins->operands[ CALL_OP_ADDR ]= RTMemRef( RT_TLS_REGION ); new_ins->result = eax_name; new_ins->zap = &eax_name->r; new_ins->num_operands = 2; /* special case for OP_CALL*/ PrefixIns( ins, new_ins ); new_ins = MakeMove( eax_name, temp, WD ); PrefixIns( ins, new_ins ); }
void ScInitRegs( score *scoreboard ) /************************************** Add some register equality "truths" to the scoreboard "sc" */ { int xs; int ds; ds = AllocRegName( HW_DS )->r.reg_index; if( _IsntTargetModel( FLOATING_DS ) ) { if( _IsntTargetModel( FLOATING_ES ) ) { xs = AllocRegName( HW_ES )->r.reg_index; if( !RegsEqual( scoreboard, xs, ds ) ) { RegInsert( scoreboard, xs, ds ); } } if( _IsntTargetModel( FLOATING_SS ) ) { xs = AllocRegName( HW_SS )->r.reg_index; if( !RegsEqual( scoreboard, xs, ds ) ) { RegInsert( scoreboard, xs, ds ); } } } }
static void CheckOp( name **offsets, instruction *ins, name **pop ) { /************************************************************************ used by FixFarLocalRefs to change one far local reference to an index, using the appropriate multiple of 4K constant to get at the temporary. The constant values are adjusted after the prolog is generated. */ name *op; name *base; name *temp; unsigned_32 place; int i; instruction *new_ins; op = *pop; if( op->n.class == N_INDEXED ) { temp = op->i.index; if( temp->n.class != N_TEMP ) return; if( !( temp->t.temp_flags & FAR_LOCAL ) ) return; new_ins = MakeMove( temp, AllocTemp( temp->n.name_class ), temp->n.name_class ); *pop = ScaleIndex( new_ins->result, op->i.base, op->i.constant, op->n.class, op->n.size, op->i.scale, op->i.index_flags ); PrefixIns( ins, new_ins ); CheckOp( offsets, new_ins, &new_ins->operands[ 0 ] ); } if( op->n.class != N_TEMP ) return; if( !( op->t.temp_flags & FAR_LOCAL ) ) return; base = DeAlias( op ); place = base->t.location + ( op->v.offset - base->v.offset ); i = place/_4K; if( offsets[ i ] == NULL ) { /*set the symbol field in the AddrConst to non-NULL for score-boarder*/ new_ins = MakeMove( AllocAddrConst( (name *)&CurrProc, i, CONS_OFFSET, WD ), AllocTemp( WD ), WD ); offsets[ i ] = new_ins->result; PrefixIns( HeadBlock->ins.hd.next, new_ins ); } temp = AllocTemp( WD ), new_ins = MakeMove( offsets[ i ], temp, WD ); PrefixIns( ins, new_ins ); new_ins = MakeBinary( OP_ADD, temp, AllocRegName( DisplayReg() ), temp, WD); PrefixIns( ins, new_ins ); *pop = ScaleIndex( temp, op, place%_4K, op->n.name_class, op->n.size, 0, X_FAKE_BASE ); }
extern an PassProcParm( an rtn ) { /**************************************/ name *op; name *reg; op = AllocTemp( XX ); op->n.size = TypePtr->length + SizeDisplayReg(); reg = AllocRegName( DisplayReg() ); AddIns( MakeMove( GenIns( rtn ), TempOffset( op, 0, ClassPointer ), ClassPointer ) ); AddIns( MakeMove( reg, TempOffset( op, TypePtr->length, reg->n.name_class ), reg->n.name_class ) ); return( AddrName( op, TypeProcParm ) ); }
static void AddCall( instruction *ins, cn call ) { /****************************************************/ name *proc_name; if( _IsTargetModel(FLOATING_DS) && (call->state->attr&ROUTINE_NEEDS_DS_LOADED) ) { AddIns( MakeMove( NearSegment(), AllocRegName( HW_DS ), U2 ) ); } if( call->name->tipe == TypeProcParm ) { proc_name = AllocTemp( ClassPointer ); /* what to do? proc_name->usage |= USE_REGISTER;*/ AddIns( MakeMove( ins->operands[CALL_OP_ADDR], proc_name, ClassPointer )); ins->operands[CALL_OP_ADDR] = proc_name; SetDisplay( GenIns( call->name ) ); AddIns( ins ); SaveDisplay( OP_POP ); } else { AddCallIns( ins, call ); } }
void BGProcDecl( cg_sym_handle sym, type_def *tipe ) /*****************************************************/ { type_class_def class; name *temp; hw_reg_set reg; class = AddCallBlock( sym, tipe ); SaveTargetModel = TargetModel; if( tipe != TypeNone ) { if( class == XX ) { reg = HW_D3; 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; } } }
void BGProcDecl( cg_sym_handle sym, type_def *tipe ) /*****************************************************/ { hw_reg_set reg; name *temp; type_class_def type_class; segment_id old_segid; label_handle lbl; SaveTargetModel = TargetModel; type_class = AddCallBlock( sym, tipe ); if( tipe != TypeNone ) { if( type_class == XX ) { if( CurrProc->state.attr & ROUTINE_ALLOCS_RETURN ) { old_segid = 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_segid ); } 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( CurrProc->state.attr & ROUTINE_FARSS ) { TargetModel |= FLOATING_SS; } }
*/ { name *op; i_flags flags; name *index; hw_reg_set tmp; op = *pop; if( op->n.class == N_MEMORY && !SegIsCS( op ) ) { *pop = SAllocIndex( gblreg, op, op->v.offset, op->n.type_class, op->n.size ); } else if( op->n.class == N_INDEXED ) { if( op->i.base != NULL && op->i.base->n.class == N_MEMORY && !SegIsCS( op->i.base ) ) { tmp = gblreg->r.reg; HW_TurnOn( tmp, op->i.index->r.reg ); index = AllocRegName( tmp ); tmp = High64Reg( index->r.reg ); if( HW_Equal( tmp, gblreg->r.reg ) ) { flags = X_HIGH_BASE; } else { flags = X_LOW_BASE; } *pop = ScaleIndex( index, op->i.base, op->i.constant, op->n.type_class, op->n.size, op->i.scale, op->i.index_flags|flags); } } } static void AddGlobalIndex( void ) /*************************************
instruction *rMAKECALL( instruction *ins ) /********************************************* Using the table RTInfo[], do all the necessary stuff to turn instruction "ins" into a call to a runtime support routine. Move the parms into registers, and move the return register of the runtime routine into the result. Used for 386 and 370 versions */ { rtn_info *info; label_handle lbl; instruction *left_ins; instruction *new_ins; instruction *last_ins; name *reg_name; hw_reg_set regs; hw_reg_set all_regs; hw_reg_set tmp; rt_class rtindex; if( !_IsConvert( ins ) ) { rtindex = LookupRoutine( ins ); } else { /* look it up again in case we ran out of memory during expansion*/ rtindex = LookupConvertRoutine( ins ); } info = &RTInfo[rtindex]; regs = _ParmReg( info->left ); all_regs = regs; left_ins = MakeMove( ins->operands[0], AllocRegName( regs ), info->operand_class ); ins->operands[0] = left_ins->result; MoveSegOp( ins, left_ins, 0 ); PrefixIns( ins, left_ins ); regs = _ParmReg( info->right ); if( !HW_CEqual( regs, HW_EMPTY ) ) { new_ins = MakeMove( ins->operands[1], AllocRegName( regs ), info->operand_class ); ins->operands[1] = new_ins->result; MoveSegOp( ins, new_ins, 0 ); HW_TurnOn( all_regs, regs ); PrefixIns( ins, new_ins ); } #if _TARGET & _TARG_370 tmp = RAReg(); HW_TurnOn( all_regs, tmp ); tmp = LNReg(); HW_TurnOn( all_regs, tmp ); #elif _TARGET & _TARG_80386 { tmp = ReturnReg( WD, false ); HW_TurnOn( all_regs, tmp ); } #endif reg_name = AllocRegName( all_regs ); lbl = RTLabel( rtindex ); new_ins = NewIns( 3 ); new_ins->head.opcode = OP_CALL; new_ins->type_class = ins->type_class; new_ins->operands[CALL_OP_USED] = reg_name; new_ins->operands[CALL_OP_USED2] = reg_name; new_ins->operands[CALL_OP_ADDR] = AllocMemory( lbl, 0, CG_LBL, ins->type_class ); new_ins->result = NULL; new_ins->num_operands = 2; /* special case for OP_CALL*/ #if _TARGET & _TARG_AXP { HW_CTurnOn( all_regs, HW_FULL ); HW_TurnOff( all_regs, SavedRegs() ); HW_CTurnOff( all_regs, HW_UNUSED ); HW_TurnOn( all_regs, ReturnAddrReg() ); } #endif new_ins->zap = (register_name *)AllocRegName( all_regs ); /* all parm regs could be zapped*/ last_ins = new_ins; if( ins->result == NULL || _OpIsCondition( ins->head.opcode ) ) { /* comparison, still need conditional jumps*/ ins->operands[0] = AllocIntConst( 0 ); ins->operands[1] = AllocIntConst( 1 ); DelSeg( ins ); DoNothing( ins ); /* just conditional jumps for ins*/ PrefixIns( ins, new_ins ); new_ins->ins_flags |= INS_CC_USED; last_ins = ins; } else { regs = _ParmReg( info->result ); tmp = regs; HW_TurnOn( tmp, new_ins->zap->reg ); new_ins->zap = (register_name *)AllocRegName( tmp ); reg_name = AllocRegName( regs ); new_ins->result = reg_name; last_ins = MakeMove( reg_name, ins->result, ins->type_class ); ins->result = last_ins->operands[0]; MoveSegRes( ins, last_ins ); SuffixIns( ins, last_ins ); ReplIns( ins, new_ins ); } FixCallIns( new_ins ); UpdateLive( left_ins, last_ins ); return( left_ins ); }
void ScoreCalcList( void ) /***************************/ { score_reg *curr; name *reg_name; int i; hw_reg_set reg; ScoreCount = 0; AddRegs(); for( reg_name = Names[N_REGISTER]; reg_name != NULL; reg_name = reg_name->n.next_name ) { if( ScRealRegister( reg_name ) ) { reg = HighOffsetReg( reg_name->r.reg ); if( !HW_CEqual( reg, HW_EMPTY ) ) { AllocRegName( reg ); } reg = LowOffsetReg( reg_name->r.reg ); if( !HW_CEqual( reg, HW_EMPTY ) ) { AllocRegName( reg ); } } } for( reg_name = Names[N_REGISTER]; reg_name != NULL; reg_name = reg_name->n.next_name ) { if( ScRealRegister( reg_name ) ) { ++ScoreCount; } } if( ScoreCount != 0 ) { ScoreList = ScAlloc( ScoreCount * ( sizeof( pointer ) + sizeof( score_reg ) ) ); curr = (score_reg *)&ScoreList[ScoreCount]; i = 0; for( reg_name = Names[N_REGISTER]; reg_name != NULL; reg_name = reg_name->n.next_name ) { if( ScRealRegister( reg_name ) ) { curr->reg_name = reg_name; curr->reg = reg_name->r.reg; curr->type_class = reg_name->n.type_class; curr->size = reg_name->n.size; curr->high_of = NO_INDEX; curr->low_of = NO_INDEX; reg_name->r.reg_index = i; ScoreList[i] = curr; /*% This avoids MANY multiplies!*/ ++curr; ++i; } } i = ScoreCount; while( curr != ScoreList[0] ) { --curr; --i; reg = HighOffsetReg( curr->reg ); if( !HW_CEqual( reg, HW_EMPTY ) ) { reg_name = AllocRegName( reg ); if( !ScRealRegister( reg_name ) || reg_name->r.reg_index == NO_INDEX ) { curr->high = NO_INDEX; } else { curr->high = reg_name->r.reg_index; ScoreList[curr->high]->high_of = i; } } else { curr->high = NO_INDEX; } reg = LowOffsetReg( curr->reg ); if( !HW_CEqual( reg, HW_EMPTY ) ) { reg_name = AllocRegName( reg ); if( !ScRealRegister( reg_name ) || reg_name->r.reg_index == NO_INDEX ) { curr->low = NO_INDEX; } else { curr->low = reg_name->r.reg_index; ScoreList[curr->low]->low_of = i; } } else { curr->low = NO_INDEX; } } } }
void FlowSave( hw_reg_set *preg ) /*******************************/ { int score; int i, j; int best; int num_blocks; int num_regs; int curr_reg; hw_reg_set *curr_push; reg_flow_info *reg_info; block *save; block *restore; instruction *ins; type_class_def reg_type; HW_CAsgn( flowedRegs, HW_EMPTY ); if( _IsntModel( FLOW_REG_SAVES ) ) return; if( !HaveDominatorInfo ) return; // we can't do this if we have push's which are 'live' at the end of a block // - this flag is set when we see a push being generated for a call in a different // block #if _TARGET & _TARG_INTEL if( CurrProc->targ.never_sp_frame ) return; #endif num_regs = CountRegs( *preg ); if( num_regs == 0 ) return; reg_info = CGAlloc( num_regs * sizeof( reg_flow_info ) ); num_blocks = CountBlocks(); InitBlockArray(); curr_push = PushRegs; for( curr_reg = 0; curr_reg < num_regs; curr_reg++ ) { while( !HW_Ovlap( *curr_push, *preg ) ) curr_push++; HW_Asgn( reg_info[curr_reg].reg, *curr_push ); reg_info[curr_reg].save = NULL; reg_info[curr_reg].restore = NULL; #if _TARGET & _TARG_INTEL if( HW_COvlap( *curr_push, HW_BP ) ) continue; // don't mess with BP - it's magical #endif GetRegUsage( ®_info[curr_reg] ); best = 0; for( i = 0; i < num_blocks; i++ ) { for( j = 0; j < num_blocks; j++ ) { if( PairOk( blockArray[i], blockArray[j], ®_info[0], curr_reg ) ) { // we use the number of blocks dominated by the save block plus // the number of blocks post-dominated by the restore block as a // rough metric for determining how much we like a given (valid) // pair of blocks - the more blocks dominated, the further 'in' // we have pushed the save, which should be good score = CountDomBits( &blockArray[i]->dom.dominator ); score += CountDomBits( &blockArray[j]->dom.post_dominator ); if( score > best ) { best = score; reg_info[curr_reg].save = blockArray[i]; reg_info[curr_reg].restore = blockArray[j]; } } } } // so now we know where we are going to save and restore the register // emit the instructions to do so, and remove reg from the set to push // in the normal prolog sequence save = reg_info[curr_reg].save; restore = reg_info[curr_reg].restore; if( ( save != NULL && save != HeadBlock ) && ( restore != NULL && !_IsBlkAttr( restore, BLK_RETURN ) ) ) { reg_type = WD; #if _TARGET & _TARG_INTEL if( IsSegReg( reg_info[curr_reg].reg ) ) { reg_type = U2; } #endif ins = MakeUnary( OP_PUSH, AllocRegName( reg_info[curr_reg].reg ), NULL, reg_type ); ResetGenEntry( ins ); PrefixIns( save->ins.hd.next, ins ); ins = MakeUnary( OP_POP, NULL, AllocRegName( reg_info[curr_reg].reg ), reg_type ); ins->num_operands = 0; ResetGenEntry( ins ); SuffixIns( restore->ins.hd.prev, ins ); HW_TurnOff( *preg, reg_info[curr_reg].reg ); HW_TurnOn( flowedRegs, reg_info[curr_reg].reg ); FixStackDepth( save, restore ); } curr_push++; } CGFree( reg_info ); }
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 ) ); }
static void Far16Parms( cn call ) { /*************************************/ instruction *ins; type_length parm_size; pn parm, next; instruction *call_ins; name *eax; name *ecx; name *esi; label_handle lbl; type_length offset; name *parmlist; call_state *state; rt_class rtindex; call_ins = call->ins; parm_size = 0; state = call->state; for( parm = call->parms; parm != NULL; parm = parm->next ) { parm_size += _RoundUp( parm->name->tipe->length, 2 ); } parmlist = SAllocTemp( XX, parm_size ); parmlist->v.usage |= NEEDS_MEMORY | USE_IN_ANOTHER_BLOCK | USE_ADDRESS; offset = 0; for( parm = call->parms; parm != NULL; parm = parm->next ) { parm->name->u.i.ins->result = STempOffset( parmlist, offset, TypeClass( parm->name->tipe ), parm->name->tipe->length ); offset += _RoundUp( parm->name->tipe->length, 2 ); } for( parm = call->parms; parm != NULL; parm = next ) { next = parm->next; parm->name->format = NF_ADDR; /* so instruction doesn't get freed! */ BGDone( parm->name ); CGFree( parm ); } eax = AllocRegName( HW_EAX ); ecx = AllocRegName( HW_ECX ); esi = AllocRegName( HW_ESI ); HW_TurnOn( state->parm.used, eax->r.reg ); HW_TurnOn( state->parm.used, ecx->r.reg ); HW_TurnOn( state->parm.used, esi->r.reg ); ins = MakeMove( AllocS32Const( parm_size ), ecx, WD ); AddIns( ins ); ins = MakeUnary( OP_LA, parmlist, esi, WD ); AddIns( ins ); if( ins->head.opcode == OP_CALL ) { ins = MakeUnary( OP_LA, call->name->u.n.name, eax, WD ); } else { ins = MakeMove( GenIns( call->name ), eax, WD ); call_ins->head.opcode = OP_CALL; } call_ins->num_operands = 2; AddIns( ins ); if( call_ins->type_class == XX ) { if( state->attr & ROUTINE_ALLOCS_RETURN ) { rtindex = RT_Far16Cdecl; } else { rtindex = RT_Far16Pascal; } } else { rtindex = RT_Far16Func; } lbl = RTLabel( rtindex ); call->name->u.n.name = AllocMemory( lbl, 0, CG_LBL, WD ); call_ins->flags.call_flags |= CALL_FAR16 | CALL_POPS_PARMS; call_ins->operands[CALL_OP_USED] = AllocRegName( state->parm.used ); call_ins->operands[CALL_OP_POPS] = AllocS32Const( 0 ); call_ins->zap = &call_ins->operands[CALL_OP_USED]->r; }