📄 dspfns.h
字号:
__asm {
msr CPSR_f, armdsp_flagdata.armdsp_flags_word;
adcs result, x, y;
mrs flags, CPSR;
orrvs flags, flags, #0x08000000; // set Q if V is set
mov armdsp_flagdata.armdsp_flags_word, flags;
}
return result;
}
/*
* Subtract one 32-bit signed integer, together with the Carry
* variable, from another 32-bit signed integer, without
* saturation.
*/
__inline Word32 L_sub_c(Word32 x, Word32 y)
{
Word32 result, flags;
__asm {
msr CPSR_f, armdsp_flagdata.armdsp_flags_word;
sbcs result, x, y;
mrs flags, CPSR;
orrvs flags, flags, #0x08000000; // set Q if V is set
mov armdsp_flagdata.armdsp_flags_word, flags;
}
return result;
}
/*
* Multiply two 16-bit signed integers together to give a 32-bit
* signed integer, shift left by one _with_ saturation, and add
* with carry to another 32-bit integer _without_ saturation.
*/
__inline Word32 L_macNs(Word32 accumulator, Word16 x, Word16 y)
{
return L_add_c(accumulator, L_mult(x, y));
}
/*
* Multiply two 16-bit signed integers together to give a 32-bit
* signed integer, shift left by one _with_ saturation, and
* subtract with carry from another 32-bit integer _without_
* saturation.
*/
__inline Word32 L_msuNs(Word32 accumulator, Word16 x, Word16 y)
{
return L_sub_c(accumulator, L_mult(x, y));
}
/*
* Negate a 32-bit signed integer, with saturation. (Saturation is
* only necessary when the input is -0x80000000.)
*/
__inline Word32 L_negate(Word32 x)
{
if (x == ARMDSP_WORD32_MIN)
return ARMDSP_WORD32_MAX;
return -x;
}
/*
* Multiply two 16-bit signed integers, shift the result right by
* 15 with rounding, and saturate it. (Saturation is only necessary
* if both inputs were -0x8000, in which case the result "should"
* be 0x8000 and is saturated to 0x7FFF.)
*/
__inline Word16 mult_r(Word16 x, Word16 y)
{
Word32 product;
__asm {
smulbb product, x, y;
qdadd product, 0x8000, product;
}
return (Word16) (product >> 16); /* qdadd adds one to the 15 */
}
/*
* Shift a 32-bit signed integer left (or right, if the shift count
* is negative). Saturate on overflow.
*/
__inline Word32 L_shl(Word32 x, Word16 shift)
{
int lz;
int absx;
if (shift <= 0)
return x >> (-shift);
absx = (x < 0 ? -x : x);
__asm {
clz lz, absx;
}
if (shift < lz || x == 0)
return x << shift;
if (x < 0)
return ARMDSP_WORD32_MIN;
else
return ARMDSP_WORD32_MAX;
}
/*
* Shift a 32-bit signed integer right (or left, if the shift count
* is negative). Saturate on overflow.
*/
__inline Word32 L_shr(Word32 x, Word16 shift)
{
int lz;
int absx;
if (shift >= 0)
return x >> shift;
absx = (x < 0 ? -x : x);
__asm {
clz lz, absx;
}
if (-shift < lz || x == 0)
return x << (-shift);
if (x < 0)
return ARMDSP_WORD32_MIN;
else
return ARMDSP_WORD32_MAX;
}
/*
* Shift a 16-bit signed integer right, with rounding. Shift left
* with saturation if the shift count is negative.
*/
__inline Word16 shr_r(Word16 x, Word16 shift)
{
if (shift == 0 || x == 0)
return (Word16) (x >> shift);
if (shift > 0)
return (Word16) (((x >> (shift-1)) + 1) >> 1);
if (shift < -15)
shift = -16;
return saturate(x << (-shift));
}
/*
* Multiply two 16-bit signed integers together to give a 32-bit
* signed integer, shift left by one with saturation, and add to
* another 32-bit integer with saturation (like L_mac). Then shift
* the result right by 15 bits with rounding (like round).
*/
__inline Word16 mac_r(Word32 accumulator, Word16 x, Word16 y)
{
return round(L_mac(accumulator, x, y));
}
/*
* Multiply two 16-bit signed integers together to give a 32-bit
* signed integer, shift left by one with saturation, and subtract
* from another 32-bit integer with saturation (like L_msu). Then
* shift the result right by 15 bits with rounding (like round).
*/
__inline Word16 msu_r(Word32 accumulator, Word16 x, Word16 y)
{
return round(L_msu(accumulator, x, y));
}
/*
* Shift a 16-bit signed integer left by 16 bits to generate a
* 32-bit signed integer. The bottom 16 bits are zeroed.
*/
__inline Word32 L_deposit_h(Word16 x)
{
return ((Word32)x) << 16;
}
/*
* Sign-extend a 16-bit signed integer by 16 bits to generate a
* 32-bit signed integer.
*/
__inline Word32 L_deposit_l(Word16 x)
{
return (Word32)x;
}
/*
* Shift a 32-bit signed integer right, with rounding. Shift left
* with saturation if the shift count is negative.
*/
__inline Word32 L_shr_r(Word32 x, Word16 shift)
{
int lz;
int absx;
if (shift == 0 || x == 0)
return x >> shift;
if (shift > 0) {
Word32 x2 = x >> (shift-1);
return (x2 >> 1) + (x2 & 1);
}
absx = (x < 0 ? -x : x);
__asm {
clz lz, absx;
}
if (-shift < lz || x == 0)
return x << (-shift);
if (x < 0)
return ARMDSP_WORD32_MIN;
else
return ARMDSP_WORD32_MAX;
}
/*
* Absolute value of a 32-bit signed integer. Saturating, so
* abs(-0x80000000) becomes +0x7FFFFFFF.
*/
__inline Word32 L_abs(Word32 x)
{
if (x >= 0)
return x;
else if (x == ARMDSP_WORD32_MIN)
return ARMDSP_WORD32_MAX;
else
return -x;
}
/*
* Return a saturated value appropriate to the most recent carry-
* affecting operation (L_add_c, L_macNs, L_sub_c, L_msuNs).
*
* In other words: return the argument if the Q flag is clear.
* Otherwise, return -0x80000000 or +0x7FFFFFFF depending on
* whether the Carry flag is set or clear (respectively).
*/
__inline Word32 L_sat(Word32 x)
{
int qflag;
__asm {
mrs qflag, CPSR;
}
if (!(qflag & 0x08000000))
return x;
if (Carry)
return ARMDSP_WORD32_MIN;
else
return ARMDSP_WORD32_MAX;
}
/*
* Return the number of bits of left shift needed to arrange for a
* 16-bit signed integer to have value >= 0x4000 or <= -0x4001.
*
* Returns zero if x is zero.
*/
__inline Word16 norm_s(Word16 x)
{
int lz;
if (x == 0)
return 0; /* 0 is a special case */
x = (Word16) (x ^ (x >> 15)); /* invert x if it's negative */
__asm {
clz lz, x;
}
return (Word16) (lz - 17);
}
/*
* Divide one 16-bit signed integer by another, and produce a
* 15-bit fixed point fractional result (by multiplying the true
* mathematical result by 0x8000). The divisor (denominator) is
* assumed to be non-zero and also assumed to be greater or equal
* to the dividend (numerator). Hence the (unscaled) result is
* necessarily within the range [0,1].
*
* Both operands are assumed to be positive.
*
* After division, the result is saturated to fit into a 16-bit
* signed integer. (The only way this can happen is if the operands
* are equal, so that the result would be 1, i.e. +0x8000 in 15-bit
* fixed point.)
*/
__inline Word16 div_s(Word16 x, Word16 y)
{
Word32 quot;
assert(y > 0);
assert(x >= 0);
assert(x <= y);
quot = 0x8000 * x;
quot /= y;
if (quot > ARMDSP_WORD16_MAX)
return ARMDSP_WORD16_MAX;
else
return (Word16)quot;
}
/*
* Return the number of bits of left shift needed to arrange for a
* 32-bit signed integer to have value >= 0x40000000 (if
*
* Returns zero if x is zero.
*/
__inline Word16 norm_l(Word32 x)
{
int lz;
if (x == 0)
return 0; /* 0 is a special case */
x ^= (x >> 31); /* invert x if it's negative */
__asm {
clz lz, x;
}
return (Word16) (lz - 1);
}
#ifdef __cplusplus
}
#endif
#endif /* ARMDSP_DSPFNS_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -