I would like to allocate some temporary words onto the stack for use in an assembly language function, and just want to make sure I do it right. Is it something like the code I have shown below? (Please consider putting a short example like this into the next revision of the compiler docs SPRU514.)
It looks like there are at least two ways to allocate stack space ("MOV *SP++, something" for initialized allocation = "push"; "ADDB SP, #something" for uninitialized allocation), at least two ways to deallocate stack space ("MOV something, *--SP" for a "pop", "SUBB SP, #something" for deallocation), and there are some subtleties with the *-SP[n] addressing mode:
- when is *-SP[0] ever valid? (if you push 3 onto the stack using MOV *SP++, #3, isn't it now stored in *-SP[1] since the stack pointer has been postincremented?)
- If I access a 32-bit value on the stack using "MOVL ACC, *-SP[2]" or "MOVL *-SP[2], ACC", does the CPU use *-SP[1] and *-SP[2], or does it use *-SP[2] and *-SP[3]?
- If my assembly function isn't going to call another function, are there any cases where stack pointer alignment matters?
; uint16_t myfunc(uint16_t *x)
; x is an array of 2 integers
; we return x[0] + x[1], clamped within the range [0, 31]
_myfunc:
; allocate 7 words onto the stack, for pedagogical purposes
; (we could do this more easily w/o the stack)
; *-SP[1] output
; *-SP[2:3] 31
; *-SP[4:5] 0
; *-SP[6] x[1]
; *-SP[7] x[2]
SETC SXM
; allocate+initialize local stack storage
MOV *SP++, *+XAR4[0]
MOV *SP++, *+XAR4[1]
MOV ACC, #0
MOVL *SP++, ACC
MOV ACC, #31
MOVL *SP++, ACC
; allocate an uninitialized word onto the stack
ADDB SP, #1
; perform computation
MOV ACC, *-SP[6]
ADD ACC, *-SP[7]
MINL ACC, *-SP[2]
MAXL ACC, *-SP[4]
MOV *-SP[1], AL
; now deallocate local stack storage
; move output into the accumulator
MOV AL, *--SP
SUBB SP,#6
LRETR