ref: 4f86a1253940f8f866413a2095ae3b21598d6b6f
parent: 7b8d4de35c2dc284501218982fb1a05f6a1a8321
parent: 7e2457c9bee44041dbb9ace4d67158711be6352d
author: AntonioND <[email protected]>
date: Thu Mar 2 04:17:46 EST 2017
Merge pull request #125 from Ben10do/section-alignment Implement byte alignment for data
--- a/include/asm/output.h
+++ b/include/asm/output.h
@@ -10,6 +10,7 @@
ULONG nPC;
ULONG nOrg;
ULONG nBank;
+ ULONG nAlign;
struct Section *pNext;
struct Patch *pPatches;
struct Charmap *charmap;
@@ -20,6 +21,7 @@
void out_SetFileName(char *s);
void out_NewSection(char *pzName, ULONG secttype);
void out_NewAbsSection(char *pzName, ULONG secttype, SLONG org, SLONG bank);
+void out_NewAlignedSection(char *pzName, ULONG secttype, SLONG alignment, SLONG bank);
void out_AbsByte(int b);
void out_AbsByteGroup(char *s, int length);
void out_RelByte(struct Expression * expr);
--- a/include/link/mylink.h
+++ b/include/link/mylink.h
@@ -63,8 +63,10 @@
struct sSection {
SLONG nBank;
SLONG nOrg;
+ SLONG nAlign;
BBOOL oAssigned;
+ char *pzName;
SLONG nByteSize;
enum eSectionType Type;
UBYTE *pData;
--- a/src/asm/asmy.y
+++ b/src/asm/asmy.y
@@ -460,7 +460,7 @@
%left T_OP_MUL T_OP_DIV T_OP_MOD
%left T_OP_NOT
%left T_OP_DEF
-%left T_OP_BANK
+%left T_OP_BANK T_OP_ALIGN
%left T_OP_SIN
%left T_OP_COS
%left T_OP_TAN
@@ -1113,6 +1113,10 @@
else
yyerror("Address $%x not 16-bit", $6);
}
+ | T_POP_SECTION string ',' sectiontype ',' T_OP_ALIGN '[' const ']'
+ {
+ out_NewAlignedSection($2, $4, $8, -1);
+ }
| T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' const ']'
{
bankrangecheck($2, $4, -1, $8);
@@ -1123,6 +1127,14 @@
yyerror("Address $%x not 16-bit", $6);
}
bankrangecheck($2, $4, $6, $11);
+ }
+ | T_POP_SECTION string ',' sectiontype ',' T_OP_ALIGN '[' const ']' ',' T_OP_BANK '[' const ']'
+ {
+ out_NewAlignedSection($2, $4, $8, $13);
+ }
+ | T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' const ']' ',' T_OP_ALIGN '[' const ']'
+ {
+ out_NewAlignedSection($2, $4, $13, $8);
}
;
--- a/src/asm/globlex.c
+++ b/src/asm/globlex.c
@@ -267,6 +267,7 @@
{"def", T_OP_DEF},
{"bank", T_OP_BANK},
+ {"align", T_OP_ALIGN},
{"round", T_OP_ROUND},
{"ceil", T_OP_CEIL},
--- a/src/asm/output.c
+++ b/src/asm/output.c
@@ -201,17 +201,18 @@
void
writesection(struct Section * pSect, FILE * f)
{
- //printf("SECTION: %s, ID: %d\n", pSect->pzName, getsectid(pSect));
-
+ fputstring(pSect->pzName, f); // RGB3 addition
fputlong(pSect->nPC, f);
fputc(pSect->nType, f);
fputlong(pSect->nOrg, f);
//RGB1 addition
- fputlong(pSect->nBank, f);
+ fputlong(pSect->nBank, f);
//RGB1 addition
+
+ fputlong(pSect->nAlign, f); // RGB3 addition
- if ((pSect->nType == SECT_ROM0)
+ if ((pSect->nType == SECT_ROM0)
|| (pSect->nType == SECT_ROMX)) {
struct Patch *pPatch;
@@ -490,7 +491,7 @@
struct PatchSymbol *pSym;
struct Section *pSect;
- fwrite("RGB2", 1, 4, f);
+ fwrite("RGB3", 1, 4, f);
fputlong(countsymbols(), f);
fputlong(countsections(), f);
@@ -546,7 +547,7 @@
* Find a section by name and type. If it doesn't exist, create it
*/
struct Section *
-out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank)
+out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank, SLONG alignment)
{
struct Section *pSect, **ppSect;
@@ -557,7 +558,8 @@
if (strcmp(pzName, pSect->pzName) == 0) {
if (secttype == pSect->nType
&& ((ULONG) org) == pSect->nOrg
- && ((ULONG) bank) == pSect->nBank) {
+ && ((ULONG) bank) == pSect->nBank
+ && ((ULONG) alignment == pSect->nAlign)) {
return (pSect);
} else
fatalerror
@@ -574,6 +576,7 @@
pSect->nPC = 0;
pSect->nOrg = org;
pSect->nBank = bank;
+ pSect->nAlign = alignment;
pSect->pNext = NULL;
pSect->pPatches = NULL;
pSect->charmap = NULL;
@@ -610,7 +613,7 @@
void
out_NewSection(char *pzName, ULONG secttype)
{
- out_SetCurrentSection(out_FindSection(pzName, secttype, -1, -1));
+ out_SetCurrentSection(out_FindSection(pzName, secttype, -1, -1, 1));
}
/*
@@ -619,7 +622,19 @@
void
out_NewAbsSection(char *pzName, ULONG secttype, SLONG org, SLONG bank)
{
- out_SetCurrentSection(out_FindSection(pzName, secttype, org, bank));
+ out_SetCurrentSection(out_FindSection(pzName, secttype, org, bank, 1));
+}
+
+/*
+ * Set the current section by name and type, using a given byte alignment
+ */
+void
+out_NewAlignedSection(char *pzName, ULONG secttype, SLONG alignment, SLONG bank)
+{
+ if (alignment < 0 || alignment > 16) {
+ yyerror("Alignment must be between 0-16 bits.");
+ }
+ out_SetCurrentSection(out_FindSection(pzName, secttype, -1, bank, 1 << alignment));
}
/*
--- a/src/link/assign.c
+++ b/src/link/assign.c
@@ -46,7 +46,7 @@
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);}
@@ -78,45 +78,51 @@
}
SLONG
-area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
+area_doAlloc(struct sFreeArea *pArea, SLONG org, SLONG size)
{
- struct sFreeArea *pArea;
-
- pArea = *ppArea;
- while (pArea) {
- if (org >= pArea->nOrg
- && (org + size - 1) <= (pArea->nOrg + pArea->nSize - 1)) {
- if (org == pArea->nOrg) {
- pArea->nOrg += 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 0;
+ return org;
} else {
- if ((org + size - 1) ==
- (pArea->nOrg + pArea->nSize - 1)) {
- pArea->nSize -= size;
- return 0;
- } else {
- struct sFreeArea *pNewArea;
+ 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);
- }
+ 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)
+{
+ struct sFreeArea *pArea;
+
+ pArea = *ppArea;
+ while (pArea) {
+ SLONG result = area_doAlloc(pArea, org, size);
+ if (result != -1) {
+ return result;
+ }
+
ppArea = &(pArea->pNext);
pArea = *ppArea;
}
@@ -141,31 +147,35 @@
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;
@@ -172,7 +182,7 @@
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,35 +192,73 @@
}
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;
}
+
+bool
+VerifyAndSetBank(struct sSection *pSection)
+{
+ ensureSectionTypeIsValid(pSection->Type);
+
+ if (pSection->nBank >= SECT_ATTRIBUTES[pSection->Type].minBank
+ && pSection->nBank < SECT_ATTRIBUTES[pSection->Type].minBank + SECT_ATTRIBUTES[pSection->Type].bankCount) {
+ pSection->nBank += SECT_ATTRIBUTES[pSection->Type].bank + SECT_ATTRIBUTES[pSection->Type].offset;
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
void
-AssignBankedSections(enum eSectionType type)
+AssignFixedBankSections(enum eSectionType type)
{
ensureSectionTypeIsValid(type);
struct sSection *pSection;
- while ((pSection = FindLargestSection(type))) {
+ 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, type)) != -1) {
+ if ((org = area_AllocAnyBank(pSection->nByteSize, pSection->nAlign, type)) != -1) {
pSection->nOrg = org & 0xFFFF;
pSection->nBank = org >> 16;
pSection->oAssigned = 1;
@@ -219,24 +267,9 @@
errx(1, "Unable to place %s section anywhere",
SECT_ATTRIBUTES[type].name);
}
- }
+ }
}
-bool
-VerifyAndSetBank(struct sSection *pSection)
-{
- ensureSectionTypeIsValid(pSection->Type);
-
- if (pSection->nBank >= SECT_ATTRIBUTES[pSection->Type].minBank
- && pSection->nBank < SECT_ATTRIBUTES[pSection->Type].minBank + SECT_ATTRIBUTES[pSection->Type].bankCount) {
- pSection->nBank += SECT_ATTRIBUTES[pSection->Type].bank + SECT_ATTRIBUTES[pSection->Type].offset;
- return true;
-
- } else {
- return false;
- }
-}
-
void
AssignSections(void)
{
@@ -353,35 +386,11 @@
}
/*
- * 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 @@
* 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
--- a/src/link/object.c
+++ b/src/link/object.c
@@ -18,6 +18,11 @@
UBYTE dummymem;
BBOOL oReadLib = 0;
+enum ObjectFileContents {
+ CONTAINS_SECTION_NAME = 1 << 0,
+ CONTAINS_SECTION_ALIGNMENT = 1 << 1
+};
+
/*
* The usual byte order stuff
*
@@ -46,21 +51,41 @@
return (r);
}
+
/*
* Read a NULL terminated string from a file
*
*/
-
-SLONG
-readasciiz(char *s, FILE * f)
+SLONG
+readasciiz(char **dest, FILE *f)
{
SLONG r = 0;
-
- while (((*s++) = fgetc(f)) != 0)
+
+ size_t bufferLength = 16;
+ char *start = malloc(bufferLength);
+ char *s = start;
+
+ if (!s) {
+ err(1, NULL);
+ }
+
+ while (((*s++) = fgetc(f)) != 0) {
r += 1;
-
+
+ if (r >= bufferLength) {
+ bufferLength *= 2;
+ start = realloc(start, bufferLength);
+ if (!start) {
+ err(1, NULL);
+ }
+ s = start + r;
+ }
+ }
+
+ *dest = start;
return (r + 1);
}
+
/*
* Allocate a new section and link it into the list
*
@@ -97,7 +122,6 @@
struct sSymbol *
obj_ReadSymbol(FILE * f)
{
- char s[256];
struct sSymbol *pSym;
pSym = malloc(sizeof *pSym);
@@ -105,13 +129,7 @@
err(1, NULL);
}
- readasciiz(s, f);
- pSym->pzName = malloc(strlen(s) + 1);
- if (!pSym->pzName) {
- err(1, NULL);
- }
-
- strcpy(pSym->pzName, s);
+ readasciiz(&pSym->pzName, f);
if ((pSym->Type = (enum eSymbolType) fgetc(f)) != SYM_IMPORT) {
pSym->nSectionID = readlong(f);
pSym->nOffset = readlong(f);
@@ -130,10 +148,12 @@
pSection = AllocSection();
+ pSection->pzName = "";
pSection->nByteSize = readlong(f);
pSection->Type = (enum eSectionType) fgetc(f);
pSection->nOrg = -1;
pSection->nBank = -1;
+ pSection->nAlign = 1;
/* does the user want the -s mode? */
@@ -153,7 +173,6 @@
SLONG nNumberOfPatches;
struct sPatch **ppPatch, *pPatch;
- char s[256];
fread(pSection->pData, sizeof(UBYTE),
pSection->nByteSize, f);
@@ -171,15 +190,8 @@
}
*ppPatch = pPatch;
- readasciiz(s, f);
+ readasciiz(&pPatch->pzFilename, f);
- pPatch->pzFilename = malloc(strlen(s) + 1);
- if (!pPatch->pzFilename) {
- err(1, NULL);
- }
-
- strcpy(pPatch->pzFilename, s);
-
pPatch->nLineNo =
readlong(f);
pPatch->nOffset =
@@ -272,21 +284,28 @@
*/
struct sSection *
-obj_ReadRGB1Section(FILE * f)
+obj_ReadRGBSection(FILE * f, enum ObjectFileContents contents)
{
struct sSection *pSection;
pSection = AllocSection();
+ if (contents & CONTAINS_SECTION_NAME) {
+ readasciiz(&pSection->pzName, f);
+ } else {
+ pSection->pzName = "";
+ }
+
pSection->nByteSize = readlong(f);
pSection->Type = (enum eSectionType) fgetc(f);
- /*
- * And because of THIS new feature I'll have to rewrite loads and
- * loads of stuff... oh well it needed to be done anyway
- *
- */
pSection->nOrg = readlong(f);
pSection->nBank = readlong(f);
+
+ if (contents & CONTAINS_SECTION_ALIGNMENT) {
+ pSection->nAlign = readlong(f);
+ } else {
+ pSection->nAlign = 1;
+ }
/* does the user want the -s mode? */
@@ -306,7 +325,6 @@
SLONG nNumberOfPatches;
struct sPatch **ppPatch, *pPatch;
- char s[256];
fread(pSection->pData, sizeof(UBYTE),
pSection->nByteSize, f);
@@ -324,13 +342,7 @@
}
*ppPatch = pPatch;
- readasciiz(s, f);
- pPatch->pzFilename = malloc(strlen(s) + 1);
- if (!pPatch->pzFilename) {
- err(1, NULL);
- }
-
- strcpy(pPatch->pzFilename, s);
+ readasciiz(&pPatch->pzFilename, f);
pPatch->nLineNo = readlong(f);
pPatch->nOffset = readlong(f);
pPatch->Type = (enum ePatchType) fgetc(f);
@@ -358,7 +370,7 @@
}
void
-obj_ReadRGB1(FILE * pObjfile)
+obj_ReadRGB(FILE * pObjfile, enum ObjectFileContents contents)
{
struct sSection *pFirstSection;
SLONG nNumberOfSymbols, nNumberOfSections, i;
@@ -385,7 +397,7 @@
while (nNumberOfSections--) {
struct sSection *pNewSection;
- pNewSection = obj_ReadRGB1Section(pObjfile);
+ pNewSection = obj_ReadRGBSection(pObjfile, contents);
pNewSection->nNumberOfSymbols = nNumberOfSymbols;
if (pFirstSection == NULL)
pFirstSection = pNewSection;
@@ -432,8 +444,12 @@
case '1':
case '2':
//V2 is really the same but the are new patch types
- obj_ReadRGB1(pObjfile);
+ obj_ReadRGB(pObjfile, 0);
break;
+ case '3':
+ // V3 is very similiar, but contains section names and byte alignment
+ obj_ReadRGB(pObjfile, CONTAINS_SECTION_NAME | CONTAINS_SECTION_ALIGNMENT);
+ break;
default:
errx(1, "'%s' is an unsupported version", tzObjectfile);
}
@@ -482,9 +498,9 @@
size = file_Length(f) - 4;
while (size) {
- char name[256];
+ char *name;
- size -= readasciiz(name, f);
+ size -= readasciiz(&name, f);
readword(f);
size -= 2;
readword(f);
@@ -492,5 +508,6 @@
size -= readlong(f);
size -= 4;
obj_ReadOpenFile(f, name);
+ free(name);
}
}