added %option no_sysinit to avoid having the system re-initialization code executed at the start of the program

This commit is contained in:
Irmen de Jong 2020-09-23 23:01:47 +02:00
parent 2b9316c4ff
commit 1d1fe364d0
8 changed files with 57 additions and 64 deletions

View File

@ -709,7 +709,7 @@ internal class AstChecker(private val program: Program,
err("this directive may only occur in a block or at module level") err("this directive may only occur in a block or at module level")
if(directive.args.isEmpty()) if(directive.args.isEmpty())
err("missing option directive argument(s)") err("missing option directive argument(s)")
else if(directive.args.map{it.name in setOf("enable_floats", "force_output")}.any { !it }) else if(directive.args.map{it.name in setOf("enable_floats", "force_output", "no_sysinit")}.any { !it })
err("invalid option directive argument(s)") err("invalid option directive argument(s)")
} }
"%target" -> { "%target" -> {

View File

@ -27,7 +27,8 @@ data class CompilationOptions(val output: OutputType,
val launcher: LauncherType, val launcher: LauncherType,
val zeropage: ZeropageType, val zeropage: ZeropageType,
val zpReserved: List<IntRange>, val zpReserved: List<IntRange>,
val floats: Boolean) val floats: Boolean,
val noSysInit: Boolean)
class CompilerException(message: String?) : Exception(message) class CompilerException(message: String?) : Exception(message)

View File

@ -125,6 +125,7 @@ private fun determineCompilationOptions(program: Program): CompilationOptions {
as? Directive)?.args?.single()?.name?.toUpperCase() as? Directive)?.args?.single()?.name?.toUpperCase()
val allOptions = program.modules.flatMap { it.statements }.filter { it is Directive && it.directive == "%option" }.flatMap { (it as Directive).args }.toSet() val allOptions = program.modules.flatMap { it.statements }.filter { it is Directive && it.directive == "%option" }.flatMap { (it as Directive).args }.toSet()
val floatsEnabled = allOptions.any { it.name == "enable_floats" } val floatsEnabled = allOptions.any { it.name == "enable_floats" }
val noSysInit = allOptions.any { it.name == "no_sysinit" }
var zpType: ZeropageType = var zpType: ZeropageType =
if (zpoption == null) if (zpoption == null)
if(floatsEnabled) ZeropageType.FLOATSAFE else ZeropageType.KERNALSAFE if(floatsEnabled) ZeropageType.FLOATSAFE else ZeropageType.KERNALSAFE
@ -160,7 +161,7 @@ private fun determineCompilationOptions(program: Program): CompilationOptions {
return CompilationOptions( return CompilationOptions(
if (outputType == null) OutputType.PRG else OutputType.valueOf(outputType), if (outputType == null) OutputType.PRG else OutputType.valueOf(outputType),
if (launcherType == null) LauncherType.BASIC else LauncherType.valueOf(launcherType), if (launcherType == null) LauncherType.BASIC else LauncherType.valueOf(launcherType),
zpType, zpReserved, floatsEnabled zpType, zpReserved, floatsEnabled, noSysInit
) )
} }

View File

@ -126,13 +126,13 @@ internal class AsmGen(private val program: Program,
out(" .null $9e, format(' %d ', _prog8_entrypoint), $3a, $8f, ' prog8 by idj'") out(" .null $9e, format(' %d ', _prog8_entrypoint), $3a, $8f, ' prog8 by idj'")
out("+\t.word 0") out("+\t.word 0")
out("_prog8_entrypoint\t; assembly code starts here\n") out("_prog8_entrypoint\t; assembly code starts here\n")
if(!CompilationTarget.instance.initProcName.isNullOrEmpty()) if(!options.noSysInit && !CompilationTarget.instance.initProcName.isNullOrEmpty())
out(" jsr ${CompilationTarget.instance.initProcName}") out(" jsr ${CompilationTarget.instance.initProcName}")
} }
options.output == OutputType.PRG -> { options.output == OutputType.PRG -> {
out("; ---- program without basic sys call ----") out("; ---- program without basic sys call ----")
out("* = ${program.actualLoadAddress.toHex()}\n") out("* = ${program.actualLoadAddress.toHex()}\n")
if(!CompilationTarget.instance.initProcName.isNullOrEmpty()) if(!options.noSysInit && !CompilationTarget.instance.initProcName.isNullOrEmpty())
out(" jsr ${CompilationTarget.instance.initProcName}") out(" jsr ${CompilationTarget.instance.initProcName}")
} }
options.output == OutputType.RAW -> { options.output == OutputType.RAW -> {

View File

@ -129,7 +129,7 @@ class TestC64Zeropage {
@Test @Test
fun testNames() { fun testNames() {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false)) val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false))
zp.allocate("", DataType.UBYTE, null, errors) zp.allocate("", DataType.UBYTE, null, errors)
zp.allocate("", DataType.UBYTE, null, errors) zp.allocate("", DataType.UBYTE, null, errors)
@ -142,37 +142,37 @@ class TestC64Zeropage {
@Test @Test
fun testZpFloatEnable() { fun testZpFloatEnable() {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false)) val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false))
assertFailsWith<CompilerException> { assertFailsWith<CompilerException> {
zp.allocate("", DataType.FLOAT, null, errors) zp.allocate("", DataType.FLOAT, null, errors)
} }
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true)) val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, false))
assertFailsWith<CompilerException> { assertFailsWith<CompilerException> {
zp2.allocate("", DataType.FLOAT, null, errors) zp2.allocate("", DataType.FLOAT, null, errors)
} }
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true)) val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false))
zp3.allocate("", DataType.FLOAT, null, errors) zp3.allocate("", DataType.FLOAT, null, errors)
} }
@Test @Test
fun testZpModesWithFloats() { fun testZpModesWithFloats() {
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false)) C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false))
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false)) C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false))
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false)) C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false))
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false)) C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false))
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true)) C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false))
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true)) C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false))
assertFailsWith<CompilerException> { assertFailsWith<CompilerException> {
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), true)) C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), true, false))
} }
assertFailsWith<CompilerException> { assertFailsWith<CompilerException> {
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), true)) C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), true, false))
} }
} }
@Test @Test
fun testZpDontuse() { fun testZpDontuse() {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false)) val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, false))
println(zp.free) println(zp.free)
assertEquals(0, zp.available()) assertEquals(0, zp.available())
assertFailsWith<CompilerException> { assertFailsWith<CompilerException> {
@ -182,19 +182,19 @@ class TestC64Zeropage {
@Test @Test
fun testFreeSpaces() { fun testFreeSpaces() {
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true)) val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false))
assertEquals(16, zp1.available()) assertEquals(16, zp1.available())
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false)) val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false))
assertEquals(89, zp2.available()) assertEquals(89, zp2.available())
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false)) val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false))
assertEquals(125, zp3.available()) assertEquals(125, zp3.available())
val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false)) val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false))
assertEquals(238, zp4.available()) assertEquals(238, zp4.available())
} }
@Test @Test
fun testReservedSpace() { fun testReservedSpace() {
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false)) val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false))
assertEquals(238, zp1.available()) assertEquals(238, zp1.available())
assertTrue(50 in zp1.free) assertTrue(50 in zp1.free)
assertTrue(100 in zp1.free) assertTrue(100 in zp1.free)
@ -203,7 +203,7 @@ class TestC64Zeropage {
assertTrue(200 in zp1.free) assertTrue(200 in zp1.free)
assertTrue(255 in zp1.free) assertTrue(255 in zp1.free)
assertTrue(199 in zp1.free) assertTrue(199 in zp1.free)
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, listOf(50 .. 100, 200..255), false)) val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, listOf(50 .. 100, 200..255), false, false))
assertEquals(139, zp2.available()) assertEquals(139, zp2.available())
assertFalse(50 in zp2.free) assertFalse(50 in zp2.free)
assertFalse(100 in zp2.free) assertFalse(100 in zp2.free)
@ -216,7 +216,7 @@ class TestC64Zeropage {
@Test @Test
fun testBasicsafeAllocation() { fun testBasicsafeAllocation() {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true)) val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false))
assertEquals(16, zp.available()) assertEquals(16, zp.available())
assertFailsWith<ZeropageDepletedError> { assertFailsWith<ZeropageDepletedError> {
@ -239,7 +239,7 @@ class TestC64Zeropage {
@Test @Test
fun testFullAllocation() { fun testFullAllocation() {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false)) val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false))
assertEquals(238, zp.available()) assertEquals(238, zp.available())
val loc = zp.allocate("", DataType.UWORD, null, errors) val loc = zp.allocate("", DataType.UWORD, null, errors)
assertTrue(loc > 3) assertTrue(loc > 3)
@ -269,7 +269,7 @@ class TestC64Zeropage {
@Test @Test
fun testEfficientAllocation() { fun testEfficientAllocation() {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true)) val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false))
assertEquals(16, zp.available()) assertEquals(16, zp.available())
assertEquals(0x04, zp.allocate("", DataType.WORD, null, errors)) assertEquals(0x04, zp.allocate("", DataType.WORD, null, errors))
assertEquals(0x06, zp.allocate("", DataType.UBYTE, null, errors)) assertEquals(0x06, zp.allocate("", DataType.UBYTE, null, errors))

View File

@ -117,10 +117,15 @@ Directives
Level: module, block. Level: module, block.
Sets special compiler options. Sets special compiler options.
For a module option, only the ``enable_floats`` option is recognised, which will tell the compiler
- For a module option, there is ``enable_floats``, which will tell the compiler
to deal with floating point numbers (by using various subroutines from the Commodore-64 kernal). to deal with floating point numbers (by using various subroutines from the Commodore-64 kernal).
Otherwise, floating point support is not enabled. Otherwise, floating point support is not enabled.
When used in a block with the ``force_output`` option, it will force the block to be outputted - There's also ``no_sysinit`` which cause the resulting program to *not* include
the system re-initialization logic of clearing the screen, resetting I/O config etc. You'll have to
take care of that yourself. The program will just start running from whatever state the machine is in when the
program was launched.
- When used in a block with the ``force_output`` option, it will force the block to be outputted
in the final program. Can be useful to make sure some in the final program. Can be useful to make sure some
data is generated that would otherwise be discarded because it's not referenced (such as sprite data). data is generated that would otherwise be discarded because it's not referenced (such as sprite data).

View File

@ -3,7 +3,6 @@ TODO
==== ====
- get rid of all other TODO's in the code ;-) - get rid of all other TODO's in the code ;-)
- add an %option that omits the 'system-init' code at the start. Useful to create separate standalone routines that shouldn't re-init the whole machine every time they're called
- line-circle-gfx examples are now a few hundred bytes larger than before (~4.0/4.1 version i think?). Why is that, can it be fixed? - line-circle-gfx examples are now a few hundred bytes larger than before (~4.0/4.1 version i think?). Why is that, can it be fixed?
- until condition should be able to refer to variables defined IN the do-until block itself. - until condition should be able to refer to variables defined IN the do-until block itself.
- add support? example? for processing arguments to a sys call : sys 999, 1, 2, "aaa" - add support? example? for processing arguments to a sys call : sys 999, 1, 2, "aaa"

View File

@ -7,23 +7,10 @@
main $0900{ main $0900{
sub start() { sub start() {
do {
ubyte v = 1 ubyte v = 1
@($c000+v) = 10 } until v==0
txt.print_ub(@($c001))
txt.chrout('\n')
@($c000+v) ++
txt.print_ub(@($c001))
txt.chrout('\n')
@($c000+v) += 10
txt.print_ub(@($c001))
txt.chrout('\n')
@($c000+v) *= 10
txt.print_ub(@($c001))
txt.chrout('\n')
; @($c000) *= 99 ; TODO implement ; @($c000) *= 99 ; TODO implement