程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Vdsp(bf561)中的浮點運算(7):float乘法運算

Vdsp(bf561)中的浮點運算(7):float乘法運算

編輯:關於C++

1.1 Vdsp對float乘法運算的處理

在vdsp下,可以很簡單地用:

float mul (float x, float y)
{
float r = x * y;
return r;
}

來完成浮點乘法運算,編譯器自動將裡面的乘法操作轉換為___float32_mul的函數調用,這個函數的調用實現在libdsp/fpmult.asm中,在這個文件的開頭說明了這個函數的用法:

/***************************************************************************
Copyright (c) 2000-2008 Analog Devices Inc. All rights reserved.

****************************************************************************
File name :  fpmult.asm

This function performs 32 bit floating point multiplication. Implemention
is based on the algorithm mentioned in the reference. Some more conditionS
are added in the present algorithm to take care of various testcases.

Registers used:
Operands in  R0 & R1
R0 - X operand,
R1 - Y operand
R2 - R7


Special case:
1) If (x AND y) == 0, Return 0,
2) Overflow  :  If(Exp(x) + Exp(y) > 254,
Return 0X7F80000 or 0xFF80000
depending upon sign of X and y.

3) Underflow :  If(Exp(x) + Exp(y) <= -149, RETURN 0.

Reference  : Computer Architecture a Quantitative Approach 2nd Ed.
by Jhon l Hennessy and David Patterson

!!NOTE- Uses non-standard clobber set in compiler:
DefaultClobMinusBIMandLoopRegs

Remember to change the #pragma regs_clobbered in fpmult.c in softfloat if you
change this clobber set

**************************************************************/

1.2 當x和y都為0

看實現代碼:

R2 = R0^R1;   /* sign of the result of X * Y */ 
P0 = R2;     /* Store sign  */
R2 = R0 << 1;  /* Remove the sign bit of X */
CC = R2 == 0;
R3 = R1 << 1;   /* Remove the sign bit of Y */
CC |= AZ;
IF CC JUMP .HANDLE_ZERO_OP;
………..
.HANDLE_ZERO_OP:
// One operand is zero. If the other is NaN or inf, return NaN, otherwise
// zero
R2 = R2 | R3;
R2 = R2 >> 24;
R3 = MAXBIASEXP+1;  // Max biased exponent
CC = R2 == R3;
R0 = 0;
IF !CC JUMP .SIGN_RESULT; // Return zero (signed appropriately)
R0 = -1;  // return default NAN
RTS;    // no regs to restore on this path

當x和y都為0時,直接返回0,此時的操作需要的CYCLE數為12。

這裡一個比較有意思的事情是0是可以有正負號的,也就是說如果計算0.0 * (-0.0),那麼結果的符號位保持為負!

1.3 當x為nan或者inf

看代碼:

[--SP] = (R7:4);  /* Push registers R4-R7 */
R4 = MAXBIASEXP+1; /* Max biased exponent */

/* Get exponents. */
R2 = R2 >> 24;  /* Exponent of X operand */
R3 = R3 >> 24;  /* Exponent of Y operand */
CC = R2 == R4;
IF CC JUMP .HANDLE_NAN_INF_X;
……………..
.HANDLE_NAN_INF_X:
// Return signed inf if X=inf, and Y is either inf or a non-zero number
// Otherwise return NaN
R5 = R1 << 1;  // If Y = 0
CC = AZ;           // Return NaN
IF CC JUMP .RET_DEFAULT_NAN;
CC = R3 < R4;  // if y exp is valid
R5 = R1 << 9;  // or if Y significand is zero
CC |= AZ;
R5 = R0 << 9;  // then Y is either inf or a valid number
CC &= AZ;    // And if X is inf, then return inf, otherwise NaN
IF !CC JUMP .RET_DEFAULT_NAN;
.RET_INF:
R0 = 0x7F8 (Z);
R0 <<= 21;
(R7:4) = [SP++]; /* Pop registers R4-R7 */

.SIGN_RESULT:
CC = P0 < 0;   /* Extract sign, and set into result */
R0 = ROT R0 BY -1;  /* by rotating back with CC */
RTS;

.RET_DEFAULT_NAN:
R0 = -1;
(R7:4) = [SP++];  /* Pop registers R4-R7 */
RTS;

l 當x為inf且y為inf或者非0值

結果為inf。

mul (inf, inf)的結果為inf。

mul (inf, 1.0)的結果為inf。

此時的符號位仍然根據兩個操作數的符號位來確定。

此時的操作需要的CYCLE數為53。

l 當x為inf且y為0

結果為NAN。

l 當x為inf且y為-inf

結果為-inf

1.4 當y為nan或者inf

看代碼:

CC = R3 == R4;
IF CC JUMP .HANDLE_NAN_INF_Y;
…………..
// Handle certain identities concerning multiplying by NaNs and +/-inf
.HANDLE_NAN_INF_Y:
// Swap operands and exponents
R5 = R0;
R0 = R1;
R1 = R5;
R5 = R2;
R2 = R3;
R3 = R5;

.HANDLE_NAN_INF_X:
………..

簡單交換xy,然後和上一個判斷條件相同。

1.5 向上溢出

當兩個操作數的指數相加大於254時,認為溢出:

// Compute result exponent, and check for overflow
R4 = BIASEXP;
R5 = R2 + R3;
R5 = R5 - R4;
R4 <<= 1;    // R4 now 254, max allowed exponent
CC = R4 < R5;
IF CC JUMP .RET_INF;
……………
.RET_INF:
R0 = 0x7F8 (Z);
R0 <<= 21;

(R7:4) = [SP++]; /* Pop registers R4-R7 */

.SIGN_RESULT:
CC = P0 < 0;  /* Extract sign, and set into result */
R0 = ROT R0 BY -1; /* by rotating back with CC */
RTS;

理解這段代碼有點費勁,因為float能表示的最大指數是127,那麼應該是大於127就認為溢出,為什麼要和254做比較呢?

判斷條件應該是在

(e1 – 127) + (e2 - 127) > 127

時溢出,在上面的代碼裡相當於等價改為e1 + e2 – 127 > 254

為何不干脆改為e1 + e2 > 381呢?

奇怪!

溢出計算時的CYCLE值為52。

1.6 正常計算

在正常計算一個浮點乘法時,所用的CYCLE值為92,居然比做浮點加減所用的CYCLE少,一個出乎意料的結果!

1.7 向下溢出

在代碼說明裡給出的下溢條件是

Exp(x) + Exp(y) <= -149

為什麼為是這樣的條件呢?想不通!看來非得去看看Reference提及的書才行。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved