//
// 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-2018 Reboot and Friends
// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
// Source utilised with the kind permission of Landon Dyer
//
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)
w |= symbol->senv << 3;
*wp++ = w >> 8;
- *wp = w;
+ *wp = (uint8_t)w;
}
}
else
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
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)
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);
// Setup pointer for D_long/word/byte macros
chptr = buf;
+ ch_size = 0;
for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext)
{