ZHCUAQ1F july 2015 – april 2023
严格的惯例将特定寄存器与 C/C++ 环境中的特定运算相关联。如计划在 C/C++ 程序中使用汇编语言例程,则必须理解并遵循这些寄存器惯例。
寄存器惯例规定了编译器如何使用寄存器以及如何在函数调用之间保留值。表 8-2 总结了编译器如何使用 TMS320C6000 寄存器。
表 8-2 中的寄存器可供编译器分配寄存器变量和临时表达式结果之用。如果编译器无法分配所需类型的寄存器,则会发生溢出。溢出是将寄存器的内容移动到存储器以释放寄存器用于其他目的的过程。
双精度型、长整型、超长整型或长双精度型的对象被分配到奇数/偶数寄存器对中,并且始终作为寄存器对引用(例如,A1:A0)。奇数寄存器包含符号位、指数和尾数的最高有效部分。偶数寄存器包含尾数的最低有效部分。如果第一个参数是双精度型、长整型、超长整型或长双精度型,则 A4 寄存器与 A5 一起用于传递第一个参数。第二个参数的 B4 和 B5 也是如此,依此类推。有关参数传递寄存器和返回寄存器的更多信息,请参阅节 8.4。
寄存器 | 保留 函数 |
特殊用途 | 寄存器 | 保留 函数 |
特殊用途 |
---|---|---|---|---|---|
A0 | 父级 | – | B0 | 父级 | – |
A1 | 父级 | – | B1 | 父级 | – |
A2 | 父级 | – | B2 | 父级 | – |
A3 | 父级 | 结构寄存器 (指向返回结构的指针)(1) |
B3 | 父级 | 返回寄存器 (返回到的地址) |
A4 | 父级 | 参数 1 或返回值 | B4 | 父级 | 参数 2 |
A5 | 父级 | 参数 1 或返回值,双精度、长整型和超长整型值返回 A4 | B5 | 父级 | 参数 2,双精度、长整型和超长整型值返回 B4 |
A6 | 父级 | 参数 3 | B6 | 父级 | 参数 4 |
A7 | 父级 | 参数 3,双精度、长整型和超长整型值返回 A6 | B7 | 父级 | 参数 4,双精度、长整型和超长整型值返回 B6 |
A8 | 父级 | 参数 5 | B8 | 父级 | 参数 6 |
A9 | 父级 | 参数 5,双精度、长整型和超长整型值返回 A8 | B9 | 父级 | 参数 6,双精度、长整型和超长整型值返回 B8 |
A10 | 子级 | 参数 7 | B10 | 子级 | 参数 8 |
A11 | 子级 | 参数 7,双精度、长整型和超长整型值返回 A10 | B11 | 子级 | 参数 8,双精度、长整型和超长整型值返回 B10 |
A12 | 子级 | 参数 9 | B12 | 子级 | 参数 10 |
A13 | 子级 | 参数 9,双精度、长整型和超长整型值返回 A12 | B13 | 子级 | 参数 10,双精度、长整型和超长整型值返回 B12 |
A14 | 子级 | – | B14 | 子级 | 数据页指针 (DP) |
A15 | 子级 | 帧指针 (FP) | B15 | 子级 | 栈指针 (SP) |
A16-A31 | 父级 | B16-B31 | 父级 | ||
ILC | 子级 | 循环缓冲区计数器 | NRP | 父级 | |
IRP | 父级 | RILC | 子级 | 循环缓冲区计数器 |
编译器不会保存或恢复所有其他控制寄存器。
编译器假设,表 8-2 中未列出的控制寄存器会影响具有默认值的编译代码。例如,编译器假设,所有启用了循环寻址的寄存器均可用于线性寻址(AMR 用于启用循环寻址)。启用循环寻址然后调用 C/C++ 函数而不将 AMR 恢复为默认设置违反了调用惯例。确定的是,对编译器所生成代码有影响的控制寄存器,在使用汇编代码调用 C/C++ 函数时便具有默认值。
汇编语言程序员必须知道链接器假定 B15 包含栈指针。链接器需要在它生成的 trampoline 代码中保存和恢复栈上的值。如果在汇编代码中不使用 B15 作为栈指针,则应使用禁用 trampoline 的链接器选项 --trampolines=off 。否则,trampoline 可能会破坏内存并覆盖寄存器值。