mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Implement byte alignment in section assingment
Yay, more refactoring of the section assignment… This version of the linker will allocate sections by their alignment, and then by their size (largest first, in both cases). In future, this may be improved by using dense packing (as suggested by #83).
This commit is contained in:
@@ -46,7 +46,7 @@ const struct sSectionAttributes SECT_ATTRIBUTES[] = {
|
|||||||
case SECT_WRAMX: DOMAXWBANK(y); break; \
|
case SECT_WRAMX: DOMAXWBANK(y); break; \
|
||||||
case SECT_SRAM: DOMAXSBANK(y); break; \
|
case SECT_SRAM: DOMAXSBANK(y); break; \
|
||||||
case SECT_VRAM: DOMAXVBANK(y); break; \
|
case SECT_VRAM: DOMAXVBANK(y); break; \
|
||||||
default: errx(1, "DOMAXBANK used with invalid parameters"); break; }}
|
default: break; }}
|
||||||
#define DOMAXRBANK(x) {if( (x)>MaxBankUsed ) MaxBankUsed=(x);}
|
#define DOMAXRBANK(x) {if( (x)>MaxBankUsed ) MaxBankUsed=(x);}
|
||||||
#define DOMAXWBANK(x) {if( (x)>MaxWBankUsed ) MaxWBankUsed=(x);}
|
#define DOMAXWBANK(x) {if( (x)>MaxWBankUsed ) MaxWBankUsed=(x);}
|
||||||
#define DOMAXSBANK(x) {if( (x)>MaxSBankUsed ) MaxSBankUsed=(x);}
|
#define DOMAXSBANK(x) {if( (x)>MaxSBankUsed ) MaxSBankUsed=(x);}
|
||||||
@@ -77,6 +77,40 @@ area_Avail(SLONG bank)
|
|||||||
return (r);
|
return (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLONG
|
||||||
|
area_doAlloc(struct sFreeArea *pArea, SLONG org, SLONG size)
|
||||||
|
{
|
||||||
|
if (org >= pArea->nOrg && (org + size) <= (pArea->nOrg + pArea->nSize)) {
|
||||||
|
if (org == pArea->nOrg) {
|
||||||
|
pArea->nOrg += size;
|
||||||
|
pArea->nSize -= size;
|
||||||
|
return org;
|
||||||
|
} else {
|
||||||
|
if ((org + size) == (pArea->nOrg + pArea->nSize)) {
|
||||||
|
pArea->nSize -= size;
|
||||||
|
return org;
|
||||||
|
} else {
|
||||||
|
struct sFreeArea *pNewArea;
|
||||||
|
|
||||||
|
if ((pNewArea = malloc(sizeof(struct sFreeArea))) != NULL) {
|
||||||
|
*pNewArea = *pArea;
|
||||||
|
pNewArea->pPrev = pArea;
|
||||||
|
pArea->pNext = pNewArea;
|
||||||
|
pArea->nSize = org - pArea->nOrg;
|
||||||
|
pNewArea->nOrg = org + size;
|
||||||
|
pNewArea->nSize -= size + pArea->nSize;
|
||||||
|
return org;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
err(1, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
SLONG
|
SLONG
|
||||||
area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
|
area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
|
||||||
{
|
{
|
||||||
@@ -84,39 +118,11 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
|
|||||||
|
|
||||||
pArea = *ppArea;
|
pArea = *ppArea;
|
||||||
while (pArea) {
|
while (pArea) {
|
||||||
if (org >= pArea->nOrg
|
SLONG result = area_doAlloc(pArea, org, size);
|
||||||
&& (org + size - 1) <= (pArea->nOrg + pArea->nSize - 1)) {
|
if (result != -1) {
|
||||||
if (org == pArea->nOrg) {
|
return result;
|
||||||
pArea->nOrg += size;
|
|
||||||
pArea->nSize -= size;
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
if ((org + size - 1) ==
|
|
||||||
(pArea->nOrg + pArea->nSize - 1)) {
|
|
||||||
pArea->nSize -= size;
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
struct sFreeArea *pNewArea;
|
|
||||||
|
|
||||||
if ((pNewArea =
|
|
||||||
malloc(sizeof(struct sFreeArea)))
|
|
||||||
!= NULL) {
|
|
||||||
*pNewArea = *pArea;
|
|
||||||
pNewArea->pPrev = pArea;
|
|
||||||
pArea->pNext = pNewArea;
|
|
||||||
pArea->nSize =
|
|
||||||
org - pArea->nOrg;
|
|
||||||
pNewArea->nOrg = org + size;
|
|
||||||
pNewArea->nSize -=
|
|
||||||
size + pArea->nSize;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
err(1, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ppArea = &(pArea->pNext);
|
ppArea = &(pArea->pNext);
|
||||||
pArea = *ppArea;
|
pArea = *ppArea;
|
||||||
}
|
}
|
||||||
@@ -141,38 +147,42 @@ area_AllocAbsAnyBank(SLONG org, SLONG size, enum eSectionType type)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLONG
|
SLONG
|
||||||
area_Alloc(struct sFreeArea ** ppArea, SLONG size)
|
area_Alloc(struct sFreeArea ** ppArea, SLONG size, SLONG alignment) {
|
||||||
{
|
|
||||||
struct sFreeArea *pArea;
|
struct sFreeArea *pArea;
|
||||||
|
if (alignment < 1) {
|
||||||
|
alignment = 1;
|
||||||
|
}
|
||||||
|
|
||||||
pArea = *ppArea;
|
pArea = *ppArea;
|
||||||
while (pArea) {
|
while (pArea) {
|
||||||
if (size <= pArea->nSize) {
|
SLONG org = pArea->nOrg;
|
||||||
SLONG r;
|
if (org % alignment) {
|
||||||
|
org += alignment;
|
||||||
r = pArea->nOrg;
|
|
||||||
pArea->nOrg += size;
|
|
||||||
pArea->nSize -= size;
|
|
||||||
|
|
||||||
return (r);
|
|
||||||
}
|
}
|
||||||
|
org -= org % alignment;
|
||||||
|
|
||||||
|
SLONG result = area_doAlloc(pArea, org, size);
|
||||||
|
if (result != -1) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ppArea = &(pArea->pNext);
|
ppArea = &(pArea->pNext);
|
||||||
pArea = *ppArea;
|
pArea = *ppArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLONG
|
SLONG
|
||||||
area_AllocAnyBank(SLONG size, enum eSectionType type) {
|
area_AllocAnyBank(SLONG size, SLONG alignment, enum eSectionType type) {
|
||||||
ensureSectionTypeIsValid(type);
|
ensureSectionTypeIsValid(type);
|
||||||
|
|
||||||
SLONG startBank = SECT_ATTRIBUTES[type].bank;
|
SLONG startBank = SECT_ATTRIBUTES[type].bank;
|
||||||
SLONG bankCount = SECT_ATTRIBUTES[type].bankCount;
|
SLONG bankCount = SECT_ATTRIBUTES[type].bankCount;
|
||||||
|
|
||||||
for (int i = 0; i < bankCount; i++) {
|
for (int i = 0; i < bankCount; i++) {
|
||||||
SLONG org = area_Alloc(&BankFree[startBank + i], size);
|
SLONG org = area_Alloc(&BankFree[startBank + i], size, alignment);
|
||||||
if (org != -1) {
|
if (org != -1) {
|
||||||
return ((startBank + i) << 16) | org;
|
return ((startBank + i) << 16) | org;
|
||||||
}
|
}
|
||||||
@@ -182,45 +192,27 @@ area_AllocAnyBank(SLONG size, enum eSectionType type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct sSection *
|
struct sSection *
|
||||||
FindLargestSection(enum eSectionType type)
|
FindLargestSection(enum eSectionType type, bool bankFixed)
|
||||||
{
|
{
|
||||||
struct sSection *pSection, *r = NULL;
|
struct sSection *pSection, *r = NULL;
|
||||||
SLONG nLargest = 0;
|
SLONG nLargest = 0;
|
||||||
|
SLONG nLargestAlignment = 0;
|
||||||
|
|
||||||
pSection = pSections;
|
pSection = pSections;
|
||||||
while (pSection) {
|
while (pSection) {
|
||||||
if (pSection->oAssigned == 0 && pSection->Type == type) {
|
if (pSection->oAssigned == 0 && pSection->Type == type && (bankFixed ^ (pSection->nBank == -1))) {
|
||||||
if (pSection->nByteSize > nLargest) {
|
if (pSection->nAlign > nLargestAlignment || (pSection->nAlign == nLargestAlignment && pSection->nByteSize > nLargest)) {
|
||||||
nLargest = pSection->nByteSize;
|
nLargest = pSection->nByteSize;
|
||||||
|
nLargestAlignment = pSection->nAlign;
|
||||||
r = pSection;
|
r = pSection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pSection = pSection->pNext;
|
pSection = pSection->pNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
AssignBankedSections(enum eSectionType type)
|
|
||||||
{
|
|
||||||
ensureSectionTypeIsValid(type);
|
|
||||||
|
|
||||||
struct sSection *pSection;
|
|
||||||
|
|
||||||
while ((pSection = FindLargestSection(type))) {
|
|
||||||
SLONG org;
|
|
||||||
|
|
||||||
if ((org = area_AllocAnyBank(pSection->nByteSize, type)) != -1) {
|
|
||||||
pSection->nOrg = org & 0xFFFF;
|
|
||||||
pSection->nBank = org >> 16;
|
|
||||||
pSection->oAssigned = 1;
|
|
||||||
DOMAXBANK(pSection->Type, pSection->nBank);
|
|
||||||
} else {
|
|
||||||
errx(1, "Unable to place %s section anywhere",
|
|
||||||
SECT_ATTRIBUTES[type].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
VerifyAndSetBank(struct sSection *pSection)
|
VerifyAndSetBank(struct sSection *pSection)
|
||||||
@@ -237,6 +229,47 @@ VerifyAndSetBank(struct sSection *pSection)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AssignFixedBankSections(enum eSectionType type)
|
||||||
|
{
|
||||||
|
ensureSectionTypeIsValid(type);
|
||||||
|
|
||||||
|
struct sSection *pSection;
|
||||||
|
|
||||||
|
while ((pSection = FindLargestSection(type, true))) {
|
||||||
|
if (VerifyAndSetBank(pSection) &&
|
||||||
|
(pSection->nOrg = area_Alloc(&BankFree[pSection->nBank], pSection->nByteSize, pSection->nAlign)) != -1) {
|
||||||
|
pSection->oAssigned = 1;
|
||||||
|
DOMAXBANK(pSection->Type, pSection->nBank);
|
||||||
|
} else {
|
||||||
|
errx(1, "Unable to load fixed %s section into bank $%02lX",
|
||||||
|
SECT_ATTRIBUTES[pSection->Type].name, pSection->nBank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AssignFloatingBankSections(enum eSectionType type)
|
||||||
|
{
|
||||||
|
ensureSectionTypeIsValid(type);
|
||||||
|
|
||||||
|
struct sSection *pSection;
|
||||||
|
|
||||||
|
while ((pSection = FindLargestSection(type, false))) {
|
||||||
|
SLONG org;
|
||||||
|
|
||||||
|
if ((org = area_AllocAnyBank(pSection->nByteSize, pSection->nAlign, type)) != -1) {
|
||||||
|
pSection->nOrg = org & 0xFFFF;
|
||||||
|
pSection->nBank = org >> 16;
|
||||||
|
pSection->oAssigned = 1;
|
||||||
|
DOMAXBANK(pSection->Type, pSection->nBank);
|
||||||
|
} else {
|
||||||
|
errx(1, "Unable to place %s section anywhere",
|
||||||
|
SECT_ATTRIBUTES[type].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AssignSections(void)
|
AssignSections(void)
|
||||||
{
|
{
|
||||||
@@ -353,35 +386,11 @@ AssignSections(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Next, let's assign all the bankfixed ONLY ROMX sections...
|
* Next, let's assign all the bankfixed ONLY sections...
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
for (enum eSectionType i = SECT_MIN; i <= SECT_MAX; i++) {
|
||||||
pSection = pSections;
|
AssignFixedBankSections(i);
|
||||||
while (pSection) {
|
|
||||||
if (pSection->oAssigned == 0
|
|
||||||
&& pSection->nOrg == -1 && pSection->nBank != -1) {
|
|
||||||
switch (pSection->Type) {
|
|
||||||
case SECT_ROMX:
|
|
||||||
case SECT_SRAM:
|
|
||||||
case SECT_VRAM:
|
|
||||||
case SECT_WRAMX:
|
|
||||||
if (VerifyAndSetBank(pSection) &&
|
|
||||||
(pSection->nOrg = area_Alloc(&BankFree[pSection->nBank], pSection->nByteSize)) != -1) {
|
|
||||||
pSection->oAssigned = 1;
|
|
||||||
DOMAXBANK(pSection->Type, pSection->nBank);
|
|
||||||
} else {
|
|
||||||
errx(1, "Unable to load fixed %s section into bank $%02lX",
|
|
||||||
SECT_ATTRIBUTES[pSection->Type].name, pSection->nBank);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: // Handle other sections later
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pSection = pSection->pNext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -421,41 +430,9 @@ AssignSections(void)
|
|||||||
* sections
|
* sections
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
for (enum eSectionType i = SECT_MIN; i <= SECT_MAX; i++) {
|
||||||
pSection = pSections;
|
AssignFloatingBankSections(i);
|
||||||
while (pSection) {
|
|
||||||
if (pSection->oAssigned == 0) {
|
|
||||||
switch (pSection->Type) {
|
|
||||||
case SECT_WRAM0:
|
|
||||||
case SECT_HRAM:
|
|
||||||
case SECT_ROM0:
|
|
||||||
pSection->nBank = SECT_ATTRIBUTES[pSection->Type].bank;
|
|
||||||
if ((pSection->nOrg =
|
|
||||||
area_Alloc(&BankFree[pSection->nBank],
|
|
||||||
pSection->nByteSize)) == -1) {
|
|
||||||
errx(1, "%s section too large", SECT_ATTRIBUTES[pSection->Type].name);
|
|
||||||
}
|
|
||||||
pSection->oAssigned = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SECT_SRAM:
|
|
||||||
case SECT_VRAM:
|
|
||||||
case SECT_WRAMX:
|
|
||||||
case SECT_ROMX:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
errx(1, "(INTERNAL) Unknown section type!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pSection = pSection->pNext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AssignBankedSections(SECT_ROMX);
|
|
||||||
AssignBankedSections(SECT_VRAM);
|
|
||||||
AssignBankedSections(SECT_WRAMX);
|
|
||||||
AssignBankedSections(SECT_SRAM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
Reference in New Issue
Block a user