ref: 76d6ef869582a3c714a4b8c7839c2d445b4bfcb1
parent: c67a696a87a35ba3c2fcf10468a6043c2426643c
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Sun Feb 14 11:55:19 EST 2021
Implement LOAD UNION and LOAD FRAGMENT Fix #632
--- a/include/asm/section.h
+++ b/include/asm/section.h
@@ -43,7 +43,8 @@
struct SectionSpec const *attributes,
enum SectionModifier mod);
void out_SetLoadSection(char const *name, uint32_t secttype, uint32_t org,
- struct SectionSpec const *attributes);
+ struct SectionSpec const *attributes,
+ enum SectionModifier mod);
void out_EndLoadSection(void);
struct Section *sect_GetSymbolSection(void);
--- a/src/asm/parser.y
+++ b/src/asm/parser.y
@@ -853,8 +853,8 @@
| T_POP_SHIFT const { macro_ShiftCurrentArgs($2); }
;
-load : T_POP_LOAD string T_COMMA sectiontype sectorg sectattrs {
- out_SetLoadSection($2, $4, $5, &$6);
+load : T_POP_LOAD sectmod string T_COMMA sectiontype sectorg sectattrs {
+ out_SetLoadSection($3, $5, $6, &$7, $2);
}
| T_POP_ENDL { out_EndLoadSection(); }
;
--- a/src/asm/rgbasm.5
+++ b/src/asm/rgbasm.5
@@ -719,6 +719,13 @@
You cannot nest
.Ic LOAD
blocks, nor can you change the current section within them.
+.Pp
+.Ic LOAD
+blocks can use the
+.Ic UNION
+or
+.Ic FRAGMENT
+modifiers, as described below.
.Ss Unionized Sections
When you're tight on RAM, you may want to define overlapping blocks of variables, as explained in the
.Sx Unions
--- a/src/asm/section.c
+++ b/src/asm/section.c
@@ -30,7 +30,7 @@
struct SectionStackEntry *sectionStack;
uint32_t curOffset; /* Offset into the current section (see sect_GetSymbolOffset) */
static struct Section *currentLoadSection = NULL;
-uint32_t loadOffset; /* The offset of the LOAD section within its parent */
+int32_t loadOffset; /* Offset into the LOAD section's parent (see sect_GetOutputOffset) */
struct UnionStackEntry {
uint32_t start;
@@ -387,7 +387,8 @@
* Set the current section by name and type
*/
void out_SetLoadSection(char const *name, uint32_t type, uint32_t org,
- struct SectionSpec const *attribs)
+ struct SectionSpec const *attribs,
+ enum SectionModifier mod)
{
checkcodesection();
@@ -397,11 +398,11 @@
if (sect_HasData(type))
error("`LOAD` blocks cannot create a ROM section\n");
- struct Section *sect = getSection(name, type, org, attribs, false);
+ struct Section *sect = getSection(name, type, org, attribs, mod);
- loadOffset = curOffset;
- curOffset = 0; /* curOffset -= loadOffset; */
changeSection();
+ loadOffset = curOffset - (mod == SECTION_UNION ? 0 : sect->size);
+ curOffset -= loadOffset;
currentLoadSection = sect;
}
@@ -409,11 +410,11 @@
{
if (!currentLoadSection)
error("Found `ENDL` outside of a `LOAD` block\n");
- currentLoadSection = NULL;
changeSection();
curOffset += loadOffset;
loadOffset = 0;
+ currentLoadSection = NULL;
}
struct Section *sect_GetSymbolSection(void)
--- /dev/null
+++ b/test/asm/load-fragment.asm
@@ -1,0 +1,29 @@
+SECTION "A", ROM0
+AData::
+LOAD FRAGMENT "RAM", WRAM0
+AMem::
+ db 0, 1, 2
+AMemEnd::
+ENDL
+ADataEnd::
+ dw AMem
+
+SECTION "B", ROM0
+BData::
+LOAD FRAGMENT "RAM", WRAM0
+BMem::
+ db 3, 4, 5, 6, 7
+BMemEnd::
+ENDL
+BDataEnd::
+ dw BMem
+
+SECTION "C", ROM0
+CData::
+LOAD FRAGMENT "RAM", WRAM0
+CMem::
+ db 8, 9
+CMemEnd::
+ENDL
+CDataEnd::
+ dw CMem
binary files /dev/null b/test/asm/load-fragment.out.bin differ
--- /dev/null
+++ b/test/asm/load-union.asm
@@ -1,0 +1,29 @@
+SECTION "A", ROM0
+AData::
+LOAD UNION "RAM", WRAM0
+AMem::
+ db 0, 1, 2
+AMemEnd::
+ENDL
+ADataEnd::
+ dw AMem
+
+SECTION "B", ROM0
+BData::
+LOAD UNION "RAM", WRAM0
+BMem::
+ db 3, 4, 5, 6, 7
+BMemEnd::
+ENDL
+BDataEnd::
+ dw BMem
+
+SECTION "C", ROM0
+CData::
+LOAD UNION "RAM", WRAM0
+CMem::
+ db 8, 9
+CMemEnd::
+ENDL
+CDataEnd::
+ dw CMem
binary files /dev/null b/test/asm/load-union.out.bin differ