Nimbus
Nimbus

Reputation: 1

MIPS - How to Convert a set of Integers into Single-Precision Floats

I'm really having a difficult time figuring out how to approach this problem. I get that I want to take the binary representation of both the integer and fraction, combine them for the mantissa, and assign the sign bit to the beginning, but I don't know how to actually implement it in MIPS.

Can anyone help me at least get started?

Assume that your MIPS hardware does not have floating-point registers and floating-point ALU. If you want to perform floating point addition, you will have to use MIPS integer instructions that use the integer registers ($0 - $31) and the integer ALU to get the job done. In this assignment question, you will write MIPS code, using integer instructions and integer registers only, to implement a procedure to add two float-point numbers and to write a main function to call the procedure.

  1. Write a MIPS procedure toFloat to put a floating-point number into IEEE single-precision format. The procedure takes three integers as input: $a0, $a1, $a2, which represents a floating-point number in this way: If $a0 contains 0, the floating-point number is positive, else if $a0 contains 1, the floating-point number is negative. The number stored in register $a1 is the integer part of the floating-point number, and the number stored in register $a2 is the fraction part of the floating-point number. For example, to present the floating-point number -5.25, the three input registers should contain these numbers: $a0 = 1, $a1 = 5, and $a2 = 25. For the fraction part, you can use the div rs rt instruction to divide 25 by 100. The fraction will be stored in the HI register, and you can use the mfhi instruction to retrieve the fraction. The procedure will return v0, which contains the IEEE single-precision pattern corresponding to the floating-point number represented by the three input numbers. Once you have this procedure, you can use it to convert the input numbers 2.5 and 7.5 into their IEEE single-precision format.

  2. Write a MIPS procedure printFloat to print a number that is in the IEEE single-precision format. The input of the procedure is in $a0, which is a number in the IEEE single-precision format. The procedure will simply print the bit pattern stored in $a0. You can use a loop to print each bit. Once you have this procedure, you can use it to print the input number 2.5 and 7.5 in their floating-point format.

  3. Write a MIPS program to implement the main function to call your procedures. In this program, you will call

    toFloat(0, 2, 5) to generate the float-point format for 2.5;

    toFloat(0, 7, 5) to generate the float-point format for 7.5;

    printFloat to print 2.5

    printFloat to print 7.5

Here's the code that I have so far:

http://s7.postimg.org/v39ufikaj/code.png

Upvotes: 0

Views: 7524

Answers (1)

RobertB
RobertB

Reputation: 1076

Ok, the first step (as noted in comments) is to spend some quality time with a converter that show the bits, like the one here: binaryconvert.com floating point converter.

Then, the easy part is to take $a0 and dump bit 0 into bit 1 of our result. Something like:

add $v0, $zero, $zero # initialize our result
sll $t0, $a0, 31 # shift the lsb to the msb
or $v0, $v0, $t0 # set the sign bit in the result

But now we've got to do math. I was hoping that $a1 would be a whole number portion, and $a2 would be a binary fractional portion. But it's not like that... they say $a1 is the whole number (still a whole number in binary), but $a2 is, in effect, cents. (If 25/100 = 0.25 decimal, then $a2 contains cents.)

Here's where I'm getting confused, myself. The instructions say "use the div rs rt instruction to divide 25 by 100. The fraction will be stored in the HI register". But when I read what div does (MIPS Instruction Reference), it says it puts the quotient in $LO and the remainder in $HI. So dividing 25 by 100 would give you... 25. That's a good way to discard an amount greater than 100, but it doesn't get us to a binary fractional representation of the number.

In fact, I just spent a whole class plus lunch trying to figure out an elegant way to take a number between 0 and 99, divide it by 100, and convert the result to binary without using the FPU. I'm coming up short. So I'll let you ask the prof about that part.

But once we have the whole number portion in $a1, and a string of 1's and 0's representing the fractional part (lets put that in $s2), we just need to normalize it. We have a number in $a1.$s2, and we need it to be in this format:

1.nnnnnnn

... where we start with a 1, and then the fractional part is however many binary digits.

Here's some pseudocode that might work.

  • Shift $a1 left until the msb is "1". Store number of shifts in $t0. (Note: this assumes the integer portion is nonzero)
  • (31 - $t0) gives you the exponent. Adjust it by the Bias and stuff into bits 30-23 of your floating point result.
  • $t0 also tells you how much room you have for fractional bits. Shift $s2 by an appropriate amount (which depends on how it's encoded), and or it so that it fills in the least significant bits of $a1
  • Shift $a1 left one more bit, because the leading "1" is discarded in IEEE FP
  • Stuff the top 23 bits of $a1 into bits 22-0 of the floating point result

Let's see if that works in an example. $a1 has the integer portion of 0x0000C000, and $s2 has somehow been loaded with 0.75 (1 x 2^-1 + 1 x 2^-2)

$a1: 0000 0000 0000 0000 1100 0000 0000 0000 
$s2: 1100 0000 0000 0000 0000 0000 0000 0000

I have to shift $a1 16 times:

$a1: 1100 0000 0000 0000 0000 0000 0000 0000 

That should give me an exponent of 31 - 16 = 15. Add bias of 127 and I get 142 (0x8E). That goes in the exponent section.

I need to shift $s2 right by the same amount (16):

$s2: 0000 0000 0000 0000 1100 0000 0000 0000

or those together:

$a1:  1100 0000 0000 0000 1100 0000 0000 0000

Visualize that with a decimal point:

original:  1100 0000 0000 0000.1100 0000 0000 0000
normaliz: 1.100 0000 0000 0000 1100 0000 0000 0000

Because we omit the implied '1' to the left of the decimal point, shift it out and we have:

$a1:  100 0000 0000 0000 1100 0000 0000 0000 0

Take 23 bits of that. So if I've got this right, that converter above should say that 49152.75 stores in an IEEE FP as:

01000111 01000000 00000000 11000000

Sign = 0

Exponent = 10001110 (0x8E)

Mantissa = 1000 0000 0000 0001 1000 000

(Now, try to imagine my surprise that this actually worked!)

Upvotes: 1

Related Questions