X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=mark.c;h=d593b21d6997adda8fbf45015fb0672bd48e586d;hp=ed76b4effc9116a5762d65bcbd4f9c73aab9d3bd;hb=d1fe92e22362ab81cdf10f09b4847261f3b9899a;hpb=29dd8f10767ccf362235d6f9e0fbf4f557af3d27 diff --git a/mark.c b/mark.c index ed76b4e..d593b21 100644 --- a/mark.c +++ b/mark.c @@ -19,6 +19,10 @@ LONG mcalloc; // #bytes alloc'd to current mark chunk LONG mcused; // #bytes used in current mark chunk uint16_t curfrom; // Current "from" section +// +// Imports +// +extern int prg_flag; // 1, write ".PRG" relocatable executable //#define DEBUG_IMAGE_MARKING @@ -69,6 +73,21 @@ if (symbol) if (symbol != NULL) flags |= MSYMBOL; + // + // Complain about some things are not allowed in `-p' mode: + // o marks that aren't to LONGs; + // o external references. + // + if (prg_flag) + { + if ((flags & MLONG) == 0) + error("illegal word relocatable (in .PRG mode)"); + + if (symbol != NULL) + errors("illegal external reference (in .PRG mode) to '%s'", + symbol->sname); + } + mcused += sizeof(WORD) + sizeof(LONG); *markptr.wp++ = flags; *markptr.lp++ = loc; @@ -126,6 +145,201 @@ int amark(void) } +/* + * Table to convert from TDB to fixup triad + * + */ +static char mark_tr[] = { + 0, /* (n/a) */ + 2, /* TEXT relocatable */ + 1, 0, /* DATA relocatable */ + 3 /* BSS relocatable */ +}; + + +/* + * Make mark image for Alcyon .o file + * okflag -- 1, ok to deposit reloc information + */ +LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) +{ + MCHUNK * mch; /* -> mark chunk */ + register PTR p; /* source point from within mark chunk */ + WORD from; /* section fixups are currently FROM */ + register WORD w; /* a word (temp) */ + LONG loc; /* location (temp) */ + LONG lastloc; /* last location fixed up (RELMOD) */ + SYM * symbol; /* -> symbols (temp) */ + char * wp; /* pointer into raw relocation information */ + register char * dp; /* deposit point for RELMOD information */ + int firstp; /* 1, first relocation (RELMOD) */ + LONG diff; /* difference to relocate (RELMOD) */ + + if (okflag) + //clear(mp, siz); /* zero relocation buffer */ + memset(mp, 0, siz); /* zero relocation buffer */ + + from = 0; + + for(mch=firstmch; mch!=NULL; mch=mch->mcnext) + { + for(p=mch->mcptr;;) + { + w = *p.wp++; /* w = next mark entry */ + + if (w & MCHEND) /* (end of mark chunk) */ + break; + + /* + * Get mark record + */ + symbol = NULL; + loc = *p.lp++; /* mark location */ + + if (w & MCHFROM) /* maybe change "from" section */ + from = *p.wp++; + + if (w & MSYMBOL) /* maybe includes a symbol */ + symbol = *p.sy++; + + /* + * Compute mark position in relocation information; + * in RELMOD mode, get address of data to fix up. + */ + if (from == DATA) + loc += tsize; + + wp = (char *)(mp + loc); + + if (okflag && (w & MLONG)) /* indicate first word of long */ + { + wp[1] = 5; + wp += 2; + } + + if (symbol) + { + /* + * Deposit external reference + */ + if (okflag) + { + if (w & MPCREL) + w = 6; /* pc-relative fixup */ + else + w = 4; /* absolute fixup */ + + w |= symbol->senv << 3; + *wp++ = w >> 8; + *wp = w; + } + } + else + { + /* + * Deposit section-relative mark; + * in RELMOD mode, fix it up in the chunk, + * kind of like a sleazoid linker. + * + * In RELMOD mode, marks to words (MWORDs) "cannot happen," + * checks are made when mark() is called, so we don't have + * to check again here. + */ + w &= TDB; + + if (okflag) + wp[1] = mark_tr[w]; + else if (prg_flag && (w & (DATA | BSS))) + { + dp = wp; + diff = ((LONG)(*dp++ & 0xff)) << 24; + diff |= ((LONG)(*dp++ & 0xff)) << 16; + diff |= ((LONG)(*dp++ & 0xff)) << 8; + diff |= (LONG)(*dp & 0xff); + +#ifdef DO_DEBUG + DEBUG printf("diff=%lx ==> ", diff); +#endif + diff += sect[TEXT].sloc; + + if (w == BSS) + diff += sect[DATA].sloc; + + dp = wp; + *dp++ = (char)(diff >> 24); + *dp++ = (char)(diff >> 16); + *dp++ = (char)(diff >> 8); + *dp = (char)diff; +#ifdef DO_DEBUG + DEBUG printf("%lx\n", diff); +#endif + } + } + } + } + + /* + * Generate ".PRG" relocation information in place in + * the relocation words (the ``RELMOD'' operation). + */ + if (okflag && prg_flag) + { + firstp = 1; + wp = mp; + dp = mp; + + for(loc=0; loc> 24); + *dp++ = (char)(loc >> 16); + *dp++ = (char)(loc >> 8); + *dp++ = (char)loc; + firstp = 0; + } + else + { + for(diff=loc-lastloc; diff>254; diff-= 254) + *dp++ = 1; + + *dp++ = (char)diff; + } + + wp += 4; + lastloc = loc; + loc += 4; + } + else + { + loc += 2; + wp += 2; + } + } + + /* + * Terminate relocation list with 0L (if there was no + * relocation) or 0.B (if relocation information was + * written). + */ + if (!firstp) + *dp++ = 0; + else for (firstp = 0; firstp < 4; ++firstp) + *dp++ = 0; + + /* + * Return size of relocation information + */ + loc = dp - mp; + return loc; + } + + return siz; +} + + // // Make mark image for BSD .o file // @@ -336,3 +550,4 @@ printf(" rsize = $%X\n", rsize); return siz; } +