]> Shamusworld >> Repos - rmac/blobdiff - mark.c
Version bump for last patch; now at v1.13.4.
[rmac] / mark.c
diff --git a/mark.c b/mark.c
index 70f90fde4ab4e3fd26fdb2134fd22e645bb191e5..a5e1975498d33d3fd155267e957581d795b21907 100644 (file)
--- a/mark.c
+++ b/mark.c
@@ -1,7 +1,7 @@
 //
-// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
+// 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-2012 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2018 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)
@@ -90,16 +90,13 @@ if (symbol)
 
        //
        // Complain about some things are not allowed in '-p' (PRG) mode:
-       //  o Marks that aren't to LONGs
-       //  o External references
+       //  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'",
+                       error("illegal external reference (in .PRG mode) to '%s'",
                                symbol->sname);
        }
 
@@ -224,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,6 +377,16 @@ printf(" validsegment: raddr = $%08X\n", loc);
                        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)
                        {
                                // Deposit external reference
@@ -412,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 = GETBE32(dp, 0);
+                                       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)
@@ -433,7 +452,41 @@ printf("  validsegment(4): diff = $%08X --> ", diff);
                                        if (rflag & 0x01)
                                                diff = WORDSWAP32(diff);
 
-                                       SETBE32(dp, 0, diff);
+                                       // Make sure to deposit the correct size payload
+                                       // N.B.: The braces around the SETBExx macros are needed
+                                       //       because the macro supplies its own set of braces,
+                                       //       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)               // 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);
+                                       }
+
                                        DEBUG printf("%uX\n", diff);
 #ifdef DEBUG_IMAGE_MARKING
 printf("$%08X\n", diff);
@@ -466,6 +519,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)
        {
@@ -531,7 +585,7 @@ uint32_t CreateELFRelocationRecord(uint8_t * buf, uint8_t * secBuf, uint16_t sec
 
                                // Deposit the relocation record
                                D_long(r_offset);
-                               D_long((r_sym << 8) | r_type);
+                               D_long(((r_sym << 8) | r_type));
                                D_long(r_addend);
                                rsize += 0x0C;
                        }