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 { sub cpu_is_65816() -> bool {
; Returns true when you have a 65816 cpu, false when it's a 6502. ; Returns true when you have a 65816 cpu, false when it's a 6502.
; The SuperCPU expansion for the C64/C128 contains a 65816. ; 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 { sub cpu_is_65816() -> bool {
; Returns true when you have a 65816 cpu, false when it's a 6502. ; Returns true when you have a 65816 cpu, false when it's a 6502.
; The SuperCPU expansion for the C64/C128 contains a 65816. ; 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 { asmsub cpu_is_65816() -> bool @A {
; -- Returns true when you have a 65816 cpu, false when it's a 6502. ; -- Returns true when you have a 65816 cpu, false when it's a 6502.
%asm {{ %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 { sub cpu_is_65816() -> bool {
; Returns true when you have a 65816 cpu, false when it's a 6502. ; Returns true when you have a 65816 cpu, false when it's a 6502.
return false 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) { 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 ; note: this actually doesn't do anything useful on the VM because the code execution doesn't use the simulated cpu stack
%ir {{ %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 { sub read_flags() -> ubyte {
; "simulate" the 6502 status register a little bit ; "simulate" the 6502 status register a little bit
if_neg { if_neg {

View File

@@ -12,6 +12,7 @@ internal fun makePushPopFunctionCalls(value: PtExpression): Pair<PtFunctionCall,
var pushTypecast: DataType? = null var pushTypecast: DataType? = null
var pushWord = false var pushWord = false
var pushFloat = false var pushFloat = false
var pushLong = false
when { when {
value.type.isBool -> { value.type.isBool -> {
@@ -29,13 +30,14 @@ internal fun makePushPopFunctionCalls(value: PtExpression): Pair<PtFunctionCall,
} }
value.type.isUnsignedByte -> {} value.type.isUnsignedByte -> {}
value.type.isUnsignedWord -> pushWord = true value.type.isUnsignedWord -> pushWord = true
value.type.isLong -> pushLong = true
value.type.isPassByRef -> pushWord = true value.type.isPassByRef -> pushWord = true
value.type.isFloat -> pushFloat = true value.type.isFloat -> pushFloat = true
else -> throw FatalAstException("unsupported return value type ${value.type} with defer") 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 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 "sys.pop" 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) val pushCall = PtFunctionCall(pushFunc, true, DataType.UNDEFINED, value.position)
if(pushTypecast!=null) { if(pushTypecast!=null) {
val typecast = PtTypeCast(pushTypecast, value.position).also { val typecast = PtTypeCast(pushTypecast, value.position).also {
@@ -47,7 +49,7 @@ internal fun makePushPopFunctionCalls(value: PtExpression): Pair<PtFunctionCall,
} }
val popCall = if(popTypecast!=null) { val popCall = if(popTypecast!=null) {
PtTypeCast(popTypecast, value.position).also { 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)) it.add(PtFunctionCall(popFunc, false, returnDt, value.position))
} }
} else } else

View File

@@ -372,7 +372,7 @@ class Antlr2KotlinVisitor(val source: SourceCode): AbstractParseTreeVisitor<Node
else if(literalText.length>2) else if(literalText.length>2)
datatype = BaseDataType.UWORD datatype = BaseDataType.UWORD
try { try {
integer = literalText.toInt(16) integer = literalText.lowercase().toLong(16).toInt()
} catch(x: NumberFormatException) { } catch(x: NumberFormatException) {
throw SyntaxError("invalid hexadecimal literal ${x.message}", ctx.toPosition()) 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. This allows other code to run that might clobber these values temporarily.
``push (value)`` ``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)`` ``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. 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)`` ``push_returnaddress (address)``
pushes a 16 bit memory address on the CPU hardware stack in the same byte order as a JSR instruction would, 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 which means the next RTS instruction will jump to that address instead.you
@@ -1190,11 +1197,15 @@ sys (part of syslib)
``pop ()`` ``pop ()``
pops a byte value off the CPU hardware stack and returns it. 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 ()`` ``popw ()``
pops a 16-bit word value off the CPU hardware stack that was pushed before by pushw, and returns it. 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.*) textio (txt.*)

View File

@@ -3,8 +3,7 @@ TODO
LONG TYPE LONG TYPE
--------- ---------
= add pushl popl - scan through more library routines if there are opportunities to use a long param or returnvalue?
- scan through more library routines if there are opportunities to use the long?
- 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 - 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 - 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? - 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 { sub cpu_is_65816() -> bool {
; Returns true when you have a 65816 cpu, false when it's a 6502. ; Returns true when you have a 65816 cpu, false when it's a 6502.
return false 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 { sub cpu_is_65816() -> bool {
; Returns true when you have a 65816 cpu, false when it's a 6502. ; Returns true when you have a 65816 cpu, false when it's a 6502.
return false 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 { sub cpu_is_65816() -> bool {
; Returns true when you have a 65816 cpu, false when it's a 6502. ; Returns true when you have a 65816 cpu, false when it's a 6502.
return false 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() { asmsub reset_system() {
; Soft-reset the system back to initial power-on Basic prompt. ; Soft-reset the system back to initial power-on Basic prompt.
%asm {{ %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() { asmsub reset_system() {
; Soft-reset the system back to initial power-on Basic prompt. ; 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. ; 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() { asmsub reset_system() {
; Soft-reset the system back to initial power-on Basic prompt. ; Soft-reset the system back to initial power-on Basic prompt.
%asm {{ %asm {{

View File

@@ -1,13 +1,16 @@
%import textio %import textio
%zeropage basicsafe %zeropage basicsafe
%import bcd
main { main {
sub start() { sub start() {
cbm.SETTIML($12fe56) sys.pushl($aabb1234)
repeat { long lv = sys.popl()
txt.home() txt.print_ulhex(lv, false)
txt.print_ulhex(cbm.RDTIML(), 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 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 99000 - 99099 : WORD registers for syscall arguments and response value(s)
reserved 99100 - 99199 : BYTE 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 100K virtual floating point registers (64 bits double precision) fr0-fr99999
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits. 65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
Value stack, max 128 entries of 1 byte each. 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 b1 = removeLast().toUInt()
val b2 = removeLast().toUInt() val b2 = removeLast().toUInt()
val b3 = 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 { internal fun ArrayDeque<UByte>.popf(): Double {