	.orig x3000

; program calls sum, a recursive subroutine that
; calculates the sum of the ints 0+1+...+n

	lea	r6, stackbase	; r6 is the stack pointer
	and	r0, r0, #0
	add	r0, r0, #3	; pass 3 as arg to sum (0+1+2+3=?)
	jsr	push
	jsr	sum
	halt			; sum 0+1+2+3=6 should be in R1

; sum is a recursive subroutine that calculates the sum 0+1+2+...+n
; where n is passed to the subroutine on the stack
; sum returns the sum in R1
	
sum	add	r0, r7, #0	; copy return address to R0
	jsr	push		; and push on the stack

	ldr	r0, r6, 1	; grab argument from stack
	brnp	cont		; argument = 0?
	and	r1, r1, #0	; yes, base case, return sum=0
	brnzp	done

cont	add	r0, r0, #-1	; no, argument != 0, call sum(n-1)
	jsr	push		; put new argument on stack
	jsr	sum		; make recursive call

	ldr	r0, r6, #1	; pick up argument to add to sum
	add	r1, r1, r0	; (it's on the stack)

done	jsr	pop		; pop return address to prepare to return
				; to previous level
	st	r0, savr7	; save temporarily (because r7 needs to be used
				; for next JSR)
	jsr	pop		; take argument off stack (this is the argument
				; that has most recently been added to the sum)
	ld	r7, savr7	; restore return address
	ret

savr7	.fill #0		; place to save return address

; note that these implementations for push and pop do not
; check for overflow or underflow
; stack pointer is in R6
; item to be push'd or pop'd is in R0

push	add	r6, r6, #-1
	str	r0, r6, #0
	ret

pop	ldr	r0, r6, #0
	add	r6, r6, #1
	ret

stackmax	.blkw #20	; area to hold items on the stack
stackbase	.fill x0000	; stack address
	.end
