mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
vm: implement float type casts to integer types
This commit is contained in:
parent
10c8cc35c5
commit
0869789214
@ -9,6 +9,7 @@ import prog8.code.core.PassByValueDatatypes
|
||||
import prog8.code.core.SignedDatatypes
|
||||
import prog8.vm.Opcode
|
||||
import prog8.vm.VmDataType
|
||||
import java.nio.channels.FileLock
|
||||
|
||||
|
||||
internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
@ -59,7 +60,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1=resultRegister, reg2=addressRegister)
|
||||
}
|
||||
}
|
||||
is PtTypeCast -> code += translate(expr, resultRegister)
|
||||
is PtTypeCast -> code += translate(expr, resultRegister, resultFpRegister)
|
||||
is PtPrefix -> code += translate(expr, resultRegister)
|
||||
is PtArrayIndexer -> code += translate(expr, resultRegister)
|
||||
is PtBinaryExpression -> code += translate(expr, resultRegister, resultFpRegister)
|
||||
@ -192,27 +193,29 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
return code
|
||||
}
|
||||
|
||||
private fun translate(cast: PtTypeCast, resultRegister: Int): VmCodeChunk {
|
||||
private fun translate(cast: PtTypeCast, resultRegister: Int, predefinedResultFpRegister: Int): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
if(cast.type==cast.value.type)
|
||||
return code
|
||||
code += translateExpression(cast.value, resultRegister, -1)
|
||||
val actualResultFpReg = if(predefinedResultFpRegister>=0) predefinedResultFpRegister else codeGen.vmRegisters.nextFreeFloat()
|
||||
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)
|
||||
when(cast.type) {
|
||||
DataType.UBYTE -> {
|
||||
when(cast.value.type) {
|
||||
DataType.BYTE, DataType.UWORD, DataType.WORD -> { /* just keep the LSB as it is */ }
|
||||
DataType.FLOAT -> {
|
||||
TODO("float -> ubyte") // float not yet supported
|
||||
}
|
||||
DataType.FLOAT -> code += VmCodeInstruction(Opcode.FTOUB, VmDataType.FLOAT, reg1=resultRegister, 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 -> {
|
||||
TODO("float -> byte") // float not yet supported
|
||||
}
|
||||
DataType.FLOAT -> code += VmCodeInstruction(Opcode.FTOSB, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = actualResultFpReg)
|
||||
else -> throw AssemblyError("weird cast value type")
|
||||
}
|
||||
}
|
||||
@ -228,7 +231,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
}
|
||||
DataType.WORD -> { }
|
||||
DataType.FLOAT -> {
|
||||
TODO("float -> uword") // float not yet supported
|
||||
code += VmCodeInstruction(Opcode.FTOUW, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = actualResultFpReg)
|
||||
}
|
||||
else -> throw AssemblyError("weird cast value type")
|
||||
}
|
||||
@ -245,13 +248,13 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
}
|
||||
DataType.UWORD -> { }
|
||||
DataType.FLOAT -> {
|
||||
TODO("float -> word") // float not yet supported
|
||||
code += VmCodeInstruction(Opcode.FTOSW, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = actualResultFpReg)
|
||||
}
|
||||
else -> throw AssemblyError("weird cast value type")
|
||||
}
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
TODO("floating point not yet supported")
|
||||
TODO("floating point to integer cast not yet supported")
|
||||
// when(cast.value.type) {
|
||||
// DataType.BYTE -> {
|
||||
// }
|
||||
|
@ -3,7 +3,7 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- vm: implement float type casts to integer types
|
||||
- compiler: fix crash when print_ub(float as ubyte)
|
||||
- vm: implement float any, all, reverse, sort
|
||||
- vm: fix test fp calc result being 0
|
||||
- vm: get rid of intermediate floats.xxx() functions somehow, instead generate the float instructions directly?
|
||||
|
@ -8,22 +8,19 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
float fl1 = 500.0
|
||||
float fzero = 0.0
|
||||
floats.print_f(fl1 / fzero)
|
||||
float fl = -4.567
|
||||
float fl2 = fl / 1.0
|
||||
floats.print_f(fl2)
|
||||
txt.nl()
|
||||
txt.print_ub(fl2 as ubyte) ; TODO fix crash source dt size must be less or equal to target dt size
|
||||
txt.nl()
|
||||
txt.print_b(fl2 as byte) ; TODO fix crash
|
||||
txt.nl()
|
||||
txt.print_uw(fl2 as uword) ; TODO fix crash
|
||||
txt.nl()
|
||||
txt.print_w(fl2 as word) ; TODO fix crash
|
||||
txt.nl()
|
||||
|
||||
ubyte ub1 = 50
|
||||
ubyte ubzero = 0
|
||||
txt.print_ub(ub1/ubzero)
|
||||
txt.nl()
|
||||
|
||||
uword uw1 = 5000
|
||||
uword uwzero = 0
|
||||
txt.print_uw(uw1/uwzero)
|
||||
txt.nl()
|
||||
|
||||
; float fl = 500.0
|
||||
; txt.print("rad 180 = ")
|
||||
; floats.print_f(floats.rad(180.0))
|
||||
; txt.print("rad 360 = ")
|
||||
|
@ -82,6 +82,18 @@ class Assembler {
|
||||
val (_, instr, typestr, rest) = match.groupValues
|
||||
val opcode = Opcode.valueOf(instr.uppercase())
|
||||
var type: VmDataType? = convertType(typestr)
|
||||
val formats = instructionFormats.getValue(opcode)
|
||||
val format: InstructionFormat
|
||||
if(type !in formats) {
|
||||
type = VmDataType.BYTE
|
||||
format = if(type !in formats)
|
||||
formats.getValue(null)
|
||||
else
|
||||
formats.getValue(type)
|
||||
} else {
|
||||
format = formats.getValue(type)
|
||||
}
|
||||
// parse the operands
|
||||
val operands = rest.lowercase().split(",").toMutableList()
|
||||
var reg1: Int? = null
|
||||
var reg2: Int? = null
|
||||
@ -129,17 +141,19 @@ class Assembler {
|
||||
}
|
||||
}
|
||||
}
|
||||
val formats = instructionFormats.getValue(opcode)
|
||||
val format: InstructionFormat
|
||||
if(type !in formats) {
|
||||
type = VmDataType.BYTE
|
||||
format = if(type !in formats)
|
||||
formats.getValue(null)
|
||||
else
|
||||
formats.getValue(type)
|
||||
} else {
|
||||
format = formats.getValue(type)
|
||||
|
||||
// shift the operands back into place
|
||||
while(reg1==null && reg2!=null) {
|
||||
reg1 = reg2
|
||||
reg2 = reg3
|
||||
reg3 = null
|
||||
}
|
||||
while(fpReg1==null && fpReg2!=null) {
|
||||
fpReg1 = fpReg2
|
||||
fpReg2 = fpReg3
|
||||
fpReg3 = null
|
||||
}
|
||||
|
||||
if(type!=null && type !in formats)
|
||||
throw IllegalArgumentException("invalid type code for $line")
|
||||
if(format.reg1 && reg1==null)
|
||||
|
@ -330,8 +330,6 @@ data class Instruction(
|
||||
if (type==VmDataType.FLOAT) {
|
||||
if(format.fpValue && (fpValue==null && symbol==null))
|
||||
throw IllegalArgumentException("$opcode: missing a fp-value or symbol")
|
||||
if (reg1 != null || reg2 != null || reg3 != null)
|
||||
throw java.lang.IllegalArgumentException("$opcode: floating point instruction can't use integer registers")
|
||||
} else {
|
||||
if(format.value && (value==null && symbol==null))
|
||||
throw IllegalArgumentException("$opcode: missing a value or symbol")
|
||||
|
@ -172,6 +172,27 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
Opcode.BREAKPOINT -> InsBREAKPOINT()
|
||||
Opcode.CLC -> { statusCarry = false; pc++ }
|
||||
Opcode.SEC -> { statusCarry = true; pc++ }
|
||||
|
||||
Opcode.FFROMUB -> TODO()
|
||||
Opcode.FFROMSB -> TODO()
|
||||
Opcode.FFROMUW -> TODO()
|
||||
Opcode.FFROMSW -> TODO()
|
||||
Opcode.FTOUB -> InsFTOUB(ins)
|
||||
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()
|
||||
else -> throw IllegalArgumentException("invalid opcode ${ins.opcode}")
|
||||
}
|
||||
}
|
||||
@ -1041,6 +1062,26 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsFTOUB(i: Instruction) {
|
||||
registers.setUB(i.reg1!!, registers.getFloat(i.fpReg1!!).toInt().toUByte())
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsFTOUW(i: Instruction) {
|
||||
registers.setUW(i.reg1!!, registers.getFloat(i.fpReg1!!).toInt().toUShort())
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsFTOSB(i: Instruction) {
|
||||
registers.setSB(i.reg1!!, registers.getFloat(i.fpReg1!!).toInt().toByte())
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsFTOSW(i: Instruction) {
|
||||
registers.setSW(i.reg1!!, registers.getFloat(i.fpReg1!!).toInt().toShort())
|
||||
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())
|
||||
@ -1085,7 +1126,6 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun getSetOnConditionOperands(ins: Instruction): Triple<Int, Int, Int> {
|
||||
return when(ins.type) {
|
||||
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getSB(ins.reg2!!).toInt(), registers.getSB(ins.reg3!!).toInt())
|
||||
|
Loading…
Reference in New Issue
Block a user