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 ); }
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 ) ); }
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 void SaveDisplay( opcode_defs op ) { /*********************************************/ name *reg; reg = AllocRegName( DisplayReg() ); AddIns( MakeUnary( op, reg, NULL, reg->n.name_class ) ); }
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 ) ); }
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 ) ); } }
void MkSelOp( name *idx, type_class_def type_class ) /*****************************************************/ { instruction *ins; ins = NewIns( 2 ); ins->head.opcode = OP_ADD; ins->type_class = WD; ins->operands[0] = idx->i.index; ins->operands[1] = idx->i.index; ins->result = idx->i.index; AddIns( ins ); ins = NewIns( 1 ); ins->operands[0] = idx; ins->result = idx->i.index; ins->head.opcode = OP_SELECT; ins->type_class = type_class; ins->ins_flags |= INS_CC_USED; AddIns( ins ); }
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 ); } }
static an Unary( cg_op op, an left, type_def *tipe ) /***************************************************/ { instruction *ins; an res; ins = MakeNary( (opcode_defs)op, GenIns( left ), NULL, NULL, TypeClass( tipe ), TypeClass( left->tipe ), 1 ); res = InsName( ins, tipe ); AddIns( ins ); BGDone( left ); return( res ); }
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 an FlowOut( an node, type_def *tipe ) { /**************************************************/ name *temp; label_handle lbl; lbl = AskForNewLabel(); temp = BGGlobalTemp( tipe ); AddIns( MakeMove( AllocIntConst( FETrue() ), temp, temp->n.type_class ) ); *(node->u.b.t) = CurrBlock->label; GenBlock( BLK_JUMP, 1 ); AddTarget( lbl, false ); EnLink( AskForNewLabel(), true ); AddIns( MakeMove( AllocIntConst( 0 ), temp, temp->n.type_class ) ); *(node->u.b.f) = CurrBlock->label; GenBlock( BLK_JUMP, 1 ); AddTarget( lbl, false ); EnLink( lbl, true ); NamesCrossBlocks(); AddrFree( node ); return( AddrName( temp, tipe ) ); }
extern void BGParmInline( cg_sym_handle sym, type_def *tipe ) { /**************************************************************/ name *temp; name *parm_value; inline_parm *parm; parm = InlineStack->parms; InlineStack->parms = InlineStack->parms->next; // if( NotEquiv( parm->addr->tipe, tipe ) ) { // _Zoiks( ZOIKS_070 ); // } temp = SAllocUserTemp( sym, TypeClass( tipe ), tipe->length ); temp->v.usage |= USE_IN_ANOTHER_BLOCK; parm_value = GenIns( parm->addr ); BGDone( parm->addr ); AddIns( MakeMove( parm_value, temp, temp->n.name_class ) ); CGFree( parm ); }
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; } } }
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 ); }
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; } }
bool PDetPlacement::Optimize() { bool OptimizationResult = false; const int NInss = _problem.size(); // Save Initial Solution BestSolution.reserve(NInss); Problem::iterator ifirst = _problem.begin(); Problem::iterator ilast = _problem.end(); vector<double>::iterator It = BestSolution.begin(); while (ifirst != ilast) *It++ = (*ifirst++)->GetLeftCornerX(); for(Idx = 0; Idx != NInss; ) Queue.push_back(Idx++); // Init Best Cost BBoxFlag++; BestCost = InitCost(BBoxFlag); #ifdef PLACE_DEBUG cout<<" Orig Cost: "<< BestCost << endl; cout<<" Actual Cost: " << CurrentCost() << endl; #endif // Init Initial Cost BBoxFlag++; // Init Edges LeftEdge = (*_problem.begin())->GetLeftCornerX(); RightEdge =(*_problem.rbegin())->GetLeftCornerX() + (*_problem.rbegin())->GetMarginWidth(); UnPlaceAll(); Cost = InitCost(BBoxFlag); #ifdef PLACE_DEBUG cout << " Init Cost: " << Cost << endl; #endif UVect.reserve(NInss + 2); for (int id = 0; id < NInss + 2; id++) UVect.push_back(0); UVect[NInss] = NInss; UVect[NInss + 1] = NInss + 1; Stack.reserve(NInss); Idx = NInss - 1; unsigned NumAdds = 0; while(Idx < NInss) { AddIns(); NumAdds++; if(UVect[Idx] == 0 || Cost >= BestCost) { UVect[Idx] = 0; //force a bound if(Cost < BestCost) //got here if: // new best complete soln (curWL < best) // bounded partial soln (curWL > best) // so there is no need to additionally // check to ensure this is a complete soln { OptimizationResult = true; BestCost = Cost; #ifdef PLACE_DEBUG cout<<" New Best: "<< Cost <<" found after "<< NumAdds<< endl; BBoxFlag++; cout << "Cost recalculated " << InitCost(BBoxFlag) << endl; cout << "actual Cost" << CurrentCost() << endl; #endif ifirst = _problem.begin(); It = BestSolution.begin(); while (ifirst != ilast) { *It++ = (*ifirst++)->GetLeftCornerX(); } } while(UVect[Idx] == 0) { if(Idx < NInss) RemoveIns(); UVect[++Idx]--; } } Idx--; } ifirst = _problem.begin(); It = BestSolution.begin(); while (ifirst != ilast) (*ifirst++)->SetLeftCornerX(*It++); PlaceAll(); BestSolution.clear(); #ifdef PLACE_DEBUG cout<<" Total Add Operations: "<< NumAdds<< endl; cout<<" Final solution has cost: "<< BestCost << endl << endl; #endif UVect.clear(); Queue.clear(); Stack.clear(); return OptimizationResult; }
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; }