ir/vm: syscall params in high base register to avoid push/pop

This commit is contained in:
Irmen de Jong 2022-11-06 12:40:39 +01:00
parent 469e042216
commit 38efaae7b2
14 changed files with 186 additions and 193 deletions

View File

@ -71,11 +71,11 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
else -> throw IllegalArgumentException("weird type") else -> throw IllegalArgumentException("weird type")
} }
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
result += exprGen.translateExpression(call.args[0], 0, -1) result += exprGen.translateExpression(call.args[0], SyscallRegisterBase, -1)
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = 1, value = array.length) it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = SyscallRegisterBase+1, value = array.length)
it += IRInstruction(Opcode.SYSCALL, value = syscall.number) it += IRInstruction(Opcode.SYSCALL, value = syscall.number)
if (resultRegister != 0) if(resultRegister!=0)
it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1 = resultRegister, reg2 = 0) it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1 = resultRegister, reg2 = 0)
} }
return result return result
@ -94,11 +94,11 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
else -> throw IllegalArgumentException("weird type") else -> throw IllegalArgumentException("weird type")
} }
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
result += exprGen.translateExpression(call.args[0], 0, -1) result += exprGen.translateExpression(call.args[0], SyscallRegisterBase, -1)
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = 1, value = array.length) it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = SyscallRegisterBase+1, value = array.length)
it += IRInstruction(Opcode.SYSCALL, value = syscall.number) it += IRInstruction(Opcode.SYSCALL, value = syscall.number)
if (resultRegister != 0) if(resultRegister!=0)
it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1 = resultRegister, reg2 = 0) it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1 = resultRegister, reg2 = 0)
} }
return result return result
@ -213,9 +213,9 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
else -> throw IllegalArgumentException("weird type to reverse") else -> throw IllegalArgumentException("weird type to reverse")
} }
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
result += exprGen.translateExpression(call.args[0], 0, -1) result += exprGen.translateExpression(call.args[0], SyscallRegisterBase, -1)
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = 1, value = array.length) it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = SyscallRegisterBase+1, value = array.length)
it += IRInstruction(Opcode.SYSCALL, value = syscall.number) it += IRInstruction(Opcode.SYSCALL, value = syscall.number)
} }
return result return result
@ -235,9 +235,9 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
else -> throw IllegalArgumentException("weird type to sort") else -> throw IllegalArgumentException("weird type to sort")
} }
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
result += exprGen.translateExpression(call.args[0], 0, -1) result += exprGen.translateExpression(call.args[0], SyscallRegisterBase, -1)
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = 1, value = array.length) it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = SyscallRegisterBase+1, value = array.length)
it += IRInstruction(Opcode.SYSCALL, value = syscall.number) it += IRInstruction(Opcode.SYSCALL, value = syscall.number)
} }
return result return result

View File

@ -10,7 +10,7 @@ import prog8.intermediate.*
internal class ExpressionGen(private val codeGen: IRCodeGen) { internal class ExpressionGen(private val codeGen: IRCodeGen) {
fun translateExpression(expr: PtExpression, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { fun translateExpression(expr: PtExpression, resultRegister: Int, resultFpRegister: Int): IRCodeChunks {
require(codeGen.registers.peekNext() > resultRegister) require(codeGen.registers.peekNext() > resultRegister || resultRegister >= SyscallRegisterBase)
return when (expr) { return when (expr) {
is PtMachineRegister -> { is PtMachineRegister -> {
@ -101,49 +101,33 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val iterable = codeGen.symbolTable.flat.getValue(check.iterable.targetName) as StStaticVariable val iterable = codeGen.symbolTable.flat.getValue(check.iterable.targetName) as StStaticVariable
when(iterable.dt) { when(iterable.dt) {
DataType.STR -> { DataType.STR -> {
val push = IRCodeChunk(null, null) result += translateExpression(check.element, SyscallRegisterBase, -1)
push += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=1) result += translateExpression(check.iterable, SyscallRegisterBase+1, -1)
result += push result += IRCodeChunk(null, null).also {
result += translateExpression(check.element, 0, -1) it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.STRING_CONTAINS.number)
result += translateExpression(check.iterable, 1, -1)
val syscall = IRCodeChunk(null, null)
syscall += IRInstruction(Opcode.SYSCALL, value = IMSyscall.STRING_CONTAINS.number)
syscall += IRInstruction(Opcode.POP, IRDataType.WORD, reg1=1)
if(resultRegister!=0) if(resultRegister!=0)
syscall += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=resultRegister, reg2=0) it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=resultRegister, reg2=0)
result += syscall }
} }
DataType.ARRAY_UB, DataType.ARRAY_B -> { DataType.ARRAY_UB, DataType.ARRAY_B -> {
val push = IRCodeChunk(null, null) result += translateExpression(check.element, SyscallRegisterBase, -1)
push += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=1) result += translateExpression(check.iterable, SyscallRegisterBase+1, -1)
push += IRInstruction(Opcode.PUSH, IRDataType.BYTE, reg1=2) result += IRCodeChunk(null, null).also {
result += push it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=SyscallRegisterBase+2, value = iterable.length!!)
result += translateExpression(check.element, 0, -1) it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.BYTEARRAY_CONTAINS.number)
result += translateExpression(check.iterable, 1, -1)
val syscall = IRCodeChunk(null, null)
syscall += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=2, value = iterable.length!!)
syscall += IRInstruction(Opcode.SYSCALL, value = IMSyscall.BYTEARRAY_CONTAINS.number)
syscall += IRInstruction(Opcode.POP, IRDataType.BYTE, reg1=2)
syscall += IRInstruction(Opcode.POP, IRDataType.WORD, reg1=1)
if(resultRegister!=0) if(resultRegister!=0)
syscall += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=resultRegister, reg2=0) it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=resultRegister, reg2=0)
result += syscall }
} }
DataType.ARRAY_UW, DataType.ARRAY_W -> { DataType.ARRAY_UW, DataType.ARRAY_W -> {
val push = IRCodeChunk(null, null) result += translateExpression(check.element, SyscallRegisterBase, -1)
push += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=1) result += translateExpression(check.iterable, SyscallRegisterBase+1, -1)
push += IRInstruction(Opcode.PUSH, IRDataType.BYTE, reg1=2) result += IRCodeChunk(null, null).also {
result += push it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=SyscallRegisterBase+2, value = iterable.length!!)
result += translateExpression(check.element, 0, -1) it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.WORDARRAY_CONTAINS.number)
result += translateExpression(check.iterable, 1, -1)
val syscall = IRCodeChunk(null, null)
syscall += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=2, value = iterable.length!!)
syscall += IRInstruction(Opcode.SYSCALL, value = IMSyscall.WORDARRAY_CONTAINS.number)
syscall += IRInstruction(Opcode.POP, IRDataType.BYTE, reg1=2)
syscall += IRInstruction(Opcode.POP, IRDataType.WORD, reg1=1)
if(resultRegister!=0) if(resultRegister!=0)
syscall += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=resultRegister, reg2=0) it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=resultRegister, reg2=0)
result += syscall }
} }
DataType.ARRAY_F -> throw AssemblyError("containment check in float-array not supported") 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}")
@ -332,23 +316,18 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister), null) addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister), null)
} else { } else {
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) { if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
require(codeGen.registers.peekNext() > 1) result += translateExpression(binExpr.left, SyscallRegisterBase, -1)
val push = IRCodeChunk(null, null) result += translateExpression(binExpr.right, SyscallRegisterBase+1, -1)
push += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=1) result += IRCodeChunk(null, null).also {
result += push it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number)
result += translateExpression(binExpr.left, 0, -1)
result += translateExpression(binExpr.right, 1, -1)
val syscall = IRCodeChunk(null, null)
syscall += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number)
if(resultRegister!=0) if(resultRegister!=0)
syscall += IRInstruction(Opcode.LOADR, vmDt, reg1=resultRegister, reg2=0) it += IRInstruction(Opcode.LOADR, vmDt, reg1 = resultRegister, reg2 = 0)
syscall += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=1, value=0) it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = 1, value = 0)
syscall += if(greaterEquals) it += if (greaterEquals)
IRInstruction(Opcode.SGES, IRDataType.BYTE, reg1=resultRegister, reg2=1) IRInstruction(Opcode.SGES, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1)
else else
IRInstruction(Opcode.SGTS, IRDataType.BYTE, reg1=resultRegister, reg2=1) IRInstruction(Opcode.SGTS, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1)
syscall += IRInstruction(Opcode.POP, IRDataType.WORD, reg1=1) }
result += syscall
} else { } else {
val rightResultReg = codeGen.registers.nextFree() val rightResultReg = codeGen.registers.nextFree()
result += translateExpression(binExpr.left, resultRegister, -1) result += translateExpression(binExpr.left, resultRegister, -1)
@ -388,23 +367,18 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister), null) addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister), null)
} else { } else {
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) { if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
require(codeGen.registers.peekNext() > 1) result += translateExpression(binExpr.left, SyscallRegisterBase, -1)
val push = IRCodeChunk(null, null) result += translateExpression(binExpr.right, SyscallRegisterBase+1, -1)
push += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=1) result += IRCodeChunk(null, null).also {
result += push it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number)
result += translateExpression(binExpr.left, 0, -1)
result += translateExpression(binExpr.right, 1, -1)
val syscall = IRCodeChunk(null, null)
syscall += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number)
if(resultRegister!=0) if(resultRegister!=0)
syscall += IRInstruction(Opcode.LOADR, vmDt, reg1=resultRegister, reg2=0) it += IRInstruction(Opcode.LOADR, vmDt, reg1 = resultRegister, reg2 = 0)
syscall += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=1, value=0) it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = 1, value = 0)
syscall += if(lessEquals) it += if (lessEquals)
IRInstruction(Opcode.SLES, IRDataType.BYTE, reg1=resultRegister, reg2=1) IRInstruction(Opcode.SLES, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1)
else else
IRInstruction(Opcode.SLTS, IRDataType.BYTE, reg1=resultRegister, reg2=1) IRInstruction(Opcode.SLTS, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1)
syscall += IRInstruction(Opcode.POP, IRDataType.WORD, reg1=1) }
result += syscall
} else { } else {
val rightResultReg = codeGen.registers.nextFree() val rightResultReg = codeGen.registers.nextFree()
result += translateExpression(binExpr.left, resultRegister, -1) result += translateExpression(binExpr.left, resultRegister, -1)
@ -440,21 +414,16 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
} }
} else { } else {
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) { if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
require(codeGen.registers.peekNext() > 1) result += translateExpression(binExpr.left, SyscallRegisterBase, -1)
val push = IRCodeChunk(null, null) result += translateExpression(binExpr.right, SyscallRegisterBase+1, -1)
push += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=1) result += IRCodeChunk(null, null).also {
result += push it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number)
result += translateExpression(binExpr.left, 0, -1)
result += translateExpression(binExpr.right, 1, -1)
val syscall = IRCodeChunk(null, null)
syscall += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number)
syscall += IRInstruction(Opcode.POP, IRDataType.WORD, reg1=1)
if(resultRegister!=0) if(resultRegister!=0)
syscall += IRInstruction(Opcode.LOADR, vmDt, reg1=resultRegister, reg2=0) it += IRInstruction(Opcode.LOADR, vmDt, reg1 = resultRegister, reg2 = 0)
if(!notEquals) if (!notEquals)
syscall += IRInstruction(Opcode.INV, vmDt, reg1=resultRegister) it += IRInstruction(Opcode.INV, vmDt, reg1 = resultRegister)
syscall += IRInstruction(Opcode.AND, vmDt, reg1=resultRegister, value=1) it += IRInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value = 1)
result += syscall }
} else { } else {
val rightResultReg = codeGen.registers.nextFree() val rightResultReg = codeGen.registers.nextFree()
result += translateExpression(binExpr.left, resultRegister, -1) result += translateExpression(binExpr.left, resultRegister, -1)

View File

@ -1,10 +1,12 @@
package prog8.codegen.intermediate package prog8.codegen.intermediate
import prog8.code.core.AssemblyError import prog8.code.core.AssemblyError
import prog8.intermediate.SyscallRegisterBase
internal class RegisterPool { internal class RegisterPool {
private var firstFree: Int=3 // integer registers 0,1,2 are reserved // reserve 0,1,2 for return values of subroutine calls and syscalls
private var firstFreeFloat: Int=0 private var firstFree: Int=3
private var firstFreeFloat: Int=3
fun peekNext() = firstFree fun peekNext() = firstFree
fun peekNextFloat() = firstFreeFloat fun peekNextFloat() = firstFreeFloat
@ -12,7 +14,7 @@ internal class RegisterPool {
fun nextFree(): Int { fun nextFree(): Int {
val result = firstFree val result = firstFree
firstFree++ firstFree++
if(firstFree>65535) if(firstFree >= SyscallRegisterBase)
throw AssemblyError("out of virtual registers (int)") throw AssemblyError("out of virtual registers (int)")
return result return result
} }
@ -20,7 +22,7 @@ internal class RegisterPool {
fun nextFreeFloat(): Int { fun nextFreeFloat(): Int {
val result = firstFreeFloat val result = firstFreeFloat
firstFreeFloat++ firstFreeFloat++
if(firstFreeFloat>65535) if(firstFreeFloat >= SyscallRegisterBase)
throw AssemblyError("out of virtual registers (fp)") throw AssemblyError("out of virtual registers (fp)")
return result return result
} }

View File

@ -196,7 +196,7 @@ sub str2uword(str string) -> uword {
; the number may NOT be preceded by a + sign and may NOT contain spaces ; the number may NOT be preceded by a + sign and may NOT contain spaces
; (any non-digit character will terminate the number string that is parsed) ; (any non-digit character will terminate the number string that is parsed)
%ir {{ %ir {{
loadm.w r0,conv.str2uword.string loadm.w r65500,conv.str2uword.string
syscall 11 syscall 11
return return
}} }}
@ -207,7 +207,7 @@ sub str2word(str string) -> word {
; the number may be preceded by a + or - sign but may NOT contain spaces ; the number may be preceded by a + or - sign but may NOT contain spaces
; (any non-digit character will terminate the number string that is parsed) ; (any non-digit character will terminate the number string that is parsed)
%ir {{ %ir {{
loadm.w r0,conv.str2word.string loadm.w r65500,conv.str2word.string
syscall 12 syscall 12
return return
}} }}

View File

@ -10,7 +10,7 @@ floats {
sub print_f(float value) { sub print_f(float value) {
; ---- prints the floating point value (without a newline). ; ---- prints the floating point value (without a newline).
%ir {{ %ir {{
loadm.f fr0,floats.print_f.value loadm.f fr65500,floats.print_f.value
syscall 25 syscall 25
return return
}} }}
@ -133,9 +133,9 @@ sub rndf() -> float {
sub rndseedf(ubyte s1, ubyte s2, ubyte s3) { sub rndseedf(ubyte s1, ubyte s2, ubyte s3) {
%ir {{ %ir {{
loadm.b r0,floats.rndseedf.s1 loadm.b r65500,floats.rndseedf.s1
loadm.b r1,floats.rndseedf.s2 loadm.b r65501,floats.rndseedf.s2
loadm.b r2,floats.rndseedf.s3 loadm.b r65502,floats.rndseedf.s3
syscall 32 syscall 32
}} }}
} }

View File

@ -176,8 +176,8 @@ math {
sub rndseed(uword seed1, uword seed2) { sub rndseed(uword seed1, uword seed2) {
; -- reset the pseudo RNG's seed values. Defaults are: $a55a, $7653. ; -- reset the pseudo RNG's seed values. Defaults are: $a55a, $7653.
%ir {{ %ir {{
loadm.w r0,math.rndseed.seed1 loadm.w r65500,math.rndseed.seed1
loadm.w r1,math.rndseed.seed2 loadm.w r65501,math.rndseed.seed2
syscall 31 syscall 31
return return
}} }}

View File

@ -84,8 +84,8 @@ string {
; Note that you can also directly compare strings and string values with eachother using ; Note that you can also directly compare strings and string values with eachother using
; comparison operators ==, < etcetera (it will use strcmp for you under water automatically). ; comparison operators ==, < etcetera (it will use strcmp for you under water automatically).
%ir {{ %ir {{
loadm.w r0,string.compare.st1 loadm.w r65500,string.compare.st1
loadm.w r1,string.compare.st2 loadm.w r65501,string.compare.st2
syscall 29 syscall 29
return return
}} }}

View File

@ -15,7 +15,7 @@ sys {
sub wait(uword jiffies) { sub wait(uword jiffies) {
; --- wait approximately the given number of jiffies (1/60th seconds) ; --- wait approximately the given number of jiffies (1/60th seconds)
%ir {{ %ir {{
loadm.w r0,sys.wait.jiffies loadm.w r65500,sys.wait.jiffies
syscall 13 syscall 13
}} }}
} }
@ -62,7 +62,7 @@ sys {
sub exit(ubyte returnvalue) { sub exit(ubyte returnvalue) {
; -- immediately exit the program with a return code in the A register ; -- immediately exit the program with a return code in the A register
%ir {{ %ir {{
loadm.b r0,sys.exit.returnvalue loadm.b r65500,sys.exit.returnvalue
syscall 1 syscall 1
}} }}
} }
@ -82,31 +82,31 @@ sys {
sub gfx_enable(ubyte mode) { sub gfx_enable(ubyte mode) {
%ir {{ %ir {{
loadm.b r0,sys.gfx_enable.mode loadm.b r65500,sys.gfx_enable.mode
syscall 8 syscall 8
}} }}
} }
sub gfx_clear(ubyte color) { sub gfx_clear(ubyte color) {
%ir {{ %ir {{
loadm.b r0,sys.gfx_clear.color loadm.b r65500,sys.gfx_clear.color
syscall 9 syscall 9
}} }}
} }
sub gfx_plot(uword xx, uword yy, ubyte color) { sub gfx_plot(uword xx, uword yy, ubyte color) {
%ir {{ %ir {{
loadm.w r0,sys.gfx_plot.xx loadm.w r65500,sys.gfx_plot.xx
loadm.w r1,sys.gfx_plot.yy loadm.w r65501,sys.gfx_plot.yy
loadm.b r2,sys.gfx_plot.color loadm.b r65502,sys.gfx_plot.color
syscall 10 syscall 10
}} }}
} }
sub gfx_getpixel(uword xx, uword yy) -> ubyte { sub gfx_getpixel(uword xx, uword yy) -> ubyte {
%ir {{ %ir {{
loadm.w r0,sys.gfx_getpixel.xx loadm.w r65500,sys.gfx_getpixel.xx
loadm.w r1,sys.gfx_getpixel.yy loadm.w r65501,sys.gfx_getpixel.yy
syscall 30 syscall 30
return return
}} }}

View File

@ -7,7 +7,7 @@ txt {
sub clear_screen() { sub clear_screen() {
str @shared sequence = "\x1b[2J\x1B[H" str @shared sequence = "\x1b[2J\x1B[H"
%ir {{ %ir {{
load.w r0,txt.clear_screen.sequence load.w r65500,txt.clear_screen.sequence
syscall 3 syscall 3
}} }}
} }
@ -30,14 +30,14 @@ sub uppercase() {
sub chrout(ubyte char) { sub chrout(ubyte char) {
%ir {{ %ir {{
loadm.b r0,txt.chrout.char loadm.b r65500,txt.chrout.char
syscall 2 syscall 2
}} }}
} }
sub print (str text) { sub print (str text) {
%ir {{ %ir {{
loadm.w r0,txt.print.text loadm.w r65500,txt.print.text
syscall 3 syscall 3
}} }}
} }
@ -114,7 +114,7 @@ sub input_chars (uword buffer) -> ubyte {
; ---- Input a string (max. 80 chars) from the keyboard. Returns length of input. (string is terminated with a 0 byte as well) ; ---- Input a string (max. 80 chars) from the keyboard. Returns length of input. (string is terminated with a 0 byte as well)
; It assumes the keyboard is selected as I/O channel! ; It assumes the keyboard is selected as I/O channel!
%ir {{ %ir {{
loadm.w r0,txt.input_chars.buffer loadm.w r65500,txt.input_chars.buffer
syscall 6 syscall 6
return return
}} }}

View File

@ -3,6 +3,9 @@ TODO
For next release For next release
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
- add a pget() to gfx2 to get the pixel color value
- ir: write addresses as hex into p8ir file
... ...
@ -17,14 +20,13 @@ Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
Compiler: Compiler:
- ir/vm: SYSCALL opcode should take args in r65500, r65501 etc instead of r0, r1. Then also remove excess PUSH/POP of regs to save them. - ir: register allocation per data type a specific allocation, so we are certain when a reg is used it's just for one specific datatype
- create BSS section in output program and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE! So requires self-modifying code - create BSS section in output program and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE! So requires self-modifying code
- ir: mechanism to determine for chunks which registers are getting input values from "outside" - ir: mechanism to determine for chunks which registers are getting input values from "outside"
- ir: mechanism to determine for chunks which registers are passing values out? (i.e. are used again in another chunk) - ir: mechanism to determine for chunks which registers are passing values out? (i.e. are used again in another chunk)
- ir: peephole opt: renumber registers in chunks to start with 1 again every time (but keep entry values in mind!) - ir: peephole opt: renumber registers in chunks to start with 1 again every time (but keep entry values in mind!)
- ir peephole opt: reuse registers in chunks (but keep result registers in mind that pass values out!) - ir peephole opt: reuse registers in chunks (but keep result registers in mind that pass values out!)
- ir: add more optimizations in IRPeepholeOptimizer - ir: add more optimizations in IRPeepholeOptimizer
- ir: write addresses as hex into p8ir file
- see if we can let for loops skip the loop if end<start, like other programming languages. Without adding a lot of code size/duplicating the loop condition. - see if we can let for loops skip the loop if end<start, like other programming languages. Without adding a lot of code size/duplicating the loop condition.
this is documented behavior to now loop around but it's too easy to forget about! this is documented behavior to now loop around but it's too easy to forget about!
Lot of work because of so many special cases in ForLoopsAsmgen..... Lot of work because of so many special cases in ForLoopsAsmgen.....
@ -55,7 +57,6 @@ Libraries:
- optimize several inner loops in gfx2 even further? - optimize several inner loops in gfx2 even further?
- add modes 3 and perhaps even 2 to gfx2 (lores 16 color and 4 color)? - add modes 3 and perhaps even 2 to gfx2 (lores 16 color and 4 color)?
- add a flood fill (span fill/scanline fill) routine to gfx2? - add a flood fill (span fill/scanline fill) routine to gfx2?
- add a pget() to gfx2 to get the pixel color value
Expressions: Expressions:

View File

@ -1,4 +1,5 @@
%import textio %import textio
%import floats
%import string %import string
%zeropage basicsafe %zeropage basicsafe
@ -6,13 +7,26 @@ main {
str name1 = "abc" str name1 = "abc"
str name2 = "irmen" str name2 = "irmen"
ubyte[] arr1 = [11,22,33] ubyte[] arr1 = [11,22,0,33]
uword[] arr2 = [1111,2222,3333] uword[] arr2 = [1111,2222,0,3333]
sub start() { sub start() {
sys.exit(42)
floats.rndseedf(11,22,33)
floats.print_f(floats.rndf())
txt.nl()
floats.print_f(floats.rndf())
txt.nl()
floats.print_f(floats.rndf())
txt.nl()
ubyte @shared xx ubyte @shared xx
ubyte value = 33 ubyte value = 33
uword value2 = 3333 uword value2 = 3333
txt.print_ub(all(arr1))
txt.print_ub(any(arr1))
reverse(arr1)
sort(arr1)
txt.print_ub(value in name1) txt.print_ub(value in name1)
txt.print_ub('c' in name1) txt.print_ub('c' in name1)
txt.print_ub(value in arr1) txt.print_ub(value in arr1)

View File

@ -23,3 +23,5 @@ enum class IMSyscall(val number: Int) {
BYTEARRAY_CONTAINS(10015), BYTEARRAY_CONTAINS(10015),
WORDARRAY_CONTAINS(10016) WORDARRAY_CONTAINS(10016)
} }
const val SyscallRegisterBase = 65500

View File

@ -1,6 +1,7 @@
package prog8.vm package prog8.vm
import prog8.code.core.AssemblyError import prog8.code.core.AssemblyError
import prog8.intermediate.SyscallRegisterBase
import kotlin.math.min import kotlin.math.min
/* /*
@ -85,19 +86,20 @@ enum class Syscall {
object SysCalls { object SysCalls {
fun call(call: Syscall, vm: VirtualMachine) { fun call(call: Syscall, vm: VirtualMachine) {
when(call) { when(call) {
Syscall.RESET -> { Syscall.RESET -> {
vm.reset() vm.reset()
} }
Syscall.EXIT ->{ Syscall.EXIT ->{
vm.exit() vm.exit(vm.registers.getUB(SyscallRegisterBase).toInt())
} }
Syscall.PRINT_C -> { Syscall.PRINT_C -> {
val char = vm.registers.getUB(0).toInt() val char = vm.registers.getUB(SyscallRegisterBase).toInt()
print(Char(char)) print(Char(char))
} }
Syscall.PRINT_S -> { Syscall.PRINT_S -> {
var addr = vm.registers.getUW(0).toInt() var addr = vm.registers.getUW(SyscallRegisterBase).toInt()
while(true) { while(true) {
val char = vm.memory.getUB(addr).toInt() val char = vm.memory.getUB(addr).toInt()
if(char==0) if(char==0)
@ -107,21 +109,21 @@ object SysCalls {
} }
} }
Syscall.PRINT_U8 -> { Syscall.PRINT_U8 -> {
print(vm.registers.getUB(0)) print(vm.registers.getUB(SyscallRegisterBase))
} }
Syscall.PRINT_U16 -> { Syscall.PRINT_U16 -> {
print(vm.registers.getUW(0)) print(vm.registers.getUW(SyscallRegisterBase))
} }
Syscall.INPUT -> { Syscall.INPUT -> {
var input = readln() var input = readln()
val maxlen = vm.registers.getUB(1).toInt() val maxlen = vm.registers.getUB(SyscallRegisterBase+1).toInt()
if(maxlen>0) if(maxlen>0)
input = input.substring(0, min(input.length, maxlen)) input = input.substring(0, min(input.length, maxlen))
vm.memory.setString(vm.registers.getUW(0).toInt(), input, true) vm.memory.setString(vm.registers.getUW(SyscallRegisterBase).toInt(), input, true)
vm.registers.setUW(0, input.length.toUShort()) vm.registers.setUW(0, input.length.toUShort())
} }
Syscall.SLEEP -> { Syscall.SLEEP -> {
val duration = vm.registers.getUW(0).toLong() val duration = vm.registers.getUW(SyscallRegisterBase).toLong()
Thread.sleep(duration) Thread.sleep(duration)
} }
Syscall.GFX_ENABLE -> vm.gfx_enable() Syscall.GFX_ENABLE -> vm.gfx_enable()
@ -129,13 +131,13 @@ object SysCalls {
Syscall.GFX_PLOT -> vm.gfx_plot() Syscall.GFX_PLOT -> vm.gfx_plot()
Syscall.GFX_GETPIXEL ->vm.gfx_getpixel() Syscall.GFX_GETPIXEL ->vm.gfx_getpixel()
Syscall.WAIT -> { Syscall.WAIT -> {
val millis = vm.registers.getUW(0).toLong() * 1000/60 val millis = vm.registers.getUW(SyscallRegisterBase).toLong() * 1000/60
Thread.sleep(millis) Thread.sleep(millis)
} }
Syscall.WAITVSYNC -> vm.waitvsync() Syscall.WAITVSYNC -> vm.waitvsync()
Syscall.SORT_UBYTE -> { Syscall.SORT_UBYTE -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val array = IntProgression.fromClosedRange(address, address+length-1, 1).map { val array = IntProgression.fromClosedRange(address, address+length-1, 1).map {
vm.memory.getUB(it) vm.memory.getUB(it)
}.sorted() }.sorted()
@ -144,8 +146,8 @@ object SysCalls {
} }
} }
Syscall.SORT_BYTE -> { Syscall.SORT_BYTE -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val array = IntProgression.fromClosedRange(address, address+length-1, 1).map { val array = IntProgression.fromClosedRange(address, address+length-1, 1).map {
vm.memory.getSB(it) vm.memory.getSB(it)
}.sorted() }.sorted()
@ -154,8 +156,8 @@ object SysCalls {
} }
} }
Syscall.SORT_UWORD -> { Syscall.SORT_UWORD -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map { val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map {
vm.memory.getUW(it) vm.memory.getUW(it)
}.sorted() }.sorted()
@ -164,8 +166,8 @@ object SysCalls {
} }
} }
Syscall.SORT_WORD -> { Syscall.SORT_WORD -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map { val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map {
vm.memory.getSW(it) vm.memory.getSW(it)
}.sorted() }.sorted()
@ -174,8 +176,8 @@ object SysCalls {
} }
} }
Syscall.REVERSE_BYTES -> { Syscall.REVERSE_BYTES -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val array = IntProgression.fromClosedRange(address, address+length-1, 1).map { val array = IntProgression.fromClosedRange(address, address+length-1, 1).map {
vm.memory.getUB(it) vm.memory.getUB(it)
}.reversed() }.reversed()
@ -184,8 +186,8 @@ object SysCalls {
} }
} }
Syscall.REVERSE_WORDS -> { Syscall.REVERSE_WORDS -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map { val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map {
vm.memory.getUW(it) vm.memory.getUW(it)
}.reversed() }.reversed()
@ -194,8 +196,8 @@ object SysCalls {
} }
} }
Syscall.REVERSE_FLOATS -> { Syscall.REVERSE_FLOATS -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val array = IntProgression.fromClosedRange(address, address+length*4-2, 4).map { val array = IntProgression.fromClosedRange(address, address+length*4-2, 4).map {
vm.memory.getFloat(it) vm.memory.getFloat(it)
}.reversed() }.reversed()
@ -204,8 +206,8 @@ object SysCalls {
} }
} }
Syscall.ANY_BYTE -> { Syscall.ANY_BYTE -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2)
if(addresses.any { vm.memory.getUB(it).toInt()!=0 }) if(addresses.any { vm.memory.getUB(it).toInt()!=0 })
vm.registers.setUB(0, 1u) vm.registers.setUB(0, 1u)
@ -213,8 +215,8 @@ object SysCalls {
vm.registers.setUB(0, 0u) vm.registers.setUB(0, 0u)
} }
Syscall.ANY_WORD -> { Syscall.ANY_WORD -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2)
if(addresses.any { vm.memory.getUW(it).toInt()!=0 }) if(addresses.any { vm.memory.getUW(it).toInt()!=0 })
vm.registers.setUB(0, 1u) vm.registers.setUB(0, 1u)
@ -222,8 +224,8 @@ object SysCalls {
vm.registers.setUB(0, 0u) vm.registers.setUB(0, 0u)
} }
Syscall.ANY_FLOAT -> { Syscall.ANY_FLOAT -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val addresses = IntProgression.fromClosedRange(address, address+length*4-2, 4) val addresses = IntProgression.fromClosedRange(address, address+length*4-2, 4)
if(addresses.any { vm.memory.getFloat(it).toInt()!=0 }) if(addresses.any { vm.memory.getFloat(it).toInt()!=0 })
vm.registers.setUB(0, 1u) vm.registers.setUB(0, 1u)
@ -231,8 +233,8 @@ object SysCalls {
vm.registers.setUB(0, 0u) vm.registers.setUB(0, 0u)
} }
Syscall.ALL_BYTE -> { Syscall.ALL_BYTE -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2)
if(addresses.all { vm.memory.getUB(it).toInt()!=0 }) if(addresses.all { vm.memory.getUB(it).toInt()!=0 })
vm.registers.setUB(0, 1u) vm.registers.setUB(0, 1u)
@ -240,8 +242,8 @@ object SysCalls {
vm.registers.setUB(0, 0u) vm.registers.setUB(0, 0u)
} }
Syscall.ALL_WORD -> { Syscall.ALL_WORD -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2) val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2)
if(addresses.all { vm.memory.getUW(it).toInt()!=0 }) if(addresses.all { vm.memory.getUW(it).toInt()!=0 })
vm.registers.setUB(0, 1u) vm.registers.setUB(0, 1u)
@ -249,8 +251,8 @@ object SysCalls {
vm.registers.setUB(0, 0u) vm.registers.setUB(0, 0u)
} }
Syscall.ALL_FLOAT -> { Syscall.ALL_FLOAT -> {
val address = vm.registers.getUW(0).toInt() val address = vm.registers.getUW(SyscallRegisterBase).toInt()
val length = vm.registers.getUB(1).toInt() val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
val addresses = IntProgression.fromClosedRange(address, address+length*4-2, 4) val addresses = IntProgression.fromClosedRange(address, address+length*4-2, 4)
if(addresses.all { vm.memory.getFloat(it).toInt()!=0 }) if(addresses.all { vm.memory.getFloat(it).toInt()!=0 })
vm.registers.setUB(0, 1u) vm.registers.setUB(0, 1u)
@ -258,11 +260,11 @@ object SysCalls {
vm.registers.setUB(0, 0u) vm.registers.setUB(0, 0u)
} }
Syscall.PRINT_F -> { Syscall.PRINT_F -> {
val value = vm.registers.getFloat(0) val value = vm.registers.getFloat(SyscallRegisterBase)
print(value) print(value)
} }
Syscall.STR_TO_UWORD -> { Syscall.STR_TO_UWORD -> {
val stringAddr = vm.registers.getUW(0) val stringAddr = vm.registers.getUW(SyscallRegisterBase)
val string = vm.memory.getString(stringAddr.toInt()).takeWhile { it.isDigit() } val string = vm.memory.getString(stringAddr.toInt()).takeWhile { it.isDigit() }
val value = try { val value = try {
string.toUShort() string.toUShort()
@ -272,7 +274,7 @@ object SysCalls {
vm.registers.setUW(0, value) vm.registers.setUW(0, value)
} }
Syscall.STR_TO_WORD -> { Syscall.STR_TO_WORD -> {
val stringAddr = vm.registers.getUW(0) val stringAddr = vm.registers.getUW(SyscallRegisterBase)
val string = vm.memory.getString(stringAddr.toInt()).takeWhile { it.isDigit() } val string = vm.memory.getString(stringAddr.toInt()).takeWhile { it.isDigit() }
val value = try { val value = try {
string.toShort() string.toShort()
@ -282,8 +284,8 @@ object SysCalls {
vm.registers.setSW(0, value) vm.registers.setSW(0, value)
} }
Syscall.COMPARE_STRINGS -> { Syscall.COMPARE_STRINGS -> {
val firstAddr = vm.registers.getUW(0) val firstAddr = vm.registers.getUW(SyscallRegisterBase)
val secondAddr = vm.registers.getUW(1) val secondAddr = vm.registers.getUW(SyscallRegisterBase+1)
val first = vm.memory.getString(firstAddr.toInt()) val first = vm.memory.getString(firstAddr.toInt())
val second = vm.memory.getString(secondAddr.toInt()) val second = vm.memory.getString(secondAddr.toInt())
val comparison = first.compareTo(second) val comparison = first.compareTo(second)
@ -295,14 +297,14 @@ object SysCalls {
vm.registers.setSB(0, 1) vm.registers.setSB(0, 1)
} }
Syscall.RNDFSEED -> { Syscall.RNDFSEED -> {
val seed1 = vm.registers.getUB(0) val seed1 = vm.registers.getUB(SyscallRegisterBase)
val seed2 = vm.registers.getUB(1) val seed2 = vm.registers.getUB(SyscallRegisterBase+1)
val seed3 = vm.registers.getUB(2) val seed3 = vm.registers.getUB(SyscallRegisterBase+2)
vm.randomSeedFloat(seed1, seed2, seed3) vm.randomSeedFloat(seed1, seed2, seed3)
} }
Syscall.RNDSEED -> { Syscall.RNDSEED -> {
val seed1 = vm.registers.getUW(0) val seed1 = vm.registers.getUW(SyscallRegisterBase)
val seed2 = vm.registers.getUW(1) val seed2 = vm.registers.getUW(SyscallRegisterBase+1)
vm.randomSeed(seed1, seed2) vm.randomSeed(seed1, seed2)
} }
Syscall.RND -> { Syscall.RND -> {
@ -315,15 +317,15 @@ object SysCalls {
vm.registers.setFloat(0, vm.randomGeneratorFloats.nextFloat()) vm.registers.setFloat(0, vm.randomGeneratorFloats.nextFloat())
} }
Syscall.STRING_CONTAINS -> { Syscall.STRING_CONTAINS -> {
val char = vm.registers.getUB(0).toInt().toChar() val char = vm.registers.getUB(SyscallRegisterBase).toInt().toChar()
val stringAddr = vm.registers.getUW(1) val stringAddr = vm.registers.getUW(SyscallRegisterBase+1)
val string = vm.memory.getString(stringAddr.toInt()) val string = vm.memory.getString(stringAddr.toInt())
vm.registers.setUB(0, if(char in string) 1u else 0u) vm.registers.setUB(0, if(char in string) 1u else 0u)
} }
Syscall.BYTEARRAY_CONTAINS -> { Syscall.BYTEARRAY_CONTAINS -> {
val value = vm.registers.getUB(0) val value = vm.registers.getUB(SyscallRegisterBase)
var array = vm.registers.getUW(1).toInt() var array = vm.registers.getUW(SyscallRegisterBase+1).toInt()
var length = vm.registers.getUB(2) var length = vm.registers.getUB(SyscallRegisterBase+2)
while(length>0u) { while(length>0u) {
if(vm.memory.getUB(array)==value) { if(vm.memory.getUB(array)==value) {
vm.registers.setUB(0, 1u) vm.registers.setUB(0, 1u)
@ -336,9 +338,9 @@ object SysCalls {
} }
Syscall.WORDARRAY_CONTAINS -> { Syscall.WORDARRAY_CONTAINS -> {
// r0.w = value, r1.w = array, r2.b = array length // r0.w = value, r1.w = array, r2.b = array length
val value = vm.registers.getUW(0) val value = vm.registers.getUW(SyscallRegisterBase)
var array = vm.registers.getUW(1).toInt() var array = vm.registers.getUW(SyscallRegisterBase+1).toInt()
var length = vm.registers.getUB(2) var length = vm.registers.getUB(SyscallRegisterBase+2)
while(length>0u) { while(length>0u) {
if(vm.memory.getUW(array)==value) { if(vm.memory.getUW(array)==value) {
vm.registers.setUB(0, 1u) vm.registers.setUB(0, 1u)

View File

@ -92,8 +92,8 @@ class VirtualMachine(irProgram: IRProgram) {
statusZero = false statusZero = false
} }
fun exit() { fun exit(statuscode: Int) {
throw ProgramExitException(registers.getUW(0).toInt()) throw ProgramExitException(statuscode)
} }
fun step(count: Int=1) { fun step(count: Int=1) {
@ -118,7 +118,7 @@ class VirtualMachine(irProgram: IRProgram) {
} }
null -> { null -> {
exit() // end of program reached exit(0) // end of program reached
} }
else -> { else -> {
@ -574,7 +574,7 @@ class VirtualMachine(irProgram: IRProgram) {
private fun InsRETURN() { private fun InsRETURN() {
if(callStack.isEmpty()) if(callStack.isEmpty())
exit() exit(0)
else { else {
val (chunk, idx) = callStack.pop() val (chunk, idx) = callStack.pop()
pcChunk = chunk pcChunk = chunk
@ -2108,7 +2108,7 @@ class VirtualMachine(irProgram: IRProgram) {
private var window: GraphicsWindow? = null private var window: GraphicsWindow? = null
fun gfx_enable() { fun gfx_enable() {
window = when(registers.getUB(0).toInt()) { window = when(registers.getUB(SyscallRegisterBase).toInt()) {
0 -> GraphicsWindow(320, 240, 3) 0 -> GraphicsWindow(320, 240, 3)
1 -> GraphicsWindow(640, 480, 2) 1 -> GraphicsWindow(640, 480, 2)
else -> throw IllegalArgumentException("invalid screen mode") else -> throw IllegalArgumentException("invalid screen mode")
@ -2117,18 +2117,21 @@ class VirtualMachine(irProgram: IRProgram) {
} }
fun gfx_clear() { fun gfx_clear() {
window?.clear(registers.getUB(0).toInt()) window?.clear(registers.getUB(SyscallRegisterBase).toInt())
} }
fun gfx_plot() { fun gfx_plot() {
window?.plot(registers.getUW(0).toInt(), registers.getUW(1).toInt(), registers.getUB(2).toInt()) window?.plot(registers.getUW(SyscallRegisterBase).toInt(),
registers.getUW(SyscallRegisterBase+1).toInt(),
registers.getUB(SyscallRegisterBase+2).toInt())
} }
fun gfx_getpixel() { fun gfx_getpixel() {
if(window==null) if(window==null)
registers.setUB(0, 0u) registers.setUB(0, 0u)
else { else {
val color = Color(window!!.getpixel(registers.getUW(0).toInt(), registers.getUW(1).toInt())) val color = Color(window!!.getpixel(registers.getUW(SyscallRegisterBase).toInt(),
registers.getUW(SyscallRegisterBase+1).toInt()))
registers.setUB(0, color.green.toUByte()) registers.setUB(0, color.green.toUByte())
} }
} }