//
// 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-2018 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2019 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)
// 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
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)
// 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);
}