ZHCUAV8W january   1998  – march 2023 66AK2E05 , 66AK2H06 , 66AK2H12 , 66AK2H14 , AM1705 , AM1707 , AM1802 , AM1806 , AM1808 , AM1810 , AM5K2E04 , C346BA02 , C348A01 , CS241C01-Q1 , CS241C05-Q1 , CS246C01-Q1 , CS348C02-Q1 , OMAP-L132 , OMAP-L137 , OMAP-L138 , S470AV336LYSQRB , TMS470R1A288 , TMS470R1A384 , TMS470R1A64 , TMS470R1B1M , TMS470R1B512 , TMS470R1B768

 

  1.   请先阅读
    1.     关于本手册
    2.     标记规则
    3.     相关文档
    4.     德州仪器 (TI) 提供的相关文档
    5.     商标
  2. 1软件开发工具简介
    1. 1.1 软件开发工具概述
    2. 1.2 编译器接口
    3. 1.3 ANSI/ISO 标准
    4. 1.4 输出文件
    5. 1.5 实用程序
  3. 2使用 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 设置默认编译器选项 (TI_ARM_C_OPTION)
      2. 2.4.2 命名一个或多个备用目录 (TI_ARM_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 内联限制
    12. 2.12 使用交叉列出功能
    13. 2.13 控制应用程序二进制接口
    14. 2.14 VFP 支持
    15. 2.15 启用入口挂钩和出口挂钩函数
  4. 3优化您的代码
    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  访问优化代码中的别名变量
    10. 3.10 在优化代码中谨慎使用 asm 语句
    11. 3.11 通过优化使用交叉列出特性
    12. 3.12 调试和分析优化代码
      1. 3.12.1 分析优化的代码
    13. 3.13 正在执行什么类型的优化?
      1. 3.13.1  基于成本的寄存器分配
      2. 3.13.2  别名消歧
      3. 3.13.3  分支优化和控制流简化
      4. 3.13.4  数据流优化
      5. 3.13.5  表达式简化
      6. 3.13.6  函数的内联扩展
      7. 3.13.7  函数符号别名
      8. 3.13.8  归纳变量和强度降低
      9. 3.13.9  循环不变量代码运动
      10. 3.13.10 循环旋转
      11. 3.13.11 指令排程
      12. 3.13.12 尾部合并
      13. 3.13.13 自动增量寻址
      14. 3.13.14 块条件化
        1. 3.13.14.1 块条件化 C 源代码
        2. 3.13.14.2 的 C/C++ 编译器输出
      15. 3.13.15 结语内联
      16. 3.13.16 删除与零的比较
      17. 3.13.17 用常数除数进行整数除法
      18. 3.13.18 分支链接
  5. 4链接 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 生成死函数列表(--generate_dead_funcs_list 选项)
      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 Cinit 的初始化和看门狗计时器保持
      4. 4.3.4 全局对象构造函数
      5. 4.3.5 指定全局变量初始化类型
      6. 4.3.6 指定在内存中分配段的位置
      7. 4.3.7 链接器命令文件示例
  6. 5C/C++ 语言实现
    1. 5.1  ARM C 的特征
      1. 5.1.1 实现定义的行为
    2. 5.2  ARM C++ 的特征
    3. 5.3  使用 MISRA C 2004
    4. 5.4  使用 ULP Advisor
    5. 5.5  数据类型
      1. 5.5.1 枚举类型大小
    6. 5.6  文件编码和字符集
    7. 5.7  关键字
      1. 5.7.1 const 关键字
      2. 5.7.2 __interrupt 关键字
      3. 5.7.3 volatile 关键字
    8. 5.8  C++ 异常处理
    9. 5.9  寄存器变量和参数
      1. 5.9.1 本地寄存器变量和参数
      2. 5.9.2 全局寄存器变量
    10. 5.10 __asm 语句
    11. 5.11 pragma 指令
      1. 5.11.1  CALLS Pragma
      2. 5.11.2  CHECK_MISRA Pragma
      3. 5.11.3  CHECK_ULP Pragma
      4. 5.11.4  CODE_SECTION Pragma
      5. 5.11.5  CODE_STATE Pragma
      6. 5.11.6  DATA_ALIGN Pragma
      7. 5.11.7  DATA_SECTION Pragma
        1. 5.11.7.1 使用 DATA_SECTION Pragma C 源文件
        2. 5.11.7.2 使用 DATA_SECTION Pragma C++ 源文件
        3. 5.11.7.3 使用 DATA_SECTION Pragma 汇编源文件
      8. 5.11.8  诊断消息 Pragma
      9. 5.11.9  DUAL_STATE Pragma
      10. 5.11.10 FORCEINLINE Pragma
      11. 5.11.11 FORCEINLINE_RECURSIVE Pragma
      12. 5.11.12 FUNC_ALWAYS_INLINE Pragma
      13. 5.11.13 FUNC_CANNOT_INLINE Pragma
      14. 5.11.14 FUNC_EXT_CALLED Pragma
      15. 5.11.15 FUNCTION_OPTIONS Pragma
      16. 5.11.16 INTERRUPT Pragma
      17. 5.11.17 LOCATION Pragma
      18. 5.11.18 MUST_ITERATE Pragma
        1. 5.11.18.1 MUST_ITERATE Pragma 语法
        2. 5.11.18.2 使用 MUST_ITERATE 扩展编译器对循环的了解
      19. 5.11.19 NOINIT 和 PERSISTENT Pragma
      20. 5.11.20 NOINLINE Pragma
      21. 5.11.21 NO_HOOKS Pragma
      22. 5.11.22 once Pragma
      23. 5.11.23 pack Pragma
      24. 5.11.24 PROB_ITERATE Pragma
      25. 5.11.25 RESET_MISRA Pragma
      26. 5.11.26 RESET_ULP Pragma
      27. 5.11.27 RETAIN Pragma
      28. 5.11.28 SET_CODE_SECTION 和 SET_DATA_SECTION Pragma
      29. 5.11.29 SWI_ALIAS Pragma
      30. 5.11.30 TASK Pragma
      31. 5.11.31 UNROLL Pragma
      32. 5.11.32 WEAK Pragma
    12. 5.12 _Pragma 运算符
    13. 5.13 应用程序二进制接口
    14. 5.14 ARM 指令内在函数
    15. 5.15 目标文件符号命名规则(链接名)
    16. 5.16 更改 ANSI/ISO C/C++ 语言模式
      1. 5.16.1 C99 支持 (--c99)
      2. 5.16.2 C11 支持 (--c11)
      3. 5.16.3 严格 ANSI 模式和宽松 ANSI 模式(--strict_ansi 和 --relaxed_ansi)
    17. 5.17 GNU 、Clang 和 ACLE 语言扩展
      1. 5.17.1 扩展
      2. 5.17.2 函数属性
      3. 5.17.3 For 循环属性
      4. 5.17.4 变量属性
      5. 5.17.5 类型属性
      6. 5.17.6 内置函数
    18. 5.18 AUTOSAR
    19. 5.19 编译器限制
  7. 6运行时环境
    1. 6.1  存储器模型
      1. 6.1.1
      2. 6.1.2 C/C++ 系统堆栈
      3. 6.1.3 动态存储器分配
    2. 6.2  对象表示
      1. 6.2.1 数据类型存储
        1. 6.2.1.1 char 和 short 数据类型(有符号和无符号)
        2. 6.2.1.2 float、int 和 long 数据类型(有符号和无符号)
        3. 6.2.1.3 double、long double 和 long long 数据类型(有符号和无符号)
        4. 6.2.1.4 指向数据成员类型的指针
        5. 6.2.1.5 指向成员函数类型的指针
        6. 6.2.1.6 结构和数组对齐
      2. 6.2.2 位字段
      3. 6.2.3 字符串常量
    3. 6.3  寄存器惯例
    4. 6.4  函数结构和调用惯例
      1. 6.4.1 函数如何进行调用
      2. 6.4.2 被调用函数如何响应
      3. 6.4.3 C 异常处理程序调用惯例
      4. 6.4.4 访问参数和局部变量
    5. 6.5  访问 C 和 C++ 中的链接器符号
    6. 6.6  将 C 和 C++ 与汇编语言相连
      1. 6.6.1 使用汇编语言模块与 C/C++ 代码
      2. 6.6.2 从 C/C++ 访问汇编语言函数
        1. 6.6.2.1 从 C/C++ 程序调用汇编语言函数
        2. 6.6.2.2 由 调用的汇编语言程序
        3.       237
      3. 6.6.3 从 C/C++ 访问汇编语言变量
        1. 6.6.3.1 访问汇编语言全局变量
          1. 6.6.3.1.1 汇编语言变量程序
          2. 6.6.3.1.2 C 程序从 中访问汇编语言
        2.       242
        3. 6.6.3.2 访问汇编语言常量
          1. 6.6.3.2.1 从 C 语言访问汇编语言常量
          2. 6.6.3.2.2 的汇编语言程序
          3.        246
      4. 6.6.4 与汇编源代码共享 C/C++ 头文件
      5. 6.6.5 使用内联汇编语言
      6. 6.6.6 修改编译器输出
    7. 6.7  中断处理
      1. 6.7.1 在中断期间保存寄存器
      2. 6.7.2 使用 C/C++ 中断例程
      3. 6.7.3 使用汇编语言中断例程
      4. 6.7.4 如何将中断例程映射到中断向量
        1. 6.7.4.1 intvecs.asm 文件示例
      5. 6.7.5 使用软件中断功能
      6. 6.7.6 其他中断信息
    8. 6.8  固有运行时支持算术和转换例程
      1. 6.8.1 CPSR 寄存器和中断内在函数
    9. 6.9  内置函数
    10. 6.10 系统初始化
      1. 6.10.1 用于系统预初始化的引导挂钩函数
      2. 6.10.2 运行时栈
      3. 6.10.3 变量的自动初始化
        1. 6.10.3.1 零初始化变量
        2. 6.10.3.2 的直接初始化
        3. 6.10.3.3 运行时变量自动初始化
        4. 6.10.3.4 的自动初始化表
          1. 6.10.3.4.1 数据格式遵循的长度
          2. 6.10.3.4.2 零初始化格式
          3. 6.10.3.4.3 行程编码 (RLE) 格式
          4. 6.10.3.4.4 Lempel-Ziv-Storer-Szymanski 压缩 (LZSS) 格式
          5. 6.10.3.4.5 用于处理 C 自动初始化表的 C 代码示例
        5. 6.10.3.5 在加载时初始化变量
        6. 6.10.3.6 全局构造函数
      4. 6.10.4 初始化表
    11. 6.11 TIABI 下的双状态交互工作(已弃用)
      1. 6.11.1 双状态支持级别
      2. 6.11.2 实现
        1. 6.11.2.1 入口点的命名规则
        2. 6.11.2.2 间接调用
          1. 6.11.2.2.1 针对 16-BIS 状态编译的 C 代码:sum( )
          2. 6.11.2.2.2 的 16 位汇编语言程序
          3. 6.11.2.2.3 针对 32-BIS 状态编译的 C 代码:sum( )
          4. 6.11.2.2.4 的 32 位汇编语言程序
          5.        286
  8. 7使用运行时支持函数并构建库
    1. 7.1 C 和 C++ 运行时支持库
      1. 7.1.1 将代码与对象库链接
      2. 7.1.2 头文件
      3. 7.1.3 修改库函数
      4. 7.1.4 支持字符串处理
      5. 7.1.5 极少支持国际化
      6. 7.1.6 时间和时钟函数支持
      7. 7.1.7 允许打开的文件数量
      8. 7.1.8 源码树中的非标准头文件
      9. 7.1.9 库命名规则
    2. 7.2 C I/O 函数
      1. 7.2.1 高级别 I/O 函数
        1. 7.2.1.1 格式化和格式转换缓冲区
      2. 7.2.2 低级 I/O 实现概述
        1.       open
        2.       close
        3.       read
        4.       write
        5.       lseek
        6.       unlink
        7.       rename
      3. 7.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. 7.2.4 为 C I/O 添加用户定义的器件驱动程序
        1. 7.2.4.1 将默认流映射到器件
      5. 7.2.5 器件前缀
        1.       add_device
        2.       321
        3. 7.2.5.1 为 C I/O 器件编程
    3. 7.3 处理可重入性(_register_lock() 和 _register_unlock() 函数)
    4. 7.4 库构建流程
      1. 7.4.1 所需的非德州仪器 (TI) 软件
      2. 7.4.2 使用库构建流程
        1. 7.4.2.1 通过链接器自动重建标准库
        2. 7.4.2.2 手动调用 mklib
          1. 7.4.2.2.1 构建标准库
          2. 7.4.2.2.2 共享或只读库目录
          3. 7.4.2.2.3 使用自定义选项构建库
          4. 7.4.2.2.4 mklib 程序选项摘要
      3. 7.4.3 扩展 mklib
        1. 7.4.3.1 底层机制
        2. 7.4.3.2 来自其他供应商的库
  9. 8C++ 名称还原器
    1. 8.1 调用 C++ 名称还原器
    2. 8.2 C++ 名称还原器的示例用法
  10.   A 术语表
    1.     A.1 术语
  11.   B 修订历史记录
  12.   B 早期修订版本

ARM 指令内在函数

可使用下表中的内在函数生成汇编指令。表 5-3 显示了不同 ARM 目标上可用的内在函数。表 5-4 显示了每个内在函数的调用语法,以及相应的汇编指令和说明。节 6.8.1 中提供了用于获取和设置 CPSR 寄存器、启用/禁用中断的其他内在函数。

表 5-3 目标对 ARM 内在函数的支持
C/C++ 编译器内在函数ARM V5e (ARM9E)ARM V6 (ARM11)ARM V6M0 (Cortex-M0)ARM V7M3 (Cortex-M3)ARM V7M4 (Cortex-M4)ARM V7R (Cortex-R4)ARM V7A8 (Cortex-A8)
_ _clz
_ _delay_cycles
_ _get_MSP
_ _get_PRIMASK
_ _ldrex
_ _ldrexb
_ _ldrexd
_ _ldrexh
_ _MCR
_ _MRC
_ _ nop
_norm
_ _rev
_ _rev16
_ _revsh
_ _rbit
_ _ror
_pkhbt
_pkhtb
_qadd16
_qadd8
_qaddsubx
_qsub16
_qsub8
_qsubaddx
_sadd
_sadd16
_sadd8
_saddsubx
_sdadd
_sdsub
_sel
_ _set_MSP
_ _set_PRIMASK
_shadd16
_shadd8
_shsub16
_shsub8
_smac
_smlabb
_smlabt
_smlad
_smladx
_smlalbb
_smlalbt
_smlald
_smlaldx
_smlaltb
_smlaltt
_smlatb
_smlatt
_smlawb
_smlawt
_smlsd
_smlsdx
_smlsld
_smlsldx
_smmla
_smmlar
_smmls
_smmlsr
_smmul
_smmulr
_smuad
_smuadx
_smusd
_smusdx
_smpy
_smsub
_smulbb
_smulbt
_smultb
_smultt
_smulwb
_smulwt
_ _sqrt
_ _sqrtf
_ssat16
_ssata
_ssatl
_ssub
_ssub16
_ssub8
_ssubaddx
_ _strex
_ _strexb
_ _strexd
_ _strexh
_subc
_sxtab
_sxtab16
_sxtah
_sxtb
_sxtb16
_sxth
_uadd16
_uadd8
_uaddsubx
_uhadd16
_uhadd8
_uhsub16
_uhsub8
_umaal
_uqadd16
_uqadd8
_uqaddsubx
_uqsub16
_uqsub8
_uqsubaddx
_usad8
_usat16
_usata
_usatl
_usub16
_usub8
_usubaddx
_uxtab
_uxtab16
_uxtah
_uxtb
_uxtb16
_uxth
_ _wfe
_ _wfi

表 5-4 显示了每个内在函数的调用语法,以及相应的汇编指令和说明。请参阅表 5-3,以查看有关不同 ARM 目标的可用内在函数列表。节 6.8.1 中提供了用于获取和设置 CPSR 寄存器、启用/禁用中断的其他内在函数。

表 5-4 ARM 编译器内在函数
C/C++ 编译器内在函数汇编
指令
说明
int count = _ _clz(int src );CLZcount , src返回前导零的计数。
void _ _delay_cycles( unsigned int cycles );不尽相同将执行指定周期数的延迟。周期数必须是常数。

__delay_cycles 内在函数会插入代码,以精确地使用指定的周期数,而不会产生任何副作用。延迟的周期数必须是编译时间常量。

注意:循环计时基于 0 个等待状态。结果因其他等待状态而异。该实现方案不考虑动态预测。鉴于流水线清除行为,较低的延迟周期计数可能不太准确。

unsigned int dst = _ _get_MSP(void );MRS dst, MSP返回主栈指针的当前值。
unsigned int dst = _ _get_PRIMASK(void );MRS dst, PRIMASK返回优先级屏蔽寄存器的当前值。如果该值为 1,则禁止激活具有可配置优先级的所有异常。
unsigned int dest = _ _ldrex(void* src );LDREXdst , src从包含文字(32 位)数据的内存地址加载数据
unsigned int dest= _ _ldrexb(void* src );LDREXBdst , src从包含字节数据的内存地址加载数据
unsigned long long dest = _ _ldrexd(void* src );LDREXDdst , src从支持 long-long 的内存地址加载数据
unsigned int dest = _ _ldrexh(void* src );LDREXHdst , src从包含半字(16 位)数据的内存地址加载数据
void __MCR (unsigned int coproc, unsigned int opc1, unsigned int src, unsigned int coproc_reg1, unsigned int coproc_reg2, unsigned int opc2);MCRcoproc, opc1, src, CR<coproc_reg1>, CR<coproc_reg2>, opc2访问协处理器寄存器
unsigned int __MRC(unsigned int coproc, unsigned int opc1, unsigned int coproc_reg1, unsigned int coproc_reg2, unsigned int opc2);MRCcoproc, opc1, src, CR<coproc_reg1>, CR<coproc_reg2>, opc2访问协处理器寄存器
void _ _nop( void );NOP执行不做任何事情的指令。
int dst = _norm(int src );CLZ dst , src计算前导零位数。在实现整数规范化时,可以使用此内在函数。
int dst = _pkhbt(int src1 , int src2 , int shift );PKHBTdst , src1 , src2 , #shift组合 src1 的底部半字和 src2 的移位顶部半字
nt dst = _pkhtb(int src1 , int src2 , int shift );PKHTBdst , src1 , src2 , #shift组合 src1 的顶部半字和 src2 的移位底部半字
int dst = _qadd16(int src1 , int src2 );QADD16dst , src1 , src2执行两个有符号半字饱和加法
int dst = _qadd8(int src1 , int src2 );QADD8dst , src1 , src2执行四个有符号饱和 8 位加法
int dst = _qaddsubx(int src1 , int src2 );QASXdst , src1 , src2交换 src2 的半字,对顶部半字执行有符号饱和加法,对底部半字执行有符号饱和减法。
int dst = _qsub16(int src1 , int src2 );QSUB16dst , src1 , src2执行两个有符号饱和半字减法
int dst = _qsub8(int src1 , int src2 );QSUB8dst , src1 , src2执行四个有符号饱和 8 位减法
int dst = _qsubaddx(int src1 , int src2 );QSAXdst , src1 , src2交换 src2 的半字,对顶部半字执行有符号饱和减法,对底部半字执行有符号饱和加法。
int dst = _ _rbit(int src );RBITdst , src反转文字中的位顺序。
int dst = _ _rev(int src );REVdst , src反转文字中的字节顺序。也就是说,在大端字节序和小端字节序之间转换 32 位数据,反之亦然。
int dst = _ _rev16(int src );REV16dst , src独立反转文字中每个字节的字节顺序。也就是说,在大端字节序和小端字节序之间转换 16 位数据,反之亦然。
int dst = _ _revsh(int src );REVSHdst , src反转文字的低位字节的字节顺序,并将符号扩展到 32 位。也就是说,将 16 位有符号数据转换为 32 位有符号数据,同时在大端字节序和小端字节序之间进行转换,反之亦然。
int dst = _ _ror(int src , int shift );RORdst , src , shift将值向右旋转指定的位数。从右端旋转的位放入左端的空位。
int dst =_sadd(int src1 , int src2 );QADDdst , src1 , src2饱和加法
int dst = _sadd16(int src1 , int src2 );SADD16 dst , src1 , src2执行两个有符号半字加法
int dst = _sadd8(int src1 , int src2 );SADD8dst , src1 , src2执行四个有符号 8 位加法
int dst = _saddsubx(int src1 , int src2 );SASXdst , src1 , src2交换 src2 的半字,添加顶部半字并减去底部半字
int dst =_sdadd(int src1 , int src2 );QDADDdst , src1 , src2饱和双加
int dst =_sdsub(int src1 , int src2 );QDSUBdst , src1 , src2饱和双减
int dst = _sel(int src1 , int src2 );SELdst , src1 , src2如果设置了 GE 位 n,则从 src1 选择字节 n;如果未设置 GE 位 n,则从 src2 选择字节 n,其中 n 的范围为 0 到 3。
void _ _set_MSP(unsigned int src);MSR MSP,src将主栈指针的值设置为 src。
unsigned int dst = _ _set_PRIMASK(unsigned int src);MRSdst , PRIMASK (optional)
MSR PRIMASK, src
将优先级屏蔽寄存器设置为 src 值,并返回设置为 dst 之前的值。将此寄存器设置为 1 可防止激活具有可配置优先级的所有异常。
int dst = _shadd16(int src1 , int src2 );SHADD16dst , src1 , src2执行两个带符号的半字加法并将结果减半
int dst = _shadd8(int src1 , int src2 );SHADD8 dst , src1 , src2执行四个带符号的 8 位加法并将结果减半
int dst = _shsub16(int src1 , int src2 );SHSUB16dst , src1 , src2执行两个带符号的半字减法并将结果减半
int dst = _shsub8int src1 , int src2 );SHSUB8dst , src1 , src2执行四个带符号的 8 位减法并将结果减半
int dst =_smac(int dst, int src1 , int src2 );SMULBB tmp , src1 , src2
QDADD dst, dst , tmp
饱和乘法累加
int dst =_smlabb(int dst , short src1 , short src2 );SMLABB dst , src1 , src2有符号乘法累加底部半字
int dst =_smlabt(int dst , short src1 , int src2 );SMLABT dst , src1 , src2有符号乘法累加底部半字和顶部半字
int dst _smlad(int src1 , int src2 , int acc );SMLADdst , src1 , src2 , acc对 src1 和 src2 的顶部半字和底部半字执行两次有符号 16 位乘法,并将结果添加到 acc。
int dst _smladx(int src1 , int src2 , int acc );SMLADXdst , src1 , src2 , acc与 _smlad 相同,只是 src2 中的半字在乘法之前交换。
long long dst =_smlalbb(long long dst , short src1 , short src2 );SMLALBB dstlo , dsthi , src1 , src2有符号长整数乘法并累加底部半字
long long dst =_smlalbt(long long dst , short src1 , int src2 );SMLALBT dstlo , dsthi , src1 , src2有符号长整数乘法并累加底部半字和顶部半字
long long dst _smlald(long long acc , int src1 , int src2 );SMLALDdst , src1 , src2对 src1 和 src2 的顶部半字和底部半字执行两次 16 位乘法,并将结果添加到 64 位 acc 操作数
long long dst _smlaldx(long long acc , int src1 , int src2 );SMLALDX dst , src1 , src2与 _smlald 相同,只是 src2 中的半字已交换。
long long dst =_smlaltb(long long dst , int src1 , short src2 );SMLALTB dstlo , dsthi , src1 , src2有符号长整数乘法并累加顶部半字和底部半字
long long dst =_smlaltt(long long dst , int src1 , int src2 );SMLALTT dstlo , dsthi , src1 , src2有符号长整数乘法并累加顶部半字
int dst =_smlatb(int dst , int src1 , short src2 );SMLATB dst , src1 , src2有符号乘法累加顶部半字和底部半字
int dst =_smlatt(int dst , int src1 , int src2 );SMLATT dst , src1 , src2有符号乘法累加顶部半字
int dst _smlawb(int src1 , short src2 , int acc );SMLAWB dst , src1 , src2有符号乘法累加文字和底部半字
int dst _smlawt(int src1 , short src2 , int acc );SMLAWT dst , src1 , src2有符号乘法累加文字和顶部半字
int dst _smlsd(int src1 , int src2 , int acc );SMLSDdst , src1 , src2 , acc对 src1 和 src2 的顶部半字和底部半字执行两次有符号 16 位乘法,并将结果差异添加到 acc。
int dst _smlsdx(int src1 , int src2 , int acc );SMLSDXdst , src1 , src2 , acc与 _smlsd 相同,只是 src2 中的半字在乘法之前交换。
long long dst _smlsld(long long acc , int src1 , int src2 );SMLSLDdst , src1 , src2对 src1 和 src2 的顶部半字和底部半字执行两次 16 位乘法,并将结果差异添加到 64 位 acc 操作数。
long long dst _smlsldx(long long acc , int src1 , int src2 );SMLSLDX dst , src1 , src2与 _smlsld 相同,只是 src2 中的半字已交换。
int dst _smmla(int src1 , int src2 , int acc );SMMLAdst , src1 , src2 , acc对 src1 和 src2 执行有符号乘法,提取结果的最高有效 32 位,并添加累积值。
int dst _smmlar(int src1 , int src2 , int acc );SMMLARdst , src1 , src2 , acc与 _smmla 相同,只是结果是四舍五入的,而不是被截断的。
int dst _smmls(int src1 , int src2 , int acc );SMMLSdst , src1 , src2 , acc对 src1 和 src2 执行有符号乘法,从左移 32 位的累积值中减去结果,并提取减法结果的最高有效 32 位。
int dst _smmlsr(int src1 , int src2 , int acc );SMMLSRdst , src1 , src2 , acc与 _smmls 相同,只是结果是四舍五入的,而不是被截断的。
int dst _smmul(int src1 , int src2 , int acc );SMMULdst , src1 , src2 , acc对 src1 和 src2 执行有符号 32 位乘法,并提取结果的最高有效 32 位。
int dst _smmulr(int src1 , int src2 , int acc );SMMULRdst , src1 , src2 , acc与 _smmul 相同,只是结果是四舍五入的,而不是被截断的。
int dst =_smpy(int src1 , int src2 );SMULBB dst , src1 , src2
QADD dst, dst , dst
饱和乘法
int dst =_smsub(int src1 , int src2 );SMULBB tmp , src1 , src2
QDSUB dst, dst , tmp
饱和乘减
int dst _smuad(int src1 , int src2 );SMUADdst , src1 , src2对顶部半字和底部半字执行两次有符号 16 位乘法,并将乘积相加。
int dst _smuadx(int src1 , int src2 );SMUADXdst , src1 , src2与 _smuad 相同,只是 src2 中的半字在乘法之前交换。
int dst =_smulbb(int src1 , int src2 );SMULBB dst , src1 , src2有符号乘法底部半字
int dst =_smulbt(int src1 , int src2 );SMULBT dst , src1 , src2有符号乘法底部半字和顶部半字
int dst =_smultb(int src1 , int src2 );SMULTB dst , src1 , src2有符号乘法顶部半字和底部半字
int dst =_smultt(int src1 , int src2 );SMULTT dst , src1 , src2有符号乘法顶部半字
int dst _smulwb(int src1 , short src2 , int acc );SMULWB dst , src1 , src2有符号乘法文字和底部半字
int dst _smulwt(int src1 , short src2 , int acc );SMULWT dst , src1 , src2有符号乘法文字和顶部半字
int dst _smusd(int src1 , int src2 );SMUSDdst , src1 , src2对顶部半字和底部半字执行两次有符号 16 位乘法,并减去乘积。
int dst _smusdx(int src1 , int src2 );SMUSDXdst , src1 , src2与 _smusd 相同,只是 src2 中的半字在乘法之前交换。
double __sqrt( double );VSQRTdst , src1返回指定双精度值的平方根。如果 --fp_mode=relaxed,则直接使用 VSQRT 指令替换此内在函数。如果使用严格浮点模式并且发生域错误,函数还必须设置 errno。
float __sqrtf( float );VSQRTdst , src1返回指定浮点值的平方根。如果 --fp_mode=relaxed,则直接使用 VSQRT 指令替换此内在函数。如果使用严格浮点模式并且发生域错误,函数还必须设置 errno。
int dst =_ssat16(int src , int bitpos );SSAT16dst , #bitpos对 bitpos 指定的可选有符号范围执行两个半字饱和
int dst =_ssata(int src , int shift , int bitpos );SSAT dst , #bitpos, src, ASR #shift右移 src 并饱和到 bitpos 指定的可选有符号范围
int dst =_ssatl(int src , int shift , int bitpos );SSAT dst , #bitpos, src, LSL #shift左移 src 并饱和到 bitpos 指定的可选有符号范围
int dst =_ssub(int src1 , int src2 );QSUBdst , src1 , src2饱和减法
int dst = _ssub16(int src1 , int src2 );SSUB16 dst , src1 , src2执行两个有符号半字减法
int dst = _ssub8(int src1 , int src2 );SSUB8dst , src1 , src2执行四个有符号 8 位减法
int dst = _ssubaddx(int src1 , int src2 );SSAXdst , src1 , src2交换 src2 的半字,减去顶部半字并添加底部半字
int status = _ _strex(unsigned int src, void* dst );STREXstatus , src , dest在内存地址中存储文字(32 位)数据
int status = _ _strexb(unsigned char src, void* dst );STREXBstatus , src , dest在内存地址中存储字节数据
int status = _ _strexd(unsigned long long src, void* dst );STREXDstatus , src , dest在内存地址中存储超长整型数据
int status = _ _strexh(unsigned short src, void* dst );STREXHstatus , src , dest在内存地址中存储半字(16 位)数据
int dst = _subc(int src1 , int src2 );SUBCdst , src1 , src2带进位的减法
int dst _sxtab(int src1 , int src2 , int rotamt );SXTABdst , src1 , src2 , ROR #rotamt从 src2 中提取一个可选的旋转 8 位值,并将其符号扩展到 32 位,然后将该值添加到 src1。旋转量可以是 0、8、16 或 24。
int dst _sxtab16(int src1 , int src2 , int rotamt );SXTAB16 dst , src1 , src2 , ROR #rotamt从 src2 中提取两个可选的旋转 8 位值,并将其符号扩展到每个 16 位,然后将这些值添加到 src1 中的两个 16 位值。旋转量应为 0、8、16 或 24。
int dst _sxtah(int src1 , int src2 , int rotamt );SXTAHdst , src1 , src2 , ROR #rotamt从 src2 中提取一个可选的旋转 16 位值,并将其符号扩展到 32 位,然后将结果添加到 src1。旋转量可以是 0、8、16 或 32。
int dst _sxtb(int src1 , int rotamt );SXTB dst , src1 , ROR #rotamt从 src1 中提取一个可选的旋转 8 位值,并将其符号扩展到 32 位。旋转量可以是 0、8、16 或 24。
int dst _sxtb16(int src1 , int rotamt );SXTAB16 dst , src1 , ROR #rotamt从 src1 中提取两个可选的旋转 8 位值,并将其符号扩展到 16 位。旋转量可以是 0、8、16 或 24。
int dst _sxth(int src1 , int rotamt );SXTHdst , src1 , ROR #rotamt从 src2 中提取一个可选的旋转 16 位值,并将其符号扩展到 32 位。旋转量可以是 0、8、16 或 24。
int dst = _uadd16(int src1 , int src2 );UADD16 dst , src1 , src2执行两个无符号半字加法
int dst = _uadd8(int src1 , int src2 );UADD8dst , src1 , src2执行四个无符号 8 位加法
int dst = _uaddsubx(int src1 , int src2 );UASXdst , src1 , src2交换 src2 的半字,添加顶部半字并减去底部半字
int dst = _uhadd16(int src1 , int src2 );UHADD16dst , src1 , src2执行两个无符号的半字加法并将结果减半
int dst = _uhadd8(int src1 , int src2 );UHADD8 dst , src1 , src2执行四个无符号的 8 位加法并将结果减半
int dst = _uhsub16(int src1 , int src2 );UHSUB16dst , src1 , src2执行两个无符号的半字减法并将结果减半
int dst = _uhsub8(int src1 , int src2 );UHSUB8 dst , src1 , src2执行四个无符号的 8 位减法并将结果减半
int dst = _umaal(long long acc , int src1 , int src2 );UMAALdst1 , dst2 , src1 , src2对 src1 和 src2 执行无符号 32 位乘法,然后在 acc 中添加两个无符号 32 位值。
int dst = _uqadd16(int src1 , int src2 );UQADD16dst , src1 , src2执行两个无符号半字饱和加法
int dst = _uqadd8(int src1 , int src2 );UQADD8 dst , src1 , src2执行四个无符号饱和 8 位加法
int dst = _uqaddsubx(int src1 , int src2 );UQASXdst , src1 , src2交换 src2 的半字,对顶部半字执行无符号饱和加法,对底部半字执行无符号饱和减法。
int dst = _uqsub16(int src1 , int src2 );UQSUB16dst , src1 , src2执行两个无符号饱和半字减法
int dst = _uqsub8(int src1 , int src2 );UQSUB8 dst , src1 , src2执行四个无符号饱和 8 位减法
int dst = _uqsubaddx(int src1 , int src2 );UQSAXdst , src1 , src2交换 src2 的半字,对顶部半字执行无符号饱和减法,对底部半字执行无符号饱和加法。
int dst = _usad8(int src1 , int src2 );USAD8dst , src1 , src2执行四个无符号 8 位减法,并将差值的绝对值相加。
int dst =_usat16(int src , int bitpos );USAT16 dst , #bitpos对 bitpos 指定的可选无符号范围执行两个半字饱和
int dst =_usata(int src , int shift , int bitpos );USAT dst , #bitpos, src, ASR #shift右移 src 并饱和到 bitpos 指定的可选无符号范围
int dst =_usatl(int src , int shift , int bitpos );USAT dst , #bitpos, src, LSL #shift左移 src 并饱和到 bitpos 指定的可选无符号范围
int dst = _usub16(int src1 , int src2 );USUB16 dst , src1 , src2执行两个无符号半字减法
int dst = _usub8(int src1 , int src2 );USUB8dst , src1 , src2执行四个无符号 8 位减法
int dst = _usubaddx(int src1 , int src2 );USAXdst , src1 , src2交换 src2 的半字,减去顶部半字并添加底部半字
int dst _uxtab(int src1 , int src2 , int rotamt );UXTABdst , src1 , src2 , ROR #rotamt从 src2 中提取一个可选的旋转 8 位值,并将 0 扩展到 32 位,然后将该值添加到 src1。旋转量可以是 0、8、16 或 24。
int dst _uxtab16(int src1 , int src2 , int rotamt );UXTAB16 dst , src1 , src2 , ROR #rotamt从 src2 中提取两个可选的旋转 8 位值,并将 0 扩展到每个 16 位,然后将这些值添加到 src1 中的两个 16 位值。旋转量应为 0、8、16 或 24。
int dst _uxtah(int src1 , int src2 , int rotamt );UXTAHdst , src1 , src2 , ROR #rotamt从 src2 中提取一个可选的旋转 16 位值,并将 0 扩展到 32 位,然后将结果添加到 src1。旋转量可以是 0、8、16 或 32。
int dst _uxtb(int src1 , int rotamt );UXTBdst , src1 , ROR #rotamt从 src2 中提取一个可选的旋转 8 位值,并将 0 扩展到 32 位。旋转量可以是 0、8、16 或 24。
int dst _uxtb16(int src1 , int rotamt );UXTB16dst , src1 , ROR #rotamt从 src1 中提取两个可选的旋转 8 位值,并将 0 扩展到 16 位。旋转量可以是 0、8、16 或 24。
int dst _uxth(int src1 , int rotamt );UXTHdst , src1 , ROR #rotamt从 src2 中提取一个可选的旋转 16 位值,并将 0 扩展到 32 位。旋转量可以是 0、8、16 或 24。
void _ _wfe( void );WFE等待事件。通过等待异常或事件来节省电源。
void _ _wfi( void );WFI等待中断。进入待机、休眠或关机模式,在此类模式中,需要中断才能将处理器唤醒。

此外,编译器还支持 ARM C 语言扩展 (ACLE) 规范中所述的许多内在函数。这些内在函数适用于 Cortex-M 和 Cortex-R 处理器变体。实现 ACLE 内在函数以支持源代码开发,这些源代码可以使用多个供应商提供的 ACLE 兼容编译器为各种 ARM 处理器进行编译。许多内在函数与上表中列出的内在函数重复,但名称略有不同(例如一个与两个前导下划线)。

编译器不支持 ACLE 规格中列出的所有 ACLE 内在函数。例如,CLS 指令在 Cortex-M 或 Cortex-R 架构上不可用,因此不支持 __cls、__clsl 和 __clsll ACLE 内在函数。

为了使用 ACLE 内在函数,您的代码必须包含提供的 arm_acle.h 头文件。有关 ACLE 内在函数的详细信息,请参阅 ACLE 规格。有关支持哪些 ACLE 内在函数的信息,请参阅 arm_acle.h 文件。在适用的情况下,不受支持的 ACLE 内在函数声明将包含在该头文件中的注释中,并简要说明不支持该内在函数的原因,以及包含对 ACLE 规格中描述该内在函数的相应章节的引用。