Instructions

page 1 of 7
ENCM 369 Winter 2015 Lab 12
for the Week of April 13
Steve Norman
Department of Electrical & Computer Engineering
University of Calgary
April 2015
Lab instructions and other documents for ENCM 369 can be found at
http://people.ucalgary.ca/~norman/encm369winter2015/
1
This Lab is important, but will not be marked
Solutions will be posted sometime during the week of April 13.
Please make a serious effort to solve the Exercises yourself before checking solutions!
You can expect a significant portion of the marks on the final exam to be related
to integer multiplication and division, and to floating-point number representation
and arithmetic.
2
2.1
Exercise A: Practice with mult, multu, div, divu
Read This First
mult and multu were the original integer MIPS multiplication instructions, and are
the ones explained in lectures and your textbook. Please use these instructions in
this exercise, not any other instructions.
There is one more real MIPS instruction for integer multiplication: mul. The mul
instruction has two GPRs as sources, and writes bits 31–0 of the product directly
to a destination GPR. This is useful for compilers—a compiler can avoid using a
mflo instruction when only the low 32 bits of an integer product are needed.
MARS assembly language also allows a lot of pseudoinstructions for integer
division and multiplication, for example, allowing constants instead of GPRs as
sources. Please avoid these pseudoinstructions.
To keep things as simple as possible, the ENCM 360 final exam in Winter 2014
will test you on the real instructions mult, multu, div, and divu, not any other real
instructions or pseudoinstructions for integer multiplication or division. Of course,
that implies that you also need to know how to use mflo or mfhi to copy a result
out of Lo or Hi into a GPR.
2.2
What to Do
Copy the files in encm369w15lab12/exA
Read the two files. You should see that ex12A.asm is a nearly complete translation
of ex12A.c—all the tedious work of translating main has been done. However, code
must be added to ex12A.asm for the procedures func1 and func2.
ENCM 369 Winter 2015 Lab 12
page 2 of 7
Make a copy of ex12A.asm, and add appropriate instructions to func1 and
func2 to properly translate the C versions. If you do this correctly, the output
of the MARS program should show you the same numbers as the output of the C
program.
In doing the translation,
• do not modify main in any way;
• handle multiplication as a typical C compiler would—the result of multiplying
two 32-bit integers should be taken as the low 32 bits of the 64-bit product;
• do not worry about the possibility of division by zero—in this exercise, you
do not need to write code for special behaviour in the case of a zero divisor.
3
Exercise B: IEEE 754 floating-point formats
3.1
Read This First
You should be able to do all parts of this exercise with just pencil and paper—the
numbers have been set up to make the arithmetic easy to do.
3.2
What to Do
Answer the following questions. In each case, take time to write down the steps you
take to work toward an answer.
1. If the 32-bit IEEE 754 format is being used, what number does the bit pattern
0xc0a8_0000 represent?
2. If the 32-bit IEEE 754 format is being used, what number does the bit pattern
0x3f20_0000 represent?
3. If the 64-bit IEEE 754 format is being used, what number does the bit pattern
0x4015_0000_0000_0000 represent?
4. If the 64-bit IEEE 754 format is being used, what number does the bit pattern
0xfff0_0000_0000_0000 represent?
5. What is the 32-bit IEEE 754 representation of −3.25? Express your final
answer using hexadecimal notation.
6. What is the 64-bit IEEE 754 representation of −3.25? Express your final
answer using hexadecimal notation.
4
4.1
Exercise C: The minifloat type
Read This First
To understand how floating-point number representation and arithmetic work, it’s
useful to consider some pencil-and-paper examples. However, doing pencil-andpaper work with 32-bit patterns (or worse, 64-bit patterns) is tedious, so in this
exercise we’ll do it with an 8-bit floating-point type called the minifloat type. The
minifloat type is intended to mimic the IEEE 754 32-bit and 64-bit floating-point
types. With only 8 bits, the precision and range of magnitudes for minifloat will
obviously be severely limited. The layout of a minifloat is as follows:
ENCM 369 Winter 2015 Lab 12
bit 7:
sign
bit
page 3 of 7
bits 3-0:
fraction
bits 6-4:
biased exponent
Before continuing to describe the minifloat type, I would like to introduce a bit
of notation. I will use the ** operator (borrowed from the Fortran and Python programming languages) for exponentiation; this is handy when writing mathematics
in Web pages and program comments. (So, for example, 2**4 means 24 .)
Here is the specification for the minifloat type:
• The sign bit of a minifloat is 0 for positive numbers and 1 for negative numbers.
• The exponent field of a minifloat is used as follows:
– Bit patterns 001, 010, 011, 100, 101 and 110 are used for exponents of
normal, nonzero numbers. There is a bias of three in the exponent.
– The bit pattern 000 is the exponent field in for representations of zero.
(IEEE 754 types use all-0 exponents for zero values and also for verysmall-magnitude nonzero values called denormalized numbers; we won’t
bother with denormalized numbers in the minifloat type.)
– The bit pattern 111 is not used at all. (IEEE 754 types use all-1 exponents to indicate special values of Infinity and NaN—“not a number”.
We won’t bother with Infinity and NaN in the minifloat type.)
• In a nonzero minifloat, the fraction bits are used to represent the fractional
part of the significand. In representations of zero, the fraction bits must all
be 0.
Now that the uses of the individual fields have been described, it’s possible to
determine what real number (if any) is represented by an 8-bit pattern.
• First of all, both 00000000 and 10000000 represent zero; note that in an
IEEE 754 system, there are also two representations of zero.
• Next, there are some bit patterns that don’t represent any real number at
all. Examples are: 10001010, which has a special exponent of 000 but does
not have 0000 in its fraction field; and 01110000, which has the meaningless
exponent of 111.
• Finally, there are normal, nonzero numbers, such as 01101011. To see what
number this is, first split it into fields: the sign bit is 0, the exponent field is
110, and the fraction field is 1011. In base two, then, the number represented
is
1.1011 * two ** three
Note that the significand is obtained by putting a 1 and a binary point in
front of the four-bit fraction field and that the exponent of three is obtained
by subtracting the bias of three from the value of six (110). In base ten, the
number is
(1 + 1/2 + 1/8 + 1/16) × 23 = 1.6875 × 8 = 13.5.
ENCM 369 Winter 2015 Lab 12
page 4 of 7
Let’s consider the problem of determining a minifloat representation of a number
given in base 10, say 0.390625. To start with we need to write our number in the
form
sign * significand * 2 ** exponent
where the significand is greater than or equal to 1 and less than 2. This gives us
0.390625 = 1 * 1.5625 * 2 ** (-2)
The sign bit should be 0, obviously. The biased exponent should be −2 + 3, or
001 in base two. What is the fractional part of the significand? Here I will cheat
a little and just state that 0.5625 is in fact exactly 1/2 + 1/16, so the correct bit
pattern is 1001. Putting all the bit fields together, the minifloat representation is
00011001.
The fractional part of the significand in a minifloat is
bit3 / 2 + bit2 / 4 + bit1 / 8 + bit0 / 16
From this it should be clear that the fractional part of the significand is always an
integer multiple of 1/16. Determining the significand bits in the previous example
was relatively easy because 0.5625 just happened to be an integer multiple of 1/16.
Most base ten fractions are not integer multiples of 1/16, so usually when converting
from base ten to minifloat, the fraction will have to be rounded to an integer multiple
of 1/16. The following table is useful for doing such rounding:
value
0/16
1/16
2/16
3/16
4/16
5/16
6/16
7/16
base two
0.0000
0.0001
0.0010
0.0011
0.0100
0.0101
0.0110
0.0111
base ten
0.0000
0.0625
0.1250
0.1875
0.2500
0.3125
0.3750
0.4375
value
8/16
9/16
10/16
11/16
12/16
13/16
14/16
15/16
base two
0.1000
0.1001
0.1010
0.1011
0.1100
0.1101
0.1110
0.1111
base ten
0.5000
0.5625
0.6250
0.6875
0.7500
0.8125
0.8750
0.9375
Let’s find a minifloat representation for −3.6, which is −1 × 1.8 × 21 . The sign bit
is 1 and the exponent field is 100. The fraction bits depend on what rule we choose
for rounding. If we use a round-to-nearest rule, the correct choice is 1101, because
0.8 is closer to 0.8125 than it is to 0.7500. With a round-towards-zero rule, the
correct choice is 1100. Other rounding rules could be used instead, but in all cases
the correct choice will be either 1100 or 1101. So the minifloat representation of
−3.6 would be either 11001101 or 11001100; neither representation would be exact.
4.2
What to Do
For each of the following minifloat bit patterns, determine the equivalent base ten
number, or explain why no such base ten number can be found.
1.
2.
3.
01001100
10101000
11111111
Convert each of the following base ten numbers to a minifloat representation, or
explain why the conversion is not possible. If rounding is necessary, use round-tonearest logic.
4.
5.
6.
0.4
−11.0
17.5
ENCM 369 Winter 2015 Lab 12
5
page 5 of 7
Exercise D: Multiplication of minifloats
5.1
Read This First
This exercise is designed to help you understand the steps required to multiply two
floating-point numbers. The exercise should also give you a general idea of the kinds
of components needed in digital hardware for floating-point multiplication.
Suppose you are asked to find the product of two minifloats, and the only tools
you have are a pencil and some paper. Here is an algorithm that works on positive
minifloats only, illustrated with an example. Let’s suppose you are asked to multiply
01101011 and 00101101.
• First, extract the bit patterns for biased exponents: 110 and 010. Because of
the bias, the actual exponents are 3 = 6 − 3 and −1 = 2 − 3. The sum of the
exponents is 2, so you can tentatively set the exponent bits of the product to
be 101 (from 2 + 3 = 5).
• Second, find the two significands by putting 1’s in front of the 4-bit fractions
from the minifloat bit patterns. For the example, 1.1011 (base two) and 1.1101
(base two) are the significands.
• Third, multiply the significands. Because they are both greater than or equal
to one and less than two, the result will be greater than or equal to one and
less than four. In our example, the multiplication produces 11.00001111 (base
two), which is just a little larger than three.
• Fourth, determine the significand for the overall result. This needs to be
greater than or equal to one and less than two. You can achieve that by dividing 11.00001111 by two to get 1.100001111 and incrementing the exponent
of the result from 101 to 110. (Dividing the result by two and incrementing
the exponent would be skipped in a case where the product of significands is
less than two.) Rounded to five bits, the significand is 1.1000; therefore the
fraction bits will be 1000.
• Combine the sign, exponent, and fraction bits to get an overall result, which
for the example would be 01101000.
5.2
What to Do
Use the algorithm given in “Read This First” to compute
1. the product of minifloats 00110100 and 01000101.
2. the product of minifloats 11001100 and 00101000.
6
Quick Reference for floating-point programming
In order to help you quickly find information you need about instructions you will
use in this lab, a two-page document called “MIPS floating-point reference for
Lab 12” has been created. You can find a link to it on the Web page for ENCM
369 lab instructions.
ENCM 369 Winter 2015 Lab 12
7
page 6 of 7
Exercise E: Introduction to floating point instructions
7.1
What to Do
Copy the files from encm369w15lab12/exE
Read the file 12Eprog.c. Build an executable and run it to see what the output is.
Now study the file 12Eprog.asm, which is a MARS translation of the C program.
This provides examples of many of the key MIPS floating-point instructions. Some
key things to look at are:
• Note that even though the program is doing some floating-point operations,
a lot of work is still done using GPRs. In particular, addresses always go in
GPRs—never FPRs—even when memory is being used to hold floating-point
numbers.
• Note that a double is eight bytes (two words) in size; this matters when saving
a double-precision register on the stack, when allocating an array of doubles,
and when computing the address of an array element of type double.
• Note how the constants 1.57079632679489661923 and 0.5 get copied from
memory to FPRs.
• Note how the expression i * pi_over_2 is handled. There is NO MIPS instruction that can multiply an int and a double! Instead, three instructions
are needed: mtc1 to copy an integer bit pattern from a GPR to an FPR;
cvt.d.w to convert an integer bit pattern in an FPR to a double-precision bit
pattern in another FPR; and finally a mul.d instruction to do the multiplication.
Use MARS to assembler and run the MARS program. You should notice that the
MARS program output is very similar to but not exactly the same as the C program
output.
8
Exercise F: Quadratic equation solver
8.1
Read This First
To do this exercise you should expect to refer repeatedly to the “MIPS floating-point
reference for Lab 12” document.
8.2
What to Do
Copy the files from encm369w15lab12/exF
Build an executable for the C program you find, and run the executable to see what
the output is. Note that you will have to use -lm (with letter l not digit 1) on the
command line to build the executable—the linker has to be to told to search the C
math library to find the sqrt function.
Study the C code carefully, then complete the MARS translation in quadratic.asm
by writing assembly language code for the quadratic procedure—main and test_q
are already complete.
For this exercise, use the usual register conventions for GPRs and the following
conventions for double-precision FPRs:
• Registers $f2, $f4, . . . , $f10 should be used as temporaries (like $t0–$t9).
• Registers $f20, $f22, . . . , $f30 should be used as callee-save registers (like
$s0–$s7).
ENCM 369 Winter 2015 Lab 12
page 7 of 7
• Arguments are passed to quadratic in the following registers: $f12 for a,
$f14 for b, $f16 for c, $a0 for roots.
9
Exercise G: Sorting an array of doubles
9.1
Read This First
As in Exercise F, you should expect to refer frequently to documentation of floatingpoint instructions.
9.2
What to Do
Copy the files from encm369w15lab12/exG
Build an executable using the C code you find, and run the executable to see what
the output is.
Complete the MARS translation of the C program by a writing a correct definition
for sort in sort.asm—the MARS code for main is complete and correct. For this
exercise, use the usual register conventions for GPRs and the following conventions
for double-precision FPRs:
• Registers $f2, $f4, . . . , $f10 should be used as temporaries (like $t0–$t9).
• Registers $f20, $f22, . . . , $f30 should be used as callee-save registers (like
$s0–$s7).
The arguments should be in a-registers because the arguments are pointers or ints.