From 1b05c43b979f8cc8c9bd571a7c96f13614724111 Mon Sep 17 00:00:00 2001 From: Ben10do Date: Sun, 19 Feb 2017 22:43:45 +0000 Subject: [PATCH] Implement byte alignment in section assingment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- src/link/assign.c | 243 +++++++++++++++++++++------------------------- 1 file changed, 110 insertions(+), 133 deletions(-) diff --git a/src/link/assign.c b/src/link/assign.c index e602ebd7..91192578 100644 --- a/src/link/assign.c +++ b/src/link/assign.c @@ -46,7 +46,7 @@ const struct sSectionAttributes SECT_ATTRIBUTES[] = { case SECT_WRAMX: DOMAXWBANK(y); break; \ case SECT_SRAM: DOMAXSBANK(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 DOMAXWBANK(x) {if( (x)>MaxWBankUsed ) MaxWBankUsed=(x);} #define DOMAXSBANK(x) {if( (x)>MaxSBankUsed ) MaxSBankUsed=(x);} @@ -77,6 +77,40 @@ area_Avail(SLONG bank) 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 area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size) { @@ -84,39 +118,11 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size) pArea = *ppArea; while (pArea) { - if (org >= pArea->nOrg - && (org + size - 1) <= (pArea->nOrg + pArea->nSize - 1)) { - if (org == pArea->nOrg) { - 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); - } - } - } + SLONG result = area_doAlloc(pArea, org, size); + if (result != -1) { + return result; } + ppArea = &(pArea->pNext); pArea = *ppArea; } @@ -141,38 +147,42 @@ area_AllocAbsAnyBank(SLONG org, SLONG size, enum eSectionType type) return -1; } -SLONG -area_Alloc(struct sFreeArea ** ppArea, SLONG size) -{ +SLONG +area_Alloc(struct sFreeArea ** ppArea, SLONG size, SLONG alignment) { struct sFreeArea *pArea; - + if (alignment < 1) { + alignment = 1; + } + pArea = *ppArea; while (pArea) { - if (size <= pArea->nSize) { - SLONG r; - - r = pArea->nOrg; - pArea->nOrg += size; - pArea->nSize -= size; - - return (r); + SLONG org = pArea->nOrg; + if (org % alignment) { + org += alignment; } + org -= org % alignment; + + SLONG result = area_doAlloc(pArea, org, size); + if (result != -1) { + return result; + } + ppArea = &(pArea->pNext); pArea = *ppArea; } - return (-1); + return -1; } SLONG -area_AllocAnyBank(SLONG size, enum eSectionType type) { +area_AllocAnyBank(SLONG size, SLONG alignment, enum eSectionType type) { ensureSectionTypeIsValid(type); SLONG startBank = SECT_ATTRIBUTES[type].bank; SLONG bankCount = SECT_ATTRIBUTES[type].bankCount; 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) { return ((startBank + i) << 16) | org; } @@ -182,45 +192,27 @@ area_AllocAnyBank(SLONG size, enum eSectionType type) { } struct sSection * -FindLargestSection(enum eSectionType type) +FindLargestSection(enum eSectionType type, bool bankFixed) { struct sSection *pSection, *r = NULL; SLONG nLargest = 0; + SLONG nLargestAlignment = 0; pSection = pSections; while (pSection) { - if (pSection->oAssigned == 0 && pSection->Type == type) { - if (pSection->nByteSize > nLargest) { + if (pSection->oAssigned == 0 && pSection->Type == type && (bankFixed ^ (pSection->nBank == -1))) { + if (pSection->nAlign > nLargestAlignment || (pSection->nAlign == nLargestAlignment && pSection->nByteSize > nLargest)) { nLargest = pSection->nByteSize; + nLargestAlignment = pSection->nAlign; r = pSection; } } pSection = pSection->pNext; } + 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 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 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... * */ - - pSection = pSections; - 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; + for (enum eSectionType i = SECT_MIN; i <= SECT_MAX; i++) { + AssignFixedBankSections(i); } /* @@ -421,41 +430,9 @@ AssignSections(void) * sections * */ - - pSection = pSections; - 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; + for (enum eSectionType i = SECT_MIN; i <= SECT_MAX; i++) { + AssignFloatingBankSections(i); } - - AssignBankedSections(SECT_ROMX); - AssignBankedSections(SECT_VRAM); - AssignBankedSections(SECT_WRAMX); - AssignBankedSections(SECT_SRAM); } void