Allow specifying offset in addition to alignment

This commit is contained in:
ISSOtm
2020-04-08 00:40:41 +02:00
parent e82ad21704
commit b0ec8468e6
16 changed files with 154 additions and 44 deletions

View File

@@ -132,7 +132,8 @@ static bool isLocationSuitable(struct Section const *section,
if (section->isAddressFixed && section->org != location->address)
return false;
if (section->isAlignFixed && location->address & section->alignMask)
if (section->isAlignFixed
&& ((location->address - section->alignOfs) & section->alignMask))
return false;
if (location->address < freeSpace->address)
@@ -183,8 +184,13 @@ static struct FreeSpace *getPlacement(struct Section const *section,
space = NULL;
} else if (section->isAlignFixed) {
/* Move to next aligned location */
/* Move back to alignment boundary */
location->address -= section->alignOfs;
/* Ensure we're there (e.g. on first check) */
location->address &= ~section->alignMask;
location->address += section->alignMask + 1;
/* Go to next align boundary and add offset */
location->address += section->alignMask + 1
+ section->alignOfs;
} else {
/* Any location is fine, so, next free block */
space = space->next;
@@ -309,8 +315,8 @@ static void placeSection(struct Section *section)
if (section->isAddressFixed)
snprintf(where, 64, "at address $%04x", section->org);
else if (section->isAlignFixed)
snprintf(where, 64, "with align mask %x",
~section->alignMask);
snprintf(where, 64, "with align mask %x and offset %u",
~section->alignMask, section->alignOfs);
else
strcpy(where, "anywhere");
}

View File

@@ -255,7 +255,7 @@ static void readSection(FILE *file, struct Section *section,
char const *fileName, struct Section *fileSections[])
{
int32_t tmp;
uint8_t type;
uint8_t byte;
tryReadstr(section->name, file, "%s: Cannot read section name: %s",
fileName);
@@ -265,24 +265,34 @@ static void readSection(FILE *file, struct Section *section,
errx(1, "\"%s\"'s section size (%d) is invalid", section->name,
tmp);
section->size = tmp;
tryGetc(type, file, "%s: Cannot read \"%s\"'s type: %s",
tryGetc(byte, file, "%s: Cannot read \"%s\"'s type: %s",
fileName, section->name);
section->type = type & 0x7F;
section->isUnion = type >> 7;
section->type = byte & 0x7F;
section->isUnion = byte >> 7;
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s org: %s",
fileName, section->name);
section->isAddressFixed = tmp >= 0;
if (tmp > UINT16_MAX)
errx(1, "\"%s\"'s org' is too large (%d)", section->name, tmp);
if (tmp > UINT16_MAX) {
error("\"%s\"'s org is too large (%d)", section->name, tmp);
tmp = UINT16_MAX;
}
section->org = tmp;
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s bank: %s",
fileName, section->name);
section->isBankFixed = tmp >= 0;
section->bank = tmp;
tryGetc(tmp, file, "%s: Cannot read \"%s\"'s alignment: %s",
tryGetc(byte, file, "%s: Cannot read \"%s\"'s alignment: %s",
fileName, section->name);
section->isAlignFixed = tmp != 0;
section->alignMask = (1 << tmp) - 1;
section->isAlignFixed = byte != 0;
section->alignMask = (1 << byte) - 1;
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s alignment offset: %s",
fileName, section->name);
if (tmp > UINT16_MAX) {
error("\"%s\"'s alignment offset is too large (%d)",
section->name, tmp);
tmp = UINT16_MAX;
}
section->alignOfs = tmp;
if (sect_HasData(section->type)) {
/* Ensure we never allocate 0 bytes */

View File

@@ -48,21 +48,28 @@ static void mergeSections(struct Section *target, struct Section *other)
errx(1, "Section \"%s\" is defined with conflicting addresses $%x and $%x",
other->name, target->org, other->org);
} else if (target->isAlignFixed) {
if (other->org & target->alignMask)
errx(1, "Section \"%s\" is defined with conflicting %u-byte alignment and address $%x",
if ((other->org - target->alignOfs) & target->alignMask)
errx(1, "Section \"%s\" is defined with conflicting %u-byte alignment (offset %u) and address $%x",
other->name, target->alignMask + 1,
other->org);
target->alignOfs, other->org);
}
target->isAddressFixed = true;
target->org = other->org;
} else if (other->isAlignFixed) {
if (target->isAddressFixed) {
if (target->org & other->alignMask)
errx(1, "Section \"%s\" is defined with conflicting address $%x and %u-byte alignment",
if ((target->org - other->alignOfs) & other->alignMask)
errx(1, "Section \"%s\" is defined with conflicting address $%x and %u-byte alignment (offset %u)",
other->name, target->org,
other->alignMask + 1);
other->alignMask + 1, other->alignOfs);
} else if (target->isAlignFixed
&& (other->alignMask & target->alignOfs)
!= (target->alignMask & other->alignOfs)) {
errx(1, "Section \"%s\" is defined with conflicting %u-byte alignment (offset %u) and %u-byte alignment (offset %u)",
other->name, target->alignMask + 1,
target->alignOfs, other->alignMask + 1,
other->alignOfs);
} else if (!target->isAlignFixed
|| other->alignMask > target->alignMask) {
|| (other->alignMask > target->alignMask)) {
target->isAlignFixed = true;
target->alignMask = other->alignMask;
}