Mercurial > hg > index.cgi
view 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 source
*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