mirror of
https://github.com/irmen/prog8.git
synced 2025-01-22 09:31:36 +00:00
ir/vm: syscall params in high base register to avoid push/pop
This commit is contained in:
parent
469e042216
commit
38efaae7b2
@ -71,11 +71,11 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
else -> throw IllegalArgumentException("weird type")
|
||||
}
|
||||
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 {
|
||||
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)
|
||||
if (resultRegister != 0)
|
||||
if(resultRegister!=0)
|
||||
it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1 = resultRegister, reg2 = 0)
|
||||
}
|
||||
return result
|
||||
@ -94,11 +94,11 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
else -> throw IllegalArgumentException("weird type")
|
||||
}
|
||||
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 {
|
||||
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)
|
||||
if (resultRegister != 0)
|
||||
if(resultRegister!=0)
|
||||
it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1 = resultRegister, reg2 = 0)
|
||||
}
|
||||
return result
|
||||
@ -213,9 +213,9 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
else -> throw IllegalArgumentException("weird type to reverse")
|
||||
}
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
return result
|
||||
@ -235,9 +235,9 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
else -> throw IllegalArgumentException("weird type to sort")
|
||||
}
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
return result
|
||||
|
@ -10,7 +10,7 @@ import prog8.intermediate.*
|
||||
|
||||
internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
fun translateExpression(expr: PtExpression, resultRegister: Int, resultFpRegister: Int): IRCodeChunks {
|
||||
require(codeGen.registers.peekNext() > resultRegister)
|
||||
require(codeGen.registers.peekNext() > resultRegister || resultRegister >= SyscallRegisterBase)
|
||||
|
||||
return when (expr) {
|
||||
is PtMachineRegister -> {
|
||||
@ -101,49 +101,33 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val iterable = codeGen.symbolTable.flat.getValue(check.iterable.targetName) as StStaticVariable
|
||||
when(iterable.dt) {
|
||||
DataType.STR -> {
|
||||
val push = IRCodeChunk(null, null)
|
||||
push += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=1)
|
||||
result += push
|
||||
result += translateExpression(check.element, 0, -1)
|
||||
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)
|
||||
syscall += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=resultRegister, reg2=0)
|
||||
result += syscall
|
||||
result += translateExpression(check.element, SyscallRegisterBase, -1)
|
||||
result += translateExpression(check.iterable, SyscallRegisterBase+1, -1)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.STRING_CONTAINS.number)
|
||||
if(resultRegister!=0)
|
||||
it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=resultRegister, reg2=0)
|
||||
}
|
||||
}
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B -> {
|
||||
val push = IRCodeChunk(null, null)
|
||||
push += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=1)
|
||||
push += IRInstruction(Opcode.PUSH, IRDataType.BYTE, reg1=2)
|
||||
result += push
|
||||
result += translateExpression(check.element, 0, -1)
|
||||
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)
|
||||
syscall += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=resultRegister, reg2=0)
|
||||
result += syscall
|
||||
result += translateExpression(check.element, SyscallRegisterBase, -1)
|
||||
result += translateExpression(check.iterable, SyscallRegisterBase+1, -1)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=SyscallRegisterBase+2, value = iterable.length!!)
|
||||
it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.BYTEARRAY_CONTAINS.number)
|
||||
if(resultRegister!=0)
|
||||
it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=resultRegister, reg2=0)
|
||||
}
|
||||
}
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||
val push = IRCodeChunk(null, null)
|
||||
push += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=1)
|
||||
push += IRInstruction(Opcode.PUSH, IRDataType.BYTE, reg1=2)
|
||||
result += push
|
||||
result += translateExpression(check.element, 0, -1)
|
||||
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)
|
||||
syscall += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=resultRegister, reg2=0)
|
||||
result += syscall
|
||||
result += translateExpression(check.element, SyscallRegisterBase, -1)
|
||||
result += translateExpression(check.iterable, SyscallRegisterBase+1, -1)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=SyscallRegisterBase+2, value = iterable.length!!)
|
||||
it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.WORDARRAY_CONTAINS.number)
|
||||
if(resultRegister!=0)
|
||||
it += IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=resultRegister, reg2=0)
|
||||
}
|
||||
}
|
||||
DataType.ARRAY_F -> throw AssemblyError("containment check in float-array not supported")
|
||||
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)
|
||||
} else {
|
||||
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
|
||||
require(codeGen.registers.peekNext() > 1)
|
||||
val push = IRCodeChunk(null, null)
|
||||
push += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=1)
|
||||
result += push
|
||||
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)
|
||||
syscall += IRInstruction(Opcode.LOADR, vmDt, reg1=resultRegister, reg2=0)
|
||||
syscall += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=1, value=0)
|
||||
syscall += if(greaterEquals)
|
||||
IRInstruction(Opcode.SGES, IRDataType.BYTE, reg1=resultRegister, reg2=1)
|
||||
else
|
||||
IRInstruction(Opcode.SGTS, IRDataType.BYTE, reg1=resultRegister, reg2=1)
|
||||
syscall += IRInstruction(Opcode.POP, IRDataType.WORD, reg1=1)
|
||||
result += syscall
|
||||
result += translateExpression(binExpr.left, SyscallRegisterBase, -1)
|
||||
result += translateExpression(binExpr.right, SyscallRegisterBase+1, -1)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number)
|
||||
if(resultRegister!=0)
|
||||
it += IRInstruction(Opcode.LOADR, vmDt, reg1 = resultRegister, reg2 = 0)
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = 1, value = 0)
|
||||
it += if (greaterEquals)
|
||||
IRInstruction(Opcode.SGES, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1)
|
||||
else
|
||||
IRInstruction(Opcode.SGTS, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1)
|
||||
}
|
||||
} else {
|
||||
val rightResultReg = codeGen.registers.nextFree()
|
||||
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)
|
||||
} else {
|
||||
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
|
||||
require(codeGen.registers.peekNext() > 1)
|
||||
val push = IRCodeChunk(null, null)
|
||||
push += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=1)
|
||||
result += push
|
||||
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)
|
||||
syscall += IRInstruction(Opcode.LOADR, vmDt, reg1=resultRegister, reg2=0)
|
||||
syscall += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=1, value=0)
|
||||
syscall += if(lessEquals)
|
||||
IRInstruction(Opcode.SLES, IRDataType.BYTE, reg1=resultRegister, reg2=1)
|
||||
else
|
||||
IRInstruction(Opcode.SLTS, IRDataType.BYTE, reg1=resultRegister, reg2=1)
|
||||
syscall += IRInstruction(Opcode.POP, IRDataType.WORD, reg1=1)
|
||||
result += syscall
|
||||
result += translateExpression(binExpr.left, SyscallRegisterBase, -1)
|
||||
result += translateExpression(binExpr.right, SyscallRegisterBase+1, -1)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number)
|
||||
if(resultRegister!=0)
|
||||
it += IRInstruction(Opcode.LOADR, vmDt, reg1 = resultRegister, reg2 = 0)
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = 1, value = 0)
|
||||
it += if (lessEquals)
|
||||
IRInstruction(Opcode.SLES, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1)
|
||||
else
|
||||
IRInstruction(Opcode.SLTS, IRDataType.BYTE, reg1 = resultRegister, reg2 = 1)
|
||||
}
|
||||
} else {
|
||||
val rightResultReg = codeGen.registers.nextFree()
|
||||
result += translateExpression(binExpr.left, resultRegister, -1)
|
||||
@ -440,21 +414,16 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
} else {
|
||||
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
|
||||
require(codeGen.registers.peekNext() > 1)
|
||||
val push = IRCodeChunk(null, null)
|
||||
push += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1=1)
|
||||
result += push
|
||||
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)
|
||||
syscall += IRInstruction(Opcode.LOADR, vmDt, reg1=resultRegister, reg2=0)
|
||||
if(!notEquals)
|
||||
syscall += IRInstruction(Opcode.INV, vmDt, reg1=resultRegister)
|
||||
syscall += IRInstruction(Opcode.AND, vmDt, reg1=resultRegister, value=1)
|
||||
result += syscall
|
||||
result += translateExpression(binExpr.left, SyscallRegisterBase, -1)
|
||||
result += translateExpression(binExpr.right, SyscallRegisterBase+1, -1)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.SYSCALL, value = IMSyscall.COMPARE_STRINGS.number)
|
||||
if(resultRegister!=0)
|
||||
it += IRInstruction(Opcode.LOADR, vmDt, reg1 = resultRegister, reg2 = 0)
|
||||
if (!notEquals)
|
||||
it += IRInstruction(Opcode.INV, vmDt, reg1 = resultRegister)
|
||||
it += IRInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value = 1)
|
||||
}
|
||||
} else {
|
||||
val rightResultReg = codeGen.registers.nextFree()
|
||||
result += translateExpression(binExpr.left, resultRegister, -1)
|
||||
|
@ -1,10 +1,12 @@
|
||||
package prog8.codegen.intermediate
|
||||
|
||||
import prog8.code.core.AssemblyError
|
||||
import prog8.intermediate.SyscallRegisterBase
|
||||
|
||||
internal class RegisterPool {
|
||||
private var firstFree: Int=3 // integer registers 0,1,2 are reserved
|
||||
private var firstFreeFloat: Int=0
|
||||
// reserve 0,1,2 for return values of subroutine calls and syscalls
|
||||
private var firstFree: Int=3
|
||||
private var firstFreeFloat: Int=3
|
||||
|
||||
fun peekNext() = firstFree
|
||||
fun peekNextFloat() = firstFreeFloat
|
||||
@ -12,7 +14,7 @@ internal class RegisterPool {
|
||||
fun nextFree(): Int {
|
||||
val result = firstFree
|
||||
firstFree++
|
||||
if(firstFree>65535)
|
||||
if(firstFree >= SyscallRegisterBase)
|
||||
throw AssemblyError("out of virtual registers (int)")
|
||||
return result
|
||||
}
|
||||
@ -20,7 +22,7 @@ internal class RegisterPool {
|
||||
fun nextFreeFloat(): Int {
|
||||
val result = firstFreeFloat
|
||||
firstFreeFloat++
|
||||
if(firstFreeFloat>65535)
|
||||
if(firstFreeFloat >= SyscallRegisterBase)
|
||||
throw AssemblyError("out of virtual registers (fp)")
|
||||
return result
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ sub str2uword(str string) -> uword {
|
||||
; 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)
|
||||
%ir {{
|
||||
loadm.w r0,conv.str2uword.string
|
||||
loadm.w r65500,conv.str2uword.string
|
||||
syscall 11
|
||||
return
|
||||
}}
|
||||
@ -207,7 +207,7 @@ sub str2word(str string) -> word {
|
||||
; 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)
|
||||
%ir {{
|
||||
loadm.w r0,conv.str2word.string
|
||||
loadm.w r65500,conv.str2word.string
|
||||
syscall 12
|
||||
return
|
||||
}}
|
||||
|
@ -10,7 +10,7 @@ floats {
|
||||
sub print_f(float value) {
|
||||
; ---- prints the floating point value (without a newline).
|
||||
%ir {{
|
||||
loadm.f fr0,floats.print_f.value
|
||||
loadm.f fr65500,floats.print_f.value
|
||||
syscall 25
|
||||
return
|
||||
}}
|
||||
@ -133,9 +133,9 @@ sub rndf() -> float {
|
||||
|
||||
sub rndseedf(ubyte s1, ubyte s2, ubyte s3) {
|
||||
%ir {{
|
||||
loadm.b r0,floats.rndseedf.s1
|
||||
loadm.b r1,floats.rndseedf.s2
|
||||
loadm.b r2,floats.rndseedf.s3
|
||||
loadm.b r65500,floats.rndseedf.s1
|
||||
loadm.b r65501,floats.rndseedf.s2
|
||||
loadm.b r65502,floats.rndseedf.s3
|
||||
syscall 32
|
||||
}}
|
||||
}
|
||||
|
@ -176,8 +176,8 @@ math {
|
||||
sub rndseed(uword seed1, uword seed2) {
|
||||
; -- reset the pseudo RNG's seed values. Defaults are: $a55a, $7653.
|
||||
%ir {{
|
||||
loadm.w r0,math.rndseed.seed1
|
||||
loadm.w r1,math.rndseed.seed2
|
||||
loadm.w r65500,math.rndseed.seed1
|
||||
loadm.w r65501,math.rndseed.seed2
|
||||
syscall 31
|
||||
return
|
||||
}}
|
||||
|
@ -84,8 +84,8 @@ string {
|
||||
; 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).
|
||||
%ir {{
|
||||
loadm.w r0,string.compare.st1
|
||||
loadm.w r1,string.compare.st2
|
||||
loadm.w r65500,string.compare.st1
|
||||
loadm.w r65501,string.compare.st2
|
||||
syscall 29
|
||||
return
|
||||
}}
|
||||
|
@ -15,7 +15,7 @@ sys {
|
||||
sub wait(uword jiffies) {
|
||||
; --- wait approximately the given number of jiffies (1/60th seconds)
|
||||
%ir {{
|
||||
loadm.w r0,sys.wait.jiffies
|
||||
loadm.w r65500,sys.wait.jiffies
|
||||
syscall 13
|
||||
}}
|
||||
}
|
||||
@ -62,7 +62,7 @@ sys {
|
||||
sub exit(ubyte returnvalue) {
|
||||
; -- immediately exit the program with a return code in the A register
|
||||
%ir {{
|
||||
loadm.b r0,sys.exit.returnvalue
|
||||
loadm.b r65500,sys.exit.returnvalue
|
||||
syscall 1
|
||||
}}
|
||||
}
|
||||
@ -82,31 +82,31 @@ sys {
|
||||
|
||||
sub gfx_enable(ubyte mode) {
|
||||
%ir {{
|
||||
loadm.b r0,sys.gfx_enable.mode
|
||||
loadm.b r65500,sys.gfx_enable.mode
|
||||
syscall 8
|
||||
}}
|
||||
}
|
||||
|
||||
sub gfx_clear(ubyte color) {
|
||||
%ir {{
|
||||
loadm.b r0,sys.gfx_clear.color
|
||||
loadm.b r65500,sys.gfx_clear.color
|
||||
syscall 9
|
||||
}}
|
||||
}
|
||||
|
||||
sub gfx_plot(uword xx, uword yy, ubyte color) {
|
||||
%ir {{
|
||||
loadm.w r0,sys.gfx_plot.xx
|
||||
loadm.w r1,sys.gfx_plot.yy
|
||||
loadm.b r2,sys.gfx_plot.color
|
||||
loadm.w r65500,sys.gfx_plot.xx
|
||||
loadm.w r65501,sys.gfx_plot.yy
|
||||
loadm.b r65502,sys.gfx_plot.color
|
||||
syscall 10
|
||||
}}
|
||||
}
|
||||
|
||||
sub gfx_getpixel(uword xx, uword yy) -> ubyte {
|
||||
%ir {{
|
||||
loadm.w r0,sys.gfx_getpixel.xx
|
||||
loadm.w r1,sys.gfx_getpixel.yy
|
||||
loadm.w r65500,sys.gfx_getpixel.xx
|
||||
loadm.w r65501,sys.gfx_getpixel.yy
|
||||
syscall 30
|
||||
return
|
||||
}}
|
||||
|
@ -7,7 +7,7 @@ txt {
|
||||
sub clear_screen() {
|
||||
str @shared sequence = "\x1b[2J\x1B[H"
|
||||
%ir {{
|
||||
load.w r0,txt.clear_screen.sequence
|
||||
load.w r65500,txt.clear_screen.sequence
|
||||
syscall 3
|
||||
}}
|
||||
}
|
||||
@ -30,14 +30,14 @@ sub uppercase() {
|
||||
|
||||
sub chrout(ubyte char) {
|
||||
%ir {{
|
||||
loadm.b r0,txt.chrout.char
|
||||
loadm.b r65500,txt.chrout.char
|
||||
syscall 2
|
||||
}}
|
||||
}
|
||||
|
||||
sub print (str text) {
|
||||
%ir {{
|
||||
loadm.w r0,txt.print.text
|
||||
loadm.w r65500,txt.print.text
|
||||
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)
|
||||
; It assumes the keyboard is selected as I/O channel!
|
||||
%ir {{
|
||||
loadm.w r0,txt.input_chars.buffer
|
||||
loadm.w r65500,txt.input_chars.buffer
|
||||
syscall 6
|
||||
return
|
||||
}}
|
||||
|
@ -3,6 +3,9 @@ TODO
|
||||
|
||||
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:
|
||||
|
||||
- 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
|
||||
- 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: 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: 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.
|
||||
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.....
|
||||
@ -55,7 +57,6 @@ Libraries:
|
||||
- optimize several inner loops in gfx2 even further?
|
||||
- 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 pget() to gfx2 to get the pixel color value
|
||||
|
||||
|
||||
Expressions:
|
||||
|
@ -1,4 +1,5 @@
|
||||
%import textio
|
||||
%import floats
|
||||
%import string
|
||||
%zeropage basicsafe
|
||||
|
||||
@ -6,13 +7,26 @@ main {
|
||||
|
||||
str name1 = "abc"
|
||||
str name2 = "irmen"
|
||||
ubyte[] arr1 = [11,22,33]
|
||||
uword[] arr2 = [1111,2222,3333]
|
||||
ubyte[] arr1 = [11,22,0,33]
|
||||
uword[] arr2 = [1111,2222,0,3333]
|
||||
|
||||
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 value = 33
|
||||
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('c' in name1)
|
||||
txt.print_ub(value in arr1)
|
||||
|
@ -22,4 +22,6 @@ enum class IMSyscall(val number: Int) {
|
||||
STRING_CONTAINS(10014),
|
||||
BYTEARRAY_CONTAINS(10015),
|
||||
WORDARRAY_CONTAINS(10016)
|
||||
}
|
||||
}
|
||||
|
||||
const val SyscallRegisterBase = 65500
|
||||
|
@ -1,6 +1,7 @@
|
||||
package prog8.vm
|
||||
|
||||
import prog8.code.core.AssemblyError
|
||||
import prog8.intermediate.SyscallRegisterBase
|
||||
import kotlin.math.min
|
||||
|
||||
/*
|
||||
@ -85,19 +86,20 @@ enum class Syscall {
|
||||
|
||||
object SysCalls {
|
||||
fun call(call: Syscall, vm: VirtualMachine) {
|
||||
|
||||
when(call) {
|
||||
Syscall.RESET -> {
|
||||
vm.reset()
|
||||
}
|
||||
Syscall.EXIT ->{
|
||||
vm.exit()
|
||||
vm.exit(vm.registers.getUB(SyscallRegisterBase).toInt())
|
||||
}
|
||||
Syscall.PRINT_C -> {
|
||||
val char = vm.registers.getUB(0).toInt()
|
||||
val char = vm.registers.getUB(SyscallRegisterBase).toInt()
|
||||
print(Char(char))
|
||||
}
|
||||
Syscall.PRINT_S -> {
|
||||
var addr = vm.registers.getUW(0).toInt()
|
||||
var addr = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
while(true) {
|
||||
val char = vm.memory.getUB(addr).toInt()
|
||||
if(char==0)
|
||||
@ -107,21 +109,21 @@ object SysCalls {
|
||||
}
|
||||
}
|
||||
Syscall.PRINT_U8 -> {
|
||||
print(vm.registers.getUB(0))
|
||||
print(vm.registers.getUB(SyscallRegisterBase))
|
||||
}
|
||||
Syscall.PRINT_U16 -> {
|
||||
print(vm.registers.getUW(0))
|
||||
print(vm.registers.getUW(SyscallRegisterBase))
|
||||
}
|
||||
Syscall.INPUT -> {
|
||||
var input = readln()
|
||||
val maxlen = vm.registers.getUB(1).toInt()
|
||||
val maxlen = vm.registers.getUB(SyscallRegisterBase+1).toInt()
|
||||
if(maxlen>0)
|
||||
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())
|
||||
}
|
||||
Syscall.SLEEP -> {
|
||||
val duration = vm.registers.getUW(0).toLong()
|
||||
val duration = vm.registers.getUW(SyscallRegisterBase).toLong()
|
||||
Thread.sleep(duration)
|
||||
}
|
||||
Syscall.GFX_ENABLE -> vm.gfx_enable()
|
||||
@ -129,13 +131,13 @@ object SysCalls {
|
||||
Syscall.GFX_PLOT -> vm.gfx_plot()
|
||||
Syscall.GFX_GETPIXEL ->vm.gfx_getpixel()
|
||||
Syscall.WAIT -> {
|
||||
val millis = vm.registers.getUW(0).toLong() * 1000/60
|
||||
val millis = vm.registers.getUW(SyscallRegisterBase).toLong() * 1000/60
|
||||
Thread.sleep(millis)
|
||||
}
|
||||
Syscall.WAITVSYNC -> vm.waitvsync()
|
||||
Syscall.SORT_UBYTE -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length-1, 1).map {
|
||||
vm.memory.getUB(it)
|
||||
}.sorted()
|
||||
@ -144,8 +146,8 @@ object SysCalls {
|
||||
}
|
||||
}
|
||||
Syscall.SORT_BYTE -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length-1, 1).map {
|
||||
vm.memory.getSB(it)
|
||||
}.sorted()
|
||||
@ -154,8 +156,8 @@ object SysCalls {
|
||||
}
|
||||
}
|
||||
Syscall.SORT_UWORD -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map {
|
||||
vm.memory.getUW(it)
|
||||
}.sorted()
|
||||
@ -164,8 +166,8 @@ object SysCalls {
|
||||
}
|
||||
}
|
||||
Syscall.SORT_WORD -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map {
|
||||
vm.memory.getSW(it)
|
||||
}.sorted()
|
||||
@ -174,8 +176,8 @@ object SysCalls {
|
||||
}
|
||||
}
|
||||
Syscall.REVERSE_BYTES -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length-1, 1).map {
|
||||
vm.memory.getUB(it)
|
||||
}.reversed()
|
||||
@ -184,8 +186,8 @@ object SysCalls {
|
||||
}
|
||||
}
|
||||
Syscall.REVERSE_WORDS -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map {
|
||||
vm.memory.getUW(it)
|
||||
}.reversed()
|
||||
@ -194,8 +196,8 @@ object SysCalls {
|
||||
}
|
||||
}
|
||||
Syscall.REVERSE_FLOATS -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length*4-2, 4).map {
|
||||
vm.memory.getFloat(it)
|
||||
}.reversed()
|
||||
@ -204,8 +206,8 @@ object SysCalls {
|
||||
}
|
||||
}
|
||||
Syscall.ANY_BYTE -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
|
||||
val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2)
|
||||
if(addresses.any { vm.memory.getUB(it).toInt()!=0 })
|
||||
vm.registers.setUB(0, 1u)
|
||||
@ -213,8 +215,8 @@ object SysCalls {
|
||||
vm.registers.setUB(0, 0u)
|
||||
}
|
||||
Syscall.ANY_WORD -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
|
||||
val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2)
|
||||
if(addresses.any { vm.memory.getUW(it).toInt()!=0 })
|
||||
vm.registers.setUB(0, 1u)
|
||||
@ -222,8 +224,8 @@ object SysCalls {
|
||||
vm.registers.setUB(0, 0u)
|
||||
}
|
||||
Syscall.ANY_FLOAT -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+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)
|
||||
@ -231,8 +233,8 @@ object SysCalls {
|
||||
vm.registers.setUB(0, 0u)
|
||||
}
|
||||
Syscall.ALL_BYTE -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
|
||||
val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2)
|
||||
if(addresses.all { vm.memory.getUB(it).toInt()!=0 })
|
||||
vm.registers.setUB(0, 1u)
|
||||
@ -240,8 +242,8 @@ object SysCalls {
|
||||
vm.registers.setUB(0, 0u)
|
||||
}
|
||||
Syscall.ALL_WORD -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+1).toInt()
|
||||
val addresses = IntProgression.fromClosedRange(address, address+length*2-2, 2)
|
||||
if(addresses.all { vm.memory.getUW(it).toInt()!=0 })
|
||||
vm.registers.setUB(0, 1u)
|
||||
@ -249,8 +251,8 @@ object SysCalls {
|
||||
vm.registers.setUB(0, 0u)
|
||||
}
|
||||
Syscall.ALL_FLOAT -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val address = vm.registers.getUW(SyscallRegisterBase).toInt()
|
||||
val length = vm.registers.getUB(SyscallRegisterBase+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)
|
||||
@ -258,11 +260,11 @@ object SysCalls {
|
||||
vm.registers.setUB(0, 0u)
|
||||
}
|
||||
Syscall.PRINT_F -> {
|
||||
val value = vm.registers.getFloat(0)
|
||||
val value = vm.registers.getFloat(SyscallRegisterBase)
|
||||
print(value)
|
||||
}
|
||||
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 value = try {
|
||||
string.toUShort()
|
||||
@ -272,7 +274,7 @@ object SysCalls {
|
||||
vm.registers.setUW(0, value)
|
||||
}
|
||||
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 value = try {
|
||||
string.toShort()
|
||||
@ -282,8 +284,8 @@ object SysCalls {
|
||||
vm.registers.setSW(0, value)
|
||||
}
|
||||
Syscall.COMPARE_STRINGS -> {
|
||||
val firstAddr = vm.registers.getUW(0)
|
||||
val secondAddr = vm.registers.getUW(1)
|
||||
val firstAddr = vm.registers.getUW(SyscallRegisterBase)
|
||||
val secondAddr = vm.registers.getUW(SyscallRegisterBase+1)
|
||||
val first = vm.memory.getString(firstAddr.toInt())
|
||||
val second = vm.memory.getString(secondAddr.toInt())
|
||||
val comparison = first.compareTo(second)
|
||||
@ -295,14 +297,14 @@ object SysCalls {
|
||||
vm.registers.setSB(0, 1)
|
||||
}
|
||||
Syscall.RNDFSEED -> {
|
||||
val seed1 = vm.registers.getUB(0)
|
||||
val seed2 = vm.registers.getUB(1)
|
||||
val seed3 = vm.registers.getUB(2)
|
||||
val seed1 = vm.registers.getUB(SyscallRegisterBase)
|
||||
val seed2 = vm.registers.getUB(SyscallRegisterBase+1)
|
||||
val seed3 = vm.registers.getUB(SyscallRegisterBase+2)
|
||||
vm.randomSeedFloat(seed1, seed2, seed3)
|
||||
}
|
||||
Syscall.RNDSEED -> {
|
||||
val seed1 = vm.registers.getUW(0)
|
||||
val seed2 = vm.registers.getUW(1)
|
||||
val seed1 = vm.registers.getUW(SyscallRegisterBase)
|
||||
val seed2 = vm.registers.getUW(SyscallRegisterBase+1)
|
||||
vm.randomSeed(seed1, seed2)
|
||||
}
|
||||
Syscall.RND -> {
|
||||
@ -315,15 +317,15 @@ object SysCalls {
|
||||
vm.registers.setFloat(0, vm.randomGeneratorFloats.nextFloat())
|
||||
}
|
||||
Syscall.STRING_CONTAINS -> {
|
||||
val char = vm.registers.getUB(0).toInt().toChar()
|
||||
val stringAddr = vm.registers.getUW(1)
|
||||
val char = vm.registers.getUB(SyscallRegisterBase).toInt().toChar()
|
||||
val stringAddr = vm.registers.getUW(SyscallRegisterBase+1)
|
||||
val string = vm.memory.getString(stringAddr.toInt())
|
||||
vm.registers.setUB(0, if(char in string) 1u else 0u)
|
||||
}
|
||||
Syscall.BYTEARRAY_CONTAINS -> {
|
||||
val value = vm.registers.getUB(0)
|
||||
var array = vm.registers.getUW(1).toInt()
|
||||
var length = vm.registers.getUB(2)
|
||||
val value = vm.registers.getUB(SyscallRegisterBase)
|
||||
var array = vm.registers.getUW(SyscallRegisterBase+1).toInt()
|
||||
var length = vm.registers.getUB(SyscallRegisterBase+2)
|
||||
while(length>0u) {
|
||||
if(vm.memory.getUB(array)==value) {
|
||||
vm.registers.setUB(0, 1u)
|
||||
@ -336,9 +338,9 @@ object SysCalls {
|
||||
}
|
||||
Syscall.WORDARRAY_CONTAINS -> {
|
||||
// r0.w = value, r1.w = array, r2.b = array length
|
||||
val value = vm.registers.getUW(0)
|
||||
var array = vm.registers.getUW(1).toInt()
|
||||
var length = vm.registers.getUB(2)
|
||||
val value = vm.registers.getUW(SyscallRegisterBase)
|
||||
var array = vm.registers.getUW(SyscallRegisterBase+1).toInt()
|
||||
var length = vm.registers.getUB(SyscallRegisterBase+2)
|
||||
while(length>0u) {
|
||||
if(vm.memory.getUW(array)==value) {
|
||||
vm.registers.setUB(0, 1u)
|
||||
|
@ -92,8 +92,8 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
statusZero = false
|
||||
}
|
||||
|
||||
fun exit() {
|
||||
throw ProgramExitException(registers.getUW(0).toInt())
|
||||
fun exit(statuscode: Int) {
|
||||
throw ProgramExitException(statuscode)
|
||||
}
|
||||
|
||||
fun step(count: Int=1) {
|
||||
@ -118,7 +118,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
}
|
||||
|
||||
null -> {
|
||||
exit() // end of program reached
|
||||
exit(0) // end of program reached
|
||||
}
|
||||
|
||||
else -> {
|
||||
@ -574,7 +574,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun InsRETURN() {
|
||||
if(callStack.isEmpty())
|
||||
exit()
|
||||
exit(0)
|
||||
else {
|
||||
val (chunk, idx) = callStack.pop()
|
||||
pcChunk = chunk
|
||||
@ -2108,7 +2108,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
private var window: GraphicsWindow? = null
|
||||
|
||||
fun gfx_enable() {
|
||||
window = when(registers.getUB(0).toInt()) {
|
||||
window = when(registers.getUB(SyscallRegisterBase).toInt()) {
|
||||
0 -> GraphicsWindow(320, 240, 3)
|
||||
1 -> GraphicsWindow(640, 480, 2)
|
||||
else -> throw IllegalArgumentException("invalid screen mode")
|
||||
@ -2117,18 +2117,21 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
}
|
||||
|
||||
fun gfx_clear() {
|
||||
window?.clear(registers.getUB(0).toInt())
|
||||
window?.clear(registers.getUB(SyscallRegisterBase).toInt())
|
||||
}
|
||||
|
||||
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() {
|
||||
if(window==null)
|
||||
registers.setUB(0, 0u)
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user