     .orig x3000

; program calls sum, a recursive subroutine that
; calculates the sum of the ints from 0 to n

	lea	r6, stackbase	;r6 is the stackpointer
	and	r0, r0, #0
	add	r0, r0, #3	;pass 3 as the argument to sum
				;(0 + 1 + 2 + 3)
	jsr	push
	jsr	sum

	halt			;sum returns answer 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
; each activation record for the stack consists of the argument,
; the old frame pointer (R5) and the return address (R7)
; the current frame pointer points to the old frame pointer
;
; sum returns its answer to the caller in R1
; note:  sum destroys R4

sum	add	r0, r7, #0	;push caller's return address
	jsr	push

	add	r0, r5, #0	;push caller's frame
	jsr	push
	add	r5, r6, #0	;set new value for frame pointer
	
	ldr	r0, r5, #2	;pick up argument to this call
	brp	cont		;argument > 0?
	and	r1, r1, #0	;no, arg==0, set sum=0...
	brnzp	done		; ...and return (base case)

cont	add	r0, r0, -1	;yes, arg>0, call sum(n-1)
	jsr	push		;push new argument on stack
	jsr	sum		;make recursive call

	ldr	r0, r5, #2	;pick up argument to add to sum
	add	r1, r1, r0	;add it in

done	jsr	pop		;pop caller's frame pointer
	add	r5, r0, #0	;and put it into R5

	jsr	pop		;pop return address
	add	r4, r0, #0      ;(can't put it in R7 yet because
				; we need to do another JSR - use R4)
	jsr	pop		;pop off argument (it has already been added in)

	add	r7, r4, #0	;restore return to caller
	ret

; 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
stackbase	.fill x0000
	.end

