mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +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
|
||||
|
||||
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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 }
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user