float stuff

This commit is contained in:
Irmen de Jong 2018-12-02 17:59:36 +01:00
parent 35b112eb2c
commit 89ac374db9
7 changed files with 164 additions and 95 deletions

View File

@ -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
}

View File

@ -1324,7 +1324,7 @@ data class IdentifierReference(val nameInSource: List<String>, 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)

View File

@ -27,7 +27,7 @@ fun Module.checkIdentifiers(heap: HeapValues): MutableMap<String, IStatement> {
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)")
}
}

View File

@ -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:
* <condition-expression evaluation>
* 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:
* <condition-expression evaluation>
* 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:
* <evaluate condition>
* 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:
* <evaluate untilCondition>
* 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()

View File

@ -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
// """
// }
)
}

View File

@ -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"),

View File

@ -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
todo_include_todos = True