vm: implement rest of float instructions

This commit is contained in:
Irmen de Jong 2022-05-04 22:31:45 +02:00
parent da01a5b4dc
commit b1a49e5f29
4 changed files with 116 additions and 34 deletions

View File

@ -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
ldy #>value
jsr floats.CONUPK
lda #<power
ldy #>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
ldy #>value
jsr MOVFM
jsr ABS
plx
ldx P8ZP_SCRATCH_REG
rts
}}
}

View File

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

View File

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

View File

@ -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<Instruction>) {
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<Instruction>) {
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<Int, Int> {
return when(i.type) {
VmDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), registers.getSB(i.reg2!!).toInt())