vm: syscalls can now return value

This commit is contained in:
Irmen de Jong 2022-04-05 20:46:34 +02:00
parent 461b38e653
commit a8cf9f5cc4
7 changed files with 34 additions and 53 deletions

View File

@ -1,13 +1,11 @@
package prog8.codegen.virtual
import prog8.code.StArray
import prog8.code.StStaticVariable
import prog8.code.ast.PtBuiltinFunctionCall
import prog8.code.ast.PtIdentifier
import prog8.code.ast.PtNumber
import prog8.code.ast.PtString
import prog8.code.core.DataType
import prog8.code.core.WordDatatypes
import prog8.vm.Opcode
import prog8.vm.Syscall
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())
}
"syscall1" -> {
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 0)
val callNr = (call.args[0] as PtNumber).number.toInt()
code += exprGen.translateExpression(call.args[1], 0)
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 0)
}
"syscall2" -> {
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 0)
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1)
while(codeGen.vmRegisters.peekNext()<2) {
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 += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 0)
}
"syscall3" -> {
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 0)
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1)
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 2)
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.POP, VmDataType.WORD, reg1 = 2)
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 0)
}
"msb" -> {
code += exprGen.translateExpression(call.args.single(), resultRegister)

View File

@ -39,17 +39,17 @@ sys {
sub reset_system() {
; Soft-reset the system back to initial power-on Basic prompt.
syscall(SC_RESET)
void syscall(SC_RESET)
}
sub wait(uword jiffies) {
; --- wait approximately the given number of jiffies (1/60th seconds)
syscall1(SC_WAIT, jiffies)
void syscall1(SC_WAIT, jiffies)
}
sub waitvsync() {
; --- 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) {
@ -76,7 +76,7 @@ sys {
sub exit(ubyte returnvalue) {
; -- immediately exit the program with a return code in the A register
syscall1(SC_EXIT, returnvalue)
void syscall1(SC_EXIT, returnvalue)
}
}

View File

@ -8,7 +8,7 @@
txt {
sub clear_screen() {
syscall1(3, "\x1b[2J\x1B[H")
void syscall1(3, "\x1b[2J\x1B[H")
}
sub nl() {
@ -28,11 +28,11 @@ sub uppercase() {
}
sub chrout(ubyte char) {
syscall1(2, char)
void syscall1(2, char)
}
sub print (str text) {
syscall1(3, text)
void syscall1(3, text)
}
sub print_ub0 (ubyte value) {
@ -164,8 +164,7 @@ sub print_w (word value) {
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!
; TODO
return 0
return syscall1(6, buffer)
}
}

View File

@ -166,10 +166,10 @@ private val functionSignatures: List<FSignature> = listOf(
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("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("syscall1" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", 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))), 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))), 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))), true, DataType.UWORD, 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))), true, DataType.UWORD, null),
)
val BuiltinFunctions = functionSignatures.associateBy { it.name }

View File

@ -4,7 +4,7 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- 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
- 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.
@ -48,7 +48,7 @@ Compiler:
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.
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
Libraries:
@ -82,6 +82,5 @@ Optimizations:
- 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
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.
- introduce byte-index operator to avoid index multiplications in loops over arrays? see github issue #4

View File

@ -5,34 +5,25 @@
; NOTE: meant to test to virtual machine output target (use -target vitual)
main {
sub start() {
uword[] array = [1111,2222,3333,4444,5555]
txt.print_uw(array[3])
txt.nl()
; a "pixelshader":
; syscall1(8, 0) ; enable lo res creen
; ubyte shifter
;
; shifter >>= 1
;
; repeat {
; uword xx
; uword yy = 0
; repeat 240 {
; xx = 0
; repeat 320 {
; syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
; xx++
; }
; yy++
; }
; shifter+=4
;
; txt.print_ub(shifter)
; txt.nl()
; }
void syscall1(8, 0) ; enable lo res creen
ubyte shifter
shifter >>= 1
repeat {
uword xx
uword yy = 0
repeat 240 {
xx = 0
repeat 320 {
syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
xx++
}
yy++
}
shifter+=4
}
}
}

View File

@ -12,7 +12,7 @@ SYSCALLS:
3 = print_s ; print 0-terminated string from memory
4 = print_u8 ; print unsigned int byte
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
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
@ -90,7 +90,7 @@ object SysCalls {
if(maxlen>0)
input = input.substring(0, min(input.length, maxlen))
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 -> {
val duration = vm.registers.getUW(0).toLong()