diff --git a/compiler/res/prog8lib/c128/syslib.p8 b/compiler/res/prog8lib/c128/syslib.p8 index 2bc7baf2c..bc314e265 100644 --- a/compiler/res/prog8lib/c128/syslib.p8 +++ b/compiler/res/prog8lib/c128/syslib.p8 @@ -1056,6 +1056,32 @@ _no_msb_size }} } + inline asmsub pushl(long value @R0R1_32) { + %asm {{ + lda cx16.r0 + pha + lda cx16.r0+1 + pha + lda cx16.r0+2 + pha + lda cx16.r0+3 + pha + }} + } + + inline asmsub popl() -> long @R0R1_32 { + %asm {{ + pla + sta cx16.r0+3 + pla + sta cx16.r0+2 + pla + sta cx16.r0+1 + pla + sta cx16.r0 + }} + } + sub cpu_is_65816() -> bool { ; Returns true when you have a 65816 cpu, false when it's a 6502. ; The SuperCPU expansion for the C64/C128 contains a 65816. diff --git a/compiler/res/prog8lib/c64/syslib.p8 b/compiler/res/prog8lib/c64/syslib.p8 index ee601ae65..42c0a7b99 100644 --- a/compiler/res/prog8lib/c64/syslib.p8 +++ b/compiler/res/prog8lib/c64/syslib.p8 @@ -1065,6 +1065,32 @@ _no_msb_size }} } + inline asmsub pushl(long value @R0R1_32) { + %asm {{ + lda cx16.r0 + pha + lda cx16.r0+1 + pha + lda cx16.r0+2 + pha + lda cx16.r0+3 + pha + }} + } + + inline asmsub popl() -> long @R0R1_32 { + %asm {{ + pla + sta cx16.r0+3 + pla + sta cx16.r0+2 + pla + sta cx16.r0+1 + pla + sta cx16.r0 + }} + } + sub cpu_is_65816() -> bool { ; Returns true when you have a 65816 cpu, false when it's a 6502. ; The SuperCPU expansion for the C64/C128 contains a 65816. diff --git a/compiler/res/prog8lib/cx16/syslib.p8 b/compiler/res/prog8lib/cx16/syslib.p8 index fc51070bd..045d1636a 100644 --- a/compiler/res/prog8lib/cx16/syslib.p8 +++ b/compiler/res/prog8lib/cx16/syslib.p8 @@ -2141,6 +2141,32 @@ save_SCRATCH_ZPWORD2 .word ? }} } + inline asmsub pushl(long value @R0R1_32) { + %asm {{ + lda cx16.r0 + pha + lda cx16.r0+1 + pha + lda cx16.r0+2 + pha + lda cx16.r0+3 + pha + }} + } + + inline asmsub popl() -> long @R0R1_32 { + %asm {{ + pla + sta cx16.r0+3 + pla + sta cx16.r0+2 + pla + sta cx16.r0+1 + pla + sta cx16.r0 + }} + } + asmsub cpu_is_65816() -> bool @A { ; -- Returns true when you have a 65816 cpu, false when it's a 6502. %asm {{ diff --git a/compiler/res/prog8lib/pet32/syslib.p8 b/compiler/res/prog8lib/pet32/syslib.p8 index b2b9e176d..cff92fb49 100644 --- a/compiler/res/prog8lib/pet32/syslib.p8 +++ b/compiler/res/prog8lib/pet32/syslib.p8 @@ -532,6 +532,32 @@ save_SCRATCH_ZPWORD2 .word ? }} } + inline asmsub pushl(long value @R0R1_32) { + %asm {{ + lda cx16.r0 + pha + lda cx16.r0+1 + pha + lda cx16.r0+2 + pha + lda cx16.r0+3 + pha + }} + } + + inline asmsub popl() -> long @R0R1_32 { + %asm {{ + pla + sta cx16.r0+3 + pla + sta cx16.r0+2 + pla + sta cx16.r0+1 + pla + sta cx16.r0 + }} + } + sub cpu_is_65816() -> bool { ; Returns true when you have a 65816 cpu, false when it's a 6502. return false diff --git a/compiler/res/prog8lib/virtual/syslib.p8 b/compiler/res/prog8lib/virtual/syslib.p8 index 2cd51bd53..f00a4b2d4 100644 --- a/compiler/res/prog8lib/virtual/syslib.p8 +++ b/compiler/res/prog8lib/virtual/syslib.p8 @@ -192,6 +192,14 @@ sys { }} } + sub pushl(long l) { + ; note: this *should* be inlined, however since the VM has separate program counter and value stacks, this also works + %ir {{ + loadm.l r99200,sys.pushl.l + push.l r99200 + }} + } + sub push_returnaddress(uword w) { ; note: this actually doesn't do anything useful on the VM because the code execution doesn't use the simulated cpu stack %ir {{ @@ -222,6 +230,14 @@ sys { }} } + sub popl() -> long { + ; note: this *should* be inlined, however since the VM has separate program counter and value stacks, this also works + %ir {{ + pop.l r99200 + returnr.l r99200 + }} + } + sub read_flags() -> ubyte { ; "simulate" the 6502 status register a little bit if_neg { diff --git a/compiler/src/prog8/compiler/astprocessing/Utility.kt b/compiler/src/prog8/compiler/astprocessing/Utility.kt index d4aaba45d..649c906aa 100644 --- a/compiler/src/prog8/compiler/astprocessing/Utility.kt +++ b/compiler/src/prog8/compiler/astprocessing/Utility.kt @@ -12,6 +12,7 @@ internal fun makePushPopFunctionCalls(value: PtExpression): Pair { @@ -29,13 +30,14 @@ internal fun makePushPopFunctionCalls(value: PtExpression): Pair {} value.type.isUnsignedWord -> pushWord = true + value.type.isLong -> pushLong = true value.type.isPassByRef -> pushWord = true value.type.isFloat -> pushFloat = true else -> throw FatalAstException("unsupported return value type ${value.type} with defer") } - val pushFunc = if(pushFloat) "floats.push" else if(pushWord) "sys.pushw" else "sys.push" - val popFunc = if(pushFloat) "floats.pop" else if(pushWord) "sys.popw" else "sys.pop" + val pushFunc = if(pushFloat) "floats.push" else if(pushWord) "sys.pushw" else if (pushLong) "sys.pushl" else "sys.push" + val popFunc = if(pushFloat) "floats.pop" else if(pushWord) "sys.popw" else if(pushLong) "sys.popl" else "sys.pop" val pushCall = PtFunctionCall(pushFunc, true, DataType.UNDEFINED, value.position) if(pushTypecast!=null) { val typecast = PtTypeCast(pushTypecast, value.position).also { @@ -47,7 +49,7 @@ internal fun makePushPopFunctionCalls(value: PtExpression): Pair2) datatype = BaseDataType.UWORD try { - integer = literalText.toInt(16) + integer = literalText.lowercase().toLong(16).toInt() } catch(x: NumberFormatException) { throw SyntaxError("invalid hexadecimal literal ${x.message}", ctx.toPosition()) } diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index 3fe28a8b8..c13a16a69 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -1177,12 +1177,19 @@ sys (part of syslib) This allows other code to run that might clobber these values temporarily. ``push (value)`` - pushes a byte value on the CPU hardware stack. Low-level function that should normally not be used. + pushes a byte value on the CPU hardware stack. + Low-level function that is seldomly used in user code. ``pushw (value)`` - pushes a 16-bit word value on the CPU hardware stack. Low-level function that should normally not be used. + pushes a 16-bit word value on the CPU hardware stack. + Low-level function that is seldomly used in user code. Don't assume anything about the order in which the bytes are pushed - popw will make sense of them again. +``pushl (value)`` + pushes a 32-bit value on the CPU hardware stack. + Low-level function that is seldomly used in user code. + Don't assume anything about the order in which the bytes are pushed - popl will make sense of them again. + ``push_returnaddress (address)`` pushes a 16 bit memory address on the CPU hardware stack in the same byte order as a JSR instruction would, which means the next RTS instruction will jump to that address instead.you @@ -1190,11 +1197,15 @@ sys (part of syslib) ``pop ()`` pops a byte value off the CPU hardware stack and returns it. - Low-level function that should normally not be used. + Low-level function that is seldomly used in user code. ``popw ()`` pops a 16-bit word value off the CPU hardware stack that was pushed before by pushw, and returns it. - Low-level function that should normally not be used. + Low-level function that is seldomly used in user code. + +``popl ()`` + pops a 32-bit value off the CPU hardware stack that was pushed before by pushl, and returns it. + Low-level function that is seldomly used in user code. textio (txt.*) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 2d256c9ac..5252f6ebf 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,8 +3,7 @@ TODO LONG TYPE --------- -= add pushl popl -- scan through more library routines if there are opportunities to use the long? +- scan through more library routines if there are opportunities to use a long param or returnvalue? - document the new long type! and mklong(a,b,c,d) and mklong2(w1,w2) , print_l , print_ulhex (& conv.str_l) and pokel, peekl, cbm.SETTIML/RDTIML, and the use of R0:R1 when doing LONG calculations - asmsub call convention: @R0R1_32 to specify a 32 bits long combined register R0:R1 - how hard is it to also implement the other comparison operators (<,>,<=,>=) on longs? diff --git a/examples/customtarget/libraries/atari/syslib.p8 b/examples/customtarget/libraries/atari/syslib.p8 index 4c60d85bf..24d6f403e 100644 --- a/examples/customtarget/libraries/atari/syslib.p8 +++ b/examples/customtarget/libraries/atari/syslib.p8 @@ -411,6 +411,32 @@ save_SCRATCH_ZPWORD2 .word ? }} } + inline asmsub pushl(long value @R0R1_32) { + %asm {{ + lda cx16.r0 + pha + lda cx16.r0+1 + pha + lda cx16.r0+2 + pha + lda cx16.r0+3 + pha + }} + } + + inline asmsub popl() -> long @R0R1_32 { + %asm {{ + pla + sta cx16.r0+3 + pla + sta cx16.r0+2 + pla + sta cx16.r0+1 + pla + sta cx16.r0 + }} + } + sub cpu_is_65816() -> bool { ; Returns true when you have a 65816 cpu, false when it's a 6502. return false diff --git a/examples/customtarget/libraries/f256/syslib.p8 b/examples/customtarget/libraries/f256/syslib.p8 index f6369e2d8..169563c8c 100644 --- a/examples/customtarget/libraries/f256/syslib.p8 +++ b/examples/customtarget/libraries/f256/syslib.p8 @@ -672,6 +672,32 @@ save_SCRATCH_ZPWORD2 .word ? }} } + inline asmsub pushl(long value @R0R1_32) { + %asm {{ + lda cx16.r0 + pha + lda cx16.r0+1 + pha + lda cx16.r0+2 + pha + lda cx16.r0+3 + pha + }} + } + + inline asmsub popl() -> long @R0R1_32 { + %asm {{ + pla + sta cx16.r0+3 + pla + sta cx16.r0+2 + pla + sta cx16.r0+1 + pla + sta cx16.r0 + }} + } + sub cpu_is_65816() -> bool { ; Returns true when you have a 65816 cpu, false when it's a 6502. return false diff --git a/examples/customtarget/libraries/neo6502/syslib.p8 b/examples/customtarget/libraries/neo6502/syslib.p8 index cebc2f2eb..9370df077 100644 --- a/examples/customtarget/libraries/neo6502/syslib.p8 +++ b/examples/customtarget/libraries/neo6502/syslib.p8 @@ -344,6 +344,32 @@ save_SCRATCH_ZPWORD2 .word ? }} } + inline asmsub pushl(long value @R0R1_32) { + %asm {{ + lda cx16.r0 + pha + lda cx16.r0+1 + pha + lda cx16.r0+2 + pha + lda cx16.r0+3 + pha + }} + } + + inline asmsub popl() -> long @R0R1_32 { + %asm {{ + pla + sta cx16.r0+3 + pla + sta cx16.r0+2 + pla + sta cx16.r0+1 + pla + sta cx16.r0 + }} + } + sub cpu_is_65816() -> bool { ; Returns true when you have a 65816 cpu, false when it's a 6502. return false diff --git a/examples/customtarget/libraries/tinyc64/syslib.p8 b/examples/customtarget/libraries/tinyc64/syslib.p8 index ae962fa56..bc6eae093 100644 --- a/examples/customtarget/libraries/tinyc64/syslib.p8 +++ b/examples/customtarget/libraries/tinyc64/syslib.p8 @@ -49,6 +49,32 @@ sys { }} } + inline asmsub pushl(long value @R0R1_32) { + %asm {{ + lda cx16.r0 + pha + lda cx16.r0+1 + pha + lda cx16.r0+2 + pha + lda cx16.r0+3 + pha + }} + } + + inline asmsub popl() -> long @R0R1_32 { + %asm {{ + pla + sta cx16.r0+3 + pla + sta cx16.r0+2 + pla + sta cx16.r0+1 + pla + sta cx16.r0 + }} + } + asmsub reset_system() { ; Soft-reset the system back to initial power-on Basic prompt. %asm {{ diff --git a/examples/customtarget/libraries/tinycx16/syslib.p8 b/examples/customtarget/libraries/tinycx16/syslib.p8 index d07cf4634..eaf836236 100644 --- a/examples/customtarget/libraries/tinycx16/syslib.p8 +++ b/examples/customtarget/libraries/tinycx16/syslib.p8 @@ -49,6 +49,32 @@ sys { }} } + inline asmsub pushl(long value @R0R1_32) { + %asm {{ + lda cx16.r0 + pha + lda cx16.r0+1 + pha + lda cx16.r0+2 + pha + lda cx16.r0+3 + pha + }} + } + + inline asmsub popl() -> long @R0R1_32 { + %asm {{ + pla + sta cx16.r0+3 + pla + sta cx16.r0+2 + pla + sta cx16.r0+1 + pla + sta cx16.r0 + }} + } + asmsub reset_system() { ; Soft-reset the system back to initial power-on Basic prompt. ; We do this via the SMC so that a true reset is performed that also resets the Vera fully. diff --git a/examples/customtarget/libraries/tinypet/syslib.p8 b/examples/customtarget/libraries/tinypet/syslib.p8 index ed88fe11a..7d70fc1cf 100644 --- a/examples/customtarget/libraries/tinypet/syslib.p8 +++ b/examples/customtarget/libraries/tinypet/syslib.p8 @@ -49,6 +49,32 @@ sys { }} } + inline asmsub pushl(long value @R0R1_32) { + %asm {{ + lda cx16.r0 + pha + lda cx16.r0+1 + pha + lda cx16.r0+2 + pha + lda cx16.r0+3 + pha + }} + } + + inline asmsub popl() -> long @R0R1_32 { + %asm {{ + pla + sta cx16.r0+3 + pla + sta cx16.r0+2 + pla + sta cx16.r0+1 + pla + sta cx16.r0 + }} + } + asmsub reset_system() { ; Soft-reset the system back to initial power-on Basic prompt. %asm {{ diff --git a/examples/test.p8 b/examples/test.p8 index 96c098b52..0940c5198 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,13 +1,16 @@ %import textio %zeropage basicsafe -%import bcd main { sub start() { - cbm.SETTIML($12fe56) - repeat { - txt.home() - txt.print_ulhex(cbm.RDTIML(), false) - } + sys.pushl($aabb1234) + long lv = sys.popl() + txt.print_ulhex(lv, false) + +; cx16.r0 = sys.popw() +; cx16.r1 = sys.popw() + +; txt.print_uwhex(cx16.r0, false) +; txt.print_uwhex(cx16.r1, false) } } diff --git a/intermediate/src/prog8/intermediate/IRInstructions.kt b/intermediate/src/prog8/intermediate/IRInstructions.kt index 028781278..ec4e60f68 100644 --- a/intermediate/src/prog8/intermediate/IRInstructions.kt +++ b/intermediate/src/prog8/intermediate/IRInstructions.kt @@ -14,6 +14,7 @@ Program to execute is not stored in the system memory, it's just a separate list 100K virtual registers, 16 bits wide, can also be used as 8 bits. r0-r99999 reserved 99000 - 99099 : WORD registers for syscall arguments and response value(s) reserved 99100 - 99199 : BYTE registers for syscall arguments and response value(s) + reseverd 99200 - 99299 : LONG registers for syscall arguments and response value(s) 100K virtual floating point registers (64 bits double precision) fr0-fr99999 65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits. Value stack, max 128 entries of 1 byte each. diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index d25dd7202..4f8f1f63f 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -3141,7 +3141,7 @@ internal fun ArrayDeque.popl(): Int { val b1 = removeLast().toUInt() val b2 = removeLast().toUInt() val b3 = removeLast().toUInt() - return (b0 shl 24 or b1 shl 16 or b2 shl 8 or b3).toInt() + return ((b0 shl 24) or (b1 shl 16) or (b2 shl 8) or b3).toInt() } internal fun ArrayDeque.popf(): Double {