ZHCU876Z July 2001 – October 2023 SM320F28335-EP
C28x 编译器可识别多种内在函数运算符。一些汇编语句难以或无法用 C/C++ 表达,而内在函数能够表达这类语句的含义。内在函数的用法与函数类似;可以将 C/C++ 变量与这些内在函数结合使用,就像在任何普通函数中一样。
内在函数通过前导双下划线指定,可像用函数调用一样进行访问。例如:
long lvar;
int ivar;
unsigned int uivar;
lvar = __mpyxu(ivar, uivar);
表 7-6 中列出的内在函数均可用。它们对应于所示的 TMS320C28x 汇编语言指令。更多信息,请参阅《TMS320C28x CPU 和指令集参考指南》。
内在函数 | 汇编指令 | 说明 | |
---|---|---|---|
int __abs16_sat( int src ); | SETC OVM MOV AH, src ABS ACC MOV dst, AH CLRC OVM |
清除 OVM 状态位。将 src 载入 AH。取 ACC 的绝对值。将 AH 存储到 dst。清除 OVM 状态位。 | |
void __add( int *m, int b ); | ADD * m , b | 将存储器位置 m 至 b 的内容相加并将结果以原子形式存储在 m 中。 | |
long __addcu( long src1, unsigned int src2 ); | ADDCU ACC, {mem | reg} | 将src2 的内容和进位位的值加到 ACC 中。结果位于 ACC 中。 | |
void __addl( long *m, long b ); | ADDL *m, b | 将存储器位置 m 至 b 的内容相加并将结果以原子形式存储在 m 中。 | |
void __and( int *m, int b ); | AND * m, b | 对存储器位置 m 至 b 的内容进行与运算,并将结果以原子形式存储在 m 中。 | |
int &__byte( int *array, unsigned int byte_index); | MOVB array [byte_index].LSB, src 或 MOVB dst, array [byte_index ].LSB |
C28x 中的最小可寻址单元为 16 位。因此,您通常无法访问存储器位置之外的 8 位实体。以下内在函数可帮助访问存储器位置之外的 8 位数,并可通过以下方式调用: 当用于读取存储器时,16 位结果的高 8 位始终为 0。 |
|
unsigned long &y __byte_peripheral_32(unsigned long *x); | 用于访问 32 位字节外设数据地址,而无需拆分访问。该内在函数会返回对无符号长整型值的引用,并可用于读取和写入数据。请参阅节 6.15.7。 | ||
void __dec( int *m ); | DEC * m | 以原子形式对存储器位置 m 的内容进行递减。 | |
unsigned int __disable_interrupts( ); | PUSH ST1 SETC INTM, DBGM POP reg16 |
禁用中断并返回中断向量的旧值。 | |
void __dmac( long *src1, long *src2, long &accum1, long &accum2, int shift); | SPMn ; the PM value required for shift MOVL ACC,accum1 MOVL P, accum2 MOVL XARx, src1 MOVL XAR7, src2 DMAC ACC:P, *XARx++, *XAR7++ |
设置移位所需的 PM 值。 将 accum1 和 accum2 移入 ACC 和 P。 将地址 src1 和 src2 移入 XARx 和 XAR7。 ACC = ACC + (src1[i+1] * src2[i+1]) << PM P = P + (src1[i] * src2[i]) << PM 更多信息请参阅节 3.15.3。 |
|
void __eallow( void ); | EALLOW | 允许 CPU 任意写入受保护的寄存器。 | |
void __edis( void ); | EDIS | 在使用 EALLOW 后防止 CPU 任意写入受保护的寄存器。 | |
unsigned int __enable_interrupts( ); | PUSH ST1 CLRC INTM, DBGM POP reg16 |
启用中断并返回中断向量的旧值。 | |
uint32_t __f32_bits_as_u32( float src ); | -- | 将浮点型中的位提取为 32 位寄存器。此内在函数不生成代码;该函数告诉编译器要改变解释位的方式。示例请参阅节 7.6.1。 | |
uint64_t __f64_bits_as_u64( double src ); | -- | 将双精度型中的位提取为 64 位寄存器。此内在函数不生成代码;该函数告诉编译器要改变解释位的方式。示例请参阅节 7.6.1。 | |
int __flip16(int src); | FLIP AX | 反转整型 src 中的位顺序。 | |
long __flip32(long src); | FLIP AX | 反转长整型 src 中的位顺序。 | |
long long __flip64(long long src); | FLIP AX | 反转超长整型 src 中的位顺序。 | |
void __inc( int *m ); | INC *m | 以原子形式对存储器位置 m 的内容进行递增。 | |
long=__IQ( long double A , int N ); | 将长双精度型 A 转换为正确的 IQN 值并作为长整型返回。如果两个参数都是常数,编译器会在编译期间将参数转换为 IQ 值。否则会调用 RTS 例程 __IQ。此内在函数无法用于将全局变量初始化为 .cinit 段。 | ||
long dst =__IQmpy( long A, long B , int N ); | 使用 C28 IQmath 库执行经优化的乘法。dst 成为 ACC 或 P,A 成为 XT: | ||
如果 N == 0: | IMPYL {ACC|P}, XT, B | dst 为 ACC 或 P。如果 dst 为 ACC,该指令需要 2 个周期。如果 dst 为 P,该指令需要 1 个周期。 | |
如果 0 < N < 16: | IMPYL P, XT, B QMPYL ACC, XT, B ASR64 ACC:P, # N |
||
如果 15 < N < 32: | IMPYL P, XT, B QMPYL ACC, XT, B LSL64 ACC:P, #(32- N ) |
||
如果 N == 32: | QMPYL {ACC|P}, XT, B | ||
如果 N 为变量: | IMPYL P, XT, B QMPYL ACC, XT, B MOV T, N LSR64 ACC:P, T |
||
long dst= __IQsat( long A, long max, long min ); | dst 成为 ACC。根据 max 和/或 min 的值,会生成不同的代码。使用 max < min 调用 __IQsat 会导致出现未定义的行为。 | ||
如果 max 和 min 为 22 位无符号常数: | MOVL ACC, A MOVL XAR n, # 22bits MINL ACC, XAR n MOVL XAR n, # 22bits MAXL ACC, XAR n |
||
如果 max 和 min 为其他常数: | MOVL ACC, A MOV PL, # max lower 16 bits MOV PH, # max upper 16 bits MINL ACC, P MOV PL, # min lower 16 bits MOV PH, # min upper 16 bits MAXL ACC, P |
||
如果 max 和/或 min 为变量: | MOVL ACC, A MINL ACC, max MAXL ACC, min |
||
long dst= __IQxmpy(long A, long B, int N); | 使用 C28 IQmath 库来执行幂为 2 的经优化的乘法。dst 成为 ACC 或 P;A 成为 XT。代码会基于 N 的值生成。 | ||
如果 N == 0: | IMPYL ACC/P, XT, B | dst 位于 ACC 或 P 中。 | |
如果 0 < N < 17: | IMPYL P, XT, B QMPYL ACC, XT, B LSL64 ACC:P, # N |
dst 位于 ACC 中。 | |
如果 0 > N > -17: | QMPYL ACC, XT, B SETC SXM SFR ACC, #abs(N) |
dst 位于 ACC 中。 | |
如果 16 < N < 32: | IMPYL P, XT, B QMPYL ACC, XT, B ASR64 ACC:P, # N |
dst 位于 P 中。 | |
如果 N == 32: | IMPYL P, XT, B | dst 位于 P 中。 | |
如果 -16 > N > -33 | QMPYL ACC, XT, B SETC SXM SRF ACC, #16 SRF ACC, #abs(N)−16 |
dst 位于 ACC 中。 | |
如果 32 < N < 49: | IMPYL ACC, XT, B LSL ACC, # N -32 |
dst 位于 ACC 中。 | |
如果 -32 > N > -49: | QMPYL ACC, XT, B SETC SXM SFR ACC, #16 SFR ACC, #16 |
dst 位于 ACC 中。 | |
如果 48 < N < 65: | IMPYL ACC, XT, B LSL64 ACC:P, #16 LSL64 ACC:P, # N −48 |
dst 位于 ACC 中。 | |
如果 -48 > N > -65: | QMPYL ACC, XT, B SETC SXM SFR ACC, #16 SFR ACC, #16 |
dst 位于 ACC 中。 | |
long long __llmax(long long dst, long long src); | MAXL ACC,src.hi32 MAXCUL P, src.lo32 |
如果 src > dst,则将 src 复制到 dst。 | |
long long __llmin(long long dst, long long src); | MINL ACC,src.hi32 MINCUL P, src.lo32 |
如果 src < dst,则将 src 复制到 dst | |
long __lmax(long dst, long src); | MAXL ACC,src | 如果 src > dst,则将 src 复制到 dst。 | |
long __lmin(long dst, long src); | MINL ACC,src | 如果 src < dst,则将 src 复制到 dst | |
int __max(int dst, int src); | MAXdst, src | 如果 src > dst,则将 src 复制到 dst | |
int __min(int dst, int src); | MINdst, src | 如果 src < dst,则将 src 复制到 dst | |
int __mov_byte( int *src, unsigned int n ); | MOVB AX.LSB,*+XARx[ n ] 或 MOVZ AR0/AR1, @ n MOVB AX.LSB,*XARx[ {AR0|AR1} ] |
返回字节表中 src 指向的第 n 个 8 位元素。 此内在函数用于确保向后兼容性。最好使用内在函数 __byte,因为它会返回引用值。使用 _byte() 无法完成的运算也无法使用 __mov_byte() 来完成。 |
|
long __mpy( int src1, int src2 ); | MPY ACC,src1 , #src2 | 将 src1 移入 T 寄存器。将 16 位立即数 (src2) 乘以 T。结果位于 ACC 中。 | |
long __mpyb( int src1, uint src2 ); | MPYB {ACC | P}, T, # src2 | 将 src1(T 寄存器)乘以无符号 8 位立即数 (src2)。结果位于 ACC 或 P 中。 | |
long __mpy_mov_t( int src1, int src2, int * dst2); | MPY ACC, T,src2 MOV @ dst2, T |
将 src1(T 寄存器)乘以 src2。结果位于 ACC 中。将 src1 移入 *dst2。 | |
unsigned long __mpyu(unit src2, unit srt2); | MPYU {ACC | P}, T,src2 | 将 src1(T 寄存器)乘以 src2。这两个操作数都会作为无符号 16 位数字处理。结果位于 ACC 或 P 中。 | |
long __mpyxu( int src1, uint src2 ); | MPYXU ACC, T, {mem|reg} | T 寄存器会载入 src1。src2 由存储器引用或载入寄存器。结果位于 ACC 中。 | |
long dst= __norm32(long src, int * shift ); | CSB ACC LSLL ACC, T MOV @ shift, T |
将 src 归一化为 dst 并将 *shift 更新为移位的位数。 | |
long long dst= __norm64(long long src, int * shift); |
CSB ACC LSL64 ACC:P, T MOV @ shift, T CSB ACC LSL64 ACC:P, T MOV TMP16, AH MOV AH, T ADD shift, AH MOV AH, TMP16 |
将 64 位 src 归一化为 dst 并将 *shift 更新为移位的位数。 | |
void __or( int * m , int b ); | OR * m , b | 对存储器位置 m 至 b 的内容进行或运算,并将结果以原子形式存储在 m 中。 | |
long __qmpy32( long src32a, long src32b, int q ); | CLRC OVM SPM − 1 MOV T, src32a + 1 MPYXU P, T, src32b + 0 MOVP T, src32b + 1 MPYXU P, T, src32a + 0 MPYA P, T, src32a + 1 |
扩展的精密 DSP Q 数学。根据 q 的值会生成不同的代码。 | |
如果 q = 31、30: | SPM q − 30 SFR ACC, #45 − q ADDL ACC, P |
||
如果 q = 29: | SFR ACC, #16 ADDL ACC, P |
||
如果 q = 28 至 24: | SPM q - 30 SFR ACC, #16 SFR ACC, #29 - q ADDL ACC, P |
||
如果 q = 23 至 13: | SFR ACC, #16 ADDL ACC, P SFR ACC, #29 − q |
||
如果 q = 12 至 0: | SFR ACC, #16 ADDL ACC, P SFR ACC, #16 SFR ACC, #13 − q |
||
long __qmpy32by16(long src32, int src16, int q); | CLRC OVM MOV T, src16 + 0 MPYXU P, T, src32 + 0 MPY P, T, src32 + 1 |
扩展的精密 DSP Q 数学。根据 q 的值会生成不同的代码。 | |
如果 q = 31、30: | SPM q − 30 SFR ACC, #46 − q ADDL ACC, P |
||
如果 q = 29 至 14: | SPM 0 SFR ACC, #16 ADDL ACC, P SFR ACC, #30 − q |
||
如果 q = 13 至 0: | SPM 0 SFR ACC, #16 ADDL ACC, P SFR ACC, #16 SFR ACC, #14 − q |
||
void __restore_interrupts(unsigned int val); | PUSH val POP ST1 |
恢复中断并将中断向量设置为值 val。 | |
long __rol( long src ); | ROL ACC | 向左旋转 ACC。 | |
long __ror( long src ); | ROR ACC | 向右旋转 ACC。 | |
void *result = __rpt_mov_imm(void * dst , int src , int count ); |
MOV result , dst MOV ARx, dst RPT # count || MOV *XARx++, # src |
将 dst 寄存器移入 result 寄存器。将 dst 寄存器移入临时 (ARx) 寄存器。将立即数 src 复制到该临时寄存器 count + 1 次。 src 必须为 16 位立即数。count 可以是 0 至 255 的立即数或变量。 |
|
int __rpt_norm_inc( long src, int dst, int count ); | MOV ARx, dst RPT # count || NORM ACC, ARx++ |
重复归一化累加器值 count + 1 次。 count 可以是 0 至 255 的立即数或变量。 |
|
int __rpt_norm_dec(long src, int dst, int count); | MOV ARx, dst RPT # count || NORM ACC, ARx-- |
重复归一化累加器值 count + 1 次。 count 可以是 0 至 255 的立即数或变量。 |
|
long __rpt_rol(long src, int count); | RPT # count || ROL ACC |
向左重复旋转累加器 count + 1 次。结果位于 ACC 中。 count 可以是 0 至 255 的立即数或变量。 |
|
long __rpt_ror(long src, int count); | RPT # count || ROR ACC |
向右重复旋转累加器 count + 1 次。结果位于 ACC 中。 count 可以是 0 至 255 的立即数或变量。 |
|
long __rpt_subcu(long dst, int src, int count); | RPT count || SUBCU ACC, src |
src 操作数从存储器引用,或者载入寄存器并用作 SUBCU 指令的操作数。结果位于 ACC 中。 count 可以是 0 至 255 的立即数或变量。该指令会重复 count + 1 次。 |
|
unsigned long __rpt_subcul(unsigned long num, unsigned long den, unsigned long &remainder, int count); | RPT count || SUBCUL ACC, den |
执行无符号模除法中常用的重复条件长整型减法。返回商。 | |
long __sat( long src ); | SAT ACC | 在 ACC 中载入 32 位 src。结果位于 ACC 中。 | |
long __sat32( long src, long limit ); | SETC OVM ADDL ACC, {mem|P} SUBL ACC, {mem|P} SUBL ACC, {mem|P} ADDL ACC, {mem|P} CLRC OVM |
使 32 位值饱和为 32 位掩码。在 ACC 中载入 src。Limit 值从存储器引用或者载入 P 寄存器。结果位于 ACC 中。 | |
long __sathigh16(long src, int limit); | SETC OVM ADDL ACC, {mem|P}<<16 SUBL ACC, {mem|P}<<16 SUBL ACC, {mem|P}<<16 ADDL ACC, {mem|P}<<16 CLRC OVM SFR ACC, rshift |
使 32 位值饱和至高 16 位。在 ACC 中载入 src。limit 值从存储器引用或者载入寄存器。结果位于 ACC 中。结果可以向右移位并存储为整型。例如:
|
|
long __satlow16( long src ); | SETC OVM MOV T, #0xFFFF CLR SXM ; if necessary ADD ACC, T <<15 SUB ACC, T <<15 SUB ACC, T <<15 ADD ACC, T <<15 CLRC OVM |
使 32 位值饱和至低 16 位。在 ACC 中载入 src。在 T 寄存器中载入 #0xFFFF。结果位于 ACC 中。 | |
long __sbbu( long src1 , uint src2 ); | SBBU ACC, src2 | 从 ACC (src1) 中减去 src2 + C 的逻辑反向。结果位于 ACC 中。 | |
void __sub( int * m, int b ); | SUB * m , b | 从存储器位置 m 的内容中减去 b,并将结果以原子形式存储在 m 中。 | |
long __subcu( long src1, int src2 ); | SUBCU ACC, src2 | 从 ACC (src1) 中减去向左移 15 位的 src2。结果位于 ACC 中。 | |
unsigned long __subcul(unsigned long num, unsigned long den, unsigned long &remainder); | SUBCUL ACC, den | 执行无符号模除法中常用的单次条件长整型减法。返回商。 | |
void __subl( long * m, long b ); | SUBL *m , b | 从存储器位置 m 的内容中减去 b,并将结果以原子形式存储在 m 中。 | |
void __subr( int * m , int b ); | SUBR *m , b | 从 b 中减去存储器位置 m 的内容,并将结果以原子形式存储在 m 中。 | |
void __subrl( long * m , long b ); | SUBRL *m , b | 从 b 中减去存储器位置 m 的内容,并将结果以原子形式存储在 m 中。 | |
if (__tbit( int src , int bit ) ); | TBIT src , # bit | 如果 src 的指定 位 为 1,则设置 TC 状态位。 | |
float __u32_bits_as_f32( uint32_t src ); | -- | 将 32 位寄存器打包为浮点型。此内在函数不生成代码;该函数告诉编译器要改变解释位的方式。示例请参阅节 7.6.1。 | |
double __u64_bits_as_f64( uint64_t src ); | -- | 将 64 位寄存器打包为双精度型。此内在函数不生成代码;该函数告诉编译器要改变解释位的方式。示例请参阅节 7.6.1。 | |
void __xor( int * m, int b ); | XOR * m, b | 对存储器位置 m 至 b 的内容进行异或运算,并将结果以原子形式存储在 m 中。 |