Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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 AB 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 =AB 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