从超级计算机到游戏控制台,从服务器到手机,随处可见 PowerPC 处理器的身影 -- 它们的体系结构全都相同。本篇对 PowerPC 应用级编程模型的介绍概述了指令集、重要的寄存器以及其他细节,这些细节对于开发可靠的、高性能的 PowerPC 应用程序和保持代码在不同处理器的兼容性来说是必须要了解的。
对 PowerPC 体系结构家族树的所有分支来说,PowerPC 体系结构和应用级编程模型是通用的。要获得详细的资料,请参阅 IBM? PowerPC Web 站点技术库中的产品用户手册(参阅 参考资料以获取链接)。
PowerPC 体系结构是一种精减指令集计算机(Reduced Instruction Set Computer,RISC)体系结构,定义了 200 多条指令。PowerPC 之所以是 RISC,原因在于大部分指令在一个单一的周期内执行,而且通常只执行一个单一的操作(比如将内存加载到寄存器,或者将寄存器数据存储到内存)。
PowerPC 体系结构分为三个级别(或者说是“book”)。通过对体系结构以这种方式进行划分,为实现可以选择价格/性能比平衡的复杂性级别留出了空间,同时还保持了实现间的代码兼容性。
从最初的 PowerPC 体系结构的开发开始,就根据特定的市场需求而发生分支。当前,PowerPC 体系结构家族树有两个活跃的分支,分别是 PowerPC AS体系结构和 PowerPC Book E体系结构。PowerPC AS 体系结构是 IBM 为了满足它的 eServer pSeries UNIX 和 Linux 服务器产品家族及它的 eServer iSeries 企业服务器产品家族的具体需要而定义的(参阅 参考资料中的链接以获得更多资料)。PowerPC Book E 体系结构,也被称为 Book E,是 IBM 和 Motorola 为满足嵌入式市场的特定需求而合作推出的。PowerPC AS 所采用的原始 PowerPC 体系结构与 Book E 所采用的扩展之间的主要区别大部分集中于 Book III 区域中。
在这些衍生的体系结构中还有一些适当的应用级扩展,这些扩展大部分与具体应用的场合相关,但是 PowerPC AS 和 PowerPC Book E 共享在 PowerPC 体系结构的 Book I 中定义的基本指令集。虽然三种体系结构主要在操作系统级别上表现出不同,但它们在很大程度上具备应用级的兼容性。
PowerPC 最初定义了同时对 32 位和 64 位实现的支持,可以让 32 位的应用程序运行于 64 位系统之上。在 IBM pSeries 和 iSeries 服务器上使用的 PowerPC AS 系统现在只提供体系结构的 64 位实现,新的 64 位应用程序和遗留的 32 位的应用程序可以运行于同一个系统之上。PowerPC Book E 体系结构同时有 32 位实现和 64 位实现,64 位实现也完全兼容 32 位 PowerPC 应用程序。这两种体系结构都具备与 PowerPC Book I 指令和寄存器的完全兼容性,同时提供了对内存管理、异常和中断、计时器支持和调试支持等各方面的系统级扩展。
![]() |
|
最初的 PowerPC 体系结构仍是 PowerPC AS 和 PowerPC Book E 的主要组成部分,并仍保持了其完整性,表现出了令人信服的应用级兼容性。
当用到不只一种类型的 PowerPC 处理器时,开发人员应时刻谨记处理器处理内存的方式存在一些差异。
PowerPC 体系结构本身支持字节(8 位)、半字(16 位)、字(32 位) 和双字(64 位) 数据类型。PowerPC 实现还可以处理最长 128 字节的多字节字符串操作。32 位 PowerPC 实现支持 4-gigabyte 的有效地址空间,而 64 位 PowerPC 实现支持 16-exabyte 的有效地址空间。所有存储都可以字节寻址。
对于错位数据访问来说,不同的产品家族提供了不同的校准支持,有一些是以处理异常的方式,其他的是通过硬件中的一步或者多步操作来处理访问。
最高位字节在最前(Big-endian)还是最低位字节在最前(little-endian)?
PowerPC、PowerPC AS 以及早期的 IBM PowerPC 4xx 家族大部分是字节排列顺序最高位在最前的机器,这就意味着对半字、字以及双字访问来说,最重要的字节(most-significant byte,MSB)位于最低的地址。各实现对最低位在最前的字节排列顺序方式的支持不同。PowerPC 和 PowerPC AS 提供了最小限度的支持,而 4xx 家族为最低位字节在最前的存储提供了更为健壮的支持。Book E 是字节排列顺序无关的,因为 Book E 体系结构完全支持这两种访问方法。
![]() ![]() |
![]()
|
PowerPC 的应用级寄存器分为三类:通用寄存器(general-purpose register,GPR)、浮点寄存器(floating-point register [FPR] 和浮点状态和控制寄存器 [Floating-Point Status and Control Register,FPSCR])和专用寄存器(special-purpose register,SPR)。让我们来分别看一下这三类寄存器。
用户指令集体系结构(Book I)规定,所有实现都有 32 个 GPR(从GPR0 到 GPR31)。GPR 是所有整数操作的源和目的,也是所有加载/存储操作的地址操作数的源。GPR 还提供对 SPR 的访问。所有 GRP 都是可用的,只有一种情况例外:在某些指令中,GPR0 只是代表数值 0,而不会去查找 GPR0 的内容。
Book I 规定,所有实现都有 32 个 FPR(从 FPR0 到 FPR31)。FPR 是所有浮点操作的源和目的操作数,可以存放 32 位和 64 位的有符号和无符号整数,以及单精度和双精度浮点数。FPR 还提供对 FPSCR 的访问。
注意,嵌入式微处理器实现时经常不提供对浮点指令集的直接硬件支持,或者只是提供一个附加浮点硬件的接口。很多嵌入式应用程序很少或者根本不需要浮点算法,而当需要的时候,对 PowerPC 浮点指令执行进行软件仿真就足够了。在嵌入式微处理器中,硬件中省去浮点(支持)而为实现带来的芯片面积和功率的减少是至关重要的。
浮点状态和控制寄存器(FPSCR)捕获浮点操作的状态和异常结果,FPSCR 还具有控制位,以支持特定的异常类型和对四种舍入模式之一的选择。对 FPSCR 的访问要通过 FPR。
SPR 给出处理器核心内部资源的状态并对其进行控制。不需要系统服务的支持就可以由应用程序读写的 SPR 包括计数寄存器(Count Register)、链接寄存器(Link Register)和整型异常寄存器(Integer Exception Register)。需要系统服务的支持才可以由应用程序读写的 SPR 包括时基(Time Base)和其他各种可能支持的计时器。
bclr
转移到 LR 中的值。 lswx
和 stswx
)中传输的字节数。 bcctr
转移到 CTR 中的值。 stwcx
或者 stdcx
) 的结果。还有一组指令可以操纵特定的 CR 位、特定的 CR 字段或者整个 CR,通常为了测试而将几个条件组合到同一个位中。 ![]() ![]() |
![]()
|
表 1 列出了不同的指令类别以及每类的指令类型。
表 1. 指令类别
指令类别 | 基本指令 |
Branch | branch, branch conditional, branch to LR, branch to CTR |
Condition register | crand, crnor, creqv, crxor, crandc, crorc, crnand, cror, CR move |
Storage access | load GPR/FPR, store GPR/FPR |
Integer arithmetic | add, subtract, negate, multiply, divide |
Integer comparison | compare algebraic, compare algebraic immediate, compare logical,compare logical immediate |
Integer logical | and, andc, nand, or, orc, nor, xor, eqv, sign extension, countleading zeros |
Integer rotate/shift | rotate, rotate and mask, shift left, shift right |
Floating-point arithmetic | add, subtract, negate, multiply, divide, square root, multiply-add,multiply-subtract, negative multiply-add, negative multiply-subtract |
Floating-point comparison | compare ordered, compare unordered |
Floating-point conversion | round to single, convert from/to integer word/doubleword |
FPSCR management | move to/from FPSCR, set/clear FPSCR bit, copy FPSCR field to CR |
Cache control | touch, zero, flush, store |
Processor management | system call, move to/from special purpose registers, mtcrf, mfcr |
所有指令的编码长度都是 32 位。PowerPC 的位编号方式与大部分其他定义相反:第 0 位是最重要的位,第 31 位是最不重要的位。指令首先由一个字段中较高的 6 位进行解码,这 6 位称为 主要操作码(primary opcode)。其余 26 位包含的字段分别是操作数说明、立即(immediate)操作数以及扩展的操作码(opcode),而且这些还可能是保留的位或字段。表 2 列出了 PowerPC 定义的基本指令格式。
表 2. PowerPC 指令格式
格式 | 0 | 6 | 11 | 16 | 21 | 26 | 30 | 31 |
D-form | opcd | tgt/src | src/tgt | immediate | ||||
X-form | opcd | tgt/src | src/tgt | src | extended opcd | |||
A-form | opcd | tgt/src | src/tgt | src | src | extended opcd | Rc | |
BD-form | opcd | BO | BI | BD | AA | LK | ||
I-form | opcd | LI | AA | LK |
如前所述,这些指令格式各有其变种。不过,这些格式是对大部分 PowerPC 指令集编码结构的最好描述。
PowerPC 为控制流程提供了一组指令,包括:
所有的转移指令都具备保存后继顺序指令地址的能力,包括到链接寄存器的转移。条件寄存器 32 位中的任意一位都可以指定为条件转移的条件,并可以指定 CR 位是否必须为 0 或 1 时转移条件才成立。
PowerPC 提供了一组用于对 CR 的特定位执行布尔操作和对 CR 字段进行拷贝的指令。它允许组合多个转移条件,这样可以减少代价高昂的条件转移的数量。表 3 列出了 PowerPC CR 逻辑指令。
表 3. PowerPC CR 逻辑指令
助记符 | 指令名 |
crand | CR logical and |
crandc | CR logical and with complement |
creqv | CR logical equivalent |
crnand | CR logical not and |
crnor | CR logical not or |
cror | CR logical or |
crorc | CR logical or with complement |
crxor | CR logical xor |
很多指令用于执行运算操作,包括 add、substract、negate、compare、multiply 和 divide。很多格式用于立即值、溢出检测以及进位和借位。各实现中 multiply 和 divide 的执行是不同的,因为这些通常是多周期指令。表 4 列出了 PowerPC 整数运算指令。
表 4. PowerPC 整数运算指令
助记符 | 指令名 |
add[o][.] | add [& record OV] [& record CR0] |
addc[o][.] | add carrying [& record OV] [& record CR0] |
adde[o][.] | add extended [& record OV] [& record CR0] |
addi | add immediate |
addis | add immediate shifted |
addic[.] | add immediate carrying [& record CR0] |
addme[o][.] | add to minus one [& record OV] [& record CR0] |
addze[o][.] | add to zero [& record OV] [& record CR0] |
divd[o][.] | divide doubleword [& record OV] [& record CR0] |
divdu[o][.] | divide doubleword unsigned [& record OV] [& record CR0] |
divw[o][.] | divide word [& record OV] [& record CR0] |
divwu[o][.] | divide word unsigned [& record OV] [& record CR0] |
mulhd[.] | multiply high doubleword [& record CR0] |
mulhdu[.] | multiply high doubleword unsigned [& record CR0] |
mulhw[.] | multiply high word [& record CR0] |
mulhwu[.] | multiply high word unsigned [& record CR0] |
mulld[o][.] | multiply low doubleword [& record OV] [& record CR0] |
mulli | multiply low immediate |
mullw[o][.] | multiply low word [& record OV] [& record CR0] |
neg[o][.] | negate [& record OV] [& record CR0] |
subf[o][.] | subtract from [& record OV] [& record CR0] |
subfc[o][.] | subtract from carrying [& record OV] [& record CR0] |
subfe[o][.] | subtract from extended [& record OV] [& record CR0] |
subfi | subtract from immediate |
subfis | subtract from immediate shifted |
subfic[.] | subtract from immediate carrying [& record CR0] |
subfme[o][.] | subtract from to minus one [& record OV] [& record CR0] |
subfze[o][.] | subtract from to zero [& record OV] [& record CR0] |
PowerPC 提供了一组完整的逻辑操作(指令),还支持对符号的扩展以及对 GPR 中前置零的统计。表 5 列出了 PowerPC 逻辑指令。
表 5. PowerPC 逻辑指令
助记符 | 指令名 |
and[.] | and [& record CR0] |
andc[.] | and with complement [& record CR0] |
andi. | and immediate & record CR0 |
andis. | and immediate shifted & record CR0 |
eqv[.] | equivalent [& record CR0] |
nand[.] | not and [& record CR0] |
nor[.] | not or [& record CR0] |
or[.] | or [& record CR0] |
orc[.] | or with complement [& record CR0] |
oris | or immediate shifted |
ori | or immediate |
xor[.] | xor [& record CR0] |
xoris | xor immediate shifted |
xori | xor immediate |
cntlzd[.] | count leading zeros doubleword [& record CR0] |
cntlzw[.] | count leading zeros word [& record CR0] |
extsb[.] | extend sign byte [& record CR0] |
extsh[.] | extend sign halfword [& record CR0] |
extsw[.] | extend sign word [& record CR0] |
PowerPC 提供了一组健壮而强大的循环和移位操作(指令),如表 6 所列。
表 6. PowerPC 循环和移位指令
助记符 | 指令名 |
rldc[.] | rotate left doubleword then clear [& record CR0] |
rldcl[.] | rotate left doubleword then clear left [& record CR0] |
rldcr[.] | rotate left doubleword then clear right [& record CR0] |
rldicl[.] | rotate left doubleword immediate then clear left [& record CR0] |
rldicr[.] | rotate left doubleword immediate then clear right [& record CR0] |
rldimi[.] | rotate left doubleword immediate then mask insert [& record CR0] |
rlwimi[.] | rotate left word immediate then mask insert [& record CR0] |
rlwinm[.] | rotate left word immediate then and with mask [& record CR0] |
rlwnm[.] | rotate left word then and with mask [& record CR0] |
sld[.] | shift left doubleword [& record CR0] |
slw[.] | shift left word [& record CR0] |
srad[.] | shift right doubleword [& record CR0] |
sradi[.] | shift right doubleword immediate [& record CR0] |
sraw[.] | shift right word [& record CR0] |
srawi[.] | shift right word immediate [& record CR0] |
srd[.] | shift right doubleword [& record CR0] |
srw[.] | shift right word [& record CR0] |
PowerPC 提供了一组健壮的浮点运算、比较和转换操作(指令)。与软件支持一道,PowerPC 浮点运算完全符合 ANSI/IEEE 标准 754-1985 规范。在所有运算和比较操作中都支持单精度和双精度浮点格式。
虽然浮点数以双精度格式存储于 FPR 中,但是,有一组单精度运算指令,可以执行运算操作并将最终结果舍入为单精度,同时检测进行单精度操作时可能会发生的异常(比如指数溢出、下溢和失去精度)。
可以启用或禁用具体种类的浮点异常来支持设陷(trapping) 环境。表 7 列出了基本的和可选的 PowerPC 浮点指令集。
表 7. PowerPC 浮点指令
助记符 | 指令名 |
fmr[.] | FP move [& record CR1] |
fneg[.] | FP negate [& record CR1] |
fabs[.] | FP absolute value [& record CR1] |
fnabs[.] | FP negative absolute value [& record CR1] |
fadd | FP add [single] [& record CR1] |
fsub | FP subtract [single] [& record CR1] |
fmul | FP multiply [single] [& record CR1] |
fdiv | FP divide [single] [& record CR1] |
fsqrt | FP square root [single] [& record CR1] |
fmadd | FP multiply-add [single] [& record CR1] |
fmsub | FP multiply-subtract [single] [& record CR1] |
fnmadd | FP negative multiply-add [single] [& record CR1] |
fnmsub | FP negative multiply-subtract [single] [& record CR1] |
fcmpo | FP compare ordered |
fcmpu | FP compare unordered |
fsel[.] | FP select [& record CR1] |
frsp[.] | FP round to single [& record CR1] |
fcfid[.] | FP convert from integer doubleword [& record CR1] |
fctid[z][.] | FP convert to integer doubleword [& round to zero] [& record CR1] |
fctiw[z][.] | FP convert to integer word [& round to zero] [& record CR1] |
fres[.] | FP reciprocal estimate single [& record CR1] |
frsqrte[.] | FP reciprocal square root estimate [& record CR1] |
表 8 列出了基本的 PowerPC FPSCR 处理指令集。
表 8. PowerPC FPSCR 处理指令集
助记符 | 指令名 |
mcrfs | move to CR from FPSCR |
mffs[.] | move from FPSCR |
mtfsb0[.] | move to FPSCR bit 0 |
mtfsb1[.] | move to FPSCR bit 1 |
mtfsf[.] | move to FPSCR field |
mtfsfi[.] | move to FPSCR field immediate |
所有加载和存储指令的执行都使用 GPR 或者 GPR 和指令中的立即字段作为存储器访问的地址说明符。用指令生成的数据有效地址来更新基址寄存器(也就是 RA)是大部分加载和存储指令的一个可选项。
有用于以下方面的指令:
特殊的存储器访问指令包括:
lmw
和 stmw
,可以操作最多 31 个 32 位字。 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. 高速缓存管理指令
助记符 | 指令名 |
dcbf | Flush Data Cache Line |
dcbst | Store Data Cache Line |
dcbt | Touch Data Cache Line(for load) |
dcbtst | Touch Data Cache Line(for store) |
dcbz | Zero Data Cache Line |
icbi | Invalidate Instruction Cache Line |
当将高速缓存处理代码移植到不同的 PowerPC 实现时要当心。虽然高速缓存指令可能是跨不同实现而通用的,高速缓存的组织和大小可能会有变化。例如,假定高速缓存大小以对其进行刷新的代码,在用于其他大小的高速缓存时可能需要进行修改。而且,各实现的高速缓存初始化可能不同。有一些实现提供了自动清除高速缓存标签的硬件,而其他实现需要使用软件循环来使高速缓存标签无效。
虽然编写自修改代码不是一个工业标准,但有些情况下它是必不可少的。下面的序列介绍了执行代码修改用到的指令:
dcbst
指令,强制包含有修改过的指令的高速缓存行进行存储。 sync
指令,确保 dcbst
完成。 icbi
指令,使将要存放修改后指令的指令高速缓存行无效。 isync
指令,清除所有指令的指令管道,那些指令在高速缓存行被设为无效之前可能早已被取走了。 ![]() ![]() |
![]()
|
大部分实现都提供了一个 64 位时基,可以通过两个 32 位寄存器读取,或者通过一个 64 位寄存器读取。各实现的计时器增量不同,SPR 数和访问时基的指令也不同。所以,跨实现移植计时器代码时要当心。另外的计时器可能也不同,但大多数实现都提供了至少一种递减的可编程计时器。
![]() ![]() |
![]()
|
需要在多个实现上进行编程的 PowerPC 用户通常会问及保持代码兼容性的技巧。下面的建议将有助于尽量减少移植问题:
![]() ![]() |
![]()
|
PowerPC AS 和 PowerPC 都支持最初的 PowerPC 体系结构中定义的应用级基础设施,同时为它们的具体目标市场提供了最佳的优化。
就其两种操作模式之一而言,PowerPC AS 实质上与最初的 PowerPC 相同,而 PowerPC Book E 在它的 Book III 级别的定义中,已经走向了不同的方向,为低价格、低功率以及体系结构灵活的嵌入式应用进行了最优化。当然,在 32 位的实现上还不能用双字整数指令,在大部分嵌入式实现中浮点指令也只是通过软件仿真提供支持。
不过,这对应用程序二进制在 PowerPC 体系结构家族树的分支中自由地迁移来说是一个非常有意义的机会。
![]() | ||
![]() | Brett Olsson 致力于 PowerPC Book E 体系结构团队的 VMX 体系结构方面的工作。可以通过 brett@us.ibm.com 与 Brett 联系。 |
![]() | ||
![]() | Anthony Marsala 有很多头衔:演员、软件工程师、作家、丈夫,最近又增加了一个头衔 —— 父亲。他从 1993 年起加入了 IBM 嵌入式 PowerPC 团队的工作,在那里他帮助创建了用于下一代 PowerPC 处理器的软件工具。可以通过 marsala@us.ibm.com 与 Anthony 联系。 |
从超级计算机到游戏控制台,从服务器到手机,随处可见 PowerPC 处理器的身影 -- 它们的体系结构全都相同。本篇对 PowerPC 应用级编程模型的介绍概述了指令集、重要的寄存器以及其他细节,这些细节对于开发可靠的、高性能的 PowerPC 应用程序和保持代码在不同处理器的兼容性来说是必须要了解的。
对 PowerPC 体系结构家族树的所有分支来说,PowerPC 体系结构和应用级编程模型是通用的。要获得详细的资料,请参阅 IBM? PowerPC Web 站点技术库中的产品用户手册(参阅 参考资料以获取链接)。
PowerPC 体系结构是一种精减指令集计算机(Reduced Instruction Set Computer,RISC)体系结构,定义了 200 多条指令。PowerPC 之所以是 RISC,原因在于大部分指令在一个单一的周期内执行,而且通常只执行一个单一的操作(比如将内存加载到寄存器,或者将寄存器数据存储到内存)。
PowerPC 体系结构分为三个级别(或者说是“book”)。通过对体系结构以这种方式进行划分,为实现可以选择价格/性能比平衡的复杂性级别留出了空间,同时还保持了实现间的代码兼容性。
从最初的 PowerPC 体系结构的开发开始,就根据特定的市场需求而发生分支。当前,PowerPC 体系结构家族树有两个活跃的分支,分别是 PowerPC AS体系结构和 PowerPC Book E体系结构。PowerPC AS 体系结构是 IBM 为了满足它的 eServer pSeries UNIX 和 Linux 服务器产品家族及它的 eServer iSeries 企业服务器产品家族的具体需要而定义的(参阅 参考资料中的链接以获得更多资料)。PowerPC Book E 体系结构,也被称为 Book E,是 IBM 和 Motorola 为满足嵌入式市场的特定需求而合作推出的。PowerPC AS 所采用的原始 PowerPC 体系结构与 Book E 所采用的扩展之间的主要区别大部分集中于 Book III 区域中。
在这些衍生的体系结构中还有一些适当的应用级扩展,这些扩展大部分与具体应用的场合相关,但是 PowerPC AS 和 PowerPC Book E 共享在 PowerPC 体系结构的 Book I 中定义的基本指令集。虽然三种体系结构主要在操作系统级别上表现出不同,但它们在很大程度上具备应用级的兼容性。
PowerPC 最初定义了同时对 32 位和 64 位实现的支持,可以让 32 位的应用程序运行于 64 位系统之上。在 IBM pSeries 和 iSeries 服务器上使用的 PowerPC AS 系统现在只提供体系结构的 64 位实现,新的 64 位应用程序和遗留的 32 位的应用程序可以运行于同一个系统之上。PowerPC Book E 体系结构同时有 32 位实现和 64 位实现,64 位实现也完全兼容 32 位 PowerPC 应用程序。这两种体系结构都具备与 PowerPC Book I 指令和寄存器的完全兼容性,同时提供了对内存管理、异常和中断、计时器支持和调试支持等各方面的系统级扩展。
![]() |
|
最初的 PowerPC 体系结构仍是 PowerPC AS 和 PowerPC Book E 的主要组成部分,并仍保持了其完整性,表现出了令人信服的应用级兼容性。
当用到不只一种类型的 PowerPC 处理器时,开发人员应时刻谨记处理器处理内存的方式存在一些差异。
PowerPC 体系结构本身支持字节(8 位)、半字(16 位)、字(32 位) 和双字(64 位) 数据类型。PowerPC 实现还可以处理最长 128 字节的多字节字符串操作。32 位 PowerPC 实现支持 4-gigabyte 的有效地址空间,而 64 位 PowerPC 实现支持 16-exabyte 的有效地址空间。所有存储都可以字节寻址。
对于错位数据访问来说,不同的产品家族提供了不同的校准支持,有一些是以处理异常的方式,其他的是通过硬件中的一步或者多步操作来处理访问。
最高位字节在最前(Big-endian)还是最低位字节在最前(little-endian)?
PowerPC、PowerPC AS 以及早期的 IBM PowerPC 4xx 家族大部分是字节排列顺序最高位在最前的机器,这就意味着对半字、字以及双字访问来说,最重要的字节(most-significant byte,MSB)位于最低的地址。各实现对最低位在最前的字节排列顺序方式的支持不同。PowerPC 和 PowerPC AS 提供了最小限度的支持,而 4xx 家族为最低位字节在最前的存储提供了更为健壮的支持。Book E 是字节排列顺序无关的,因为 Book E 体系结构完全支持这两种访问方法。
![]() ![]() |
![]()
|
PowerPC 的应用级寄存器分为三类:通用寄存器(general-purpose register,GPR)、浮点寄存器(floating-point register [FPR] 和浮点状态和控制寄存器 [Floating-Point Status and Control Register,FPSCR])和专用寄存器(special-purpose register,SPR)。让我们来分别看一下这三类寄存器。
用户指令集体系结构(Book I)规定,所有实现都有 32 个 GPR(从GPR0 到 GPR31)。GPR 是所有整数操作的源和目的,也是所有加载/存储操作的地址操作数的源。GPR 还提供对 SPR 的访问。所有 GRP 都是可用的,只有一种情况例外:在某些指令中,GPR0 只是代表数值 0,而不会去查找 GPR0 的内容。
Book I 规定,所有实现都有 32 个 FPR(从 FPR0 到 FPR31)。FPR 是所有浮点操作的源和目的操作数,可以存放 32 位和 64 位的有符号和无符号整数,以及单精度和双精度浮点数。FPR 还提供对 FPSCR 的访问。
注意,嵌入式微处理器实现时经常不提供对浮点指令集的直接硬件支持,或者只是提供一个附加浮点硬件的接口。很多嵌入式应用程序很少或者根本不需要浮点算法,而当需要的时候,对 PowerPC 浮点指令执行进行软件仿真就足够了。在嵌入式微处理器中,硬件中省去浮点(支持)而为实现带来的芯片面积和功率的减少是至关重要的。
浮点状态和控制寄存器(FPSCR)捕获浮点操作的状态和异常结果,FPSCR 还具有控制位,以支持特定的异常类型和对四种舍入模式之一的选择。对 FPSCR 的访问要通过 FPR。
SPR 给出处理器核心内部资源的状态并对其进行控制。不需要系统服务的支持就可以由应用程序读写的 SPR 包括计数寄存器(Count Register)、链接寄存器(Link Register)和整型异常寄存器(Integer Exception Register)。需要系统服务的支持才可以由应用程序读写的 SPR 包括时基(Time Base)和其他各种可能支持的计时器。
bclr
转移到 LR 中的值。 lswx
和 stswx
)中传输的字节数。 bcctr
转移到 CTR 中的值。 stwcx
或者 stdcx
) 的结果。还有一组指令可以操纵特定的 CR 位、特定的 CR 字段或者整个 CR,通常为了测试而将几个条件组合到同一个位中。 ![]() ![]() |
![]()
|
表 1 列出了不同的指令类别以及每类的指令类型。
表 1. 指令类别
指令类别 | 基本指令 |
Branch | branch, branch conditional, branch to LR, branch to CTR |
Condition register | crand, crnor, creqv, crxor, crandc, crorc, crnand, cror, CR move |
Storage access | load GPR/FPR, store GPR/FPR |
Integer arithmetic | add, subtract, negate, multiply, divide |
Integer comparison | compare algebraic, compare algebraic immediate, compare logical,compare logical immediate |
Integer logical | and, andc, nand, or, orc, nor, xor, eqv, sign extension, countleading zeros |
Integer rotate/shift | rotate, rotate and mask, shift left, shift right |
Floating-point arithmetic | add, subtract, negate, multiply, divide, square root, multiply-add,multiply-subtract, negative multiply-add, negative multiply-subtract |
Floating-point comparison | compare ordered, compare unordered |
Floating-point conversion | round to single, convert from/to integer word/doubleword |
FPSCR management | move to/from FPSCR, set/clear FPSCR bit, copy FPSCR field to CR |
Cache control | touch, zero, flush, store |
Processor management | system call, move to/from special purpose registers, mtcrf, mfcr |
所有指令的编码长度都是 32 位。PowerPC 的位编号方式与大部分其他定义相反:第 0 位是最重要的位,第 31 位是最不重要的位。指令首先由一个字段中较高的 6 位进行解码,这 6 位称为 主要操作码(primary opcode)。其余 26 位包含的字段分别是操作数说明、立即(immediate)操作数以及扩展的操作码(opcode),而且这些还可能是保留的位或字段。表 2 列出了 PowerPC 定义的基本指令格式。
表 2. PowerPC 指令格式
格式 | 0 | 6 | 11 | 16 | 21 | 26 | 30 | 31 |
D-form | opcd | tgt/src | src/tgt | immediate | ||||
X-form | opcd | tgt/src | src/tgt | src | extended opcd | |||
A-form | opcd | tgt/src | src/tgt | src | src | extended opcd | Rc | |
BD-form | opcd | BO | BI | BD | AA | LK | ||
I-form | opcd | LI | AA | LK |
如前所述,这些指令格式各有其变种。不过,这些格式是对大部分 PowerPC 指令集编码结构的最好描述。
PowerPC 为控制流程提供了一组指令,包括:
所有的转移指令都具备保存后继顺序指令地址的能力,包括到链接寄存器的转移。条件寄存器 32 位中的任意一位都可以指定为条件转移的条件,并可以指定 CR 位是否必须为 0 或 1 时转移条件才成立。
PowerPC 提供了一组用于对 CR 的特定位执行布尔操作和对 CR 字段进行拷贝的指令。它允许组合多个转移条件,这样可以减少代价高昂的条件转移的数量。表 3 列出了 PowerPC CR 逻辑指令。
表 3. PowerPC CR 逻辑指令
助记符 | 指令名 |
crand | CR logical and |
crandc | CR logical and with complement |
creqv | CR logical equivalent |
crnand | CR logical not and |
crnor | CR logical not or |
cror | CR logical or |
crorc | CR logical or with complement |
crxor | CR logical xor |
很多指令用于执行运算操作,包括 add、substract、negate、compare、multiply 和 divide。很多格式用于立即值、溢出检测以及进位和借位。各实现中 multiply 和 divide 的执行是不同的,因为这些通常是多周期指令。表 4 列出了 PowerPC 整数运算指令。
表 4. PowerPC 整数运算指令
助记符 | 指令名 |
add[o][.] | add [& record OV] [& record CR0] |
addc[o][.] | add carrying [& record OV] [& record CR0] |
adde[o][.] | add extended [& record OV] [& record CR0] |
addi | add immediate |
addis | add immediate shifted |
addic[.] | add immediate carrying [& record CR0] |
addme[o][.] | add to minus one [& record OV] [& record CR0] |
addze[o][.] | add to zero [& record OV] [& record CR0] |
divd[o][.] | divide doubleword [& record OV] [& record CR0] |
divdu[o][.] | divide doubleword unsigned [& record OV] [& record CR0] |
divw[o][.] | divide word [& record OV] [& record CR0] |
divwu[o][.] | divide word unsigned [& record OV] [& record CR0] |
mulhd[.] | multiply high doubleword [& record CR0] |
mulhdu[.] | multiply high doubleword unsigned [& record CR0] |
mulhw[.] | multiply high word [& record CR0] |
mulhwu[.] | multiply high word unsigned [& record CR0] |
mulld[o][.] | multiply low doubleword [& record OV] [& record CR0] |
mulli | multiply low immediate |
mullw[o][.] | multiply low word [& record OV] [& record CR0] |
neg[o][.] | negate [& record OV] [& record CR0] |
subf[o][.] | subtract from [& record OV] [& record CR0] |
subfc[o][.] | subtract from carrying [& record OV] [& record CR0] |
subfe[o][.] | subtract from extended [& record OV] [& record CR0] |
subfi | subtract from immediate |
subfis | subtract from immediate shifted |
subfic[.] | subtract from immediate carrying [& record CR0] |
subfme[o][.] | subtract from to minus one [& record OV] [& record CR0] |
subfze[o][.] | subtract from to zero [& record OV] [& record CR0] |
PowerPC 提供了一组完整的逻辑操作(指令),还支持对符号的扩展以及对 GPR 中前置零的统计。表 5 列出了 PowerPC 逻辑指令。
表 5. PowerPC 逻辑指令
助记符 | 指令名 |
and[.] | and [& record CR0] |
andc[.] | and with complement [& record CR0] |
andi. | and immediate & record CR0 |
andis. | and immediate shifted & record CR0 |
eqv[.] | equivalent [& record CR0] |
nand[.] | not and [& record CR0] |
nor[.] | not or [& record CR0] |
or[.] | or [& record CR0] |
orc[.] | or with complement [& record CR0] |
oris | or immediate shifted |
ori | or immediate |
xor[.] | xor [& record CR0] |
xoris | xor immediate shifted |
xori | xor immediate |
cntlzd[.] | count leading zeros doubleword [& record CR0] |
cntlzw[.] | count leading zeros word [& record CR0] |
extsb[.] | extend sign byte [& record CR0] |
extsh[.] | extend sign halfword [& record CR0] |
extsw[.] | extend sign word [& record CR0] |
PowerPC 提供了一组健壮而强大的循环和移位操作(指令),如表 6 所列。
表 6. PowerPC 循环和移位指令
助记符 | 指令名 |
rldc[.] | rotate left doubleword then clear [& record CR0] |
rldcl[.] | rotate left doubleword then clear left [& record CR0] |
rldcr[.] | rotate left doubleword then clear right [& record CR0] |
rldicl[.] | rotate left doubleword immediate then clear left [& record CR0] |
rldicr[.] | rotate left doubleword immediate then clear right [& record CR0] |
rldimi[.] | rotate left doubleword immediate then mask insert [& record CR0] |
rlwimi[.] | rotate left word immediate then mask insert [& record CR0] |
rlwinm[.] | rotate left word immediate then and with mask [& record CR0] |
rlwnm[.] | rotate left word then and with mask [& record CR0] |
sld[.] | shift left doubleword [& record CR0] |
slw[.] | shift left word [& record CR0] |
srad[.] | shift right doubleword [& record CR0] |
sradi[.] | shift right doubleword immediate [& record CR0] |
sraw[.] | shift right word [& record CR0] |
srawi[.] | shift right word immediate [& record CR0] |
srd[.] | shift right doubleword [& record CR0] |
srw[.] | shift right word [& record CR0] |
PowerPC 提供了一组健壮的浮点运算、比较和转换操作(指令)。与软件支持一道,PowerPC 浮点运算完全符合 ANSI/IEEE 标准 754-1985 规范。在所有运算和比较操作中都支持单精度和双精度浮点格式。
虽然浮点数以双精度格式存储于 FPR 中,但是,有一组单精度运算指令,可以执行运算操作并将最终结果舍入为单精度,同时检测进行单精度操作时可能会发生的异常(比如指数溢出、下溢和失去精度)。
可以启用或禁用具体种类的浮点异常来支持设陷(trapping) 环境。表 7 列出了基本的和可选的 PowerPC 浮点指令集。
表 7. PowerPC 浮点指令
助记符 | 指令名 |
fmr[.] | FP move [& record CR1] |
fneg[.] | FP negate [& record CR1] |
fabs[.] | FP absolute value [& record CR1] |
fnabs[.] | FP negative absolute value [& record CR1] |
fadd | FP add [single] [& record CR1] |
fsub | FP subtract [single] [& record CR1] |
fmul | FP multiply [single] [& record CR1] |
fdiv | FP divide [single] [& record CR1] |
fsqrt | FP square root [single] [& record CR1] |
fmadd | FP multiply-add [single] [& record CR1] |
fmsub | FP multiply-subtract [single] [& record CR1] |
fnmadd | FP negative multiply-add [single] [& record CR1] |
fnmsub | FP negative multiply-subtract [single] [& record CR1] |
fcmpo | FP compare ordered |
fcmpu | FP compare unordered |
fsel[.] | FP select [& record CR1] |
frsp[.] | FP round to single [& record CR1] |
fcfid[.] | FP convert from integer doubleword [& record CR1] |
fctid[z][.] | FP convert to integer doubleword [& round to zero] [& record CR1] |
fctiw[z][.] | FP convert to integer word [& round to zero] [& record CR1] |
fres[.] | FP reciprocal estimate single [& record CR1] |
frsqrte[.] | FP reciprocal square root estimate [& record CR1] |
表 8 列出了基本的 PowerPC FPSCR 处理指令集。
表 8. PowerPC FPSCR 处理指令集
助记符 | 指令名 |
mcrfs | move to CR from FPSCR |
mffs[.] | move from FPSCR |
mtfsb0[.] | move to FPSCR bit 0 |
mtfsb1[.] | move to FPSCR bit 1 |
mtfsf[.] | move to FPSCR field |
mtfsfi[.] | move to FPSCR field immediate |
所有加载和存储指令的执行都使用 GPR 或者 GPR 和指令中的立即字段作为存储器访问的地址说明符。用指令生成的数据有效地址来更新基址寄存器(也就是 RA)是大部分加载和存储指令的一个可选项。
有用于以下方面的指令:
特殊的存储器访问指令包括:
lmw
和 stmw
,可以操作最多 31 个 32 位字。 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. 高速缓存管理指令
助记符 | 指令名 |
dcbf | Flush Data Cache Line |
dcbst | Store Data Cache Line |
dcbt | Touch Data Cache Line(for load) |
dcbtst | Touch Data Cache Line(for store) |
dcbz | Zero Data Cache Line |
icbi | Invalidate Instruction Cache Line |
当将高速缓存处理代码移植到不同的 PowerPC 实现时要当心。虽然高速缓存指令可能是跨不同实现而通用的,高速缓存的组织和大小可能会有变化。例如,假定高速缓存大小以对其进行刷新的代码,在用于其他大小的高速缓存时可能需要进行修改。而且,各实现的高速缓存初始化可能不同。有一些实现提供了自动清除高速缓存标签的硬件,而其他实现需要使用软件循环来使高速缓存标签无效。
虽然编写自修改代码不是一个工业标准,但有些情况下它是必不可少的。下面的序列介绍了执行代码修改用到的指令:
dcbst
指令,强制包含有修改过的指令的高速缓存行进行存储。 sync
指令,确保 dcbst
完成。 icbi
指令,使将要存放修改后指令的指令高速缓存行无效。 isync
指令,清除所有指令的指令管道,那些指令在高速缓存行被设为无效之前可能早已被取走了。 ![]() ![]() |
![]()
|
大部分实现都提供了一个 64 位时基,可以通过两个 32 位寄存器读取,或者通过一个 64 位寄存器读取。各实现的计时器增量不同,SPR 数和访问时基的指令也不同。所以,跨实现移植计时器代码时要当心。另外的计时器可能也不同,但大多数实现都提供了至少一种递减的可编程计时器。
![]() ![]() |
![]()
|
需要在多个实现上进行编程的 PowerPC 用户通常会问及保持代码兼容性的技巧。下面的建议将有助于尽量减少移植问题:
![]() ![]() |
![]()
|
PowerPC AS 和 PowerPC 都支持最初的 PowerPC 体系结构中定义的应用级基础设施,同时为它们的具体目标市场提供了最佳的优化。
就其两种操作模式之一而言,PowerPC AS 实质上与最初的 PowerPC 相同,而 PowerPC Book E 在它的 Book III 级别的定义中,已经走向了不同的方向,为低价格、低功率以及体系结构灵活的嵌入式应用进行了最优化。当然,在 32 位的实现上还不能用双字整数指令,在大部分嵌入式实现中浮点指令也只是通过软件仿真提供支持。
不过,这对应用程序二进制在 PowerPC 体系结构家族树的分支中自由地迁移来说是一个非常有意义的机会。
![]() | ||
![]() | Brett Olsson 致力于 PowerPC Book E 体系结构团队的 VMX 体系结构方面的工作。可以通过 brett@us.ibm.com 与 Brett 联系。 |
![]() | ||
![]() | Anthony Marsala 有很多头衔:演员、软件工程师、作家、丈夫,最近又增加了一个头衔 —— 父亲。他从 1993 年起加入了 IBM 嵌入式 PowerPC 团队的工作,在那里他帮助创建了用于下一代 PowerPC 处理器的软件工具。可以通过 marsala@us.ibm.com 与 Anthony 联系。 |
文章评论(0条评论)
登录后参与讨论