1、32 位 PowerPC 构架通用寄存器分析及总结一第一部分 32 位 PowerPC 构架下寄存器概述32 位 PowerPC 构架寄存器模型可以分成三个类级别:UISA,VEA,OEA,我们根据这三个级别把 PowerPC 所使用的所有寄存器分为三类:第一类:用户指令集构架(UISA-User Instruction Set Architecture)下所使用的寄存器;第二类:虚拟环境构架(VEA-Virtual Environment Architecture)下所使用的寄存器;第三类:操作系统环境(OEA-Operating Environment Architecture)下所使用的
2、寄存器;PowerPC 指令集构架为所有的算术逻辑运算指令定义了“寄存器到寄存器”格式的指令,这些指令的操作数来自或者来自于寄存器,或者来自于指令中的立即数。而对于“三寄存器”格式的指令,PowerPC 指令集定义其中一个寄存器用来存目的操作数,另外两个寄存器用来存放源操作数。这样的话,存放源操作数的寄存器还可以被其它指令使用,从而减少了某些操作的指令数目。并且对于访问寄存器,PowerPC 构架定义了明确的 load 和store 访存指令(这是 RISC 指令集的典型特点) 。备注:寄存器中的保留位允许软件写任何值(其实就是 0 或者 1) ,但是读出来的值,未必是我们写出来的值。它的值依
3、赖于具体的执行系统。接下来,我们分别来介绍这三类寄存器。第二部分 UISA 寄存器集合用户模式下的寄存器可以被所有的用户级软件和特权级软件所使用,它包含以下的寄存器:32 个通用寄存器 GPRs(General-purpose registers):GPR0-GPR31;32 个浮点寄存器 FRPs(Floating-point registers):FPR0-FPR31;1 个条件寄存器:CR(Condition register) ;1 个 XER 寄存器;1 个 LR(Link register)寄存器;1 个 CTR(Count register)寄存器;1 个浮点状态控制寄存器:FP
4、SCR(Floating-point status and control register) ;备注:不管是单精度数还是双精度数,在浮点寄存器中都是以双精度格式存储。示意图如下:2.1 通用寄存器 GPRs32 个 32 位通用寄存器主要用来操作整数数据,它们可以作为指令源寄存器和目的寄存器使用,使用起来比较简单,这里就不再相信介绍2.2 浮点寄存器 FPRsPowerPC 构架使用 32 个 64 位的浮点寄存器,这些寄存器可以在浮点指令中用作源操作数和目的操作数。无论是单精度浮点数还是双精度浮点数在浮点寄存器中都是以双精度格式存储。除了浮点比较指令之外,其他的浮点操作指令都是操作 FPR
5、s 中的数据,然后把操作结果放入 FPRs 中,同时把浮点操作的状态信息存入 FPSCR 中;而浮点比较指令的结果一般会存放在 CR 寄存器的 CR2 字段中。另外对于 FPRs 同存放在内存中的双精度输进行数据转存时,不需要格式转换;而对于FPRs 和放在在内存中的单精度数进行转存时需要格式转换;而且单精度指令操作 FPRs 中的数据时,必须把 FPRs 中的双精度格式的数据转化成单精度格式,单精度指令才能使用。2.3 CR 寄存器32 位的 CR 寄存器可以反映某些操作的结果(比如 cmp 指令) ,协助测试和分支转移指令的执行。CR 寄存器用来存放指令执行之后的状态,该寄存器分为 8 个
6、字段。分别为CR0,CR1,CR7。每个字段都由 4bit 组成。各个字段 CRn(n 从 0 至 7)都可以表示响应指令执行的结果:比如整数的加减及逻辑运算,使用 CR0 来存放状态,CR0 的四个 bit 位的含义如下:CR0(0):用来表示 LT(小于) ,当整型指令运算结果为负时置 1;CR0(1):用来表示 GT(大于) ,当整型指令运算结果为正时置 1;CR0(2):用来表示 EQ(等于) ,当整型指令运算结果为 0 时置 1;CR0(3):用来表示 SO(溢出) ,当整型指令运算结果溢出时置 1;同理浮点数的运算使用 CR1 来保存运算状态,保存过程同上。其实比较指令可以使用 C
7、R 寄存器的全部的 CRn(n 从 0 至 7)来保存运算的结果。在使用CR 寄存器时,比较指令 cmp 之后都会有一个条件跳转指令,比如 bc 指令。其中 cmp 指令可以指定由 CR 寄存器的 CRn 段来保存结构, cmpi 指令就用 BF 字段来指定 CRn 字段,一般而言 bc 指令就会指向 cmp 中相同的 CRn 段来决定跳转。下面的指令用来操作 CR 寄存器的各个 CRn 域:1:mtcrf 用一个 GPR 的值来设置 CR 寄存器的 CRn 域;2:mcrf 把 CR 寄存器的一个域 CRn 拷贝到另一个域 CRm;3:mcrxr 把 XER 寄存器的 bit0-bit3 拷
8、贝到 CR 寄存器的一个域 CRn4:mcrfs 把指定的 FPSCR 寄存器的一个域拷贝到指定的 CR 寄存器的一个域 CRn5:CR 寄存器的 CR0 域存放整数指令的运算结果6:CR 寄存器的 CR1 域存放浮点数指令的运算结果7:可以指定 CR 寄存器的任何一个域 CRn 来存放整数指令和浮点数指令的运算结果;2.3.1 对于 CR 寄存器的 CR0 域解释对于所有的整数指令比如 addic. ,adni. 和 andis.等(.表示 Rc 位置位) ,指令的执行结果将会反映在 CR0 位上。CR00:2位根据整数指令的运算结构设定,CR3由 XERS0位拷贝过来,四个 bit 位的含
9、义上面已经讲过。备注:我们不难想到,如果发生溢出,CR0 的前三个 bit 就没有参考价值了。2.3.2 对于 CR 寄存器的 CR1 域对于所有的浮点运算指令(指令的 Rc 位置位) ,CR1 将反映浮点运算指令的结果。具体的说 CR10:3位拷贝自 FPSCR0:3,来反映浮点运算的异常状态。2.3.3 对于指定的 CRn 域的解释对于比较指令而言,它们通常会自己指定一个 CRn 域来存放比较指令的运算结果。比如对 cmpi 指令:cmpi BF,L,RA,SI语义:n EXTS(SI) then c 0b010 /大于时设置 CRn(1)为 1else c 0b001 /等于时设置 CR
10、n(2)为 1CR 寄存器中的: 4BF+32:4BF+35 - c | XER 寄存器中 SO 位 /|表示字符连接解释:将寄存器 RA 与立即数 SI 进行比较,然后将比较指令产生的状态放入 CR 寄存器的不同字段中,CR 寄存器有 8 个 CRn 字段(n 从 0 至 7) ,可以有三个 bit 位的 BF 段指定。L 表示是进行 32 位还是 64 的比较。对于 e600 而言,只有 L=0 的比较。2.4 FPSCR 寄存器FPSCR 寄存器的各个 bit 位的作用:1:记录浮点操作的异常2:记录浮点操作的结果的类型3:控制浮点操作的回旋模式(rounding mode)4:使能或者
11、禁止异常报告FPSCR0:23是状态 bit 位,在浮点指令的执行单元完成时更新;FPSCR24:31是控制位;2.5 XER 寄存器XER 寄存器是用户模式寄存器,存放整数运算操作的进位,溢出信息以及特殊加载和存储指令 lswd 和 stsws 传输的字节数。XER 寄存器有三个有效位(SO-Summary Overflow,OV-Overflow,CA-Carry)和一个有效字段 Byte countSO 位:XER0位,该位为 1 表示算术指令曾经将 OV 位置 1;CR 寄存器的 SO 位就是复制了XER 寄存器的 SO 位,SO 位一旦被设置,就不会被清除,真到程序使用 mtspr,
12、mcrxr 指令进行清除。OV 位:XER1位,表示有符合数的算术运算产生了溢出。CA 位:XER2位,表示无符号数运算产生了进位。Byte count 字段:XER25:31存放 lswd 和 stsws 传输的字节数。2.6 LR 寄存器LR 寄存器用来存放函数的返回地址,某些转移指令可以自动的将 LR 寄存器赋值为该转移指令所在地址的下一个地址。LR 寄存器还可以用作 bclr 指令的目标地址,来实现长跳转。示意图如下:备注:图中的 blr 是 bclr 20, 0 指令的助记符。2.7 CTR 指令CTR 寄存器用来保存循环变量,并可以根据 bclr 的 BO 操作数来自动进行减 1
13、操作。此外 CTR 寄存器还可用来保存 bcctr 指令的目标地址,用来实现长调转。第三部分 虚拟环境构架(VEA-Virtual Environment Architecture)寄存器集虚拟环境工具寄存器集只包含 Time-Base 寄存器组。示意图如下:VEA 寄存器组可以被所有的处于用户模式或者系统模式下的软件所访问,从 VEA 寄存器组的示意图我们可以看出,和 UISA 寄存器相比。VEA 寄存器只是引入了一个 64 位的结构体,它包含两个寄存器:TBU(Time Base Upper)寄存器和 TBL(Time Base Lower)寄存器,这两个寄存器可以被用户模式和系统模式的指
14、令访问。在 VEA 环境中,用户模式下的应用程序仅能访问 TB 寄存器,而在操作系统环境构架(OEA)定义的系统模式下,系统模式指令可以写入 TB 寄存器。TB 寄存器组是存放了一个 64bit 的无符号整数,这个整数周期性的递增。每次递增,TB 中的 TBL 寄存器第 31bit 位加 1,TB 中计数器更新的周期与具体的操作相关,即它依赖于具体的实现。TB 寄存器会以一种依赖于实现的频率周期性地增加,这个频率可能不是恒定的。操作系统(OS)要负责确定更新频率是否发生了变化,以及对内部结构进行必要的调整。小结一下:1:TB 寄存器是 64 位长的;2:每次更新都会增加 1;3:操作系统必须要
15、能够确定更新频率;4:当 TB 达到自己的最大值时,就会溢出并从 0 重新开始。此时没有明显的迹象,要交由操作系统进行处理。5:OS 必须要在开机时对 TB 寄存器进行初始化。备注:TB 寄存器自己并没有包含计算时间所需要的足够信息。Power Architecture 规范将很多对 TB 寄存器进行处理的责任都交给操作系统来完成,操作系统需要提供其他一些信息,例如更新频率、启动时的 Time Base 寄存器的值,等等。整个计算机制非常迅速且高效。关于 TB 寄存器的使用,更详细的内容可以参考: 64 位 Linux 中 Power Architecture Time Base 的寄存器这篇文章写的很到位。待续。 。 。 。 。 。