Compare commits

...

3 Commits

Author SHA1 Message Date
Rangi
ade898d815 List -B in rgbgfx options 2026-01-13 09:46:33 -05:00
Rangi
e738b90c69 Refactor to combine similar functions into one 2026-01-07 16:36:04 -05:00
Rangi
a91d26192d Fix SECTION UNION alignment depending on piece order 2026-01-07 16:36:04 -05:00
7 changed files with 92 additions and 75 deletions

View File

@@ -13,6 +13,7 @@
.Op Fl CmhOuVwXYZ
.Op Fl v Op Fl v No ...
.Op Fl a Ar attrmap | Fl A
.Op Fl B Ar color
.Op Fl b Ar base_ids
.Op Fl c Ar pal_spec
.Op Fl \-color Ar when

View File

@@ -25,90 +25,71 @@ void sect_ForEach(void (*callback)(Section &)) {
}
}
static void checkAgainstFixedAddress(Section const &target, Section const &other, uint16_t org) {
if (target.isAddressFixed) {
if (target.org != org) {
fatalTwoAt(
target,
other,
"Section \"%s\" is defined with address $%04" PRIx16
", but also with address $%04" PRIx16,
target.name.c_str(),
target.org,
other.org
);
static void checkPieceCompat(Section &target, Section const &other, size_t delta) {
assume(other.modifier != SECTION_UNION || delta == 0);
if (other.isAddressFixed) {
uint16_t org = other.org - delta;
if (target.isAddressFixed) {
if (target.org != org) {
fatalTwoAt(
target,
other,
"Section \"%s\" is defined with address $%04" PRIx16
", but also with address $%04" PRIx16,
target.name.c_str(),
target.org,
other.org
);
}
} else if (target.isAlignFixed) {
if ((org - target.alignOfs) & target.alignMask) {
fatalTwoAt(
target,
other,
"Section \"%s\" is defined with %d-byte alignment (offset %" PRIu16
"), but also with address $%04" PRIx16,
target.name.c_str(),
target.alignMask + 1,
target.alignOfs,
other.org
);
}
}
} else if (target.isAlignFixed) {
if ((org - target.alignOfs) & target.alignMask) {
target.isAddressFixed = true;
target.org = org;
} else if (other.isAlignFixed) {
uint32_t ofs = (other.alignOfs - delta) & other.alignMask;
if (target.isAddressFixed) {
if ((target.org - ofs) & other.alignMask) {
fatalTwoAt(
target,
other,
"Section \"%s\" is defined with address $%04" PRIx16
", but also with %d-byte alignment (offset %" PRIu16 ")",
target.name.c_str(),
target.org,
other.alignMask + 1,
other.alignOfs
);
}
} else if (target.isAlignFixed
&& (other.alignMask & target.alignOfs) != (target.alignMask & ofs)) {
fatalTwoAt(
target,
other,
"Section \"%s\" is defined with %d-byte alignment (offset %" PRIu16
"), but also with address $%04" PRIx16,
"), but also with %d-byte alignment (offset %" PRIu16 ")",
target.name.c_str(),
target.alignMask + 1,
target.alignOfs,
other.org
);
}
}
}
static bool checkAgainstFixedAlign(Section const &target, Section const &other, uint32_t ofs) {
if (target.isAddressFixed) {
if ((target.org - ofs) & other.alignMask) {
fatalTwoAt(
target,
other,
"Section \"%s\" is defined with address $%04" PRIx16
", but also with %d-byte alignment (offset %" PRIu16 ")",
target.name.c_str(),
target.org,
other.alignMask + 1,
other.alignOfs
);
}
return false;
} else if (target.isAlignFixed
&& (other.alignMask & target.alignOfs) != (target.alignMask & ofs)) {
fatalTwoAt(
target,
other,
"Section \"%s\" is defined with %d-byte alignment (offset %" PRIu16
"), but also with %d-byte alignment (offset %" PRIu16 ")",
target.name.c_str(),
target.alignMask + 1,
target.alignOfs,
other.alignMask + 1,
other.alignOfs
);
} else {
return !target.isAlignFixed || (other.alignMask > target.alignMask);
}
}
static void checkSectUnionCompat(Section &target, Section &other) {
if (other.isAddressFixed) {
checkAgainstFixedAddress(target, other, other.org);
target.isAddressFixed = true;
target.org = other.org;
} else if (other.isAlignFixed) {
if (checkAgainstFixedAlign(target, other, other.alignOfs)) {
target.isAlignFixed = true;
target.alignMask = other.alignMask;
}
}
}
static void checkFragmentCompat(Section &target, Section &other) {
if (other.isAddressFixed) {
uint16_t org = other.org - target.size;
checkAgainstFixedAddress(target, other, org);
target.isAddressFixed = true;
target.org = org;
} else if (other.isAlignFixed) {
uint32_t ofs = (other.alignOfs - target.size) & other.alignMask;
if (checkAgainstFixedAlign(target, other, ofs)) {
} else if (!target.isAlignFixed || other.alignMask > target.alignMask) {
target.isAlignFixed = true;
target.alignMask = other.alignMask;
target.alignOfs = ofs;
@@ -157,14 +138,14 @@ static void mergeSections(Section &target, std::unique_ptr<Section> &&other) {
switch (other->modifier) {
case SECTION_UNION:
checkSectUnionCompat(target, *other);
checkPieceCompat(target, *other, 0);
if (other->size > target.size) {
target.size = other->size;
}
break;
case SECTION_FRAGMENT:
checkFragmentCompat(target, *other);
checkPieceCompat(target, *other, target.size);
// Append `other` to `target`
other->offset = target.size;
target.size += other->size;

View File

@@ -0,0 +1,4 @@
SECTION "ROM", ROM0
LOAD UNION "U", WRAM0
ds 1
ENDL

View File

@@ -0,0 +1,17 @@
SECTION "R1", WRAM0
ds $77
SECTION "R2", WRAM0
ds $ef
SECTION UNION "U", WRAM0
ds $52e
SECTION UNION "U", WRAM0
wStart::
ds $89
assert @ & $FF == 0, "wContent must be 8-bit aligned"
align 8
wContent::
ds $111
wEnd::

Binary file not shown.

View File

@@ -0,0 +1,5 @@
WRAM0
align 8
"R1"
"U"
"R2"

View File

@@ -390,6 +390,15 @@ rgblinkQuiet "$otemp" "$gbtemp" 2>"$outtemp"
tryDiff "$test"/out.err "$outtemp"
evaluateTest
test="section-union/compat"
startTest
"$RGBASM" -o "$otemp" "$test"/a.asm
"$RGBASM" -o "$gbtemp2" "$test"/b.asm
continueTest
rgblinkQuiet -o "$gbtemp" -l "$test"/script.link "$otemp" "$gbtemp2"
tryCmpRom "$test"/ref.out.bin
evaluateTest
test="section-union/good"
startTest
"$RGBASM" -o "$otemp" "$test"/a.asm