; > Stack
; BASIC stack manipulation

; UnstackIntAndCallOp
; ===================
.UnstackIntAndCallOp
; On entry, r2/r3/r4=RHS value
;           sp=> retaddr, operator, type, b0-b15, b16-b31
;           sp=> retaddr, operator, type, length, string...
;
jsr  pc,EnsureInteger	; If RHS value float, convert to integer


; UnstackValAndCallOp
; ===================
.UnstackValAndCallOp
			; sp=> retaddr, operator, type, b0-b15, b16-b31
			; sp=> retaddr, operator, type, length, string...
mov  2(sp),r0		; Get operator to r0
mov  (sp)+,r1		; sp=> operator, type, b0-b15, b16-b31   r1=retaddr
mov  r1,(sp)		; sp=> retaddr, type, b0-b15, b16-b31
			; sp=> retaddr, type, length, string
cmp  r0,#ASC"+"
beq  EvalFuncPlus	; '+' allowed to operate on strings
bit  r2,2(sp)
bmi  errTypeMis2	; Other operations must be <number> <op> <number>
.EvalFuncPlus
bit  #&80,r0
bne  EvalFunction	; Dispatch 'AND'..'OR'
sub  #3,r0		; Reduce range for '*'..'/','^'
bic  #&FFF0,r0		; Reduce to 7..15

; EvalFunction - dispatch a function token
; ----------------------------------------
.EvalFunction
bic  #&FF80,r0		; Reduce range
add  r0,r0		; Offset into command table
adr  FunctionTable,r1	; Point to command address table
add  r0,r1		; Index into command table
add  (r1),r1		; Calculate routine address
jsr  pc,SkipSpaces	; r5=>next char, r0=next char
jmp  (r1)		; Jump to function routine


.UnstackStringDropOp
; On entry, sp=> retaddr, op, type, length, string...
mov  (sp)+,(sp)		; Overwrite op with return address

; UnstackString - Pop a stacked string
; ====================================
; On entry, sp=> retaddr, type, length, string...
; On exit,  r4=string start
;           r3=string length
;           r2=type
;           r1=preserved
;           r0=preserved
;
.UnstackString
mov  sp,r2		; Point to stack
add  #6,r2		; Point to stacked string
			; Must prevent SP from being odd
adr  SV_STRING,r4	; Point to string buffer
mov  4(sp),r3		; Get length
beq  UnstackStrDone	; Zero-length string
.UnstackStrLp
movb (r2)+,(r4)+	; Copy bytes from stack
dec  r3
bne  UnstackStrLp	; Loop to 'pop' all characters
inc  r2
bic  #1,r2		; Align stack pointer
.UnstackStrDone
mov  (sp)+,r4		; Get return address
mov  2(sp),r3		; Get length
mov  r2,sp		; Update SP
mov  r4,-(sp)		; Push return address back
adr  SV_STRING,r4	; r4=start of string
mov  #&8000,r2		; r3=length, r2=string
rts  pc			; r1=preserved, r0=preserved


; StackValAndOp - Push a value and operator onto stack
; ====================================================
.StackValAndOp
tst  r2
bpl  StackNumAndOp


; StackStringAndOp - Push a string and operator onto stack
; ========================================================
; On entry, sp=> retaddr
;           r4=string start, r3=string length, r0=operation
; On exit,  sp=> operation, type, length, string...
;
.StackStringAndOp
mov  (sp)+,r1		; Get return address
mov  r3,r2		; Copy string length to byte count
bit  #1,r2		; Odd number of characters?
beq  StackStrGo
inc  r2			; Ensure even number
.StackStrGo
sub  r2,sp		; Drop stack to fit string
mov  r3,-(sp)		; Stack length
mov  #&8000,-(sp)	; Stack type
mov  r0,-(sp)		; Stack operation
tst  r3
beq  StackStrDone	; Zero-length string
mov  sp,r2		; Point to top of stack
add  #6,r2		; Point to start of string space
.StackStrLp
movb (r4)+,(r2)+	; Copy byte to stack
dec  r3
bne  StackStrLp		; Loop to 'push' all characters
.StackStrDone
jmp (r1)		; Return via r1


; StackIntAndOp - Push integer and operator onto stack
; ====================================================
; On entry, r2/r3/r4=current value
;           sp=> <empty>
; On exit,  r2/r3/r4 may be corruputed
;           sp=> operator, exponent, b0-b15, b16-b31
;                   r0        r2         r4      r3
;
.StackIntAndOp
jsr  pc,EnsureInteger	; If float, convert to integer
.StackNumAndOp		; sp=> retaddr
mov  r4,-(sp)		; sp=> r4, retaddr
mov  2(sp),r4		; sp=> r4, retaddr     r4=retaddr
mov  r3,2(sp)		; sp=> r4, r3          r4=retaddr
mov  r2,-(sp)		; sp=> r2, r4, r3      r4=retaddr
mov  r0,-(sp)		; sp=> r0, r2, r4, r3  r4=retaddr
mov  r4,pc		; Return

.errTypeMis2
jmp errTypeMismatch

