ZHCU876Z July   2001  – October 2023 SM320F28335-EP

 

  1.   1
  2.   请先阅读
    1.     关于本手册
    2.     标记规则
    3.     相关文档
    4.     德州仪器 (TI) 提供的相关文档
    5.     商标
  3. 软件开发工具简介
    1. 1.1 软件开发工具概述
    2. 1.2 编译器接口
    3. 1.3 ANSI/ISO 标准
    4. 1.4 输出文件
    5. 1.5 实用程序
  4. 使用 C/C++ 编译器
    1. 2.1  关于编译器
    2. 2.2  调用 C/C++ 编译器
    3. 2.3  使用选项更改编译器的行为
      1. 2.3.1  链接器选项
      2. 2.3.2  常用选项
      3. 2.3.3  其他有用的选项
      4. 2.3.4  运行时模型选项
      5. 2.3.5  符号调试和分析选项
      6. 2.3.6  指定文件名
      7. 2.3.7  更改编译器解释文件名的方式
      8. 2.3.8  更改编译器处理 C 文件的方式
      9. 2.3.9  更改编译器解释和命名扩展名的方式
      10. 2.3.10 指定目录
      11. 2.3.11 汇编器选项
      12. 2.3.12 已弃用的选项
    4. 2.4  通过环境变量控制编译器
      1. 2.4.1 设置默认编译器选项 (C2000_C_OPTION)
      2. 2.4.2 命名一个或多个备用目录 (C2000_C_DIR)
    5. 2.5  控制预处理器
      1. 2.5.1  预先定义的宏名称
      2. 2.5.2  #include 文件的搜索路径
        1. 2.5.2.1 在 #include 文件搜索路径(--include_path 选项)中新增目录
      3. 2.5.3  支持#warning 和 #warn 指令
      4. 2.5.4  生成预处理列表文件(--preproc_only 选项)
      5. 2.5.5  预处理后继续编译(--preproc_with_compile 选项)
      6. 2.5.6  生成带有注释的预处理列表文件(--preproc_with_comment 选项)
      7. 2.5.7  生成带有行控制详细信息的预处理列表(--preproc_with_line 选项)
      8. 2.5.8  为 Make 实用程序生成预处理输出(--preproc_dependency 选项)
      9. 2.5.9  生成包含#include在内的文件列表(--preproc_includes 选项)
      10. 2.5.10 在文件中生成宏列表(--preproc_macros 选项)
    6. 2.6  将参数传递给 main()
    7. 2.7  了解诊断消息
      1. 2.7.1 控制诊断消息
      2. 2.7.2 如何使用诊断抑制选项
    8. 2.8  其他消息
    9. 2.9  生成交叉参考列表信息(--gen_cross_reference_listing 选项)
    10. 2.10 生成原始列表文件(--gen_preprocessor_listing 选项)
    11. 2.11 使用内联函数扩展
      1. 2.11.1 内联内在函数运算符
      2. 2.11.2 内联限制
      3. 2.11.3 不受保护定义控制的内联
        1. 2.11.3.1 使用内联关键字
      4. 2.11.4 保护内联和 _INLINE 预处理器符号
        1. 2.11.4.1 头文件 string.h
        2. 2.11.4.2 库定义文件
    12. 2.12 使用交叉列出功能
    13. 2.13 关于应用程序二进制接口
    14. 2.14 启用入口挂钩和出口挂钩函数
    15. 2.15 实时固件更新 (LFU)
  5. 优化您的代码
    1. 3.1  调用优化
    2. 3.2  控制代码大小与速度
    3. 3.3  执行文件级优化(--opt_level=3 选项)
      1. 3.3.1 创建优化信息文件(--gen_opt_info 选项)
    4. 3.4  程序级优化(--program_level_compile 和 --opt_level=3 选项)
      1. 3.4.1 控制程序级优化(--call_assumptions 选项)
      2. 3.4.2 混合 C/C++ 和汇编代码时的优化注意事项
    5. 3.5  自动内联扩展(--auto_inline 选项)
    6. 3.6  链接时优化(--opt_level=4 选项)
      1. 3.6.1 选项处理
      2. 3.6.2 不兼容的类型
    7. 3.7  使用反馈制导优化
      1. 3.7.1 反馈向导优化
        1. 3.7.1.1 第 1 阶段 - 收集程序分析信息
        2. 3.7.1.2 第 2 阶段 - 使用应用程序分析信息进行优化
        3. 3.7.1.3 生成和使用配置文件信息
        4. 3.7.1.4 反馈制导优化的应用示例
        5. 3.7.1.5 .ppdata 段
        6. 3.7.1.6 反馈制导优化和代码大小调整
        7. 3.7.1.7 检测程序执行开销
        8. 3.7.1.8 无效的分析数据
      2. 3.7.2 分析数据解码器
      3. 3.7.3 反馈制导优化 API
      4. 3.7.4 反馈制导优化总结
    8. 3.8  使用配置文件信息分析代码覆盖率
      1. 3.8.1 代码覆盖
        1. 3.8.1.1 第 1 阶段 - 收集程序分析信息
        2. 3.8.1.2 第 2 阶段 -- 生成代码覆盖信息报告
      2. 3.8.2 相关的特征和功能
        1. 3.8.2.1 路径分析器
        2. 3.8.2.2 分析选项
        3. 3.8.2.3 环境变量
    9. 3.9  使用优化时的特殊注意事项
      1. 3.9.1 在优化代码中谨慎使用 asm 语句
      2. 3.9.2 使用易失性关键字进行必要的内存访问
        1. 3.9.2.1 访问别名变量时的注意事项
        2. 3.9.2.2 使用 --aliased_variables 选项来指示采用了以下技术
        3. 3.9.2.3 仅在 FPU 目标上:使用 restrict 关键字指示指针没有别名
          1. 3.9.2.3.1 restrict 类型限定符与指针搭配使用
          2. 3.9.2.3.2 restrict 类型限定符与指针搭配使用
    10. 3.10 通过优化使用交叉列出特性
    11. 3.11 数据页 (DP) 指针加载优化
    12. 3.12 调试和分析优化代码
      1. 3.12.1 分析优化的代码
    13. 3.13 提高代码大小优化级别(--opt_for_space 选项)
    14. 3.14 编译器支持重入 VCU 代码
    15. 3.15 编译器支持生成DMAC 指令
      1. 3.15.1 自动生成 DMAC 指令
      2. 3.15.2 指定数据地址对齐的断言
      3. 3.15.3 __dmac 内在函数
    16. 3.16 正在执行什么类型的优化?
      1. 3.16.1  基于成本的寄存器分配
      2. 3.16.2  别名消歧
      3. 3.16.3  分支优化和控制流简化
      4. 3.16.4  数据流优化
      5. 3.16.5  表达式简化
      6. 3.16.6  函数的内联扩展
      7. 3.16.7  函数符号别名
      8. 3.16.8  归纳变量和强度降低
      9. 3.16.9  循环不变量代码运动
      10. 3.16.10 循环旋转
      11. 3.16.11 指令排程
      12. 3.16.12 寄存器变量
      13. 3.16.13 寄存器跟踪/定位
      14. 3.16.14 尾部合并
      15. 3.16.15 自动增量寻址
      16. 3.16.16 删除与零的比较
      17. 3.16.17 RPTB 生成(仅适用于FPU 目标)
  6. 链接 C/C++ 代码
    1. 4.1 通过编译器调用链接器(-z 选项)
      1. 4.1.1 单独调用链接器
      2. 4.1.2 调用链接器作为编译步骤的一部分
      3. 4.1.3 禁用链接器(--compile_only 编译器选项)
    2. 4.2 链接器代码优化
      1. 4.2.1 生成函数子段(--gen_func_subsections 编译器选项)
      2. 4.2.2 生成聚合数据子段(--gen_data_subsections 编译器选项)
    3. 4.3 控制链接过程
      1. 4.3.1 包含运行时支持库
        1. 4.3.1.1 自动选择运行时支持库
          1. 4.3.1.1.1 使用 --issue_remarks 选项
        2. 4.3.1.2 手动选择运行时支持库
        3. 4.3.1.3 用于搜索符号的库顺序
      2. 4.3.2 运行时初始化
      3. 4.3.3 通过中断向量进行初始化
      4. 4.3.4 全局对象构造函数
      5. 4.3.5 指定全局变量初始化类型
      6. 4.3.6 指定在内存中分配段的位置
      7. 4.3.7 链接器命令文件示例
    4. 4.4 链接 C28x 和 C2XLP 代码
  7. 链接后优化器
    1. 5.1 链接后优化器在软件开发流程中的作用
    2. 5.2 删除冗余 DP 负载
    3. 5.3 跟踪跨分支的 DP 值
    4. 5.4 跟踪跨函数调用的 DP 值
    5. 5.5 其他链接后优化
    6. 5.6 控制链接后优化
      1. 5.6.1 排除文件(-ex 选项)
      2. 5.6.2 控制汇编文件中的链接后优化
      3. 5.6.3 保留链接后优化器输出(--keep_asm 选项)
      4. 5.6.4 禁用跨函数调用的优化(-nf 选项)
      5. 5.6.5 使用建议对汇编代码进行注释(--plink_advice_only 选项)
    7. 5.7 有关使用链接后优化器的限制
    8. 5.8 命名输出文件(--output_file 选项)
  8. C/C++ 语言实现
    1. 6.1  TMS320C28x C 的特征
      1. 6.1.1 实现定义的行为
    2. 6.2  TMS320C28x C++ 的特征
    3. 6.3  数据类型
      1. 6.3.1 枚举类型大小
      2. 6.3.2 支持 64 位整数
      3. 6.3.3 C28x double 和 long double 浮点类型
    4. 6.4  文件编码和字符集
    5. 6.5  关键字
      1. 6.5.1 const 关键字
      2. 6.5.2 __cregister 关键字
      3. 6.5.3 __interrupt 关键字
      4. 6.5.4 restrict 关键字
      5. 6.5.5 volatile 关键字
    6. 6.6  C++ 异常处理
    7. 6.7  寄存器变量和参数
    8. 6.8  __asm 语句
    9. 6.9  pragma 指令
      1. 6.9.1  CALLS Pragma
      2. 6.9.2  CLINK Pragma
      3. 6.9.3  CODE_ALIGN Pragma
      4. 6.9.4  CODE_SECTION Pragma
      5. 6.9.5  DATA_ALIGN Pragma
      6. 6.9.6  DATA_SECTION Pragma
        1. 6.9.6.1 使用 DATA_SECTION Pragma C 源文件
        2. 6.9.6.2 使用 DATA_SECTION Pragma C++ 源文件
        3. 6.9.6.3 使用 DATA_SECTION Pragma 汇编源文件
      7. 6.9.7  诊断消息 Pragma
      8. 6.9.8  FAST_FUNC_CALL Pragma
      9. 6.9.9  FORCEINLINE Pragma
      10. 6.9.10 FORCEINLINE_RECURSIVE Pragma
      11. 6.9.11 FUNC_ALWAYS_INLINE Pragma
      12. 6.9.12 FUNC_CANNOT_INLINE Pragma
      13. 6.9.13 FUNC_EXT_CALLED Pragma
      14. 6.9.14 FUNCTION_OPTIONS Pragma
      15. 6.9.15 INTERRUPT Pragma
      16. 6.9.16 LOCATION Pragma
      17. 6.9.17 MUST_ITERATE Pragma
        1. 6.9.17.1 MUST_ITERATE Pragma 语法
        2. 6.9.17.2 使用 MUST_ITERATE 扩展编译器对循环的了解
      18. 6.9.18 NOINIT 和 PERSISTENT Pragma
      19. 6.9.19 NOINLINE Pragma
      20. 6.9.20 NO_HOOKS Pragma
      21. 6.9.21 once Pragma
      22. 6.9.22 RETAIN Pragma
      23. 6.9.23 SET_CODE_SECTION 和 SET_DATA_SECTION Pragma
      24. 6.9.24 UNROLL Pragma
      25. 6.9.25 WEAK Pragma
    10. 6.10 _Pragma 运算符
    11. 6.11 应用程序二进制接口
    12. 6.12 目标文件符号命名规则(链接名)
    13. 6.13 在 COFF ABI 模式下初始化静态和全局变量
      1. 6.13.1 使用链接器初始化静态和全局变量
      2. 6.13.2 使用常量类型限定符初始化静态和全局变量
    14. 6.14 更改 ANSI/ISO C/C++ 语言模式
      1. 6.14.1 C99 支持 (--c99)
      2. 6.14.2 C11 支持 (--c11)
      3. 6.14.3 严格 ANSI 模式和宽松 ANSI 模式(--strict_ansi 和 --relaxed_ansi)
    15. 6.15 GNU 和 Clang 语言扩展
      1. 6.15.1 扩展
      2. 6.15.2 函数属性
      3. 6.15.3 For 循环属性
      4. 6.15.4 变量属性
      5. 6.15.5 类型属性
      6. 6.15.6 内置函数
      7. 6.15.7 使用字节外设类型属性
    16. 6.16 编译器限制
  9. 运行时环境
    1. 7.1  存储器模型
      1. 7.1.1
      2. 7.1.2 C/C++ 系统堆栈
      3. 7.1.3 将 .econst 分配给程序内存
      4. 7.1.4 动态存储器分配
      5. 7.1.5 变量的初始化
      6. 7.1.6 为静态变量和全局变量分配内存
      7. 7.1.7 字段/结构对齐
      8. 7.1.8 字符串常量
    2. 7.2  寄存器惯例
      1. 7.2.1 TMS320C28x 寄存器的使用和保留
      2. 7.2.2 状态寄存器
    3. 7.3  函数结构和调用惯例
      1. 7.3.1 函数如何进行调用
      2. 7.3.2 被调用函数如何响应
      3. 7.3.3 被调用函数的特殊情况(大帧)
      4. 7.3.4 访问参数和局部变量
      5. 7.3.5 分配帧并访问内存中的 32 位值
    4. 7.4  访问 C 和 C++ 中的链接器符号
    5. 7.5  将 C 和 C++ 与汇编语言相连
      1. 7.5.1 使用汇编语言模块与 C/C++ 代码
      2. 7.5.2 从 C/C++ 访问汇编语言函数
        1. 7.5.2.1 从 C/C++ 程序调用汇编语言函数
        2. 7.5.2.2 由 调用的汇编语言程序
        3.       261
      3. 7.5.3 从 C/C++ 访问汇编语言变量
        1. 7.5.3.1 访问汇编语言全局变量
          1. 7.5.3.1.1 汇编语言变量程序
          2. 7.5.3.1.2 C 程序从 中访问汇编语言
        2.       266
        3. 7.5.3.2 访问汇编语言常量
          1. 7.5.3.2.1 从 C 语言访问汇编语言常量
          2. 7.5.3.2.2 的汇编语言程序
          3.        270
      4. 7.5.4 与汇编源代码共享 C/C++ 头文件
      5. 7.5.5 使用内联汇编语言
    6. 7.6  使用内在函数访问汇编语言语句
      1. 7.6.1 浮点转换内在函数
      2. 7.6.2 浮点单元 (FPU) 内在函数
      3. 7.6.3 三角函数加速器 (TMU) 固有函数
      4. 7.6.4 快速整数除法内在函数
    7. 7.7  中断处理
      1. 7.7.1 有关中断的要点
      2. 7.7.2 使用 C/C++ 中断例程
    8. 7.8  整数表达式分析
      1. 7.8.1 使用运行时支持调用计算的运算
      2. 7.8.2 支持快速整数除法的除法运算
      3. 7.8.3 C/C++ 代码访问 16 位乘法的上 16 位
    9. 7.9  浮点表达式分析
    10. 7.10 系统初始化
      1. 7.10.1 用于系统预初始化的引导挂钩函数
      2. 7.10.2 运行时栈
      3. 7.10.3 COFF 变量的自动初始化
        1. 7.10.3.1 初始化表
        2.       291
        3. 7.10.3.2 在 COFF 运行时自动初始化变量
        4. 7.10.3.3 加载时初始化 COFF 格式的变量
        5. 7.10.3.4 全局构造函数
      4. 7.10.4 EABI 变量的自动初始化
        1. 7.10.4.1 零初始化变量
        2. 7.10.4.2 EABI 的直接初始化
        3. 7.10.4.3 EABI 运行时变量自动初始化
        4. 7.10.4.4 EABI 的自动初始化表
          1. 7.10.4.4.1 数据格式遵循的长度
          2. 7.10.4.4.2 零初始化格式
          3. 7.10.4.4.3 行程编码 (RLE) 格式
          4. 7.10.4.4.4 Lempel-Ziv-Storer-Szymanski 压缩 (LZSS) 格式
        5. 7.10.4.5 在加载时初始化变量
        6. 7.10.4.6 全局构造函数
  10. 使用运行时支持函数并构建库
    1. 8.1 C 和 C++ 运行时支持库
      1. 8.1.1 将代码与对象库链接
      2. 8.1.2 头文件
      3. 8.1.3 修改库函数
      4. 8.1.4 支持字符串处理
      5. 8.1.5 极少支持国际化
      6. 8.1.6 时间和时钟函数支持
      7. 8.1.7 允许打开的文件数量
      8. 8.1.8 库命名规则
    2. 8.2 C I/O 函数
      1. 8.2.1 高级别 I/O 函数
        1. 8.2.1.1 格式化和格式转换缓冲区
      2. 8.2.2 低级 I/O 实现概述
        1.       open
        2.       close
        3.       read
        4.       write
        5.       lseek
        6.       unlink
        7.       rename
      3. 8.2.3 器件驱动程序级别 I/O 函数
        1.       DEV_open
        2.       DEV_close
        3.       DEV_read
        4.       DEV_write
        5.       DEV_lseek
        6.       DEV_unlink
        7.       DEV_rename
      4. 8.2.4 为 C I/O 添加用户定义的器件驱动程序
        1. 8.2.4.1 将默认流映射到器件
      5. 8.2.5 器件前缀
        1.       add_device
        2.       339
        3. 8.2.5.1 为 C I/O 器件编程
    3. 8.3 处理可重入性(_register_lock() 和 _register_unlock() 函数)
    4. 8.4 在热启动期间重新初始化变量
    5. 8.5 库构建流程
      1. 8.5.1 所需的非德州仪器 (TI) 软件
      2. 8.5.2 使用库构建流程
        1. 8.5.2.1 通过链接器自动重建标准库
        2. 8.5.2.2 手动调用 mklib
          1. 8.5.2.2.1 构建标准库
          2. 8.5.2.2.2 共享或只读库目录
          3. 8.5.2.2.3 使用自定义选项构建库
          4. 8.5.2.2.4 mklib 程序选项摘要
      3. 8.5.3 扩展 mklib
        1. 8.5.3.1 底层机制
        2. 8.5.3.2 来自其他供应商的库
  11. C++ 名称还原器
    1. 9.1 调用 C++ 名称还原器
    2. 9.2 C++ 名称还原器的示例用法
  12. 10CLA 编译器
    1. 10.1 如何调用 CLA 编译器
      1. 10.1.1 CLA 特定的选项
    2. 10.2 CLA C 语言实现
      1. 10.2.1 变量和数据类型
      2. 10.2.2 Pragma、关键字和内在函数
      3. 10.2.3 使用 CLA 编译器进行优化
      4. 10.2.4 C 语言限制
      5. 10.2.5 存储器模型 - 相应的段
      6. 10.2.6 函数结构和调用惯例
  13.   A 术语表
    1.     369
  14.   B 修订历史记录
  15.   B 早期修订版本

使用内在函数访问汇编语言语句

C28x 编译器可识别多种内在函数运算符。一些汇编语句难以或无法用 C/C++ 表达,而内在函数能够表达这类语句的含义。内在函数的用法与函数类似;可以将 C/C++ 变量与这些内在函数结合使用,就像在任何普通函数中一样。

内在函数通过前导双下划线指定,可像用函数调用一样进行访问。例如:

long lvar;
int  ivar;
unsigned int uivar;
lvar = __mpyxu(ivar, uivar);

表 7-6 中列出的内在函数均可用。它们对应于所示的 TMS320C28x 汇编语言指令。更多信息,请参阅《TMS320C28x CPU 和指令集参考指南》。

表 7-6 TMS320C28x C/C++ 编译器内在函数
内在函数 汇编指令 说明
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 将存储器位置 mb 的内容相加并将结果以原子形式存储在 m 中。
long __addcu( long src1, unsigned int src2 ); ADDCU ACC, {mem | reg} src2 的内容和进位位的值加到 ACC 中。结果位于 ACC 中。
void __addl( long *m, long b ); ADDL *m, b 将存储器位置 mb 的内容相加并将结果以原子形式存储在 m 中。
void __and( int *m, int b ); AND * m, b 对存储器位置 mb 的内容进行与运算,并将结果以原子形式存储在 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 位数,并可通过以下方式调用:
__byte(array,5) = 10;
 b = __byte(array,20);
当用于读取存储器时,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 会导致出现未定义的行为。
如果 maxmin 为 22 位无符号常数: MOVL ACC, A
MOVL XAR n, # 22bits
MINL ACC, XAR n
MOVL XAR n, # 22bits
MAXL ACC, XAR n
如果 maxmin 为其他常数: 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 寄存器会载入 src1src2 由存储器引用或载入寄存器。结果位于 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 对存储器位置 mb 的内容进行或运算,并将结果以原子形式存储在 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 中载入 srclimit 值从存储器引用或者载入寄存器。结果位于 ACC 中。结果可以向右移位并存储为整型。例如:
ivar=__sathigh16(lvar, mask)>>6;
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 对存储器位置 mb 的内容进行异或运算,并将结果以原子形式存储在 m 中。