当前版本: 1.0
完成日期: 2008-7-23
作者: Jack Tan
Email: jiankemeng@gmail.com
版权声明: 转载请注明出处,商业用途请联系作者
1. 概述
Book E 定义的 PowerPC 指令集的指令可分为以下几类:
分支跳转指令
CR 指令 整数指令
浮点指令
处理器控制指令
存储管理相关指令
CR 指令主要是对 CR 内部位运算支持的一些指令,如 crand, cror, crxor 等等。
2. 常用指令
先看一个测试程序:
int test_call(int a, int b, int c) { a = b + c; return a; } int test_if(int s) { int i; if(s > 0) i = s; else if(s < 0) i = -s; else i = s * 8; return i; } int test_cyc1(int c) { int sum = 0; do { sum += c; c--; } while(c > 0); return c; } int test_cyc2(int c) { int sum = 0; for(; c > 0; c--) sum += c; return c; } int main() { int a, b, c, d; a = test_if(5); b = test_cyc1(10); c = test_cyc2(10); d = test_call(1, 2, 3); return a + b + c + d; }
引入的目的在于查看判断、循环和过程调用这些基本结构在 PowerPC 里怎么被支持。
-O2 参数编译后,objdump -S -d 反汇编,则:
1000040c <test_call>: int test_call(int a, int b, int c) { a = b + c; return a; } 1000040c: 7c 64 2a 14 add r3,r4,r5 --> 对应 a, b, c 三个参数,同时 r3 又置返回值 10000410: 4e 80 00 20 blr --> 跳转到 LR 所存放的地址处,即函数返回 10000414 <test_if>: int test_if(int s) { int i; if(s > 0) 10000414: 7c 60 1b 79 mr. r0,r3 --> r3 移到 r0,若 r0 小于、大于、等于 0,则置 CR0 的相应位。指令后多一点,则说明该指令会据执行结果,设置 CR 的相应位 10000418: 7c 03 03 78 mr r3,r0 --> 此条指令多余 1000041c: 4d a1 00 20 bgtlr+ --> 若 CR0[gt] 位为 1,则跳转到 LR 所存放的地址处,即直接函数返回了。此条指令等价于 bclr 13, 1 i = s; else if(s < 0) 10000420: 38 60 00 00 li r3,0 10000424: 4d 82 00 20 beqlr --> 若 CR0[eq] 位为 1,则跳转到 LR 所存放的地址处,也直接函数返回了。此条指令等价于 bclr 12, 2 i = -s; 10000428: 7c 60 00 d0 neg r3,r0 --> r0 取反,入 r3 else i = s * 8; return i; } 1000042c: 4e 80 00 20 blr --> 跳转到 LR 所存放的地址处,函数返回 10000430 <test_cyc1>: int test_cyc1(int c) { 10000430: 34 03 ff ff addic. r0,r3,-1 10000434: 7c 69 03 a6 mtctr r3 10000438: 41 80 00 10 blt- 10000448 <test_cyc1+0x18> int sum = 0; do { sum += c; c--; 1000043c: 38 63 ff ff addi r3,r3,-1 } while(c > 0); 10000440: 42 00 ff fc bdnz+ 1000043c <test_cyc1+0xc> return c; } 10000444: 4e 80 00 20 blr 10000448: 38 00 00 01 li r0,1 1000044c: 7c 09 03 a6 mtctr r0 10000450: 4b ff ff ec b 1000043c <test_cyc1+0xc> 10000454 <test_cyc2>: int test_cyc2(int c) { 10000454: 2c 03 00 00 cmpwi r3,0 10000458: 39 20 00 00 li r9,0 1000045c: 7d 23 48 1e .long 0x7d23481e int sum = 0; for(; c > 0; c--) sum += c; return c; } 10000460: 7d 23 4b 78 mr r3,r9 10000464: 4e 80 00 20 blr int main() { 10000468: 94 21 ff e0 stwu r1,-32(r1) 1000046c: 7c 08 02 a6 mflr r0 int a, b, c, d; a = test_if(5); 10000470: 38 60 00 05 li r3,5 10000474: 90 01 00 24 stw r0,36(r1) 10000478: 93 61 00 0c stw r27,12(r1) 1000047c: 93 81 00 10 stw r28,16(r1) 10000480: 93 a1 00 14 stw r29,20(r1) 10000484: 4b ff ff 91 bl 10000414 <test_if> 10000488: 7c 7d 1b 78 mr r29,r3 b = test_cyc1(10); 1000048c: 38 60 00 0a li r3,10 10000490: 4b ff ff a1 bl 10000430 <test_cyc1> 10000494: 7c 7b 1b 78 mr r27,r3 c = test_cyc2(10); 10000498: 38 60 00 0a li r3,10 d = test_call(1, 2, 3); 1000049c: 7f bd da 14 add r29,r29,r27 100004a0: 4b ff ff b5 bl 10000454 <test_cyc2> 100004a4: 38 80 00 02 li r4,2 100004a8: 7c 7c 1b 78 mr r28,r3 100004ac: 38 a0 00 03 li r5,3 100004b0: 38 60 00 01 li r3,1 100004b4: 4b ff ff 59 bl 1000040c <test_call> return a + b + c + d; } 100004b8: 80 01 00 24 lwz r0,36(r1) 100004bc: 7f 9c 1a 14 add r28,r28,r3 100004c0: 83 61 00 0c lwz r27,12(r1) 100004c4: 7c 7d e2 14 add r3,r29,r28 100004c8: 83 81 00 10 lwz r28,16(r1) 100004cc: 83 a1 00 14 lwz r29,20(r1) 100004d0: 7c 08 03 a6 mtlr r0 100004d4: 38 21 00 20 addi r1,r1,32 100004d8: 4e 80 00 20 blr
3. 分类概述
3.1 分支跳转指令
这类指令算是 PowerPC 里比较有特色的,也是稍显复杂的。这类指令与 CR, LR 和 CTR 紧密相联,建构起判断、循环和过程调用这些程序的基本结构。其大致可分为四类:
Branch
Branch Conditional
Branch Conditional to Count Register
Branch Conditional to Link Register
3.1.1 Branch
这类指令与 CR 没有联系,即为非条件跳转,助记符后直接跟立即数地址。指令内为立即数地址预留 26 位,即可跳转 2^26 大小的空间,如:(CIA, Current Instruction Address)
b 0×20 —–> 以当前指令地址为基点,往后跳转 0×20 字节,即 PC = CIA + 0×20
ba 0×20 —–> 直接跳转到地址 0×20 处。后缀为 a,则表示使用 Absolute Address,PC = 0×20。
bl 0×20 —–> 在 b 0×20 的基础上,将 LR 更新为 CIA + 4
bla 0×20 —–> 使用绝对地址,且更新 LR。后缀带 l,则表示更新 LR 为 CIA + 4
以上针对 32 位的情形,对 64 位则使用指令 be, bea, bel, bela 功能与上同。
3.1.2 Branch Conditional
此类为条件跳转指令。皆以 bc 开头,带 3 个操作数,如:
bc BO, BI, BD
bca BO, BI, BD
bcl BO, BI, BD
bcla BO, BI, BD
后缀 a, l 的含义与 branch 类指令同。BO 指定跳转的条件,5 位;BI 指定关联的 CR 位,也是 5 位;BD 为跳转的立即数地址,16 位。
其中以 BO 的编码最为复杂(BO 从左到右编号为 0 ~ 4):
BO[0]: 为 1,则直接跳转
BO[1]: 为 1,则条件为真时,跳转。否则条件为假时,跳转
BO[2]: 为 1,则 CTR 不自动减 1
BO[3]: 为 1 时,则 CTR == 0 时跳转;为 0 时,则 CTR != 0 时跳转
BO[4]: 静态预测位,1 表示 unlikely,0 表示 likely
则常见的 BO 值:
20 (0b10100) 则表示无条件跳转
12 (0b01100) 则表示 CR 的某个位为 1 时跳转
4 (0b00100) 则表示 CR 的某个位为 0 时跳转
至于静态预测的策略位,默认被置为 0,则其行为为:
b1. 目标地址小于当前指令地址,预测为跳转
b2. 目标地址大于当前指令地址,预测为不跳转
b3. 对于目标地址在 CTR/LR 中的条件跳转指令,一律预测为不跳转
若该位被置 1,则上述 b1, b2, b3 的静态预测行为分别为:不跳转,跳转,跳转。
可以给分支指令加一个 +/- 的后缀,来简化。加 ‘+’ 的指令,一律预测为跳转。加 ‘-’ 的分支指令,一律预测为不跳转。
则对于 b1,后缀 ‘+’ 会将 y 位置 0,’-’ 则将 y 位置 1。
对于 b2,后缀 ‘+’ 会将 y 位置 1,’-’ 则将 y 位置 0。
对于 b3,后缀 ‘+’ 会将 y 位置 1,’-’ 则将 y 位置 0。
BI 与关联 CR 位的关系为:
32 + BI
即,若 BI 为 2,则对应于 CR[34],即为 CR0[gt] 位。
以上针对 32 位的情形,对 64 位则使用指令 bce, bcea, bcel, bcela 功能与上同。
3.1.3 Branch Conditional to Count Register
bcctr BO, BI
bcctrl BO, BI
后缀 l 的含义与 branch 类指令同。
BO,BI 的编码与 Branch Conditional 类指令同。
跳转目标地址位于 CTR 中。
以上针对 32 位的情形,对 64 位则使用指令 bcctre, bcctrel 功能与上同。
3.1.4 Branch Conditional to Link Register
bclr BO, BI
bclrl BO, BI
后缀 l 的含义与 branch 类指令同。
BO,BI 的编码与 Branch Conditional 类指令同。
跳转目标地址位于 LR 中。
以上针对 32 位的情形,对 64 位则使用指令 bclre, bclrel 功能与上同。
3.2 CR 指令
这类指令包括用来支持 CR 内部位运算的指令和 CR 与 GPR 之间的数据交换指令。
3.2.1 CR 内位运算指令
这类指令的格式皆为: crxxx BT, BA, BB
BT, BA, BB 是 CR 内的位编号,取值范围为 0 ~ 31,如 crand 0, 8, 12,则将 CR[32+8] (CR2[lt]) 与 CR[32+12] (CR3[lt]) 作与操作后,将结果置入 CR[32+0] (CR0[lt]),即 CR[32] = CR[40] & CR[44]
crand: CR[32+BA] & CR[32+BB]
crandc: CR[32+BA] & (~CR[32+BB])
creqv: ~(CR[32+BA] ^ CR[32+BB]),即位相等,则置 1;不等则置 0
crnand: ~(CR[32+BA] & CR[32+BB])
crnor: ~(CR[32+BA] | CR[32+BB])
cror: CR[32+BA] | CR[32+BB]
crorc: CR[32+BA] | (~CR[32+BB]),先取反后再或
crxor: CR[32+BA] ^ CR[32+BB],位异或
3.2.2 CR 与 GPR 间数据交换指令
3.2.2.1 mcrf BF, BFA — Move Condition Register Fields
将 CR 之 BFA 域复制到 BF 域。如 mcrf 0, 3 则将 CR3 拷入 CR0
3.2.2.2 mtcrf FXM, RS — Move To Condition Register Fields
通用寄存器 RS 之 32 ~ 63 位以 4 位为单位,对应于 CR 的 8 个域,编号为 RS0 ~ RS7;
FXM 为域掩码,8 位,从左到右编号为 0 ~ 7,对应于 RS、CR 的 8 个域。某位为 1,则将对应的 RS 域拷贝到对应的 CR 域中。
若 FXM 为 0×80,则只将 CR0 = RS0
若 FXM 为 0xc8,则将 CR0 = RS0, CR1 = RS1, CR4 = RS4
3.2.2.3 mfcr RT — Move From Condition Register
将 CR 的内容移入通用寄存器 RT 的 32 ~ 63 位。