2.2 数据类型

2.2.1 使用数据格式

Blackfin处理器主要是16位定点处理器。大多数操作都采用补码数表示方法,其他的则采用无符号数或者简单的二进制串。一些指令支持32 位整数算术,具有更多特征来支持8位算术和块浮点。处理器支持32-bit字、16-bit半字和字节,32-bit和16-bit字可以是整数或小数,但字节总是整数。整数数据类型可以是有符号数或无符号数,小数类型是有符号数。

二进制串 二进制串格式是最简单的二进制表示,其中16位当做比特模式。使用这种格式来计算的例子是逻辑操作NOT、AND、OR、XOR,这些ALU操作把它们的操作数当做二进制串,不规定符号位或者二进制小数点的位置。

无符号数 无符号二进制数可认为是正数,几乎能表示相同长度的有符号数的2倍幅度,处理器把多倍精度数最低有效字当做无符号数。

有符号数(补码) Blackfin处理器算术中有符号字是补码数,大多数Blackfin处理器成员都支持补码算术。

小数表示(1.15) Blackfin处理器对于1.15二进制格式小数算术是优化的。在1.15格式中,有1个符号位(最高有效位,MSB)和15个小数位,可以表示-1~0.999969的值。如图2-3所示为1.15数的位权重和一些具体值及其对应的小数。

图2-3 1.15数的位权重

表2-2举例说明了存储器、寄存器文件以及An里的数据的格式。注意表中下列符号的含义:s为符号位,d为数据位,“.”为约定的小数点,斜体表示数据是来源于一个源而不是邻近的位。

表2-2 数据格式

一些指令在寄存器中将数据符号扩展或零扩展到32位:对于无符号数据进行零扩展;对于有符号16-bit半字和8-bit字节进行符号扩展。另外一些指令按32-bit数处理数据。另外,两个16-bit半字或4个8-bit字节可当做32-bit值进行处理。内部和外部存储器访问都采用little endian字节序。

ALU数据类型 ALU结果将产生状态信息。关于如何使用其状态信息,请参见“ALU指令汇总”。ALU结果状态位把结果当做有符号的,指示状态有溢出标志(AV0、AV1)和负数标志(AN),每个ALU都有它的黏性溢出标志(AV0S或AV1S),一旦置位将保持置位状态直到直接写入ASTAT寄存器而清除。另一个V标志的置位或清除取决于从An到Rn的结果的传送,黏性VS位随V位一同置位并保持置位状态直到清0。溢出位(V、VS、AV0、AV0S、AV1、AV1S)逻辑都是基于补码算术。如果MSB的改变方式不是操作数符号位和操作本身特性所预测的方式,那么一个位或一个组合位都会置位。例如,两个正数相加,结果也必为正数。符号位的改变表示溢出并使相应的溢出标志AVn置位。一个正数和一个负数相加可能产生一个正数或者一个负数,但是不会导致溢出。进位(AC0、AC1)逻辑是基于无符号数算术。如果是从位16(MSB)产生了进位就会将进位置位,进位对于一个多字操作的低位字部分来说是非常有用的。

乘法器数据类型 根据指令本身给定的信息,输入被解释成不同的类型:有符号数乘以有符号数、无符号数乘以无符号数、混合类型,或者是一个圆整操作。乘法器的32位结果假定是有符号的,也是符号扩展的,充满A0或A1寄存器的整个40-bit的宽度。处理器支持两种调整模式:小数模式,用于小数操作数(1.15格式);整数模式,用于整型操作数(16.0格式)。当处理器将两个1.15操作数相乘时,结果是一个2.30(2个符号位和30个小数位)的数。小数模式里在把结果传送到乘法器结果累加器An之前左移一位,使得乘法器结果是1.31格式的,它可以圆整为1.15格式。在整数模式里,则不会发生左移,如果操作数都是16.0格式,乘法结果将是32.0格式。当用乘法器结果更新An,或将它们传送到目的寄存器时,将产生状态信息。更多信息请参见“乘法器指令汇总”。

移位器数据类型 移位器中的许多操作是明确地采用有符号(补码)或无符号数——逻辑移位采用无符号数或二进制串,算术移位采用补码数。指数逻辑采用补码数,指数逻辑支持块浮点,这也是基于补码的小数。移位器结果产生状态信息,关于使用移位器状态的更多信息参见“移位器指令汇总”。表2-3~表2-6总结了一些计算操作算术特性。

表2-3 ALU算术格式

表2-4 乘法器小数模式格式

表2-5 乘法器算术整数模式格式

表2-6 移位算术格式

2.2.2 使用乘法器整数和小数格式

对于乘累加功能,处理器提供了两种选择——小数(1.15)的小数算术和整数(16.0)的整数算术。不管是小数还是整数操作,都将把乘法器输出输送到一个40-bit的加法器/减法器,在A0或A1的当前值上加上或减去这个新的乘积,得到最终的40位的结果。

圆整乘法器结果 很多乘法器操作上都支持乘法器结果的圆整(RND选项)。圆整是降低数值精度的一种方式,它去除一个数的比特中的低位部分,并可能修改该数的剩余部分以更精确地表示它原来的值。若原来的数有N比特的精度,而新的数只有M比特的精度(N >M),这个圆整处理就会去除该数N-M比特的精度。寄存器ASTAT里的位RND_MOD决定了RND选项是有偏还是无偏圆整,该位清0对应无偏圆整,该位置1对应有偏圆整。对所有算法,无偏圆整是首先的。

1.无偏圆整

无偏圆整返回一个最接近原始数的值,当原始数刚好位于两个数中间时返回最接近的偶数,最低有效位是0。例如,要圆整一个3-bit的补码小数0.25(二进制0.01)到2-bit的补码小数,其结果将是0.0(二进制0.0),因为是从0.5(二进制0.1)和0.0中选择偶数。由于它是基于附近的值向上和向下圆整,所以该方法称为无偏圆整。

累加器使用无偏圆整方案。传统的有偏圆整方法是在加法器的比特位置15 上加上一个1,这个方法将引起一个净正偏差,因为中间值(A0.L/A1.L=0x8000)总是向上圆整的。无偏圆整使ALU能将40-bit的结果在比特15和比特16边界之间进行圆整,圆整可以指定为指令代码的一个部分,当选择了圆整,输出寄存器就包含了已经圆整的16-bit的结果。当检测到结果是中间点值时,通过强迫结果输出中的比特16为0,累加器可消除这个偏差。强迫比特16为0的作用是:将奇数的A0.L/A1.L值向上圆整,将偶数值向下圆整,得到大样本偏差为0、均匀分布的数值。累加器内容是从不圆整的。

下面的例子中使用x表示任意的比特模式。如图2-4所示为对于A0的一个典型的圆整操作。当所有的低15比特都是0且比特15是1(中间点值)时,如图2-5所示,将A0的比特16强迫为0,这对于避免净偏差的补偿是明显的。

图2-4 典型的无偏乘法器圆整

图2-5 无偏乘法器圆整中避免净偏差

2.有偏圆整

按照惯例,当原始数刚好位于两个数的中间点时总是圆整到其中较大的那个数。例如,要圆整一个3-bit的补码小数0.25到最接近的2-bit的补码小数,这个方法返回的是0.5,原始数刚好位于0.5和0.0之间,因此这个方法是向上圆整的。因为它总是向上圆整,所以该方法被称为有偏圆整。

在该模式下,圆整操作将值为0x8000 的A0.L/A1.L向上圆整,而不只是将奇数值向上圆整,见表2-7。有偏圆整是仅当A0.L/A1.L寄存器为0x8000的时候才会影响结果,而其他的圆整操作都是正常的工作方式。这个模式对于使用了有偏圆整的位指定算法能更加有效的实现(如GSM语音压缩例程)。

表2-7 乘法器操作中的有偏圆整

3.截断

另外一种降低数的有效位的通常方法是简单地屏蔽掉其低 N-M 个位,这就是众所周知的截断,它会导致一个相对较大的偏差。不支持圆整的指令便使用截断方式,ASTAT中的RND_MOD位对截断无影响。

4.特殊的圆整指令

ALU能够按照前述有偏或无偏圆整方式将算术结果圆整并直接写入数据寄存器中。它也提供了这样的能力——在不同的比特边界上圆整,这些选项是RND12、RND和RND20,分别从比特12、16和20上提取16位的值,并执行有偏圆整,而不管ASTAT中的RND_MOD位的状态。例如指令:

        R3.L=R4 (RND);

它将在比特16上执行有偏圆整,保存结果于一个半字中。

        R3.L=R4+R5 (RND12);

它将执行两个32位数的加法,在比特12上执行有偏圆整,将结果保存到一个半字里。

它将执行两个32位数的加法,在比特20上执行有偏圆整,将结果保存到一个半字里。

        R3.L=R4+R5 (RND20);