]> Shamusworld >> Repos - rmac/blobdiff - mark.c
Fix a small buglet in the last patch. :-)
[rmac] / mark.c
diff --git a/mark.c b/mark.c
index 955fcab0c7a81d0535c4e06b625be8dab1fae07a..ebd798353017e057b4f32e3bbfe25b973e4a8afe 100644 (file)
--- a/mark.c
+++ b/mark.c
@@ -1,7 +1,7 @@
 //
 // RMAC - Reboot's Macro Assembler for all Atari computers
 // MARK.C - A record of things that are defined relative to any of the sections
-// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2020 Reboot and Friends
 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
 // Source utilised with the kind permission of Landon Dyer
 //
@@ -71,9 +71,9 @@ void StopMark(void)
 uint32_t MarkRelocatable(uint16_t section, uint32_t loc, uint16_t to, uint16_t flags, SYM * symbol)
 {
 #ifdef DEBUG_IMAGE_MARKING
-printf("MarkRelocatable: section=%i, loc=$%X, to=$%X, flags=$%x, symbol=$%X\n", section, loc, to, flags, symbol);
+printf("MarkRelocatable: section=%i, loc=$%X, to=$%X, flags=$%x, symbol=%p\n", section, loc, to, flags, 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);
+       printf("      symbol->stype=$%02X, sattr=$%04X, sattre=$%08X, svalue=%li, sname=%s\n", symbol->stype, symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname);
 #endif
 
        if ((mcalloc - mcused) < MIN_MARK_MEM)
@@ -221,7 +221,7 @@ uint32_t MarkImage(register uint8_t * mp, uint32_t siz, uint32_t tsize, int okfl
 
                                        w |= symbol->senv << 3;
                                        *wp++ = w >> 8;
-                                       *wp = w;
+                                       *wp = (uint8_t)w;
                                }
                        }
                        else
@@ -380,9 +380,13 @@ printf(" validsegment: raddr = $%08X\n", loc);
                        // This tells the linker to do a WORD relocation (otherwise it
                        // defaults to doing a LONG, throwing things off for WORD sized
                        // fixups)
-                       if (!(w & MLONG))
+                       if (!(w & (MLONG | MQUAD)))
                                rflag |= 0x00000002;
 
+                       // Tell the linker that the fixup is an OL QUAD data address
+                       if (w & MQUAD)
+                               rflag |= 0x00000004;
+
                        if (symbol != NULL)
                        {
                                // Deposit external reference
@@ -415,19 +419,31 @@ printf("  validsegment(3): rflag = $%08X\n", rflag);
                                if (w & (DATA | BSS))
                                {
                                        uint8_t * dp = objImage + BSDHDRSIZE + loc;
+                                       uint32_t olBitsSave = 0;
 
                                        // Bump the start of the section if it's DATA (& not TEXT)
                                        if (from == DATA)
                                                dp += tsize;
 
                                        uint32_t diff = (rflag & 0x02 ? GETBE16(dp, 0) : GETBE32(dp, 0));
+
+                                       // Special handling for OP (data addr) relocation...
+                                       if (rflag & 0x04)
+                                       {
+                                               olBitsSave = diff & 0x7FF;
+                                               diff = (diff & 0xFFFFF800) >> 8;
+                                       }
+
                                        DEBUG printf("diff=%uX ==> ", diff);
 #ifdef DEBUG_IMAGE_MARKING
-printf("  validsegment(4): diff = $%08X --> ", diff);
+printf("  validsegment(4): diff = $%08X ", diff);
 #endif
                                        if (rflag & 0x01)
                                                diff = WORDSWAP32(diff);
 
+#ifdef DEBUG_IMAGE_MARKING
+printf("(sect[TEXT].sloc=$%X) --> ", sect[TEXT].sloc);
+#endif
                                        diff += sect[TEXT].sloc;
 
                                        if (w == BSS)
@@ -442,11 +458,31 @@ printf("  validsegment(4): diff = $%08X --> ", diff);
                                        //       thus leaving a naked semicolon afterwards to
                                        //       screw up the if/else structure. This is the price
                                        //       you pay when using macros pretending to be code.
-                                       if (rflag & 0x02)
+                                       if (rflag & 0x02)               // WORD relocation
                                        {
                                                SETBE16(dp, 0, diff);
                                        }
-                                       else
+                                       else if (rflag & 0x04)  // OP data address relocation
+                                       {
+                                               // We do it this way because we might have an offset
+                                               // that is not a multiple of 8 and thus we need this in
+                                               // place to prevent a bad address at link time. :-P As
+                                               // a consequence of this, the highest address we can
+                                               // have here is $1FFFF8.
+                                               uint32_t diffsave = diff;
+                                               diff = ((diff & 0x001FFFFF) << 11) | olBitsSave;
+                                               SETBE32(dp, 0, diff);
+                                               // But we need those 3 bits, otherwise we can get in
+                                               // trouble with things like OL data that is in the cart
+                                               // space, and BOOM! So the 2nd phrase of the fixup (it
+                                               // will *always* have a 2nd phrase) has a few spare
+                                               // bits, we chuck them in there.
+                                               uint32_t p2 = GETBE32(dp, 8);
+                                               p2 &= 0x1FFFFFFF;
+                                               p2 |= (diffsave & 0x00E00000) << 8;
+                                               SETBE32(dp, 8, p2);
+                                       }
+                                       else                                    // LONG relocation
                                        {
                                                SETBE32(dp, 0, diff);
                                        }
@@ -472,6 +508,161 @@ printf("  rsize = $%X\n", rsize);
 }
 
 
+//
+// Make mark image for RAW file
+//
+uint32_t MarkABSImage(uint8_t * mp, uint32_t siz, uint32_t tsize, int reqseg)
+{
+       uint16_t from = 0;                      // Section fixups are currently FROM
+       uint32_t rsize = 0;                     // Relocation table size (written to mp)
+       int validsegment = 0;           // We are not yet in a valid segment...
+
+       // Initialize relocation table point (for D_foo macros)
+       chptr = mp;
+
+       // Run through all the relocation mark chunks
+       for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext)
+       {
+               for (PTR p = mch->mcptr;;)
+               {
+                       SYM * symbol = NULL;
+                       uint16_t w = *p.wp++;   // Next mark entry
+
+                       // If we hit the end of a chunk, go get the next one
+                       if (w & MCHEND)
+                               break;
+
+                       // Get the rest of the mark record
+                       uint32_t loc = *p.lp++; // Mark location
+
+                       // Maybe change "from" section
+                       if (w & MCHFROM)
+                       {
+                               from = *p.wp++;
+
+                               if (((reqseg == TEXT) && (from == TEXT))
+                               || ((reqseg == DATA) && (from == DATA)))
+                                       validsegment = 1;
+                               else
+                                       validsegment = 0;
+                       }
+
+                       // Maybe includes a symbol
+                       if (w & MSYMBOL)
+                               symbol = *p.sy++;
+
+                       if (!validsegment)
+                               continue;
+
+                       uint32_t rflag = 0x00000040;    // Absolute relocation
+
+                       if (w & MPCREL)
+                               rflag = 0x000000A0;                     // PC-relative relocation
+
+                       // This flag tells the linker to WORD swap the LONG when doing the
+                       // relocation.
+                       if (w & MMOVEI)
+                               rflag |= 0x00000001;
+
+                       // This tells the linker to do a WORD relocation (otherwise it
+                       // defaults to doing a LONG, throwing things off for WORD sized
+                       // fixups)
+                       if (!(w & (MLONG | MQUAD)))
+                               rflag |= 0x00000002;
+
+                       // Tell the linker that the fixup is an OL QUAD data address
+                       if (w & MQUAD)
+                               rflag |= 0x00000004;
+
+                       if (symbol != NULL)
+                       {
+                               return error("Unresolved symbol when outputting raw image");
+                       }
+                       else
+                       {
+                               w &= TDB;                               // Set reloc flags to segment
+
+                               switch (w)
+                               {
+                               case TEXT: rflag |= 0x00000400; break;
+                               case DATA: rflag |= 0x00000600; break;
+                               case BSS:  rflag |= 0x00000800; break;
+                               }
+
+                               // Fix relocation by adding in start of TEXT segment, since it's
+                               // currently relative to the start of the DATA (or BSS) segment
+                               uint8_t * dp = objImage + loc;
+                               uint32_t olBitsSave = 0;
+
+                               // Bump the start of the section if it's DATA (& not TEXT)
+                               if (from == DATA)
+                                       dp += tsize;
+
+                               uint32_t diff = (rflag & 0x02 ? GETBE16(dp, 0) : GETBE32(dp, 0));
+
+                               if (w & (DATA | BSS))
+                               {
+                                       // Special handling for OP (data addr) relocation...
+                                       if (rflag & 0x04)
+                                       {
+                                               olBitsSave = diff & 0x7FF;
+                                               diff = (diff & 0xFFFFF800) >> 8;
+                                       }
+
+                                       if (rflag & 0x01)
+                                               diff = WORDSWAP32(diff);
+
+                                       diff += sect[TEXT].sloc;
+
+                                       if (w == BSS)
+                                               diff += sect[DATA].sloc;
+                               }
+                               if ((rflag & 0x02) == 0)
+                               {
+                                       diff += org68k_address;
+                               }
+
+                               if (rflag & 0x01)
+                                       diff = WORDSWAP32(diff);
+                
+                               // Make sure to deposit the correct size payload
+                               // Check comments in MarkBSDImage for more candid moments
+                               if (rflag & 0x02)               // WORD relocation
+                               {
+                                       SETBE16(dp, 0, diff);
+                               }
+                               else if (rflag & 0x04)  // OP data address relocation
+                               {
+                                       // We do it this way because we might have an offset
+                                       // that is not a multiple of 8 and thus we need this in
+                                       // place to prevent a bad address at link time. :-P As
+                                       // a consequence of this, the highest address we can
+                                       // have here is $1FFFF8.
+                                       uint32_t diffsave = diff;
+                                       diff = ((diff & 0x001FFFFF) << 11) | olBitsSave;
+                                       SETBE32(dp, 0, diff);
+                                       // But we need those 3 bits, otherwise we can get in
+                                       // trouble with things like OL data that is in the cart
+                                       // space, and BOOM! So the 2nd phrase of the fixup (it
+                                       // will *always* have a 2nd phrase) has a few spare
+                                       // bits, we chuck them in there.
+                                       uint32_t p2 = GETBE32(dp, 8);
+                                       p2 &= 0x1FFFFFFF;
+                                       p2 |= (diffsave & 0x00E00000) << 8;
+                                       SETBE32(dp, 8, p2);
+                               }
+                               else                                    // LONG relocation
+                               {
+                                       SETBE32(dp, 0, diff);
+                               }
+                       }
+               }
+       }
+
+       return OK;
+}
+
+
 //
 // Make relocation record for ELF .o file.
 // Returns the size of the relocation record.
@@ -483,6 +674,7 @@ uint32_t CreateELFRelocationRecord(uint8_t * buf, uint8_t * secBuf, uint16_t sec
 
        // Setup pointer for D_long/word/byte macros
        chptr = buf;
+       ch_size = 0;
 
        for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext)
        {