## LSU EE 4720
#
## Recursion example.
#
# Factorial procedure written recursively. (Inefficient, but easy to
# understand.)
#
# Presented in class 1 October 2004
# Linkage (register usage) Rules for this Example:
#
# Caller Save: $tX, $fX, $aX (if caller will need values after return).
# Callee Save: $ra, $sX
.data
ONE:
.double 1.0
MSG:
.asciiz "%/s0/d! = %/f0/.0f\n"
.text
.globl __start
__start:
addi $s0, $0, 0
MAINLOOP:
mtc1 $s0, $f2
jal fact
cvt.d.w $f2, $f2
la $a0, MSG
addi $v0, $0, 11
syscall
slti $t0, $s0, 20
bne $t0, $0, MAINLOOP
addi $s0, $s0, 1
addi $v0, $0, 10
syscall
################################################################################
## fact: Factorial
#
# Load constant 1.0 into register f4 and call fact1, which computes factorial.
#
fact:
## Register Usage
#
# CALL VALUE: $f2/$f2 Number, n, double.
# RETURN VALUE: $f0/$f1 n! (0! = 1! = 1), double.
# Save $ra on the stack.
#
sw $ra, -4($sp)
addi $sp, $sp, -4 # Move stack pointer above saved registers.
la $t0, ONE
jal fact1
ldc1 $f4, 0($t0)
# Restore $ra from stack and restore stack pointer.
#
addi $sp, $sp, 4
lw $ra, -4($sp)
jr $ra
nop
################################################################################
## fact1: Factorial
#
# Return $f2! in $f0.
#
fact1:
## Register Usage
#
# CALL VALUE: $f2/$f3 Number, n, double.
# CALL VALUE: $f4/$f5 1.0, double. (Used as a constant.)
# RETURN VALUE: $f0/$f1 n! (0! = 1! = 1)
#
# Save $ra and $f2 on stack.
#
# $f4 is not saved because we know the called routine (this one)
# won't modify it.
#
sdc1 $f2, -8($sp)
sw $ra, -12($sp)
addi $sp, $sp, -12
#
# If n <= 1 return a 1. (Assume n is 0 or 1.)
#
c.le.d $f2, $f4
bc1t F1DONE
mov.d $f0, $f4
#
# Recursive call and factorial computation.
#
jal fact1
sub.d $f2, $f2, $f4 # n_for_called_routine = n - 1
ldc1 $f2, 4($sp) # Get "our" value of n from stack.
mul.d $f0, $f0, $f2
F1DONE:
#
# Restore $ra and $sp.
#
# (Register $f2 was restored above, where needed.)
#
addi $sp, $sp, 12
lw $ra, -12($sp)
jr $ra
nop