force_output option added

This commit is contained in:
Irmen de Jong 2019-01-01 21:47:19 +01:00
parent 21136e8cad
commit 39a8b76534
8 changed files with 43 additions and 30 deletions

View File

@ -1,10 +1,10 @@
%import c64lib
%import c64utils
%option force_output, enable_floats
~ main {
const uword SP0X = $d000
const uword SP0Y = $d001
~ spritedata $0a00 {
%option force_output ; make sure the data appears in the program
ubyte[63] balloonsprite = [ %00000000,%01111111,%00000000,
%00000001,%11111111,%11000000,
@ -27,23 +27,26 @@
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00011100,%00000000 ]
}
const uword sprite_data_address = 13*64 ; // safe area inside the tape buffer
~ main {
const uword SP0X = $d000
const uword SP0Y = $d001
sub start() {
c64.STROUT("balloon sprites!\n")
c64.STROUT("...we are all floating...\n")
memcopy(balloonsprite, sprite_data_address, 63)
c64.SPRPTR0 = sprite_data_address//64
c64.SPRPTR1 = sprite_data_address//64
c64.SPRPTR2 = sprite_data_address//64
c64.SPRPTR3 = sprite_data_address//64
c64.SPRPTR4 = sprite_data_address//64
c64.SPRPTR5 = sprite_data_address//64
c64.SPRPTR6 = sprite_data_address//64
c64.SPRPTR7 = sprite_data_address//64
c64.SPRPTR0 = $0a00//64
c64.SPRPTR1 = $0a00//64
c64.SPRPTR2 = $0a00//64
c64.SPRPTR3 = $0a00//64
c64.SPRPTR4 = $0a00//64
c64.SPRPTR5 = $0a00//64
c64.SPRPTR6 = $0a00//64
c64.SPRPTR7 = $0a00//64
for ubyte i in 0 to 7 {
@(SP0X+i*2) = 50+25*i

View File

@ -1,6 +1,8 @@
%import c64utils
%option enable_floats
~ main {
ubyte[3] balloonsprite = [ %00000000,%01111111,%00000000 ]
sub start() {
@ -14,8 +16,5 @@
@($d020) = @($d020+i) + 1
@($d020+i) = @($d020+i) + 1
c64scr.print_ub(X)
i = 2+balloonsprite
}
}

View File

@ -523,6 +523,8 @@ class Block(override val name: String,
override fun toString(): String {
return "Block(name=$name, address=$address, ${statements.size} statements)"
}
val options = statements.filter { it is Directive && it.directive == "%option" }.flatMap { (it as Directive).args }.map {it.name!!}.toSet()
}

View File

@ -617,17 +617,17 @@ class AstChecker(private val namespace: INameScope,
err("invalid import directive, cannot import itself")
}
"%breakpoint" -> {
if(directive.parent is Module) err("this directive may only occur in a block")
if(directive.parent !is Block) err("this directive may only occur in a block")
if(directive.args.isNotEmpty())
err("invalid breakpoint directive, expected no arguments")
}
"%asminclude" -> {
if(directive.parent is Module) err("this directive may only occur in a block")
if(directive.parent !is Block) err("this directive may only occur in a block")
if(directive.args.size!=2 || directive.args[0].str==null || directive.args[1].name==null)
err("invalid asminclude directive, expected arguments: \"filename\", scopelabel")
}
"%asmbinary" -> {
if(directive.parent is Module) err("this directive may only occur in a block")
if(directive.parent !is Block) err("this directive may only occur in a block")
val errormsg = "invalid asmbinary directive, expected arguments: \"filename\" [, offset [, length ] ]"
if(directive.args.isEmpty()) err(errormsg)
if(directive.args.isNotEmpty() && directive.args[0].str==null) err(errormsg)
@ -636,8 +636,10 @@ class AstChecker(private val namespace: INameScope,
if(directive.args.size>3) err(errormsg)
}
"%option" -> {
if(directive.parent !is Module) err("this directive may only occur at module level")
if(directive.args.size!=1 || directive.args[0].name != "enable_floats")
if(directive.parent !is Block && directive.parent !is Module) err("this directive may only occur in a block or at module level")
if(directive.args.isEmpty())
err("missing option directive argument(s)")
else if(directive.args.map{it.name in setOf("enable_floats", "force_output")}.any { !it })
err("invalid option directive argument(s)")
}
else -> throw SyntaxError("invalid directive ${directive.directive}", directive.position)

View File

@ -151,7 +151,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
val continueStmtLabelStack : Stack<String> = Stack()
override fun process(block: Block): IStatement {
prog.newBlock(block.scopedname, block.name, block.address)
prog.newBlock(block.scopedname, block.name, block.address, block.options)
processVariables(block) // @todo optimize initializations with same value: load the value only once (sort on initalization value, datatype ?)
prog.label("block."+block.scopedname)
prog.line(block.position)

View File

@ -14,7 +14,8 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
val instructions: MutableList<Instruction> = mutableListOf(),
val variables: MutableMap<String, Value> = mutableMapOf(),
val memoryPointers: MutableMap<String, Pair<Int, DataType>> = mutableMapOf(),
val labels: MutableMap<String, Instruction> = mutableMapOf())
val labels: MutableMap<String, Instruction> = mutableMapOf(),
val force_output: Boolean)
{
val numVariables: Int
get() { return variables.size }
@ -368,8 +369,8 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
currentBlock.memoryPointers[name] = Pair(address, datatype)
}
fun newBlock(scopedname: String, shortname: String, address: Int?) {
currentBlock = ProgramBlock(scopedname, shortname, address)
fun newBlock(scopedname: String, shortname: String, address: Int?, options: Set<String>) {
currentBlock = ProgramBlock(scopedname, shortname, address, force_output="force_output" in options)
blocks.add(currentBlock)
}

View File

@ -49,7 +49,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
newinstructions,
newvars,
newConstants,
newlabels))
newlabels,
force_output = block.force_output))
}
program.blocks.clear()
program.blocks.addAll(newblocks)
@ -196,7 +197,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
out(".cerror * > ${block.address?.toHex()}, 'block address overlaps by ', *-${block.address?.toHex()},' bytes'")
out("* = ${block.address?.toHex()}")
}
out("${block.shortname}\t.proc\n")
if(!blk.force_output)
out("${block.shortname}\t.proc\n")
out("\n; memdefs and kernel subroutines")
memdefs2asm(block)
out("\n; variables")
@ -218,7 +220,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
processed--
}
if (trace) println("END BLOCK: ${block.scopedname}")
out("\n\t.pend\n")
if(!blk.force_output)
out("\n\t.pend\n")
}
private fun memdefs2asm(block: IntermediateProgram.ProgramBlock) {

View File

@ -103,11 +103,14 @@ Directives
.. data:: %option <option> [, <option> ...]
Level: module.
Level: module, block.
Sets special compiler options.
For now, only the ``enable_floats`` option is recognised, which will tell the compiler
For a module option, only the ``enable_floats`` option is recognised, which will tell the compiler
to deal with floating point numbers (by using various subroutines from the Commodore-64 kernal).
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
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:: %asmbinary "<filename>" [, <offset>[, <length>]]