]> Shamusworld >> Repos - rmac/blobdiff - mark.c
Version bump for last commit. ;-)
[rmac] / mark.c
diff --git a/mark.c b/mark.c
index d3b827aede1bc00a44dae7080aebaeafa6ce47e5..d593b21d6997adda8fbf45015fb0672bd48e586d 100644 (file)
--- a/mark.c
+++ b/mark.c
@@ -3,26 +3,34 @@
 // 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
 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;
@@ -33,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
        }
 }
 
@@ -46,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;
@@ -89,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;
        }
@@ -108,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;
@@ -117,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<siz;)
+               {
+                       if ((wp[1] & 7) == 5)
+                       {
+                               if (firstp)
+                               {
+                                       *dp++ = (char)(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
@@ -175,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;
@@ -199,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
                                        }
                                }
                        }
@@ -223,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)
                                        {
@@ -234,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;
@@ -244,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);
@@ -262,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
                                                }
                                        }
                                }
@@ -277,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;
 }
+