一个函数(父级函数)在调用另一个函数(子级函数)时会执行以下任务。
C7000 有专门的指令和寄存器来管理调用和返回操作。CALL 指令将返回地址保存在返回指针 (RP) 寄存器中,并将控制权转移给被调用函数。RET 指令从 RP 恢复 PC,从而将控制权返回给被调用方。
C7000 CPU 具有流水线模型,可在受保护或不受保护状态下运行。当进行调用或返回时,CPU 必须处于受保护状态,而不是无保护状态。
一个函数(父级函数)在调用另一个函数(子级函数)时会执行以下任务:
- 传递给函数的参数被放置在寄存器或堆栈上。
- 如果将参数传递给函数,则将尽可能多的参数放入可用于参数传递的九个“标量”寄存器和十六个“矢量”寄存器中。
- 声明类型为 64 位或更小的参数被分配给标量寄存器 A4 到 A12。
- 声明在 64 位到 512 位之间的参数在矢量寄存器 VB0-VB15 中传递
- 声明为矢量谓词的参数在矢量谓词寄存器 P0-P7 中传递。
- 大于 512 位的参数通过引用传递。请参阅《C7000 嵌入式应用二进制接口 (EABI) 参考指南》(SPRUIG4) 中的“通过引用传递和返回的值”部分。
- 所有其余的参数都被放置在堆栈中递增的地址处,这样第一个参数在进入被调用方时将位于地址 SP+16 处。
- 每个具有标量或矢量类型的参数都放置在下一个与其类型正确对齐的可用地址处。
- 结构体与大于或等于其大小的下一个 2 的幂对齐,最多 8 个字节。
- 每个参数都保留一定数量的堆栈空间,其大小等于其四舍五入为其对齐的下一个倍数。
- 对于可变参数的 C 函数(用省略号声明,表明其是使用不同数量的参数调用的),最后一个显式声明的参数和所有剩余的参数都在堆栈上传递,以便其栈地址可以作为访问未声明参数的引用。
- 根据 C 语言,未在原型中声明且大小小于 int 大小的参数作为 int 传递。
- 调用函数必须保存寄存器 RP,如此调用函数不会被 CALL 指令覆盖。调用函数还必须保存未被调用函数保留的任何活跃的本地或全局寄存器(作为入口保存寄存器集的一部分)。入口保存寄存器组包括 A8-A15、B14/VB14 和 B15/VB15。
- 调用方(父级)会调用函数(子级)。
更多相关信息,请参阅《C7000 嵌入式应用二进制接口 (EABI) 参考指南》(SPRUIG4) 的“调用惯例”一章。