A jump table

Four addresses in memory, an index that picks one of them, and a jr through a register instead of a chain of comparisons.

A number picks which of four pieces of code runs. t2 holds 2, the program reads the third address out of a table in memory and jumps to it, and the multiplication is what happens. Changing t2 changes the answer without changing a comparison anywhere.

The bigger of two numbers chose between two paths with a blt. A chain of those works for three or four cases and gets slower with every one you add, since a value at the bottom of the chain is compared against everything above it first. A table is looked up once whatever the value is.

You need to know: the "Branch on compare" lecture and the "Loads, stores and immediates" lecture. What is new here is a jump to an address the program worked out, jr t5 goes to whatever t5 holds, which nothing in the source names.

.word add_op, sub_op, mul_op, div_op writes four words, and each one is the address the assembler gave that label. Put the memory panel on 10010000 and they read 00400024, 0040002C, 00400034 and 0040003C, which are four addresses inside your own code. A label is nothing but an address, and this is what that sentence is for.

The three instructions before the jr are C's table[op]: multiply the index by the size of an element with a shift, add it to the base, and read the word there. What comes out is an address, and jr is the same instruction that returns from a subroutine, since ret is jalr zero, ra, 0 and jr t5 is jalr zero, t5, 0. Writing jalr t5 instead would make this four calls rather than a switch, because that form writes the return address into ra on the way.

t6 comes out at 00000012, which is 18, and t5 at 00400034, the address of mul_op. Each arm ends with j done for the same reason the two halves of an if do: the arms are laid out one after another and nothing stops the program running into the next one.

All four arms are one real instruction each. mul and div are the M extension, which this simulator has, and they behave like any other instruction here; MIPS spells its three operand div as a pseudo-instruction that expands to four, a bne and a break checking the divisor before the real division.

Try changing li t2, 2 to li t2, 3 and t6 comes out at 2, which is 6 divided by 3. With 0 it comes out at 9 and with 1 at 3. Nothing else in the program moves, and there is no comparison anywhere in it to change.