1.11k likes | 1.22k Views
第 八 章 运 算 方 法. 执行算术和逻辑运算的指令以及微操作是任何 CPU 的一个必不可少的重要部分。. 1. 几种 常用数据格式 的 算术运算算法 和它们的 硬件实现 。包括 定点数 表示及其加、减、乘、除过程和硬件实现, 二 — 十进制 (或 BCD ) 码 的格式和操作。. 2. 提高算术操作性能的 专用硬件 。 (流水线、查找表、华莱士树). 3. 介绍 浮点数 的格式和它们的算术操作。包括浮点数的格式,性质,以及加、减、乘、除过程和硬件实现,还有 IEEE 754 浮点数标准。. 8.1 无符号表示法.
E N D
第 八 章 运 算 方 法
执行算术和逻辑运算的指令以及微操作是任何CPU的一个必不可少的重要部分。执行算术和逻辑运算的指令以及微操作是任何CPU的一个必不可少的重要部分。 1. 几种常用数据格式的算术运算算法和它们的硬件实现。包括定点数表示及其加、减、乘、除过程和硬件实现,二—十进制(或BCD)码的格式和操作。 2. 提高算术操作性能的专用硬件。 (流水线、查找表、华莱士树) 3. 介绍浮点数的格式和它们的算术操作。包括浮点数的格式,性质,以及加、减、乘、除过程和硬件实现,还有IEEE 754浮点数标准。
8.1 无符号表示法 有两种常用的无符号表示法: 非负数码:表示0或一个正数。n位非负数码的数值范围为0 (所有位都为0)到2n-1(所有位都为1)。 2的补码(简称补码):既能表示正数又能表示负数。n位数 的数值范围为 -2n-1到2n-1-1。当最高位为1时表示负数,最高位为0时表示正数(包括0)。正数(包括0)的补码与非负数码相同,负数的补码为其绝对值的2的补码,等于它的绝对值按位取反(该数的1的补码,简称为反码),加1。
例如,求-5的4位补码表示,首先求出它的绝对值5(0101),产生反码值1010,再加1得补码1011。例如,求-5的4位补码表示,首先求出它的绝对值5(0101),产生反码值1010,再加1得补码1011。 下表列出了8位二进制数的非负数码和补码表示的数值。 表8.1 无符号表示的数值
8.1.1 加法和减法 加法直接采用二进制加法实现,硬件中通过使用一个并行加法器来实现,如下图所示。 X和Y是8位寄存器,该电路实现微操作 ADD:X←X+Y 只要结果在正常范围内(对非负数码而言为0到2n-1,对2的补码而言为-2n-1到2n-1-1),该电路就能得到正确的结果。 图8.1 微操作X←X+Y的实现
当结果不能表示为一个8位数值时就会导致溢出:当结果不能表示为一个8位数值时就会导致溢出: 例如,非负数码加法255 +1,即1111 1111 + 0000 0001,直接加得 1 0000 0000,有9位,不能存于8位寄存器中。 并行加法器产生额外的进位输出,它用来标志算术溢出。在非负数码中,这个进位能置溢出标志,它提示系统产生了溢出,所得结果不完全正确,系统应进行相应的结果修复处理或错误处理。 在补码中,判断溢出不但要检查进位输出,还要检查结果最高位的进位输入。如果这两者相等,那么不产生溢出,否则产生溢出。见下图:
溢出 溢出 图8.2 补码加法的溢出产生 在(a)和(c)中最高位的进位输入和进位输出相等,不产生溢出;而在(b)和(d)中两者不等,产生溢出。
减法可以转换成加法,即X – Y通过执行X +(-Y)来实现。首先将Y转换成 –Y的补码,再将 –Y的补码与X的补码相加即可得X – Y的补码:[X – Y]补=[X]补+[-Y]补 左图给出了执行微操作 SUB:X←X–Y 的一种硬件实现。 图8.3 微操作X←X–Y的实现
对于非负数码,减法的结果不会比2n-1大,但可能比0小。例如,1–2执行为0000 0001+1111 1110 = 1111 1111,即255。 此时,如果减法(通过补码加法实现)产生了进位输出0而不是1时,则发生了溢出。 溢出 图中 (b)和(d)溢出,而 (a)和(c)没有溢出。 溢出 图8.4 无符号2的补码减法的溢出产生 同样,补码减法也将X–Y转换成X +(–Y)来执行,而判断溢出的条件与补码加法相同。
8.1.2 乘法 乘法可以看成加法的重复。一个数乘以n与n个该数相加的结果相同。可以用下列算法来实现乘法x×y。 z = 0; FOR i = 1 TO y DO { z = z + x } 这种算法不理想,原因是速度慢、计算x×y的时间不确定。我们希望不论x 、y取何值,执行乘法的时间相同。 x = 2 7 y = 2 5 3 8 1 1 3 5 5 4 6 8 3 1
这个过程被称为移位——相加乘法。首先计算每个部分积并左移到正确位置,然后再将所有的部分积相加。这个过程被称为移位——相加乘法。首先计算每个部分积并左移到正确位置,然后再将所有的部分积相加。 对这个算法稍做修改,使得硬件实现更为简单,就可得到无符号非负二进制数的乘法基本算法。 第一个修改是每求出一个部分积后就计算和: 因为硬件上,二输入加法器很容易实现,而三输入或多输入的加法器则变得非常复杂。 x = 2 7 y = 2 5 3 8 1 1 3 5 1 4 3 1 ←计算的和 5 4 6 8 3 1 ←最终计算的和 任何时候都没有多于两个数的加。 注意:每一个部分积都逐次左移一位,因此排列的位置不同。在当前和与部分积的相加中,某些位的运算不必要。
第二个修改用右移当前和代替左移部分积: x = 27 y = 253 81 ←右移一位 81 ← 1被右移出,故不参加加法运算 135 1431 ←右移一位 1431 ← 3 1被右移出,故不参加加法运算 54 6831 ← 最后右移一位 6831 每次都是相同的两列数字进行加法。已经右移到这两列右边的数字只是简单的写下,不进行加法。
若用二进制,被乘数不是乘以0就是乘以1,因此部分积不是0(X×0 = 0)就是被乘数的值(X×1 = X)。 算法 :两个n位寄存器的值X和Y的移位——相加乘法 n位寄存器U和V:保存结果 (中U保存结果的高n位,V保存结果的低n位) C是一位寄存器:用来保存执行加法时的进位 U = 0; FOR i = 1 TO n DO { IF Y0 = 1 THEN CU = U + X; 线性右移CUV; 循环右移 Y }
考虑乘法: 13×11,即1101×1011 初始化X = 1101,Y = 1011
算法的RTL代码如下所示。注意:当i = 0时,Z = 1;而1,2,3是连续的状态,即算法是由状态1到2再到3的。 1:U←0,i←n Y02:CU←U + X 2:i←i-1 3:shr(CUV),cir(Y) Z’3:GOTO 2 Z 3: FINISH←1 表8.3列出了13×11的RTL代码的执行步骤。同样初始化X = 1101,Y = 1011。除了在每个周期增加了满足的条件和执行的微操作外,表8.3同表8.2一样。
根据 RTL代码设计硬件。 硬件包括两部分:寄存器部分,微操作在此执行; 控制部分,产生需要的控制信号和状态值。 X —— n位寄存器 Y、U、V —— n位移位寄存器 (当SHR信号有效时它们右移一位) 寄存器i ——存储值n的递减计数器 C和FINISH ——一位寄存器 在寄存器之间设置数据通路来实现RTL代码中的微操作所要求的数据传送。 将i的所有位异或在一起产生Z,即仅当i的所有位都为0(i = 0)时,Z才为1。
3 图8.5 移位——相加乘法算法的 硬件实现
考察图8.5给出的控制部分,看它是如何实现RTL代码的。考察图8.5给出的控制部分,看它是如何实现RTL代码的。 当START置1时,State Counter和FINISH清零,Decoder工作。Decoder输出1,使U清零,数n装载到i中。 State Counter加1到01, Decoder输出2。使i减1,并且,若Y0 = 1,将U + X保存在CU中;若Y0 = 0,则C、U的值不变。 State Counter加1到10, Decoder输出3。此时,C、U、V都右移一位。以下两件事必有一件发生: 当Z = 0时,State Counter被装载值01, Decoder输出2,实现操作“GOTO 2”。 否则Z = 1时,FINISH置1,Decoder使能端置0,不再输出1,2,3,硬件停止工作。
如果不要求保存原值,则可以进一步优化算法,使硬件实现更简单。特别是如果Y值不要求保存,可将其值保存在V寄存器中,则乘法转换为UV←X × V。每次检查V的最低位V0,若为1,执行加法。下一步执行右移时,该位将丢弃,因为它不再需要使用。修改后的RTL代码为: 1:U←0,i←n V02:CU←U + X 2:i←i-1 3:shr(CUV) Z’3:GOTO 2 Z 3: FINISH←1 与前面的代码有两处不同:一是CU←U + X的条件由Y02改为V02;二是减少了cir(Y)的操作。 除了C和U的LD信号改为V0∧2,以及去掉了寄存器Y之外,该代码的硬件实现与图8.5的相同。
下表显示改进后的RTL代码执行13 × 11的步骤。 表8.4 改进后的RTL代码的执行步骤 除了初始化V寄存器和去掉Y寄存器之外,该表与表8.3相同。
8.1.2.1 布斯算法 对于无符号补码数据,上面的算法并不总能得出正确的结果。上一个例子( 13 × 11)中,1101 和1011的补码表示分别为–3和-5,它们的积应是+15;而上面的算法将得出结果1000 1111,即 –113,显然是错的。 原因是该算法仅能处理两个正数相乘,当有一个或两个操作数为负数时,通过执行下面的程序,上面的算法仍然可以使用: IF 被乘数< 0 THEN 被乘数←- 被乘数; IF 乘数< 0 THEN 乘数←- 乘数; 用非负数乘法进行乘法运算; 恢复被乘数和乘数的原值; IF 被乘数和乘数中有一个为负数,并且另一个非零, THEN 结果←- 结果
这个算法很麻烦,而booth’s算法比它简单。该算法直接对补码数据进行运算,不需进行正数和负数之间的转换。这个算法很麻烦,而booth’s算法比它简单。该算法直接对补码数据进行运算,不需进行正数和负数之间的转换。 booth’s算法也检查乘数的每一位,并把当前和右移一位。不同的是,并不是乘数的每个1都执行加法;而是对于一串1的第一个1执行减法,对于一串1的最后一个1执行加法。 booth’s乘法UV←X×Y,U、V、X、Y为n位值,Y-1为1位值: U = 0;Y-1 = 0; FOR i = 1 TO n DO {IF 一串1的开始 THEN U = U – X(= U + X’ + 1); IF 一串1的结尾 THEN U = U + X; 算术右移 UV; 循环右移 Y并将Y0复制给Y-1 }
检查Y的一串1的关键是要保留上一次Y的最低位。如果Y的最低位Y0和最后移出的位为:检查Y的一串1的关键是要保留上一次Y的最低位。如果Y的最低位Y0和最后移出的位为: 10,则该1开始了一串1,执行减法; 01,则该0结束了一串1,执行加法; 11,则在一串1中,不做任何操作。 00,则该算法既不需要加法又不需要减法。 为了检查这两位,用一个1位寄存器Y-1来保存最后移出的位。它被初始化为0,以保证Y的第一串1能被检查到。 表8.5列出了当X = -3(1101)和Y = -5(1011)时,该算法的步骤。算法能得出正确结果0000 1111(+15)。
表8.5 booth’s算法的步骤 如果乘数的最高位为1,则最后一个循环中不可能出现加法。
该算法的RTL代码。信号START和一位寄存器FINISH用于初始化和终止算法。算法中U、V、X、Y为n位值,Y-1为一位值。循环计数器i为递减计数器,由n递减到0。 1:U←0,Y-1←0,i←n Y0Y-1’2:U←U + X’ + 1 Y0’Y-12:U←U + X 2:i←i-1 3:ashr(UV),cir(Y),Y-1←Y0 Z’3:GOTO 2 Z 3: FINISH←1 注意,条件Y0Y-1’对应于一串1的开始,执行减法;Y0’Y-1对应于一串1的结尾,执行加法。加、减法语句可合并一起: (Y0⊕Y-1)2:U←U +(X⊕Y0)+ Y0
该RTL代码执行(-3)×(-5)的步骤,初始化X=1101,Y=1011。 表8.6 booth’s算法RTL代码的执行步骤 与移位——相加算法相同,该算法也可以通过将Y的值保存在V中来去掉Y寄存器
合并后的RTL代码的硬件实现如图所示。 1 3 图8.6 booth’s算法的 硬件实现
8.1.3 除法 除法可以看成减法的重复,z = x÷y可以这样实现: Z=0; WHILE x≥y DO { z=z+1;x=x-y } 此算法效率低、执行时间随着z的最终值的不同而改变。 可采用移位——相减算法减少执行时间,例: 096 71 6827 639 437 426 11 注意第一步操作是比较除数71和被除数的前两位68。由于71大于68,故该位商0。这在计算机的除法运算中是很重要的一步,它被用来检测商是否溢出。
将被除数左移,使得每次相减的结果总是送到同一位置上。将被除数左移,使得每次相减的结果总是送到同一位置上。 左移出的位不参加减法计算 096 71 6827 00 ← 68 除以71 商0 682 ← 取出下一位 682 ← 左移一位 639 ← 682 除以71 商9 437 ← 取出下一位 437 ← 左移一位 426 ← 437 除以71 商6 11 ← 余数 第一步检查68是否大于等于71,这是一个溢出检测
溢出检测: 在除法的硬件实现中,通常被除数(如6827)保存在一个2n位的寄存器或两个n位的寄存器中。除数(71)和商(96)保存在n位的寄存器中。余数保存在被除数的两个n位寄存器中的一个中。如果被除数的高n位大于等于除数,那么商将大于n位而不能保存在商寄存器中,此时产生溢出。 例如,十进制的除法7827÷71,其中被除数为4位,除数为2位。由于78 > 71,商至少有3位,比商寄存器的位数(2位)还要多一位,因此产生溢出。 这种溢出检测的附加好处是可以防止除以0的操作,此时也会产生溢出。
采用二进制更简单,商只可能为0或1。当被除数大于等于除数时,商1;否则商0。采用二进制更简单,商只可能为0或1。当被除数大于等于除数时,商1;否则商0。 下面的算法实现了两个二进制值的移位——相减除法。被除数在初始化时加载到UV,其中U保存高n位,V保存低n位。除数和商分别保存在n位值X和Y中。余数保存在U中。C为1位值,用来保存U的移出位。 U ≥ X THEN 产生溢出并终止算法; Y = 0;C = 0; FOR i = 1 TO n DO { 线性左移 CUV; 线形左移 Y; IF CU ≥ X THEN {Y0 = 1,U = CU – X}} 考虑第一步就终止的情况。如112÷7,若n =4,则UV = 0111 0000,X = 0111。由于U≥X,均为0111,将终止算法。如果继续执行,将产生商16(1 0000)和余数0。但值1 0000不能保存在4位的Y中,产生溢出。
下表列出了该算法执行147÷13的步骤。初始化时,U = 1001,V = 0011,X = 1101,n = 4。 表8.7 移位——相减算法的执行步骤
算法的RTL代码。其中X、U、V、Y为n位值,C和OVERFLOW为1位值。当i = 0时,Z = 1;当U≥X时,G = 1。FINISHI置1则算法结束。1,2,3,4是连续的状态。 G 1: FINISH←1,OVERFLOW←1 2: Y←0,C←0,OVERFLOW←0,i←n 3: shl(CUV),shl(Y),i←i-1 (C + G)4: Y0 ←1,U←U + X’ + 1 Z’4: GOTO 3 Z 4: FINISH←1 大部分的RTL语句由算法直接转换而成,注意条件 CU≥X等价于条件 U≥X(G)或(C =1),即(C + G);补码加法:U ← U + X’ + 1实现算法中的U =CU – X 。
下表列出了该RTL代码执行除法:147÷13的执行步骤。初始化时U = 1001,V = 0011,X = 1101,n = 4。 表8.8 移位——相减除法的RTL代码的执行步骤
该算法的硬件实现。 图8.7 移位—相减除法的硬件实现
以上称为不恢复余数的除法算法,这种算法是仅当CU ≥X时,才执行减法U ← U – X。第二种类型的除法是恢复余数的除法算法。它不是在执行减法之前先检查是否CU ≥ X,它是先执行减法再比较CU是否大于等于X。如果CU < X,则该算法再执行一次U ← U + X,使U恢复为原来值。 恢复余数的算法有相同的步骤:首先检测溢出。如果没有产生溢出,则进入移位——相减循环。它们的主要区别是处理比较的方式不同。不恢复余数的算法是先进行CU和X的比较,如果CU ≥ X则执行减法U ←CU – X。恢复余数的算法则相反,先执行减法U ← U – X,如果发现CU < X(结果为负),则说明不应执行减法,此时通过执行加法U ← U + X,使U恢复为原来值。
恢复余数的算法。被除数初始化时保存在UV中,除数保存在X中,商保存在Y中,余数最后保存在U中。U、V、X、Y都是n位值,C是1位值。恢复余数的算法。被除数初始化时保存在UV中,除数保存在X中,商保存在Y中,余数最后保存在U中。U、V、X、Y都是n位值,C是1位值。 CU = U + X’ + 1; U = U + X,IF C = 1 THEN 产生溢出并终止算法; Y = 0; FOR i = 1 TO n DO { 线性左移CUV; 线形左移Y; IF C = 1 THEN { U= U+ X’ +1} ELSE{ CU= U+ X’ +1 } IF C = 1 THEN { Y0 = 1} ELSE { U = U + X } } 算法第一步为CU与X的比较 如C = 1,则CU一定比X大,执行减法U ← U + X’ + 1,并且使C仍保持1值,表示CU ≥ X。如C = 0,执行减法CU ← U + X’ + 1。该减法仅当CU ≥ X时,使C置1。结果是:无论执行哪个减法,都有U = U –X,以及当CU ≥ X时C置1,否则置0。
CU与X的比较。 操作C U = U + X’ + 1实际上实现了两个功能:显式的功能是减法U = U –X ,而隐含的功能是U和X的比较。如果U ≥ X,该操作将C置1,否则将C置0。 在(a)和(b)中,C置1,表示U ≥ X; 在(c)中,C置0,表示U < X。 图8.8 在计算C U = U + X’ + 1的同时比较了U和X:(a)正结果,(b)零结果,(c)负结果
整个算法的分析。 头两条语句是比较U和X的大小。如果U ≥ X,将产生溢出,此时U ← U + X’ + 1将C置1。否则不溢出,它将C置0。第二条语句是将U恢复为原来值,如果没有溢出,将初始化Y并进入移位——相减循环。 移位——相减循环从左移CUV和Y 开始的。而下一条语句实现了减法(U = U –X)和CU与X的比较(如果CU ≥ X则C = 1)。 如C = 1,则CU一定比X大,执行减法U ← U + X’ + 1,并且使C仍保持1值,表示CU ≥ X。如C = 0,执行减法CU ← U + X’ + 1。该减法仅当CU ≥ X时,使C置1。结果是:无论执行哪个减法,都有U = U –X,以及当CU ≥ X时C置1,否则置0。 下一条语句当C = 1时,CU ≥ X,减法有效,不需要恢复余数,只需在商的相应位(Y0)上商1。而当C = 0时,CU < X,加法将U恢复为原来值。
两个例子。 第一个例子为225÷13,它的执行步骤如表8.9(a)所示。首先初始化X = 1101,n = 4。第一个减法将C置1,说明将产生溢出。(实际上,由于225÷13 = 17 余4,而17的二进制是1 0001,因此不能存于4位的寄存器中。)下一步恢复U值并终止算法。 表8.9 恢复余数除法算法的执行步骤(a)有溢出, 另一个例子147÷13,执行步骤如表8.9(b)所示。没有溢出。算法的前几步检测溢出和初始化Y。接下来每三步为一组表示循环的一次迭代。
该算法正确地计算了147÷13,结果是:商为11,余数为4。 表8.9 恢复余数除法算法的执行步骤(b)无溢出 每次迭代都执行相似的移位和减法 / 比较操作。 每次迭代的最后一步不是更新商(保存在Y中)就是将余数恢复为原来值(保存在U中)。
恢复余数除法算法的RTL代码。 它采用的值与不恢复余数算法中采用的值基本相同。除了以下几点,它与不恢复余数算法非常接近。 ● OVERFLOW为1位值,当溢出发生时置1,否则置0。 ● FINISH为1位值,当算法终止时置1。不管是循环结束的正常终止还是溢出,都要将FINISH置1。这与本章其他算法的RTL代码是相同的。 ● 与其他算法相同,计数器i的值从n递减到0。当i = 0时,Z = 1。 ● 除非遇到GOTO操作,在正常情况下状态从11到12到2到3到41到42。状态11和12等价于不恢复余数算法中的状态1,而状态41和42等价于不恢复余数算法中的状态4。
11: CU←U + X’ + 1; 12: U←U + X C 12:FINISH←1,OVERFLOW←1 2:Y←0,OVERFLOW←0,i←n 3:shl(CUV),shl(Y),i←i-1 C 41:U←U + X’ + 1 C’41:CU←U + X’ + 1 C 42:Y0←1 C’42:U←U + X Z 42:FINISH←1 Z’42: GOTO 3 CU = U + X’ + 1; U = U + X,IF C = 1 THEN 产生溢出并终止算法; Y = 0; FOR i = 1 TO n DO { 线性左移CUV; 线形左移Y; IF C = 1 THEN { U= U+ X’ +1} ELSE{ CU= U+ X’ +1 } IF C = 1 THEN { Y0 = 1} ELSE { U = U + X } }
表8.10 恢复余数除法算法的RTL代码的执行步骤 147÷13
该算法的硬件实现如图所示。 42 减少了产生G的比较器,但并行加法器的输入更加复杂。因为此时要求它进行两种操作U + X或U – X。同时,由于有6个状态,状态计数器和译码器要稍微大一些。 图8.9 恢复余数除法的硬件实现
补码相除 补码相除没有一种通用的算法。一般是通过对正负数值进行转换来实现补码相除。该算法如下所示。除法可以使用恢复余数的硬件实现或不恢复余数的硬件实现。 IF 被除数< 0 THEN 被除数←- 被除数; IF 除数< 0 THEN 除数←- 除数; 使用恢复余数或不恢复余数的硬件实现除法运算; IF 被除数和除数中有一个为负数 THEN 结果← - 结果
8. 2 带符号表示法 符号—幅值表示法(signed_magnitude notation) 符号—补码表示法(signed_two’s complement notation) 8.2.1 符号—幅值表示法(signed_magnitude notation) 包括两个部分:符号部分为1位,0表示正数(或0),1表示负数;幅值部分为n位,以非负数码的形式表示数的绝对值。 例如:+3和-3有相同的幅值3,仅仅符号不同。在二进制中,+3表示为0(符号)0011,而-3表示为1(符号)0011。 用XsX 表示符号—幅值表示法,其中Xs为1位的符号值,X为n位幅值。
8.2.1.1 加法和减法 操作UsU←XsX±YsY,定义AS为计算操作符。AS =0表示加, =1表示减。还定义PM =Xs⊕AS⊕Ys。Xs、AS和Ys共有8种可能的组合。下表列出这些组合及其相应的PM值,同时分别给出了当X =3,Y =5和X =5,Y =3时这8种组合的结果。 表8.11 符号—幅值数据的加法和减法 PM表示实际执行是加还是减
执行何种操作由两个值决定:PM的值以及X和Y的相对幅值,相对幅值表示是X > Y、X = Y还是X < Y。分两种情况考虑:PM = 0和PM = 1。 第一种情况:PM = 0 将X和Y的幅值加在一起; 结果的符号总与第一个操作数的符号Xs相同。 通过微操作Us←Xs,U←X + Y实现。 结合考虑溢出情况,可以用CU←X + Y代替U←X + Y,并将C的值赋给溢出标志。 因此PM = 0时符号—幅值表示加减法的RTL代码为: PM’1:Us←Xs,CU←X + Y PM’2:OVERFLOW←C