mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
float stuff
This commit is contained in:
parent
35b112eb2c
commit
89ac374db9
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
// """
|
||||
// }
|
||||
|
||||
)
|
||||
|
||||
}
|
||||
|
@ -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"),
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user