Download Lecture 2

Document related concepts
no text concepts found
Transcript
Crunching Numbers
• Topics we need to explore
• Representing numbers on a computer
• Negatives, too
• Building hardware to do logic and math
•
•
•
•
And, Or
Hardware Alert!
Addition, Subtraction
Comparisons
Multiplication and Division
• Building hardware to work with Floating Point
numbers
4.1
Representation
• All data on a computer is represented in binary
• 32 bits of data may be:
•
•
•
•
32-bit unsigned integer
4 ASCII characters
Single-precision IEEE floating point number
Who knows...
data: 1000 1001 0100 0110 0000 0101 0010 1000
As 32-bit unsigned integer: 2,303,067,432
As 32-bit 2’s complement integer: -1,991,899,864
As 4 ASCII characters: ‘??’, ‘F’, ENQ, ‘(‘
Note: Limited ASCII chart on p. 142
4.2
ASCII Representation of Numbers
• Terminal I/O (keyboard, display) only deals with
ASCII characters
NULL Termination
• Typically, strings of characters
• “We’re #1” --> 87,101,44,114,101,32,35,49,0
• Note that the number ‘1’ is represented by 49
• Numbers in I/O consist of their ASCII representations
• To output 103, use ASCII values 49, 48, 51 (3 bytes)
• Outputting 103 (one byte) won’t work
code for ‘g’
‘1’, ‘0’, ‘3’
4.2
Number Systems- Negative Numbers
• What about negative numbers?
• We need to represent numbers less than zero as well
as zero or higher
• In n bits, we get 2n combinations
• Make half positive, half negative...
First method: use an extra bit for the sign
0 000 0000 0000 0000 0000 0000 0000 0101
1 000 0000 0000 0000 0000 0000 0000 0101
Sign bit: 0-->positive, 1-->negative
+5
-5
31 remaining bits for magnitude
4.2
Sign and Magnitude Representation
-7
Seven Negative
Numbers and
“Negative” Zero
-6
1111
+0
0001
1110
-5
+1
0000
1101
-4
1100
-3
1011
-2
0010
Inner numbers: 0011 +3
Binary
representation 0100 +4
1010
0101
1001
-1
+2
+5
Note: Example is shown
for 4-bit numbers
Seven Positive
Numbers and
“Positive” Zero
0110
1000
-0
0111
+6
+7
• High order bit is sign: 0 = positive (or zero), 1 = negative
• Three low order bits represent the magnitude: 0 (000) through 7 (111)
• Number range for n bits = +/- 2n-1 -1
• Two different representations for 0!
• Two discontinuities
4.2
Two’s Complement Representation
-1
Re-order
Negative
Numbers to
Eliminate
Discontinuities
-2
1111
+0
0001
1110
-3
+1
0000
1101
-4
1100
-5
1011
-6
0010
Inner numbers: 0011 +3
Binary
representation 0100 +4
1010
0101
1001
-7
+2
Note: Example is shown
for 4-bit numbers
Eight Positive
Numbers
+5
0110
1000
-8
0111
+6
+7
• Only one discontinuity now
• Only one zero
• One extra negative number
Note: Negative numbers
still have 1 for MSB
4.2
2’s Complement Negation Method #1
To calculate the negative of a 2’s complement number:
1. Complement the entire number
2. Add one
Examples:
n = 0110= 6
complement
1001
add 1
-n =1010 = -6
WARNING: This is for calculating
the negative of a number. There is
no such thing as “taking the 2’s
complement of a number”.
n = 01000100 = 68
complement
n = 10010000= -112
complement
10111011
add 1
01101111
add 1
-n =10111100 = -68
-n =01110000 = 112
2’s Complement Negation Method #2
To calculate the negative of a 2’s complement number:
1. Starting at LSB, search to the left for the first one
2. Copy (unchanged) all of the bits to the right of the first one and
the first one itself
3. Complement the remaining bits
Examples:
n = 0110= 6
complement
copy
n = 01000100 = 68
complement
copy
-n = 10111 100 = -68
-n = 1010 = -6
n = 10010000= -112
complement
copy
-n = 01110000 = 112
Adding Two’s Complement Numbers
Just add the complete
numbers together.
4
0100
-4
1100
+3
0011
+ (-3)
1101
7
0111
-7
11001
Sign taken care of
automatically.
4
0100
-4
1100
-3
1101
+3
0011
1
10001
-1
1111
Ignore carry-out (for now)
A carry out from sign bit does not necessarily mean overflow!
4.3
Overflow
Add two positive numbers to get a negative number
or two negative numbers to get a positive number
-1
Not a discontinuity No Overflow
-2
1111
+0
0001
1110
-3
1101
0010
+2
-4
1100
0011
+3 -7 - 2 = +7
-5
1011
0100
+4
-6
1010
0101
1001
A carryout from the
MSB could mean
crossing at either of
these places – One is
OK, one is Overflow
5 + 3 = -8
+1
0000
-7
0110
1000
-8
0111
+5
Overflow occurs when
crossing discontinuity
+6
+7
Overflow cannot occur when
adding a positive and negative
number together
4.3
Detecting Overflow
Overflow occurs when:
We add two positive numbers and obtain a negative
We add two negative numbers and obtain a positive
Looking at the sign bit (MSB):
+
+
+
Cout
0
0
+0
0
Cin
0
No overflow
+
+
-
Cout
0
0
+0
1
Cin
1
Overflow
+
Cout
1
1
+1
0
Cin
0
Overflow
Overflow when carry in to sign
bit does not equal carry out
-
Cout
1
1
+1
1
Cin
1
No Overflow
Cin
Cout
+
-
Cout
0
1
+0
1
Cin
0
+
+
No Overflow
Cout
1
1
+0
0
No Overflow
Overflow
4.3
Cin
1
Signed and Unsigned operations
Consider the following:
$t0 = 0000 0000 0000 0000 0000 0000 0000 0101
$t1 = 1111 1111 1111 1111 1111 1111 1111 1001
execute:
slt $s0, $t0, $t1
What’s the result?
If we mean for $t0 to be 5 and $t1 to be 4,294,967,289 (treat
as unsigned integers) then $s0 should get 1
If we mean for $t0 to be 5 and $t1 to be -7 (treat as signed
integers) then $s0 should get 0
The default is to treat as signed integers
Use sltu for unsigned integers
4.2
Using more bits
What’s different between 4-bit 2’s complement and 32-bit?
MSB has moved from bit 3 to bit 31!
Sign Extension
To convert from 4-bit 2’s complement to 32-bit:
Copy all 4 bits to 4 Least significant bits of the 32-bit number.
Copy MSB of original number into all remaining bits
4-bit
2’s comp.
0111
710
0000 0000 0000 0000 0000 0000 0000 0111
710 (32-bit 2’s comp.)
1010
-610
1111 1111 1111 1111 1111 1111 1111
-610 (32-bit 2’s comp.)
1010
4.2
Loading a single byte from memory
We can read a single 8-bit byte from memory location 3000 by using:
lb $t0, 3000($0)
# read byte at mem[3000]
assuming mem[3000] = 0xF3, we get...
$t0: 0xFFFFFFF3
(sign-extension for other 3 bytes)
0x prefix means Hex
If we only want the byte at 3000 (without extension), used an unsigned load:
lbu $t0, 3000($0)
# read byte a mem[3000]
$t0: 0x000000F3
(no sign-extension)
4.2
There is logic to it
and
or
Rd, Rs, Rt
Rd, Rs, Rt
Rd <-- Rs • Rt
Rd <-- Rs  Rt
Note: Bit numbering
starts at zero.
AND, OR are bitwise logic operations
0010 0011 0111 0110 1010 1111 0000 1101
OR 1001 1010 1000 0101 0001 1011 1010 0011
1011 1011 1111 0111 1011 1111 1010 1111
Example: Set bit 7 of $s9 to ‘1’ (Don’t mess with the other 31 bits)
ori
$s9, $s9, 0x0080
0x0080 = 0000 0000 1000 0000
Example: Clear bit 14 of $t3 to ‘0’
andi
$t3, $t3, 0xBFFF 0xBFFF = 1011 1111 1111 1111
4.4
Shift Instructions
sll
$s3, $t2, 1
# $s3 <-- $t2 shifted left 1 bit
Old MSB: Bit-bucketed
$t2
0010 0011 0111 0110 1010 1111 0000 1101
$s3
0100 0110 1110 1101 0101 1110 0001 101 0
0
New LSB: Zero
Opcode
srl
RS
$t3, $s4, 5
RT
RD ShAmt Function
R-Type Instruction
# $t3 <-- $s4 right shifted 5 bits
4.4
To access only part
of a word, we need
the bits on the RHS
Using Shifts
1. You need only the 2nd byte of a 4-byte word
$t1
0010 0011 0111 0110 1010 1111 0000 1101
srl $t1, $t1, 8
$t1
$t1
8
0000 0000 0010 0011 0111 0110 1010 1111
0000 0000 0000 0000 0000 0000 1111 1111
andi $t1, $t1, 0x00FF
0000 0000 0000 0000 0000 0000 1010 1111
Must isolate only
the 8 bits on RHS
Note - extended
with 16 0’s
2. You want to multiply $t3 by 8 (note: 8 equals 23)
$t3
0000 0000 0000 0000 0000 0000 0000 0101
sll $t3, $t3, 3
$t3
(equals 5)
# move 3 places to the left
0000 0000 0000 0000 0000 0000 0010 1000
(equals 40)
4.4
Arithmetic and Logic Unit
• The ALU is at the heart of the CPU
• Does math and logic
• The ALU is primarily involved in R-type instructions
• Perform an operation on two registers and produce a
result
• Where is the operation specified?
• The instruction type specifies the operation
• The ALU will have to be controlled by the instruction
opcode
Constructing an ALU - Logic Operations
Start out by supporting AND and OR operations
Operation
2-to-1 Mux
A
AB
0
Result
B
1A+B
If Operation = 0, Result = A • B
If Operation = 1, Result = A  B
Two operands, two results.
We need only one result...
The Operation input comes from logic that looks at the opcode
4.5
Half Adder
Ai
0
0
1
1
Bi Sum CarryOut
0
0
0
1
1
0
0
1
0
1
0
1
A half adder adds two bits, A and B
and produces a Sum and CarryOut
Ai
+
Bi
CarryOut
Sum = Ai Bi  Ai Bi
= Ai Bi
CarryOut = Ai Bi
Sum
Ai
Sum
Bi
CarryOut
Problem: We often need to add two bits and a CarryIn...
4.5
A full adder adds two bits, A and B, and a
CarryIn and produces a Sum and CarryOut
Full Adder
A
0
0
0
0
1
1
1
1
CarryIn
A1
Sum
+
B1
CarryOut
Cout
Cin
Sum
A
AB
00
01
11
10
0
0
0
1
0
1
0
1
1
1
B
Cin
B
0
0
1
1
0
0
1
1
Cin
0
1
0
1
0
1
0
1
Cout
0
0
0
1
0
1
1
1
A
AB
00
01
11
10
0
0
1
0
1
1
1
0
1
0
Cout = AB BCin ACin
Sum
0
1
1
0
1
0
0
1
B
Sum = A B  Cin
4.5
Adding to our ALU
Cin Op (2 bits)
(Op is now 2 bits)
A
CarryIn Operation
B
A
0
Result
Cin
Result
ALU
Cout
Cout
11
B
Add an Adder
+
2
Operation Function
00
A•B
01
AB
10
A+B
CarryOut
Connect CarryIn (from previous bit) and CarryOut (to next bit)
Expand Mux to 3-to-1 (Op is now 2 bits)
4.5
Putting it all together
• Stack 32 of our 1-bit ALU’s
together
• Each one gets one bit from
A and one from B
• Connect to common
Operation controls
• Now we can do 32-bit AND
and OR operations
• Connect Cout’s to Cin’s
• Now, 32-bit adds will work
• Note: Carry will ripple
through the stages, one at
a time
• Ripple-Carry Adder
Cin
A0
B0
A1
B1
A2
B2
A31
B31
Operation
Cin
ALU0
Cout
Result0
Cin
ALU1
Cout
Result1
Cin
ALU2
Cout
Result2
Cin
ALU31
Cout
Result31
Cout
4.5
Subtracting
• Our ALU can add now, but
what about subtraction?
• To compute A - B, we can
instead compute A + (-B)
• In 2’s complement,
-B = B + 1
• Add an inverter, and a signal
BInvert to get B
• Now, how about that +1?
• CarryIn to LSB is unused
(always zero)
• Set it to 1!
• Subtraction just sets BInvert
and Cin to 1
Set to 1 for LSB
BInvert
CarryIn Operation
A
0
1
B
B
0
1
+
2
CarryOut
For subtraction:
Set CarryIn of LSB to 1,
Set BInvert to 1
4.5
Result
Support for SLT
BInvert
• We need to support the SLT
CarryIn
Operation
A
operation
• Set Result to
0000 0000 0000 0000
0000 0000 0000 0001 if A <B
• A<B is equivalent to (A - B) < 0
• Subtract B from A
• If the result is negative, then
0
1
B
0
+
Result
2
1
3
Less
CarryOut
Less will be ‘0’ for bits
set LSB of Result to ‘1’, all
1-31, special for bit 0
others to ‘0’
• The result is negative if the
MSB after the subtraction is
‘1’ (Two’s complement)
We’re going to have to do something different
for the MSB and the LSB
4.5
That tricky MSB
• To properly execute the
SLT, we need to Set the
LSB if the MSB is ‘1’
• (After a subtraction)
• Can’t use the ‘Result’ of
the MSB
• Op will set the Mux to the
‘Less’ Field
• Bring out the adder
output directly: ‘Set’
CarryIn Operation
BInvert
A
0
1
Result
B
0
+
2
1
Less
3
Set
MSB Only
• Also, we need to check for
overflow
• Overflow if Cin to MSB is
different from Cout of MSB
CarryOut OverFlow
4.5
The Whole Thing
• Our new and improved 32-bit
ALU
BInvert
A0
B0
• Connect ‘0’ to all the Less
inputs except LSB
• Connect ‘Set’ output of MSB
to ‘Less’ Input of LSB
• Set the LSB during SLT
when negative
Operation
Cin
ALU0
Result0
Less
Cout
• Add the BInvert control to
each bit
Cin
A1
B1
0
A2
B2
0
Cin
ALU1
Result1
Less
Cout
Cin
ALU2
Result2
Less
Cout
• Output OverFlow from MSB
A31
B31
0
Result31
OverFlow
Cin
ALU31
Less
Cout
Set
Cout
4.5
One Last
Change
BInvert
A0
B0
Cin
Operation
Cin
Result0
ALU0
Less
Cout
We need to add a check
to see if the result is zero
A1
B1
0
Cin
ALU1
Result1
Less
Cout
Zero
Operation
A2
B2
0
A
Zero
Result
OverFlow
B
Cout
A31
B31
0
Cin
ALU2
Less
Cout
Result2
Result31
Cin
ALU31
Less
Cout
OverFlow
Set
Cout
4.5
ALU Functions
Function
And
Or
Add
Subtract
SLT
BInv Op
0
00
0
01
0
10
1
10
1
11
Carryin
0
0
0
1
1
Result
R =A•B
R =AB
R =A+B
R =A-B
R = 1 if A < B
0 if A B
Since Binvert and Carryin are always
the same, we can combine them in to a
single signal subtract
We also have zero-detect for BEQ,
BNE (use subtract).
BInvert
CarryIn Operation
A
0
1
Result
B
0
1
+
2
3
Less
CarryOut
Note: Adding would be a lot
faster if we didn’t use a ripplecarry adder...
Skipping over Shift operations...
4.5
Multiplication
421
x 123
1263
842
+ 421
51783
Multiplying two numbers A and B
n partial products, where B is n digits long
n additions
In Binary...
Each partial product is either:
110 (A*1) or 000 (A*0)
Note: Product may take as many
as two times the number of bits!
110
x 101
110
000
+ 110
11110
6x5
Equals 30
4.6
Multiplication Steps
00
111
01
x 11
0
01
110
0000
+ 11000
01
1
0110
Step1: LSB of multiplier is 1 --> Add a copy of multiplicand
Step2: Shift multiplier right to reveal new LSB
Shift multiplicand left to multiply by 2
Step 3: LSB of multiplier is 0 --> Add zero
Step 4: Shift multiplier right, multiplicand left
Step5: LSB of multiplier is 1 --> Add a copy of multiplicand
Done!
Thus, we need hardware to:
1. Hold multiplier (32 bits) and shift it right
2. Hold multiplicand (32 bits) and shift it left (requires 64 bits)
3. Hold product (result) (64 bits)
4. Add the multiplicand to the current result
4.6
Multiplication
We need hardware to:
1. Hold multiplier (32 bits) and shift it right
2. Hold multiplicand (32 bits) and shift it left (requires 64 bits)
3. Hold product (result) (64 bits)
4. Add the multiplicand to the current result
Algorithm:
5. Control the whole process
initialize registers;
Multiplicand ShLeft
64 bit
for (i=0; i<32; i++) {
ShRight
if LSB(multiplier)==1{
Multiplier
product += multiplicand;
32 bit
64-bit
}
left shift multiplicand 1;
Product
Write
64 bit
Control
right shift multiplier 1;
}
4.6
Multiplication example: 1101 x 0101
Multiplicand
Multiplier Product
•1-->Add Multiplicand to Product
•Shift M’cand left, M’plier right
xxxx1101
0101
xxx11010
0010
•0-->Do nothing
•Shift M’cand left, M’plier right
xx110100
0001
x1101000
0000
00001101
+
01000001
11010000
0000
01000001
Initial Values
•1-->Add Multiplicand to Product
•Shift M’cand left, M’plier right
xxxx1101
ShLeft
•0-->Do nothing
•Shift M’cand left, M’plier right
8 bit
ShRight
8-bit
000000000
Write
Control
0101
4 bit
00000000
+
00001101
1101 x 0101 =
01000001
13 x 5 = 65
Note: Using 4/8 bit values for
example.
Assume unsigned integers.
8 bit
4.6
Improved Multiplier
Even though we’re only adding 32 bits at a time, we need a 64-bit adder
Results from shifting multiplicand left over and over again
Instead, hold the multiplicand still and shift the product register right!
Now we’re only adding 32 bits each time
Algorithm:
Extra bit for carryout
Multiplicand
MultiplicandShLeft
64 bit
32 bit
ShRight
initialize registers;
Multiplier
ShRight
32 bit
Multiplier
for (i=0; i<32; i++) {
if LSB(multiplier)==1{
LH product += multiplicand;
32 bit
64-bit
32-bit
Control
}
Write
64 bit
Write
LHProduct
Product RH
Product
64 bit
right shift product 1;
ShRight
Control
right shift multiplier 1;
}
4.6
Improved Multiplier: 1101 x 0101
Initial Values
Multiplicand
•1-->Add Multiplicand to LH Product
•Shift Product right, M’plier right
0011
+ 1101
10000
•0-->Do nothing
•Shift Product right, M’plier right
•1-->Add Multiplicand to Product
•Shift Product right, M’plier right
•0-->Do nothing
•Shift Product right, M’plier right
Multiplicand
ShRight
32 bit
32-bit
Control
Write
64 bit
LH Product RH Product
ShRight
Multiplier Product
1101 0101
0000 xxxx
+
1101 xxxx
0110 1xxx
1101 0101
1101 x010
1101 xx01
1101 xx01
1101 xxx0
0011 01xx
+
10000 01xx
1000 001x
1101 xxxx
0100 0001
Multiplier
32 bit
1101 x 0101 =
01000001
13 x 5 = 65
4.6
Improved Improved Multiplier
Note that we’re shifting bits out of the multiplier and into the product
Why not put these together into the same register
As space opens up in the multiplier, overwrite it with the product bits
Algorithm:
Multiplicand
ShRight
32 bit
32-bit
Multiplier
initialize registers
32 bit
(multiplier in RH product);
for (i=0; i<32; i++) {
if LSB(multiplier)==1{
Control
LH product += multiplicand;
Write
64 bit
LH Product RH
Product
Multiplier
64 bit
ShRight
}
right shift product-multiplier 1;
}
4.6
Improved Multiplier: 1101 x 0101
Initial Values
Multiplicand
•1-->Add Multiplicand to LH Product
•Shift Product-M’plier right
0011
+ 1101
10000
•0-->Do nothing
•Shift Product-M’plier right
•1-->Add Multiplicand to Product
•Shift Product-M’plier right
•0-->Do nothing
•Shift Product-M’plier right
Product-Multiplier
1101 0000 0101
+
1101 1101 0101
1101 0110 1010
1101 0011 0101
+
1101 10000 0101
1101 1000 0010
1101 0100 0001
Multiplicand
32 bit
32-bit
Control
Write
LH Product Multiplier
64 bit
ShRight
1101 x 0101 =
01000001
13 x 5 = 65
4.6
MIPS Multiplying
MIPS hardware does
32-bit multiplies
32-bit x 32-bit --> 64 bit
Rs
32 bit
32-bit
Control
Write
Hi
Lo
64 bit
ShRight
mult Rs, Rt -->
Upper 32-bits of result in Hi
Lower 32-bits of result in Lo
The 64-bit product register is divided into two parts:
Hi: Holds upper 32 bits of product
Lo: Holds lower 32 bits
mfhi
mflo
$t5
$t6
# move Hi to register $t5
# move Lo to register $t6
mul Rd, Rs, Rt -->
mult Rs, Rt
mflo Rd
4.6
Dividing
divisor
quotient
3221
15 48323
-45
33
-30
32
-30
23
-15
remainder
8
Dividend = Divisor * Quotient + Remainder
dividend
14
5
Idea: Repeatedly subtract
divisor. Shift as appropriate.
0111 0
101 1001001
-000
1001
-101
1000
-101
110
-101
11
3 -000
11
4.7
73
Division
We need hardware to:
1. Hold divisor (32 bits) and shift it right (requires 64 bits)
2. Hold remainder (64 bits)
3. Hold quotient (result) (32 bits) and shift it left
4. Subtract the divisor from the current result Algorithm:
5. Control the whole process
initialize registers
Divisor
ShRight
64 bit
64-bit
Remainder
Write
64 bit
(divisor in LHS);
for (i=0; i<33; i++) {
remainder -= divisor;
if (remainder < 0)
ShLeft
{
Quotient
remainder+=divisor;
32 bit
left shift quotient 1, LSB=0
} else {
left shift quotient 1, LSB=1
Control
}
right shift divisor 1
}
4.6
Division
Example:
1001001/0101
Quotient Divisor
Initial Values (Divisor in LHS)
•1a. Rem. <-- Rem-Divisor
•1b. Rem.<0, Add Div., LSh Q, Q0=0; RSh Div.
•2a. Rem. <-- Rem-Divisor
•2b. Rem>=0, LSh Q, Q0=1; RSh Div.
•3a. Rem. <-- Rem-Divisor
•3b. Rem>=0, LSh Q, Q0=1; RSh Div.
•4a. Rem. <-- Rem-Divisor
•4b. Rem>=0, LSh Q, Q0=1; RSh Div.
•5a. Rem. <-- Rem-Divisor
•5b. Rem<0, Add Div., LSh Q, Q0=0; RSh Div.
Divisor
ShRight
64 bit
64-bit
Remainder
Write
64 bit
ShLeft
Quotient
32 bit
Control
Remainder
xxxx
xxxx
01010000 01001001
01010000 11111001
xxx0
xxx0
xx01
xx01
00101000 01001001
00101000 00100001
2
00010100 00100001
00010100 00001101
x011
x011
00001010 00001101
00001010 00000011
0111
0111
00000101 00000011
00000101 11111110
1110
00000010 00000011
1
3
1001001/0101 = 1110 rem 0011
73/5 = 14 rem 3
N+1 Steps, but first step cannot produce a 1.
4.7
4
5
Improved Divider
As with multiplication, we’re using a 64-bit divisor and a 64-bit ALU
when there are only 32 useful bits.
The 64-bit divisor is needed just to provide the correct alignment.
Instead of shifting the divisor right, we shift the remainder left.
Also, since we know the first subtraction is useless,
Algorithm:
don’t do it (still shift the remainder left, though).
initialize registers
(Changes from 33 iterations to 32!)
for (i=0; i<32; i++) {
Divisor
left shift remainder 1;
Divisor ShRight
32 bit
LH remainder -= divisor;
64 bit
ShLeft
if (remainder < 0)
ShLeft Quotient
{
Quotient
LH remainder+=divisor;
32 bit
32 bit
32-bit
left shift quotient 1, LSB=0;
64-bit
} else {
Write
left shift quotient 1, LSB=1;
Control
LH Rem.
RH Rem. ShLeft
Control
Remainder Write
}
64 bit
64 bit
}
4.6
Improved Divider: 1001001/0101
Initial Values
•0. LSh Rem
•1a. Rem. <-- Rem-Divisor
•1b. Rem>=0, LSh Q, Q0=1; LSh Rem.
•2a. Rem. <-- Rem-Divisor
•2b. Rem>=0, LSh Q, Q0=1; LSh Rem.
•3a. Rem. <-- Rem-Divisor
•3b. Rem>=0, LSh Q, Q0=1; LSh Rem.
•4a. Rem. <-- Rem-Divisor
•4b. Rem<0, Add Div., LSh Q, Q0=0
Divisor
32 bit
ShLeft
32-bit
LH Rem.
RH Rem.
64 bit
Write
ShLeft
Control
Quotient
32 bit
Quotient Divisor
Remainder
xxxx
xxxx
0101
0101
01001001
1001001x
xxxx
0101
xxx1
xxx1
xx11
xx11
0101
0101
0101
0101
x111
x111
0101
0101
0011xxxx
1110xxxx
1110
0101
0011xxxx
-
0100001x
1
100001xx
001101xx
2
01101xxx
00011xxx
-
3
1001001/0101 = 1110 rem 0011
73/5 = 14 rem 3
4.7
4
Improved Improved Divider
Note that the remainder is emptying at the same rate that the quotient is filling.
Combine the two!
A problem: We’re shifting the remainder left 33 times, but it should be 32.
(Quotient doesn’t exist on first iteration, so it’s shifted only 32 times)
Undo the extra shift by shifting the remainder (LH remainder-quotient) right by
1 at the end
Algorithm:
initialize registers
left shift rem-quotient 1;
Divisor
Divisor
for (i=0; i<32; i++) {
32 bit32 bit
LH remainder -= divisor;
ShLeft
if (remainder < 0)
Quotient
{
32 bit
LH remainder+=divisor;
32-bit
32-bit
left shift rem-quotient 1, LSB=0;
} else {
Write Write
ShLeft Control
Control
LH
Rem.
Rem-Quot.
ShLeft
LH Rem.
RH Rem.
left shift rem-quotient 1, LSB=1;
64
bit
64 bit
}
}
right shift LH remainder-quotient 1
4.6
Improved Improved
Divider:
1001001/0101
Initial Values
Divisor Remainder-Quotient
•0. LSh Rem-Quo.
•1a. Rem <-- Rem-Divisor
•1b. Rem>=0, LSh Rem-Quo, Q0=1
•2a. Rem. <-- Rem-Divisor
•2b. Rem>=0, LSh Rem-Quo, Q0=1
•3a. Rem. <-- Rem-Divisor
•3b. Rem>=0, LSh Rem-Quo, Q0=1
•4a. Rem. <-- Rem-Divisor
•4b. Rem<0, Add Div., LSh Rem-Quo, Q0=0
Divisor
32 bit
•Final: RSh Rem 1
32-bit
LH Rem.
Rem-Quot.
64 bit
Write
ShLeft
Control
0101
0101
0101
0101
0101
0101
0101
-
01001001
10010010
01000010
1
10000101
00110101
2
01101011
00011011
-
3
0101
0101
00110111
11100111
0101
0101
01101110
00111110
4
1001001/0101 = 1110 rem 0011
73/5 = 14 rem 3
4.7
MIPS Dividing
MIPS hardware does
64-bit / 32-bit division
Divisor
32 bit
Result has two parts:
Quotient in Lo
Remainder in Hi
32-bit
Hi
Lo
64 bit
Write
ShLeft
div $t1,$t2
Lo = $t1/$t2 (integer)
Hi = $t1 % $t2
Control
pseudoinstructions:
div $t0, $t1, $t2
$t0 = $t1/$t2 (integer)
rem $t3, $t1, $t2
$t3 = $t1 % $t2
4.6
Floating Point Numbers
• Floating point is used to represent “real” numbers
• 1.23233, 0.0003002, 3323443898.3325358903
• Real means “not imaginary”
• Computer floating-point numbers are a subset of real
numbers
• Limit on the largest/smallest number represented
• Depends on number of bits used
• Limit on the precision
• 12345678901234567890 --> 12345678900000000000
• Floating Point numbers are approximate, while
integers are exact representation
4.8
Scientific Notation
+ 34.383 x 102 = 3438.3
Sign
Significand
Exponent
+ 3.4383 x 103 = 3438.3
Normalized form: Only one
digit before the decimal point
+3.4383000E+03 = 3438.3
Floating point notation
8 digit significand can only represent 8 significant digits
4.8
Binary Floating Point Numbers
+ 101.1101
= 1 x 22 + 0 x 21 + 1 x 20 + 1 x 2-1 + 1 x 2-2 + 0 x 2-3 + 1 x 2-4
= 4 + 0
+
1 + 1/2 + 1/4 + 0
+ 1/16
= 5.8125
+1.011101 E+2
Normalized so that the binary point
immediately follows the leading digit
Note: First digit is always non-zero
--> First digit is always one.
4.8
IEEE Floating Point Format
31 30
23 22
8 bits
Sign
0: Positive
1: Negative
0
23 bits
Exponent
Significand
Biased by 127.
Leading ‘1’ is implied, but not
represented
Number = -1S * (1 + Sig) x 2E-127
• Allows representation of numbers in range 2-127 to 2+128 (10±38)
• Since the significand always starts with ‘1’, we don’t have to
represent it explicitly
• Significand is effectively 24 bits
• Zero is represented by Sign=Significand=Exp=0
4.8
IEEE Double Precision Format
Sign
63 62
52 51
11 bits
20 bits
Exponent
31
32
Bias:1023
Significand
0
32 bits
Number = -1S * (1 + Sig) x 2E-1023
• Allows representation of numbers in range 2-1023 to 2+1024(10± 308)
• Larger significand means more precision
• Takes two registers to hold one number
4.8
Conversion
Convert 5.75 to Single-Precision IEEE Floating Point
1. Convert 5.7510 to Binary ---> 101.112
2. Normalize
---> 1.0111 x 22
Significand
Exponent
3. Sign = 0 (positive).
4. Add 127 (bias) to exponent. Exponent = 12910 = 100000012
5. Express significand as 24 bits
Sig = 1.01110000000000000000000
6. Remove leading one from significand, leaving 23 bits
Sig = .01110000000000000000000
7. Put in proper bit fields
Number = 0 10000001 01110000000000000000000 = 0x40B80000
4.8
Adding Floating Point Numbers
1.2232E+3 + 4.211E+5
1. Normalize to higher exponent
a. Find the difference between exponents (= 2)
b. Shift smaller number right by that amount
1.2232E+3 == 0.012232E+5
2. Now that exponents are the same, add significands together
4.211
E+5
+
0.012232 E+5
4.223232 E+5
5.0 E+2
Note: If carry out of MSD, re-normalize + 7.0 E+2
12.0 E+2 = 1.2 E+3
4.8
Adding IEEE Floating Point Numbers
SE
Sig.
0x45B8CD8D --> 0 8B 38CD8D = 5913.69410
+ 0x46FC8672 --> 0 8D 7C8672 = 32323.2210
1. Check for Sign=Exp=Significand=0 --> If so, treat as a special case
2. Put the ‘1’ back in bit 23 of significands
38CD8D = 011 1000 1100 1101 1000 1101
---> 1011 1000 1100 1101 1000 1101 = B8CD8D
7C8672 =
111 1100 1000 0110 0111 0010
---> 1111 1100 1000 0110 0111 0010 = FC8672
0 8B B8CD8D
+ 0 8D FC8672
4.8
Adding IEEE Floating Point Numbers
0 8B B8CD8D
+ 0 8D FC8672
3. Normalize to higher exponent:
a. Find difference in exponents: 8D - 8B = 2
b. Shift significand of number with smaller exponent right by the difference
B8CD8D =
1011 1000 1100 1101 1000 1101
right shift by 2 --> 0010 1110 0011 0011 0110 0011 = 2E3363
c. Set lower-valued exponent to higher one
0 8D 2E3363 (re-normalized form of 0 8B B8CD8D)
+ 0 8D FC8672
4.8
Adding IEEE Floating Point Numbers
0 8D 2E3363
+ 0 8D FC8672
4. Add significands: (note: carry produced one too many bits)
0010 1110 0011 0011 0110 0011
+ 1111 1100 1000 0110 0111 0010
1 0010 1010 1011 1001 1101 0101 = 12AB9D5
5. Since bit 24 is ‘1’, we must re-normalize by shifting significand right
1 and incrementing exponent by one.
1 0010 1010 1011 1001 1101 0101
SRL --> 1001 0101 0101 1100 1110 1010 = 955CEA (significand)
exp: 8D --> 8E
Result is:
6. Get rid of bit 23 in significand (for IEEE standard) 0 8E 155CEA
or 0x47155CEA
1001 0101 0101 1100 1110 1010
= 38236.9110
--> 001 0101 0101 1100 1110 1010 = 155CEA
Bit 24
4.8
Multiplying Floating Point Numbers
34.233 E +09 * 212.32 E +03
1. Add exponents: --> 9 + 3 = 12
2. Multiply significands --> 34.233 * 212.32 = 7268.35056
3. Result is 7268.35056 E +12
4. Normalize: 7.26835056 E +15
5. Truncate extra bits... --> 7.26835 E +15
4.8
Multiplying IEEE Floating Point Numbers
0 8B 38CD8D = 5913.69410
x 0 8D 7C8672 = 32323.2210
1. Check for zero.
2. Add exponents. (Note: both have the bias of 127 already. Only
want to bias once, so subtract 127 (7F) .)
8B + 8D - 7F = 99
3. Put ‘1’ back onto bit 23, multiply significands.
38CD8D --> B8CD8D
Multiplying two 24-bit numbers with 23 bits to
7C8672 --> FC8672
the right of the binary point – result has 48
bits, with 46 bits to the right of the point
B8CD8D * FC8672 =
10.11 0110 0100 1011 0110 0100 1010 1111 0101 0110 1100 1010
4.8
Multiplying IEEE Floating Point Numbers
0 8B 38CD8D = 5913.69410
x 0 8D 7C8672 = 32323.2210
10.11 0110 0100 1011 0110 0100 1010 1111 0101 0110 1100 1010
5. Re-normalize so one place to left of binary point.
1.011 0110 0100 1011 0110 0100 1010 1111 0101 0110 1100 1010
(Add one to exponent) --> 99 + 1 = 9A
6. Remove extra bits so only 24 bits remain
1.011 0110 0100 1011 0110 0100
7. Remove implied one (bit 23)
011 0110 0100 1011 0110 0100
Result is: 0 9A 364B64 = 191149632.174710
4.8
Instruction
R5
R6
R7
Addr:Data
1
add $6, $0, $0
2
addi $7, $0, 8
(ARRAY)
6000: 0xBA
6004: 0x0B
3
lb $5, ARRAY($7)
6008: 0xAC
4
srl $5, $5, 28
600C
5
lbu $6, ARRAY($0)
6010
6
andi $5, $6, 0x5
6014
7
bne $5, $0, EXIT
6018
8
addi $5, $0, 0x1234
601C
9
li $7, 0x1000
6020
10
mult $7, $5
11
mfhi $7
12
mflo $5
13
sw $5, ARRAY($0)
14
addi $sp, $sp, -4
15
sw $7, 0($sp)
16
lw $5, 0($sp)
17
addi $sp, $sp, 4
18
EXIT:
Instruction
R5
R6
R7
Addr:Data
1
add $6, $0, $0
2
addi $7, $0, 8
(ARRAY)
6000: 0x0A
6004: 0x0B
3
lb $5, ARRAY($7)
6008: 0x0C
4
srl $5, $5, 28
600C
5
lbu $6, ARRAY($0)
6010
6
ori $5, $6, 0x5
6014
7
beq $5, $0, EXIT
6018
8
addi $5, $0, 0x1234
601C
9
li $7, 0x1000
6020
10
div $7, $5
11
mfhi $7
12
mflo $5
13
sw $5, ARRAY($0)
14
addi $sp, $sp, -4
15
sw $7, 0($sp)
16
lw $5, 0($sp)
17
addi $sp, $sp, 4
18
EXIT:
Example
• Write a program that reads a 4-element row and column vectors
from memory and
• Multiplies both by a scalar also found in memory
• Calculates the scalar product of the two vectors
• Assume no partial product may exceed 32 bits
• Use v1= [1 2 3 4], v2= [0 1 2 3]T, s=5 as test inputs
.data
V1: .word 1, 2, 3, 4 #vector1
V2T: .word 0, 1, 2, 3 #transpose vector2
S: .word 5
SV1: .space 16
SV2T: .space 16
V1V2: .space 4
Example 2
• Write a program that finds the greatest common
divisor of two integers found in memory by
repeatedly dividing and incrementing.
.data
NUM1:
NUM2:
MSG1:
MSG2:
.word 5 #for test
.word 7 #for test
.asciiz “the common divisor is:”
.asciiz “No common divisor except 1!”
.text
main:
gcd=1;
count=2;
while
(count < a && count < b)
{if (a%gcd=0 && b%gcd=0)
gcd++
count++}
WHILE:
SKIP:
CHECK:
PRINT:
exit:
addi $t0, $0, 2 #initialize GCD
addi $t3, $0, 0 #current GCD
lw $t1, NUM1($0) #num1 in t1
lw $t2, NUM2($0) #num2 in t2
div $t1,$t0
mfhi $t4 #remainder in $t4
bne $t4, $0, SKIP #if remainder not zero,
#no point dividing the other
div $t2, $t0
mfhi $t4
bne $t4,$0, SKIP #NOT a CD
move $t3, $t0
#t3 has current GCD
bgt $t0, $t1, CHECK
#equal to num1, exit
bgt $t0, $t2, CHECK
#equal to num2, exit
addi $t0, $t0, 1
#try next integer
j WHILE
bne $t3, $0, PRINT
#print GCD
la $a0, MSG2
li $v0, 4
syscall
j exit
la $a0, MSG1
#printing MSG1
li $v0, 4
syscall
move $a0, $t3
#printing GCD
li $v0,1
syscall
li $v0, 10
syscall
Related documents