]> Shamusworld >> Repos - rmac/blobdiff - mark.c
New directive: PRGFLAGS sets GEMDOS PRG flags (such as Fastload, etc)
[rmac] / mark.c
diff --git a/mark.c b/mark.c
index 0ca98f0f033c2e8b6773a3dc3497b0b6507a6bf1..d593b21d6997adda8fbf45015fb0672bd48e586d 100644 (file)
--- 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,16 +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
-uint16_t 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;
@@ -37,7 +41,7 @@ void init_mark(void)
 //
 // Wrap up marker (called after final mark is made)
 //
-void stopmark(void)
+void StopMark(void)
 {
        if (curmch)
        {
@@ -54,8 +58,9 @@ int rmark(uint16_t from, uint32_t loc, uint16_t to, uint16_t size, SYM * symbol)
 {
 #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
-//     uint16_t w;
 
        if ((mcalloc - mcused) < MIN_MARK_MEM)
                amark();
@@ -68,6 +73,21 @@ printf("rmark: from=%i, loc=$%X, to=$%X, size=$%x, symbol=$%X\n", from, loc, to,
        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;
@@ -125,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<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
 //
@@ -212,8 +427,12 @@ printf(" validsegment: raddr = $%08X\n", raddr);
                                else
                                        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;
@@ -231,8 +450,14 @@ printf(" validsegment: raddr = $%08X\n", raddr);
                                        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)
                                        {
@@ -275,7 +500,7 @@ printf("  validsegment(3): rflag = $%08X\n", rflag);
                                        {
                                                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;
@@ -296,7 +521,7 @@ printf("  validsegment(4): diff = $%08X --> ", diff);
                                                        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);
@@ -325,3 +550,4 @@ printf("  rsize = $%X\n", rsize);
 
        return siz;
 }
+