mirror of
https://github.com/irmen/prog8.git
synced 2025-08-14 22:27:48 +00:00
vm: implement float to integer cast, any, all, reverse
This commit is contained in:
@@ -328,8 +328,6 @@ internal class AssignmentAsmGen(private val program: Program,
|
|||||||
val variable = (containment.iterable as? IdentifierReference)?.targetVarDecl(program)
|
val variable = (containment.iterable as? IdentifierReference)?.targetVarDecl(program)
|
||||||
?: throw AssemblyError("invalid containment iterable type")
|
?: throw AssemblyError("invalid containment iterable type")
|
||||||
|
|
||||||
if(elementDt istype DataType.FLOAT)
|
|
||||||
throw AssemblyError("containment check of floats not supported")
|
|
||||||
if(variable.origin!=VarDeclOrigin.USERCODE) {
|
if(variable.origin!=VarDeclOrigin.USERCODE) {
|
||||||
when(variable.datatype) {
|
when(variable.datatype) {
|
||||||
DataType.STR -> {
|
DataType.STR -> {
|
||||||
@@ -388,7 +386,9 @@ internal class AssignmentAsmGen(private val program: Program,
|
|||||||
asmgen.out(" jsr prog8_lib.containment_bytearray")
|
asmgen.out(" jsr prog8_lib.containment_bytearray")
|
||||||
return
|
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 -> {
|
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
||||||
val arrayVal = variable.value as ArrayLiteral
|
val arrayVal = variable.value as ArrayLiteral
|
||||||
assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt istype DataType.BYTE)
|
assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt istype DataType.BYTE)
|
||||||
|
@@ -64,36 +64,34 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
private fun funcAny(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
private fun funcAny(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||||
val arrayName = call.args[0] as PtIdentifier
|
val arrayName = call.args[0] as PtIdentifier
|
||||||
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
|
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
|
||||||
val elementDt: VmDataType = codeGen.vmType(ArrayToElementTypes.getValue(array.dt))
|
val code = VmCodeChunk()
|
||||||
val syscall =
|
val syscall =
|
||||||
when(array.dt) {
|
when (array.dt) {
|
||||||
DataType.ARRAY_UB,
|
DataType.ARRAY_UB,
|
||||||
DataType.ARRAY_B -> Syscall.ANY_BYTE
|
DataType.ARRAY_B -> Syscall.ANY_BYTE
|
||||||
DataType.ARRAY_UW,
|
DataType.ARRAY_UW,
|
||||||
DataType.ARRAY_W -> Syscall.ANY_WORD
|
DataType.ARRAY_W -> Syscall.ANY_WORD
|
||||||
DataType.ARRAY_F -> TODO("float any")
|
DataType.ARRAY_F -> Syscall.ANY_FLOAT
|
||||||
else -> throw IllegalArgumentException("weird type")
|
else -> throw IllegalArgumentException("weird type")
|
||||||
}
|
}
|
||||||
val code = VmCodeChunk()
|
|
||||||
code += exprGen.translateExpression(call.args[0], 0, -1)
|
code += exprGen.translateExpression(call.args[0], 0, -1)
|
||||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1 = 1, value = array.length)
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
code += VmCodeInstruction(Opcode.SYSCALL, value = syscall.ordinal)
|
||||||
if(resultRegister!=0)
|
if (resultRegister != 0)
|
||||||
code += VmCodeInstruction(Opcode.LOADR, elementDt, reg1=resultRegister, reg2=0)
|
code += VmCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1 = resultRegister, reg2 = 0)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun funcAll(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
private fun funcAll(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||||
val arrayName = call.args[0] as PtIdentifier
|
val arrayName = call.args[0] as PtIdentifier
|
||||||
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
|
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
|
||||||
val elementDt: VmDataType = codeGen.vmType(ArrayToElementTypes.getValue(array.dt))
|
|
||||||
val syscall =
|
val syscall =
|
||||||
when(array.dt) {
|
when(array.dt) {
|
||||||
DataType.ARRAY_UB,
|
DataType.ARRAY_UB,
|
||||||
DataType.ARRAY_B -> Syscall.ALL_BYTE
|
DataType.ARRAY_B -> Syscall.ALL_BYTE
|
||||||
DataType.ARRAY_UW,
|
DataType.ARRAY_UW,
|
||||||
DataType.ARRAY_W -> Syscall.ALL_WORD
|
DataType.ARRAY_W -> Syscall.ALL_WORD
|
||||||
DataType.ARRAY_F -> TODO("float all")
|
DataType.ARRAY_F -> Syscall.ALL_FLOAT
|
||||||
else -> throw IllegalArgumentException("weird type")
|
else -> throw IllegalArgumentException("weird type")
|
||||||
}
|
}
|
||||||
val code = VmCodeChunk()
|
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.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
code += VmCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
||||||
if(resultRegister!=0)
|
if(resultRegister!=0)
|
||||||
code += VmCodeInstruction(Opcode.LOADR, elementDt, reg1=resultRegister, reg2=0)
|
code += VmCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +199,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
when(array.dt) {
|
when(array.dt) {
|
||||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.STR -> Syscall.REVERSE_BYTES
|
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.STR -> Syscall.REVERSE_BYTES
|
||||||
DataType.ARRAY_UW, DataType.ARRAY_W -> Syscall.REVERSE_WORDS
|
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")
|
else -> throw IllegalArgumentException("weird type to reverse")
|
||||||
}
|
}
|
||||||
val code = VmCodeChunk()
|
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_B -> Syscall.SORT_BYTE
|
||||||
DataType.ARRAY_UW -> Syscall.SORT_UWORD
|
DataType.ARRAY_UW -> Syscall.SORT_UWORD
|
||||||
DataType.ARRAY_W -> Syscall.SORT_WORD
|
DataType.ARRAY_W -> Syscall.SORT_WORD
|
||||||
DataType.ARRAY_F -> TODO("float sort")
|
|
||||||
DataType.STR -> Syscall.SORT_UBYTE
|
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")
|
else -> throw IllegalArgumentException("weird type to sort")
|
||||||
}
|
}
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
|
@@ -62,7 +62,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
}
|
}
|
||||||
is PtTypeCast -> code += translate(expr, resultRegister, resultFpRegister)
|
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, resultFpRegister)
|
||||||
is PtBinaryExpression -> code += translate(expr, resultRegister, resultFpRegister)
|
is PtBinaryExpression -> code += translate(expr, resultRegister, resultFpRegister)
|
||||||
is PtBuiltinFunctionCall -> code += codeGen.translateBuiltinFunc(expr, resultRegister)
|
is PtBuiltinFunctionCall -> code += codeGen.translateBuiltinFunc(expr, resultRegister)
|
||||||
is PtFunctionCall -> code += translate(expr, resultRegister, resultFpRegister)
|
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))
|
call.children.add(PtNumber(DataType.UBYTE, iterable.length!!.toDouble(), iterable.position))
|
||||||
code += translate(call, resultRegister, resultFpRegister)
|
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}")
|
else -> throw AssemblyError("weird iterable dt ${iterable.dt} for ${check.iterable.targetName}")
|
||||||
}
|
}
|
||||||
return code
|
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 eltSize = codeGen.program.memsizer.memorySize(arrayIx.type)
|
||||||
val vmDt = codeGen.vmType(arrayIx.type)
|
val vmDt = codeGen.vmType(arrayIx.type)
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
@@ -154,12 +154,18 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
if(arrayIx.index is PtNumber) {
|
if(arrayIx.index is PtNumber) {
|
||||||
// optimized code when index is known - just calculate the memory address here
|
// optimized code when index is known - just calculate the memory address here
|
||||||
val memOffset = (arrayIx.index as PtNumber).number.toInt() * eltSize
|
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 {
|
} else {
|
||||||
code += translateExpression(arrayIx.index, idxReg, -1)
|
code += translateExpression(arrayIx.index, idxReg, -1)
|
||||||
if(eltSize>1)
|
if(eltSize>1)
|
||||||
code += codeGen.multiplyByConst(VmDataType.BYTE, idxReg, eltSize)
|
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
|
return code
|
||||||
}
|
}
|
||||||
@@ -193,29 +199,30 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
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()
|
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()
|
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) {
|
if(cast.value.type==DataType.FLOAT) {
|
||||||
// a cast from float to integer, so evaluate the value into a float register first
|
// a cast from float to integer, so evaluate the value into a float register first
|
||||||
code += translateExpression(cast.value, -1, actualResultFpReg)
|
code += translateExpression(cast.value, -1, actualResultFpReg)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
code += translateExpression(cast.value, resultRegister, -1)
|
code += translateExpression(cast.value, actualResultReg, -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 -> 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")
|
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 -> 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")
|
else -> throw AssemblyError("weird cast value type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,15 +230,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
when(cast.value.type) {
|
when(cast.value.type) {
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
// byte -> uword: sign extend
|
// byte -> uword: sign extend
|
||||||
code += VmCodeInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = resultRegister)
|
code += VmCodeInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = actualResultReg)
|
||||||
}
|
}
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
// ubyte -> uword: sign extend
|
// 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.WORD -> { }
|
||||||
DataType.FLOAT -> {
|
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")
|
else -> throw AssemblyError("weird cast value type")
|
||||||
}
|
}
|
||||||
@@ -240,32 +247,35 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
when(cast.value.type) {
|
when(cast.value.type) {
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
// byte -> word: sign extend
|
// byte -> word: sign extend
|
||||||
code += VmCodeInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = resultRegister)
|
code += VmCodeInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = actualResultReg)
|
||||||
}
|
}
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
// byte -> word: sign extend
|
// 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.UWORD -> { }
|
||||||
DataType.FLOAT -> {
|
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")
|
else -> throw AssemblyError("weird cast value type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
TODO("floating point to integer cast not yet supported")
|
when(cast.value.type) {
|
||||||
// when(cast.value.type) {
|
DataType.UBYTE -> {
|
||||||
// DataType.BYTE -> {
|
code += VmCodeInstruction(Opcode.FFROMUB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||||
// }
|
}
|
||||||
// DataType.UBYTE -> {
|
DataType.BYTE -> {
|
||||||
// }
|
code += VmCodeInstruction(Opcode.FFROMSB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||||
// DataType.WORD -> {
|
}
|
||||||
// }
|
DataType.UWORD -> {
|
||||||
// DataType.UWORD -> {
|
code += VmCodeInstruction(Opcode.FFROMUW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||||
// }
|
}
|
||||||
// else -> throw AssemblyError("weird cast value type")
|
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")
|
else -> throw AssemblyError("weird cast type")
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,7 @@ sub print_f(float value) {
|
|||||||
; ---- prints the floating point value (without a newline).
|
; ---- prints the floating point value (without a newline).
|
||||||
%asm {{
|
%asm {{
|
||||||
loadm.f fr0,{floats.print_f.value}
|
loadm.f fr0,{floats.print_f.value}
|
||||||
syscall 35
|
syscall 25
|
||||||
return
|
return
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@ TODO
|
|||||||
|
|
||||||
For next release
|
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?
|
- 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.
|
- 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
|
- 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 modes 2 and 3 to gfx2 (lowres 4 color and 16 color)?
|
||||||
- add a flood fill routine to gfx2?
|
- 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)
|
- 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:
|
Expressions:
|
||||||
|
|
||||||
|
@@ -9,15 +9,19 @@
|
|||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
float fl = 42.123
|
float fl = 42.123
|
||||||
float fl2 = fl / 1.0
|
float[] farray = [0.0, 0.0, 1.11, 2.22, 42.123, 0.0, -99.99]
|
||||||
txt.print("rad 180 = ")
|
ubyte ix
|
||||||
floats.print_f(floats.rad(180.0))
|
for ix in 0 to len(farray)-1 {
|
||||||
txt.print("\nrad 360 = ")
|
floats.print_f(farray[ix])
|
||||||
floats.print_f(floats.rad(360.0))
|
txt.spc()
|
||||||
txt.print("\ndeg 2 = ")
|
}
|
||||||
floats.print_f(floats.deg(2.0))
|
txt.nl()
|
||||||
txt.print("\ndeg pi = ")
|
reverse(farray)
|
||||||
floats.print_f(floats.deg(floats.PI))
|
for ix in 0 to len(farray)-1 {
|
||||||
|
floats.print_f(farray[ix])
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
|
txt.nl()
|
||||||
sys.exit(42)
|
sys.exit(42)
|
||||||
; floats.print_f(-42.42)
|
; floats.print_f(-42.42)
|
||||||
; float f1 = 1.2345
|
; float f1 = 1.2345
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
<keywords keywords="&;->;@;\$;and;as;asmsub;break;clobbers;do;downto;else;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;romsub;step;sub;to;true;until;when;while;xor;~" ignore_case="false" />
|
<keywords keywords="&;->;@;\$;and;as;asmsub;break;clobbers;do;downto;else;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;romsub;step;sub;to;true;until;when;while;xor;~" ignore_case="false" />
|
||||||
<keywords2 keywords="%address;%asm;%asmbinary;%asminclude;%breakpoint;%import;%launcher;%option;%output;%zeropage;%zpreserved;iso:;petscii:;sc:" />
|
<keywords2 keywords="%address;%asm;%asmbinary;%asminclude;%breakpoint;%import;%launcher;%option;%output;%zeropage;%zpreserved;iso:;petscii:;sc:" />
|
||||||
<keywords3 keywords="@requirezp;@shared;@zp;byte;const;float;str;ubyte;uword;void;word" />
|
<keywords3 keywords="@requirezp;@shared;@zp;byte;const;float;str;ubyte;uword;void;word" />
|
||||||
<keywords4 keywords="abs;all;any;avg;callfar;callrom;cmp;len;lsb;max;memory;min;mkword;msb;peek;peekw;poke;pokew;pop;popw;push;pushw;reverse;rnd;rndw;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;sgn;sizeof;sort;sqrt16;sum;swap;|>" />
|
<keywords4 keywords="abs;all;any;avg;callfar;callrom;cmp;len;lsb;memory;mkword;msb;peek;peekw;poke;pokew;pop;popw;push;pushw;reverse;rnd;rndw;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;sgn;sizeof;sort;sqrt16;swap;|>" />
|
||||||
</highlighting>
|
</highlighting>
|
||||||
<extensionMap>
|
<extensionMap>
|
||||||
<mapping ext="p8" />
|
<mapping ext="p8" />
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
<Keywords name="Keywords1">void const
str
byte ubyte
word uword
float
zp shared requirezp</Keywords>
|
<Keywords name="Keywords1">void const
str
byte ubyte
word uword
float
zp shared requirezp</Keywords>
|
||||||
<Keywords name="Keywords2">%address
%asm
%asmbinary
%asminclude
%breakpoint
%import
%launcher
%option
%output
%zeropage
%zpreserved</Keywords>
|
<Keywords name="Keywords2">%address
%asm
%asmbinary
%asminclude
%breakpoint
%import
%launcher
%option
%output
%zeropage
%zpreserved</Keywords>
|
||||||
<Keywords name="Keywords3">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</Keywords>
|
<Keywords name="Keywords3">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</Keywords>
|
||||||
<Keywords name="Keywords4">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</Keywords>
|
<Keywords name="Keywords4">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</Keywords>
|
||||||
<Keywords name="Keywords5">true false
not and or xor
as to downto |></Keywords>
|
<Keywords name="Keywords5">true false
not and or xor
as to downto |></Keywords>
|
||||||
<Keywords name="Keywords6"></Keywords>
|
<Keywords name="Keywords6"></Keywords>
|
||||||
<Keywords name="Keywords7"></Keywords>
|
<Keywords name="Keywords7"></Keywords>
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
syn keyword prog8BuiltInFunc sgn sqrt16
|
syn keyword prog8BuiltInFunc sgn sqrt16
|
||||||
|
|
||||||
" Array functions
|
" Array functions
|
||||||
syn keyword prog8BuiltInFunc any all len max min reverse sum sort
|
syn keyword prog8BuiltInFunc any all len reverse sort
|
||||||
|
|
||||||
" Miscellaneous functions
|
" Miscellaneous functions
|
||||||
syn keyword prog8BuiltInFunc cmp lsb msb mkword peek peekw poke pokew rnd rndw push pushw pop popw rsave rsavex rrestore rrestorex
|
syn keyword prog8BuiltInFunc cmp lsb msb mkword peek peekw poke pokew rnd rndw push pushw pop popw rsave rsavex rrestore rrestorex
|
||||||
|
@@ -24,23 +24,16 @@ SYSCALLS:
|
|||||||
16 = sort_byte array
|
16 = sort_byte array
|
||||||
17 = sort_uword array
|
17 = sort_uword array
|
||||||
18 = sort_word array
|
18 = sort_word array
|
||||||
19 = max_ubyte array
|
19 = any_byte array
|
||||||
20 = max_byte array
|
20 = any_word array
|
||||||
21 = max_uword array
|
21 = any_float array
|
||||||
22 = max_word array
|
22 = all_byte array
|
||||||
23 = min_ubyte array
|
23 = all_word array
|
||||||
24 = min_byte array
|
24 = all_float array
|
||||||
25 = min_uword array
|
25 = print_f (floating point value in fp reg 0)
|
||||||
26 = min_word array
|
26 = reverse_bytes array
|
||||||
27 = sum_byte array
|
27 = reverse_words array
|
||||||
28 = sum_word array
|
28 = reverse_floats 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)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum class Syscall {
|
enum class Syscall {
|
||||||
@@ -63,23 +56,16 @@ enum class Syscall {
|
|||||||
SORT_BYTE,
|
SORT_BYTE,
|
||||||
SORT_UWORD,
|
SORT_UWORD,
|
||||||
SORT_WORD,
|
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_BYTE,
|
||||||
ANY_WORD,
|
ANY_WORD,
|
||||||
|
ANY_FLOAT,
|
||||||
ALL_BYTE,
|
ALL_BYTE,
|
||||||
ALL_WORD,
|
ALL_WORD,
|
||||||
|
ALL_FLOAT,
|
||||||
|
PRINT_F,
|
||||||
REVERSE_BYTES,
|
REVERSE_BYTES,
|
||||||
REVERSE_WORDS,
|
REVERSE_WORDS,
|
||||||
PRINT_F
|
REVERSE_FLOATS,
|
||||||
}
|
}
|
||||||
|
|
||||||
object SysCalls {
|
object SysCalls {
|
||||||
@@ -191,75 +177,15 @@ object SysCalls {
|
|||||||
vm.memory.setUW(address+index*2, value)
|
vm.memory.setUW(address+index*2, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Syscall.MAX_UBYTE -> {
|
Syscall.REVERSE_FLOATS -> {
|
||||||
val address = vm.registers.getUW(0).toInt()
|
val address = vm.registers.getUW(0).toInt()
|
||||||
val length = vm.registers.getUB(1).toInt()
|
val length = vm.registers.getUB(1).toInt()
|
||||||
val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2)
|
val array = IntProgression.fromClosedRange(address, address+length*4-2, 4).map {
|
||||||
val value = addresses.map { vm.memory.getUB(it) }.maxOf { it }
|
vm.memory.getFloat(it)
|
||||||
vm.registers.setUB(0, value)
|
}.reversed()
|
||||||
}
|
array.withIndex().forEach { (index, value)->
|
||||||
Syscall.MAX_BYTE -> {
|
vm.memory.setFloat(address+index*4, value)
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
Syscall.ANY_BYTE -> {
|
Syscall.ANY_BYTE -> {
|
||||||
val address = vm.registers.getUW(0).toInt()
|
val address = vm.registers.getUW(0).toInt()
|
||||||
@@ -279,6 +205,15 @@ object SysCalls {
|
|||||||
else
|
else
|
||||||
vm.registers.setUB(0, 0u)
|
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 -> {
|
Syscall.ALL_BYTE -> {
|
||||||
val address = vm.registers.getUW(0).toInt()
|
val address = vm.registers.getUW(0).toInt()
|
||||||
val length = vm.registers.getUB(1).toInt()
|
val length = vm.registers.getUB(1).toInt()
|
||||||
@@ -297,6 +232,15 @@ object SysCalls {
|
|||||||
else
|
else
|
||||||
vm.registers.setUB(0, 0u)
|
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 -> {
|
Syscall.PRINT_F -> {
|
||||||
val value = vm.registers.getFloat(0)
|
val value = vm.registers.getFloat(0)
|
||||||
print(value)
|
print(value)
|
||||||
|
@@ -173,10 +173,10 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
Opcode.CLC -> { statusCarry = false; pc++ }
|
Opcode.CLC -> { statusCarry = false; pc++ }
|
||||||
Opcode.SEC -> { statusCarry = true; pc++ }
|
Opcode.SEC -> { statusCarry = true; pc++ }
|
||||||
|
|
||||||
Opcode.FFROMUB -> TODO()
|
Opcode.FFROMUB -> InsFFROMUB(ins)
|
||||||
Opcode.FFROMSB -> TODO()
|
Opcode.FFROMSB -> InsFFROMSB(ins)
|
||||||
Opcode.FFROMUW -> TODO()
|
Opcode.FFROMUW -> InsFFROMUW(ins)
|
||||||
Opcode.FFROMSW -> TODO()
|
Opcode.FFROMSW -> InsFFROMSW(ins)
|
||||||
Opcode.FTOUB -> InsFTOUB(ins)
|
Opcode.FTOUB -> InsFTOUB(ins)
|
||||||
Opcode.FTOSB -> InsFTOSB(ins)
|
Opcode.FTOSB -> InsFTOSB(ins)
|
||||||
Opcode.FTOUW -> InsFTOUW(ins)
|
Opcode.FTOUW -> InsFTOUW(ins)
|
||||||
@@ -276,7 +276,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(registers.getUW(i.reg2!!).toInt()))
|
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.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++
|
pc++
|
||||||
}
|
}
|
||||||
@@ -285,7 +285,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
when (i.type!!) {
|
when (i.type!!) {
|
||||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(i.value!! + registers.getUW(i.reg2!!).toInt()))
|
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.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++
|
pc++
|
||||||
}
|
}
|
||||||
@@ -1062,6 +1062,26 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
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) {
|
private fun InsFTOUB(i: Instruction) {
|
||||||
registers.setUB(i.reg1!!, registers.getFloat(i.fpReg1!!).toInt().toUByte())
|
registers.setUB(i.reg1!!, registers.getFloat(i.fpReg1!!).toInt().toUByte())
|
||||||
pc++
|
pc++
|
||||||
|
Reference in New Issue
Block a user