long AddrDiff( address a, address b ) { AddrFix( &a ); AddrFix( &b ); DeAlias( &a.mach ); DeAlias( &b.mach ); return( MADAddrDiff( &a, &b, MAF_FULL ) ); }
int SameAddrSpace( address a, address b ) { if( _IsOn( SW_IGNORE_SEGMENTS ) ) return( TRUE ); if( a.sect_id == 0 ) a.sect_id = b.sect_id; if( b.sect_id == 0 ) b.sect_id = a.sect_id; if( a.sect_id != b.sect_id ) return( FALSE ); AddrFix( &a ); AddrFix( &b ); DeAlias( &a.mach ); DeAlias( &b.mach ); return( a.mach.segment == b.mach.segment ); }
static bool SameLocation( name *n1, name *n2 ) { /**************************************************/ type_length loc1, loc2; name *base; if( n1->t.location == NO_LOCATION ) return( FALSE ); if( n2->t.location == NO_LOCATION ) return( FALSE ); base = DeAlias( n1 ); loc1 = base->t.location + n1->v.offset - base->v.offset; base = DeAlias( n2 ); loc2 = base->t.location + n2->v.offset - base->v.offset; if( _IsFloating( n1->n.name_class ) || _IsFloating( n2->n.name_class ) ) { if( n1->n.name_class != n2->n.name_class ) return( FALSE ); } return( loc1 == loc2 ); }
static void ForceTempsMemory( void ) /**************************************/ { name *op; name *next; ParmPropagate(); for( op = Names[N_TEMP]; op != LastTemp; op = next ) { next = op->n.next_name; if( ( op->v.usage & USE_IN_ANOTHER_BLOCK ) || _FrontEndTmp( op ) ) { op = DeAlias( op ); op->v.usage |= NEEDS_MEMORY | USE_MEMORY; while( op->v.conflict != NULL ) { FreeAConflict( op->v.conflict ); } } } AssignOtherLocals(); for( op = Names[N_MEMORY]; op != NULL; op = op->n.next_name ) { op->v.usage |= USE_IN_ANOTHER_BLOCK | USE_MEMORY; if( op->v.conflict != NULL ) { FreeAConflict( op->v.conflict ); op->v.conflict = NULL; } } LastTemp = Names[ N_TEMP ]; }
//TODO: maybe this should be some sort of call back extern void _CGAPI DFDwarfLocal( pointer client, pointer locid, pointer sym ) { /*** add to location expr where local sym is *********************************/ name *tmp; type_length offset; tmp = DeAlias( AllocUserTemp( sym, XX ) ); offset = NewBase( tmp ); DWLocOp( client, locid, DW_LOC_fbreg, offset ); }
int AddrComp( address a, address b ) { if( a.sect_id == 0 ) a.sect_id = b.sect_id; if( b.sect_id == 0 ) b.sect_id = a.sect_id; if( a.sect_id > b.sect_id ) { return( 3 ); } else if( a.sect_id < b.sect_id ) { return( -3 ); } else { if( _IsOn( SW_IGNORE_SEGMENTS ) ) { return( MADAddrComp( &a, &b, MAF_OFFSET ) ); } else { AddrFix( &a ); AddrFix( &b ); DeAlias( &a.mach ); DeAlias( &b.mach ); return( MADAddrComp( &a, &b, MAF_FULL ) ); } } }
static temp_entry *LookupTempEntry( name *op ) { /***********************************************/ temp_entry *temp; if( op == NULL ) return( NULL ); if( op->n.class == N_TEMP ) op = DeAlias( op ); for( temp = TempList; temp != NULL; temp = temp->next ) { if( temp->op == op ) return( temp ); } return( NULL ); }
static void AssignPushLocals( void ) { /*********************************** Scan through HeadBlock to see if there are any leading instructions of the form MOV REG => temp, where temp is on the stack. We can eliminate the instruction (call DoNothing to mark it as unnecessary to generate) and then the guy that generates the prolog can come along later and generate PUSH REG, and adjust the SUB SP,n instruction appropriately. this replaces a move with a less expensive push, and if all locals turn out to be push locals, eliminates the SUP SP,n instruction as well */ instruction *move; name *src; name *dst; type_length curr_offset; move = HeadBlock->ins.hd.next; curr_offset = 0; for(;;) { if( CurrProc->prolog_state & GENERATED_PROLOG ) break; if( DoesSomething( move ) ) { if( move->head.opcode != OP_MOV ) break; if( UnChangeable( move ) ) break; src = move->operands[ 0 ]; dst = move->result; if( src->n.class != N_REGISTER ) break; if( _IsFloating( src->n.name_class ) ) break; /*90-Dec-17*/ if( dst->n.class != N_TEMP ) break; #if _TARGET & _TARG_80386 if( dst->n.size != 4 ) break; #else if( dst->n.size != 2 && dst->n.size != 4 ) break; #endif curr_offset -= PushSize( dst->n.size );/* assume it will be pushed*/ if( DeAlias( dst ) != dst ) break; if( dst->v.usage & HAS_MEMORY ) { if( dst->t.location != curr_offset ) break; } else { CurrProc->targ.push_local_size += PushSize( dst->n.size ); dst->t.location = - CurrProc->targ.push_local_size; dst->v.usage |= HAS_MEMORY; PropLocal( dst ); } move->head.state = OPERANDS_NEED_WORK; DoNothing( move ); } move = move->head.next; } }
static byte DoDisp( type_length val, hw_reg_set base_reg, name *op ) /**********************************************************************/ { name *base; if( op == NULL ) { return( Displacement( val, base_reg ) ); } else if( op->n.class == N_TEMP ) { base = DeAlias( op ); if( base->t.location == NO_LOCATION ) { _Zoiks( ZOIKS_034 ); } val += TmpLoc( base, op ); return( Displacement( val, base_reg ) ); } else if( op->n.class == N_MEMORY ) {
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 ); }
static void setTempLocations( void ) /**************************************/ { name *base; name *temp; for( temp = Names[N_TEMP]; temp != NULL; temp = temp->n.next_name ) { base = DeAlias( temp ); if( base->t.location == NO_LOCATION ) { temp->t.v.alt_location = NO_LOCATION; } else { temp->t.v.alt_location = base->t.location + temp->v.offset - base->v.offset; } } }
static byte DoDisp( name *op, hw_reg_set regs ) /*************************************************/ { name *base; int val; byte dmod; name *temp_base; val = op->i.constant; /* use integer value*/ base = op->i.base; if( !HasTrueBase( op ) ) { dmod = Displacement( val, regs ); } else if( base->n.class == N_TEMP ) { temp_base = DeAlias( base ); if( temp_base->t.location == NO_LOCATION ) { _Zoiks( ZOIKS_034 ); } val += NewBase( temp_base ) + base->v.offset - temp_base->v.offset; dmod = Displacement( val, regs ); } else {
static temp_entry *AddTempEntry( name *op ) { /********************************************/ temp_entry *temp; temp = LookupTempEntry( op ); if( temp == NULL ) { temp = CGAlloc( sizeof( *temp ) ); temp->next = TempList; TempList = temp; temp->actual_op = op; if( op->n.class == N_TEMP ) op = DeAlias( op ); temp->op = op; temp->first = NULL; temp->last = NULL; temp->savings = 0; temp->actual_locn = ACTUAL_NONE; temp->savings = 0; temp->cached = FALSE; temp->defined = FALSE; temp->killed = FALSE; temp->global = FALSE; temp->whole_block = FALSE; }
static void OnTheEdge() { /**************************** Well, we have marked a bunch of temporaries as VISITED (meaning they need an expensive reference). We can change our mind now and let one of these stick its nose into the 4K area so it can be cheaply addressed. (NoseIn). Figure out which one is most worthy (saves most references) and remember it */ name *temp; for( temp = Names[ N_TEMP ]; temp != NULL; temp = temp->n.next_name ) { if( temp->t.temp_flags & VISITED ) { if( temp->t.u.ref_count > NoseIn->t.u.ref_count ) { NoseIn = DeAlias( temp ); } } } temp = NoseIn; do { temp->t.temp_flags &= ~VISITED; temp = temp->t.alias; } while( temp != NoseIn ); }
static void ThrowOutParms() { /******************************** We're going to be bumping AR past the parameters, so all parameters need an expensive reference. */ name *temp; name *base; name *alias; type_length place; NoseIn = NULL; for( temp = Names[ N_TEMP ]; temp != NULL; temp = temp->n.next_name ) { if( temp->t.temp_flags & ALIAS ) continue; if( !( temp->t.temp_flags & STACK_PARM ) ) continue; base = DeAlias( temp ); place = base->t.location + ( temp->v.offset - base->v.offset ); alias = temp; do { alias->t.temp_flags |= FAR_LOCAL; alias = alias->t.alias; } while( alias != temp ); } }