From b1a49e5f2920dfe5007c9f5b798e8813a0158b06 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 4 May 2022 22:31:45 +0200 Subject: [PATCH] vm: implement rest of float instructions --- compiler/res/prog8lib/floats_functions.p8 | 12 +-- docs/source/todo.rst | 1 - examples/test.p8 | 36 ++++--- virtualmachine/src/prog8/vm/VirtualMachine.kt | 101 +++++++++++++++--- 4 files changed, 116 insertions(+), 34 deletions(-) diff --git a/compiler/res/prog8lib/floats_functions.p8 b/compiler/res/prog8lib/floats_functions.p8 index 83fca59a2..a6a7860bc 100644 --- a/compiler/res/prog8lib/floats_functions.p8 +++ b/compiler/res/prog8lib/floats_functions.p8 @@ -25,28 +25,28 @@ sub print_f(float value) { sub pow(float value, float power) -> float { %asm {{ - phx - phy + stx P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 lda #value jsr floats.CONUPK lda #power jsr floats.FPWR - ply - plx + ldx P8ZP_SCRATCH_W1 + ldy P8ZP_SCRATCH_W1+1 rts }} } sub fabs(float value) -> float { %asm {{ - phx + stx P8ZP_SCRATCH_REG lda #value jsr MOVFM jsr ABS - plx + ldx P8ZP_SCRATCH_REG rts }} } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 289376570..fdccd323b 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- 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 diff --git a/examples/test.p8 b/examples/test.p8 index 101763daa..050055516 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -8,19 +8,31 @@ main { sub start() { - float fl = 42.123 - 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() - } + float fl = -4.55 + floats.print_f(floats.fabs(fl)) txt.nl() - reverse(farray) - for ix in 0 to len(farray)-1 { - floats.print_f(farray[ix]) - txt.spc() - } + floats.print_f(floats.sin(fl)) + txt.nl() + floats.print_f(floats.cos(fl)) + txt.nl() + floats.print_f(floats.tan(fl)) + txt.nl() + floats.print_f(floats.atan(fl)) + txt.nl() + floats.print_f(floats.round(fl)) + txt.nl() + floats.print_f(floats.floor(fl)) + txt.nl() + floats.print_f(floats.ceil(fl)) + txt.nl() + fl = 4.55 + floats.print_f(floats.ln(fl)) + txt.nl() + floats.print_f(floats.log2(fl)) + txt.nl() + floats.print_f(floats.sqrt(fl)) + txt.nl() + floats.print_f(floats.pow(fl, 2.2)) ; TODO fix illegal quantity error txt.nl() sys.exit(42) ; floats.print_f(-42.42) diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index b6135b06c..0bae365da 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -3,9 +3,7 @@ package prog8.vm import prog8.code.target.virtual.IVirtualMachineRunner import java.awt.Toolkit import java.util.* -import kotlin.math.roundToInt -import kotlin.math.sign -import kotlin.math.sqrt +import kotlin.math.* import kotlin.random.Random @@ -181,18 +179,18 @@ class VirtualMachine(val memory: Memory, program: List) { Opcode.FTOSB -> InsFTOSB(ins) Opcode.FTOUW -> InsFTOUW(ins) Opcode.FTOSW -> InsFTOSW(ins) - Opcode.FPOW -> TODO() - Opcode.FABS -> TODO() - Opcode.FSIN -> TODO() - Opcode.FCOS -> TODO() - Opcode.FTAN -> TODO() - Opcode.FATAN -> TODO() - Opcode.FLN -> TODO() - Opcode.FLOG -> TODO() - Opcode.FSQRT -> TODO() - Opcode.FROUND -> TODO() - Opcode.FFLOOR -> TODO() - Opcode.FCEIL -> TODO() + Opcode.FPOW -> InsFPOW(ins) + Opcode.FABS -> InsFABS(ins) + Opcode.FSIN -> InsFSIN(ins) + Opcode.FCOS -> InsFCOS(ins) + Opcode.FTAN -> InsFTAN(ins) + Opcode.FATAN -> InsFATAN(ins) + Opcode.FLN -> InsFLN(ins) + Opcode.FLOG -> InsFLOG(ins) + Opcode.FSQRT -> InsFSQRT(ins) + Opcode.FROUND -> InsFROUND(ins) + Opcode.FFLOOR -> InsFFLOOR(ins) + Opcode.FCEIL -> InsFCEIL(ins) else -> throw IllegalArgumentException("invalid opcode ${ins.opcode}") } } @@ -1102,6 +1100,79 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } + private fun InsFPOW(i: Instruction) { + val value = registers.getFloat(i.fpReg2!!) + val exponent = registers.getFloat(i.fpReg3!!) + registers.setFloat(i.fpReg1!!, value.pow(exponent)) + pc++ + } + + private fun InsFSIN(i: Instruction) { + val angle = registers.getFloat(i.fpReg2!!) + registers.setFloat(i.fpReg1!!, sin(angle)) + pc++ + } + + private fun InsFCOS(i: Instruction) { + val angle = registers.getFloat(i.fpReg2!!) + registers.setFloat(i.fpReg1!!, cos(angle)) + pc++ + } + + private fun InsFTAN(i: Instruction) { + val angle = registers.getFloat(i.fpReg2!!) + registers.setFloat(i.fpReg1!!, tan(angle)) + pc++ + } + + private fun InsFATAN(i: Instruction) { + val angle = registers.getFloat(i.fpReg2!!) + registers.setFloat(i.fpReg1!!, atan(angle)) + pc++ + } + + private fun InsFABS(i: Instruction) { + val value = registers.getFloat(i.fpReg2!!) + registers.setFloat(i.fpReg1!!, abs(value)) + pc++ + } + + private fun InsFLN(i: Instruction) { + val value = registers.getFloat(i.fpReg2!!) + registers.setFloat(i.fpReg1!!, ln(value)) + pc++ + } + + private fun InsFLOG(i: Instruction) { + val value = registers.getFloat(i.fpReg2!!) + registers.setFloat(i.fpReg1!!, log2(value)) + pc++ + } + + private fun InsFROUND(i: Instruction) { + val value = registers.getFloat(i.fpReg2!!) + registers.setFloat(i.fpReg1!!, round(value)) + pc++ + } + + private fun InsFFLOOR(i: Instruction) { + val value = registers.getFloat(i.fpReg2!!) + registers.setFloat(i.fpReg1!!, floor(value)) + pc++ + } + + private fun InsFCEIL(i: Instruction) { + val value = registers.getFloat(i.fpReg2!!) + registers.setFloat(i.fpReg1!!, ceil(value)) + pc++ + } + + private fun InsFSQRT(i: Instruction) { + val value = registers.getFloat(i.fpReg2!!) + registers.setFloat(i.fpReg1!!, sqrt(value)) + pc++ + } + private fun getBranchOperands(i: Instruction): Pair { return when(i.type) { VmDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), registers.getSB(i.reg2!!).toInt())