Mercurial > hg > index.cgi
diff src/stack.s @ 119:a6a53e5c04bd
Make a call stack implementation that is more complete and maybe cleaner.
author | William Astle <lost@l-w.ca> |
---|---|
date | Fri, 29 Dec 2023 01:40:39 -0700 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/stack.s Fri Dec 29 01:40:39 2023 -0700 @@ -0,0 +1,80 @@ + *pragmapush list + *pragma list +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Call stack management. +; +; The call stack exists above the interpreter stack. The call stack consists of a sequence of stack records of varying +; sizes which start with an 8 bit length field, then the payload, which will usually begin with an 8 bit type code. The +; bottom of the call stack is stored in cstackptr. The frame sizes must all be <= 125 bytes since a 2 byte frame header +; will be included in the sizing +; +; Allocate a call stack frame of size B and type A. Return a pointer to the payload area of the allocated entry in U +cstack_alloc pshs a ; save type flag + addb #2 ; account for the frame header + negb ; so we can subtract from pointers + leax ,s ; point to current stack pointer + leas b,s ; move the stack pointer down + leau ,s ; point to new stack pointer for data copy +cstack_alloc0 lda ,x+ ; copy a byte in the stack down + sta ,y+ + cmpx cstackptr ; have we reached the original call stack? + bne cstack_alloc0 ; brif not + negb ; get back original size + stu cstackptr ; save the new bottom of the call stack + stb ,u++ ; save size in entry + puls a ; get back type flag + sta -11,u ; put it in the stack frame +cstack_pop0 rts +; Clear call stack without resetting the interpreter stack +cstack_clear ldd stringtab ; point to the bottom of the string space + subd #1 ; make room for a NULL stack frame marking the top of the stack +cstack_pop1 tfr d,u ; save new call stack pointer - destination of copy + subd cstackptr ; subtract out the current call stack pointer + beq cstack_clear1 ; brif the stack is already empty + tfr d,y ; save byte count to move in counter + sts ,--s ; save the current stack pointer - end of copy address + ldx cstackptr ; get current call stack pointer - source of copy + stu cstackptr ; save new call stack pointer + clr ,u ; put the NULL frame at the top of the call stack +cstack_clear0 lda ,-x ; copy a byte upward + sta ,-u + cmpx ,s ; have we reached the end of the copy? + bne cstack_clear0 ; brif not + leas ,u ; reset the main stack to the moved location +cstack_clear1 rts +; Pop the entry pointed to by U off the call stack and all entries below it +cstack_popto ldb ,u ; get size of the current entry + bra cstack_popto0 ; go do the rest of the processing +; Pop the first entry off the call stack +cstack_pop ldu cstackptr ; point to the call stack + ldb ,u ; get size of this frame + beq cstack_pop0 ; brif there's nothing to pop - do nothing +cstack_popto0 leau b,u ; point to the next entry + tfr u,d ; put pointer where we need it + bra cstack_pop1 ; go adjust the call stack +; Search for the first matching stack frame where the second byte matches the value in A. Enter +; at cstack_searchnext to search from the entry following the entry pointed to by X. Return with +; C set if not found. +cstack_search ldx cstackptr ; point to the call stack +cstack_search0 ldb ,x ; get size of this entry + bne cstack_search2 ; brif not the end of the call stack +cstack_search1 comb ; clear C for not found + rts +cstack_search2 cmpa 1,x ; does the type match? + bne cstack_search3 ; brif not + rts ; return result (C is clear from CMPA match) +cstack_searchnext + ldb ,x ; get length of this frame + beq cstack_search1 ; brif we're already at the end of the stack +cstack_search3 abx ; move to next entry + bra cstack_search0 ; check if this one matches +; Point X to the first entry on the call stack +cstack_first ldx cstackptr ; point to stack entry + lda ,x++ ; set Z set if end of stack, move to payload + rts +; Point X to the next entry on the call stack +cstack_next ldb -2,x ; get length of this entry + abx ; adjust to next entry payload + ldb -2,x ; set Z if end of stack + rts + *pragmapop list