2023年12月21日发(作者:)
PowerPC汇编指令集
标签:?汇编??指令??PowerPC??PPC?2008-05-0421:25
PowerPC?体系结构规范(PowerPCArchitectureSpecification)发布于?1993?年,它是一个?64?位规范?(?也包含?32?位子集?)。几乎所有常规可用的?PowerPC(除了新型号?IBMRS/6000?和所有?IBMpSeries?高端服务器)都是?32?位的。
PowerPC?处理器有?32?个(32?位或?64?位)GPR(通用寄存器)以及诸如?PC(程序计数器,也称为IAR/指令地址寄存器或?NIP/下一指令指针)、LR(链接寄存器)、CR(条件寄存器)等各种其它寄存器。有些?PowerPCCPU?还有?32?个?64?位?FPR(浮点寄存器)。MPC555使用的PowerPCCPU是带有FPR的。一些常用寄存器介绍如下:
通用寄存器的用途:
r0 在函数开始(functionprologs)时使用。
r1 堆栈指针,相当于ia32架构中的esp寄存器,idapro把这个寄存器反汇编标识为sp。
r2 内容表(toc)指针,idapro把这个寄存器反汇编标识为rtoc。系统调用时,它包含系统调用号(这个好像跟系统有关吧)。
r3 作为第一个参数和返回值。
r4-r10 函数或系统调用开始的参数。
r11 ?用在指针的调用和当作一些语言的环境指针。
r12 ?它用在异常处理和glink(动态连接器)代码。
r13 ?保留作为系统线程ID。
r14-r31?作为本地变量,非易失性。
专用寄存器的用途:
lr 链接寄存器,它用来存放函数调用结束处的返回地址。
ctr ?计数寄存器,它用来当作循环计数器,会随特定转移操作而递减。
xer ?定点异常寄存器,存放整数运算操作的进位以及溢出信息。
msr ?机器状态寄存器,用来配置微处理器的设定。
cr 条件寄存器,它分成8个4位字段,cr0-cr7,它反映了某个算法操作的结果并且提供条件分支的机制。
寄存器r1、r14-r31是非易失性的,这意味着它们的值在函数调用过程保持不变。寄存器r2也算非易失性,但是只有在调用函数在调用后必须恢复它的值时才被处理。
寄存器r0、r3-r12和特殊寄存器lr、ctr、xer、fpscr是易失性的,它们的值在函数调用过程中会发生变化。此外寄存器r0、r2、r11和r12可能会被交叉模块调用改变,所以函数在调用的时候不能采用它们的值。
条件代码寄存器字段cr0、cr1、cr5、cr6和cr7是易失性的。cr2、cr3和cr4是非易失性的,函数如果要改变它们必须保存并恢复这些字段。
在AIX上,svca指令(sc是PowerPC的助记符)用来表示系统调用,r2寄存器指定系统调用号,r3-r10寄存器是给该系统调用的参数。在执行系统调用指令之前有两个额外的先决条件:LR寄存器必须保存返回系统调用地址的值并且在系统调用前执行crorccr6,cr6,cr6指令(?)。
应用程序二进制接口(ABI)
从技术而言,开发人员可以将任一?GPR?用于任何操作。例如,由于不存在:“堆栈指针寄存器”,为此程序员就可以使用任何寄存器。实际上,定义一组约定很有用,这样二进制对象就可以与不同的编译器和预先编写好的汇编代码进行互操作。
调用约定是由使用的?ABI(应用程序二进制接口)决定的。ppc32Linux?和?NetBSD?实现使用SVR4(SystemVR4)ABI,而?ppc64Linux?仿效了?AIX,使用?PowerOpenABI。ABI?还指定当调用子例程时哪些寄存器被认为是易失型的(调用者保存(caller-save))以及哪些被认为是非易失型的(被调用者保存(callee-save)),以及许多其它内容。
SVR4ABI?指定了一些行为的具体示例:
-由于?PowerPC?拥有如此多的?GPR(32?个,而相比之下?IA32?只有?8?个),所以传递参数的寄存器从gpr3?开始。
-寄存器?gpr3?到?gpr12?是易失型的(调用者保存)寄存器,如果需要的话,在调用子例程之前必须先保存它们并在返回之后恢复它们。?-寄存器gpr1用来作为栈帧指针。
指令格式
PowerPC
指令包括操作码和操作数两部分,PowerPC支持三操作数的指令格式。如算术指令:
addrD,rA,rB
表示把(rA)+(rB)的和存放到rD寄存器中。
注意:
指令中的点号“.”表示:指令将更新条件寄存器CR0。如,rA,rB。
指令中的字母“c”表示:指令显示说明结果影响XER寄存器中的进位位[CA],如addcrD,rA,rB。
指令中的字母“e”表示:在指令中把XER[CA]中的数据作为一个操作数,并在XER[CA]位记录进位位,如adderD,rA,rB
指令中的字母“o”表示:溢出标志。对于整数,在XER[OA]位记录溢出和在CR0[SO]记录溢出位,如addorD,rA,rB
条件寄存器
条件寄存器CR包括8个4bit的字段,即CR0~CR7。每个字段可以表示整数运算或比较的结果。每个条件字段可以记录比较结果,即大于、小于、等于和总体溢出等。条件寄存器格式如图1所示。
异常处理器
整数异常寄存器XER是一个特殊功能寄存器,它包括一些对增加计算精度有用的信息和出错信息。XER的格式如下:
SO为总体溢出标志:一旦有溢出位OV置位,SO就会置位。
OV为溢出标志:当发生溢出时置位,否则清零;在作乘法或除法运算时,如果结果超过寄存器的表达范围,则溢出置位。
CA为进位标志:当最高位产生进位时,置位,否则清零;扩展精度指令(后述)可以用CA作为操作符参与运算。
存储/加载指令
1?整数存储指令
整数存储指令如表2所示。
名称
字节存储(偏移地址寻址)
字节存储(寄存器寻址)
记录有效地址的字节存储(偏移地址寻址)
记录有效地址的字节存储(寄存器寻址)
半字存储(偏移地址寻址)
半字存储(寄存器寻址)
记录有效地址的半字存储(偏移地址寻址)
记录有效地址的半字存储(寄存器寻址)
字存储(偏移地址寻址)
表2?整数存储指令
助记符
stb
stbx
stbu
stbux
sth
sthx
sthu
sthux
stw
语法格式
rS,d(rA)
rS,rA,rB
rS,d(rA)
rS,rA,rB
rS,d(rA)
rS,rA,rB
rS,d(rA)
rS,rA,rB
rS,d(rA)
字存储(寄存器寻址)
记录有效地址的字存储(偏移地址寻址)
记录有效地址的字存储(寄存器寻址)
stbrS,d(rA)
stwx
stwu
stwux
rS,rA,rB
rS,d(rA)
rS,rA,rB
(1)?字节存储指令stb(偏移地址寻址)
有效地址为rA的内容加d,rS的低8位内容存储到有效地址为EA的存储器中。
(2)?字节存储指令stbx(寄存器寻址)
stbxrS,rA,rB
有效地址为rA的内容加上rB的内容,rS的低8位内容存储到有效地址为EA的存储器中。
(3)?记录有效地址的字节存储指令stbu(偏移地址寻址)
stubrS,d(rA)
有效地址EA=(rA)+d,rS的低8位内容存储到有效地址为EA的存储器中。rA=EA,如果rA=0,则指令无效。
(4)?记录有效地址的字节存储指令stbux(寄存器寻址)
stbuxrS,rA,rB
有效地址EA=(rA)+(rB),rS的低8位内容存储到有效地址为EA的存储器中,rA=EA,如果rA=0,则指令无效。
(5)?半字存储指令sth(偏移地址寻址)
sthrS,d(rA)
有效地址EA=(rA)+d,rS的低16位内容存储到有效地址为EA的存储器中。
(6)?记录有效地址的半字存储指令sthu(偏移地址寻址)
sthurS,d(rA)
有效地址EA=(rA)+d,rS的低16位内容存储到有效地址为EA的存储器中。rA=EA,如果rA=0,则指令无效。
(7)?字存储指令stw(偏移地址寻址)
stwrS,d(rA)
有效地址EA=(rA)+d,rS的32位内容存储到有效地址为EA的存储器中。
(8)?记录有效地址的字存储指令stwu(偏移地址寻址)
stwurS,d(rA)
有效地址EA=(rA)+d,rS的32位内容存储到有效地址为EA的存储器中,rA=EA,如果rA=0,则指令无效。
(9)?记录有效地址的字存储指令stwux(寄存器寻址)
stwuxrS,rA,rB
有效地址EA=(rA)+(rB),rS的32位内容存储到有效地址为EA的存储器中。rA=EA,如果rA=0,则指令无效。
(10)字存储指令stwx(寄存器寻址)
stwxrS,rA,rB
有效地址EA=(rA)+(rB),rS的32位内容存储到有效地址为EA的存储器中。
2、整数加载指令
整数加载指令如表3所示。
名称
高位清零加载字节指令(偏移地址寻址)
高位清零的加载字节指令(寄存器寻址)
高位清零的加载字节并记录有效地址指令(偏移地址寻址)
高位清零的加载字节并记录有效地址指令(寄存器寻址)
高位清零的加载半字指令(偏移地址寻址)
高位清零的加载半字指令(寄存器寻址)
高位清零的加载半字并记录有效地址指令(偏移地址寻址)
高位清零的加载半字并记录有效地址指令(寄存器寻址)
加载半字指令(偏移地址寻址)
加载半字指令(寄存器寻址)
加载半字并记录有效地助记符
lbz
lbzx
lbzu
语法格式
rD,d(rA)
rD,rA,rB
rD,d(rA)
lbzux rD,rA,rB
lhz
lhzx
lhzu
rD,d(rA)
rD,rA,rB
rD,d(rA)
lhzux rD,rA,rB
lha
lhax
lhau
rD,d(rA)
rD,rA,rB
rD,d(rA)
址指令(偏移地址寻址)
加载半字并记录有效地址指令(寄存器寻址)
加载字指令(偏移地址寻址)
加载字指令(寄存器寻址)
加载字并记录有效地址指令(偏移地址寻址)
加载字并记录有效地址指令(寄存器寻址)
lhaux
lwz
lwzx
lwzu
lwzux
rD,rA,rB
rD,d(rA)
rD,rA,rB
rD,d(rA)
rD,rA,rB
(1)lbzrD,d(rA)?;EA=(rA|0)+d。从存储器读取EA地址的内容,并加载低8位到rD,rD的其他位清0。不影响其他寄存器。
(2)lbzurD,d(rA)?;EA=(rA)+d。从存储器读取EA地址一个字节的内容,并加载低8位到rD,rD的其他各位清零,有效地址EA存放在rA中。
(3)lbzuxrD,rA,rB?;EA=(rA)+(rB)。从存储器读取EA地址一个字节的内容,并加载低8位到rD,rD的其他各位清零,EA存放在rA中。如果rA=0或者rA=rD,则指令无效。
(4)lbzxrD,rA,rB?;EA=(rA|0)+(rB)。从存储器读取EA地址一个字节的内容,并加载低8位到rD,rD的其他各位清0。
(5)lharD,d(rA)?;EA=(rA|0)+d。从存储器EA处读取两个字节的数,并加载到rD的低16位。rD的其他位填充最高位的值。
(6)lhaxrD,rA,rB?;EA=(rA)+(rB)。从存储器EA处读取两个字节的数,并加载到rD的低16位。rD的其他位填充最高位的值。
(7)lhaurD,d(rA)?;EA=(rA)+d。从存储器EA处读取两个字节的数,并加载到rD的低16位。rD的其他位填充最高位的值。EA存放在rA中,如果rA=0或者rA=rD,则指令格式无效。
(8)lhauxrD,rA,rB?;EA=(rA)+(rB)。从存储器EA处读取两个字节的数,并加载到rD的低16位。rD的其他位填充最高位的值。EA存放在rA中,如果rA=0或者rA=rD,则指令格式无效。
(9)lhzrD,d(rA)?;EA=(rA|0)+d。从存储器EA处读取两个字节的数,并加载到rD的低16位。rD的其他位清零。
(10)lhzurD,d(rA)?;EA=(rA|0)+d。从存储器EA处读取两个字节的数,并加载到rD的低16位。rD其他位清零。EA存入rA,如果rA=0或者rA=rD,则指令格式无效。
(11)lhzuxrD,rA,rB?;EA=(rA)+(rB)。从存储器EA处读取两个字节的数,加载到rD的低16位,rD其他位清零。EA存入rA,如果rA=0或者rA=rD,则指令格式无效。
(12)lhzxrD,rA,rB?;EA=(rA|0)+(rB),从EA处读取两个字节的数,并加载到rD的低16位,将rD的其他位清零。
(13)lwzrD,d(rA)?;EA=(rA|0)+d,从EA处读取4个字节的数,并加载到rD。
(14)lwzurD,d(rA)?;EA=(rA)+d,从EA处读取4个字节的数,并加载到rD。rA=EA,如果rA=0或rA=rD,则指令格式无效。
(15)lwzuxrD,rA,rB?;EA=(rA)+(rB),从EA处读取4个字节的数,并加载到rD。rA=EA,如果rA=0或rA=rD,则指令格式无效。
(16)lwzxrD,rA,rB?;EA=(rA|0)+(rB),从EA处读取4个字节的数,并加载到rD。
整数多字存储/加载指令
名称
多字加载
多字存储
表3?整数多字存储/加载指令
助记符
lmw
stmw
语法格式
rD,d(rA)
rS,d(rA)
(1)lmwrD,d(rA)?;EA=rA+d。以EA起始的n个连续的字加载到通用寄存器GPRsrD到r31处,n=32-rD。EA必须为4的倍数,如果rA=0,则指令格式无效。指令执行时间长。
(2)stmwrS,d(rA)?;EA=rA+d。把通用寄存器从GPRsrS到GPRsr31,存储到以EA起始的n个连续的字存储器,EA必须是4的倍数。指令执行时间长。
转移指令
名称
无条件转移
条件转移
条件转移(转移目标地址由LR指出)
条件转移(转移目标地址由CTR指出)
指令的编码格式:
表4?分支控制指令
助记符
b(bablbla)
bc(bcabclbcla)
bclr(bclrl)
bcctr(bcctrl)
语法格式
target_addr
BO,BI,target_addr
BO,BI
BO,BI
(1)?无条件转移指令bx(bbablbla)
指令的语法格式:
btarget_addr(AA=0LK=0)
batarget_addr(AA=1LK=0)
bltarget_addr(AA=0LK=1)
blatarget_addr(AA=1LK=1)
如果AA=0,则转移目标地址为LI||0b00的值经符号位扩展后加上指令地址。
如果AA=1,则转移目标地址为LI||0b00的值经符号扩展后的值。
如果LK=1,则转移指令下一条指令的有效地址存放到连接寄存器。
(1)?条件转移指令bcx
指令编码格式:
指令语法格式:
bcBO,BI,target_addr(AA=0LK=0)
bcaBO,BI,target_addr(AA=1LK=0)
bclBO,BI,target_addr(AA=0LK=1)
bclaBO,BI,target_addr(AA=1LK=1)
BI字段表示条件寄存器CR中的位用于转移条件。BO字段操作码定义见表5。
BO
0000y
0001y
001zy
0100y
0101y
011zy
1z00y
1z01y
1z1zz
表5BO字段操作码定义
说明
计数器CTR减量,如果条件不成立则转移
计数器CTR减量,如果条件不成立则转移
如果条件不成立,则转移
计数器CTR减量,如果条件成立则转移
计数器CTR减量,如果条件成立则转移
如果条件成立则转移
计数器CTR减量,如果CTR!=0,则发生转移
计数器CTR减量,如果CTR=0,则发生转移
发生转移
注:位z表示该位可以被忽略,位y表示是不是条件转移
(2)?条件转移指令bclx(转移目标地址由LR指出)
指令的编码格式:
指令的语法格式:
bclrBO,BI(LK=0)
bclrlBO,BI(LK=1)
BI字段表示条件寄存器CR中的位用于转移条件。
BO字段操作码定义如表5所示。
转移目标地址为LR[0-29]||0b00。
如果LK=1,则转移指令下一条有效地址存放到连接寄存器。
(3)?条件转移指令bcctrx(转移目标地址由CTR指出)
指令的编码格式:
指令的语法格式:
bcctrBO,BI(LK=0)
bcctrlBO,BI(LK=1)
转移目标地址是CTR||0b00。
如果LK=1,则转移指令下一条指令的有效地址存放到连接寄存器。
如果减量计数器(BO[2]=0),指令格式无效,则转移到目标地址。
特殊寄存器传送指令
特殊寄存器传送指令如表6所示。
名称
读取机器状态寄存器
写入机器状态寄存器
读取特殊功能寄存器
写入特殊功能寄存器
读取段寄存器
写入段寄存器
间接读取段寄存器
间接写入段寄存器
读取时基寄存器
指令的编码格式:
指令的语法格式:
mfmsrrD
读取MSR的内容放入rD中,这是超级用户层指令,不影响其他寄存器。
(2)写入机器状态寄存器指令mtmsr
指令的编码格式:
指令的语法格式:
mtmsrrS
把rS的内容存入MSR中,这是超级用户指令。
(1)?读取特殊功能寄存器指令mfspr
表6?特殊寄存器传送指令
助记符
mfmsr
mtmsr
mfspr
mtspr
mfsr
mtsr
mfsrin
mtsrin
mftb
语法格式
rD
rS
rD,SPR
SPR,rS
rD,SR
SR,rS
rD,rB
rS,rB
rD,TBR
(1)?读取机器状态寄存器指令mfmsr
指令的编码格式:
指令的语法格式:
mfsprrD,SPR
指令操作:
n<—spr[5-9]||spr[0-4]
rD<—spr(n)
特殊功能寄存器(SPR)的编码如表7所示,将SPR的内容存入rD中。
编码n
1
8
9
指令的编码格式:
指令的语法格式:
mtsprspr,rS
把rS的内容存入到指定的特殊功能寄存器中。
(3)?读取段寄存器指令mfsr
指令的编码格式:
指令的语法格式:
mfsrrD,SR
指令操作:
rD<—SEGREG(SR)
将段寄存器SR的内容读入rD中,这是一个超级用户层指令。
(1)?写入段寄存器指令mtsr
指令的编码格式:
指令的语法格式:
mtsrSR,rS
将rS中的内容读入SR,这是一个超级用户层指令。
(2)?间接读取段寄存器指令mfsrin
指令的编码格式:
指令的语法格式:
mfsrinrD,rB
指令操作:
表7PowerPCUISASPR编码
spr
spr[5-9]
00000
00000
00000
spr[0-4]
00001
01000
01001
XER
LR
CR
寄存器名
(2)?写入特殊功能寄存器指令mtspr
rD<—SEGREG(rB[0-3])
由rB寄存器的0~3位选取的段寄存器的内容,复制到rDzhong。这是一个超级用户层指令。
(3)?间接写入段寄存器指令mtsrin
指令的编码格式:
指令的语法格式:
mtsrinrS,rB
指令操作:
SEGREG(rB[0-3])<—(rS)
将rS中的内容复制到由rB的0~3位所指定的寄存器中。这是一个超级用户层指令。
(4)?读取时基寄存器指令mftb
指令的编码格式:
指令的语法格式:
mftbrD,TBR
指令操作:
n<—tbr[5-9]||tbr[0-4]
ifn=268then
rD<—TBL
elseifn=269then
rD<—TBU
该指令的TBR编码如表8所示。
编码
268
269
系统调用指令
(1)?系统调用指令sc
指令的编码格式:
指令的使用:
sc指令调用操作系统去执行服务程序。当控制返回到一个执行系统调用的程序时,寄存器的内容依赖于程序提供的系统所使用的寄存器的约定。
TBR
tbr[5-9]
01000
01000
表8?指令mftb的TBR编码
寄存器名
tbr[0-4]
01100 TBL
01101 TBR
访问
用户
用户
跟在sc指令后面的有效指令地址被放在SRR0中。MSR中的位0、5~9和16~31被放在SRR1中对应的位置,SRR1中位1~4和10~15被设置为未定义值。当sc异常产生,异常处理程序更改MSR寄存器。异常处理程序到MSR[IP]形成基址加0xC00偏移量形成的地址去取下一条指令。
受影响的寄存器有:
依赖于系统服务、SRR0、SRR1及MSR。
(2)?中断返回指令rfi
指令的编码格式:
指令操作:
MSR[16-23,25-27,30-31]<—SRR1[16-23,25-27,30-31]
NIA<—ieaSRR0[0-29]||0b00
SRR1中的位0、5~9和16~31被放在MSR中对应的位置。如果新的MSR值没有使能任何未完的操作,则在MSR的控制下,从地址SRR0[0-29]||0b00取下一条指令。
指令的使用中受影响的寄存器为MSR。
看懂PowerPC汇编,需要如下3方面的知识:
??C指令集架构即PowerISA,可以从获得,包括寄存器定义,数据模型,寻址方式和指令定义以及指令助记符;
??CABI即应用程序二进制接口,即寄存器的使用规范和栈调用结构;
??CPseudo-ops,即.text,.alignn等汇编语言中常用的伪操作符。
??PowerPCISA分为3个级别即“Book”,分别对应于用户指令集体系结构,虚拟环境体系结构和操作环境体系结构。其中BookIII分化出了服务器版本BookIII-S(经典PowerPC架构)和嵌入式版本BookIII-E(专门为嵌入式优化的版本)。
??1.寄存器定义:
??PowerPC处理器寄存器分为2大类-专用寄存器和非专用寄存器。其中,非专用寄存器包括32个通用目的寄存器(GPR),32个浮点寄存器(FPR),条件寄存器(CR),浮点状态和控制寄存器(FPSCR);专用寄存器主要包括连接寄存器(LR),计数寄存器(CTR),机器状态寄存器(MSR)以及时间基准寄存器(TBL/TBU)等等。PPC4xx系列处理器还有DCR寄存器,需要用专门的指令访问。这里有两点需要注意:
??C处理器可以运行于两个级别,即用户模式和特权模式。用户模式下,仅有GPR,FPR,CR,FPSCR,LR,CTR,XER以及TBL/TBU可以访问。从PowerISA2.05开始,DCR寄存器也可以在通过用户模式DCR访问指令进行访问。
??C处理器没有专用的栈指针寄存器和PC指针寄存器,也就是说硬件不负责维护调用栈。
2.数据模型:
??PowerPC支持如下数据格式:byte,halfword,word,doubleword,quadword,同时默认支持big-endian
??注意:PowerPC习惯,msb(最高有效位)为bit0,lsb为bit31.
3.寻址方式
??PowerPC没有专门的IO操作指令,所有地址访问一视同仁,并且只支持地址和寄存器之间的访问。因此寻址方式非常简单,可以概括为2类6种:
??3.1Load/store/算术/逻辑/cache指令:
??a)寄存器间接寻址模式,通常写作RA或者RB;
??b)寄存器间接立即数索引寻址模式,即(基址寄存器+立即数偏移)寻址模式,通常写作d(RA);
??c)寄存器间接索引寻址模式(基址寄存器+偏移寄存器)寻址模式,通常写作RA,RB。
??注意:对于三种模式,若寄存器为GPR0,则其内容被忽略,并以0代替其内容。
??3.2跳转指令:
??a)立即数寻址模式;
??b)链接寄存器(LR)模式,即目的地址被保存在LR中;
??c)计数寄存器(CTR)模式,即目的地址保存在CTR中。
???注意:实际上还有一些特殊的跳转指令rfi/rfci/rfmci,其目的地址保存在SRR0/CSRR0/MCSRR0中。
4.指令定义和指令助记符:
??PowerPC指令的长度都是4字节,但是种类繁多,而且有些指令极其复杂。因此,通常情况下,PowerPC汇编编程中采用指令和助记符混用的方式。助记符主要用来简化内存访问、算术运算、逻辑运算等常用指令,例如用bnetarget代替bc4,2,target表示不为零则跳转。下面仅以一些常见的汇编代码片段来做一些简单的归纳,具体信息请参考相应的处理器core用户手册或者PowerISA。注意,cache和MMU指令会跟其实现一起介绍,此处不再赘述。
??4.1
???lis/**/
??oriRB,RA,/*RA与低16位(0x5678)相或后构成完整数据放进RA*/
???注意:PowerPC指令中,?i后缀表示立即数,s后缀表示左移16位。例如addi、addis、ori、oris等。这段代码也可以用来读取某个变量的值,只需要把立即数替换成变量名。
??2.从某个地址(0x56789abc)读取数据
???lisRA,0x56789abc@ha?/*?调整后的高16位(0x5679)*/
??lwzRB,0x56789abc@l?(RA)/*RA加上低16位(0xffff9abc)?构成完整数据地址,然后将其内容放进RB*/
??注意:
@l,@h和@ha:用于算术运算的操作数(包括addi的操作数)时,@l获取的是符号扩展的低16位数据(0xffff9abc),因此高16位必须进行根据bit15进行调整,而不能简单的使用@h来获取。??
load/store指令的通常格式为(l/st)(w/h/b)(z/br)(u/x)RA,…?.其中l代表读取数据到RA中;st代表将RA的内容写入内存;w/h/b分别代表针对word、halfword/byte进行操作;z仅用于读取数据,代表字或者半字读到寄存器中后将其高位清零(注意:对word的读取无意义,但必须加);br代表读取后或者存入前对数据进行字节序反转;u代表从某个内存地址读取数据后,同时更
新保存内存地址的寄存器;x代表使用寄存器间接索引寻址模式(基址寄存器+偏移寄存器)寻址模式(默认使用寄存器间接立即数索引寻址模式)??
这段代码也可以用来访问数组或者结构中的某个成员,或者指针指向的地址块中的数据,只需把立即数换成相应的数组名、结构名或者指针即可。
??3.入栈/出栈操作
??入栈:
????stwu1,–16(1)/*原始栈指针GPR1保存在新栈顶(原始栈指针减去16)*/
????mflr0/*LR暂存在GPR1*/
????stw0,20(1)/*保存LR到调用者的栈中*/
??出栈:
????lwz0,20(1)/*LR出栈*/
????mtlr0/*恢复LR*/
????addir1,r1,16/*销毁栈*/
???注意:栈定义会在ABI部分详细解释,此处不再赘述。
??4.循环
??li0,10/*循环次数暂存入GPR0*/
??mtctr0/*更新计数寄存器CTR*/
label:
??…/*需要重复执行的指令*/
??bdnzlabel/*递减计数器,不等于0则跳转到标号处重复执行*/
??注意:
label类似于C语言中的标号,因此在同一段代码中,不能重复。因此,习惯中使用数字标号来代替。数字标号作为跳转指令的目的地址时,通常在其后一个b表示向最近的低地址数字标号跳转,加f表示向最近的高地址数字标号跳转。例如beq1f或者blt2b。注意,标号,不管是数字形式还是字母形式,都可以用作一个代表标号所对应行的地址的变量使用。例如,可以用lisRA,1f@ha;lwzRB,1f@l(RA)可以用来获取标号1f处的指令内容。
跳转指令分为条件跳转和无条件跳转两种:
无条件跳转主要有b(跳转到相对地址)ba(跳转到绝对地址)blr(跳转到连接寄存器)bctr(跳转到计数寄存器)4种;(注意,rfi、rfci、rfmci等异常返回指令也可以看做是特殊的无条件跳转。)
条件跳转指令分为两种:需要配合比较指令/算术指令/逻辑运算指令使用的beq(相等或者为0则跳转)/bne(不等或者非0则跳转)/blt(小于则跳转)/bgt(大于则跳转)/ble(小于等于则跳转)/bge(大于等于则跳转)/bnl(不小于则跳转)/bng(不小于则跳转)等和需要配合计数寄存器CTR使用的bdz(CTR递减到0则跳转)/bdnz(CTR没有递减到0则跳转)等。
此外条件跳转指令还可以增加后缀a表示跳转到绝对地址;所有跳转指令增加后缀l表示同时更新连接寄存器(LR),用于子程序调用。
配合条件跳转指令使用的比较指令主要是cmp(l)w(i),其中l表示逻辑比较既无符号数比较,w表示比较2个word,i表示寄存器内容跟立即数进行比较;
配合条件跳转指令使用的算术指令必须加上后缀“.”用以表示更新条件寄存器CR,主要有add(寄存器内容相加)/addi(寄存器内容跟立即数相加)/addis(立即数左移16位后跟寄存器内容相加)和subi(寄存器内容减去立即数)/subis(寄存器内容减去左移16位后的立即数)/subf(从RB(第三个参数)中减去RA(第二个参数)的内容放入RT(第一个参数));
配合条件跳转指令使用的逻辑指令也必须加上后缀“.”用以表示更新条件寄存器CR,主要包括and(i)(s)/or(i)(s)。
CTR等专用寄存器必须通过专用命令mfsprrD,SPR和mtsprSPR,rS或者mfctr/mtctr/mflr/mtlr/mfspr/mtspr/mftbl/mftbu/mttbl/mttbu鞥助记符进行操作。此外,DCR寄存器必须通过mfdcr/mtdcr/mfdcrx/mtdcrx/mfdcrux/mtdcrux等进行操作。注意,后面4条DCR指令仅在PowerISA2.05及更高版本支持。
mrra,rb;copyrbtora.
5.强大的位操作指令
PowerPC有3条强大的位操作指令,几乎能实现你能想象的所有位操作。
a)rlwinm(.)rA,rS,SH,MB,ME?寄存器RS的内容循环左移立即数SH位,然后跟立即数MB和ME形成的MASK相与后放进RA
b)rlwnm(.)rA,rS,RB,MB,ME?类似于上一条指令,只是把左移的位数放到了寄存器RB中
c)rlwimi(.)rA,rS,SH,MB,ME?寄存器RS的内容循环左移立即数SH位,然后跟立即数MB和ME形成的MASK相与,再把RA的内容跟立即数MB和ME形成的MASK的补码相与,即清掉RA中MASK对应的位,最后把处理后的RS和RA的内容相或,放入RA中
注意:MASK形成的规则是,如果MB小于等于ME,则MB到ME之间的位全部置1,包括这两位,形成MASK;否则,MB到ME之间的位清0,其他位包括这两位置1,形成MASK。
下面给出几个例子:
?????20-23,并左移16位,从而得到0x06000000.?
rlwinmrA,rS,16,4,7?
0000(MASK[4,7])相与。
*?该指令可以用来抽取C语言代码或者寄存器中的位域。
?????28-31,并右移24位,从而得到0x00123456
rlwinmrA,rS,24,8,31
ffff(MASK[8,31])相与。
*该指令可以进行除数或者乘数为2的倍数的乘法/除法操作。
rlwinmrA,rS,0,7,5?
5678,然后与MASK0xfdffffff(MASK[7,5])相与。?
*该指令可以用来清除C语言代码或者寄存器中的位域。
rlwimirA,rS,16,8,15?
0000(MASK[8,15])相与得到0x00210000(MASK[8,15])的补码0xff00ffff相与,得到0x12005678;最后0x00210000跟0x1200
*该指令可以用来清除C语言代码或者寄存器中的某个位域,然后对该位域进行赋值的操作。
结语:
???PowerPC位操作指令如斯强大和美妙,可以说是PowerPC汇编中的神器,因此几乎出处可见他们的身影。谨以此作为PowerPC指令集架构的总结,希望能够引起大家对PPC汇编的兴趣。
mtocrf 0x80,r11
/*checkMSR[GS]withoutclobberingreg*/


发布评论