mirror of
https://github.com/irmen/prog8.git
synced 2025-02-08 16:30:28 +00:00
vm: syscalls can now return value
This commit is contained in:
parent
461b38e653
commit
a8cf9f5cc4
@ -1,13 +1,11 @@
|
|||||||
package prog8.codegen.virtual
|
package prog8.codegen.virtual
|
||||||
|
|
||||||
import prog8.code.StArray
|
|
||||||
import prog8.code.StStaticVariable
|
import prog8.code.StStaticVariable
|
||||||
import prog8.code.ast.PtBuiltinFunctionCall
|
import prog8.code.ast.PtBuiltinFunctionCall
|
||||||
import prog8.code.ast.PtIdentifier
|
import prog8.code.ast.PtIdentifier
|
||||||
import prog8.code.ast.PtNumber
|
import prog8.code.ast.PtNumber
|
||||||
import prog8.code.ast.PtString
|
import prog8.code.ast.PtString
|
||||||
import prog8.code.core.DataType
|
import prog8.code.core.DataType
|
||||||
import prog8.code.core.WordDatatypes
|
|
||||||
import prog8.vm.Opcode
|
import prog8.vm.Opcode
|
||||||
import prog8.vm.Syscall
|
import prog8.vm.Syscall
|
||||||
import prog8.vm.VmDataType
|
import prog8.vm.VmDataType
|
||||||
@ -22,14 +20,11 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=vExpr.number.toInt())
|
code += VmCodeInstruction(Opcode.SYSCALL, value=vExpr.number.toInt())
|
||||||
}
|
}
|
||||||
"syscall1" -> {
|
"syscall1" -> {
|
||||||
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 0)
|
|
||||||
val callNr = (call.args[0] as PtNumber).number.toInt()
|
val callNr = (call.args[0] as PtNumber).number.toInt()
|
||||||
code += exprGen.translateExpression(call.args[1], 0)
|
code += exprGen.translateExpression(call.args[1], 0)
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
||||||
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 0)
|
|
||||||
}
|
}
|
||||||
"syscall2" -> {
|
"syscall2" -> {
|
||||||
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 0)
|
|
||||||
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1)
|
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1)
|
||||||
while(codeGen.vmRegisters.peekNext()<2) {
|
while(codeGen.vmRegisters.peekNext()<2) {
|
||||||
codeGen.vmRegisters.nextFree()
|
codeGen.vmRegisters.nextFree()
|
||||||
@ -39,10 +34,8 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
code += exprGen.translateExpression(call.args[2], 1)
|
code += exprGen.translateExpression(call.args[2], 1)
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
||||||
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
|
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
|
||||||
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 0)
|
|
||||||
}
|
}
|
||||||
"syscall3" -> {
|
"syscall3" -> {
|
||||||
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 0)
|
|
||||||
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1)
|
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1)
|
||||||
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 2)
|
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 2)
|
||||||
while(codeGen.vmRegisters.peekNext()<3) {
|
while(codeGen.vmRegisters.peekNext()<3) {
|
||||||
@ -55,7 +48,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
||||||
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 2)
|
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 2)
|
||||||
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
|
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
|
||||||
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 0)
|
|
||||||
}
|
}
|
||||||
"msb" -> {
|
"msb" -> {
|
||||||
code += exprGen.translateExpression(call.args.single(), resultRegister)
|
code += exprGen.translateExpression(call.args.single(), resultRegister)
|
||||||
|
@ -39,17 +39,17 @@ sys {
|
|||||||
|
|
||||||
sub reset_system() {
|
sub reset_system() {
|
||||||
; Soft-reset the system back to initial power-on Basic prompt.
|
; Soft-reset the system back to initial power-on Basic prompt.
|
||||||
syscall(SC_RESET)
|
void syscall(SC_RESET)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
syscall1(SC_WAIT, jiffies)
|
void syscall1(SC_WAIT, jiffies)
|
||||||
}
|
}
|
||||||
|
|
||||||
sub waitvsync() {
|
sub waitvsync() {
|
||||||
; --- busy wait till the next vsync has occurred (approximately), without depending on custom irq handling.
|
; --- busy wait till the next vsync has occurred (approximately), without depending on custom irq handling.
|
||||||
syscall(SC_WAITVSYNC)
|
void syscall(SC_WAITVSYNC)
|
||||||
}
|
}
|
||||||
|
|
||||||
sub memcopy(uword source, uword target, uword count) {
|
sub memcopy(uword source, uword target, uword count) {
|
||||||
@ -76,7 +76,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
|
||||||
syscall1(SC_EXIT, returnvalue)
|
void syscall1(SC_EXIT, returnvalue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
txt {
|
txt {
|
||||||
|
|
||||||
sub clear_screen() {
|
sub clear_screen() {
|
||||||
syscall1(3, "\x1b[2J\x1B[H")
|
void syscall1(3, "\x1b[2J\x1B[H")
|
||||||
}
|
}
|
||||||
|
|
||||||
sub nl() {
|
sub nl() {
|
||||||
@ -28,11 +28,11 @@ sub uppercase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub chrout(ubyte char) {
|
sub chrout(ubyte char) {
|
||||||
syscall1(2, char)
|
void syscall1(2, char)
|
||||||
}
|
}
|
||||||
|
|
||||||
sub print (str text) {
|
sub print (str text) {
|
||||||
syscall1(3, text)
|
void syscall1(3, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
sub print_ub0 (ubyte value) {
|
sub print_ub0 (ubyte value) {
|
||||||
@ -164,8 +164,7 @@ sub print_w (word value) {
|
|||||||
sub input_chars (uword buffer) -> ubyte {
|
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!
|
||||||
; TODO
|
return syscall1(6, buffer)
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -166,10 +166,10 @@ private val functionSignatures: List<FSignature> = listOf(
|
|||||||
FSignature("swap" , false, listOf(FParam("first", NumericDatatypes), FParam("second", NumericDatatypes)), false, null),
|
FSignature("swap" , false, listOf(FParam("first", NumericDatatypes), FParam("second", NumericDatatypes)), false, null),
|
||||||
FSignature("callfar" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), false, null),
|
FSignature("callfar" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), false, null),
|
||||||
FSignature("callrom" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), false, null),
|
FSignature("callrom" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), false, null),
|
||||||
FSignature("syscall" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE))), false, null, null),
|
FSignature("syscall" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE))), true, DataType.UWORD, null),
|
||||||
FSignature("syscall1" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.UWORD))), false, null, null),
|
FSignature("syscall1" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.UWORD))), true, DataType.UWORD, null),
|
||||||
FSignature("syscall2" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.UWORD)), FParam("arg2", arrayOf(DataType.UWORD))), false, null, null),
|
FSignature("syscall2" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.UWORD)), FParam("arg2", arrayOf(DataType.UWORD))), true, DataType.UWORD, null),
|
||||||
FSignature("syscall3" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.UWORD)), FParam("arg2", arrayOf(DataType.UWORD)), FParam("arg3", arrayOf(DataType.UWORD))), false, null, null),
|
FSignature("syscall3" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.UWORD)), FParam("arg2", arrayOf(DataType.UWORD)), FParam("arg3", arrayOf(DataType.UWORD))), true, DataType.UWORD, null),
|
||||||
)
|
)
|
||||||
|
|
||||||
val BuiltinFunctions = functionSignatures.associateBy { it.name }
|
val BuiltinFunctions = functionSignatures.associateBy { it.name }
|
||||||
|
@ -4,7 +4,7 @@ TODO
|
|||||||
For next release
|
For next release
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
- 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.
|
||||||
- writeAssembly(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
|
- createAssemblyAndAssemble(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
|
||||||
- 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
|
||||||
- make it possible to inline non-asmsub routines that just contain a single statement (return, functioncall, assignment)
|
- make it possible to inline non-asmsub routines that just contain a single statement (return, functioncall, assignment)
|
||||||
but this requires all identifiers in the inlined expression to be changed to fully scoped names.
|
but this requires all identifiers in the inlined expression to be changed to fully scoped names.
|
||||||
@ -48,7 +48,7 @@ Compiler:
|
|||||||
Perhaps replace all uses of .proc/.pend by .block/.bend will fix that?
|
Perhaps replace all uses of .proc/.pend by .block/.bend will fix that?
|
||||||
(but we lose the optimizing aspect of the assembler where it strips out unused code.
|
(but we lose the optimizing aspect of the assembler where it strips out unused code.
|
||||||
There's not really a dynamic switch possible as all assembly lib code is static and uses one or the other)
|
There's not really a dynamic switch possible as all assembly lib code is static and uses one or the other)
|
||||||
Zig-like try-based error handling where the V flag could indicate error condition? and/or BRK to jump into monitor on failure? (has to set BRK vector for that)
|
- Zig-like try-based error handling where the V flag could indicate error condition? and/or BRK to jump into monitor on failure? (has to set BRK vector for that)
|
||||||
- add special (u)word array type (or modifier?) that puts the array into memory as 2 separate byte-arrays 1 for LSB 1 for MSB -> allows for word arrays of length 256
|
- add special (u)word array type (or modifier?) that puts the array into memory as 2 separate byte-arrays 1 for LSB 1 for MSB -> allows for word arrays of length 256
|
||||||
|
|
||||||
Libraries:
|
Libraries:
|
||||||
@ -82,6 +82,5 @@ Optimizations:
|
|||||||
- AssignmentAsmGen.assignExpression() -> better code gen for assigning boolean comparison expressions
|
- AssignmentAsmGen.assignExpression() -> better code gen for assigning boolean comparison expressions
|
||||||
- when a for loop's loopvariable isn't referenced in the body, and the iterations are known, replace the loop by a repeatloop
|
- when a for loop's loopvariable isn't referenced in the body, and the iterations are known, replace the loop by a repeatloop
|
||||||
but we have no efficient way right now to see if the body references a variable.
|
but we have no efficient way right now to see if the body references a variable.
|
||||||
- AssignmentAsmGen: "real optimized code for comparison expressions that yield a boolean result value"
|
|
||||||
- automatically convert if statements that test for multiple values (if X==1 or X==2..) to if X in [1,2,..] statements, instead of just a warning.
|
- automatically convert if statements that test for multiple values (if X==1 or X==2..) to if X in [1,2,..] statements, instead of just a warning.
|
||||||
- introduce byte-index operator to avoid index multiplications in loops over arrays? see github issue #4
|
- introduce byte-index operator to avoid index multiplications in loops over arrays? see github issue #4
|
||||||
|
@ -5,34 +5,25 @@
|
|||||||
; NOTE: meant to test to virtual machine output target (use -target vitual)
|
; NOTE: meant to test to virtual machine output target (use -target vitual)
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
uword[] array = [1111,2222,3333,4444,5555]
|
|
||||||
|
|
||||||
txt.print_uw(array[3])
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
; a "pixelshader":
|
; a "pixelshader":
|
||||||
; syscall1(8, 0) ; enable lo res creen
|
void syscall1(8, 0) ; enable lo res creen
|
||||||
; ubyte shifter
|
ubyte shifter
|
||||||
;
|
|
||||||
; shifter >>= 1
|
shifter >>= 1
|
||||||
;
|
|
||||||
; repeat {
|
repeat {
|
||||||
; uword xx
|
uword xx
|
||||||
; uword yy = 0
|
uword yy = 0
|
||||||
; repeat 240 {
|
repeat 240 {
|
||||||
; xx = 0
|
xx = 0
|
||||||
; repeat 320 {
|
repeat 320 {
|
||||||
; syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
|
syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
|
||||||
; xx++
|
xx++
|
||||||
; }
|
}
|
||||||
; yy++
|
yy++
|
||||||
; }
|
}
|
||||||
; shifter+=4
|
shifter+=4
|
||||||
;
|
}
|
||||||
; txt.print_ub(shifter)
|
|
||||||
; txt.nl()
|
|
||||||
; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ SYSCALLS:
|
|||||||
3 = print_s ; print 0-terminated string from memory
|
3 = print_s ; print 0-terminated string from memory
|
||||||
4 = print_u8 ; print unsigned int byte
|
4 = print_u8 ; print unsigned int byte
|
||||||
5 = print_u16 ; print unsigned int word
|
5 = print_u16 ; print unsigned int word
|
||||||
6 = input ; reads a line of text entered by the user, r0.w = memory buffer, r1.b = maxlength (0-255, 0=unlimited). Zero-terminates the string. Returns length in r65535.w
|
6 = input ; reads a line of text entered by the user, r0.w = memory buffer, r1.b = maxlength (0-255, 0=unlimited). Zero-terminates the string. Returns length in r0.w
|
||||||
7 = sleep ; sleep amount of milliseconds
|
7 = sleep ; sleep amount of milliseconds
|
||||||
8 = gfx_enable ; enable graphics window r0.b = 0 -> lores 320x240, r0.b = 1 -> hires 640x480
|
8 = gfx_enable ; enable graphics window r0.b = 0 -> lores 320x240, r0.b = 1 -> hires 640x480
|
||||||
9 = gfx_clear ; clear graphics window with shade in r0.b
|
9 = gfx_clear ; clear graphics window with shade in r0.b
|
||||||
@ -90,7 +90,7 @@ object SysCalls {
|
|||||||
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(0).toInt(), input, true)
|
||||||
vm.registers.setUW(65535, 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(0).toLong()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user