ZHCADC3B February   2019  – October 2023

 

  1.   1
  2. 简介
    1. 1.1  ABI - C28x
    2. 1.2  范围
    3. 1.3  ABI 变体
    4. 1.4  工具链和互操作性
    5. 1.5 
    6. 1.6  目标文件的类型
    7. 1.7 
    8. 1.8  C28x 架构概述
    9. 1.9  C28x 存储器模型
    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 传递 16 位实参的
      2. 3.3.2 传递更长实参的
      3. 3.3.3 C++ 实参传递
      4. 3.3.4 传递结构体和联合体
      5. 3.3.5 未在寄存器中传递的实参的栈布局
      6. 3.3.6 帧指针
    4. 3.4 返回值
    5. 3.5 通过引用传递并返回的结构体和联合体
    6. 3.6 编译器辅助函数的约定
    7. 3.7 逻辑程序和收尾程序辅助函数
    8. 3.8 已见函数的暂存寄存器
    9. 3.9 中断函数
  5. 数据分配和寻址
    1. 4.1 数据段和数据区段
    2. 4.2 数据分块
    3. 4.3 寻址模式
    4. 4.4 静态数据的分配和寻址
      1. 4.4.1 静态数据的寻址方法
      2. 4.4.2 静态数据的放置约定
        1. 4.4.2.1 寻址的抽象约定
      3. 4.4.3 静态数据的初始化
    5. 4.5 自动变量
    6. 4.6 帧布局
      1. 4.6.1 栈对齐
      2. 4.6.2 寄存器保存顺序
    7. 4.7 堆分配对象
  6. 代码分配和寻址
    1. 5.1 计算代码标签的地址
    2. 5.2 调用
      1. 5.2.1 直接 调用
      2. 5.2.2 Far Call Trampoline
      3. 5.2.3 间接调用
  7. 辅助函数 API
    1. 6.1 浮点行为
    2. 6.2 C 辅助函数 API
    3. 6.3 C99 的浮点辅助函数
  8. 标准 C 库 API
    1. 7.1  关于标准 C 库
    2. 7.2  保留符号
    3. 7.3  <assert.h> 实现
    4. 7.4  <complex.h> 实现
    5. 7.5  <ctype.h> 实现
    6. 7.6  <errno.h> 实现
    7. 7.7  <float.h> 实现
    8. 7.8  <inttypes.h> 实现
    9. 7.9  <iso646.h> 实现
    10. 7.10 <limits.h> 实现
    11. 7.11 <locale.h> 实现
    12. 7.12 <math.h> 实现
    13. 7.13 <setjmp.h> 实现
    14. 7.14 <signal.h> 实现
    15. 7.15 <stdarg.h> 实现
    16. 7.16 <stdbool.h> 实现
    17. 7.17 <stddef.h> 实现
    18. 7.18 <stdint.h> 实现
    19. 7.19 <stdio.h> 实现
    20. 7.20 <stdlib.h> 实现
    21. 7.21 <string.h> 实现
    22. 7.22 <tgmath.h> 实现
    23. 7.23 <time.h> 实现
    24. 7.24 <wchar.h> 实现
    25. 7.25 <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 C28x 指令的重定位
        5. 11.5.1.5 其他重定位类型
      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 关于构建属性
    2. 13.2 C28x ABI 构建属性子段
    3. 13.3 构建属性标签
  15. 14复制表和变量初始化
    1. 14.1 关于复制表
    2. 14.2 复制表格式
    3. 14.3 压缩的数据格式
      1. 14.3.1 RLE
      2. 14.3.2 LZSS 格式
    4. 14.4 变量初始化
  16. 15修订历史记录
    1.     188

关于复制表

“复制表”一词是指 TI 工具链中的一个通用功能,用于促进将数据从离线存储移动到在线存储。离线存储通常是指程序加载的位置;它可以是 ROM、较慢的存储器等等。在线存储通常是指程序运行时数据所在的位置。所复制的数据可以是代码,也可以是变量。复制表 一词是指一个源地址和目标地址表,其中注册了要复制的对象。另外还有一个库函数形式的运行时组件,用于读取该表并执行复制以响应程序中的调用。

复制表有许多应用程序,但最常见的两个是:

  • 初始化 — 在基于 ROM 的裸机系统中,必须在程序启动时将初始化的读写变量从 ROM 复制到 RAM。
  • 重叠 — 在程序运行时,不同的代码和数据组件会在存储器区域中交换进出。

复制表机制不是 ABI 的一部分。已初始化变量获取其初始值的方式是通过在链接器和运行时库之间进行约定,这些库需要来自相同的工具链。但是,其他工具链遵循 TI 机制可能会有优势,或者可能需要下游工具来识别格式,因此我们在这里记录下来。

下图展示了该通用机制。在示例中,目标文件包含一个已初始化的段 .mydata。在链接时,用户指定 .myData 具有单独的加载地址和运行地址,并指定为其创建一个复制表条目。链接器从 .mysect 中删除 数据,使其成为一个未初始化段,并分配其地址作为其运行位置。它会创建一个名为 .mydata.load1 的新初始化段,其中包含编码形式的 .mydata‟s 数据,并将其放置在加载位置。它从运行时库中名为 copy_in 的函数进行链接,以在运行时解码和复制数据,以及其他特定于格式的辅助函数。最后,它会创建一个包含复制表的段(示例中为 .ovly1),该复制表是一个指向源数据和目标地址的复制记录序列,以及一个处理程序表(未显示),复制函数使用该处理程序表来选择正确的解码辅助函数。

在运行时,应用程序调用 copy_in 来解压缩并复制数据。copy_in 的实参是与该段关联的复制表的地址。该函数解析该表并执行指定的复制操作。

可以对多个对象进行编码和注册以便复制。每个都会在 .ovly (1) 段中生成自己的复制表。

GUID-9741E49A-2B9E-4006-8A8F-6FEC6B0336F3-low.gif图 14-1 复制表概述

可能有一些变化:

  • 多个对象:多个段可以注册到单个复制表中。这样,与重叠关联的所有代码和数据都可以通过单个调用复制进来,而应用程序不必知道构成重叠的独立组件的数量。一个复制表可以包含多个复制记录。每个复制记录控制连续代码块或数据块的复制。
  • 无压缩:压缩是可选的。如果未启用压缩,则不需要该段的单独加载版本。链接器只需为已初始化的段分配单独的加载地址和运行地址。
  • 初始化:变量的初始化是该通用机制的一个特殊情况。用于初始化的复制记录格式略有不同,存储在名为 .cinit 的不同段中,并支持零初始化和复制。有关这些详细信息,请参阅节 14.4
  • 引导时间复制:名为 .binit 的特殊段包含在应用程序启动时自动调用的复制表。这与初始化情况类似,但初始化是语言实现的一部分,因此内置在工具链中,但引导时间复制严格上来说是一种应用程序级别的操作。
复制表段的段名称和压缩源数据由链接器任意选择。