
MIPS_primery_zadach / dandamudi05gtr guide risc processors programmers engineers
.pdfChapter 17 • Floating-Point Operations |
317 |
The read loop consists of lines 39–47. The loop count is maintained in $t1, which is initialized to 40 on line 36. The loop count is decremented on line 44 and tested for zero on line 47. The other termination condition is implemented by the following code on lines 45 and 46.
c.eq.d |
$f0,$f2 |
# if number = 0, |
bc1t |
exit_loop |
# exit loop |
To facilitate the comparison, we initialize $f2 to zero on line 37. If the comparison is true, we exit the loop using the bc1t instruction.
The values are read using the read_double system call (lines 40 and 41). Each input double value is stored in the array on line 42. The array size is computed on lines 51 and 52. If the size is zero (tested on line 53), an error message is displayed (lines 69–72) and the program is terminated. Otherwise, the array size along with the array pointer is passed onto the array_avg procedure. After returning from the procedure, the main program outputs the average value returned by the procedure.
Program 17.3 An example to find the average of a double-precision floating-point array
1: # Find the average of an array |
ARRAY_FAVG.ASM |
2:#
3:# Objective: Finds the average of a double array.
4:# Input: Requests doubles from the user.
5: # |
Entering zero terminates the input. |
6:# Output: Outputs the average value as a double.
7:#
8:# $a0 - array pointer
9:# $a1 - array size
10:# $f0, $f1 - returns the average
11: # |
(64-bit double value) |
12:#
13:################### Data segment ###################
14:.data
15:prompt:
16: |
.asciiz |
"Please enter the numbers: \n" |
17:avg_msg:
18: |
.asciiz |
"The average is: " |
19:newline:
20: .asciiz "\n"
21:error_msg:
22: |
.asciiz |
"Empty array!\n" |
23:.align 3
24:array:
25: |
.space |
320 |
# space for 40 doubles |
26: |
|
|
|
27: |
################### Code segment ################### |
318 |
Guide to RISC Processors |
28:.text
29:.globl main
30:main:
31: |
la |
$a0,prompt |
# prompt user for input |
|
32: |
li |
$v0,4 |
|
|
33: |
syscall |
|
|
|
34: |
|
|
|
|
35: |
la |
$t0,array |
# $t0 |
= array pointer |
36: |
li |
$t1,40 |
# $t1 |
= array size |
37: |
li.d |
$f2,0.0 |
# $f2 |
= 0 |
38: |
|
|
|
|
39:read_loop:
40: |
li |
$v0,7 |
# read the input number |
41: |
syscall |
|
|
42: |
s.d |
$f0,0($t0) |
|
43: |
addu |
$t0,$t0,8 |
# update array pointer |
44: |
subu |
$t1,$t1,1 |
# decrement loop count |
45: |
c.eq.d |
$f0,$f2 |
# if number = 0, |
46: |
bc1t |
exit_loop |
# exit loop |
47: |
bnez |
$t1,read_loop |
# if loop count is not 0, |
48: |
|
|
# read more |
49:exit_loop:
50: |
la |
$a0,array |
# $a0 = array pointer |
51: |
li |
$a1,39 |
|
52: |
subu |
$a1,$a1,$t1 |
# $a1 = array size |
53: |
beqz |
$a1,error |
# if array size = 0, error |
54: |
jal |
array_avg |
|
55: |
|
|
|
56: |
la |
$a0,avg_msg |
# write average message |
57: |
li |
$v0,4 |
|
58: |
syscall |
|
|
59: |
|
|
|
60: |
mov.d |
$f12,$f0 |
# output average |
61: |
li |
$v0,3 |
|
62: |
syscall |
|
|
63: |
|
|
|
64: |
la |
$a0,newline |
# write newline |
65: |
li |
$v0,4 |
|
66:syscall
67: |
b |
exit |
68: |
|
|
69:error:
70: |
la |
$a0,error_msg # write error message |
71: |
li |
$v0,4 |
72: |
syscall |
|
73: |
|
|
74:exit:
Chapter 17 • |
Floating-Point Operations |
319 |
|
75: |
li |
$v0,10 |
# exit |
76: |
syscall |
|
|
77: |
|
|
|
78:#------------------------------------------------
79:# ARRAY_AVG receives the array pointer in $a0 and
80:# its size $a1 and returns their sum in $f0 & $f1.
81:# $t1 - array size
82:# $f0,$f1 - keeps the double sum
83:# $f2,$f3 - used as a temporary double
84:# $f4,$f5 - array size in double
85:#------------------------------------------------
86:array_avg:
87: |
move |
$t1,$a1 |
# |
$t1 |
= |
array size |
88: |
li.d |
$f0,0.0 |
# |
sum |
= |
0 |
89:add_loop:
90: |
l.d |
$f2,0($a0) |
# add the array element |
91: |
add.d |
$f0,$f0,$f2 |
# value to sum |
92: |
addu |
$a0,$a0,8 |
# update array pointer |
93: |
subu |
$t1,$t1,1 |
# decrement loop count |
94: |
bnez |
$t1,add_loop |
|
95: |
|
|
|
96: |
mtc1 |
$a1,$f4 |
# move array size to $f4 |
97:cvt.d.w $f4,$f4 # convert word in $f4 to
98: |
|
|
# |
double format |
99: |
div.d |
$f0,$f0,$f4 |
# |
$f0 = $f0/$f4 |
100: |
jr |
$ra |
|
|
|
|
|
|
|
The procedure receives the array pointer in $a0 and its size in $a1. The sum is maintained in $f0, which is initialized to zero on line 88. The add loop consists of lines 89–94. The loop count is in $t1, which is decremented on line 93 and tested for zero on line 94.
To find the average, the array size is converted to the double format using the following code on lines 96 and 97.
mtc1 |
$a1,$f4 |
# move array size to $f4 |
cvt.d.w |
$f4,$f4 |
# convert word in $f4 to double format |
The array average is computed using the divide instruction on line 99.
Example 17.3 Find the sum of a variable number of floating-point numbers.
Our objective in this example is to show how floating-point numbers are passed via the stack. To meet this objective, we redo Example 11.4 given on page 208. We pass a variable number of double-precision floating-point numbers via the stack to a procedure that finds the sum of these numbers.
320 |
Guide to RISC Processors |
As in the last example, entering a zero terminates the input. The read loop consists of lines 33–41 and is similar to the read loop of the last example. The main difference is that the values are pushed onto the stack as we read them (lines 38 and 39). After exiting the read loop, we can invoke the procedure as the parameter count is in $a0 and the values are on the stack.
Program 17.4 An example to illustrate parameter passing of floating-point values via the stack
1: # Find the sum of doubles |
VAR_FSUM.ASM |
2:#
3:# Objective: Finds the sum of variable number of
4: |
# |
doubles passed via the stack. |
5: |
# |
To demonstrate stack-based |
6: |
# |
parameter passing. |
7:# Input: Requests doubles from the user.
8: # |
Entering a zero ends the input. |
9:# Output: Outputs the sum.
10:#
11:# $a0 - number of doubles passed via the stack.
12:# $f0 - returns the sum as a double (in $f0,$f1).
13:#
14:################### Data segment ###################
15:.data
16:prompt:
17: |
.asciiz |
"Please enter the numbers: \n" |
18:sum_msg:
19: |
.asciiz |
"The sum is: " |
20:newline:
21: .asciiz "\n" 22:
23:################### Code segment ###################
24:.text
25:.globl main
26:main:
27: |
la |
$a0,prompt |
# prompt user for input |
28: |
li |
$v0,4 |
|
29: |
syscall |
|
|
30: |
|
|
|
31: |
li.d |
$f2,0.0 |
# $f2 = 0 |
32: |
li |
$a0,0 |
# parameter count = 0 |
33: |
read_loop: |
|
|
34: |
li |
$v0,7 |
# read the input number |
35:syscall
36:c.eq.d $f0,$f2 # if number = 0, exit loop
37:bc1t exit_loop

Chapter 17 • |
Floating-Point Operations |
321 |
|
38: |
subu |
$sp,$sp,8 |
# reserve 8 bytes on stack |
39: |
s.d |
$f0,0($sp) |
# store the number on stack |
40: |
addu |
$a0,$a0,1 |
# increment parameter count |
41: |
b |
read_loop |
|
42: |
|
|
|
43:exit_loop:
44: |
jal |
var_sum |
|
45: |
|
|
|
46: |
|
|
|
47: |
la |
$a0,sum_msg |
# write sum message |
48: |
li |
$v0,4 |
|
49: |
syscall |
|
|
50: |
|
|
|
51: |
mov.d |
$f12,$f0 |
# output sum |
52: |
li |
$v0,3 |
|
53: |
syscall |
|
|
54: |
|
|
|
55: |
la |
$a0,newline |
# write newline |
56: |
li |
$v0,4 |
|
57: |
syscall |
|
|
58: |
|
|
|
59: |
li |
$v0,10 |
# exit |
60: |
syscall |
|
|
61: |
|
|
|
62:#------------------------------------------------
63:# VAR_SUM receives variable number of doubles
64:# via the stack and the parameter count in $a0.
65:# It returns their sum as a double in $f0.
66:# $a0 - parameter count
67:# $f0 - sum as a double (in $f0,$f1)
68:# $f2 - used as a temporary to hold a double
69:#------------------------------------------------
70:var_sum:
71: |
li.d |
$f0,0.0 |
# sum = 0 |
72:add_loop:
73:beqz $a0,done
74: |
l.d |
$f2,0($sp) |
# |
read the top value |
75: |
add.d |
$f0,$f0,$f2 |
|
|
76: |
addu |
$sp,$sp,8 |
# |
update $sp |
77:subu $a0,$a0,1
78: |
b |
add_loop |
79:done:
80:jr $ra
The var_sum procedure receives the parameter count in $a0. The add loop is similar to that used in the last example, except that we read the numbers off the stack. As we read

322 |
Guide to RISC Processors |
the values off the stack, we update the stack pointer by adding 8 (line 76). Recall that the stack grows downward as we push values onto it. Thus, when we take values off, we have to increment the stack pointer so that, when the loop terminates, the arguments are cleared from the stack.
Summary
We presented a brief description of the floating-point unit organization. Specifically, we concentrated on the registers provided by the FPU. It provides 32 floating-point registers that can store single-precision floating-point numbers. These registers can be used in pairs to store double-precision floating-point numbers.
The floating-point instructions support the four basic arithmetic operations: add, subtract, divide, and multiply. There are also three basic comparison instructions to establish “less than”, “equal to”, or “less than or equal to” relationships between floating-point numbers. In addition, several conversion instructions are available. These instructions allow conversion of values among the integer and single and double floating-point number representations. Finally, we used some examples to illustrate the application of these floating-point instructions.
Appendices

A
Number Systems
This appendix introduces background material on various number systems and representations. We start the appendix with a discussion of various number systems, including the binary and hexadecimal systems. When we use multiple number systems, we need to convert numbers from one system to another. We present details on how such number conversions are done. We then give details on integer representations. We cover both unsigned and signed integer representations. We close the appendix with a discussion of the floating-point numbers.
Positional Number Systems
The number systems that we discuss here are based on positional number systems. The decimal number system that we are already familiar with is an example of a positional number system. In contrast, the Roman numeral system is not a positional number system.
Every positional number system has a radix or base, and an alphabet. The base is a positive number. For example, the decimal system is a base-10 system. The number of symbols in the alphabet is equal to the base of the number system. The alphabet of the decimal system is 0 through 9, a total of 10 symbols or digits.
In this appendix, we discuss four number systems that are relevant in the context of computer systems and programming. These are the decimal (base-10), binary (base-2), octal (base-8), and hexadecimal (base-16) number systems. Our intention in including the familiar decimal system is to use it to explain some fundamental concepts of positional number systems.
Computers internally use the binary system. The remaining two number systems— octal and hexadecimal—are used mainly for convenience to write a binary number even though they are number systems on their own. We would have ended up using these number systems if we had 8 or 16 fingers instead of 10.
In a positional number system, a sequence of digits is used to represent a number. Each digit in this sequence should be a symbol in the alphabet. There is a weight associated
325
326 |
Guide to RISC Processors |
with each position. If we count position numbers from right to left starting with zero, the weight of position n in a base b number system is b n. For example, the number 579 in the decimal system is actually interpreted as
5 × (10 2) + 7 × (10 1) + 9 × (10 0) .
(Of course, 10 0 = 1.) In other words, 9 is in unit’s place, 7 in 10’s place, and 5 in 100’s place. More generally, a number in the base b number system is written as
dndn−1 . . . d1d0 ,
where d 0 represents the Least Significant Digit (LSD) and dn represents the Most Significant Digit (MSD). This sequence represents the value
dnbn + dn−1bn−1 + · · · + d1b1 + d0b0 . |
(A.1) |
Each digit d i in the string can be in the range 0 ≤ di ≤ (b − 1). When we use a number system with b ≤ 10, we use the first b decimal digits. For example, the binary system uses 0 and 1 as its alphabet. For number systems with b > 10, the initial letters of the English alphabet are used to represent digits greater than 9. For example, the alphabet of the hexadecimal system, whose base is 16, is 0 through 9 and A through F, a total of 16 symbols representing the digits of the hexadecimal system. We treat lowercase and uppercase letters used in a number system such as the hexadecimal system as equivalent.
The number of different values that can be represented using n digits in a base b system is b n. Consequently, because we start counting from 0, the largest number that can be represented using n digits is (b n − 1). This number is written as
(b − 1)(b − 1) . . . (b − 1)(b − 1) .
|
|
|
|
|
total of n digits
The minimum number of digits (i.e., the length of a number) required to represent X different values is given by logb X , where represents the ceiling function. Note thatm represents the smallest integer that is greater than or equal to m.
Notation The commonality in the alphabet of several number systems gives rise to confusion. For example, if we write 100 without specifying the number system in which it is expressed, different interpretations can lead to assigning different values, as shown below:
Number |
|
Decimal value |
100 |
binary |
4 |
−→ |
||
100 |
decimal |
100 |
−→ |
||
100 |
octal |
64 |
−→ |
||
100 |
hexadecimal |
256 |
−→ |
