Vdsp(bf561)中的浮点运算(12):fract16加减运算
当前位置:以往代写 > C/C++ 教程 >Vdsp(bf561)中的浮点运算(12):fract16加减运算
2019-06-13

Vdsp(bf561)中的浮点运算(12):fract16加减运算

Vdsp(bf561)中的浮点运算(12):fract16加减运算

副标题#e#

由于减法实际可以当作加上一个负数,因此我们只需要看加法操纵。fract16的加法运算由add_fr1x16函数完成:

#pragma inline
#pragma always_inline
static fract16  add_fr1x16(fract16  __a, fract16  __b) {
fract16  __rval = __builtin_add_fr1x16(__a, __b);
return __rval;
}

从这里可以看出我们实际可以利用__builtin_add_fr1x16这一函数挪用。

写一个很简朴的措施:

typedef fract16 ft;

ft calc(ft x, ft y)
{
ft r;
r = __builtin_add_fr1x16(x, y);
return r;
}

这个函数展开后的汇编代码为:

_calc:
.LN_calc:
//-------------------------------------------------------------------
//   Procedure statistics:
//   Frame size            = 8
//   Scratch registers used:{R0.L,R0.H,R1.L,ASTAT0-ASTAT1}
//   Call preserved registers used:{FP,SP,RETS}
//-------------------------------------------------------------------
// line ".\float_test.c":27
LINK 0;
W[FP + 12] = R1;
W[FP + 8] = R0;
.LN0:
// line 29
R0.L = R1.L + R0.L (S);
R0 = R0.L (X);
W[FP + 16] = R0;
.LN1:
// line 30
UNLINK;
RTS;
.LN._calc.end:
._calc.end:
.global _calc;
.type _calc,STT_FUNC;


#p#副标题#e#

可以发明,__builtin_add_fr1x16展开后的汇编代码就是

R0.L = R1.L + R0.L (S);

因而完成这样一个加法运算将只需要一个cycle的时间。

在VDSP的文档里这样先容这条指令:

Data Registers — 16-Bit Operands, 16-Bit Result
Dreg_lo_hi = Dreg_lo_hi + Dreg_lo_hi (sat_flag) ;    /* (b) */
Dreg_lo_hi: R7–0.L, R7–0.H
sat_flag: nonoptional saturation flag, (S) or (NS)
In the syntax, where sat_flag appears, substitute one of the following values.
(S) – saturate the result
(NS) – no saturation

由于这是一条带标记的加法指令,因此它将有一个饱和问题:

Saturation is a technique used to contain the quantity within the values that the destination register can represent. When a value is computed that exceeds the capacity of the destination register, then the value written to the register is the largest value that the register can hold with the same sign as the original.

If an operation would otherwise cause a positive value to overflow and become negative, instead, saturation limits the result to the maximum positive value for the size register being used.

Conversely, if an operation would otherwise cause a negative value to overflow and become positive, saturation limits the result to the maximum negative value for the register size.

The maximum positive value in a 16-bit register is 0x7FFF. The maximum negative value is 0x8000. For a signed two’s-complement 1.15 fractional notation, the allowable range is –1 through (1–2–15).

当两个数相加高出fract16所能暗示的最大值时,它将直接返回fract16所能暗示的最大值0x7fff,即0.999969482421875,当功效小于-1时,它将返回-1。

由于fract16不是内置范例,而是界说为short,我们看看假如不利用__builtin_add_fr1x16而是直接用加号会产生什么:

typedef fract16 ft;

ft calc(ft x, ft y)
{
ft r;
r = x + y;
return r;
}

汇编输出酿成了:

// line 29
R0 = R0 + R1 (NS);
R0 = R0.L (X);
W[FP + 16] = R0;

区别照旧很大的,编译器把它酿成了32位加法再取低16位,这样就不会是返回饱和的功效了,而是返回一个不但愿看到的数字,呵呵。

减法与此雷同,不外改为挪用下面的函数挪用罢了:

#pragma inline
#pragma always_inline
static fract16  sub_fr1x16(fract16  __a, fract16  __b) {
fract16  __rval = __builtin_sub_fr1x16(__a, __b);
return __rval;
}

    关键字:

在线提交作业