mirror of
https://github.com/irmen/prog8.git
synced 2024-10-25 00:24:16 +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.code.core.SignedDatatypes
|
||||||
import prog8.vm.Opcode
|
import prog8.vm.Opcode
|
||||||
import prog8.vm.VmDataType
|
import prog8.vm.VmDataType
|
||||||
|
import java.nio.channels.FileLock
|
||||||
|
|
||||||
|
|
||||||
internal class ExpressionGen(private val codeGen: CodeGen) {
|
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)
|
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 PtPrefix -> code += translate(expr, resultRegister)
|
||||||
is PtArrayIndexer -> code += translate(expr, resultRegister)
|
is PtArrayIndexer -> code += translate(expr, resultRegister)
|
||||||
is PtBinaryExpression -> code += translate(expr, resultRegister, resultFpRegister)
|
is PtBinaryExpression -> code += translate(expr, resultRegister, resultFpRegister)
|
||||||
@ -192,27 +193,29 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(cast: PtTypeCast, resultRegister: Int): VmCodeChunk {
|
private fun translate(cast: PtTypeCast, resultRegister: Int, predefinedResultFpRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
if(cast.type==cast.value.type)
|
if(cast.type==cast.value.type)
|
||||||
return code
|
return code
|
||||||
|
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)
|
code += translateExpression(cast.value, resultRegister, -1)
|
||||||
when(cast.type) {
|
when(cast.type) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
when(cast.value.type) {
|
when(cast.value.type) {
|
||||||
DataType.BYTE, DataType.UWORD, DataType.WORD -> { /* just keep the LSB as it is */ }
|
DataType.BYTE, DataType.UWORD, DataType.WORD -> { /* just keep the LSB as it is */ }
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> code += VmCodeInstruction(Opcode.FTOUB, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = actualResultFpReg)
|
||||||
TODO("float -> ubyte") // float not yet supported
|
|
||||||
}
|
|
||||||
else -> throw AssemblyError("weird cast value type")
|
else -> throw AssemblyError("weird cast value type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
when(cast.value.type) {
|
when(cast.value.type) {
|
||||||
DataType.UBYTE, DataType.UWORD, DataType.WORD -> { /* just keep the LSB as it is */ }
|
DataType.UBYTE, DataType.UWORD, DataType.WORD -> { /* just keep the LSB as it is */ }
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> code += VmCodeInstruction(Opcode.FTOSB, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = actualResultFpReg)
|
||||||
TODO("float -> byte") // float not yet supported
|
|
||||||
}
|
|
||||||
else -> throw AssemblyError("weird cast value type")
|
else -> throw AssemblyError("weird cast value type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,7 +231,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
}
|
}
|
||||||
DataType.WORD -> { }
|
DataType.WORD -> { }
|
||||||
DataType.FLOAT -> {
|
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")
|
else -> throw AssemblyError("weird cast value type")
|
||||||
}
|
}
|
||||||
@ -245,13 +248,13 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
}
|
}
|
||||||
DataType.UWORD -> { }
|
DataType.UWORD -> { }
|
||||||
DataType.FLOAT -> {
|
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")
|
else -> throw AssemblyError("weird cast value type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
TODO("floating point not yet supported")
|
TODO("floating point to integer cast not yet supported")
|
||||||
// when(cast.value.type) {
|
// when(cast.value.type) {
|
||||||
// DataType.BYTE -> {
|
// DataType.BYTE -> {
|
||||||
// }
|
// }
|
||||||
|
@ -3,7 +3,7 @@ TODO
|
|||||||
|
|
||||||
For next release
|
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: implement float any, all, reverse, sort
|
||||||
- vm: fix test fp calc result being 0
|
- vm: fix test fp calc result being 0
|
||||||
- vm: get rid of intermediate floats.xxx() functions somehow, instead generate the float instructions directly?
|
- vm: get rid of intermediate floats.xxx() functions somehow, instead generate the float instructions directly?
|
||||||
|
@ -8,22 +8,19 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
float fl1 = 500.0
|
float fl = -4.567
|
||||||
float fzero = 0.0
|
float fl2 = fl / 1.0
|
||||||
floats.print_f(fl1 / fzero)
|
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()
|
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 = ")
|
; txt.print("rad 180 = ")
|
||||||
; floats.print_f(floats.rad(180.0))
|
; floats.print_f(floats.rad(180.0))
|
||||||
; txt.print("rad 360 = ")
|
; txt.print("rad 360 = ")
|
||||||
|
@ -82,6 +82,18 @@ class Assembler {
|
|||||||
val (_, instr, typestr, rest) = match.groupValues
|
val (_, instr, typestr, rest) = match.groupValues
|
||||||
val opcode = Opcode.valueOf(instr.uppercase())
|
val opcode = Opcode.valueOf(instr.uppercase())
|
||||||
var type: VmDataType? = convertType(typestr)
|
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()
|
val operands = rest.lowercase().split(",").toMutableList()
|
||||||
var reg1: Int? = null
|
var reg1: Int? = null
|
||||||
var reg2: Int? = null
|
var reg2: Int? = null
|
||||||
@ -129,17 +141,19 @@ class Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val formats = instructionFormats.getValue(opcode)
|
|
||||||
val format: InstructionFormat
|
// shift the operands back into place
|
||||||
if(type !in formats) {
|
while(reg1==null && reg2!=null) {
|
||||||
type = VmDataType.BYTE
|
reg1 = reg2
|
||||||
format = if(type !in formats)
|
reg2 = reg3
|
||||||
formats.getValue(null)
|
reg3 = null
|
||||||
else
|
|
||||||
formats.getValue(type)
|
|
||||||
} else {
|
|
||||||
format = formats.getValue(type)
|
|
||||||
}
|
}
|
||||||
|
while(fpReg1==null && fpReg2!=null) {
|
||||||
|
fpReg1 = fpReg2
|
||||||
|
fpReg2 = fpReg3
|
||||||
|
fpReg3 = null
|
||||||
|
}
|
||||||
|
|
||||||
if(type!=null && type !in formats)
|
if(type!=null && type !in formats)
|
||||||
throw IllegalArgumentException("invalid type code for $line")
|
throw IllegalArgumentException("invalid type code for $line")
|
||||||
if(format.reg1 && reg1==null)
|
if(format.reg1 && reg1==null)
|
||||||
|
@ -330,8 +330,6 @@ data class Instruction(
|
|||||||
if (type==VmDataType.FLOAT) {
|
if (type==VmDataType.FLOAT) {
|
||||||
if(format.fpValue && (fpValue==null && symbol==null))
|
if(format.fpValue && (fpValue==null && symbol==null))
|
||||||
throw IllegalArgumentException("$opcode: missing a fp-value or symbol")
|
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 {
|
} else {
|
||||||
if(format.value && (value==null && symbol==null))
|
if(format.value && (value==null && symbol==null))
|
||||||
throw IllegalArgumentException("$opcode: missing a value or symbol")
|
throw IllegalArgumentException("$opcode: missing a value or symbol")
|
||||||
|
@ -172,6 +172,27 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
Opcode.BREAKPOINT -> InsBREAKPOINT()
|
Opcode.BREAKPOINT -> InsBREAKPOINT()
|
||||||
Opcode.CLC -> { statusCarry = false; pc++ }
|
Opcode.CLC -> { statusCarry = false; pc++ }
|
||||||
Opcode.SEC -> { statusCarry = true; 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}")
|
else -> throw IllegalArgumentException("invalid opcode ${ins.opcode}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1041,6 +1062,26 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
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> {
|
private fun getBranchOperands(i: Instruction): Pair<Int, Int> {
|
||||||
return when(i.type) {
|
return when(i.type) {
|
||||||
VmDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), registers.getSB(i.reg2!!).toInt())
|
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> {
|
private fun getSetOnConditionOperands(ins: Instruction): Triple<Int, Int, Int> {
|
||||||
return when(ins.type) {
|
return when(ins.type) {
|
||||||
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getSB(ins.reg2!!).toInt(), registers.getSB(ins.reg3!!).toInt())
|
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getSB(ins.reg2!!).toInt(), registers.getSB(ins.reg3!!).toInt())
|
||||||
|
Loading…
Reference in New Issue
Block a user