added sys.pushl() and sys.popl()

This commit is contained in:
Irmen de Jong
2025-10-04 02:27:05 +02:00
parent 0e177cb531
commit efff74c0f1
18 changed files with 309 additions and 17 deletions

View File

@@ -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.

View File

@@ -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.

View File

@@ -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 {{

View File

@@ -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

View File

@@ -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 {

View File

@@ -12,6 +12,7 @@ internal fun makePushPopFunctionCalls(value: PtExpression): Pair<PtFunctionCall,
var pushTypecast: DataType? = null
var pushWord = false
var pushFloat = false
var pushLong = false
when {
value.type.isBool -> {
@@ -29,13 +30,14 @@ internal fun makePushPopFunctionCalls(value: PtExpression): Pair<PtFunctionCall,
}
value.type.isUnsignedByte -> {}
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): Pair<PtFunctionCall,
}
val popCall = if(popTypecast!=null) {
PtTypeCast(popTypecast, value.position).also {
val returnDt = if(pushWord) DataType.UWORD else DataType.UBYTE
val returnDt = if(pushWord) DataType.UWORD else if(pushLong) DataType.LONG else if(pushFloat) DataType.FLOAT else DataType.UBYTE
it.add(PtFunctionCall(popFunc, false, returnDt, value.position))
}
} else

View File

@@ -372,7 +372,7 @@ class Antlr2KotlinVisitor(val source: SourceCode): AbstractParseTreeVisitor<Node
else if(literalText.length>2)
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())
}

View File

@@ -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.*)

View File

@@ -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?

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {{

View File

@@ -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.

View File

@@ -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 {{

View File

@@ -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)
}
}

View File

@@ -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.

View File

@@ -3141,7 +3141,7 @@ internal fun ArrayDeque<UByte>.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<UByte>.popf(): Double {