X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=mark.c;h=ebd798353017e057b4f32e3bbfe25b973e4a8afe;hp=a5e1975498d33d3fd155267e957581d795b21907;hb=ace0b549a94110b69ec61442f825fb421b79799a;hpb=b93a2e2f8ade36a09709b4a72b10f3e8228bed2b diff --git a/mark.c b/mark.c index a5e1975..ebd7983 100644 --- 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-2018 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 // @@ -508,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.