MIPS_primery_zadach / dandamudi05gtr guide risc processors programmers engineers
.pdf
246 |
Guide to RISC Processors |
rizes the comparison instructions provided by the assembler. Notice that all comparison instructions in Table 14.1 are pseudoinstructions. For example, the pseudoinstruction
seq $a0,$a1,$a2
is translated as
beq $6,$5,skip1 ori $4,$0,0
beq $0,$0,skip2 skip1:
ori $4,$0,1 skip2:
. . .
Note that $a0, $a1, and $a2 represent registers $4, $5, and $6, respectively. The branch instructions are discussed next.
Unconditional Branch Instructions
Unconditional transfer of control is implemented by jump and branch instructions. Let us first look at the basic jump instruction. The jump instruction
j target
transfers control to the target address. As discussed before, this is a direct jump instruction in which the target address is given as part of the instruction. In the MIPS32 architecture, the control is transferred to target after executing the delay slot instruction. However, see the following SPIM note.
SPIM note |
Because SPIM does not simulate delayed branch, it does not exe- |
|
cute the delay slot instruction. |
||
|
||
|
|
There are other types of jump instructions that are useful as procedure calls. We have already discussed some of these instructions in Chapter 11. For example, we use the jal instruction to invoke a procedure. Similarly, the jr instruction is used to return from a procedure.
Branch instructions provide a more flexible test and jump execution. MIPS supports several branch instructions. We describe some of these instructions in this section.
The unconditional branch instruction
b† target
transfers control to target unconditionally. Semantically, it is very similar to the jump instruction. The main difference is that the b instruction uses a 16-bit relative address
Chapter 14 • Conditional Execution |
247 |
whereas the j instruction uses a 26-bit absolute address. Thus, the jump instruction has a larger range than the branch instruction. But the branch is more convenient because it uses relative address.
An Example To illustate the difference between jump and branch instructions, let us look at the following code fragement.
|
loop_back: |
|
[0x00400048] |
addu |
$t0,$t0,$t1 |
[0x0040004c] |
j |
loop_back |
The numbers in the square brackets are the addresses of the instructions. For example, the addu instruction is at address 0x00400048. The SPIM assembler translates the jump (j) instruction in this code as
j 0x00400048
by replacing the label loop_back by its address 0x00400048. As you can see from this example, the absolute value is used to specify the target address. However, as we have seen in Chapter 11, the instruction encoding is slightly different. The instruction encoding follows the explanation given in the example on page 186. If you have read that explanation on how the jal instruction is encoded, you will see that the j instruction follows similar encoding.
As in the jal instruction, this instruction uses the J-type encoding shown in Figure 4.2 on page 52. This jump instruction is encoded as 0x08100012. The target address is specified using 26 bits as shown below:
Opcode |
Offset |
0000 10 00 0001 0000 0000 0000 0001 0010
Because all instructions are aligned on word boundaries, the least significant 2 bits are always zero. As a result, these 2 bits are not explicitly stored in the instruction. By appending these 2 zeros, we get the 28-bit offset value as 0x0400048. By adding the most significant 4 bits from the PC, we get the target address as 0x00400048, which is the address of the addu instruction at loop_back.
Now we replace the jump instruction by the branch instruction as shown below:
|
loop_back: |
|
[0x00400048] |
addu |
$t0,$t0,$t1 |
[0x0040004c] |
b |
loop_back |
The unconditional branch instruction (b) is encoded as
bgez $0,-4
248 |
Guide to RISC Processors |
This example gives the following information about the encoding of the b instruction:
•Because the branch instruction is actually a pseudoinstruction, it is encoded using the conditional branch instruction bgez. How can this instruction implement an unconditional branch? Well, we compare register $0 to zero and jump to target if the register has a value greater than or equal to zero. Register $0 is hardwired to zero, therefore the test is always true, causing the jump to always take place.
•The offset used is a PC-relative value, not the absolute value as in the j instruction. In our example, the relative offset is −4.
Conditional Branch Instructions
Now we look at the conditional branch instructions. These instructions compare the contents of two registers and jump to the target if the specified condition is true. For example, the branch instruction
beq Rsrc1,Rsrc2,target
compares the contents of Rsrc1 and Rsrc2 and transfers control to target if they are equal.
Branch instructions to test “less than” and “greater than” are also supported. As an example, the instruction
bgt Rsrc1,Rsrc2,target
branches to the target location when the contents of Rsrc1 are greater than Rsrc2. When comparing, the contents of Rsrc1 and Rsrc2 are treated as signed numbers. For unsigned numbers, we have to use the bgtu instruction.
Branch instructions to test combinations such as “greater than or equal to” are also available. Table 14.2 summarizes some of the branch instructions provided by the MIPS assembler.
Very often, we need to compare a value with zero and transfer control to the target based on this comparison. This is often the case in constructing loops. For example, look at the code given at the beginning of this chapter. For this reason, MIPS supports conditional branch instructions that compare with zero. To illustrate the format of these instructions, we use the beqz instruction. The format is
beqz Rsrc,target
This instruction transfers control to target if the value of Rsrc is equal to zero. Table 14.3 summarizes these instructions.
Chapter 14 • Conditional Execution |
249 |
Table 14.2 MIPS branch instructions (based on register comparison)
Instruction |
Description |
|
b† |
target |
Branches unconditionally to target. |
beq |
Rsrc1,Rsrc2,target |
Branches to target if the contents of Rsrc1 and |
|
|
Rsrc2 are equal. |
bne |
Rsrc1,Rsrc2,target |
Branches to target if the contents of Rsrc1 and |
|
|
Rsrc2 are not equal. |
blt |
Rsrc1,Rsrc2,target |
Branches to target if the value of Rsrc1 is less |
|
|
than the value of Rsrc2. The source operands are |
|
|
considered as signed numbers. |
bltu |
Rsrc1,Rsrc2,target |
Same as blt except that the source operands are |
|
|
treated as unsigned numbers. |
bgt |
Rsrc1,Rsrc2,target |
Branches to target if the value of Rsrc1 is greater |
|
|
than the value of Rsrc2. The source operands are |
|
|
treated as signed numbers. |
bgtu |
Rsrc1,Rsrc2,target |
Same as bgt except that the source operands are |
|
|
treated as unsigned numbers. |
ble |
Rsrc1,Rsrc2,target |
Branches to target if the value of Rsrc1 is less |
|
|
than or equal to the value of Rsrc2. The source |
|
|
operands are treated as signed numbers. |
bleu |
Rsrc1,Rsrc2,target |
Same as ble except that the source operands are |
|
|
treated as unsigned numbers. |
bge |
Rsrc1,Rsrc2,target |
Branches to target if the value of Rsrc1 is greater |
|
|
than or equal to the value of Rsrc2. The source |
|
|
operands are treated as signed numbers. |
bgeu |
Rsrc1,Rsrc2,target |
Same as bge except that the source operands are con- |
|
|
sidered as unsigned numbers. |
|
|
|
Our First Program
As our first example of the chapter, we look at counting the number of uppercase letters in a given string. The program listing is given in Program 14.1. The main program prompts the user for a string and passes it on to the count procedure via the $a0 register. The count procedure returns the uppercase count in $v0. The procedure follows the algorithm given below:
250 |
Guide to RISC Processors |
Table 14.3 MIPS branch instructions (based on comparison to zero)
Instruction |
Description |
|
beqz |
Rsrc,target |
Branches to target if the value of Rsrc is equal to |
|
|
zero. |
bnez |
Rsrc,target |
Branches to target if the value of Rsrc is not equal |
|
|
to zero. |
bltz |
Rsrc,target |
Branches to target if the value of Rsrc is less than |
|
|
zero. |
bgtz |
Rsrc,target |
Branches to target if the value of Rsrc is greater |
|
|
than zero. |
blez |
Rsrc,target |
Branches to target if the value of Rsrc is less than |
|
|
or equal to zero. |
bgez |
Rsrc,target |
Branches to target if the value of Rsrc is greater |
|
|
than or equal to zero. |
|
|
|
count(string) uppercase_count := 0 i := 0
while (string[i] =NULL)
if ((string[i] ≥ ’A’) AND (string[i] ≤ ’Z’)) uppercase_count := uppercase_count + 1
end if
i := i + 1 end while
return (uppercase_count) end count
The if condition is tested on lines 63 and 64. If the condition is true, the uppercase count (in $v0) is incremented on line 65. The count loop index (in $t0) is incremented on line 67. The while loop condition is tested on line 62. If the loop condition is not true, the loop is terminated by the beqz instruction on line 62.
Program 14.1 A program to count the number of uppercase letters in a string
1: # Counts the uppercase letters |
UPPER_COUNT.ASM |
2:#
3:# Objective: Counts uppercase letters in a string.
4:# Input: Requests a string from the user.
Chapter 14 • Conditional Execution |
251 |
5:# Output: Outputs the uppercase letter count.
6:#
7:# $a0 - string pointer
8:# $v0 - returns the uppercase letter count
9:#
10:################### Data segment #######################
11:.data
12:prompt:
13: |
.asciiz |
"Please enter a string: \n" |
14:out_msg:
15: |
.asciiz |
"The number of uppercase letters is: " |
16:newline:
17: .asciiz "\n"
18:in_string:
19: |
.space |
31 |
20: |
|
|
21:################### Code segment #######################
22:.text
23:.globl main
24:main:
25: |
la |
$a0,prompt |
# prompt user for input |
26:li $v0,4
27:syscall
29: |
la |
$a0,in_string |
# |
read input string |
30: |
li |
$a1,31 |
# |
buffer length in $a1 |
31:li $v0,8
32:syscall
34: |
la |
$a0,in_string |
# call the count proc. |
|
35: |
jal |
count |
|
|
36: |
move |
$t0,$v0 |
# |
count is in $v0 |
37: |
|
|
|
|
38: |
la |
$a0,out_msg |
# |
write output message |
39:li $v0,4
40:syscall
42: |
move $a0,$t0 |
# output the count |
43:li $v0,1
44:syscall
46: |
la |
$a0,newline |
# write newline |
47:li $v0,4
48:syscall
50: |
li |
$v0,10 |
# exit |
51:syscall
252 |
Guide to RISC Processors |
52:
53:#-----------------------------------------------------
54:# COUNT receives a pointer to a string in $a0 and
55:# returns the number of uppercase letters in $v0.
56:# $t0 - temporary
57:#-----------------------------------------------------
58:count:
59: |
li |
$v0,0 |
# count = 0 |
60:count_loop:
61:lbu $t0,($a0)
62: |
beqz $t0,count_done |
# if NULL, we are done |
63:bgtu $t0,’Z’,skip_count
64:bltu $t0,’A’,skip_count
65: |
addu $v0,$v0,1 |
# update count |
66:skip_count:
67:addu $a0,$a0,1
68: b count_loop
69:count_done:
70:jr $ra
Illustrative Examples
We give two examples to further illustrate the instructions discussed in this chapter.
Example 14.1 Sorting of an integer array using selection sort.
The main program, shown in Program 14.2, prompts the user for the array values. The read loop on lines 33–39 reads the values entered by the user. This loop is terminated when a zero is entered. This is not a safe loop as it is possible to exceed the array bounds (which in our example can take 50 elements). You can make this loop safe by adding another termination condition that takes care of the array boundary.
The main program copies the array pointer into $a0 (line 42) and its size in $a1 (line 43 and 44). Notice that we use the shift right instruction (srl) on line 44 to divide the byte count by 4 to get the array size. The selection sort procedure is invoked on line 45. After the array has been sorted, the main program displays the sorted array using the loop on lines 52–61.
Program 14.2 Selection sort program
1: # Selection sort |
SEL_SORT.ASM |
2:#
3:# Objective: Sorts an array using selection sort.
4:# Input: Requests integers from the user;
Chapter 14 • |
Conditional Execution |
253 |
5: # |
terminated by entering a zero. |
|
6:# Output: Outputs the sorted integer array.
7:#
8:# $a0 - array pointer
9:# $a1 - array size
10:#
11:#################### Data segment ########################
12:.data
13:prompt:
14: |
.ascii |
"Please enter integers (at least two).\n" |
15: |
.asciiz |
"Entering zero terminates the input.\n" |
16:output_msg:
17: |
.asciiz |
"The sorted array is:\n" |
18:newline:
19: .asciiz "\n"
20:.align 2
21:array:
22: |
.space |
200 |
# space for 50 integers |
23: |
|
|
|
24:#################### Code segment ########################
25:.text
26:.globl main
27:main:
28: |
la |
$a0,prompt |
# prompt user for input |
29:li $v0,4
30:syscall
32:la $t0,array
33:read_more:
34: |
li |
$v0,5 |
# read a number |
35:syscall
36: |
sw |
$v0,($t0) |
# store it in the array |
37:beqz $v0,exit_read
38:addu $t0,$t0,4
39: b read_more
40:exit_read:
41:# prepare arguments for procedure call
42: |
la |
$a0,array |
# $a0 = array pointer |
43:subu $a1,$t0,$a0 # $a1 = array size in bytes
44: |
srl |
$a1,$a1,2 |
# |
$a1 = $a1/4 |
45: |
jal |
sel_sort |
|
|
46: |
|
|
|
|
47: |
la |
$a0,output_msg |
# |
write output message |
48:li $v0,4
49:syscall
51: la $t0,array
254 |
Guide to RISC Processors |
52:write_more:
53: |
lw |
$a0,($t0) |
# output sorted array |
54:beqz $a0,exit_write
55:li $v0,1
56:syscall
57: |
la |
$a0,newline |
# write newline |
58:li $v0,4
59:syscall
60:addu $t0,$t0,4
61: |
b |
write_more |
|
62: |
exit_write: |
|
|
63: |
|
|
|
64: |
li |
$v0,10 |
# exit |
65: |
syscall |
|
|
66: |
|
|
|
67:#--------------------------------------------------------
68:# SEL_SORT receives a pointer to the array in $a0 and
69:# its size in $a1. It sorts the array in ascending order
70:# using the selection sort algorithm.
71:# $t1 - array[j] pointer
72:# $t2 - min_value
73:# $t3 - array[min_position] pointer
74:# $t4 - used as a temporary
75:# $a0 - array[position] pointer
76:# $a1 - array[size-1] pointer
77:#--------------------------------------------------------
78:sel_sort:
79:# computes array[size-1] pointer (i.e., &A[size-1])
80:subu $a1,$a1,1
81:sll $a1,$a1,2
82:addu $a1,$a1,$a0
83:
84:########### outer for loop ############
85:outer_for:
86: |
lw |
$t2,($a0) |
# |
min_value = A[position] |
87: |
move |
$t3,$a0 |
# |
&A[min_position] = &A[position] |
88: |
|
|
|
|
89:# inner for loop
90: |
addu $t1,$a0,4 |
# &A[j] = &A[position+1] |
91:inner_for:
92: |
lw |
$t4,($t1) |
# 1st if condition |
93: |
bgeu |
$t4,$t2,skip_1st_if |
# |
94: |
|
|
|
95:# 1st if statement
96: |
move |
$t2,$t4 |
# min_value = A[j] |
97: |
move |
$t3,$t1 |
# &A[min_pos] = &A[j] |
98: |
# end |
of 1st if statement |
|
Chapter 14 • Conditional Execution |
255 |
99:
100:skip_1st_if:
101: |
addu $t1,$t1,4 |
# $t1 = &A[j+1] |
102:bleu $t1,$a1,inner_for
103:# end of inner for loop
105:beq $a0,$t3,skip_2nd_if # 2nd if condition
106:second_if:
107:# 2nd if statement
108:lw $t4,($a0)
109:sw $t4,($t3)
110:sw $t2,($a0)
111:# end of 2nd if statement
112:
113:skip_2nd_if:
114: |
addu $a0,$a0,4 |
# $a0 = &A[position+1] |
115:bltu $a0,$a1,outer_for
116:# end of outer for loop
118: jr $ra
The sort procedure receives a pointer to the array to be sorted in $a0 and its size in $a1. It uses the selection sort algorithm to sort the array in ascending order. The basic idea is as follows.
1.Search the array for the smallest element;
2.Move the smallest element to the first position by exchanging values of the first and smallest element positions;
3.Search the array for the smallest element from the second position of the array;
4.Move this element to the second position by exchanging values as in Step 2;
5.Continue this process until the array is sorted.
The selection sort procedure implements the following pseudocode.
selection_sort (array, size) for (position = 0 to size−2)
min_value := array[position] min_position := position
for (j = position+1 to size−1) if (array[j] < min_value) then
min_value := array[j] min_position := j
end if
