home *** CD-ROM | disk | FTP | other *** search
- /* ---------------------------------------------------------------------- */
- /* 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();
- }
-
-