From da01a5b4dc94b22f32bd9848a8d0dbc884e853ad Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 4 May 2022 20:47:48 +0200 Subject: [PATCH] vm: implement float to integer cast, any, all, reverse --- .../cpu6502/assignment/AssignmentAsmGen.kt | 6 +- .../prog8/codegen/virtual/BuiltinFuncGen.kt | 24 ++-- .../prog8/codegen/virtual/ExpressionGen.kt | 64 +++++---- compiler/res/prog8lib/virtual/floats.p8 | 2 +- docs/source/todo.rst | 5 +- examples/test.p8 | 22 +-- syntax-files/IDEA/Prog8.xml | 2 +- syntax-files/NotepadPlusPlus/Prog8.xml | 2 +- syntax-files/Vim/prog8_builtins.vim | 2 +- virtualmachine/src/prog8/vm/SysCalls.kt | 134 +++++------------- virtualmachine/src/prog8/vm/VirtualMachine.kt | 32 ++++- 11 files changed, 136 insertions(+), 159 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 2a67860cd..ec0e45723 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -328,8 +328,6 @@ internal class AssignmentAsmGen(private val program: Program, val variable = (containment.iterable as? IdentifierReference)?.targetVarDecl(program) ?: throw AssemblyError("invalid containment iterable type") - if(elementDt istype DataType.FLOAT) - throw AssemblyError("containment check of floats not supported") if(variable.origin!=VarDeclOrigin.USERCODE) { when(variable.datatype) { DataType.STR -> { @@ -388,7 +386,9 @@ internal class AssignmentAsmGen(private val program: Program, asmgen.out(" jsr prog8_lib.containment_bytearray") return } - DataType.ARRAY_F -> throw AssemblyError("containment check of floats not supported") + DataType.ARRAY_F -> { + throw AssemblyError("containment check of floats not supported") + } DataType.ARRAY_B, DataType.ARRAY_UB -> { val arrayVal = variable.value as ArrayLiteral assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt istype DataType.BYTE) diff --git a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt index d68540c00..cf5fc594a 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt @@ -64,36 +64,34 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: private fun funcAny(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { val arrayName = call.args[0] as PtIdentifier val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable - val elementDt: VmDataType = codeGen.vmType(ArrayToElementTypes.getValue(array.dt)) + val code = VmCodeChunk() val syscall = - when(array.dt) { + when (array.dt) { DataType.ARRAY_UB, DataType.ARRAY_B -> Syscall.ANY_BYTE DataType.ARRAY_UW, DataType.ARRAY_W -> Syscall.ANY_WORD - DataType.ARRAY_F -> TODO("float any") + DataType.ARRAY_F -> Syscall.ANY_FLOAT else -> throw IllegalArgumentException("weird type") } - val code = VmCodeChunk() code += exprGen.translateExpression(call.args[0], 0, -1) - code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length) - code += VmCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal) - if(resultRegister!=0) - code += VmCodeInstruction(Opcode.LOADR, elementDt, reg1=resultRegister, reg2=0) + code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1 = 1, value = array.length) + code += VmCodeInstruction(Opcode.SYSCALL, value = syscall.ordinal) + if (resultRegister != 0) + code += VmCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1 = resultRegister, reg2 = 0) return code } private fun funcAll(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { val arrayName = call.args[0] as PtIdentifier val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable - val elementDt: VmDataType = codeGen.vmType(ArrayToElementTypes.getValue(array.dt)) val syscall = when(array.dt) { DataType.ARRAY_UB, DataType.ARRAY_B -> Syscall.ALL_BYTE DataType.ARRAY_UW, DataType.ARRAY_W -> Syscall.ALL_WORD - DataType.ARRAY_F -> TODO("float all") + DataType.ARRAY_F -> Syscall.ALL_FLOAT else -> throw IllegalArgumentException("weird type") } val code = VmCodeChunk() @@ -101,7 +99,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length) code += VmCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal) if(resultRegister!=0) - code += VmCodeInstruction(Opcode.LOADR, elementDt, reg1=resultRegister, reg2=0) + code += VmCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0) return code } @@ -201,7 +199,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: when(array.dt) { DataType.ARRAY_UB, DataType.ARRAY_B, DataType.STR -> Syscall.REVERSE_BYTES DataType.ARRAY_UW, DataType.ARRAY_W -> Syscall.REVERSE_WORDS - DataType.ARRAY_F -> TODO("float reverse") + DataType.ARRAY_F -> Syscall.REVERSE_FLOATS else -> throw IllegalArgumentException("weird type to reverse") } val code = VmCodeChunk() @@ -220,8 +218,8 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: DataType.ARRAY_B -> Syscall.SORT_BYTE DataType.ARRAY_UW -> Syscall.SORT_UWORD DataType.ARRAY_W -> Syscall.SORT_WORD - DataType.ARRAY_F -> TODO("float sort") DataType.STR -> Syscall.SORT_UBYTE + DataType.ARRAY_F -> throw java.lang.IllegalArgumentException("sorting a floating point array is not supported") else -> throw IllegalArgumentException("weird type to sort") } val code = VmCodeChunk() diff --git a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt index f77d34cce..9c105a9e9 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt @@ -62,7 +62,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) { } is PtTypeCast -> code += translate(expr, resultRegister, resultFpRegister) is PtPrefix -> code += translate(expr, resultRegister) - is PtArrayIndexer -> code += translate(expr, resultRegister) + is PtArrayIndexer -> code += translate(expr, resultRegister, resultFpRegister) is PtBinaryExpression -> code += translate(expr, resultRegister, resultFpRegister) is PtBuiltinFunctionCall -> code += codeGen.translateBuiltinFunc(expr, resultRegister) is PtFunctionCall -> code += translate(expr, resultRegister, resultFpRegister) @@ -139,13 +139,13 @@ internal class ExpressionGen(private val codeGen: CodeGen) { call.children.add(PtNumber(DataType.UBYTE, iterable.length!!.toDouble(), iterable.position)) code += translate(call, resultRegister, resultFpRegister) } - DataType.ARRAY_F -> TODO("containment check in float-array") + DataType.ARRAY_F -> throw AssemblyError("containment check in float-array not supported") else -> throw AssemblyError("weird iterable dt ${iterable.dt} for ${check.iterable.targetName}") } return code } - private fun translate(arrayIx: PtArrayIndexer, resultRegister: Int): VmCodeChunk { + private fun translate(arrayIx: PtArrayIndexer, resultRegister: Int, resultFpRegister: Int): VmCodeChunk { val eltSize = codeGen.program.memsizer.memorySize(arrayIx.type) val vmDt = codeGen.vmType(arrayIx.type) val code = VmCodeChunk() @@ -154,12 +154,18 @@ internal class ExpressionGen(private val codeGen: CodeGen) { if(arrayIx.index is PtNumber) { // optimized code when index is known - just calculate the memory address here val memOffset = (arrayIx.index as PtNumber).number.toInt() * eltSize - code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, value=arrayLocation+memOffset) + if(vmDt==VmDataType.FLOAT) + code += VmCodeInstruction(Opcode.LOADM, VmDataType.FLOAT, fpReg1=resultFpRegister, value=arrayLocation+memOffset) + else + code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, value=arrayLocation+memOffset) } else { code += translateExpression(arrayIx.index, idxReg, -1) if(eltSize>1) code += codeGen.multiplyByConst(VmDataType.BYTE, idxReg, eltSize) - code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation) + if(vmDt==VmDataType.FLOAT) + code += VmCodeInstruction(Opcode.LOADX, VmDataType.FLOAT, fpReg1 = resultFpRegister, reg1=idxReg, value = arrayLocation) + else + code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation) } return code } @@ -193,29 +199,30 @@ internal class ExpressionGen(private val codeGen: CodeGen) { return code } - private fun translate(cast: PtTypeCast, resultRegister: Int, predefinedResultFpRegister: Int): VmCodeChunk { + private fun translate(cast: PtTypeCast, predefinedResultRegister: Int, predefinedResultFpRegister: Int): VmCodeChunk { val code = VmCodeChunk() if(cast.type==cast.value.type) return code val actualResultFpReg = if(predefinedResultFpRegister>=0) predefinedResultFpRegister else codeGen.vmRegisters.nextFreeFloat() + val actualResultReg = if(predefinedResultRegister>=0) predefinedResultRegister else codeGen.vmRegisters.nextFree() if(cast.value.type==DataType.FLOAT) { // a cast from float to integer, so evaluate the value into a float register first code += translateExpression(cast.value, -1, actualResultFpReg) } else - code += translateExpression(cast.value, resultRegister, -1) + code += translateExpression(cast.value, actualResultReg, -1) when(cast.type) { DataType.UBYTE -> { when(cast.value.type) { DataType.BYTE, DataType.UWORD, DataType.WORD -> { /* just keep the LSB as it is */ } - DataType.FLOAT -> code += VmCodeInstruction(Opcode.FTOUB, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = actualResultFpReg) + DataType.FLOAT -> code += VmCodeInstruction(Opcode.FTOUB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg) else -> throw AssemblyError("weird cast value type") } } DataType.BYTE -> { when(cast.value.type) { DataType.UBYTE, DataType.UWORD, DataType.WORD -> { /* just keep the LSB as it is */ } - DataType.FLOAT -> code += VmCodeInstruction(Opcode.FTOSB, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = actualResultFpReg) + DataType.FLOAT -> code += VmCodeInstruction(Opcode.FTOSB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg) else -> throw AssemblyError("weird cast value type") } } @@ -223,15 +230,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) { when(cast.value.type) { DataType.BYTE -> { // byte -> uword: sign extend - code += VmCodeInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = resultRegister) + code += VmCodeInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = actualResultReg) } DataType.UBYTE -> { // ubyte -> uword: sign extend - code += VmCodeInstruction(Opcode.EXT, type = VmDataType.BYTE, reg1 = resultRegister) + code += VmCodeInstruction(Opcode.EXT, type = VmDataType.BYTE, reg1 = actualResultReg) } DataType.WORD -> { } DataType.FLOAT -> { - code += VmCodeInstruction(Opcode.FTOUW, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = actualResultFpReg) + code += VmCodeInstruction(Opcode.FTOUW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg) } else -> throw AssemblyError("weird cast value type") } @@ -240,32 +247,35 @@ internal class ExpressionGen(private val codeGen: CodeGen) { when(cast.value.type) { DataType.BYTE -> { // byte -> word: sign extend - code += VmCodeInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = resultRegister) + code += VmCodeInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = actualResultReg) } DataType.UBYTE -> { // byte -> word: sign extend - code += VmCodeInstruction(Opcode.EXT, type = VmDataType.BYTE, reg1 = resultRegister) + code += VmCodeInstruction(Opcode.EXT, type = VmDataType.BYTE, reg1 = actualResultReg) } DataType.UWORD -> { } DataType.FLOAT -> { - code += VmCodeInstruction(Opcode.FTOSW, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = actualResultFpReg) + code += VmCodeInstruction(Opcode.FTOSW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg) } else -> throw AssemblyError("weird cast value type") } } DataType.FLOAT -> { - TODO("floating point to integer cast not yet supported") -// when(cast.value.type) { -// DataType.BYTE -> { -// } -// DataType.UBYTE -> { -// } -// DataType.WORD -> { -// } -// DataType.UWORD -> { -// } -// else -> throw AssemblyError("weird cast value type") -// } + when(cast.value.type) { + DataType.UBYTE -> { + code += VmCodeInstruction(Opcode.FFROMUB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg) + } + DataType.BYTE -> { + code += VmCodeInstruction(Opcode.FFROMSB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg) + } + DataType.UWORD -> { + code += VmCodeInstruction(Opcode.FFROMUW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg) + } + DataType.WORD -> { + code += VmCodeInstruction(Opcode.FFROMSW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg) + } + else -> throw AssemblyError("weird cast value type") + } } else -> throw AssemblyError("weird cast type") } diff --git a/compiler/res/prog8lib/virtual/floats.p8 b/compiler/res/prog8lib/virtual/floats.p8 index 865c4f1d1..da739f115 100644 --- a/compiler/res/prog8lib/virtual/floats.p8 +++ b/compiler/res/prog8lib/virtual/floats.p8 @@ -13,7 +13,7 @@ sub print_f(float value) { ; ---- prints the floating point value (without a newline). %asm {{ loadm.f fr0,{floats.print_f.value} - syscall 35 + syscall 25 return }} } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index d70856430..289376570 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,7 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- vm: implement float any, all, reverse, sort +- vm: implement rest of float instructions - vm: get rid of intermediate floats.xxx() functions somehow, instead generate the float instructions directly? - pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls. - allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type @@ -63,7 +63,8 @@ Libraries: - add modes 2 and 3 to gfx2 (lowres 4 color and 16 color)? - add a flood fill routine to gfx2? - add a diskio.f_seek() routine for the Cx16 that uses its seek dos api? (only if that's stable) -- use cx16 MACPTR() to load stuff faster? +- diskio: use cx16 MACPTR() to load stuff faster? (see it's use in X16edit to fast load blocks) + note that it might fail on non sdcard files so have to make graceful degradation Expressions: diff --git a/examples/test.p8 b/examples/test.p8 index 918b10dd4..101763daa 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -9,15 +9,19 @@ main { sub start() { float fl = 42.123 - float fl2 = fl / 1.0 - txt.print("rad 180 = ") - floats.print_f(floats.rad(180.0)) - txt.print("\nrad 360 = ") - floats.print_f(floats.rad(360.0)) - txt.print("\ndeg 2 = ") - floats.print_f(floats.deg(2.0)) - txt.print("\ndeg pi = ") - floats.print_f(floats.deg(floats.PI)) + float[] farray = [0.0, 0.0, 1.11, 2.22, 42.123, 0.0, -99.99] + ubyte ix + for ix in 0 to len(farray)-1 { + floats.print_f(farray[ix]) + txt.spc() + } + txt.nl() + reverse(farray) + for ix in 0 to len(farray)-1 { + floats.print_f(farray[ix]) + txt.spc() + } + txt.nl() sys.exit(42) ; floats.print_f(-42.42) ; float f1 = 1.2345 diff --git a/syntax-files/IDEA/Prog8.xml b/syntax-files/IDEA/Prog8.xml index 636796c03..ffe55eb04 100644 --- a/syntax-files/IDEA/Prog8.xml +++ b/syntax-files/IDEA/Prog8.xml @@ -14,7 +14,7 @@ - + diff --git a/syntax-files/NotepadPlusPlus/Prog8.xml b/syntax-files/NotepadPlusPlus/Prog8.xml index 4b7bc4516..7fb7a9b13 100644 --- a/syntax-files/NotepadPlusPlus/Prog8.xml +++ b/syntax-files/NotepadPlusPlus/Prog8.xml @@ -27,7 +27,7 @@ void const str byte ubyte word uword float zp shared requirezp %address %asm %asmbinary %asminclude %breakpoint %import %launcher %option %output %zeropage %zpreserved inline sub asmsub romsub clobbers asm if when else if_cc if_cs if_eq if_mi if_neg if_nz if_pl if_pos if_vc if_vs if_z for in step do while repeat break return goto - abs all any avg callfar callrom cmp len lsb lsl lsr max memory min mkword msb peek peekw poke pokew push pushw pop popw rsave rsavex rrestore rrestorex reverse rnd rndw rol rol2 ror ror2 sgn sizeof sort sqrt16 sum swap + abs all any avg callfar callrom cmp len lsb lsl lsr memory mkword msb peek peekw poke pokew push pushw pop popw rsave rsavex rrestore rrestorex reverse rnd rndw rol rol2 ror ror2 sgn sizeof sort sqrt16 swap true false not and or xor as to downto |> diff --git a/syntax-files/Vim/prog8_builtins.vim b/syntax-files/Vim/prog8_builtins.vim index 540f2bb53..9805743f1 100644 --- a/syntax-files/Vim/prog8_builtins.vim +++ b/syntax-files/Vim/prog8_builtins.vim @@ -10,7 +10,7 @@ syn keyword prog8BuiltInFunc sgn sqrt16 " Array functions -syn keyword prog8BuiltInFunc any all len max min reverse sum sort +syn keyword prog8BuiltInFunc any all len reverse sort " Miscellaneous functions syn keyword prog8BuiltInFunc cmp lsb msb mkword peek peekw poke pokew rnd rndw push pushw pop popw rsave rsavex rrestore rrestorex diff --git a/virtualmachine/src/prog8/vm/SysCalls.kt b/virtualmachine/src/prog8/vm/SysCalls.kt index b149f0a59..f6c1abd84 100644 --- a/virtualmachine/src/prog8/vm/SysCalls.kt +++ b/virtualmachine/src/prog8/vm/SysCalls.kt @@ -24,23 +24,16 @@ SYSCALLS: 16 = sort_byte array 17 = sort_uword array 18 = sort_word array -19 = max_ubyte array -20 = max_byte array -21 = max_uword array -22 = max_word array -23 = min_ubyte array -24 = min_byte array -25 = min_uword array -26 = min_word array -27 = sum_byte array -28 = sum_word array -29 = any_byte array -30 = any_word array -31 = all_byte array -32 = all_word array -33 = reverse_bytes array -34 = reverse_words array -35 = print_f (floating point value in fpReg0) +19 = any_byte array +20 = any_word array +21 = any_float array +22 = all_byte array +23 = all_word array +24 = all_float array +25 = print_f (floating point value in fp reg 0) +26 = reverse_bytes array +27 = reverse_words array +28 = reverse_floats array */ enum class Syscall { @@ -63,23 +56,16 @@ enum class Syscall { SORT_BYTE, SORT_UWORD, SORT_WORD, - MAX_UBYTE, - MAX_BYTE, - MAX_UWORD, - MAX_WORD, - MIN_UBYTE, - MIN_BYTE, - MIN_UWORD, - MIN_WORD, - SUM_BYTE, - SUM_WORD, ANY_BYTE, ANY_WORD, + ANY_FLOAT, ALL_BYTE, ALL_WORD, + ALL_FLOAT, + PRINT_F, REVERSE_BYTES, REVERSE_WORDS, - PRINT_F + REVERSE_FLOATS, } object SysCalls { @@ -191,75 +177,15 @@ object SysCalls { vm.memory.setUW(address+index*2, value) } } - Syscall.MAX_UBYTE -> { + Syscall.REVERSE_FLOATS -> { val address = vm.registers.getUW(0).toInt() val length = vm.registers.getUB(1).toInt() - val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) - val value = addresses.map { vm.memory.getUB(it) }.maxOf { it } - vm.registers.setUB(0, value) - } - Syscall.MAX_BYTE -> { - val address = vm.registers.getUW(0).toInt() - val length = vm.registers.getUB(1).toInt() - val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) - val value = addresses.map { vm.memory.getSB(it) }.maxOf { it } - vm.registers.setSB(0, value) - } - Syscall.MAX_UWORD -> { - val address = vm.registers.getUW(0).toInt() - val length = vm.registers.getUB(1).toInt() - val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) - val value = addresses.map { vm.memory.getUW(it) }.maxOf { it } - vm.registers.setUW(0, value) - } - Syscall.MAX_WORD -> { - val address = vm.registers.getUW(0).toInt() - val length = vm.registers.getUB(1).toInt() - val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) - val value = addresses.map { vm.memory.getSW(it) }.maxOf { it } - vm.registers.setSW(0, value) - } - Syscall.MIN_UBYTE -> { - val address = vm.registers.getUW(0).toInt() - val length = vm.registers.getUB(1).toInt() - val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) - val value = addresses.map { vm.memory.getUB(it) }.minOf { it } - vm.registers.setUB(0, value) - } - Syscall.MIN_BYTE -> { - val address = vm.registers.getUW(0).toInt() - val length = vm.registers.getUB(1).toInt() - val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) - val value = addresses.map { vm.memory.getSB(it) }.minOf { it } - vm.registers.setSB(0, value) - } - Syscall.MIN_UWORD -> { - val address = vm.registers.getUW(0).toInt() - val length = vm.registers.getUB(1).toInt() - val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) - val value = addresses.map { vm.memory.getUW(it) }.minOf { it } - vm.registers.setUW(0, value) - } - Syscall.MIN_WORD -> { - val address = vm.registers.getUW(0).toInt() - val length = vm.registers.getUB(1).toInt() - val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) - val value = addresses.map { vm.memory.getSW(it) }.minOf { it } - vm.registers.setSW(0, value) - } - Syscall.SUM_BYTE -> { - val address = vm.registers.getUW(0).toInt() - val length = vm.registers.getUB(1).toInt() - val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) - val value = addresses.map { vm.memory.getUB(it) }.sum() - vm.registers.setUB(0, value.toUByte()) - } - Syscall.SUM_WORD -> { - val address = vm.registers.getUW(0).toInt() - val length = vm.registers.getUB(1).toInt() - val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) - val value = addresses.map { vm.memory.getUW(it) }.sum() - vm.registers.setUW(0, value.toUShort()) + val array = IntProgression.fromClosedRange(address, address+length*4-2, 4).map { + vm.memory.getFloat(it) + }.reversed() + array.withIndex().forEach { (index, value)-> + vm.memory.setFloat(address+index*4, value) + } } Syscall.ANY_BYTE -> { val address = vm.registers.getUW(0).toInt() @@ -279,6 +205,15 @@ object SysCalls { else vm.registers.setUB(0, 0u) } + Syscall.ANY_FLOAT -> { + val address = vm.registers.getUW(0).toInt() + val length = vm.registers.getUB(1).toInt() + val addresses = IntProgression.fromClosedRange(address, address+length*4-2, 4) + if(addresses.any { vm.memory.getFloat(it).toInt()!=0 }) + vm.registers.setUB(0, 1u) + else + vm.registers.setUB(0, 0u) + } Syscall.ALL_BYTE -> { val address = vm.registers.getUW(0).toInt() val length = vm.registers.getUB(1).toInt() @@ -297,6 +232,15 @@ object SysCalls { else vm.registers.setUB(0, 0u) } + Syscall.ALL_FLOAT -> { + val address = vm.registers.getUW(0).toInt() + val length = vm.registers.getUB(1).toInt() + val addresses = IntProgression.fromClosedRange(address, address+length*4-2, 4) + if(addresses.all { vm.memory.getFloat(it).toInt()!=0 }) + vm.registers.setUB(0, 1u) + else + vm.registers.setUB(0, 0u) + } Syscall.PRINT_F -> { val value = vm.registers.getFloat(0) print(value) diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index d64ec7f7e..b6135b06c 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -173,10 +173,10 @@ class VirtualMachine(val memory: Memory, program: List) { Opcode.CLC -> { statusCarry = false; pc++ } Opcode.SEC -> { statusCarry = true; pc++ } - Opcode.FFROMUB -> TODO() - Opcode.FFROMSB -> TODO() - Opcode.FFROMUW -> TODO() - Opcode.FFROMSW -> TODO() + Opcode.FFROMUB -> InsFFROMUB(ins) + Opcode.FFROMSB -> InsFFROMSB(ins) + Opcode.FFROMUW -> InsFFROMUW(ins) + Opcode.FFROMSW -> InsFFROMSW(ins) Opcode.FTOUB -> InsFTOUB(ins) Opcode.FTOSB -> InsFTOSB(ins) Opcode.FTOUW -> InsFTOUW(ins) @@ -276,7 +276,7 @@ class VirtualMachine(val memory: Memory, program: List) { when(i.type!!) { VmDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(registers.getUW(i.reg2!!).toInt())) VmDataType.WORD -> registers.setUW(i.reg1!!, memory.getUW(registers.getUW(i.reg2!!).toInt())) - VmDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(registers.getUW(i.reg2!!).toInt())) + VmDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(registers.getUW(i.reg1!!).toInt())) } pc++ } @@ -285,7 +285,7 @@ class VirtualMachine(val memory: Memory, program: List) { when (i.type!!) { VmDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(i.value!! + registers.getUW(i.reg2!!).toInt())) VmDataType.WORD -> registers.setUW(i.reg1!!, memory.getUW(i.value!! + registers.getUW(i.reg2!!).toInt())) - VmDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(i.value!! + registers.getUW(i.reg2!!).toInt())) + VmDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(i.value!! + registers.getUW(i.reg1!!).toInt())) } pc++ } @@ -1062,6 +1062,26 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } + private fun InsFFROMUB(i: Instruction) { + registers.setFloat(i.fpReg1!!, registers.getUB(i.reg1!!).toFloat()) + pc++ + } + + private fun InsFFROMSB(i: Instruction) { + registers.setFloat(i.fpReg1!!, registers.getSB(i.reg1!!).toFloat()) + pc++ + } + + private fun InsFFROMUW(i: Instruction) { + registers.setFloat(i.fpReg1!!, registers.getUW(i.reg1!!).toFloat()) + pc++ + } + + private fun InsFFROMSW(i: Instruction) { + registers.setFloat(i.fpReg1!!, registers.getSW(i.reg1!!).toFloat()) + pc++ + } + private fun InsFTOUB(i: Instruction) { registers.setUB(i.reg1!!, registers.getFloat(i.fpReg1!!).toInt().toUByte()) pc++