指令系统是计算机功能的抽象模型(不仅仅是关于指令功能的编码)
> 是软硬件的界面,所有软件最终都以指令的形式运行
> 体现了结构设计者对应用的深刻理解
> 一个指令系统可以有多种实现(低功耗、高性能、软件模拟…)
计算机产业的枢纽,产业生态的基础
①指令系统是计算机软硬件的重要标准:
-决定应用程序的二进制兼容(Wintel和AA都做到)
-是操作系统二进制兼容(Wintel做到、AA没做到)的重要因素
②指令系统影响系统性能和实现复杂性等:
-如RISC/CISC,32位/64位,媒体指令,向量指令等
-微结构对系统复杂性影响更大
(1)三大主流指令系统:X86、ARM、MIPS
-X86:每年几亿片,垄断PC和服务器市场,虽受到ARM的一些威胁,但桌面的垄断地位难以动摇,并通过凌动阻止ARM向高端渗透
-ARM:每年50-100亿片,在手持终端市场处于垄断地位,成功侵蚀MIPS的数字电视、机顶盒等市场,试图在云服务器等领域与X86竞争
-MIPS:每年5-10亿片,在传统市场如打印机、网络等仍有一定势力
(2)其他指令系统
-PowerPC:在汽车电子、工控、服务器领域还有一线生机
-Alpha、PA-RISC、Sparc、IA64主流市场机会不大
-RISC-V(开源指令集):想成为CPU中的Linux,道阻且长,巨头联手逼向低端MCU
(1)历史发展历程
-X86位宽从8位、16位、32位、64位不断发展
-功能从只支持定点、到浮点、到媒体指令、到向量指令
-向量指令又经历了MMX、SSE、SSE2、SSE3、SSE4、AVX等
(2)对指令发展新的要求
-多核结构要求指令增加对多核同步、通信和数据一致性的支持
-向量部件需要指令系统增加专门的向量指令
-媒体类应用要求指令系统增加对媒体编解码的专门支持
-云计算要求指令系统增加对虚拟机的支持;等等
(1)现状
①国外垄断企业设置了严密的知识产权壁垒,主要体现在包括指令系统在内的各类接口中
②目前IT产业正从单极化向多极化发展,要抓住机遇。目前自主软硬件推进效果明显,但我国软硬件力量过于薄弱,通过统一的自主指令系统可以迅速形成合力
(2)自主指令系统发展的可行路径
①先兼容后自主
-与国外指令兼容(MIPS、RISC等),在此基础上自主发展
-“可控”权:自主扩展和自主再授权
-“对等”权:协商扩展和反向授权
②先自主后兼容
-通过二进制翻译方式,运行主流指令系统的软件
-如Transmeta,IA64上运行IA32程序等
-Intel推出的基于X86的智能手机能运行Android上ARM的应用
③二者结合
-如基于MIPS/RISC5,并通过扩展实现对X86和ARM的兼容
①软硬件的界面;
②反映了结构设计者对计算机系统的认识;
-兼容性:对软件的包容性,长时间保持不变,如X86
-通用性:对软件的易用性,编译器和程序员觉得好用
-高效性:对硬件的易用性,便于CPU设计优化和不同性能的实现
-安全性:对软硬件安全的支持,支持通用操作系统,考虑不同的安全要求
(1)工艺技术
①. 早期的硬件昂贵,指令系统设计主要考虑如何减少硬件;
②. 集成度的提高(TLB、从32位到64位、SIMD媒体运算);
③. 现在如何发挥存储层次的效率,如何利用芯片面积;
-CPU与存储器的速度差距,指令系统应能较好地利用存储层次,如通过并行或流水容忍延迟(Cache管理指令、预取指令)
-工艺进一步发展,主频极限和功耗问题引起的多核结构需要特殊指令支持(多线程管理和同步)
(2)系统结构
-指令系统本身是系统结构发展的结果,如:从16位、到32位、到64位;SIMD指令、从单核到多核等
-指令系统的兼容性要求与系统结构发展的矛盾关系:
尽量不改变指令系统的前提下提高性能,如流水、多发射等
尽量保持兼容,如Intel的做法
-增加指令功能还是提高主频?(RISC vs. CISC vs. VLIW)
-并行性: SIMD、向量、多发射(兼容性好)
(3)操作系统
-操作系统专用的核心态指令和运行环境;
-多进程支持、虚空间:(页表与TLB的关系;页保护:读写权限)
-系统安全等级:(核心态和用户态管理)
-异常和中断处理(异常处理入口、ERET指令等)
-访存和访问I/O的区别;
-虚拟机:(支持多操作系统的快速切换)
(4)编译技术与程序设计语言
-指令是编译器的工作结果
早期的指令系统主要考虑如何便于编程
后期(如RISC)兼顾便于编程和实现效率
-指令功能
只有简单指令,甚至乘法都由加法和移位来实现
具有复杂指令,如除法、开方
更复杂的函数由库函数实现(如C库)
-寄存器和存储器分配
堆栈存放局部变量,全局数据区存放静态数据,堆存放动态数据
为有效使用图着色启发式算法,至少需要16个通用寄存器
-简单规整,提高编译效率
正交性,如所有访存指令都可用所有寻址方式
简化编译器取舍,如允许编译时确定常量,只提供基本的通用操作等
(5)应用程序
-应用适应性(指令归根结底为应用设计);
-兼容性:更新计算机时,兼容老的应用;
-RISC技术有利于指令流水线的高效实现(X86处理器内部也把CISC翻译成简单操作来优化流水线);
-VLIW技术用于指令流水线优化不是很成功
(1)复杂指令系统(Complex Instruction Set Computer,简称CISC)
其指令长度可变(x86: 1~15字节)
①. 早期的CPU都采用CISC结构:昂贵的软硬件系统要求兼容性,计算机应用的发展要求新增指令;
②. 像Intel,曾经的辉煌也导致历史包袱(需要对过去指令可能已经淘汰不用的指令提供兼容性)太重,指令集的臃肿导致实现复杂,降低了常用指令的执行效率
③. 程序中80%的指令只占指令集的20%,人们开始意识到:简单指令有利于高效实现,例如:X86指令通过内部译码后的微操作类似于RISC
(2)精简指令系统(Reduced Instruction Set Computer,简称RISC)
求掉包袱,轻装上阵:其指令长度比较固定
-核心思想:简化
简化指令功能:执行时间短
简化指令编码:译码简单
简化访存类型:访存和运算分开
-运用:Power、MIPS、ARM、SPARC、Alpha……
-现代指令系统对CISC和RISC的融合:
核心流水线采用RISC
包含复杂功能的宏指令
(3)超长指令字(Very Long Instruction Word,简称VLIW)
本质上是多条同时执行的指令的组合,其“同时执行”的特征由编译器指定,无需硬件进行判断
-它是指令集并行ILP的极端:
-运用:应用在早期的GPU中,GPGPU发展后遭弃用(AMD转向了SIMT的GCN架构)
TRACE、Itanium(IA-64)
(满足现代操作系统的发展需求)
(1)存储管理上
(2)运行级别的演变
(1)地址空间的组成
(2)地址空间的演变
①堆栈型(Stack):零地址指令
-两操作数在栈顶,运算操作不用指定操作数,结果写回栈顶。
②累加器型(Accumulator):单地址指令
-一个操作数由指令指定,一个操作数总在累加器中,结果也写回累加器
③寄存器型(Register):多地址指令
-Register-Register型、Register-Memory型、Memory-Memory型
不同类型指令功能举例:不同指令在指令系统完成C=A+B的指令序列(假设ABC在内存的不同单元中)
(3)指令系统类型的发展
①早期的计算机多用堆栈和累加器型指令
• 出于降低硬件复杂度的考虑
• 现在已经不用(Intel有点例外),JAVA字节码使用堆栈结构
②1980年代后的机器主要是寄存器型
• 访问寄存器比访问存储器快,便于编译器使用和优化
• 寄存器可以用来存放变量,减少访存次数
• 寄存器间的相关容易判断,易于实现流水线、多发射、乱序执行等
• X86通过把复杂指令翻译成类似于RISC的内部操作并使用RISC指令流水线技术提高性能,X86的向量指令也是寄存器型
③RISC的不断复杂化
• 内存离寄存器越来越远,以寄存器为中心的结构增加了不必要的数据搬运开销(如memcpy)
• 向量指令、超越函数指令、Transacitonal memory等
(4)附
①不同指令系统通用寄存器数量:
②MIPS寄存器空间:
③Linux/MIPS虚拟地址空间安排:
-有关IO空间的划分:
○ X86规定了独立的IO空间,使用专门的in/out指令来访问
○ EoMIPS/ARM不区分IO空间和内存空间,使用同样的访存指令
(1)数据类型
- 整数、实数、字符、十进制数
- 字节、半字、字、双字
- IEEE 754格式
(2)类型的表示
- 一般由操作码来区分不同类型
- 专门的类型标志
(3)数据类型的分布
(4)访存对象
1)存储器按字节编址:
-所有地址都是字节地址
-访问长度:字节、半字、字、双字
2)访存地址是否对齐( Aligned vs. Misaligned ):
-地址对齐简化硬件设计:如字地址最低两位为0 -跨数据通路边界的访问可能需要访问两次RAM
-如何支持不对齐访问(如串操作)
3)大尾端(Big Endian)和小尾端(Little Endian)
-Little Endian地址指向一个字的最右字节
-Big Endian 反之
综上所述:
①应至少支持以下寻址方式:Register、Immediate、Displacement、Register indirect;
②指令中常数位数:地址偏移量位数12-16位 ,立即数位数8-16位;
(2)常见指令操作
把简单指令做快点,其他慢一点没关系;
(1)需要考虑的因素
①. 操作码部分比较简单
②. 操作数的个数、类型对指令长度影响很大
③. 变长指令程序代码短、定长指令实现简单
(2)编码方法
①. 定长:RISC
②. 变长:VAX的指令1-53字节,其中ADD指令3-19字节,Intel的X86指令1-17字节
③. 混合:IBM 360/370,MIPS16,Thumb,TI TMS320C54x
(3)特点—RISC系统结构
①. 简单操作和简单寻址方式用得最多
-10种简单操作指令占96%
-寄存器, 立即数, 偏移寻址, 寄存器间接寻址四种寻址方式
②. 简单指令便于高效实现和使用
-load-store结构简化硬件设计,提高主频
-定长简化译码
-符合编译器“常用的做得快,少用的只要对”的原则
③. 硬件优化应充分考虑兼容性
-流水、多发射不改变指令系统
-流水、多发射技术在load-store指令系统上容易实现
(1)发展过程:现代X86处理器内部的核心也是RISC结构
(2)常见RISC指令系统比较:
①指令格式:
②寻址方式:
③指令功能:
(3)具体指令说明
1)Load/Store指令:
-对任何GPR和FPR进行存取操作
-通常R0总是为0
2)ALU指令:
-所有ALU指令都是寄存器型的
-ALU的常见操作有加、减、与、或、异或、移位、比较,乘除法在专门的部件进行
3)控制流指令:
-绝对跳转jump和相对转移branch
4)条件转移的条件判断:
5)系统管理指令
原子操作指令、存储管理指令、例外管理指令、共享存储同步指令等等
6)MIPS特色-非对齐访存指令LWR和LWL
①作用:边界不对齐的数据传送(小尾端)
②说明:
③举例:
如果没有它们,取一个不对齐的字需要10条指令,包括4个load/store并需要一个临时寄存器:
7)SPARC特色-寄存器窗口
①2-32个寄存器窗口,用于不同过程:
-8个全局寄存器用于存放全局变量
-24个局部寄存器:8个输入参数,8个局部变量,8个输出参数
-过程调用和退出不用把现场保留到存储器②SAVE和RESTORE指令:
-SAVE:功能同ADD,源寄存器来自调用过程(caller),目标寄存器来自被调用过程(callee),该指令自动修改寄存器窗口指针CWP–
-RESTORE:功能同ADD,源寄存器来自被调用过程(callee),目标寄存器来自调用过程(caller),该指令自动修改寄存器窗口指针CWP++
③AMD AM29000的局部寄存器窗口大小可变,全局寄存器64个
8)PowerPC特色-Link和Count寄存器
①寄存器说明:
-Link寄存器用于保存返回地址,实现快速过程调用
-Count寄存器用于循环计数,每次自动递减
②这两个寄存器还可以放转移地址
③ PowerPC其他特色:
-PowerPC不用Delay Slot
-Load和Store指令同时存取多个寄存器(多达32个)
-Load和Store字符串(变长或定长、对齐或不对齐)
9)PA-RISC的Nullification
①根据当前指令执行结果确定下一条指令是否执行(所有的转移指令和多数算术指令可用)
-如ADDB(Add and branch)指令在完成加法后,检查加法结果是否满足条件,如果不满足就转移。同时判断下一条指令(延迟槽)是否执行。
可以消除一些简单的转移指令:
②其它指令系统有条件移数指令如“CMOV”;
③后来演化为IA64的谓词技术:运算指令通过64个谓词寄存器决定结果是否保存
(4)Alpha和PowerPC比较
-PowerPC的load-with-update和store-with-update指令适合于数组运算,Alpha没有寄存器加寄存器的寻址方式,指向数组的指针每次分别递增;
-在Alpha中,循环次数由指针实现,在PowerPC中,有CTR专门用于保存循环次数
-PowerPC只需两条浮点指令:乘及乘加
-Alpha需要10条指令,比PowerPC多4条
-Alpha指令简单容易高效实现,主频也高