/* ---------------------------------------------------------------------- */ /* Copyright (C) 1991 by Natuerlich! */ /* This file is copyrighted! */ /* Refer to the documentation for details. */ /* ---------------------------------------------------------------------- */ #define LINKER 1 #include "defines.h" #include "nasm.h" #include "debug.h" #include "labels.h" #include "object.h" #include "seg.h" #include "imm.h" #include OSBIND #include NMALLOC_H #include "process.h" #include "exprfast.h" #include "ldebug.h" #if ! VERSION extern char x1[], x2[], x3[], x4[], x5[]; #endif extern byte huge *__program, huge *__p, huge *ptohead; extern byte __c; extern word __pc, __x; extern lword __lx; extern imm huge *hip, huge *cip; extern seg huge *h_seg, huge *sp; extern int relocatable, bootable, pageflag; extern word alignment, origin; extern byte huge *pb; extern e_dropped huge *pe; extern s_dropped huge *ps; extern linksymbol huge *py; extern i_dropped huge *pi; extern r_dropped huge *pr; extern f_dropped huge *pf; extern lword bytes, sbytes, ibytes, rbytes, ebytes, ybytes, fbytes; extern word endpc, diff; ref huge *rhead; seg huge **pas; imm huge **pai; expr huge **pae; void seg_link() { extern word plus1; register s_dropped huge *p = ps; register seg huge **q; word i, index; ENTER("seg_link"); plus1 = 0; index = (word) (__p - __program); if( ! sp && p->type == S_DS) nerror("You can't start off with a .DS segment"); pas = q = nmalloc( sbytes * sizeof( seg *)); for( i = (word) sbytes; i; i--, p++) { /* V--- changin' the val of s_dropped as well */ build_seg( p->index + index, p->type, p->size); endpc += p->size; *q++ = sp; POINTER_CHECK( q[-1]); } LEAVE(); } static byte sizetab[256] = { 1,2,0,0,2,2,2,0, 1,2,1,0,3,3,3,0, 2,2,2,0,2,2,2,0, 1,3,1,0,3,3,3,0, 3,2,0,0,2,2,2,0, 1,2,1,0,3,3,3,0, 2,2,2,0,2,2,2,0, 1,3,1,0,3,3,3,0, 1,2,0,0,0,2,2,0, 1,2,1,0,3,3,3,0, 2,2,2,0,0,2,2,0, 1,3,1,0,0,3,3,0, 1,2,0,0,2,2,2,0, 1,2,1,0,3,3,3,0, 2,2,2,0,2,2,2,0, 1,3,1,0,3,3,3,0, 2,2,0,0,2,2,2,0, 1,0,1,0,3,3,3,0, 2,2,2,0,2,2,2,0, 1,3,1,0,3,3,3,0, 2,2,2,0,2,2,2,0, 1,2,1,0,3,3,3,0, 2,2,2,0,2,2,2,0, 1,3,1,0,3,3,3,0, 2,2,0,0,2,2,2,0, 1,2,1,0,3,3,3,0, 2,2,2,0,0,2,2,0, 1,3,1,0,0,3,3,0, 2,2,0,0,2,2,2,0, 1,2,1,0,3,3,3,0, 2,2,2,0,0,2,2,0, 1,3,1,0,0,3,3,0 }; void code_reloc() { register s_dropped huge *p = ps; register word rdiff = diff, val, i; register byte huge *src; lword j = sbytes; ENTER("code_reloc"); while( j--) { src = pb + p->index; #if ! VERSION if( j || p->type != S_DS) POINTER_CHECK( src); #endif POINTER_CHECK( p); POINTER_CHECK( __p); i = p->size; switch( p++->type) { case S_RCODE : while( i--) switch( sizetab[ *src]) { case 0 : nferror("object code is impure"); case 2 : i--; deposit( *src++); case 1 : deposit( *src++); break; case 3 : deposit( *src++); val = pdpeek( src); if( inrange( val, DEFORG - 1, endpc)) val += rdiff; wdeposit( val); i -= 2; } break; case S_SDATA : while( i--) { deposit( *src++); } continue; case S_RDATA : while( i) { if( val = pdpeek( src)) val += rdiff; wdeposit( val); i -= 2; } break; case S_TDATA : while( i) { if( val = pdpeek( src)) val += rdiff; wddeposit( val); i -= 2; } case S_RSTOP : /* not really implemented */ break; case S_DS : if( ! bootable) { dpoke( ptohead, __pc - 1); __pc += i; dpoke( __p, __pc); _advance( 4); ptohead = __p - 2; } else { register int j; for( j = i; j; j--) { deposit( 0); } } break; default : nierror("Whoa! *Serious* problems with segmentation"); } } LEAVE(); } void imm_link() { register i_dropped huge *p = pi; register imm huge *q; imm huge **x; register word i, tmp; ENTER("imm_link"); x = pai = nmalloc( (ibytes + 1) * sizeof( imm *)); *x++ = 0; for( i = (word) ibytes; i; p++, i--) { *x++ = q = imm_alloc(); POINTER_CHECK( p); POINTER_CHECK( q); q->block = pas[ p->block]; POINTER_CHECK( q->block); if( q->val = p->val) q->val += diff; q->type = p->type; q->offset = p->offset; if( tmp = q->val) { if( q->type) tmp >>= 8; poke( __program + q->block->index + p->offset, tmp); } q->next = 0; cip = hip ? (cip->next = q) : (hip = q); } LEAVE(); } /* This function is just for Debugging */ #if ! VERSION void lerr_imms() { register imm huge *p; if( p = hip) do { POINTER_CHECK( p); if( ! p->val) nierror("There are imms w/o a value"); } while( p = p->next); } #endif void ref_link() { register r_dropped huge *p = pr; register ref huge *q, huge *old; register word i = (word) rbytes; ENTER("ref_link"); if( i = (word) rbytes) { POINTER_CHECK( p); do { q = ref_alloc(); POINTER_CHECK( q); q->ref = (expr *) *p++; /* yet unknown */ q->hacked = 0; old = rhead ? (old->next = q) : (rhead = q); /* That's OK */ } while( --i); q->next = 0; } LEAVE(); ADD_WATCH( &rhead, sizeof( char *), "rhead"); } static void fix_link( p, q, r) register e_dropped huge *p; register expr huge *q; register f_dropped huge *r; { register fix huge *f = fix_alloc(); ENTER("fix_link"); POINTER_CHECK( p); POINTER_CHECK( q); POINTER_CHECK( r); POINTER_CHECK( f); if( q->fix == FIX_LABEL) f->poof.label = (label *) p->t; /* yet unknown */ else f->poof.block = pas[ (word) r->poof]; f->imm = pai[ r->imm]; f->index = r->index; q->zonk.fixp = f; LEAVE(); } void exp_link() { register e_dropped huge *p; register expr huge *q; register ref huge *x; expr huge **y; f_dropped huge *r; register word i; ENTER("exp_link"); if( p = pe) { y = pae = nmalloc( (ebytes + 1) * sizeof( expr *)); *y++ = 0; r = pf; for( i = 1; i <= ebytes; i++, p++) { *y++ = q = exp_alloc(); POINTER_CHECK( p); POINTER_CHECK( q); if( valued( p) && e_pcrel( p)) q->val = p->val + diff; else q->val = p->val; q->aux = p->aux + diff; q->op = p->op; q->label = p->label; q->l = (expr *) p->l; /* yet unknown */ q->r = (expr *) p->r; /* yet unknown */ if( q->fix = p->fix) fix_link( p, q, r++); else q->zonk.t = (expr *) p->t; /* yet unknown */ for( x = rhead; x; x = x->next) if( ! x->hacked && (word) x->ref == i) { POINTER_CHECK( x); POINTER_CHECK( q); x->ref = q; x->hacked = 1; break; } } MESS("the second routine"); { register expr huge *p; register word i; for( i = (word) ebytes, y = pae + 1; i; i--, y++) { p = *y; POINTER_CHECK( p); if( ! p->fix) { #if ! VERSION if( p->hacked & 0x4) nierror("Overwriting pointer with bogus address"); p->hacked |= 0x4; #endif p->zonk.t = pae[ (word) p->zonk.t]; POINTER_CHECK( p->zonk.t); } #if ! VERSION if( p->hacked & 0x3) nierror("Overwriting pointer with bogus address"); p->hacked |= 3; #endif p->l = pae[ (word) p->l]; p->r = pae[ (word) p->r]; POINTER_CHECK( p->l); POINTER_CHECK( p->r); } } } LEAVE(); } /* ---------------------------------------------------------- */ /* The first symbol link stage. What is happening ? */ /* We already hook up the as of yet untabled symbols to the */ /* already pointered ref (excepting of course >>EXPR<<) */ /* ---------------------------------------------------------- */ void sym_link() { register linksymbol huge *p; register ref huge *r, huge *old; register word i,norefs; ENTER("sym_link"); for( r = rhead, p = py, i = (word) ybytes; i; i--, p++) { MESS("loop"); POINTER_CHECK( p); INTEGRITY_CHECK(); if( norefs = (lword) p->refs) { MESS("-de-loop"); for( p->refs = r; norefs > 1; r = r->next, norefs--); POINTER_CHECK( r); old = r; r = r->next; POINTER_CHECK( r); old->next = 0; } else if( ! (p->type & L_ZERO)) { MESS("-and-loop"); POINTER_CHECK( p); INTEGRITY_CHECK(); p->val += diff; /* Else update the value */ INTEGRITY_CHECK(); } } DEL_WATCH( &rhead); LEAVE(); } #define l_unvalued( x) (x)->refs #define l_valued( x) ! l_unvalued( x) void sym2_link() { register linksymbol huge *p = py; register label huge *q; register lword i = ybytes; char *s; ENTER("sym2_link"); while( i--) { MESS("A"); POINTER_CHECK( p); s = str_alloc( SIGNIFICANT + 1); /* improve dat */ { register char huge *src = p->name, huge *dst = s; #if SIGNIFICANT == 8 *dst++ = *src++; /* SIGNIFICANT == 8 */ *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst =0; #else register int j = SIGNIFICANT; while( j--) *dst++ = *src++; *dst = 0; #endif } if( ! (q = find_label( s))) (q = enter_llabel( s, p->val, p->type))->refs = p->refs; else if( ! (q->type & p->type & L_MASK1)) nserror( "label type mismatch", s); else if( l_valued( q)) if( l_valued( p)) nserror("Doubly defined labeled", s); else { POINTER_CHECK( q); /* Case: LABEL has value, we got some refs */ q->refs = p->refs; entrefer( q); } else if( l_valued( p)) { POINTER_CHECK( q); /* Case: Label has refs, we got the value */ q->val = p->val; entrefer( q); } else { /* Just append our reflist */ register ref huge *x = q->refs; POINTER_CHECK( q); while( x->next) x = x->next; POINTER_CHECK( x); x->next = p->refs; } LABEL_CHECK( q); if( l_unvalued( p)) { register word i; fix huge *f; for( i = (word) ebytes; i; i--) if( pae[i]->fix == FIX_LABEL && ! (f = pae[i]->zonk.fixp)->hacked && (word) f->poof.label == p->no) { POINTER_CHECK( f); POINTER_CHECK( q); f->poof.label = q; f->hacked = 1; break; } } p++; } LEAVE(); }