This commit is contained in:
Scott Duensing 2026-08-14 18:02:43 -05:00
parent 4a13f9df26
commit 094d8503e6

View file

@ -431,6 +431,7 @@ struct Imm24Site {
static std::vector<Imm24Site> gImm24Sites; static std::vector<Imm24Site> gImm24Sites;
static uint32_t gTextBaseForSites = 0; static uint32_t gTextBaseForSites = 0;
static bool gRecordSites = false; static bool gRecordSites = false;
static unsigned long gBank0DataSites = 0;
// --report-self-mod: audit diagnostic. Reports every intra-.text-section // --report-self-mod: audit diagnostic. Reports every intra-.text-section
// IMM16 reference made with a STORE opcode (absolute, DBR-relative) into the // IMM16 reference made with a STORE opcode (absolute, DBR-relative) into the
@ -792,6 +793,32 @@ static void applyTextReloc(std::vector<uint8_t> &buf, uint32_t off,
// per-seg list for seg 1, since rodata is in seg 1's bank by // per-seg list for seg 1, since rodata is in seg 1's bank by
// design). // design).
if (targetSeg == 0) { if (targetSeg == 0) {
// BANK-0 DATA/BSS target (inside SEG1's payload) referenced from an overflow segment: the
// GS/OS Loader honors at most PAGE alignment (it ignores OMF ALIGN=$10000), so seg1 loads
// at an arbitrary in-bank offset and every baked data operand from another segment misses
// by that offset (measured live on the RetroNet IIgs client: functions packed into seg1
// worked, everything else read/wrote unowned memory - MAME memory-tap proven). Emit
// cINTERSEG records against seg 1 so the Loader writes the true placed address: 3 bytes
// for IMM24/DATA32, 2 for IMM16 (bank comes from DBR - BANKSIZE=$10000 keeps seg1 within
// one bank), 2+shift16 for BANK16.
if (gRecordSites && patchSeg >= 1 && !segments.empty() &&
(rtype == R_W65816_IMM24 || rtype == R_W65816_DATA32 ||
rtype == R_W65816_IMM16 || rtype == R_W65816_BANK16) &&
(target & 0xFF0000u) == 0u && target != 0u) {
uint8_t cnt = (rtype == R_W65816_IMM24 || rtype == R_W65816_DATA32) ? 3 : 2;
for (uint8_t i = 0; i < cnt; ++i)
buf[off + i] = 0;
InterImm24Site s;
s.patchSeg = static_cast<uint16_t>(patchSeg);
s.patchOff = static_cast<uint16_t>(patchAddr - pseg.base);
s.targetSeg = 1;
s.targetOff = static_cast<uint16_t>(target);
s.byteCnt = cnt;
s.bitShift = (rtype == R_W65816_BANK16) ? 16 : 0;
gInterImm24Sites.push_back(s);
gBank0DataSites++;
return;
}
applyReloc(buf, off, patchAddr, target, rtype, symName); applyReloc(buf, off, patchAddr, target, rtype, symName);
// Also push into the per-seg list with the same gates as // Also push into the per-seg list with the same gates as
// recordCRelocSite (target in same bank as textBase and // recordCRelocSite (target in same bank as textBase and
@ -2563,6 +2590,7 @@ int main(int argc, char **argv) {
linker.writeMultiSegment(outPath, linker.manifestPath, "__start"); linker.writeMultiSegment(outPath, linker.manifestPath, "__start");
} }
std::fprintf(stderr, "link816: %lu bank0-data cINTERSEG sites\n", gBank0DataSites);
std::fprintf(stderr, std::fprintf(stderr,
"linked: text=[0x%04x+%u] rodata=[0x%04x+%u] bss=[0x%04x+%u] " "linked: text=[0x%04x+%u] rodata=[0x%04x+%u] bss=[0x%04x+%u] "
"-> %s (%zu bytes)", "-> %s (%zu bytes)",