📄 dspfns.h
字号:
/* dspfns.h
*
* Copyright 2001 ARM Limited. All rights reserved.
*
* RCS $Revision: 1.1.2.2 $
* Checkin $Date: 2001/07/31 16:10:40 $
* Revising $Author: statham $
*/
/* ----------------------------------------------------------------------
* This header file provides a set of DSP-type primitive
* operations, such as 16-bit and 32-bit saturating arithmetic. The
* operations it provides are similar to the ones used by the ITU
* for publishing specifications of DSP algorithms.
*
* This header file is intended as an example implementation. It
* demonstrates how to use the inline assembly feature in the ARM
* compilers, to construct intrinsic functions that provide
* C-language access to the ARM9E's DSP capability.
*
* This header file is NOT SUFFICIENT to be used alone - you need
* to include "dspfns.c" from the examples\dsp directory as well.
*/
#ifndef ARMDSP_DSPFNS_H
#define ARMDSP_DSPFNS_H
#include <assert.h>
#ifndef ARMDSP_WORD32_DEFINED
#define ARMDSP_WORD32_DEFINED
typedef signed int Word32;
typedef signed short Word16;
#define ARMDSP_WORD32_MAX ((Word32)0x7FFFFFFF)
#define ARMDSP_WORD32_MIN ((Word32)-0x80000000)
#define ARMDSP_WORD16_MAX ((Word16)0x7FFF)
#define ARMDSP_WORD16_MIN ((Word16)-0x8000)
#endif
typedef int Flag;
/*
* This global variable needs to exist somewhere in the compiled
* program in order for the flag-using functions to work. You can
* either include the declaration
*
* armdsp_flagdata_union armdsp_flagdata;
*
* in at least one of your source files (that includes this
* header), or compile in "dspfns.c" from the examples\dsp
* directory.
*/
typedef union {
unsigned int armdsp_flags_word;
struct {
#ifdef __BIG_ENDIAN
Flag armdsp_n:1, armdsp_z:1, armdsp_c:1, armdsp_v:1, armdsp_q:1, armdsp_unused:27;
#else
Flag armdsp_unused:27, armdsp_q:1, armdsp_v:1, armdsp_c:1, armdsp_z:1, armdsp_n:1;
#endif
} armdsp_bitfields;
} armdsp_flagdata_union;
extern armdsp_flagdata_union armdsp_flagdata;
#define Carry ( armdsp_flagdata.armdsp_bitfields.armdsp_c )
#define Overflow ( armdsp_flagdata.armdsp_bitfields.armdsp_q )
#ifdef __cplusplus
extern "C" {
#endif
#if 0
}
#endif
/*
* Convert a 32-bit signed integer into a 16-bit signed integer by
* saturation.
*/
__inline Word16 saturate(Word32 x)
{
if (x > ARMDSP_WORD16_MAX)
Overflow = 1, x = ARMDSP_WORD16_MAX;
else if (x < ARMDSP_WORD16_MIN)
Overflow = 1, x = ARMDSP_WORD16_MIN;
return (Word16) x;
}
/*
* Add two 16-bit signed integers with saturation.
*/
__inline Word16 add(Word16 x, Word16 y)
{
Word32 xs, ys, rs;
__asm {
mov xs, x, lsl #16;
mov ys, y, lsl #16;
qadd rs, xs, ys;
}
return (Word16) (rs >> 16);
}
/*
* Subtract one 16-bit signed integer from another with saturation.
*/
__inline Word16 sub(Word16 x, Word16 y)
{
Word32 xs, ys, rs;
__asm {
mov xs, x, lsl #16;
mov ys, y, lsl #16;
qsub rs, xs, ys;
}
return (Word16) (rs >> 16);
}
/*
* Absolute value of a 16-bit signed integer. Saturating, so
* abs(-0x8000) becomes +0x7FFF.
*/
__inline Word16 abs_s(Word16 x)
{
if (x >= 0)
return x;
else if (x == ARMDSP_WORD16_MIN)
return ARMDSP_WORD16_MAX;
else
return (Word16) -x;
}
/*
* Shift a 16-bit signed integer left (or right, if the shift count
* is negative). Saturate on overflow.
*/
__inline Word16 shl(Word16 x, Word16 shift)
{
if (shift <= 0 || x == 0)
return (Word16) (x >> (-shift));
if (shift > 15)
shift = 16;
return saturate(x << shift);
}
/*
* Shift a 16-bit signed integer right (or left, if the shift count
* is negative). Saturate on overflow.
*/
__inline Word16 shr(Word16 x, Word16 shift)
{
if (shift >= 0 || x == 0)
return (Word16) (x >> shift);
if (shift < -15)
shift = -16;
return saturate(x << (-shift));
}
/*
* Multiply two 16-bit signed integers, shift the result right by
* 15 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(Word16 x, Word16 y)
{
Word32 product;
__asm {
smulbb product, x, y;
qadd product, product, product;
}
return (Word16) (product >> 16); /* the qadd added one to the 15 */
}
/*
* Multiply two 16-bit signed integers to give a 32-bit signed
* integer. Shift left by one, and saturate the result. (Saturation
* is only necessary if both inputs were -0x8000, in which case the
* result "should" be 0x40000000 << 1 = +0x80000000, and is
* saturated to +0x7FFFFFFF.)
*/
__inline Word32 L_mult(Word16 x, Word16 y)
{
Word32 product;
__asm {
smulbb product, x, y;
qadd product, product, product;
}
return product;
}
/*
* Negate a 16-bit signed integer, with saturation. (Saturation is
* only necessary when the input is -0x8000.)
*/
__inline Word16 negate(Word16 x)
{
if (x == ARMDSP_WORD16_MIN)
return ARMDSP_WORD16_MAX;
return (Word16) -x;
}
/*
* Return the top 16 bits of a 32-bit signed integer.
*/
__inline Word16 extract_h(Word32 x)
{
return (Word16) (x >> 16);
}
/*
* Return the bottom 16 bits of a 32-bit signed integer, with no
* saturation, just coerced into a two's complement 16 bit
* representation.
*/
__inline Word16 extract_l(Word32 x)
{
return (Word16) x;
}
/*
* Divide a 32-bit signed integer by 2^16, rounding to the nearest
* integer (round up on a tie). Equivalent to adding 0x8000 with
* saturation, then shifting right by 16.
*/
__inline Word16 round(Word32 x)
{
__asm {
qadd x, x, 0x8000;
}
return extract_h(x);
}
/*
* 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.
*
* Note the intermediate saturation operation in the definition:
*
* L_mac(-1, -0x8000, -0x8000)
*
* will give 0x7FFFFFFE and not 0x7FFFFFFF:
* the unshifted product is: 0x40000000
* shift left with saturation: 0x7FFFFFFF
* add to -1 with saturation: 0x7FFFFFFE
*/
__inline Word32 L_mac(Word32 accumulator, Word16 x, Word16 y)
{
Word32 product;
__asm {
smulbb product, x, y;
qdadd accumulator, accumulator, product;
}
return accumulator;
}
/*
* 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.
*
* Note the intermediate saturation operation in the definition:
*
* L_msu(1, -0x8000, -0x8000)
*
* will give 0x80000002 and not 0x80000001:
* the unshifted product is: 0x40000000
* shift left with saturation: 0x7FFFFFFF
* subtract from 1 with saturation: 0x80000002
*/
__inline Word32 L_msu(Word32 accumulator, Word16 x, Word16 y)
{
Word32 product;
__asm {
smulbb product, x, y;
qdsub accumulator, accumulator, product;
}
return accumulator;
}
/*
* Add two 32-bit signed integers with saturation.
*/
__inline Word32 L_add(Word32 x, Word32 y)
{
Word32 result;
__asm {
qadd result, x, y;
}
return result;
}
/*
* Subtract one 32-bit signed integer from another with saturation.
*/
__inline Word32 L_sub(Word32 x, Word32 y)
{
Word32 result;
__asm {
qsub result, x, y;
}
return result;
}
/*
* Add together the Carry variable and two 32-bit signed integers,
* without saturation.
*/
__inline Word32 L_add_c(Word32 x, Word32 y)
{
Word32 result, flags;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -