From e359b736ef1cb46deb56739a9a59e361b919f043 Mon Sep 17 00:00:00 2001 From: ggn Date: Mon, 4 Dec 2023 18:00:34 +0200 Subject: [PATCH] Partial fix for #223 - calculating expressions with labels in different sections --- expr.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ sect.c | 10 +++++++++- sect.h | 1 + 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/expr.c b/expr.c index e597257..185e54d 100644 --- a/expr.c +++ b/expr.c @@ -582,6 +582,7 @@ be converted from a linked list into an array). return evexpr(otk, a_value, a_attr, a_esym); } +extern int fixups_active; // // Evaluate expression. // If the expression involves only ONE external symbol, the expression is @@ -711,6 +712,49 @@ int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) } else { + if (fixups_active) + { + // This code addresses a very specific issue found when + // assembling code in ALCYON mode and outputting ST PRG + // binaries. At the time of assembling the start of + // TEXT, DATA and BSS is 0 based. This is because we + // have no idea how big TEXT's size is going to be in order + // to know what's the offset of DATA (same for BSS). + // In general, most cases are handled during fixups as + // at that point everything is known, so we can adjust the + // address of labels etc etc. But in the case of calculating + // an expression where some of its parts are in one section + // and some in another, then this won't work. Since we + // most likely are going to encounter expressions that + // subtract cross-section labels (at least I cannot think + // of any other use case), we add checks for these cases + // here but only when fixups are happening. This will + // simply add the start of a DATA or BSS label to it + // before doing the subtraction, so then the distance + // between the two labels will be calculated correctly. + // Note that this doesn't work if the labels are fixed + // up before this stage. + if ((sattr[0] & TDB) && (sattr[1] & TDB) && (sattr[0] & TDB) != (sattr[1] & TDB)) + { + if (sattr[0] & DATA) + { + sval[0] += sect[TEXT].sloc; + } + else if (sattr[0] & BSS) + { + sval[0] += sect[TEXT].sloc + sect[DATA].sloc; + } + if (sattr[1] & DATA) + { + sval[1] += sect[TEXT].sloc; + } + else if (sattr[1] & BSS) + { + sval[1] += sect[TEXT].sloc + sect[DATA].sloc; + } + } + } + *sval -= sval[1]; } diff --git a/sect.c b/sect.c index 12f9c89..5d7124c 100644 --- a/sect.c +++ b/sect.c @@ -29,6 +29,9 @@ void SwitchSection(int); SECT sect[NSECTS]; // All sections... int cursect; // Current section number +// Globals +int fixups_active = 0; // Give a heads up to expr() because it might need to take some special measures + // These are copied from the section descriptor, the current code chunk // descriptor and the current fixup chunk descriptor when a switch is made into // a section. They are copied back to the descriptors when the section is left. @@ -540,7 +543,7 @@ int ResolveFixups(int sno) { case TEXT: // Shouldn't there be a break here, since otherwise, it will point to the DATA section? -// break; + break; case DATA: eval += sect[TEXT].sloc; break; @@ -1044,6 +1047,11 @@ int ResolveAllFixups(void) if (glob_flag) ForceUndefinedSymbolsGlobal(); + if (prg_flag) + { + fixups_active = 1; + } + DEBUG printf("Resolving TEXT sections...\n"); ResolveFixups(TEXT); DEBUG printf("Resolving DATA sections...\n"); diff --git a/sect.h b/sect.h index 833217b..0ebca4a 100644 --- a/sect.h +++ b/sect.h @@ -200,6 +200,7 @@ extern int cursect; extern SECT sect[]; extern uint32_t challoc; extern CHUNK * scode; +extern int fixups_active; // Prototypes void InitSection(void); -- 2.40.1.windows.1