vm: implement float to integer cast, any, all, reverse

This commit is contained in:
Irmen de Jong
2022-05-04 20:47:48 +02:00
parent 3f9cdd9b56
commit da01a5b4dc
11 changed files with 136 additions and 159 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,7 +14,7 @@
<keywords keywords="&amp;;-&gt;;@;\$;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="&amp;;-&gt;;@;\$;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;|&gt;" /> <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;|&gt;" />
</highlighting> </highlighting>
<extensionMap> <extensionMap>
<mapping ext="p8" /> <mapping ext="p8" />

View File

@@ -27,7 +27,7 @@
<Keywords name="Keywords1">void const&#x000D;&#x000A;str&#x000D;&#x000A;byte ubyte&#x000D;&#x000A;word uword&#x000D;&#x000A;float&#x000D;&#x000A;zp shared requirezp</Keywords> <Keywords name="Keywords1">void const&#x000D;&#x000A;str&#x000D;&#x000A;byte ubyte&#x000D;&#x000A;word uword&#x000D;&#x000A;float&#x000D;&#x000A;zp shared requirezp</Keywords>
<Keywords name="Keywords2">%address&#x000D;&#x000A;%asm&#x000D;&#x000A;%asmbinary&#x000D;&#x000A;%asminclude&#x000D;&#x000A;%breakpoint&#x000D;&#x000A;%import&#x000D;&#x000A;%launcher&#x000D;&#x000A;%option&#x000D;&#x000A;%output&#x000D;&#x000A;%zeropage&#x000D;&#x000A;%zpreserved</Keywords> <Keywords name="Keywords2">%address&#x000D;&#x000A;%asm&#x000D;&#x000A;%asmbinary&#x000D;&#x000A;%asminclude&#x000D;&#x000A;%breakpoint&#x000D;&#x000A;%import&#x000D;&#x000A;%launcher&#x000D;&#x000A;%option&#x000D;&#x000A;%output&#x000D;&#x000A;%zeropage&#x000D;&#x000A;%zpreserved</Keywords>
<Keywords name="Keywords3">inline sub asmsub romsub&#x000D;&#x000A;clobbers&#x000D;&#x000A;asm&#x000D;&#x000A;if&#x000D;&#x000A;when else&#x000D;&#x000A;if_cc if_cs if_eq if_mi if_neg if_nz if_pl if_pos if_vc if_vs if_z&#x000D;&#x000A;for in step do while repeat&#x000D;&#x000A;break return goto</Keywords> <Keywords name="Keywords3">inline sub asmsub romsub&#x000D;&#x000A;clobbers&#x000D;&#x000A;asm&#x000D;&#x000A;if&#x000D;&#x000A;when else&#x000D;&#x000A;if_cc if_cs if_eq if_mi if_neg if_nz if_pl if_pos if_vc if_vs if_z&#x000D;&#x000A;for in step do while repeat&#x000D;&#x000A;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&#x000D;&#x000A;not and or xor&#x000D;&#x000A;as to downto |&gt;</Keywords> <Keywords name="Keywords5">true false&#x000D;&#x000A;not and or xor&#x000D;&#x000A;as to downto |&gt;</Keywords>
<Keywords name="Keywords6"></Keywords> <Keywords name="Keywords6"></Keywords>
<Keywords name="Keywords7"></Keywords> <Keywords name="Keywords7"></Keywords>

View File

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

View File

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

View File

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