Chinaunix首页 | 论坛 | 博客
  • 博客访问: 810818
  • 博文数量: 118
  • 博客积分: 2067
  • 博客等级: 大尉
  • 技术积分: 1751
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-17 14:27
文章存档

2016年(1)

2013年(1)

2012年(3)

2011年(26)

2010年(47)

2009年(40)

分类: LINUX

2010-07-01 14:15:42

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 :
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 :
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 :
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
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
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

10000454 :
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
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
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
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
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         0x20            -----> 以当前指令地址为基点,往后跳转 0x20 字节,即 PC = CIA + 0x20
ba       0x20            -----> 直接跳转到地址 0x20 处。后缀为 a,则表示使用 Absolute Address,PC = 0x20
bl        0x20            -----> 在 b 0x20 的基础上,将 LR 更新为 CIA + 4
bla      0x20            -----> 使用绝对地址,且更新 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 为 0x80,则只将 CR0 = RS0
若 FXM 为 0xc8,则将 CR0 = RS0, CR1 = RS1, CR4 = RS4

3.2.2.3 mfcr      RT   ---   Move From Condition Register

将 CR 的内容移入通用寄存器 RT 的 32 ~ 63 位。


3.3 整数指令

这类指令大致分为如下几类:

整数访存指令
整数算术运算指令
整数逻辑运算指令
整数比较指令
整数陷阱指令
整数移位指令
XER 指令

其中以整数循环移位指令最为特别。

3.3.1 整数访存指令

3.3.1.1 Load Byte/Half-word/Word and Zero

该类指令从指定地址处读取 8 位、16 位、32 位数据,置入 RT,RT 高位置 0

lbz/lbzu            RT, D(RA)
lbzx/lbzux          RT, RA, RB

lhz/lhzu            RT, D(RA)
lhzx/lhzux          RT, RA, RB

lwz/lwzu            RT, D(RA)
lwzx/lwzux          RT, RA, RB

RT, RA, RB 皆为 GPR,D 为有符号立即数。则有效地址的计算分别为:RA[32:63] + D,RA[32:63] + RB[32:63],有效地址高 32 位置 0。

后缀 u 表示 Update,即将有效地址更新到 RA 中
后缀 x 表示 Indexed,即使用 RA + RB 的寻址方式

以上用于 32 位,对 64 位,上述指令皆加后缀 'e'。则有效地址的 0 ~ 31 位, 不再置 0,其计算方式如下:RA + D,RA + RB。

此外,用于 64 位的还有对双字操作的支持:

lde/ldue/ldxe/lduxe


3.3.1.2 Load Half-word Algebraic

lha/lhau            RT, D(RA)
lhax/lhaux          RT, RA, RB

与 lhz 不同的是,该指令将所读取的半字的最高位 (RT[48]) 填充到 RT[32:47],实际上就是形成一个 16 位的补码有符号数。

有效地址计算与上同;后缀 u, x 与上同。

对 64 位情形,上述指令皆加后缀 'e',有效地址计算与上小节同。


3.3.1.3 Load Halfword/Word Byte-Reverse

从指定地址处读取 16 位/32 位数据,将字节反转后置入 RT,RT 高位置 0

    lhbrx   RT, RA, RB
lwbrx   RT, RA, RB

如: lwbrx   r3, r2, r1,若 r2 + r1 地址处的数据为 0x55aa66bb,则 r3 的结果为 0xbb66aa55

对 64 位情形,上述指令皆加后缀 'e',有效地址计算与上小节同。


3.3.1.4 Load Multiple Word

lmw    RT, D(RA)

该指令将 RA + D 开始处的数据,顺序置入 RT ~ R31 中,共读取 31 - T 个字

该指令无 64 位扩展。


3.3.1.5 Load String Word

lswi    RT, RA, NB      (后缀 i,表示立即数 Immediate)
lswx    RT, RA, RB      (后缀 x,表示 Indexed 寻址方式)

加载 n 个字节到 RT 开始的寄存器中;
当 NB == 0 时 n = 32; NB != 0 时 n = NB,NB 取值范围为 0 ~ 31

如 r3 = 0x1000 :

lswi   r4, r3, 16  

则将 0x1000 处的 16 字节,依次写入 r4, r5, r6, r7

对于 lswx,要加载的字节数则位于 XER[57:63]

该指令无 64 位扩展。


3.3.1.6 Load Word/Doubleword and Reserve

lwarx    RT, RA, RB

该指令与 lwzx 的差别在于,其还将处理器内部的 RESERVE 位置为 1,并将有效地址对应的物理地址放入 RESERVE_ADDR 中。

该指令的 64 位版本为: lwarxe   RT, RA, RB,差别还是在于有效地址的 0 ~ 31 不被置 0

此外还有一个 ldarxe   RT, RA, RB,与 lwarxe 的差别在于其加载 8 字节的数据。

这三条指令常分别与 stwcx./stwcxe./stdcxe. 联用,用于实现锁操作,类似 MIPS 之 ll/sc 指令。


3.3.1.7 Store

stb/stbu            RS, D(RA)
stbx/stbux          RS, RA, RB
sth/sthu            RS, D(RA)
sthx/sthux          RS, RA, RB
stw/stwu            RS, D(RA)
stwx/stwux          RS, RA, RB

该类指令将 RS 中的 8 位、16 位、32 位数据写入有效地址处。后缀 'u', 'x' 之含义与 3.3.1.1 同。

上述 12 条指令加后缀 'e' 则用于 64 位。有效地址计算与与 3.3.1.1 同。

另用于 64 位的还有对双字操作的支持:

stde/stdue/stdxe/stduxe


3.3.1.8 Store Halfword/Word Byte-Reverse

sthbrx RS, RA, RB
stwbrx RS, RA, RB

将 RS 中的 16/32 bit 的数据字节反转后置入有效地址处。该指令用于支持在大端系统上以小端序存储数据,亦或在小端系统上以大端序存储数据。

对 64 位情形,上述指令皆加后缀 'e',有效地址计算与上小节同。


3.3.1.9 Store Multiple Word

smw   RS, D(RA)

该指令将 RS ~ R31 中的数据 (一个字),写入到 RA + D 处

该指令无 64 位扩展。


3.3.1.10 Store String Word

stswi      RS, RA, NB    (后缀 i,表示立即数 Immediate)
stswx      RS, RA, RB    (后缀 x,表示 Indexed 寻址方式)

与 lswi/lswx 的操作相反,其将 RS 开始的寄存器组中的 n 个字节,写入到有效地址处(位于 RA)

当 NB == 0 时 n = 32; NB != 0 时 n = NB,NB 取值范围为 0 ~ 31

如 r3 = 0x1000 :

stswi   r4, r3, 16  

则将 r4, r5, r6, r7 中的 16 字节数据依次写入 0x1000 处

对于 stswx,要加载的字节数则位于 XER[57:63]

该指令无 64 位扩展。


3.3.1.11 Store Word/Doubleword Conditional

stwcx.         RS, RA, RB

如果 RESERVE 位为 1,且 RA + RB 对应的物理地址与 RESERVE_ADDR 一致,则将 RS[32:63] 的内容写入到 RA + RB 处,将 CR0[eq] 位置为 1 后,再将 RESERVE 位复位为 0。

若条件不满足,则仅将 CR0[eq] 位置为 0

可用该指令与 lwarx 联用,实现 spin_lock:

li   r0, 1
loop:
lwarx   r4, 0, r3
cmpwi   r4, 0          # r4[32:63] 与 0 比较
bne loop
stwcw.   r0, 0, r3
bne   loop
isync

解锁则为:

msync
li   r0, 0
stw   r0, 0(r3)


下面的指令用于 64 位:

stwcxe.       RS, RA, RB
stdcxe.       RS, RA, RB

差别在于有效地址的高 32 位不再被置为 0。


3.3.2 整数算术运算指令



3.3.3 整数逻辑运算指令



3.3.4 整数比较指令


cmp       BF, L, RA, RB      
cmpi       BF, L, RA, SI          # RA 与有符号立即数 SI 比较
cmpl       BF, L, RA, RB          # RA, RB 逻辑比较。l ---> logical
cmpli      BF, L, RA, UI          # RA 与无符号立即数 UI 逻辑比较

BF 取值 0 ~ 7,用于指定使用的 CR 域
L 为 0,则为 32 位比较;为 1,则为 64 位比较

如:

cmpi      0, 0, r3, 5

若 r3 > 5,则 CR0[gt] = 1;若 r3 < 5,则 CR0[lt] = 1


3.3.5 整数陷阱指令

tw      TO, RA, RB
twi   TO, RA, SI

TO 为立即数,5 位,从左到右标号为 0 ~ 4,依次表示小于、大于、等于、无符号小于、无符号大于。用于指定 Trap 的条件。
SI: Signed Immediate

如:

twi   0x10, r3, 5

则如果 r3 < 5,则陷入异常。

以上用于单字 (32 bit) 比较,双字比较则用:

td      TO, RA, RB
tdi   TO, RA, SI


3.3.6 整数移位指令


3.3.6.1 Rotate

rlwimi        RA, RS, SH, MB, ME            # Rotate Left Word Immediate then Mask Insert
rlwinm        RA, RS, SH, MB, ME            # Rotate Left Word Immediate then AND with Mask
rlwnm         RA, RS, RB, MB, ME            # Rotate Left Word then AND with Mask

以下是该指令的一些例子:

all r11 is: 0x55aa67bb

r0 = 0x00000000
rlwimi    r0, r11, 8, 0, 31
r0 is: 0xaa67bb55

r0 = 0x12345678
rlwimi    r0, r11, 8, 0, 14
r0 is: 0xaa665678

r0 = 0x12345678
rlwimi    r0, r11, 8, 28, 3
r0 is: 0xa2345675

即:取 RS 循环左移 SH 位后的 WB 到 WE 位,替换 RA 的 WB 到 WE 位。

r0 = 0x00000000
rlwinm    r0, r11, 8, 0, 31
r0 is: 0xaa67bb55

r0 = 0x12345678
rlwinm    r0, r11, 8, 0, 14
r0 is: 0xaa660000

即:取 RS 循环左移 SH 位后的 WB 到 WE 位,替换归零后的 RA

rldcl
rldcr
rldic
rldicl
rldicr
rldimi

3.3.6.2 Shift

slw
srw
sraw
srawi

slw./srw./sraw./srawi.

sld
srd
srad
sradi


3.3.7 XER 指令

mcrxr          BF
mcrxr64        BF


3.4 浮点指令

这类指令包括:

浮点数据加载与存储指令
浮点运算指令
浮点数近似和转化指令
浮点比较指令
浮点状态和控制寄存器指令

有关该指令的详情留待以后以《PowerPC 浮点结构》的形式讨论吧。

3.5 处理器控制指令

这类指令包括用于支持异常中断处理的:

sc            System Call
rfci          Return From Critical Interrupt
rfi         Return From Interrup

用于处理器控制寄存器维护的:

mfspr      RT, SPRN         Move From SPRN (Special Purpose Register) to RT
mtspr      SPRN, RS         Move RS To SPRN

mfdcr      RT, DCRN         Move From DCRN (Device Control Register) to RT
mtdcr      DCRN, RS         Move RS To DCRN

mfmsr      RT            Move From MSR to RT
mtmsr      RS            Move RS To MSR

wrtee        RA    Write MSR External Enable, MSR[EE] = RA[48]
wrteei    E   Write MSR External Enable Immediate, MSR[EE] = E

以及用于指令同步的:

isync

其保证在其之前的所有指令皆提交,在其自己被提交前,其之后的指令不会进入流水线


3.6 存储管理相关指令

这类指令包括用于 TLB 管理的:

tlbivax
tlbre
tlbwe
tlbsx
tlbsync

tlbivaxe
tlbsxe

用于 Cache 管理的:

dcba/dcbf/dcbi/dcbst/dcbt/dcbtst/dctz/icbi/icbt
dcbae/dcbfe/dcbie/dcbste/dcbte/dcbtste/dctze/icbie/icbte

用于存储同步的:

msync
mbar
阅读(7931) | 评论(0) | 转发(0) |
0

上一篇:vimdiff使用

下一篇:PowerPC linux 学习笔记!

给主人留下些什么吧!~~