diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index ba48af3b8..b184ed697 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -119,7 +119,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, "cmp" -> funcCmp(fcall) "callfar" -> funcCallFar(fcall) "callrom" -> funcCallRom(fcall) - "syscall", "syscall1", "syscall2", "syscall3", "syscall1fp" -> throw AssemblyError("6502 assembly target doesn't use syscall function interface") else -> throw AssemblyError("missing asmgen for builtin func ${func.name}") } } diff --git a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt index 514904004..d68540c00 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt @@ -5,7 +5,6 @@ import prog8.code.ast.* import prog8.code.core.ArrayToElementTypes import prog8.code.core.AssemblyError import prog8.code.core.DataType -import prog8.code.core.WordDatatypes import prog8.vm.Opcode import prog8.vm.Syscall import prog8.vm.VmDataType @@ -32,11 +31,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: "rndw" -> funcRndw(resultRegister) "callfar" -> throw AssemblyError("callfar() is for cx16 target only") "callrom" -> throw AssemblyError("callrom() is for cx16 target only") - "syscall" -> funcSyscall(call) - "syscall1" -> funcSyscall1(call) - "syscall2" -> funcSyscall2(call) - "syscall3" -> funcSyscall3(call) - "syscall1fp" -> funcSyscall1fp(call) "msb" -> funcMsb(call, resultRegister) "lsb" -> funcLsb(call, resultRegister) "memory" -> funcMemory(call, resultRegister) @@ -350,60 +344,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: return code } - private fun funcSyscall(call: PtBuiltinFunctionCall): VmCodeChunk { - val code = VmCodeChunk() - val vExpr = call.args.single() as PtNumber - code += VmCodeInstruction(Opcode.SYSCALL, value=vExpr.number.toInt()) - return code - } - - private fun funcSyscall1(call: PtBuiltinFunctionCall): VmCodeChunk { - val code = VmCodeChunk() - val callNr = (call.args[0] as PtNumber).number.toInt() - code += exprGen.translateExpression(call.args[1], 0, -1) - code += VmCodeInstruction(Opcode.SYSCALL, value=callNr) - return code - } - - private fun funcSyscall1fp(call: PtBuiltinFunctionCall): VmCodeChunk { - val code = VmCodeChunk() - val callNr = (call.args[0] as PtNumber).number.toInt() - code += exprGen.translateExpression(call.args[1], -1, 0) - code += VmCodeInstruction(Opcode.SYSCALL, value=callNr) - return code - } - - private fun funcSyscall2(call: PtBuiltinFunctionCall): VmCodeChunk { - val code = VmCodeChunk() - code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1) - while(codeGen.vmRegisters.peekNext()<2) { - codeGen.vmRegisters.nextFree() - } - val callNr = (call.args[0] as PtNumber).number.toInt() - code += exprGen.translateExpression(call.args[1], 0, -1) - code += exprGen.translateExpression(call.args[2], 1, -1) - code += VmCodeInstruction(Opcode.SYSCALL, value=callNr) - code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1) - return code - } - - private fun funcSyscall3(call: PtBuiltinFunctionCall): VmCodeChunk { - val code = VmCodeChunk() - code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1) - code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 2) - while(codeGen.vmRegisters.peekNext()<3) { - codeGen.vmRegisters.nextFree() - } - val callNr = (call.args[0] as PtNumber).number.toInt() - code += exprGen.translateExpression(call.args[1], 0, -1) - code += exprGen.translateExpression(call.args[2], 1, -1) - code += exprGen.translateExpression(call.args[3], 2, -1) - code += VmCodeInstruction(Opcode.SYSCALL, value=callNr) - code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 2) - code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1) - return code - } - private fun funcRolRor2(opcode: Opcode, call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { val vmDt = codeGen.vmType(call.args[0].type) val code = VmCodeChunk() diff --git a/compiler/res/prog8lib/virtual/floats.p8 b/compiler/res/prog8lib/virtual/floats.p8 index b41877b5a..db1c9985d 100644 --- a/compiler/res/prog8lib/virtual/floats.p8 +++ b/compiler/res/prog8lib/virtual/floats.p8 @@ -19,84 +19,130 @@ sub print_f(float value) { } sub pow(float value, float power) -> float { - ; TODO - return -42.42 + ; TODO fpow.f instruction + %asm {{ + loadm.f fr0,{floats.pow.value} + loadm.f fr1,{floats.pow.power} + fpow.f fr0,fr0 + return + }} } sub fabs(float value) -> float { - ; TODO - return -42.42 + ; TODO fabs.f instruction + %asm {{ + loadm.f fr0,{floats.fabs.value} + fabs.f fr0,fr0 + return + }} } sub sin(float angle) -> float { - ; TODO sin.f instruction + ; TODO fsin.f instruction %asm {{ loadm.f fr0,{floats.sin.angle} - sin.f fr0,fr0 + fsin.f fr0,fr0 return }} } sub cos(float angle) -> float { - ; TODO - return -42.42 + ; TODO fcos.f instruction + %asm {{ + loadm.f fr0,{floats.cos.angle} + fcos.f fr0,fr0 + return + }} } sub tan(float value) -> float { - ; TODO - return -42.42 + ; TODO ftan.f instruction + %asm {{ + loadm.f fr0,{floats.tan.value} + ftan.f fr0,fr0 + return + }} } sub atan(float value) -> float { - ; TODO - return -42.42 + ; TODO fatan.f instruction + %asm {{ + loadm.f fr0,{floats.atan.value} + fatan.f fr0,fr0 + return + }} } sub ln(float value) -> float { - ; TODO - return -42.42 + ; TODO fln.f instruction + %asm {{ + loadm.f fr0,{floats.ln.value} + fln.f fr0,fr0 + return + }} } sub log2(float value) -> float { - ; TODO - return -42.42 + ; TODO flog2.f instruction + %asm {{ + loadm.f fr0,{floats.log2.value} + flog2.f fr0,fr0 + return + }} } sub sqrt(float value) -> float { - ; TODO - return -42.42 + ; TODO fsqrt.f instruction + %asm {{ + loadm.f fr0,{floats.sqrt.value} + fsqrt.f fr0,fr0 + return + }} } sub rad(float angle) -> float { ; -- convert degrees to radians (d * pi / 180) - ; TODO - return -42.42 + return angle * PI / 180.0 } sub deg(float angle) -> float { ; -- convert radians to degrees (d * (1/ pi * 180)) - ; TODO - return -42.42 + return angle * 180.0 / PI } sub round(float value) -> float { - ; TODO - return -42.42 + ; TODO fround.f instruction + %asm {{ + loadm.f fr0,{floats.round.value} + fround.f fr0,fr0 + return + }} } sub floor(float value) -> float { - ; TODO - return -42.42 + ; TODO ffloor.f instruction + %asm {{ + loadm.f fr0,{floats.floor.value} + ffloor.f fr0,fr0 + return + }} } sub ceil(float value) -> float { ; -- ceil: tr = int(f); if tr==f -> return else return tr+1 - ; TODO - return -42.42 + ; TODO fceil.f instruction + %asm {{ + loadm.f fr0,{floats.ceil.value} + fceil.f fr0,fr0 + return + }} } sub rndf() -> float { - ; TODO - return -42.42 + ; TODO frnd.f instruction + %asm {{ + frnd.f fr0 + return + }} } } diff --git a/compiler/res/prog8lib/virtual/syslib.p8 b/compiler/res/prog8lib/virtual/syslib.p8 index f15c6a302..34c16a24b 100644 --- a/compiler/res/prog8lib/virtual/syslib.p8 +++ b/compiler/res/prog8lib/virtual/syslib.p8 @@ -8,74 +8,26 @@ sys { const ubyte target = 255 ; compilation target specifier. 64 = C64, 128 = C128, 16 = CommanderX16, 8 = atari800XL, 255 = virtual - ; Syscalls table, taken from Syscall enumeration - ; 0 = reset ; resets system - ; 1 = exit ; stops program and returns statuscode from r0.w - ; 2 = print_c ; print single character - ; 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 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 - ; 10 = gfx_plot ; plot pixel in graphics window, r0.w/r1.w contain X and Y coordinates, r2.b contains brightness - ; 11 = set_carry status flag - ; 12 = clear_carry status flag - ; 13 = wait ; wait certain amount of jiffies (1/60 sec) - ; 14 = waitvsync ; wait on vsync - ; 15 = sort_ubyte array - ; 16 = sort_byte array - ; 17 = sort_uword array - ; 18 = sort_word array - ; 19 = max_ubyte array - ; 20 = max_byte array - ; 21 = max_uword array - ; 22 = max_word array - ; 23 = min_ubyte array - ; 24 = min_byte array - ; 25 = min_uword array - ; 26 = min_word array - ; 27 = sum_byte array - ; 28 = sum_word array - ; 29 = any_byte array - ; 30 = any_word array - ; 31 = all_byte array - ; 32 = all_word array - ; 33 = reverse_bytes array - ; 34 = reverse_words array - ; 35 = printf (float arg in fpReg0) - const ubyte SC_RESET = 0 - const ubyte SC_EXIT = 1 - const ubyte SC_PRINT_C = 2 - const ubyte SC_PRINT_S = 3 - const ubyte SC_PRINT_U8 = 4 - const ubyte SC_PRINT_U16 = 5 - const ubyte SC_INPUT = 6 - const ubyte SC_SLEEP = 7 - const ubyte SC_GFX_ENABLE = 8 - const ubyte SC_GFX_CLEAR = 9 - const ubyte SC_GFX_PLOT = 10 - const ubyte SC_SET_CARRY = 11 - const ubyte SC_CLEAR_CARRY = 12 - const ubyte SC_WAIT = 13 - const ubyte SC_WAITVSYNC = 14 - const ubyte SC_PRINTF = 35 - - sub reset_system() { ; Soft-reset the system back to initial power-on Basic prompt. - void syscall(SC_RESET) + %asm {{ + syscall 0 + }} } sub wait(uword jiffies) { ; --- wait approximately the given number of jiffies (1/60th seconds) - void syscall1(SC_WAIT, jiffies) + %asm {{ + loadm.w r0, {sys.wait.jiffies} + syscall 13 + }} } sub waitvsync() { ; --- busy wait till the next vsync has occurred (approximately), without depending on custom irq handling. - void syscall(SC_WAITVSYNC) + %asm {{ + syscall 14 + }} } sub internal_stringcopy(uword source, uword target) { @@ -112,15 +64,39 @@ sys { sub exit(ubyte returnvalue) { ; -- immediately exit the program with a return code in the A register - void syscall1(SC_EXIT, returnvalue) - } - - sub clear_carry() { - void syscall(SC_CLEAR_CARRY) + %asm {{ + loadm.b r0,{sys.exit.returnvalue} + syscall 1 + }} } sub set_carry() { - void syscall(SC_SET_CARRY) + %asm {{ + sec + }} + } + + sub clear_carry() { + %asm {{ + clc + }} + } + + + sub gfx_enable(ubyte mode) { + %asm {{ + loadm.b r0, {sys.gfx_enable.mode} + syscall 8 + }} + } + + sub gfx_plot(uword xx, uword yy, ubyte color) { + %asm {{ + loadm.w r0, {sys.gfx_plot.xx} + loadm.w r1, {sys.gfx_plot.yy} + loadm.b r2, {sys.gfx_plot.color} + syscall 10 + }} } } diff --git a/compiler/res/prog8lib/virtual/textio.p8 b/compiler/res/prog8lib/virtual/textio.p8 index 8a1f678bb..3e37d2ee2 100644 --- a/compiler/res/prog8lib/virtual/textio.p8 +++ b/compiler/res/prog8lib/virtual/textio.p8 @@ -7,7 +7,11 @@ txt { sub clear_screen() { - void syscall1(3, "\x1b[2J\x1B[H") + str @shared sequence = "\x1b[2J\x1B[H" + %asm {{ + load.w r0, {txt.clear_screen.sequence} + syscall 3 + }} } sub nl() { @@ -27,11 +31,17 @@ sub uppercase() { } sub chrout(ubyte char) { - void syscall1(2, char) + %asm {{ + loadm.b r0, {txt.chrout.char} + syscall 2 + }} } sub print (str text) { - void syscall1(3, text) + %asm {{ + loadm.w r0, {txt.print.text} + syscall 3 + }} } sub print_ub0 (ubyte value) { @@ -105,7 +115,11 @@ 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! - return syscall1(6, buffer) + %asm {{ + loadm.w r0,{txt.input_chars.buffer} + syscall 6 + return + }} } } diff --git a/compilerAst/src/prog8/compiler/BuiltinFunctions.kt b/compilerAst/src/prog8/compiler/BuiltinFunctions.kt index 918a6846a..75fd4b0a8 100644 --- a/compilerAst/src/prog8/compiler/BuiltinFunctions.kt +++ b/compilerAst/src/prog8/compiler/BuiltinFunctions.kt @@ -123,11 +123,6 @@ private val functionSignatures: List = listOf( FSignature("swap" , false, listOf(FParam("first", NumericDatatypes), FParam("second", NumericDatatypes)), null), FSignature("callfar" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null), FSignature("callrom" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null), - FSignature("syscall" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE))), DataType.UWORD, null), - FSignature("syscall1" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.UWORD))), DataType.UWORD, null), - FSignature("syscall1fp" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.FLOAT))), DataType.FLOAT, null), - FSignature("syscall2" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.UWORD)), FParam("arg2", arrayOf(DataType.UWORD))), 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))), DataType.UWORD, null), ) val BuiltinFunctions = functionSignatures.associateBy { it.name } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 1228059ed..cfbc06681 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,7 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- vm: get rid of the syscall() functions in prog8 via inline assembly +- vm: fix fp reg out of bounds - vm: implement missing floating point functions - vm: get rid of intermediate floats.xxx() functions somehow, instead generate the float instructions directly? - pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls. diff --git a/examples/test.p8 b/examples/test.p8 index 6d6977776..8fbf35c66 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -8,14 +8,23 @@ main { sub start() { - txt.print("float tests: ") - floats.print_f(-42.42) - float f1 = 1.2345 - float f2 = -9.99 - float f3 - f3 = floats.sin(f3) - floats.print_f(f3) - txt.nl() + float fl = 500.0 + txt.print("rad 180 = ") + floats.print_f(floats.rad(180.0)) + txt.print("rad 360 = ") + floats.print_f(floats.rad(360.0)) + txt.print("deg 2 = ") + floats.print_f(floats.deg(2.0)) + txt.print("deg pi = ") + floats.print_f(floats.deg(floats.PI)) + sys.exit(42) +; floats.print_f(-42.42) +; float f1 = 1.2345 +; float f2 = -9.99 +; float f3 +; f3 = floats.sin(f3) +; floats.print_f(f3) +; txt.nl() ; float f1 = 1.555 ; floats.print_f(floats.sin(f1)) @@ -49,23 +58,21 @@ main { ; "deg", "round", "floor", "ceil", "rndf" ; a "pixelshader": -; void syscall1(8, 0) ; enable lo res creen -; ubyte shifter -; -; ; pokemon(1,0) -; -; 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 -; } + sys.gfx_enable(0) ; enable lo res screen + ubyte shifter + + repeat { + uword xx + uword yy = 0 + repeat 240 { + xx = 0 + repeat 320 { + sys.gfx_plot(xx, yy, xx*yy + shifter as ubyte) + xx++ + } + yy++ + } + shifter+=4 + } } } diff --git a/virtualmachine/src/prog8/vm/SysCalls.kt b/virtualmachine/src/prog8/vm/SysCalls.kt index 17daeb1e8..f2d6ba1e9 100644 --- a/virtualmachine/src/prog8/vm/SysCalls.kt +++ b/virtualmachine/src/prog8/vm/SysCalls.kt @@ -16,8 +16,8 @@ SYSCALLS: 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 10 = gfx_plot ; plot pixel in graphics window, r0.w/r1.w contain X and Y coordinates, r2.b contains brightness -11 = set_carry status flag -12 = clear_carry status flag +11 = +12 = 13 = wait ; wait certain amount of jiffies (1/60 sec) 14 = waitvsync ; wait on vsync 15 = sort_ubyte array @@ -55,8 +55,8 @@ enum class Syscall { GFX_ENABLE, GFX_CLEAR, GFX_PLOT, - SET_CARRY, - CLEAR_CARRY, + UNUSED_1, + UNUSED_2, WAIT, WAITVSYNC, SORT_UBYTE, @@ -297,8 +297,6 @@ object SysCalls { else vm.registers.setUB(0, 0u) } - Syscall.SET_CARRY -> vm.statusCarry = true - Syscall.CLEAR_CARRY -> vm.statusCarry = false Syscall.PRINT_F -> { val value = vm.registers.getFloat(0) print(value) diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index 88cbdeef2..5b00e86ad 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -61,11 +61,13 @@ class VirtualMachine(val memory: Memory, program: List) { fun reset() { registers.reset() - memory.reset() + // memory.reset() pc = 0 stepCount = 0 callStack.clear() statusCarry = false + statusNegative = false + statusZero = false } fun exit() { @@ -168,6 +170,8 @@ class VirtualMachine(val memory: Memory, program: List) { Opcode.PUSH -> InsPUSH(ins) Opcode.POP -> InsPOP(ins) Opcode.BREAKPOINT -> InsBREAKPOINT() + Opcode.CLC -> { statusCarry = false; pc++ } + Opcode.SEC -> { statusCarry = true; pc++ } else -> throw IllegalArgumentException("invalid opcode ${ins.opcode}") } }