上一个问题中链接的document 提供了 TMS320C30 浮点格式的所有必要详细信息:Randy Restle 和 Adam Cron,“TMS320C30-IEEE 浮点格式转换器”,应用报告 SPRA400,德州仪器 1997。
TMS 格式不支持无穷大、NaN、有符号零或非正规数。 8 位指数存储为 2 的补码整数,不像 IEEE-754 binary32 格式中那样有偏差。存储有效数(尾数)时不包含与 IEEE-754 匹配的隐式整数位。但是,对于负数操作数,有效数基本上存储为负数。
要从 TMS 格式转换为 IEEE-754 binary32 格式,我们基本上需要对指数应用偏差,对负操作数的有效位取反(必要时对指数进行更正),然后重新排列符号、指数和有效数字字段的顺序。
一个小问题是 TMS 格式可以将幅度 -126 的数字表示为标准化浮点数,而 IEEE-754 binary32 只能将这些存储为次正规数。在这种情况下,我们需要使有效数字的隐藏整数位可见和非规范化。由于这会丢弃最低有效位,因此我们需要对结果进行四舍五入。
我不懂 Python,但相信下面的 ISO-C 程序很容易被该语言的熟练人员翻译成 Python。格式转换适用于相应浮点格式的位表示,因此在转换函数tms_to_ieee() 中表示为无符号 32 位整数。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
uint32_t tms_to_ieee (uint32_t a)
{
uint32_t frac = a & 0x7fffff;
uint32_t sign = (a >> 23) & 1;
uint32_t expo = (a >> 24) & 0xff;
uint32_t rslt;
if (expo == 0x80) { // zero or implied zero
expo = 0;
frac = 0;
sign = 0;
} else {
/* add IEEE exponent bias of 127 */
expo = (expo + 0x7f) & 0xff;
if (sign) {
/* complement fraction */
frac = 0x00800000 - frac;
/* propagate fraction overflow to exponent */
expo = expo + (frac >> 23);
/* clear potential overflow */
frac = frac & 0x7fffff;
}
if (expo == 0) {
/* make implicit integer bit explicit */
frac = frac + 0x00800000;
/* denormalize, round to nearest-or-even */
frac = (frac >> 1) + ((frac & 3) == 3);
}
}
rslt = (sign << 31) | (expo << 23) | frac;
return rslt;
}
float uint32t_as_float (uint32_t a)
{
float r;
memcpy (&r, &a, sizeof r);
return r;
}
#define N (60) // number of test vectors
int main (void)
{
uint32_t in[N] = {
0x7f7fffff,
0x7f7ffffe,
0x7f7ffffd,
0x7f7ffffc,
0x7f000000,
0x7e7fffff,
0x7e7ffffe,
0x7e7ffffd,
0x00000000,
0xff7fffff,
0xff7ffffe,
0xff7ffffd,
0xff000000,
0xfe7fffff,
0xfe7ffffe,
0xfe7ffffd,
0x82000000,
0x817fffff,
0x817ffffe,
0x817ffffd,
0x817ffffc,
0x81000002,
0x81000001,
0x81000000,
0x807fffff,
0x807ffffe,
0x807ffffd,
0x80000001,
0x80000000,
0x80ffffff,
0x80fffffe,
0x80fffffd,
0x80800003,
0x80800002,
0x80800001,
0x80800000,
0x81ffffff,
0x81fffffe,
0x81fffffd,
0x81800002,
0x81800001,
0x81800000,
0x82ffffff,
0x82fffffe,
0x82fffffd,
0xff800001,
0xff800000,
0x00ffffff,
0x00fffffe,
0x00fffffd,
0x00800001,
0x00800000,
0x01ffffff,
0x01fffffe,
0x01fffffd,
0x7fffffff,
0x7ffffffe,
0x7ffffffd,
0x7f800001,
0x7f800000,
};
float out[N] = {
(2-exp2(-23)) * exp2(127),
(2-exp2(-22)) * exp2(127),
(2-exp2(-21)+exp2(-23)) * exp2(127),
(2-exp2(-21)) * exp2(127),
exp2(127),
(2-exp2(-23)) * exp2(126),
(2-exp2(-22)) * exp2(126),
(2-exp2(-21)+exp2(-23)) * exp2(126),
1,
1-exp2(-24),
1-exp2(-23),
1-exp2(-22)+exp2(-24),
exp2(-1),
(2-exp2(-23)) * exp2(-2),
(2-exp2(-22)) * exp2(-2),
(2-exp2(-21)+exp2(-23)) * exp2(-2),
exp2(-126),
(2-exp2(-23)) * exp2(-127),
(2-exp2(-22)) * exp2(-127),
(2-exp2(-21)+exp2(-23)) * exp2(-127),
(2-exp2(-21)) * exp2(-127),
(1+exp2(-22)) * exp2 (-127),
(1+exp2(-23)) * exp2 (-127),
exp2(-127),
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
(-1-exp2(-23)) * exp2(-127),
(-1-exp2(-22)) * exp2(-127),
(-1-exp2(-21)+exp2(-23)) * exp2(-127),
(-2+exp2(-22)) * exp2(-127),
(-2+exp2(-23)) * exp2(-127),
-exp2(-126),
(-1-exp2(-23)) * exp2 (-126),
(-1-exp2(-22)) * exp2 (-126),
(-1-exp2(-21)+exp2(-23)) * exp2 (-126),
-1+exp2(-24),
-exp2(0),
(-1-exp2(-23)) * exp2(0),
(-1-exp2(-22)) * exp2(0),
(-1-exp2(-21)+exp2(-23)) * exp2(0),
-2+exp2(-23),
-2,
-2-exp2(-22),
-2-exp2(-21),
-2-exp2(-20)+exp2(-22),
(-1-exp2(-23)) * exp2(127),
(-1-exp2(-22)) * exp2(127),
(-1-exp2(-21)+exp2(-23)) * exp2(127),
(-2+exp2(-23)) * exp2(127),
-exp2(128)
};
for (int i = 0; i < N; i++) {
uint32_t argi = in [i];;
uint32_t resi = tms_to_ieee (argi);
float resf = uint32t_as_float (resi);
float reff = out[i];
printf ("tms=%08x ieee=%08x % 15.8e ref=% 15.8e %s\n",
argi, resi, resf, reff, (resf == reff) ? "PASS" : "FAIL");
}
return EXIT_SUCCESS;
}
包含的小测试程序的输出应该类似于:
tms=7f7fffff ieee=7f7fffff 3.40282347e+038 ref= 3.40282347e+038 PASS
tms=7f7ffffe ieee=7f7ffffe 3.40282326e+038 ref= 3.40282326e+038 PASS
tms=7f7ffffd ieee=7f7ffffd 3.40282306e+038 ref= 3.40282306e+038 PASS
tms=7f7ffffc ieee=7f7ffffc 3.40282286e+038 ref= 3.40282286e+038 PASS
tms=7f000000 ieee=7f000000 1.70141183e+038 ref= 1.70141183e+038 PASS
tms=7e7fffff ieee=7effffff 1.70141173e+038 ref= 1.70141173e+038 PASS
tms=7e7ffffe ieee=7efffffe 1.70141163e+038 ref= 1.70141163e+038 PASS
tms=7e7ffffd ieee=7efffffd 1.70141153e+038 ref= 1.70141153e+038 PASS
tms=00000000 ieee=3f800000 1.00000000e+000 ref= 1.00000000e+000 PASS
tms=ff7fffff ieee=3f7fffff 9.99999940e-001 ref= 9.99999940e-001 PASS
tms=ff7ffffe ieee=3f7ffffe 9.99999881e-001 ref= 9.99999881e-001 PASS
tms=ff7ffffd ieee=3f7ffffd 9.99999821e-001 ref= 9.99999821e-001 PASS
tms=ff000000 ieee=3f000000 5.00000000e-001 ref= 5.00000000e-001 PASS
tms=fe7fffff ieee=3effffff 4.99999970e-001 ref= 4.99999970e-001 PASS
tms=fe7ffffe ieee=3efffffe 4.99999940e-001 ref= 4.99999940e-001 PASS
tms=fe7ffffd ieee=3efffffd 4.99999911e-001 ref= 4.99999911e-001 PASS
tms=82000000 ieee=00800000 1.17549435e-038 ref= 1.17549435e-038 PASS
tms=817fffff ieee=00800000 1.17549435e-038 ref= 1.17549435e-038 PASS
tms=817ffffe ieee=007fffff 1.17549421e-038 ref= 1.17549421e-038 PASS
tms=817ffffd ieee=007ffffe 1.17549407e-038 ref= 1.17549407e-038 PASS
tms=817ffffc ieee=007ffffe 1.17549407e-038 ref= 1.17549407e-038 PASS
tms=81000002 ieee=00400001 5.87747316e-039 ref= 5.87747316e-039 PASS
tms=81000001 ieee=00400000 5.87747175e-039 ref= 5.87747175e-039 PASS
tms=81000000 ieee=00400000 5.87747175e-039 ref= 5.87747175e-039 PASS
tms=807fffff ieee=00000000 0.00000000e+000 ref= 0.00000000e+000 PASS
tms=807ffffe ieee=00000000 0.00000000e+000 ref= 0.00000000e+000 PASS
tms=807ffffd ieee=00000000 0.00000000e+000 ref= 0.00000000e+000 PASS
tms=80000001 ieee=00000000 0.00000000e+000 ref= 0.00000000e+000 PASS
tms=80000000 ieee=00000000 0.00000000e+000 ref= 0.00000000e+000 PASS
tms=80ffffff ieee=00000000 0.00000000e+000 ref= 0.00000000e+000 PASS
tms=80fffffe ieee=00000000 0.00000000e+000 ref= 0.00000000e+000 PASS
tms=80fffffd ieee=00000000 0.00000000e+000 ref= 0.00000000e+000 PASS
tms=80800003 ieee=00000000 0.00000000e+000 ref= 0.00000000e+000 PASS
tms=80800002 ieee=00000000 0.00000000e+000 ref= 0.00000000e+000 PASS
tms=80800001 ieee=00000000 0.00000000e+000 ref= 0.00000000e+000 PASS
tms=80800000 ieee=00000000 0.00000000e+000 ref= 0.00000000e+000 PASS
tms=81ffffff ieee=80400000 -5.87747175e-039 ref=-5.87747175e-039 PASS
tms=81fffffe ieee=80400001 -5.87747316e-039 ref=-5.87747316e-039 PASS
tms=81fffffd ieee=80400002 -5.87747456e-039 ref=-5.87747456e-039 PASS
tms=81800002 ieee=807fffff -1.17549421e-038 ref=-1.17549421e-038 PASS
tms=81800001 ieee=80800000 -1.17549435e-038 ref=-1.17549435e-038 PASS
tms=81800000 ieee=80800000 -1.17549435e-038 ref=-1.17549435e-038 PASS
tms=82ffffff ieee=80800001 -1.17549449e-038 ref=-1.17549449e-038 PASS
tms=82fffffe ieee=80800002 -1.17549463e-038 ref=-1.17549463e-038 PASS
tms=82fffffd ieee=80800003 -1.17549477e-038 ref=-1.17549477e-038 PASS
tms=ff800001 ieee=bf7fffff -9.99999940e-001 ref=-9.99999940e-001 PASS
tms=ff800000 ieee=bf800000 -1.00000000e+000 ref=-1.00000000e+000 PASS
tms=00ffffff ieee=bf800001 -1.00000012e+000 ref=-1.00000012e+000 PASS
tms=00fffffe ieee=bf800002 -1.00000024e+000 ref=-1.00000024e+000 PASS
tms=00fffffd ieee=bf800003 -1.00000036e+000 ref=-1.00000036e+000 PASS
tms=00800001 ieee=bfffffff -1.99999988e+000 ref=-1.99999988e+000 PASS
tms=00800000 ieee=c0000000 -2.00000000e+000 ref=-2.00000000e+000 PASS
tms=01ffffff ieee=c0000001 -2.00000024e+000 ref=-2.00000024e+000 PASS
tms=01fffffe ieee=c0000002 -2.00000048e+000 ref=-2.00000048e+000 PASS
tms=01fffffd ieee=c0000003 -2.00000072e+000 ref=-2.00000072e+000 PASS
tms=7fffffff ieee=ff000001 -1.70141204e+038 ref=-1.70141204e+038 PASS
tms=7ffffffe ieee=ff000002 -1.70141224e+038 ref=-1.70141224e+038 PASS
tms=7ffffffd ieee=ff000003 -1.70141244e+038 ref=-1.70141244e+038 PASS
tms=7f800001 ieee=ff7fffff -3.40282347e+038 ref=-3.40282347e+038 PASS
tms=7f800000 ieee=ff800000 -1.#INF0000e+000 ref=-1.#INF0000e+000 PASS