ZHCADC5A June   2013  – June 2020

 

  1.   1
  2. 简介
    1. 1.1  ABI - MSP430
    2. 1.2  范围
    3. 1.3  ABI 变体
    4. 1.4  工具链和互操作性
    5. 1.5 
    6. 1.6  目标文件的类型
    7. 1.7 
    8. 1.8  MSP430 架构概述
    9. 1.9  MSP430 存储器模型
    10. 1.10 参考文档
    11. 1.11 代码片段表示法
  3. 数据表示
    1. 2.1 基本类型
    2. 2.2 寄存器中的数据
    3. 2.3 存储器中的数据
    4. 2.4 指针类型
    5. 2.5 复数类型
    6. 2.6 结构体和联合体
    7. 2.7 数组
    8. 2.8 位字段
      1. 2.8.1 易失性位字段
    9. 2.9 枚举类型
  4. 调用约定
    1. 3.1 调用和返回
      1. 3.1.1 调用指令
        1. 3.1.1.1 间接调用
        2. 3.1.1.2 直接调用
      2. 3.1.2 返回指令
      3. 3.1.3 流水线约定
      4. 3.1.4 弱函数
    2. 3.2 寄存器惯例
      1. 3.2.1 实参寄存器
      2. 3.2.2 被调用者保存的寄存器
    3. 3.3 实参传递
      1. 3.3.1 单个寄存器
      2. 3.3.2 寄存器对
      3. 3.3.3 拆分对
      4. 3.3.4 四倍字(四寄存器实参)
      5. 3.3.5 编译器辅助函数的特殊约定
      6. 3.3.6 C++ 实参传递
      7. 3.3.7 传递结构体和联合体
      8. 3.3.8 未在寄存器中传递的实参的栈布局
      9. 3.3.9 帧指针
    4. 3.4 返回值
    5. 3.5 通过引用传递并返回的结构体和联合体
    6. 3.6 编译器辅助函数的约定
    7. 3.7 已见函数的暂存寄存器
    8. 3.8 _ _mspabi_func_epilog 辅助函数
    9. 3.9 中断函数
  5. 数据分配和寻址
    1. 4.1 数据段和数据区段
    2. 4.2 寻址模式
    3. 4.3 静态数据的分配和寻址
      1. 4.3.1 静态数据的寻址方法
        1. 4.3.1.1 绝对寻址
        2. 4.3.1.2 符号寻址
        3. 4.3.1.3 立即寻址
      2. 4.3.2 静态数据的放置约定
        1. 4.3.2.1 放置的抽象约定
        2. 4.3.2.2 寻址的抽象约定
      3. 4.3.3 静态数据的初始化
    4. 4.4 自动变量
    5. 4.5 帧布局
      1. 4.5.1 栈对齐
      2. 4.5.2 寄存器保存顺序
    6. 4.6 堆分配对象
  6. 代码分配和寻址
    1. 5.1 计算代码标签的地址
      1. 5.1.1 代码的绝对寻址
      2. 5.1.2 符号寻址
      3. 5.1.3 立即寻址
    2. 5.2 分支
    3. 5.3 调用
      1. 5.3.1 直接 调用
      2. 5.3.2 Far Call Trampoline
      3. 5.3.3 间接调用
  7. 辅助函数 API
    1. 6.1 浮点行为
    2. 6.2 C 辅助函数 API
    3. 6.3 辅助函数的特殊寄存器约定
    4. 6.4 C99 的浮点辅助函数
  8. 标准 C 库 API
    1. 7.1  保留符号
    2. 7.2  <assert.h> 实现
    3. 7.3  <complex.h> 实现
    4. 7.4  <ctype.h> 实现
    5. 7.5  <errno.h> 实现
    6. 7.6  <float.h> 实现
    7. 7.7  <inttypes.h> 实现
    8. 7.8  <iso646.h> 实现
    9. 7.9  <limits.h> 实现
    10. 7.10 <locale.h> 实现
    11. 7.11 <math.h> 实现
    12. 7.12 <setjmp.h> 实现
    13. 7.13 <signal.h> 实现
    14. 7.14 <stdarg.h> 实现
    15. 7.15 <stdbool.h> 实现
    16. 7.16 <stddef.h> 实现
    17. 7.17 <stdint.h> 实现
    18. 7.18 <stdio.h> 实现
    19. 7.19 <stdlib.h> 实现
    20. 7.20 <string.h> 实现
    21. 7.21 <tgmath.h> 实现
    22. 7.22 <time.h> 实现
    23. 7.23 <wchar.h> 实现
    24. 7.24 <wctype.h> 实现
  9. C++ ABI
    1. 8.1  限制 (GC++ABI 1.2)
    2. 8.2  导出模板 (GC++ABI 1.4.2)
    3. 8.3  数据布局(GC++ABI 第 2 章)
    4. 8.4  初始化保护变量 (GC++ABI 2.8)
    5. 8.5  构造函数返回值 (GC++ABI 3.1.5)
    6. 8.6  一次性构建 API (GC++ABI 3.3.2)
    7. 8.7  控制对象构造顺序 (GC++ ABI 3.3.4)
    8. 8.8  还原器 API (GC++ABI 3.4)
    9. 8.9  静态数据 (GC++ ABI 5.2.2)
    10. 8.10 虚拟表和键函数 (GC++ABI 5.2.3)
    11. 8.11 回溯表位置 (GC++ABI 5.3)
  10. 异常处理
    1. 9.1  概述
    2. 9.2  PREL31 编码
    3. 9.3  异常索引表 (EXIDX)
      1. 9.3.1 指向行外 EXTAB 条目的指针
      2. 9.3.2 EXIDX_CANTUNWIND
      3. 9.3.3 内联 EXTAB 条目
    4. 9.4  异常处理指令表 (EXTAB)
      1. 9.4.1 EXTAB 通用模型
      2. 9.4.2 EXTAB 紧凑模型
      3. 9.4.3 个性化例程
    5. 9.5  回溯指令
      1. 9.5.1 通用序列
      2. 9.5.2 字节编码展开指令
    6. 9.6  描述符
      1. 9.6.1 类型标识符编码
      2. 9.6.2 作用域
      3. 9.6.3 Cleanup 描述符
      4. 9.6.4 catch 描述符
      5. 9.6.5 函数异常规范 (FESPEC) 描述符
    7. 9.7  特殊段
    8. 9.8  与非 C++ 代码交互
      1. 9.8.1 EXIDX 条目自动生成
      2. 9.8.2 手工编码的汇编函数
    9. 9.9  与系统功能交互
      1. 9.9.1 共享库
      2. 9.9.2 覆盖块
      3. 9.9.3 中断
    10. 9.10 TI 工具链中的汇编语言运算符
  11. 10DWARF
    1. 10.1 DWARF 寄存器名称
    2. 10.2 调用帧信息
    3. 10.3 供应商名称
    4. 10.4 供应商扩展
  12. 11ELF 目标文件(处理器补充)
    1. 11.1 注册供应商名称
    2. 11.2 ELF 标头
    3. 11.3
      1. 11.3.1 段索引
      2. 11.3.2 段类型
      3. 11.3.3 扩展段标头属性
      4. 11.3.4 子段
      5. 11.3.5 特殊段
      6. 11.3.6 段对齐
    4. 11.4 符号表
      1. 11.4.1 符号类型
      2. 11.4.2 通用块符号
      3. 11.4.3 符号名称
      4. 11.4.4 保留符号名称
      5. 11.4.5 映射符号
    5. 11.5 重定位
      1. 11.5.1 重定位类型
        1. 11.5.1.1 绝对重定位
        2. 11.5.1.2 PC 相对重定位
        3. 11.5.1.3 数据段中的重定位
        4. 11.5.1.4 MSP430 指令的重定位
        5. 11.5.1.5 MSP430X 指令的重定位
        6. 11.5.1.6 其他重定位类型
      2. 11.5.2 重定位操作
      3. 11.5.3 未解析的弱引用的重定位
  13. 12ELF 程序加载和链接(处理器补充)
    1. 12.1 程序标头
      1. 12.1.1 基址
      2. 12.1.2 段内容
      3. 12.1.3 线程局部存储
    2. 12.2 程序加载
  14. 13构建属性
    1. 13.1 MSP430 ABI 构建属性子段
    2. 13.2 MSP430 构建属性标签
  15. 14复制表和变量初始化
    1. 14.1 复制表格式
    2. 14.2 压缩的数据格式
      1. 14.2.1 RLE
      2. 14.2.2 LZSS 格式
    3. 14.3 变量初始化
  16. 15修订历史记录

C 辅助函数 API

编译器生成对辅助函数的调用以执行编译器需要支持但架构不直接支持的运算,例如在缺少专用硬件的设备上执行浮点运算。这些辅助函数必须在符合 ABI 的任何工具链的 RTS 库中实现。

辅助函数使用前缀 _ _MSP430 命名。具有此前缀的任何标识符都将保留供 ABI 使用。

辅助函数遵守标准调用约定节 6.3中指定的约定除外

下表使用 C 表示法和语法指定辅助函数。表中的类型对应于节 2.1中指定的通用数据类型。

表 6-1 中的函数根据 C 语言的转会规则以及节 6.1指定的浮点行为在各种浮点和 int 格式之间进行转换。

表 6-1 MSP430 浮点和 int 转换
签名说明
float32 _ _MSP430_cvtdf(float64 x);将双精度浮点型转换为单精度浮点型
float64 _ _MSP430_cvtfd(float32 x);将单精度浮点型转换为双精度浮点型
int16 _ _MSP430_fixdi(float64 x);将双精度浮点型转换为 int
int32 _ _MSP430_fixdli(float64 x);将双精度浮点型转换为 long int
int64 _ _MSP430_fixdlli(float64 x);将双精度浮点型转换为 long long int
uint16 _ _MSP430_fixdu(float64 x);将双精度浮点型转换为 unsigned int
uint32 _ _MSP430_fixdul(float64 x);将双精度浮点型转换为 unsigned long int
uint64 _ _MSP430_fixdull(float64 x);将双精度浮点型转换为 unsigned long long int
int16 _ _MSP430_fixfi(float32 x);将单精度浮点型转换为 int
int32 MSP430_fixfli (float32 x);将单精度浮点型转换为 long int
int64 _ _MSP430_fixflli(float32 x);将单精度浮点型转换为 long long int
uint16 _ _MSP430_fixfu(float32 x);将单精度浮点型转换为 unsigned int
uint32 _ _MSP430_fixful(float32 x);将单精度浮点型转换为 unsigned long int
uint64 _ _MSP430_fixfull(float32 x);将单精度浮点型转换为 unsigned long long int
float64 _ _MSP430_fltid(int16 x);将 int 转换为双精度浮点型
float32 _ _MSP430_fltif(int16 x);将 int 转换为单精度浮点型
float64 _ _MSP430_fltlid(int32 x);将 long int 转换为双精度浮点型
float32 _ _MSP430_fltlif(int32 x);将 long int 转换为单精度浮点型
float64 _ _MSP430_fltud(uint16 x);将 unsigned int 转换为双精度浮点型
float32 _ _MSP430_fltuf(uint16 x);将 unsigned int 转换为单精度浮点型
float64 _ _MSP430_fltuld(uint32 x);将 unsigned long int 转换为双精度浮点型
float32 _ _MSP430_fltulf(uint32 x);将 unsigned long int 转换为单精度浮点型

表 6-2 中的函数根据 C 语言的语义和节 6.1指定的浮点行为执行浮点比较。

如果 x 小于 y,则MSP430_cmp 函数返回一个小于 0 的整数;如果 x 等于 y,则返回 0;如果 x 大于 y,则返回一个大于 0 的整数。如果任一操作数为 NaN,则结果未定义。

其余的比较函数当前不受支持,但保留了名称以供将来使用。

表 6-2 MSP430 浮点比较
签名说明
int16 _ _MSP430_cmpd(float64 x, float64 y);双精度比较
int16 _ _MSP430_cmpf(float32 x, float32 y);单精度比较
int16 _ _MSP430_eqd(float64 x, float64 y);双精度比较:x == y(当前不受支持)
int16  _MSP430_geqdfloat64 x、float64 y);双精度比较:x >= y(当前不受支持)
int16 _ _MSP430_gtrd(float64 x, float64 y);双精度比较:x > y(当前不受支持)
int16 _ _MSP430_leqd(float64 x, float64 y);双精度比较:x <= y(当前不受支持)
int16 _ _MSP430_lssd(float64 x, float64 y);双精度比较:x < y(当前不受支持)
int16 _ _MSP430_neqd(float64 x, float64 y);双精度比较:x!= y(当前不受支持)

表 6-3 中的函数根据 C 语言的语义和节 6.1指定的浮点行为执行浮点运算。

表 6-3 MSP430 浮点算术
签名说明
float64 _ _MSP430_addd(float64 x, float64 y);双精度与双精度相加
float32 _ _MSP430_addf(float32 x, float32 y);单精度与单精度相加
float64 _ _MSP430_divd(float64 x, float64 y);双精度除以双精度
float32 _ _MSP430_divf(float32 x, float32 y);单精度除以单精度
float64 _ _MSP430_mpyd(float64 x, float64 y);双精度与双精度相乘
float32 _ _MSP430_mpyf(float32 x, float32 y);单精度与单精度相乘
float64 _ _MSP430_subd(float64 x, float64 y);从双精度中减去双精度
float32 _ _MSP430_subf(float32 x, float32 y);从单精度中减去单精度
float64 _ _MSP430_negd(float64 x);将双精度数取反
float32 _ _MSP430_negf(float32 x);将单精度数取反

表 6-4 中的整数算术函数根据 C 语言的语义进行运算。

表 6-4 MSP430 整数乘法、除法和余数
签名 说明
乘法
int16 _ _MSP430_mpyi(int16 x, int16 y); int 与 int 相乘。
int16 _ _MSP430_mpyi_hw(int16 x, int16 y); int 与 int 相乘。使用硬件 MPY16。
int16 _ _MSP430_mpyi_f5hw(int16 x, int16 y); int 与 int 相乘。使用硬件 MPY32(F5xx 器件及更高版本)。
int32 _ _MSP430_mpyl(int32 x, int32 y); long 与 long 相乘。
int32 _ _MSP430_mpyl_hw(int32 x, int32 y); long 与 long 相乘。使用硬件 MPY16。
int32 _ _MSP430_mpyl_hw32(int32 x, int32 y); long 与 long 相乘。使用硬件 MPY32(F4xx 器件)。
int32 _ _MSP430_mpyl_f5hw(int32 x, int32 y); long 与 long 相乘。使用硬件 MPY32(F5xx 器件及更高版本)。
int64 _ _MSP430_mpyll(int64 x, int64 y); long long 与 long long 相乘。
int64 _ _MSP430_mpyll_hw(int64 x, int64 y); long long 与 long long 相乘。使用硬件 MPY16。
int64 _ _MSP430_mpyll_hw32(int64 x, int64 y); long long 与 long long 相乘。使用硬件 MPY32(F4xx 器件)。
int64 _ _MSP430_mpyll_f5hw(int64 x, int64 y); long long 与 long long 相乘。使用硬件 MPY32(F5xx 器件及更高版本)。
int32 _ _MSP430_mpysl(int16 x, int16 y); int 与 int 相乘;结果为 long。
int32 _ _MSP430_mpysl_hw(int16 x, int16 y); int 与 int 相乘;结果为 long。使用硬件 MPY16。
int32 _ _MSP430_mpysl_f5hw(int16 x, int16 y); int 与 int 相乘;结果为 long。使用硬件 MPY32(F5xx 器件及更高版本)。
int64 _ _MSP430_mpysll(int32 x, int32 y); long 与 long 相乘;结果为 long long。
int64 _ _MSP430_mpysll_hw(int32 x, int32 y); long 与 long 相乘;结果为 long long。使用硬件 MPY16。
int64 _ _MSP430_mpysll_hw32(int32 x, int32 y); long 与 long 相乘;结果为 long long。使用硬件 MPY32(F4xx 器件)。
int64 _ _MSP430_mpysll_f5hw(int32 x, int32 y); long 与 long 相乘;结果为 long long。使用硬件 MPY32(F5xx 器件及更高版本)。
uint32 _ _MSP430_mpyul(uint16 x, uint16 y); 将 unsigned int 与 unsigned int 相乘;结果为 unsigned long。
uint32 _ _MSP430_mpyul_hw(uint16 x, uint16 y); 将 unsigned int 与 unsigned int 相乘;结果为 unsigned long。使用硬件 MPY16。
uint32 _ _MSP430_mpyul_f5hw(uint16 x, uint16 y); 将 unsigned int 与 unsigned int 相乘;结果为 unsigned long。使用硬件 MPY32(F5xx 器件及更高版本)。
uint64 _ _MSP430_mpyull(uint32 x, uint32 y); 将 unsigned long 与 unsigned long 相乘;结果为 unsigned long long。
uint64 _ _MSP430_mpyull_hw(uint32 x, uint32 y); 将 unsigned long 与 unsigned long 相乘;结果为 unsigned long long。使用硬件 MPY16。
uint64 _ _MSP430_mpyull_hw32(uint32 x, uint32 y); 将 unsigned long 与 unsigned long 相乘;结果为 unsigned long long。使用硬件 MPY32(F4xx 器件)。
uint64 _ _MSP430_mpyull_f5hw(uint32 x, uint32 y); 将 unsigned long 与 unsigned long 相乘;结果为 unsigned long long。使用硬件 MPY32(F5xx 器件及更高版本)。
除法
int16 _ _MSP430_divi(int16 x, int16 y); int 除以 int。
int32 _ _MSP430_divli(int32 x, int32 y); long 除以 long。
int64 _ _MSP430_divlli(int64 x, int64 y); long long 除以 long long。
uint16 _ _MSP430_divu(uint16 x, uint16 y); unsigned lint 除以 unsigned lint。
uint32 _ _MSP430_divlu(uint32 x, uint32 y); unsigned long 除以 unsigned long。
uint64 _ _MSP430_divllu(uint64 x, uint64 y); unsigned long long 除以 unsigned long long。
余数(模数)
int16 _ _MSP430_remi(int16 x, int16 y); int 除以 int 的余数 (x mod y)
int32 _ _MSP430_remli(int32 x, int32 y); long 除以 long 的余数 (x mod y)
int64 _ _MSP430_remlli(int64x. int64 y); long long 除以 long long 的余数 (x mod y)
uint16 _ _MSP430_remu(uint16 x, uint16 y); unsigned int 除以 unsigned int 的余数 (x mod y)
uint32 _ _MSP430_remul(uint32, uint32); unsigned long 除以 unsigned long 的余数 (x mod y)
uint64 _ _MSP430_remull(uint64, uint64); unsigned long long 除以 unsigned long long 的余数 (x mod y)

表 6-5 列出了按位运算符函数。这些函数由 MSP430 和 MSP430X 使用。

循环左移运算不带进位执行。最高有效位被移至最低有效位 (LSB),所有其他位左移。对于 long long 数据类型,没有循环函数。

逻辑左移运算与算术左移相同;一个零被移入 LSB。

算术右移运算将最高有效位 (MSB) 向右移动并将旧 MSB 复制到新 MSB 中。这会将符号保留在有符号值中。LSB 被丢弃。

逻辑右移运算在 MSB 中插入值 0 并丢弃 LSB。

接受第二个实参的函数中的移位或循环计数不能小于零,即使按 signed int 处理它也不例外。

表 6-5 MSP430/MSP430X 按位运算
签名说明
旋转
uint16 _ _MSP430_rlli(uint16 x, int16 n);将 int 的位向左循环移动 n 位,其中 n 最多可以是 16。
uint16 _ _MSP430_rlli_1(uint16 x);
...
uint16 _ _MSP430_rlli_15(uint16 x);
将 int 的位向左循环移动指定的位数。
uint32 _ _MSP430_rlll(uint32 x, int16 n);将 long 的位向左循环移动 n 位,其中 n 最多可以是 32。
逻辑左移
uint16 _ _MSP430_slli(uint16 x, int16 n);对 int 执行逻辑左移。移动 n 位,其中 n 最多可以是 16。
uint16 _ _MSP430_slli_1(uint16 x);
...
uint16 _ _MSP430_slli_15(uint16 x);
对 int 执行逻辑左移。向左移位指定的位数。
uint32 _ _MSP430_slll(uint32 x, int16 n);对 long 执行逻辑左移。移动 n 位,其中 n 最多可以是 32。
uint32 _ _MSP430_slll_1(uint32 x);
...
uint32 _ _MSP430_slll_15(uint32 x);
对 long 执行逻辑左移。向左移位指定的位数。高于 15 的移位数使用 _ _MSP430_slll。
uint64 _ _MSP430_sllll(uint64 x, int16 n);对 long long 执行逻辑左移。移动 n 位,其中 n 最多可以是 64。
算术右移
int16 _ _MSP430_srai(int16 x, int16 n);对 int 执行算术右移。移动 n 位,其中 n 最多可以是 16。
int16 _ _MSP430_srai_1(int16 x);
...
int32 _ _MSP430_srai_15(int16 x);
对 int 执行算术右移。移动指定的位数。
int16 _ _MSP430_sral(int32 x, int16 n);对 long 执行算术右移。移动 n 位,其中 n 最多可以是 32。
int32 _ _MSP430_sral_1(int32 x);
...
int32 _ _MSP430_sral_15(int32 x);
对 long 执行算术右移。移动指定的位数。高于 15 的移位数使用 _ _MSP430_sral。
int64 _ _MSP430_srall(int64 x, int16 n);对 long long 执行算术右移。移动 n 位,其中 n 最多可以是 64。
逻辑右移
uint16 _ _MSP430_srli(uint16 x, int16 n);对 int 执行逻辑右移。移动 n 位,其中 n 最多可以是 16。
uint16 _ _MSP430_srli_1(uint16 x);
...
uint16 _ _MSP430_srli_15(uint16 x);
对 int 执行逻辑右移。向右移动指定的位数。
uint32 _ _MSP430_srll(uint32 x, int16 n);对 long 执行逻辑右移。移动 n 位,其中 n 最多可以是 32。
uint32 _ _MSP430_srll_1(uint32 x);
...
uint32 _ _MSP430_srll_15(uint32 x);
对 long 执行逻辑右移。向右移动指定的位数。高于 15 的移位数使用 _ _MSP430_srll。
uint64 _ _MSP430_srlll(uint64 x, int16 n);对 long long 执行逻辑右移。移动 n 位,其中 n 最多可以是 64。

表 6-6 中的辅助函数可优化恢复被调用者保存的寄存器。MSP430 使用这些函数,但 MSP430X 不使用这些函数。

表 6-6 MSP430 收尾程序辅助函数
签名说明
void _ _MSP430_epilog_1(void);弹出 R10 并返回。
void _ _MSP430_epilog_2(void);弹出 R10 到 R9 并返回。
void _ _MSP430_epilog_3(void);弹出 R10 到 R8 并返回。
void _ _MSP430_epilog_4(void);弹出 R10 到 R7 并返回。
void _ _MSP430_epilog_5(void);弹出 R10 到 R6 并返回。
void _ _MSP430_epilog_6(void);弹出 R10 到 R5 并返回。
void _ _MSP430_epilog_7(void);弹出 R10 到 R4 并返回。

下面的章节将介绍表 6-7 中的其他辅助函数。

表 6-7 MSP430 其他辅助函数
签名说明
void _abort_msg(const char *string);报告断言失败

_abort_msg

生成函数 _abort_msg 是为了在运行时断言(例如 C 断言宏)失败时输出诊断消息。该函数不得返回。也就是说,该函数必须调用中止或通过其他方式终止程序。