diff --git a/src/link/assign.cpp b/src/link/assign.cpp index b7bd1b5c..b40c43da 100644 --- a/src/link/assign.cpp +++ b/src/link/assign.cpp @@ -143,15 +143,22 @@ static std::optional getPlacement(Section const §ion, MemoryLocation } location.address = section.org; } else if (section.isAlignFixed) { - // Move to next aligned location - // We have previously ensured alignment to 15 or fewer bits, so this will progress + // If the alignment is fixed, move to the next aligned location. + // We have previously ensured alignment to 15 or fewer bits. assume(section.alignMask < (1 << 16) - 1); - // Move back to alignment boundary + uint16_t prevAddress = location.address; + // Move back to the alignment boundary. + // Subtracting the alignment offset may underflow on the first check from address + // $0000, so applying the alignment mask ensures we have a valid address. location.address -= section.alignOfs; - // Ensure we're there (e.g. on first check) location.address &= ~section.alignMask; - // Go to next align boundary and add offset + // Go to the next align boundary and add the alignment offset. location.address += section.alignMask + 1 + section.alignOfs; + // If the aligned address wrapped around past the end of the address space, + // no further aligned location can fit in this bank. + if (location.address <= prevAddress) { + break; + } } else if (++spaceIdx < bankMem.size()) { // Any location is fine, so, next free block location.address = bankMem[spaceIdx].address; diff --git a/test/link/align-overflow.asm b/test/link/align-overflow.asm new file mode 100644 index 00000000..59a7f228 --- /dev/null +++ b/test/link/align-overflow.asm @@ -0,0 +1,8 @@ +; This used to fail as moving to the next "alignment +; boundary" would wrap across 16 bits. + +SECTION "A", HRAM[$FF80] +ds 96 ; fills $FF80..$FFDF, leaving 31 bytes free + +SECTION "B", HRAM, ALIGN[7] ; 128-byte alignment +ds 32 diff --git a/test/link/align-overflow.out b/test/link/align-overflow.out new file mode 100644 index 00000000..3630517e --- /dev/null +++ b/test/link/align-overflow.out @@ -0,0 +1,2 @@ +FATAL: Unable to place "B" (HRAM section) with align mask $ff80 and offset $0 +Linking aborted with 1 error