From 89ac374db9a33506e925724dcb4131976f2bda22 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 2 Dec 2018 17:59:36 +0100 Subject: [PATCH] float stuff --- compiler/examples/test.p8 | 52 ++++++- compiler/src/prog8/ast/AST.kt | 2 +- .../src/prog8/ast/AstIdentifiersChecker.kt | 2 +- compiler/src/prog8/compiler/Compiler.kt | 46 ++++-- .../src/prog8/compiler/target/c64/AsmGen.kt | 147 +++++++++--------- compiler/test/StackVMOpcodeTests.kt | 6 +- docs/source/conf.py | 4 +- 7 files changed, 164 insertions(+), 95 deletions(-) diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index 6b024802a..c0e211cee 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -1,14 +1,58 @@ %import c64utils +%option enable_floats ~ main { sub start() { - memory ubyte[40] firstScreenLine = $0400 +; memory ubyte[40] firstScreenLine = $0400 +; word ww=333 +; +; Y=33 +; +; if(Y>3) { +; A=99 +; } else { +; A=100 +; } +; +; if(ww>33) { +; A=99 +; } else { +; A=100 +; } +; +; for ubyte c in 10 to 30 { +; firstScreenLine[c] = c +; } + + + float[10] farr + float f = 3.3 + memory float mflt = $c000 + memory float[10] mfarr = $d000 + ubyte i=3 + + mflt = 55.44 ; @todo fix memory variables for stackvm???! (or proper error) + mfarr[2] = 44.44 ; @todo fix memory variables for stackvm???! (or proper error) + + farr[2] = 4.44 + farr[2] = f + farr[2] = mflt + farr[2] = farr[3] + farr[2] = mfarr[3] + farr[Y] = 4.44 + farr[Y] = f + farr[Y] = mflt + farr[Y] = farr[3] + farr[Y] = mfarr[3] + farr[i] = 4.44 + farr[i] = f + farr[i] = mflt + farr[i] = farr[3] + farr[i] = mfarr[3] + - for ubyte c in 10 to 30 { - firstScreenLine[c] = c - } return } diff --git a/compiler/src/prog8/ast/AST.kt b/compiler/src/prog8/ast/AST.kt index 775a6af77..d425ff3bb 100644 --- a/compiler/src/prog8/ast/AST.kt +++ b/compiler/src/prog8/ast/AST.kt @@ -1324,7 +1324,7 @@ data class IdentifierReference(val nameInSource: List, override val posi } override fun process(processor: IAstProcessor) = processor.process(this) - override fun referencesIdentifier(name: String): Boolean = nameInSource.last() == name // @todo is this correct all the time? + override fun referencesIdentifier(name: String): Boolean = nameInSource.last() == name // @todo is this correct all the time? override fun resultingDatatype(namespace: INameScope, heap: HeapValues): DataType? { val targetStmt = targetStatement(namespace) diff --git a/compiler/src/prog8/ast/AstIdentifiersChecker.kt b/compiler/src/prog8/ast/AstIdentifiersChecker.kt index 761cbbf3b..85021f3e9 100644 --- a/compiler/src/prog8/ast/AstIdentifiersChecker.kt +++ b/compiler/src/prog8/ast/AstIdentifiersChecker.kt @@ -27,7 +27,7 @@ fun Module.checkIdentifiers(heap: HeapValues): MutableMap { val parameterPos = parent.arglist.indexOf(variable.first) parent.arglist[parameterPos] = IdentifierReference(listOf("auto_heap_value_${variable.first.heapId}"), variable.first.position) } - else -> TODO("replace literalvalue by identifierref $variable (in $parent)") + else -> TODO("replace literalvalue by identifierref: $variable (in $parent)") } } diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 1a85a4f81..c7133a62e 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -414,8 +414,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, * An IF statement: IF (condition-expression) { stuff } else { other_stuff } * Which is translated into: * - * TEST - * BZ _stmt_999_else + * JZ/JZW _stmt_999_else * stuff * JUMP _stmt_999_end * _stmt_999_else: @@ -425,8 +424,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, * * or when there is no else block: * - * TEST - * BZ _stmt_999_end + * JZ/JZW _stmt_999_end * stuff * _stmt_999_end: * nop @@ -435,14 +433,19 @@ private class StatementTranslator(private val prog: IntermediateProgram, */ prog.line(stmt.position) translate(stmt.condition) + val conditionJumpOpcode = when(stmt.condition.resultingDatatype(namespace, heap)) { + DataType.UBYTE, DataType.BYTE -> Opcode.JZ + DataType.UWORD, DataType.WORD -> Opcode.JZW + else -> throw CompilerException("invalid condition datatype (expected byte or word) $stmt") + } val labelEnd = makeLabel("end") if(stmt.elsepart.isEmpty()) { - prog.instr(Opcode.JZ, callLabel = labelEnd) // TODO JZW??? + prog.instr(conditionJumpOpcode, callLabel = labelEnd) translate(stmt.truepart) prog.label(labelEnd) } else { val labelElse = makeLabel("else") - prog.instr(Opcode.JZ, callLabel = labelElse) // TODO JZW??? + prog.instr(conditionJumpOpcode, callLabel = labelElse) translate(stmt.truepart) prog.instr(Opcode.JUMP, callLabel = labelEnd) prog.label(labelElse) @@ -1593,7 +1596,10 @@ private class StatementTranslator(private val prog: IntermediateProgram, prog.instr(opcodePush(zero.type), Value(zero.type, numElements)) prog.instr(opcodePushvar(zero.type), callLabel = "X") prog.instr(opcodeSub(zero.type)) - prog.instr(Opcode.JNZ, callLabel = loopLabel) // TODO JNZW??? + if(zero.type==DataType.UWORD) + prog.instr(Opcode.JNZW, callLabel = loopLabel) + else + prog.instr(Opcode.JNZ, callLabel = loopLabel) prog.label(breakLabel) prog.instr(Opcode.NOP) @@ -1655,8 +1661,12 @@ private class StatementTranslator(private val prog: IntermediateProgram, prog.instr(opcodePush(varDt), Value(varDt, range.last + range.step)) prog.instr(opcodePushvar(varDt), callLabel = varname) prog.instr(opcodeSub(varDt)) - prog.instr(Opcode.JNZ, callLabel = loopLabel) // TODO JNZW??? - + val loopvarJumpOpcode = when(varDt) { + DataType.UBYTE, DataType.BYTE -> Opcode.JNZ + DataType.UWORD, DataType.WORD -> Opcode.JNZW + else -> throw CompilerException("invalid loop var datatype (expected byte or word) $varDt of var $varname") + } + prog.instr(loopvarJumpOpcode, callLabel = loopLabel) prog.label(breakLabel) prog.instr(Opcode.NOP) // note: ending value of loop register / variable is *undefined* after this point! @@ -1812,7 +1822,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, * continue -> goto condition * continue: * - * jnz loop + * jnz/jnzw loop * break: * nop */ @@ -1827,7 +1837,12 @@ private class StatementTranslator(private val prog: IntermediateProgram, translate(stmt.body) prog.label(continueLabel) translate(stmt.condition) - prog.instr(Opcode.JNZ, callLabel = loopLabel) // TODO JNZW??? + val conditionJumpOpcode = when(stmt.condition.resultingDatatype(namespace, heap)) { + DataType.UBYTE, DataType.BYTE -> Opcode.JNZ + DataType.UWORD, DataType.WORD -> Opcode.JNZW + else -> throw CompilerException("invalid condition datatype (expected byte or word) $stmt") + } + prog.instr(conditionJumpOpcode, callLabel = loopLabel) prog.label(breakLabel) prog.instr(Opcode.NOP) breakStmtLabelStack.pop() @@ -1846,7 +1861,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, * continue -> goto condition * condition: * - * jz goto loop + * jz/jzw goto loop * break: * nop */ @@ -1860,7 +1875,12 @@ private class StatementTranslator(private val prog: IntermediateProgram, translate(stmt.body) prog.label(continueLabel) translate(stmt.untilCondition) - prog.instr(Opcode.JZ, callLabel = loopLabel) // TODO JZW??? + val conditionJumpOpcode = when(stmt.untilCondition.resultingDatatype(namespace, heap)) { + DataType.UBYTE, DataType.BYTE -> Opcode.JZ + DataType.UWORD, DataType.WORD -> Opcode.JZW + else -> throw CompilerException("invalid condition datatype (expected byte or word) $stmt") + } + prog.instr(conditionJumpOpcode, callLabel = loopLabel) prog.label(breakLabel) prog.instr(Opcode.NOP) breakStmtLabelStack.pop() diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 1161e65f9..bf8638a18 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -207,6 +207,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, if(processed==0) { processed = instr2asm(ins) if(processed == 0) + // the instructions are not recognised yet and can't be translated into assembly throw CompilerException("no asm translation found for instruction pattern: $ins") } processed-- @@ -458,6 +459,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, dex """ } + Opcode.PUSH_MEM_FLOAT -> { + " lda #<${hexVal(ins)} | ldy #>${hexVal(ins)}| jsr prog8_lib.push_float" + } Opcode.PUSH_REGAY_WORD -> { " sta ${ESTACK_LO.toHex()},x | tya | sta ${ESTACK_HI.toHex()},x | dex " @@ -468,37 +472,30 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, " inx | lda ${ESTACK_LO.toHex()},x | ldy ${ESTACK_HI.toHex()},x " } - Opcode.READ_INDEXED_VAR_BYTE -> { // @todo is this correct? + Opcode.READ_INDEXED_VAR_BYTE -> { + TODO("$ins") + } + Opcode.READ_INDEXED_VAR_WORD -> { + TODO("$ins") + } + Opcode.READ_INDEXED_VAR_FLOAT -> { """ - ldy ${(ESTACK_LO+1).toHex()},x - lda ${ins.callLabel},y - sta ${(ESTACK_LO+1).toHex()},x + lda #<${ins.callLabel} + ldy #>${ins.callLabel} + jsr prog8_lib.push_float_from_indexed_var """ } - Opcode.READ_INDEXED_VAR_WORD -> { // @todo correct this - """ - ldy ${(ESTACK_LO+1).toHex()},x - lda ${ins.callLabel},y - sta ${(ESTACK_LO+1).toHex()},x - """ + Opcode.WRITE_INDEXED_VAR_BYTE -> { + TODO("$ins") } - - Opcode.WRITE_INDEXED_VAR_BYTE -> { // @todo is this correct? - """ - inx - ldy ${ESTACK_LO.toHex()},x - inx - lda ${ESTACK_LO.toHex()},x - sta ${ins.callLabel},y - """ + Opcode.WRITE_INDEXED_VAR_WORD -> { + TODO("$ins") } - Opcode.WRITE_INDEXED_VAR_WORD -> { // @todo correct this + Opcode.WRITE_INDEXED_VAR_FLOAT -> { """ - inx - ldy ${ESTACK_LO.toHex()},x - inx - lda ${ESTACK_LO.toHex()},x - sta ${ins.callLabel},y + lda #<${ins.callLabel} + ldy #>${ins.callLabel} + jsr prog8_lib.pop_float_to_indexed_var """ } Opcode.POP_MEM_BYTE -> { @@ -1016,7 +1013,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, } } - private fun storeAToIndexedByVar(idxVarInstr: Instruction, writeArrayInstr: Instruction): String { // writeArrayInstr [ idxVarInstr ] = A return when (idxVarInstr.callLabel) { @@ -2516,7 +2512,60 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, jsr prog8_lib.copy_float """ }, - + // floatarray[idxbyte] = float + AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> + val floatConst = getFloatConst(segment[0].arg!!) + val index = intVal(segment[1]) * Mflpt5.MemorySize + """ + lda #<$floatConst + ldy #>$floatConst + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1+1} + lda #<(${segment[2].callLabel}+$index) + ldy #>(${segment[2].callLabel}+$index) + jsr prog8_lib.copy_float + """ + }, + // floatarray[idxbyte] = floatvar + AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> + val index = intVal(segment[1]) * Mflpt5.MemorySize + """ + lda #<${segment[0].callLabel} + ldy #>${segment[0].callLabel} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1+1} + lda #<(${segment[2].callLabel}+$index) + ldy #>(${segment[2].callLabel}+$index) + jsr prog8_lib.copy_float + """ + }, + // floatarray[idxbyte] = memfloat + AsmPattern(listOf(Opcode.PUSH_MEM_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> + val index = intVal(segment[1]) * Mflpt5.MemorySize + """ + lda #<${hexVal(segment[0])} + ldy #>${hexVal(segment[0])} + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1+1} + lda #<(${segment[2].callLabel}+$index) + ldy #>(${segment[2].callLabel}+$index) + jsr prog8_lib.copy_float + """ + }, + // floatarray[idx2] = floatarray[idx1] + AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> + val index1 = intVal(segment[0]) * Mflpt5.MemorySize + val index2 = intVal(segment[2]) * Mflpt5.MemorySize + """ + lda #<(${segment[1].callLabel}+$index1) + ldy #>(${segment[1].callLabel}+$index1) + sta ${C64Zeropage.SCRATCH_W1} + sty ${C64Zeropage.SCRATCH_W1+1} + lda #<(${segment[3].callLabel}+$index2) + ldy #>(${segment[3].callLabel}+$index2) + jsr prog8_lib.copy_float + """ + }, // ---------- some special operations ------------------ // var word = AX register pair @@ -2608,50 +2657,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, " ldx ${hexVal(segment[0])} | ldy ${hexValPlusOne(segment[0])}" } - - - -// // @todo assignment: floatarray[idxbyte] = float -// AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> -// val floatConst = getFloatConst(segment[0].arg!!) -// val index = intVal(segment[1]) * Mflpt5.MemorySize -// """ -// lda #<$floatConst -// ldy #>$floatConst -// sta ${C64Zeropage.SCRATCH_W1} -// sty ${C64Zeropage.SCRATCH_W1+1} -// lda #<(${segment[2].callLabel}+$index) -// ldy #>(${segment[2].callLabel}+$index) -// jsr prog8_lib.copy_float -// """ -// }, -// // @todo assignment: floatarray[idxbyte] = floatvar -// AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> -// val index = intVal(segment[1]) * Mflpt5.MemorySize -// """ -// lda #<${segment[0].callLabel} -// ldy #>${segment[0].callLabel} -// sta ${C64Zeropage.SCRATCH_W1} -// sty ${C64Zeropage.SCRATCH_W1+1} -// lda #<(${segment[2].callLabel}+$index) -// ldy #>(${segment[2].callLabel}+$index) -// jsr prog8_lib.copy_float -// """ -// }, -// // @todo assignment: floatarray[idxbyte] = memfloat -// AsmPattern(listOf(Opcode.PUSH_MEM_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment -> -// val index = intVal(segment[1]) * Mflpt5.MemorySize -// """ -// lda #<${hexVal(segment[0])} -// ldy #>${hexVal(segment[0])} -// sta ${C64Zeropage.SCRATCH_W1} -// sty ${C64Zeropage.SCRATCH_W1+1} -// lda #<(${segment[2].callLabel}+$index) -// ldy #>(${segment[2].callLabel}+$index) -// jsr prog8_lib.copy_float -// """ -// } - ) } diff --git a/compiler/test/StackVMOpcodeTests.kt b/compiler/test/StackVMOpcodeTests.kt index 06d2ec22c..a433dacf6 100644 --- a/compiler/test/StackVMOpcodeTests.kt +++ b/compiler/test/StackVMOpcodeTests.kt @@ -42,6 +42,8 @@ import kotlin.test.* ROR2_VAR, ROR2_VAR_W + and several others. + **/ @TestInstance(TestInstance.Lifecycle.PER_CLASS) @@ -651,7 +653,7 @@ class TestStackVmOpcodes { assertEquals(DataType.UBYTE, rndb2.type) assertEquals(DataType.UWORD, rndw.type) assertEquals(DataType.FLOAT, rndf.type) - assertNotEquals(rndb1.integerValue(), rndb2.integerValue()) + assertNotEquals(rndb1.integerValue(), rndb2.integerValue()) // this *sometimes* fails when the two random numbers are the same by pure chance assertTrue(rndf.numericValue().toDouble() > 0.0 && rndf.numericValue().toDouble() < 1.0) vm.step(2) @@ -892,7 +894,6 @@ class TestStackVmOpcodes { @Test fun testReturn() { - // @todo this only tests return with zero return values for now. val ins = mutableListOf( Instruction(Opcode.RETURN), Instruction(Opcode.TERMINATE), @@ -913,7 +914,6 @@ class TestStackVmOpcodes { @Test fun testCall() { - // @todo this only tests call with zero parameters for now. val ins = mutableListOf( Instruction(Opcode.CALL, callLabel = "label"), Instruction(Opcode.LINE, callLabel = "returned"), diff --git a/docs/source/conf.py b/docs/source/conf.py index 1c31524fb..f65623a61 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -169,7 +169,7 @@ texinfo_documents = [ # -- Extension configuration ------------------------------------------------- -# -- Options for todo extension ---------------------------------------------- +# -- Options for to do extension ---------------------------------------------- # If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True \ No newline at end of file +todo_include_todos = True