ZHCUBL2K January 2018 – March 2024
对于 C7000 编译器,__float2_t
传统类型始终被视为 double
。这对于 C7000 编译器有效,因为 double 是 64 位宽,可以容纳两个 32 位浮点元素以用于 SIMD 运算。
如果使用在 Intel x86 架构上执行的主机系统,则情况并非如此。在 Intel x86 计算机上执行双精度型的加载和存储时,会发生自动转换,将 64 位双精度型转换为 80 位“扩展实数”类型。当使用双精度型来存储两个不同的 32 位浮点值时,这会带来问题,因为 80 位“扩展实数”类型会进行规范化,从而改变存储器中的位。如果对表示两个 32 位浮点类型的 double 进行规范化的 80 位类型扩展,则无法再保证数据,并且期望两个浮点值的 SIMD 运算将产生不一致的结果。
为解决此问题,C7000 主机仿真针对 __float2_t
类型包含一个单独的类定义,该定义被视为不透明容器类型。容器类型只能使用特殊的内在函数进行修改、访问和初始化。虽然 __float2_t
类定义包含公共访问器方法,但建议仅使用内在函数来修改 __float2_t
类型,因为 C7000 主机仿真 __float2_t
类型的任何成员都不会在 C7000 编译器中定义。当传统内在函数中需要表示两个 32 位浮点值的单个数据结构时,应使用 __float2_t
类类型。在编写利用 C6000 旧版构造的 C7000 主机仿真代码时,double
类型只能用于表示一个双精度浮点值。
由于 __float2_t
类型有单独的定义,因此必须使用 _ftof2
内在函数来构造 __float2_t
类型。对于 C7000 编译器,此内在函数定义为 _ftod
,它根据两个浮点指针参数创建一个 double 类型。__float2_t
的访问器方法以相同的方式定义。
表 8-1 列出了明显定义用于 C7000 主机仿真的内在函数。尽管此表中所列内在函数的定义有所不同,但为 C7000 主机仿真编写的旧代码无需更改即可传输到 C7000 编译器。
内在函数名称 | 以前的定义 | 函数 |
_ftof2 | _ftod | 从 2 个浮点值构造 __float2_t 类型 |
_lltof2 | _lltod | 将 long long 值转换为 __float2_t 类型 |
_f2toll | _dtoll | 将 __float2_t 类型转换为 long long |
_hif2 | _hif | 从 _float2_t 类型访问高 32 位 float |
_lof2 | _lof | 从 _float2_t 类型访问低 32 位 float |
_fdmv_f2 | _fdmv | 使用 PACK 指令从 2 个 float 构造 __float2_type 的替代方法 |
_fdmvd_f2 | _fdmvd | 使用 PACKWDLY4 指令从 2 个 float 构造 __float2_type 的替代方法 |
_hif2_128 | _hid128 | 从 __x128_t 类型访问高 __float2_t 类型 |
_lof2_128 | _lod128 | 从 __x128_t 类型访问低 __float2_t 类型 |
_f2to128 | _dto128 | 根据 2 个 __float2_t 类型构造 _x128_t 类型 |
以下示例以注释中所示的有效和无效方式构造和设置 __float2_t
变量。
/* __float2_t type examples: Host Emulation Code */
#include <c7x.h>
#include <c6x_migration.h>
int main(){
// Valid ways to construct a __float2_t
__float2_t src1 = _ftof2(1.1022, 2.1010);
__float2_t src2 = _ftof2(-1.1, 4.10101);
// Invalid way to construct a __float2_t in Host Emulation
// __float2_t from_double = (double)1.0;
// Legal to set a __float2_t from other pre-constructed
// __float2_t types (done using intrinsic)
src1 = src2;
// It is illegal to set a __float2_t type via a
// constructor call. The following will not compile:
// src1 = __float2_t(1.0, 2.0);
// Correct way to access lo/hi
float lo_correct = _lof2(src1);
// Intrinsic use example
__float2_t res = _daddsp(src1, src2);
return 0;
}