标题:
PPC入门与优化杂谈
[打印本页]
作者:
look_w
时间:
2017-10-24 15:34
标题:
PPC入门与优化杂谈
背景介绍
PowerPC于1991年IBM/MOTO/APPLE研制,大量应用于服务器(AIX / AS400系列及苹果系列服务器),家用游戏机(PS3, Wii, XBOX, GameCube),以及嵌入式(仅次于Arm/x86排第三)。PowerPC核心在于开放系统软件标准,其应用范围仅次于x86,是除去x86外最值得开发者了解的体系。
不需要写出非常高效的代码,但要了解基本效率原则;不需要大规模开发PPC程序,但需要时能写几段、调试时能看懂哪里错了。
本文将从对比x86入手,引入RISC及PowerPC体系概念,向读者介绍该体系指令集,常用优化方法和交叉编译环境及模拟器的搭建等内容。
PowerPC基础知识
1990年 IBM时任总裁 Kuehler说服了摩托罗拉公司和苹果公司与IBM公司共同参与制订 PowerPC体系结构。为了让 AS/400也成为其中一员,1991 / 1992年罗彻斯特实验室开始为 AS/400扩充并制订PowerPC的64
位结构。
----《罗彻斯特城堡》
大部分CPU指令集都可以分为:数据读写、数值计算、流程控制与设备管理四个部分,其中设备管理不属于介绍范围。开放系统软件标准在于硬件/软件只要符合该标准都能在 PowerPC下运行,也就是说先今有大量CPU虽然实现不一,但是他们在标准上都支持了 PowerPC体系,使得开发与接口更为方便。
PPC使用RISC(精简指令集),指令字长都是32bit,一条Intel指令往往可以由多条 PPC指令组合表示。Endian一般都是可调的,默认使用BE(Big Endian),同时PPC没有栈,也就是说应用程序需要自己实现相关操作。
常用术语介绍
常用寄存器
问题1:如何加载32位立即数?
在PPC下如何加载32位的立即数呢?RISC下PPC的每条指令都是4个字节定长。除去指令与寄存器参数编码,只有剩下16bit的长度用来描述立即数,比如立即数加载指令 LI:
LI rD, SIMM
立即数SIMM字段仅16位,如何表示32位?
答案:只有分两次载如,使用LIS(立即数载入并左移)和ADDI(立即数加法)分两次加载。因此32bit的立即数加载需要分两次完成:
LIS
R3, 0x1122
加载并左移16位
ADDI
R3, R3, 0x3344
再加上低16位
两条指令后,R3完成对 0x11223344的加载
特性:不一样的子程序调用
• f1:
子程序入口
•
blr
返回(跳转到LR地址)
• start:
•
bl
f1
调用f1(跳转并保存地址到LR)
•
li
r1, 1
设置r1 = 1
•
li
r3, 1
设置r3 = 1
•
sc
系统调用:结束程序
PPC使用了LR寄存器(Link Register)来完成:在bl指令跳转前,下条指令(li r1,1)的地址会被保存到LR而执行到f1中的blr时,系统会跳转到LR所表示的地址,完成返回。
数据读写指令
注意:LBZ R3, 0(R2)与LHZ R3,10(R2)并不全等同于MOV AL,[EBX]和MOV AX,[EBX+10]。前者将字节和半字加载到R3时顺便清空了高位,而后两条指令加载数据到EAX并不会清空高位。
第一个程序:Hello World !!
把下面的程序保存成 hello.s,并交叉编译:
# powerpc-eabi-as -gstabs hello.s -o hello.o
# powerpc-eabi-ld hello.o -o hello
• .
global
_start
/* 请将本程序保存成 hello.s */
• .
data
/* 后面将讲解如何在虚拟机中调试 */
• msg: .
asciz
"Hello, PowerPC World !!/n"
• len = . - msg
• .text
/* 代码部分开始 */
• _start:
•
li
%r0, 4
/* r0 = 4 */
•
li
%r3, 1
/* r3 = 1 */
•
lis
%r4, msg@ha
/* r4 = msg(high) << 16 */
•
addi
%r4, %r4, msg@l
/* r4 = r4 + msg(low) */
•
li
%r5, len
/* r5 = len */
•
sc
/* system call (print) */
•
li
%r0, 1
/* r0 = 1 */
•
li
%r3, 1
/* r3 = 1 */
•
sc
/* system call (exit) */
完成交叉编译后用 qemu模拟器执行:
# qemu-ppc hello
Hello, PowerPC World !!
关于如何在x86环境下交叉编译与调试,详细见第三部分的的“PowerPC编译调试”。
特殊寄存器操作
问题2:没有栈仅靠LR如何递归?
• f1:
•
mflr
r2
保存LR中记录的地址到r2
•
stw
r2, -8(r1)
记录r2的数值到MEM[r1-8]处
•
addi
r1, r1, -60
r1后移60个字节,完成进栈操作
• ….
•
addi
r1, r1, 60
r1前移60个字节,准备出栈
•
lwz
r2, -8(r1)
读出老的LR值到r2
•
mtfr
r2
将r2的内容复制到LR
•
blr
返回(跳转到LR地址)
• start:
• ….
虽然PPC没有直接提供栈相关指令(PUSH/POP/CALL/RET),应用程序却常用R1来模拟栈指针,实现多层调用时对LR的记录与恢复。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0