Decisions
So far, we have only covered sequential execution. In other words, the instructions are executed in program order from top to bottom. Unfortunately, this is not enough to perform general computing tasks1. For general computing tasks, we need two additional constructs:
- Selection (i.e., making decision):
if
andswitch-case
. - Repetition (i.e., iterations):
while
,do-while
andfor
.
In MIPS, both selection and repetition are combined into a single construct similar to if
statement followed by a goto
.
Note that C has a goto
statement but it is highly discouraged2.
What these "decision making" instructions do is to alter the control flow of the program as well as change the next instruction to be executed.
For instance, it allows a certain sequence to be executed only if a certain condition occurs (i.e., selection via goto
downward) or a certain sequence to be executed multiple times until a certain condition is no longer valid (i.e., repetition via goto
upwards).
Label
There are two types of decision making statements in MIPS:
- Conditional (a.k.a., branch)
bne $t0, $t1, label
beq $t0, $t1, label
- Unconditional (a.k.a., jump)
j label
A label is an "anchor" in the assembly code to indicate a point of interest. This is usually a branch target but can also be used to indicate a logical grouping for the programmer. It is important to note that labels are NOT instructions.
You have seen one instance of label in the previous section:
Swap Elements (in MIPS) | |
---|---|
1 2 3 4 5 6 7 |
|
Here, the name swap
is a label.
It indicates that the code below it belongs to the same logical grouping for swapping.
The labels can be any name and will be removed from the code during assembly.
As such, its use is only for us programmers to understand the code better.
Label Naming
Since the use of label is for programmers, it is highly encouraged to use descriptive names for the labels.
Conditional Branch
Branch indicates that there are at least two possible choices for the path to take.
In this case, the processor follows the branch only when the condition is satisfied (i.e., true
).
There are two conditional branch instructions in MIPS depending on whether the condition should be based on equality or non-equality.
Conditional Branch
MIPS | |
---|---|
1 |
|
MipC | |
---|---|
1 2 3 |
|
Go to statement labeled label
if the value in register $rs
equals the value in register $rt
.
MIPS | |
---|---|
1 |
|
MipC | |
---|---|
1 2 3 |
|
Go to statement labeled label
if the value in register $rs
does not equal the value in register $rt
.
Although we show the possible MipC equivalent code, it is not exactly correct.
In this case, there is an implicit assumption that label
is after the current instruction.
Furthermore, there is a common trick to slightly optimise the code for selection.
More importantly, the conversion should be the other way around (i.e., MipC to MIPS).
Unconditional Jump
A jump indicates no choice. In this case, the processor always follows the branch.
Unconditional Jump
MIPS | |
---|---|
1 |
|
Go to statement labeled label
.
Technically, this is equivalent to ignoring the assembly and how far we can jump:
MIPS Equivalent | |
---|---|
1 |
|
Any register $reg
can be used as long as it is a valid register.
Inequalities
We have beq
and bne
, but what about if want to branch on inequalities?
For example, what if we want to branch when $rs
is less than $rt
?
There is no real blt
(i.e., branch on less than) instruction but there are several pseudo-instructions.
Pseudo-Instruction | Code | Operation |
---|---|---|
Branch on Less Than | blt $rs, $rt, label |
if($rs < $rt) then goto label |
Branch on Greater Than | bgt $rs, $rt, label |
if($rs > $rt) then goto label |
Branch on Less Than or Equal | ble $rs, $rt, label |
if($rs <= $rt) then goto label |
Branch on Greater Than or Equal | bge $rs, $rt, label |
if($rs >= $rt) then goto label |
In the end, it will still be translated into real instructions. What are the real instructions used in this case? Suprisingly, only one additional real instruction is needed to be able to translate all of the pseudo-instructions.
Set on Less Than
MIPS | |
---|---|
1 |
|
Set the value of $rd
to 1 if the value of $rs
is less than the value of $rt
.
Otherwise, set the value of $rd
to 0.
In C, it looks like the following:
Set on Less Than | |
---|---|
1 2 3 4 5 |
|
Given this additional instruction, we can now build the pseudo-instructions as follows:
Pseudo-Instruction Translation
blt $rs, $rt, label
We do the translation using an intermediate form: if (($rs < $rt) != 0) goto label
blt Translation | |
---|---|
1 2 |
|
bgt $rs, $rt, label
We do the translation using an intermediate form: if (($rt < $rs) != 0) goto label
bgt Translation | |
---|---|
1 2 |
|
ble $rs, $rt, label
We do the translation using an intermediate form: if (($rt < $rs) == 0) goto label
ble Translation | |
---|---|
1 2 |
|
bge $rs, $rt, label
We do the translation using an intermediate form: if (($rs < $rt) == 0) goto label
blt Translation | |
---|---|
1 2 |
|
Take a moment to understand the translation. If you are having problem understanding the translation, do click on the explanation below.
Translation Idea
Here, the comparison $rs < $rt
will be 1 if the condition is true.
So we simply check that the result is not equal to 0.
Then we can evaluate $rs > $rt
using slt
by swapping the two registers!
In other words:
1 2 |
|
For the ble
we simply do the negation.
1 2 3 4 |
|
Lastly, for the bge
we do the same trick as before again.
1 2 3 4 5 |
|
Examples
Selection Statement
If Statement
If Statement (in C) | |
---|---|
1 2 3 |
|
Variable | Register |
---|---|
f |
$s0 |
g |
$s1 |
h |
$s2 |
i |
$s3 |
j |
$s4 |
If Statement (in MipC) | |
---|---|
1 2 3 |
|
There are two equivalent translations. Click on the "Invert" tab to see the more efficient translation.
If Statement (in MIPS) | |
---|---|
1 2 3 4 |
|
If Statement (in MIPS) | |
---|---|
1 2 3 |
|
The efficient translation uses the common technique summarised below:
Inversion
Invert the selection condition for shorter code.
If-Else Statement
If-Else Statement (in C) | |
---|---|
1 2 3 4 5 |
|
Variable | Register |
---|---|
f |
$s0 |
g |
$s1 |
h |
$s2 |
i |
$s3 |
j |
$s4 |
If-Else Statement (in MipC) | |
---|---|
1 2 3 4 5 |
|
There are two equivalent translations. We will show the inversion translation and leave the direct translation for exercise.
If-Else Statement (in MIPS) | |
---|---|
1 2 3 4 5 |
|
Although inversion does not reduce the number of instructions, it helps make the translation uniform. The flowchart is given on the right.
Exercise
-
Translate the following C code fragments to MIPS without inversion.
Question 1 1 2 3 4 5
if (i == j) { f = g + h; } else { f = g - h; }
-
What is the corresponding high-level language statement for the following MIPS code?
Question 2 1 2 3
beq $s1, $s2, Exit add $s0, $zero, $zero Exit:
-
Since there is an
else
, direct translation can be with the same number of instructions.Answer 1 1 2 3 4 5
beq $s3, $s4, Then # simply goto then branch sub $s0, $s1, $s2 j Exit Then: add $s0, $s1, $s2 Exit:
Alternatively, you can first "rewrite" the code by swapping the then and else branch as shown below. Then you can use the inversion technique to produce the same code as above.
Rewrite 1 2 3 4 5
if (i != j) { f = g - h; // previously + } else { f = g + h; // previously - }
-
Note that the 3 lines code match more of the inversion technique rather than the direct translation technique. So, instead of
$s1 == $s2
, we should think in terms of$s1 != $s2
. What this means is that theadd
is only executed if the condition$s1 != $s2
evaluates tofalse
. Thisadd
also adds 2 zeroes which is equal to 0. A simple translation may be$s0 = 0 + 0;
but this is simply$s0 = 0;
. An intermediate MipC statement looks like the following:Intermediate MipC 1 2 3
if ($s1 != $s2) { $s0 = 0; }
Then, the answer after remapping to variable, is simply:
Answer 2 1 2 3
if (i != j) { f = 0; }
Repetition Statement
For the repetition statement, the MipC intermediate is not exactly useful as we designed the MipC to be quite close to C for these high-level constructs.
As such, in the examples below, we will simply show the MIPS instructions instead with explanation in a C with goto
.
While Loop
While-Loop Statement (in C) | |
---|---|
1 2 3 |
|
Variable | Register |
---|---|
i |
$s3 |
j |
$s4 |
k |
$s5 |
If we translate the code into a C statement with goto
, we get the following code fragment:
While-Loop Statement (in C with goto) | |
---|---|
1 2 3 4 |
|
This produces the MIPS code that follows the similar structure as the C code fragment above using goto
and label.
While-Loop Statement (in MIPS) | |
---|---|
1 2 3 4 |
|
Exercise
Write the following for-loop in MIPS.
Question | |
---|---|
1 2 3 |
|
Variable | Register |
---|---|
i |
$s0 |
a |
$s2 |
The constant 10
is rather troublesome because we cannot compare easily with a constant.
We need to store this value into a register.
Let's use $s1
for this.
Now, translating this for-loop into a similar while-loop might be more useful.
Additionally, we use our understanding of the code fragment to note that the inequality can be replaced with equality.
In this case, the loop ends when variable i
is equal to 10
.
The while-loop looks like the following:
While-Loop Variant | |
---|---|
1 2 3 4 5 6 |
|
And voila! We can now use the same technique of while-loop translation to translate this to the MIPS code below.
Answer | |
---|---|
1 2 3 4 5 6 7 |
|
Array and Loop
A typical example of accessing array elements in a loop can be summarised with the diagram below:
Count Zeroes
The problem is to count the number of zeroes in an integer array A
(i.e., int A[40];
).
Here, A
is an integer array with 40 elements.
Variable | Register |
---|---|
&A[0] |
$t0 |
result |
$t8 |
You should think about the following:
- How to perform the right comparison.
- How to perform the right load operation.
In this version, we use the following simple C code:
Count Zeroes V1 (in C) | |
---|---|
1 2 3 4 5 6 7 8 |
|
Since we use a temporary variable i
, we need to map this.
Let us map this to $t1
.
We also need to store the constant 40
for comparison, we will use $t2
.
Lastly, note that we need to compute the correct address.
Since this is an integer array, it will be word aligned.
Which means, the actual offset will need to be multiplied by 4.
We use both $t3
and $t4
to compute the actual address for load.
Count Zeroes V1 (in MIPS) | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
In this version, we use pointer arithmetic version of the C code:
Count Zeroes V2 (in C) | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
Here we use two additional variables curr
and last
.
curr
is address of the current item, which we will be incremented using pointer arithmetic.
last
is a computed address of the last element.
We can compare address as if they are numbers because MIPS register has no data type.
However, this omission of data type produce a problem for curr++
.
This should increment the address by 4 because this is an integer array.
So remember to do this on your MIPS code.
Now, since curr
is already the address, we do not need to do the multiplication by 4 and add the base address.
Instead, we can simply load.
Count Zeroes V2 (in MIPS) | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
Pointer Arithmetic
Note that the use of "pointers" directly via pointer arithmetic can produce more efficient code.
Simple Loop
Given the following MIPS code:
Question 1 | |
---|---|
1 2 3 4 5 6 |
|
-
How many instructions are executed?
(a) 6
(b) 30
(c) 33
(d) 36
(e) None of the above -
What is the final value in
$t2
?(a) 10
(b) 20
(c) 300
(d) 310
(e) None of the above
Answer
- (a)
- (b)
Given the following MIPS code:
Question 2 | |
---|---|
1 2 3 4 5 6 |
|
-
How many instructions are executed?
(a) 6
(b) 12
(c) 15
(d) 18
(e) None of the above -
What is the final value in
$t1
?(a) 0
(b) 4
(c) 6
(d) 10
(e) None of the above
Answer
- (c)
- (c)
Given the following MIPS code accessing an integer array of elements in memory with the starting address in $t0
.
Question 3 | |
---|---|
1 2 3 4 5 6 |
|
-
How many times in the
bne
instruction executed?(a) 1
(b) 3
(c) 9
(d) 10
(e) 11 -
How many times does the
bne
instruction actually branch to the labelLoop
?(a) 1
(b) 8
(c) 9
(d) 10
(e) 11 -
How many instructions are executed?
(a) 6
(b) 12
(c) 41
(d) 42
(e) 46 -
How many unique bytes of data are read from the memory?
(a) 4
(b) 10
(c) 11
(d) 13
(e) 40
Answer
- (d)
- (c)
- (d)
- (d)
-
There is a growing field of computing called "Branchless Programming". However, it typically only removes selection statements (e.g.,
if
andswitch-case
) and we still need repetition statements for general purpose computing. As you will learn later on pipelining, branch prediction helps but only if the prediction is correct. ↩ -
One of the opponent is Edsger W. Dijkstra of Dijkstra's algorithm fame. You can read his opposition to understand why. In short, unchecked use of
goto
leads to unreadable code (called the spaghetti code). However, a certain highly restrictedgoto
may actually be beneficial (e.g., try escaping from nested loop, you will realise that your code will feel weird). ↩