第2章 指令系统的设计
2. 1 指令系统结构的分类
2.1.1 指令系统结构的主要分类
区别不同指令系统结构的主要因素: CPU中用来存储操作数的存储单元的类型
CPU中用来存储操作数的存储单元有三种:
- 堆栈;
- 累加器;
- 通用寄存器组
根据存储操作数的存储单元将指令系统的结构分为三种类型:
- 堆栈结构
- 累加器结构
- 通用寄存器结构,根据操作数的来源不同,又可进一步分为:
- 寄存器-存储器结构(RM结构)
- 寄存器-寄存器结构(RR结构):也称为load-store结构,只有load指令和store指令能够访问存储器
对于不同类型的结构,操作数的位置、个数以及操作数的给出方式(显式或隐式)也会不同。
- 显式给出:用指令字中的操作数字段给出
- 隐式给出:使用事先约定好的单元
操作数的给出方式 | 说明 | 举例 |
---|
显式给出 | 用指令字中的操作数字段给出 | 通用寄存器结构 | 隐式给出 | 使用事先约定好的单元 | 堆栈结构(操作数是栈顶和次栈顶顶数据,通过PUSH/POP操作,结果保持在栈顶) 累加器结构(一个操作数默认在累加器中) |
不同指令系统结构的示例
例:表达式Z=X+Y 在4种类型指令系统结构上的代码。假设:X、Y、Z均保存在存储器单元中,并且不能破坏X和Y的值。
堆 栈 | 累加器 | 寄存器(RM型) | 寄存器(RR型) |
---|
push X | load X | load R1,X | load R1,X | push Y | add Y | add R1,Y | load R2,Y | add | store Z | store R1,Z | add R3,R1,R2 | pop Z | | | store R3,Z |
2.1.2 通用寄存器型结构
通用寄存器型结构是现代指令系统结构的主流,主要原因如下:
-
堆栈型和累加器型计算机的优点是指令字比较短,程序占用的空间比较小。但是,它们都有着难以克服的缺点。
- 在堆栈型机器中,不能随机地访问堆栈,难以生成有效的代码,而且对栈顶的访问是个瓶颈。
- 在累加器型的机器中,由于只有一个中间结果暂存器(累加器),所以需要频繁地访问在储器。
-
通用寄存器型结构在灵活性和提高性能方面有明显的优势
- 跟其它的CPU内部存储单元一样,寄存器的访问速度比存储器快。
- 对编译器而言,能更加容易、有效地分配和使用寄存器。
- 寄存器可以用来存放变量。
- 加快程序的执行速度(因为寄存器比存储器快)
- 减少对存储器的访问
- 用更少的地址位(相对于存储器地址来说)来对寄存器进行寻址,从而有效地减少程序的目标代码的大小。
根据ALU指令的操作数的两个特征对通用寄存器型结构进一步细分
- 3个操作数的指令:两个源操作数、一个目的操作数
- 2个操作数的指令:其中一个操作数既作为源操作数,又作为目的操作数。
ALU指令中存储器操作数的个数,可以是0~3中的某一个,为0表示没有存储器操作数。
ALU指令中操作数个数和存储器操作数个数的典型组合
ALU指令中存 储器操作数的个数 | ALU指令中操作数的最多个数 | 结构类型 | 机器实例 |
---|
0 | 3 | RR | MIPS,SPARC,Alpha,PowerPC,ARM | 1 | 2 | RM | IBM 360/370,Intel 80x86,Motorola 68000 | 1 | 3 | RM | IBM 360/370 | 2 | 2 | MM | VAX | 3 | 3 | MM | VAX |
根据ALU指令中存储器操作数的个数,可将通用寄存器型结构进一步细分为3种类型
- 寄存器-寄存器型(RR型)
- 寄存器-存储器型(RM型)
- 存储器-存储器型(MM型)
3种通用寄存器型结构的优缺点如下表所示,表中(m,n)表示指令的n个操作数中有m个存储器操作数。
指令系统结构类型 | 优 点 | 缺 点 |
---|
寄存器-寄存器型(0,3) | 指令字长固定,指令结构简洁,是一种简单的代码生成模型,各种指令的执行时钟周期数相近。 | 与指令中含存储器操作数的指令系统结构相比,指令条数多,目标代码不够紧凑,因而程序占用的空间比较大。 | 寄存器-存储器型(1,2) | 可以在ALU指令中直接对存储器操作数进行引用,而不必先用load指令进行加载。 容易对指令进行编码,目标代码比较紧凑。 | 指令中的两个操作数不对称。 在一条指令中同时对寄存器操作数和存储器操作数进行编码,有可能限制指令所能够表示的寄存器个数。 指令的执行时钟周期数因操作数的来源(寄存器或存储器)不同而差别比较大。 | 存储器-存储器型(2,2) 或(3,3) | 目标代码最紧凑,不需要设置寄存器来保存变量。 | 指令字长变化大,特别是3操作数指令。 而且每条指令完成的工作也差别很大。 对存储器的频繁访问会使存储器成为瓶颈 这种类型的指令系统结构现在已不用了。 |
2.2 寻址方式
2.2.1 寻址方式的定义
寻址方式:指令系统中如何形成所要访问的数据的地址。
-
寻址方式可以指明指令中的操作数是一个常数、一个寄存器操作数或者是一个存储器操作数。 -
对于存储器操作数来说,由寻址方式确定的存储器地址称为有效地址。 -
示例:Mem[Regs[R1]]:以寄存器R1中的内容作为地址的存储器单元中的内容
采用多种寻址方式可以显著地减少程序的指令条数,但可能增加计算机的实现复杂度以及指令的CPI。
立即数寻址方式和偏移寻址方式的使用频度最高。
2.2.2 立即数寻址方式
立即数寻址方式主要用于ALU指令、比较指令、给寄存器装入常数等。
对指令系统的结构设计而言,首先要确定的是所有的指令还是只有部分指令具有立即数寻址方式。
大约1/4的load指令和ALU指令采用了立即数寻址。
2.2.3 两种表示寻址方式的方法
- 将寻址方式编码于操作码中,由操作码描述相应操作的寻址方式。
- 适合:处理机采用load-store结构,寻址方式只有很少几种。
- 在指令字中设置专门的寻址字段,用以直接指出寻址方式。
- 灵活,操作码短,但需要设置专门的寻址方式字段,而且操作码和寻址方式字段合起来所需要的总位数可能会比隐含方法的总位数多。
- 适合:处理机具有多种寻址方式,且指令有多个操作数。
需要注意的问题:物理地址空间的信息如何存放:
- 信息宽度不超过主存宽度的信息必须存放在一个存储字内,不能跨边界。
- 必须做到:信息在主存中存放的起始地址必须是该信息宽度(字节数)的整数倍
- 满足以下条件
- 字节信息的起始地址为:X…XXXX
- 半字信息的起始地址为:X…XXX0
- 单字信息的起始地址为:X…XX00
- 双字信息的起始地址为:X…X000
- 存在存储空间的浪费 ,但保证访问速度。
2.3 指令系统的设计与优化
2.3.1 指令系统设计的基本原则
指令系统的设计
- 首先考虑所应实现的基本功能,确定哪些基本功能应该由硬件实现,哪些功能由软件实现比较合适。
- 包括
在确定哪些基本功能用硬件来实现时,主要考虑3个因素:速度、成本、灵活性。
- 硬件实现的特点:速度快、成本高、灵活性差
- 软件实现的特点:速度慢、价格便宜、灵活性好
对指令系统的基本要求
-
完整性:在一个有限可用的存储空间内,对于任何可解问题,编制计算程序时,指令系统提供的指令足够使用。
-
要求指令系统功能齐全、使用方便 -
下表为许多指令系统结构都包含的一些指令类型
- 前4类属于通用计算机系统的基本指令
- 对于最后4种类型的操作,不同指令系统结构的支持大不相同 。
操作类型 | 实 例 |
---|
算术和逻辑运算 | 算术运算和逻辑操作:加,减,乘,除,与,或等 | 数据传输 | load,store | 控制 | 分支,跳转,过程调用和返回,自陷等 | 系统 | 操作系统调用,虚拟存储器管理等 | 浮点 | 浮点操作:加,减,乘,除,比较等 | 十进制 | 十进制加,十进制乘,十进制到字符的转换等 | 字符串 | 字符串移动,字符串比较,字符串搜索等 | 图形 | 像素操作,压缩/解压操作等 |
-
规整性:主要包括对称性和均匀性。
- 对称性:所有与指令系统有关的存储单元的使用、操作码的设置等都是对称的。
- 例如:在存储单元的使用上,所有通用寄存器都要同等对待。在操作码的设置上,如果设置了A-B的指令,就应该也设置B-A的指令。
- 均匀性:指对于各种不同的操作数类型、字长、操作种类和数据存储单元,指令的设置都要同等对待。
- 例如:如果某机器有5种数据表示,4种字长,两种存储单元,则要设置5×4×2=40种同一操作的指令。
-
正交性:在指令中各个不同含义的字段,如操作类型、数据类型、寻址方式字段等,在编码时应互不相关、相互独立。 -
高效率:指指令的执行速度快、使用频度高。 -
兼容性:主要是要实现向后兼容,指令系统可以增加新指令,但不能删除指令或更改指令的功能。
指令系统的两种设计策略
在设计指令系统时,有两种截然不同的设计策略。(产生了两类不同的计算机系统 )
- CISC(复杂指令系统计算机)
- 增强指令功能,把越来越多的功能交由硬件来实现,并且指令的数量也是越来越多。
- RISC(精简指令系统计算机)
- 尽可能地把指令系统简化,不仅指令的条数少,而且指令的功能也比较简单。
2.3.2 控制指令
控制指令是用来改变控制流的。
- 跳转:当指令是无条件改变控制流时,称之为跳转指令。
- 分支:当控制指令是有条件改变控制流时,则称之为分支指令。
能够改变控制流的指令
根据控制指令的使用频度:改变控制流的大部分指令是分支指令(条件转移)。
分支条件的方法及其优缺点
名 称 | 检测分支条件的方法 | 优 点 | 缺 点 |
---|
条件码 (CC) | 检测由ALU操作设置的一些特殊的位(即CC) | 可以自由设置分支条件 | 条件码是增设的状态。而且它限制了指令的执行顺序,因为要保证条件码能顺利地传送给分支指令。 | 条件寄存器 | 比较指令把比较结果放入任何一个寄存器,检测时就检测该寄存器。 | 简单 | 占用了一个寄存器 | 比较与分支 | 比较操作是分支指令的一部分,通常这种比较是受到一定限制的。 | 用一条指令(而不是两条)就能实现分支 | 当采用流水方式时,该指令的操作可能太多,在一拍内做不完。 |
在控制指令中,必须给出转移的目标地址,而转移目标地址的表示:
- 最常用的方法
- 在指令中提供一个偏移量,由该偏移量和程序计数器(PC)的值相加而得出目标地址。(PC相对寻址)
- 优点
- 有效地减少表示该目标地址所需要的位数
- 位置无关(代码可被装载到主存的任意位置执行)
- 关键:确定偏移量字段的长度
- 模拟结果表明:采用4~8位的偏移量字段(以指令字为单位)就能表示大多数控制指令的转移目标地址了。
对于过程调用和返回
- 除了要改变控制流之外,可能还要保存机器状态。至少也得保存返回地址(放在专用的链接寄存器或堆栈中)。
- 过去有些指令系统结构提供了专门的保存机制来保存许多寄存器的内容。
- 现在较新的指令系统结构则要求由编译器生成load和store指令来保存或恢复寄存器的内容。
2.3.3 指令操作码的优化
2.3.3.1 指令的组成
指令由两部分组成:操作码、地址码(地址信息)
操作码包括:操作种类、操作数描述。
- 操作种类:加、减、乘、除、数据传送、移位、转移、输入输出、程序控制、处理机控制等
- 操作数描述:主要有,数据的类型:定点数、浮点数、复数、字符、字符串、逻辑数、向量;进位制类型:2进制、10进制、16进制;数据字长类型:字、半字、双字、字节
指令格式的设计:确定指令字的编码方式,包括操作码字段和地址码(地址信息)字段的编码和表示方式。
指令格式的优化:如何用最短的位数来表示指令的操作信息和地址信息。
2.3.3.2 基于哈夫曼编码指令操作码的优化
(一) 固定长操作码
所有指令使用相同的代码位数,其最小码长等于:
L
ˉ
=
l
i
=
⌈
log
2
n
⌉
\bar{L}=l_{i}=\left\lceil\log _{2} n\right\rceil
Lˉ=li=⌈log2n⌉ 式中
L
ˉ
\bar{L}
Lˉ 是平均码长,
l
i
l_{i}
li 是第
i
i
i种指令的码长,
n
n
n是指令总数。
-
优点:规整,译码简单。 -
缺点:浪费信息量。
例:已知 n = 15,求定长编码的最小平均码长。
L
ˉ
=
⌈
l
o
g
2
n
⌉
=
⌈
l
o
g
2
15
⌉
=
4
\bar{L} = \left\lceil log_{2}n \right\rceil = \left\lceil log_{2}15 \right\rceil = 4
Lˉ=⌈log2n⌉=⌈log215⌉=4
(二) Huffman编码法
根据Huffman编码法的原理,采用最优Huffman编码法表示的操作码的最短平均长度可通过下式计算,也就是操作码优化的程度可以用信息熵来衡量:
H
=
−
∑
i
=
1
n
p
i
⋅
l
o
g
2
p
i
H = - \sum_{i=1}^{n} p_{i} \cdot log_{2} p_i
H=−i=1∑npi⋅log2pi 其中:
P
i
P_{i}
Pi表示第
i
i
i种操作码在程序中出现的概率,表示用二进制编码表示
n
n
n个码点时,理论上的最短平均编码长度 。
固定长操作码相对于最优Huffman操作码的信息冗余量为:
R
=
1
−
−
∑
i
=
1
n
p
i
⋅
l
o
g
2
p
i
⌈
log
2
n
⌉
R = 1 - \frac{- \sum_{i=1}^{n} p_{i} \cdot log_{2} p_i}{\left\lceil\log _{2} n\right\rceil}
R=1−⌈log2n⌉−∑i=1npi⋅log2pi 具体的**构造huffman树的方法**
- 将各事件按其使用频度从小到大依次排列 ;
- 每次从中选择两个频度值最小的结点,将其合并成一个新的结点,并把新结点画在所选结点的上面,
- 然后用两条边把新结点分别与那两个结点相连。
- 新结点的频度值是所选两个结点的频度值的和。
- 把新结点与其他剩余未结合的结点一起,再以上面的步骤进行处理,反复进行,直到全部结点都结合完毕、形成根结点为止。
Huffman编码的操作码优缺点:
- 优点:平均长度最短, 信息的冗余量最小。
- 缺点:操作码长度很不规整,硬件译码困难,与地址码共同组成固定长的指令比较困难。
(三) 扩展编码法
为了便于分级译码,一般都采用等长扩展码。(在早期的计算机上)
例如:15/15/15法和8/64/512法
- 选用哪种编码法取决于指令使用频度pi的分布。
- 衡量标准:看哪种编码法能使平均码长最短。
如下图所示
2.3.4 指令字格式的优化
2.3.4.1 存在的问题
如果指令字的宽度固定,地址码的长度和个数固定,则操作码的缩短不能带来好处,只是使指令字中出现空白浪费。
2.3.4.2 采用地址个数可变和/或地址码长度可变的方案
- 利用操作码缩短所带来的好处
- 最常用的操作码最短,其地址字段个数最多。
- 能够使指令的功能增强,从总体上减少所需的指令条数 。
2.3.4.3考虑因素
- 计算机中寄存器的个数和寻址方式的数目对机器的指令字长有很大的影响;
- 指令字的平均长度增加了,程序的平均长度也就增加了;
- 在指令系统的设计中,要在指令字长与寄存器的个数以及寻址方式的个数之间进行折中。
2.3.4.4 指令系统的3种编码格式
- 可变长度编码格式
- 当指令系统的寻址方式和操作种类很多时,这种编码格式是最好的。
- 用最少的二进制位来表示目标代码。
- 可能会使各条指令的字长和执行时间相差很大。
- 固定长度编码格式
- 将操作类型和寻址方式一起编码到操作码中。
- 当寻址方式和操作类型非常少时,这种编码格式非常好。
- 可以有效地降低译码的复杂度,提高译码的速度。
- 大部分RISC的指令系统均采用这种编码格式。
- 混合型编码格式
- 提供若干种固定的指令字长。
- 以期达到既能够减少目标代码长度又能降低译码复杂度的目标。
|