76 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			76 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <system.h>
 | |
| #include <out.h>
 | |
| #include "back.h"
 | |
| 
 | |
| /* Solve the local references.
 | |
|  */
 | |
| 
 | |
| #define seg_index( s)	( nname - SEGBSS - 1 + s)
 | |
| 
 | |
| long 		get4(); 
 | |
| 
 | |
| do_local_relocation()
 | |
| 
 | |
| /* Check if this reference is solvable. External references contain
 | |
|  * -1 in 'on_valu'.
 | |
|  * Also remove useless relocation structures.
 | |
|  */
 | |
| {
 | |
| 	register struct outrelo *rp;
 | |
| 	int diff = 0;
 | |
| 	
 | |
| 	for ( rp = reloc_info; rp < relo; rp++) {
 | |
| 		register struct outname *np = &symbol_table[rp->or_nami];
 | |
| 		int olddiff = diff;
 | |
| 		
 | |
| 		if ( np->on_valu  != -1 && ! (np->on_type & S_COM)) {
 | |
| 			register long oldval,newval;
 | |
| 			register char *sect;
 | |
| 
 | |
| 			switch( rp->or_sect - S_MIN) {
 | |
| 				case SEGTXT:
 | |
| 					sect = text_area;
 | |
| 					if ((rp->or_type & RELPC) &&
 | |
| 					    (np->on_type & S_TYP) - S_MIN == SEGTXT) {
 | |
| 						diff++;
 | |
| 					}
 | |
| 					break;
 | |
| 				case SEGCON:
 | |
| 					sect = data_area;
 | |
| 					break;
 | |
| 				default:
 | |
| 					fprint( STDERR, 
 | |
| 					  "do_local_relo(): bad section %d\n",
 | |
| 				 		rp->or_sect - S_MIN);
 | |
| 					break;
 | |
| 			}
 | |
| 
 | |
| 			if  ( rp->or_type & RELO4) {
 | |
| 				oldval = get4( sect, rp->or_addr);
 | |
| 				newval = oldval + np->on_valu;
 | |
| 				put4( sect, rp->or_addr, newval);
 | |
| 			}
 | |
| 			else if  ( rp->or_type & RELO2) {
 | |
| 				oldval = (long) get2( sect, rp->or_addr);
 | |
| 				newval = oldval + np->on_valu;
 | |
| 				put2( sect, rp->or_addr, (int) newval);
 | |
| 			}
 | |
| 			else if  ( rp->or_type & RELO1) {
 | |
| 				oldval = (long) get1( sect, rp->or_addr);
 | |
| 				newval = oldval + np->on_valu;
 | |
| 				put1( sect, rp->or_addr, (char) newval);
 | |
| 			}
 | |
| 			else
 | |
| 				fprint( STDERR, "do_relo() : bad relocation size\n");
 | |
| 			rp->or_nami = seg_index((np->on_type & S_TYP) - S_MIN);
 | |
| 	 		/* print( 
 | |
| 				"reloc %s adrr=%ld sect=%ld oldval=%ld newval=%ld def = %ld\n",
 | |
| 				np->on_foff+string_area, rp->or_addr, rp->or_sect-S_MIN, oldval, 		newval, np->on_valu);
 | |
| 	  		*/
 | |
| 		}
 | |
| 		if (diff && diff == olddiff) {
 | |
| 			rp[-diff] = rp[0];
 | |
| 		}
 | |
| 	}
 | |
| 	relo -= diff;
 | |
| }
 |