Implement unionized sections in RGBLINK

This commit is contained in:
ISSOtm
2020-03-20 23:44:02 +01:00
parent cb52ae0f26
commit e123b6dec7
11 changed files with 181 additions and 39 deletions

View File

@@ -36,17 +36,76 @@ void sect_ForEach(void (*callback)(struct Section *, void *), void *arg)
hash_ForEach(sections, forEach, &callbackArg);
}
static void mergeSections(struct Section *target, struct Section *other)
{
if (other->isAddressFixed) {
if (target->isAddressFixed) {
if (target->org != other->org)
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",
other->name, target->alignMask + 1,
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",
other->name, target->org,
other->alignMask + 1);
} else if (!target->isAlignFixed
|| other->alignMask > target->alignMask) {
target->isAlignFixed = true;
target->alignMask = other->alignMask;
}
}
if (other->isBankFixed) {
if (!target->isBankFixed) {
target->isBankFixed = true;
target->bank = other->bank;
} else if (target->bank != other->bank) {
errx(1, "Section \"%s\" is defined with conflicting banks %u and %u",
other->name, target->bank, other->bank);
}
}
if (other->size > target->size)
target->size = other->size;
target->nextu = other;
}
void sect_AddSection(struct Section *section)
{
/* Check if the section already exists */
if (hash_GetElement(sections, section->name))
errx(1, "Section name \"%s\" is already in use", section->name);
struct Section *other = hash_GetElement(sections, section->name);
/* If not, add it */
bool collided = hash_AddElement(sections, section->name, section);
if (other) {
if (other->isUnion && section->isUnion) {
mergeSections(other, section);
} else if (section->isUnion || other->isUnion) {
errx(1, "Section \"%s\" defined as both unionized and not",
section->name);
} else {
errx(1, "Section name \"%s\" is already in use",
section->name);
}
} else if (section->isUnion && sect_HasData(section->type)) {
errx(1, "Section \"%s\" is of type %s, which cannot be unionized",
section->name, typeNames[section->type]);
} else {
/* If not, add it */
bool collided = hash_AddElement(sections, section->name,
section);
if (beVerbose && collided)
warnx("Section hashmap collision occurred!");
if (beVerbose && collided)
warnx("Section hashmap collision occurred!");
}
}
struct Section *sect_GetSection(char const *name)