X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=sect.c;h=4dc7032c4c34a7834626589daf4f9eefa6c0df82;hp=49806a02b9d4e8d7570b19b5d27f35ca89b6dc86;hb=4205233c8397c581b4d27ab36ab81ec896ef3dd0;hpb=29fa5dcf504b966803063a1c2891f58f97126d04 diff --git a/sect.c b/sect.c index 49806a0..4dc7032 100644 --- a/sect.c +++ b/sect.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for all Atari computers // SECT.C - Code Generation, Fixups and Section Management -// Copyright (C) 199x Landon Dyer, 2011-2019 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 // @@ -159,7 +159,7 @@ void SaveSection(void) sp->sloc = sloc; sp->orgaddr = orgaddr; - if (scode != NULL) // Bailout code chunk + if (scode != NULL) // Bailout code chunk (if any) scode->ch_size = ch_size; } @@ -218,29 +218,43 @@ void chcheck(uint32_t amt) DEBUG { printf(" amt (adjusted)=%u\n", amt); } SECT * p = §[cursect]; CHUNK * cp = malloc(sizeof(CHUNK) + amt); + int first = 0; - // First chunk in section if (scode == NULL) { + // First chunk in section cp->chprev = NULL; p->sfcode = cp; + first = 1; } - // Add chunk to other chunks else { + // Add second and on to previous chunk cp->chprev = scode; scode->chnext = cp; scode->ch_size = ch_size; // Save old chunk's globals } // Setup chunk and global vars - cp->chloc = sloc; +/* +So, whenever there's an ORG in a 56K section, it sets sloc TO THE ADDRESS IN THE ORG. Also, the loc/sloc are incremented by 1s, which means to alias correctly to the byte-oriented memory model we have here, we have to fix that kind of crap. +*/ + cp->chloc = sloc; // <-- HERE'S THE PROBLEM FOR 56K :-/ cp->chnext = NULL; challoc = cp->challoc = amt; ch_size = cp->ch_size = 0; chptr = cp->chptr = ((uint8_t *)cp) + sizeof(CHUNK); scode = p->scode = cp; + // A quick kludge +/* +OK, so this is a bit shite, but at least it gets things working the way they should. The right way to do this is not rely on sloc & friends for the right fixup address but to have an accurate model of the thing. That will probably come with v2.0.1 :-P + +So the problem is, d_org sets sloc to the address of the ORG statement, and that gives an incorrect base for the fixup. And so when a second (or later) chunk is allocated, it gets set wrong. Further complicating things is that the orgaddress *does not* get used in a typical way with the DSP56001 code, and, as such, causes incorrect addresses to be generated. All that has to be dealt with in order to get this right and do away with this kludge. +*/ + if (((cursect == M56001P) || (cursect == M56001X) || (cursect == M56001Y)) && !first) + cp->chloc = cp->chprev->chloc + cp->chprev->ch_size; + return; } @@ -276,7 +290,7 @@ int AddFixup(uint32_t attr, uint32_t loc, TOKEN * fexpr) { attr |= FU_56001; // Save the exact spot in this chunk where the fixup should go - _orgaddr = chptr - scode->chptr; + _orgaddr = chptr - scode->chptr + scode->chloc; } // Allocate space for the fixup + any expression @@ -398,6 +412,7 @@ int ResolveFixups(int sno) // Complex expression if (dw & FU_EXPR) { + // evexpr presumably issues the errors/warnings here if (evexpr(fup->expr, &eval, &eattr, &esym) != OK) continue; } @@ -415,6 +430,8 @@ int ResolveFixups(int sno) // If the symbol is not defined, but global, set esym to sy if ((eattr & (GLOBAL | DEFINED)) == GLOBAL) esym = sy; + + DEBUG { printf(" name: %s, value: $%" PRIX64 "\n", sy->sname, sy->svalue); } } uint16_t tdb = eattr & TDB; @@ -438,12 +455,18 @@ int ResolveFixups(int sno) // // PC-relative fixups must be DEFINED and either in the same section // (whereupon the subtraction takes place) or ABS (with no subtract). - if (dw & FU_PCREL) + if ((dw & FU_PCREL) || (dw & FU_PCRELX)) { if (eattr & DEFINED) { if (tdb == sno) + { eval -= loc; + + // In this instruction the PC is located a DWORD away + if (dw & FU_PCRELX) + eval += 2; + } else if (tdb) { // Allow cross-section PCREL fixups in Alcyon mode @@ -466,6 +489,10 @@ int ResolveFixups(int sno) } eval -= loc; + + // In this instruction the PC is located a DWORD away + if (dw & FU_PCRELX) + eval += 2; } else { @@ -478,8 +505,15 @@ int ResolveFixups(int sno) warn("unoptimized short branch"); } else if (obj_format == MWC) + { eval -= loc; + // In this instruction the PC is located a DWORD away + if (dw & FU_PCRELX) + eval += 2; + } + + // Be sure to clear any TDB flags, since we handled it just now tdb = 0; eattr &= ~TDB; }