; lips example code: fibonacci numbers ; this isn't a particularily useful or realistic example, ; but it demonstrates syntax and various features in lips. [max_n]: 47 fib: ; calculate the nth fibonacci number, memoizing results 1 to 47 in a table. ; only valid for values of n between 0 and 47 inclusive. ; a0: n ; v0: Fn ; branch to return 0 if a0 <= 0. ; the + refers to the next + label, relative to here. ; ++ would refer to the + label after that, and so on. blez a0, + ; note that this executes even if the branch is taken, ; due to the single delay slot of this MIPS CPU. ; pseudo-instruction clears (sets to 0) the 32-bit value of a register: cl v0 ; check if the input is within the bounds specified earlier. ; pseudo-instruction to branch if register > immediate: bgti a0, @max_n, + ; offset the input for use with the look-up table. ; note that this executes even if the branch is taken, ; but won't break the functionality of the routine either way. ; pseudo-instruction translates into an addiu with a negated immediate: subiu t0, a0, 1 ; multiply by sizeof(word) which is 4, or 1 << 2. sll t0, t0, 2 ; load the value from the look-up table. ; pseudo-instruction utilizing addressing modes: lw t9, fib_memo(t0) ; branch to return the look-up value if it's non-zero, ; meaning it has been memoized. bnez t9, + ; once again, note that this is the delay slot of the branch instruction. ; pseudo-instruction to copy the 32-bit value of one register to another: mov v0, t9 ; set up the following loop to calculate the fibonacci number. ; pseudo-instruction to load a 32-bit value into a register: li t1, 0 ; F(0) li t2, 1 ; F(1) -: ; here's a - label referred to later. ; - labels are like + labels, except ; they look upwards in the file instead of downwards. ; calculate the next fibonacci number. addu t3, t1, t2 ; push the previous values back, part 1. mov t1, t2 ; iterate to the next number. subiu a0, a0, 1 ; loop if it hasn't yet reached the nth fibonacci number. bnez a0, - ; push the previous values back, part 2. ; this is put in the branch delay as a simple optimization. mov t2, t3 ; loop finished, copy the result to return. mov v0, t1 ; memoize the result for next time. ; pseudo-instruction not unlike the previous lw: sw v0, fib_memo(t0) ; here's the + label used at the start of the routine. +: ; return to the function that called this routine. ; when jr is given without any arguments, `jr ra` is implied. jr ; there's nothing to do in the delay slot, so don't do anything. ; this is necessary, otherwise the next instruction or data ; following the routine would be executed. ; pseudo-instruction to do nothing: nop ; set up initial values in the look-up table. fib_memo: ; lips doesn't yet have a way to specify "x, n times", ; so this will do for now. .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .word 0, 0, 0, 0, 0, 0, 0