FPSCR 处理指令
表 8 列出了基本的 PowerPC FPSCR 处理指令集。
表 8. PowerPC FPSCR 处理指令集
助记符指令名mcrfsmove to CR from FPSCRmffs[.]move from FPSCRmtfsb0[.]move to FPSCR bit 0mtfsb1[.]move to FPSCR bit 1mtfsf[.]move to FPSCR fieldmtfsfi[.]move to FPSCR field immediate
加载和存储指令
所有加载和存储指令的执行都使用 GPR 或者 GPR 和指令中的立即字段作为存储器访问的地址说明符。用指令生成的数据有效地址来更新基址寄存器(也就是 RA)是大部分加载和存储指令的一个可选项。
有用于以下方面的指令:
- 字节、半字、字和双字大小。
- 在 GPR 或 FPR 与存储器之间移动数据。
- 在 GPR 或 FPR 与存储器之间移动数据。
特殊的存储器访问指令包括:
- 多字加载/存储
即 lmw 和 stmw ,可以操作最多 31 个 32 位字。 - 字符串指令
这些指令可以操作最长 128 字节的字符串。 - 内存同步指令
这些用于实现内存同步。CR 的第 2 位(EQ 位) 设置用来记录存储操作的成功完成。内存同步指令包括:- lwarx (加载字并预留变址)
- ldarx (加载双字并预留变址)
- stwcx (存储字条件变址)
- stdcx (存储双字条件变址)
lwarx / ldarx 执行加载并设置处理器内部的预留位,编程模型不必明确了解这些行为。如果设置了预留位,相应的存储指令 stwcx. / stdcx. 执行条件存储,并清除预留位。 栈
PowerPC 体系结构没有关于本地存储器的栈的概念。体系结构没有定义压入或者弹出指令,也没有定义专门的栈指针寄存器。不过,有一个软件标准可用于 C/C++ 程序,这个标准叫做嵌入式应用程序二进制接口( Embedded Application Binary Interface,EABI),它定义了栈寄存器和内存的约定。EABI 将 GPR1 预留为栈指针,GPR3 到 GPR7 用于函数参数传递,GPR3 用于函数返回值。
需要为 C/C++ 提供接口的汇编语言程序必须遵循同样的标准来保持约定。
高速缓存管理指令
PowerPC 体系结构包含了面向应用级高速缓存访问的高速缓存管理指令。高速缓存指令在表 9 中列出。
表 9. 高速缓存管理指令
助记符指令名dcbfFlush Data Cache LinedcbstStore Data Cache LinedcbtTouch Data Cache Line(for load)dcbtstTouch Data Cache Line(for store)dcbzZero Data Cache LineicbiInvalidate Instruction Cache Line
当将高速缓存处理代码移植到不同的 PowerPC 实现时要当心。虽然高速缓存指令可能是跨不同实现而通用的,高速缓存的组织和大小可能会有变化。例如,假定高速缓存大小以对其进行刷新的代码,在用于其他大小的高速缓存时可能需要进行修改。而且,各实现的高速缓存初始化可能不同。有一些实现提供了自动清除高速缓存标签的硬件,而其他实现需要使用软件循环来使高速缓存标签无效。
自修改代码
虽然编写自修改代码不是一个工业标准,但有些情况下它是必不可少的。下面的序列介绍了执行代码修改用到的指令:
- 存储修改的指令。
- 执行 dcbst 指令,强制包含有修改过的指令的高速缓存行进行存储。
- 执行 sync 指令,确保 dcbst 完成。
- 执行 icbi 指令,使将要存放修改后指令的指令高速缓存行无效。
- 执行 isync 指令,清除所有指令的指令管道,那些指令在高速缓存行被设为无效之前可能早已被取走了。
- 现在可以运行修改后的指令了。当取这个指令时会发生指令高速缓存失败,结果就会从存储器中取得修改后的指令。
计时器
大部分实现都提供了一个 64 位时基,可以通过两个 32 位寄存器读取,或者通过一个 64 位寄存器读取。各实现的计时器增量不同,SPR 数和访问时基的指令也不同。所以,跨实现移植计时器代码时要当心。另外的计时器可能也不同,但大多数实现都提供了至少一种递减的可编程计时器。
保持代码的兼容性
需要在多个实现上进行编程的 PowerPC 用户通常会问及保持代码兼容性的技巧。下面的建议将有助于尽量减少移植问题:
- 尽可能使用 C 代码。
当今的 C 编译器在很多情况下可以生成与直接手写的汇编代码在性能上相当的代码。作为 Book I 代码,C 代码将保证代码的兼容性。 - 尽可能避免使用处理器相关的汇编指令。
尽量不要在 C 中嵌入处理器相关的汇编指令,因为它们将更难被发现。分离开那些已知会包含设备相关寄存器或指令的代码。这些通常是启动次序和设备驱动程序,不过也可能包括浮点代码(包括 long long 类型)。保持假定和依赖全部归档。 - 使用处理器版本寄存器(PVR),但只在适当的时候用。
跨差别较小的实现的通用代码还好,PVR 可以用于做出判断。但是,在需要进行较大修改的情况下(例如,PowerPC AS 相对于 Book E MMU 代码),建议使用单独的代码库(code base)。 结束语
PowerPC AS 和 PowerPC 都支持最初的 PowerPC 体系结构中定义的应用级基础设施,同时为它们的具体目标市场提供了最佳的优化。
就其两种操作模式之一而言,PowerPC AS 实质上与最初的 PowerPC 相同,而 PowerPC Book E 在它的 Book III 级别的定义中,已经走向了不同的方向,为低价格、低功率以及体系结构灵活的嵌入式应用进行了最优化。当然,在 32 位的实现上还不能用双字整数指令,在大部分嵌入式实现中浮点指令也只是通过软件仿真提供支持。
不过,这对应用程序二进制在 PowerPC 体系结构家族树的分支中自由地迁移来说是一个非常有意义的机会。 |