home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 1
/
crawlyvol1.bin
/
program
/
compiler
/
nasm20b
/
nasm_src
/
link.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-19
|
13KB
|
525 lines
/* ---------------------------------------------------------------------- */
/* 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();
}