diff --git a/man/rgbasm.5 b/man/rgbasm.5 index 46bba38ad..c9c1d0d5b 100644 --- a/man/rgbasm.5 +++ b/man/rgbasm.5 @@ -903,7 +903,7 @@ SECTION "LOAD example", ROMX CopyCode: ld de, RAMCode ld hl, RAMLocation - ld c, RAMLocation.end - RAMLocation + ld c, RAMCode.end - RAMCode \&.loop ld a, [de] inc de @@ -927,8 +927,8 @@ RAMLocation: \&.string db "Hello World!\e0" -\&.end ENDL +\&.end .Ed .Pp A @@ -938,7 +938,9 @@ block feels similar to a declaration because it creates a new one. All data and code generated within such a block is placed in the current section like usual, but all labels are created as if they were placed in this newly-created section. .Pp -In the example above, all of the code and data will end up in the "LOAD example" section. +In the example above, all of the code and data will end up in the +.Dq LOAD example +section. You will notice the .Sq RAMCode and @@ -950,6 +952,19 @@ You cannot nest .Ic LOAD blocks, nor can you change or stop the current section within them. .Pp +The current +.Ic LOAD +block can be ended by using +.Ic ENDL . +This directive is only necessary if you want to resume writing code in its containing ROM section. +Any of +.Ic LOAD , SECTION , ENDSECTION , +or +.Ic POPS +will end the current +.Ic LOAD +block before performing its own function. +.Pp .Ic LOAD blocks can use the .Ic UNION diff --git a/src/asm/section.cpp b/src/asm/section.cpp index cd7950bb4..48625940d 100644 --- a/src/asm/section.cpp +++ b/src/asm/section.cpp @@ -425,14 +425,14 @@ void sect_NewSection( SectionSpec const &attrs, SectionModifier mod ) { - if (currentLoadSection) - fatalerror("Cannot change the section within a `LOAD` block\n"); - for (SectionStackEntry &entry : sectionStack) { if (entry.section && entry.section->name == name) fatalerror("Section '%s' is already on the stack\n", name.c_str()); } + if (currentLoadSection) + sect_EndLoadSection(); + Section *sect = getSection(name, type, org, attrs, mod); changeSection(); @@ -457,11 +457,6 @@ void sect_SetLoadSection( if (!requireCodeSection()) return; - if (currentLoadSection) { - error("`LOAD` blocks cannot be nested\n"); - return; - } - if (sect_HasData(type)) { error("`LOAD` blocks cannot create a ROM section\n"); return; @@ -472,6 +467,9 @@ void sect_SetLoadSection( return; } + if (currentLoadSection) + sect_EndLoadSection(); + Section *sect = getSection(name, type, org, attrs, mod); currentLoadLabelScopes = sym_GetCurrentLabelScopes(); @@ -954,7 +952,7 @@ void sect_PopSection() { fatalerror("No entries in the section stack\n"); if (currentLoadSection) - fatalerror("Cannot change the section within a `LOAD` block\n"); + sect_EndLoadSection(); SectionStackEntry entry = sectionStack.front(); sectionStack.pop_front(); @@ -972,12 +970,12 @@ void sect_EndSection() { if (!currentSection) fatalerror("Cannot end the section outside of a SECTION\n"); - if (currentLoadSection) - fatalerror("Cannot end the section within a `LOAD` block\n"); - if (!currentUnionStack.empty()) fatalerror("Cannot end the section within a UNION\n"); + if (currentLoadSection) + sect_EndLoadSection(); + // Reset the section scope currentSection = nullptr; sym_ResetCurrentLabelScopes(); diff --git a/test/asm/endsection-in-load.err b/test/asm/endsection-in-load.err index 696beea1f..a8b82ca57 100644 --- a/test/asm/endsection-in-load.err +++ b/test/asm/endsection-in-load.err @@ -1,2 +1,3 @@ -FATAL: endsection-in-load.asm(3): - Cannot end the section within a `LOAD` block +error: endsection-in-load.asm(4): + Found `ENDL` outside of a `LOAD` block +error: Assembly aborted (1 error)! diff --git a/test/asm/load-endings.asm b/test/asm/load-endings.asm new file mode 100644 index 000000000..1d98d3df4 --- /dev/null +++ b/test/asm/load-endings.asm @@ -0,0 +1,51 @@ +MACRO data + db SECTION(@), \# +ENDM + +MACRO now_in + if strcmp("\1", "nothing") + assert !strcmp(SECTION(@), \1) + else + assert !def(@) + endc +ENDM + +now_in nothing + +SECTION "A", ROM0 + now_in "A" + data 1 + LOAD "P", WRAM0 + now_in "P" + data 2 + + ; LOAD after LOAD + LOAD "Q", WRAM0 + now_in "Q" + data 3 + +; SECTION after LOAD +SECTION "B", ROM0 + now_in "B" + data 4 + LOAD "R", WRAM0 + now_in "R" + data 5 + + ; PUSHS after LOAD + PUSHS + SECTION "C", ROM0 + now_in "C" + data 6 + LOAD "S", WRAM0 + now_in "S" + data 7 + + ; POPS after LOAD + POPS + now_in "R" + data 8 + +; ENDSECTION after LOAD +ENDSECTION +now_in nothing diff --git a/test/asm/load-endings.out.bin b/test/asm/load-endings.out.bin new file mode 100644 index 000000000..371b5348d --- /dev/null +++ b/test/asm/load-endings.out.bin @@ -0,0 +1 @@ +BRRAPQCS \ No newline at end of file diff --git a/test/asm/load-in-load.asm b/test/asm/load-in-load.asm index 28115a63b..5e25a5079 100644 --- a/test/asm/load-in-load.asm +++ b/test/asm/load-in-load.asm @@ -1,5 +1,5 @@ SECTION "outer", ROM0 -LOAD "inner", WRAM0 -LOAD "matryoshka", HRAM -ENDL -ENDL +LOAD "inner1", WRAM0 ; starts "inner1" +LOAD "inner2", HRAM ; ends "inner1", starts "inner2" +ENDL ; ends "inner2" +ENDL ; error diff --git a/test/asm/load-in-load.err b/test/asm/load-in-load.err index 7e68df175..f4a76292b 100644 --- a/test/asm/load-in-load.err +++ b/test/asm/load-in-load.err @@ -1,5 +1,3 @@ -error: load-in-load.asm(3): - `LOAD` blocks cannot be nested error: load-in-load.asm(5): Found `ENDL` outside of a `LOAD` block -error: Assembly aborted (2 errors)! +error: Assembly aborted (1 error)! diff --git a/test/asm/section-in-load.asm b/test/asm/section-in-load.asm index a32213e73..905beb651 100644 --- a/test/asm/section-in-load.asm +++ b/test/asm/section-in-load.asm @@ -1,4 +1,4 @@ -SECTION "outer", ROM0 +SECTION "outer1", ROM0 LOAD "ram", WRAM0 -SECTION "inner", ROM0 +SECTION "outer2", ROM0 ENDL diff --git a/test/asm/section-in-load.err b/test/asm/section-in-load.err index 69fd68ddd..f70e114aa 100644 --- a/test/asm/section-in-load.err +++ b/test/asm/section-in-load.err @@ -1,2 +1,3 @@ -FATAL: section-in-load.asm(3): - Cannot change the section within a `LOAD` block +error: section-in-load.asm(4): + Found `ENDL` outside of a `LOAD` block +error: Assembly aborted (1 error)!