X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=mark.c;h=d593b21d6997adda8fbf45015fb0672bd48e586d;hp=11fde4fa35f413215a9877fc9c3370d7bbd27ea2;hb=689d9bc6a5776f54995b68ad2493652f55b9d419;hpb=11a78647f7f170e6ea39dd04a3734a359151debb diff --git a/mark.c b/mark.c index 11fde4f..d593b21 100644 --- a/mark.c +++ b/mark.c @@ -3,13 +3,13 @@ // MARK.C - A record of things that are defined relative to any of the sections // Copyright (C) 199x Landon Dyer, 2011-2012 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 -// Source Utilised with the Kind Permission of Landon Dyer +// Source utilised with the kind permission of Landon Dyer // #include "mark.h" #include "error.h" #include "object.h" -#include "risca.h" +#include "riscasm.h" MCHUNK * firstmch; // First mark chunk @@ -17,13 +17,20 @@ MCHUNK * curmch; // Current mark chunk PTR markptr; // Deposit point in current mark chunk LONG mcalloc; // #bytes alloc'd to current mark chunk LONG mcused; // #bytes used in current mark chunk -WORD curfrom; // Current "from" section +uint16_t curfrom; // Current "from" section + +// +// Imports +// +extern int prg_flag; // 1, write ".PRG" relocatable executable + +//#define DEBUG_IMAGE_MARKING // -// Initialize Marker +// Initialize marker // -void init_mark(void) +void InitMark(void) { firstmch = curmch = NULL; mcalloc = mcused = 0; @@ -34,12 +41,12 @@ void init_mark(void) // // Wrap up marker (called after final mark is made) // -void stopmark(void) +void StopMark(void) { if (curmch) { - *markptr.wp = MCHEND; // Mark end of block - curmch->mcused = mcused; // Update #used in mark block + *markptr.wp = MCHEND; // Mark end of block + curmch->mcused = mcused; // Update #used in mark block } } @@ -47,36 +54,55 @@ void stopmark(void) // // Mark a word or longword relocatable // -int rmark(int from, LONG loc, int to, int size, SYM * symbol) +int rmark(uint16_t from, uint32_t loc, uint16_t to, uint16_t size, SYM * symbol) { - WORD w; +#ifdef DEBUG_IMAGE_MARKING +printf("rmark: from=%i, loc=$%X, to=$%X, size=$%x, symbol=$%X\n", from, loc, to, size, symbol); +if (symbol) + printf(" symbol->stype=$%02X, sattr=$%04X, sattre=$%08X, svalue=%i, sname=%s\n", symbol->stype, symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname); +#endif if ((mcalloc - mcused) < MIN_MARK_MEM) amark(); - w = (WORD)(size | to); + uint16_t flags = (size | to); if (from != curfrom) - w |= MCHFROM; + flags |= MCHFROM; if (symbol != NULL) - w |= MSYMBOL; + 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++ = w; + *markptr.wp++ = flags; *markptr.lp++ = loc; - if (w & MCHFROM) + if (flags & MCHFROM) { - *markptr.wp++ = (WORD)from; - curfrom = (WORD)from; + curfrom = from; + *markptr.wp++ = from; mcused += sizeof(WORD); } - if (w & MSYMBOL) + if (flags & MSYMBOL) { *markptr.sy++ = symbol; - mcused += sizeof(LONG); + mcused += sizeof(SYM *); } *markptr.wp = 0x0000; @@ -90,18 +116,19 @@ int rmark(int from, LONG loc, int to, int size, SYM * symbol) // int amark(void) { - MCHUNK * p; +// MCHUNK * p; // Alloc mark block header (and data) and set it up. // p = (MCHUNK *)amem((long)(sizeof(MCHUNK)) + MARK_ALLOC_INCR); - p = (MCHUNK *)malloc(sizeof(MCHUNK) + MARK_ALLOC_INCR); + MCHUNK * p = (MCHUNK *)malloc(sizeof(MCHUNK) + MARK_ALLOC_INCR); p->mcnext = NULL; p->mcalloc = MARK_ALLOC_INCR; p->mcptr.cp = (char *)(((char *)p) + sizeof(MCHUNK)); if (curmch) - { // Link onto previous chunk - *markptr.wp++ = MCHEND; // Mark end of block + { + // Link onto previous chunk + *markptr.wp++ = MCHEND; // Mark end of block curmch->mcused = mcused; curmch->mcnext = p; } @@ -109,7 +136,7 @@ int amark(void) if (!firstmch) firstmch = p; - curmch = p; // Setup global vars + curmch = p; // Setup global vars markptr = p->mcptr; mcalloc = MARK_ALLOC_INCR; mcused = 0; @@ -118,56 +145,258 @@ 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 // -LONG bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg) +uint32_t bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg) { - MCHUNK * mch; // Mark chunk - PTR p; // Source point from within mark chunk - WORD from; // Section fixups are currently FROM - WORD w; // A word (temp) - LONG loc; // Location (temp) - SYM * symbol; // Symbols (temp) - char * wp; // Pointer into raw relocation info - char * dp; // Deposit point for RELMOD info - LONG diff; // Difference to relocate (RELMOD) - LONG raddr, rflag = 0; // BSD relocation address and flags - LONG rsize; // Relocation size - int validsegment = 0; // Valid segment being processed - - rsize = 0; // Initialise relocation size + MCHUNK * mch; // Mark chunk + PTR p; // Source point from within mark chunk + uint16_t from; // Section fixups are currently FROM + uint16_t w; // A word (temp) + uint32_t loc; // Location (temp) + SYM * symbol; // Symbols (temp) + uint8_t * wp; // Pointer into raw relocation info + uint8_t * dp; // Deposit point for RELMOD info + uint32_t diff; // Difference to relocate (RELMOD) + uint32_t raddr, rflag = 0; // BSD relocation address and flags + uint32_t rsize; // Relocation size + int validsegment = 0; // Valid segment being processed + +#ifdef DEBUG_IMAGE_MARKING +printf("bsdmarkimg():\n"); +#endif + // Initialise relocation size + rsize = 0; chptr = mp; - from = 0; - for(mch = firstmch; mch != NULL; mch = mch->mcnext) + + for(mch=firstmch; mch!=NULL; mch=mch->mcnext) { for(p=mch->mcptr;;) { - w = *p.wp++; // Next mark entry + w = *p.wp++; // Next mark entry if (w & MCHEND) - break; // End of mark chunk + break; // End of mark chunk // Get mark record symbol = NULL; - loc = *p.lp++; // Mark location + loc = *p.lp++; // Mark location if (w & MCHFROM) - { // Maybe change "from" section + { + // Maybe change "from" section from = *p.wp++; if (obj_format == BSD) { if (reqseg == TEXT) - { // Requested segment is TEXT + { + // Requested segment is TEXT if (from == TEXT) validsegment = 1; else validsegment = 0; } else - { // Requested segment is DATA + { + // Requested segment is DATA if (from == DATA) validsegment = 1; else @@ -176,23 +405,34 @@ LONG bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg) } } - if (w & MSYMBOL) // Maybe includes a symbol + if (w & MSYMBOL) // Maybe includes a symbol symbol = *p.sy++; if (obj_format == BSD) { - raddr = loc; // Set relocation address + raddr = loc; // Set relocation address if (validsegment) - D_long(raddr); // Write relocation address +#ifdef DEBUG_IMAGE_MARKING +{ +printf(" validsegment: raddr = $%08X\n", raddr); +#endif + D_long(raddr); // Write relocation address +#ifdef DEBUG_IMAGE_MARKING +} +#endif if (w & MPCREL) - rflag = 0x000000A0; // PC-relative fixup + rflag = 0x000000A0; // PC-relative fixup else - rflag = 0x00000040; // Absolute fixup + rflag = 0x00000040; // Absolute fixup +// This flag tells the linker to WORD swap the LONG when doing the fixup. if (w & MMOVEI) +//{ +//printf("bsdmarkimg: ORing $01 to rflag (MMOVEI) [symbol=%s]...\n", symbol->sname); rflag |= 0x00000001; +//} } // Compute mark position in relocation information; @@ -200,23 +440,32 @@ LONG bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg) if (from == DATA) loc += tsize; - wp = (char *)(mp + loc); + wp = (uint8_t *)(mp + loc); if (symbol) { // Deposit external reference if (obj_format == BSD) { - rflag |= 0x00000010; // Set external reloc flag bit - rflag |= (symbol->senv << 8); // Put symbol index in flags + rflag |= 0x00000010; // Set external reloc flag bit + rflag |= (symbol->senv << 8); // Put symbol index in flags +// Looks like this is completely unnecessary (considering it does the wrong thing!) +#if 0 if (symbol->sattre & RISCSYM) +{ +printf("bsdmarkimg: ORing $01 to rflag (RISCSYM) [symbol=%s]...\n", symbol->sname); rflag |= 0x00000001; +} +#endif if (validsegment) { - D_long(rflag); // Write relocation flags - rsize += 8; // Increment relocation size +#ifdef DEBUG_IMAGE_MARKING +printf(" validsegment(2): rflag = $%08X\n", rflag); +#endif + D_long(rflag); // Write relocation flags + rsize += 8; // Increment relocation size } } } @@ -224,7 +473,10 @@ LONG bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg) { if (obj_format == BSD) { - w &= TDB; // Set reloc flags to segment +#ifdef DEBUG_IMAGE_MARKING +printf(" w = $%04X\n", w); +#endif + w &= TDB; // Set reloc flags to segment switch (w) { @@ -235,8 +487,11 @@ LONG bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg) if (validsegment) { - D_long(rflag); // Write relocation flags - rsize += 8; // Increment relocation size +#ifdef DEBUG_IMAGE_MARKING +printf(" validsegment(3): rflag = $%08X\n", rflag); +#endif + D_long(rflag); // Write relocation flags + rsize += 8; // Increment relocation size } w &= TDB; @@ -245,12 +500,15 @@ LONG bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg) { if (w & (DATA|BSS)) { - dp = objimage + BSDHDRSIZE + loc; + dp = objImage + BSDHDRSIZE + loc; diff = ((LONG)(*dp++ & 0xFF)) << 24; diff |= ((LONG)(*dp++ & 0xFF)) << 16; diff |= ((LONG)(*dp++ & 0xFF)) << 8; diff |= (LONG)(*dp & 0xFF); DEBUG printf("diff=%ux ==> ", diff); +#ifdef DEBUG_IMAGE_MARKING +printf(" validsegment(4): diff = $%08X --> ", diff); +#endif if (rflag & 0x01) diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000); @@ -263,12 +521,15 @@ LONG bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg) if (rflag & 0x01) diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000); - dp = objimage + BSDHDRSIZE + loc; + dp = objImage + BSDHDRSIZE + loc; *dp++ = (char)(diff >> 24); *dp++ = (char)(diff >> 16); *dp++ = (char)(diff >> 8); *dp = (char)diff; DEBUG printf("%ux\n", diff); +#ifdef DEBUG_IMAGE_MARKING +printf("$%08X\n", diff); +#endif } } } @@ -278,7 +539,15 @@ LONG bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg) // Return relocation size if (obj_format == BSD) +#ifdef DEBUG_IMAGE_MARKING +{ +printf(" rsize = $%X\n", rsize); +#endif return rsize; +#ifdef DEBUG_IMAGE_MARKING +} +#endif return siz; } +