第2章 计算机指令集结构 曲冠南 qugnStu@live.com http://cc.jlu.edu.cn/ComputerArchitecture.html
第二章课程安排 小节 章节名 重点内容 2.1 指令集结构的分类 堆栈、累加器、通用寄存器(RR、RM);这三种指令各自优缺点 2.2 2.2 寻址方式 操作数寻址方式 2.3 指令及结构的功能设计 设计的基本要求(完整性、规整性、高效性、兼容性)、CISC、RISC 2.4 操作数的大小和类型 数据表示 2.5 指令格式的设计 操作码+操作数(地址码) 2.6 MIPS指令系统
2.1 指令集结构的分类 区别不同指令集结构的主要因素 CPU中用来存储操作数的存储单元的类型 CPU中用来存储操作数的存储单元的主要类型 堆栈 累加器 通用寄存器组 将指令集结构分为三种类型
堆栈结构 累加器结构 通用寄存器结构 2.1 指令集结构的分类 根据操作数的来源不同,又可进一步分为: 寄存器-存储器结构(RM结构) (操作数可以来自存储器 ) 寄存器-寄存器结构(RR结构) (所有操作数都是来自通用寄存器组) 也称为load-store结构,这个名称强调:只有load指令和store指令能够访问存储器。
对于不同类型的指令集结构,操作数的位置、个数以及操作数的给出方式(显式或隐式)也会不同。 2.1 指令集结构的分类 对于不同类型的指令集结构,操作数的位置、个数以及操作数的给出方式(显式或隐式)也会不同。 显式给出:用指令字中的操作数字段给出 隐式给出:使用事先约定好的存储单元
4种指令集结构的操作数的位置以及结果的去向 灰色块:操作数 黑色块:结果 TOS(Top Of Stack):栈顶
假设:A、B、C均保存在存储器单元中,并且不能 破坏A和B的值。 2.1 指令集结构的分类 例: 表达式C=A+B在4种类型指令集结构上的代码。 假设:A、B、C均保存在存储器单元中,并且不能 破坏A和B的值。 堆 栈 累加器 寄存器(RM型) 寄存器(RR型) push A load A load R1,A push B add B add R1,B load R2,B add store C store R1,C add R3,R1,R2 pop C store R3,C 从指令本身的规整性、是否访问存储器、程序的长短、编译的灵活性等方面分析如上四段代码。 如果实现(A+B)-(C+D)+(E+F)呢?
通用寄存器结构 现代指令集结构的主流 在灵活性和提高性能方面有明显的优势 2.1 指令集结构的分类 提高访问速度 对编译器而言,能更加容易、有效地分配和使用 寄存器,例如,计算(A*B)-(C*D)-(E*F) 对寄存器进行寻址,减少地址位,从而有效地减少程序的目标代码的大小。
根据ALU指令的操作数的两个特征对通用寄存器型指 令集结构进一步细分 2.1 指令集结构的分类 根据ALU指令的操作数的两个特征对通用寄存器型指 令集结构进一步细分 操作数来源 -- RR(load-store)、RM、MM(理论上存在) ALU指令操作数个数 – 3个、2个 ALU指令中存储器操作数的个数 表 2.2: 给出ALU指令中操作数个数和存储器操作个数的组合; 表 2.3: 3种通用寄存器型指令集结构的优缺点,其中(m,n)表示指令的n个操作数中有m个存储器操作数;
表2.2 ALU指令中操作数个数和存储器操作数个数的典型组合 储器操作数的个数 ALU指令中 操作数的个数 结构 类型 实例 3 或 2 RR Add R1, R2, R3 典型机型:MIPS,SPARC,Alpha,PowerPC,ARM 1 2 RM Add R1, (1010) 典型机型:IBM 360/370,Intel 80x86,Motorola 68000 3 Add R1, R2, (1010) 典型机型:IBM 360/370 MM Add (1010), (1100) 典型机型:VAX Add(1110), (1010),(1100)
表2.3 三种常见的通用寄存器计算机的优缺点 – 定性分析 指令集结构类型 优 点 缺 点 寄存器-寄存器型 (0,3) 指令字长固定,指令结构简洁,是一种简单的代码生成模型,各种指令的执行时钟周期数相近 与指令中含存储器操作数的指令集结构相比,指令条数多,目标代码不够紧凑,因而程序占用的空间比较大 寄存器-存储器型 (1,2) 可以在ALU指令中直接对存储器操作数进行引用,而不必先用load指令进行加载。容易对指令进行编码,目标代码比较紧凑 指令中的两个操作数不对称。在一条指令中同时对寄存器操作数和存储器操作数进行编码,有可能限制指令所能够表示的寄存器个数。指令的执行时钟周期数因操作数的来源(寄存器或存储器)不同而差别比较大 存储器-存储器型 (2,2) 或(3,3) 目标代码最紧凑,不需要设置寄存器来保存变量 指令字长变化很大,特别是3操作数指令。而且每条指令完成的工作也差别很大。对存储器的频繁访问会使存储器成为瓶颈。这种类型的指令集结构现在已不用了
2.2 寻址方式 一种指令集结构如何确定所要访问的数据的地址? 当前的指令集结构中所采用的一些操作数寻址方式 一些标记 :赋值操作 Mem:存储器 Regs:寄存器组 方括号:表示内容 Mem[ ]:存储器的内容 Regs[ ]:寄存器的内容 Mem[Regs[R1]]:以寄存器R1中的内容作为地址的 存储器单元中的内容
寻址方式 指令实例 含 义 寄存器寻址 立即值寻址 偏移寻址 寄存器间接寻址 索引寻址 直接寻址或 绝对寻址 存储器间接寻址 自增寻址 含 义 寄存器寻址 Add R4 , R3 Regs[R4]←Regs[R4]+Regs[R3] 立即值寻址 Add R4 , #3 Regs[R4]←Regs[R4]+3 偏移寻址 Add R4 , 100(R1) Regs[R4]←Regs[R4]+Mem[100+Regs[R1]] 寄存器间接寻址 Add R4 , (R1) Regs[R4]←Regs[R4]+Mem[Regs[R1]] 索引寻址 Add R3 , (R1 + R2) Regs[R3]←Regs[R3]+Mem[Regs[R1]+Regs[R2]] 直接寻址或 绝对寻址 Add R1 , (1001) Regs[R1]←Regs[R1]+Mem[1001] 存储器间接寻址 Add R1 , @(R3) Regs[R1]←Regs[R1]+Mem[Mem[Regs[R3]]] 自增寻址 Add R1 , (R2)+ Regs[R1]←Regs[R1]+Mem[Regs[R2]] Regs[R2]←Regs[R2]+d 自减寻址 Add R1, -(R2) Regs[R2]←Regs[R2]-d Regs[R1]←Regs[R1]+Mem[Regs[R2]] 缩放寻址 Add R1 , 100(R2)[R3] Regs[R1]←Regs[R1]+Mem[100+Regs[R2]+Regs[R3]*d]
采用多种寻址方式可以显著地减少程序的指令条数 2.2 寻址方式 采用多种寻址方式可以显著地减少程序的指令条数 但可能增加计算机的实现复杂度以及指令的CPI
立即数寻址方式和偏移寻址方式的使用频度最高。 2.2 寻址方式 各种寻址方式的使用情况统计结果 在VAX机器上运行gcc、Spice和Tex 基准程序 立即数寻址方式和偏移寻址方式的使用频度最高。
大约1/4的load指令和ALU指令采用了立即数寻址。 2.2 寻址方式 立即数寻址方式 立即数寻址方式的使用频度 指令类型 使用频度 整型平均 浮点平均 load指令 23% 22% ALU指令 25% 19% 所有指令 21% 16% 大约1/4的load指令和ALU指令采用了立即数寻址。 实验环境:在load-store结构的机器(Alpha)上运行SPEC CPU2000基准程序
2.2 寻址方式 立即数的取值范围
2.2 寻址方式 最常用的是较小的立即数; 有时也会用到较大的立即数(主要是用于地址计算)。 在指令集结构设计中,至少要将立即数的大小设置 为8~16位。 在VAX机(支持32位立即数)上做过类似的统计,结果 表明20%~25%的立即数超过16位。
2.2 寻址方式 偏移量的取值范围 在load-store结构的机器(Alpha)上运行SPEC CPU2000基准程序
从该图可以看出: 程序所使用的偏移量大小分布十分广泛 较小的偏移量和较大的偏移量均占有相当大 的比例 2.2 寻址方式 主要是因为在存储器中所保存的数据并不是十分 集中,需要使用不同的偏移量才能对其进行访问。 较小的偏移量和较大的偏移量均占有相当大 的比例
2.3 指令集结构的功能设计 指令集结构的功能设计 确定软、硬件功能分配,即确定哪些基本功能应该由硬件实现,哪些功能由软件实现比较合适。 在确定哪些基本功能用硬件来实现时,主要考虑3个因素:速度、成本、灵活性 硬件实现的特点 速度快、成本高、灵活性差 软件实现的特点 速度慢、价格便宜、灵活性好
完整性:在一个有限可用的存储空间内,对于任何可解的问题,编制计算程序时,指令集所提供的指令足够用。 2.3 指令集结构的功能设计 对指令集的基本要求 完整性、规整性、高效率、兼容性 完整性:在一个有限可用的存储空间内,对于任何可解的问题,编制计算程序时,指令集所提供的指令足够用。 要求指令集功能齐全、使用方便 下表为许多指令集结构都包含的一些指令类型 前4类属于通用计算机系统的基本指令 对于最后4种类型的操作,不同指令集结构的支 持大不相同 。
算术运算和逻辑操作:加,减,乘,除,与,或等 2.3 指令集结构的功能设计 操作类型 实 例 算术和逻辑运算 算术运算和逻辑操作:加,减,乘,除,与,或等 数据传输 load,store 控制 分支,跳转,过程调用和返回,自陷等 系统 操作系统调用,虚拟存储器管理等 浮点 浮点操作:加,减,乘,除,比较等 十进制 十进制加,十进制乘,十进制到字符的转换等 字符串 字符串移动,字符串比较,字符串搜索等 图形 像素操作,压缩/解压操作等
规整性:主要包括对称性和均匀性。 高效率:指令的执行速度快、使用频度高。 2.3 指令集结构的功能设计 对称性:操作码与寻址方式 所有的存储单元和寄存器都同等对待 操作码的设置是对称的 例如:设置了A-B指令,就应该设置B-A指令 均匀性:操作码与数据大小、类型 一种操作性质的指令可以支持各种数据类型、字长和数据存储单元。 例如:如果某机器有5种数据表示,4种字长,两种存储单 元,则要设置5×4×2=40种同一操作的指令。 有限的规整性。 高效率:指令的执行速度快、使用频度高。
在设计指令集结构时,有两种截然不同的设计策略。 (产生了两类不同的计算机系统 ) CISC(复杂指令集计算机) 2.3 指令集结构的功能设计 在设计指令集结构时,有两种截然不同的设计策略。 (产生了两类不同的计算机系统 ) CISC(复杂指令集计算机) 增强指令功能,把越来越多的功能交由硬件来实 现,并且指令的数量也是越来越多。 RISC(精简指令集计算机) 尽可能地把指令集简化,不仅指令的条数少,而且 指令的功能也比较简单。
2.3.1 CISC指令集结构的功能设计 CISC结构追求的目标 强化指令功能,减少程序的指令条数,以达 到提高性能的目的。 2.3 指令集结构的功能设计 2.3.1 CISC指令集结构的功能设计 CISC结构追求的目标 强化指令功能,减少程序的指令条数,以达 到提高性能的目的。 增强指令功能主要是从以下几个方面着手: 面向目标程序增强指令功能 思想:对大量目标程序及其执行情况进行统计,找出使用频繁的、执行时间长的指令或者指令串 进行优化 --硬件加速或者设置新指令。 增强运算型指令的功能 – 如sin(), cos()… 增强数据传送指令的功能 – 如 成组传送… 增强程序控制指令的功能 – 条件转移,跳转… 丰富的程序控制指令为编程提供了多种选择。
例如:循环在程序中占有相当大的 比例,所以在指令上提供专 门的支持。 2.3 指令集结构的功能设计 循环控制部分通常用3条指令完成: 一条加法指令 一条比较指令 一条分支指令 在IBM270中,设置循环控制指令,用一条指令完成上述3条指令的功能。 一般循环程序的结构
高级语言与一般的机器语言的语义差距非常大,为高级语言程序的编译带来了一些问题。 2.3 指令集结构的功能设计 面向高级语言的优化实现来改进指令集 (缩小高级语言与机器语言的语义差距) 高级语言与一般的机器语言的语义差距非常大,为高级语言程序的编译带来了一些问题。 (1)编译器本身比较复杂。 (2)编译生成的目标代码比较难以达到很好的优化。
增加功能 2.3 指令集结构的功能设计 让高级语言成为 机器的汇编语言 举个例子: a = b+c; (高级语言) Load r1, b; Load r2, c; Add r3, r1, r2; Store r3, a; 让高级语言成为 机器的汇编语言
面向操作系统的优化实现改进指令集 2.3 指令集结构的功能设计 操作系统和计算机系统结构是紧密联系的,操作系 统的实现在很大程度上取决于系统结构的支持。 指令集对操作系统的支持主要有: 处理机工作状态和访问方式的切换。 进程的管理和切换。 存储管理和信息保护。 进程的同步与互斥,信号灯的管理等。 支持操作系统的有些指令属于特权指令,一般用户 程序是不能使用的。
2.3.2 RISC指令集结构的功能设计 CISC指令集结构存在的问题 (1979年开始,Patterson等人的研究) 2.3 指令集结构的功能设计 2.3.2 RISC指令集结构的功能设计 CISC指令集结构存在的问题 (1979年开始,Patterson等人的研究) 各种指令的使用频度相差悬殊 据统计:只有20%的指令使用频度比较高,占运 行时间的80%,而其余80%的指令只在20%的运行时 间内才会用到。 使用频度高的指令也是最简单的指令。
Intel 80x86最常用的10条指令 执行频度排序 80x86指令 指令执行频度(占执行指令总数的百分比) 1 load 22% 2 条件分支 20% 3 比较 16% 4 store 12% 5 加 8% 6 与 6% 7 减 5% 8 寄存器-寄存器间数据移动 4% 9 调用子程序 1% 10 返回 合 计 95%
指令集庞大,指令条数很多,许多指令的功能又 很复杂,使得控制器硬件非常复杂。 导致的问题: 2.3 指令集结构的功能设计 指令集庞大,指令条数很多,许多指令的功能又 很复杂,使得控制器硬件非常复杂。 导致的问题: 占用了大量的芯片面积(如占用CPU芯片总面积的 一半以上),给VLSI设计造成很大的困难; 增加了研制时间和成本,容易造成设计错误。 许多指令由于操作繁杂,其CPI值比较大,执行 速度慢。采用这些复杂指令有可能使整个程序的 执行时间反而增加。 由于指令功能复杂,规整性不好,不利于采用流 水技术来提高性能。
设计RISC机器遵循的原则 指令条数少而简单。只选取使用频度很高的指令,在此基础上补充一些最有用的指令。 2.3 指令集结构的功能设计 设计RISC机器遵循的原则 指令条数少而简单。只选取使用频度很高的指令,在此基础上补充一些最有用的指令。 采用简单而又统一的指令格式,并减少寻址方式;指令字长都为32位或64位。 指令的执行在单个机器周期内完成。 (采用流水线机制) 只有load和store指令才能访问存储器,其他指令的操作都是在寄存器之间进行。 (即采用load-store结构) 大多数指令都采用硬连逻辑来实现。 强调优化编译器的作用,为高级语言程序生成优化的代码。 充分利用流水技术来提高性能。
2.3 指令集结构的功能设计 早期的RISC微处理器 1981年 ,Berkeley分校的Patterson 等人的32位微处理器RISC I : 31条指令,指令字长都是32位,78个通用寄存器,时钟频率为8 MHz; 控制部分所占的芯片面积只有约6%。商品化微处理器MC68000和Z8000分别为50%和53%; 性能比MC68000和Z8000快3~4倍。 1983年的RISCⅡ: 指令条数为39,通用寄存器个数为138,时钟频率为12 MHz。 后来发展成了Sun公司的SPARC系列微处理器。 1981年,Stanford大学Hennessy等人的MIPS 后来发展成了MIPS Rxxx系列微处理器。 IBM的801
2.3 指令集结构的功能设计 共同特点: 采用load-store结构 指令字长为32位 采用高效的流水技术
2.3.3 控制指令 控制指令是用来改变控制流的。 跳转:当指令是无条件改变控制流时,称之为跳转指令。 2.3 指令集结构的功能设计 2.3.3 控制指令 控制指令是用来改变控制流的。 跳转:当指令是无条件改变控制流时,称之为跳转指令。 分支:当控制指令是有条件改变控制流时,则称之为分支指令。 能够改变控制流的指令 分支 跳转 过程调用 过程返回
改变控制流的大部分指令是分支指令(条件转移)。 2.3 指令集结构的功能设计 控制指令的使用频度 (load-store型指令集结构的机器,基准程序为SPEC CPU2000) 指令类型 使用频度 整型平均 浮点平均 调用/返回 19% 8% 跳转 6% 10% 分支 75% 82% 改变控制流的大部分指令是分支指令(条件转移)。
常用的3种表示分支条件的方法及其优缺点 名 称 检测分支条件的方法 优 点 缺 点 条件码 (CC) 优 点 缺 点 条件码 (CC) 检测由ALU操作设置的一些特殊的位(即CC) 可以自由设置分支条件 条件码是增设的状态。而且它限制了指令的执行顺序,因为要保证条件码能顺利地传送给分支指令 条件寄存器 比较指令把比较结果放入任何一个寄存器,检测时就检测该寄存器 简单 占用了一个寄存器 比较与分支 比较操作是分支指令的一部分,通常这种比较是受到一定限制的 用一条指令(而不是两条)就能实现分支 当采用流水方式时,该指令的操作可能太多,在一拍内做不完
转移目标地址的表示 最常用的方法 优点 关键:确定偏移量字段的长度 2.3 指令集结构的功能设计 在指令中提供一个偏移量,由该偏移量和程序计数 器(PC)的值相加而得出目标地址。 (PC相对寻址) 优点 有效地减少表示该目标地址所需要的位数。 位置无关(代码可被装载到主存的任意位置执行)。 关键:确定偏移量字段的长度 模拟结果表明:采用4~8位的偏移量字段(以指令字为单位)就能表示大多数控制指令的转移目标地址了。
除了要改变控制流之外,可能还要保存机器状态,至少也得保存返回地址(放在专用的链接寄存器或堆栈中)。 2.3 指令集结构的功能设计 过程调用和返回 除了要改变控制流之外,可能还要保存机器状态,至少也得保存返回地址(放在专用的链接寄存器或堆栈中)。 过去有些指令集结构提供了专门的保存机制来保存许多寄存器的内容。 现在较新的指令集结构则要求由编译器生成load和store指令来保存或恢复寄存器的内容。 注意:什么是机器的状态? 当前使用的一系列寄存器的状态
2.4 操作数的类型和大小 数据表示:计算机硬件能够直接识别、指令集可以直接调用的数据类型; 数据结构:软件进行处理和实现的各种数据类型。 3个问题: 类型? 大小? CPU如何得知类型和大小? 软硬件取舍折中的问题 类型? 简单数据类型:整型、浮点、字符、字符串、布尔、十进制、向量、堆栈; 数据结构:树形、队列、图 大小? 字节、半字、字、双字 CPU如何得知类型和大小: 在操作码中指出 在操作数中指出
2.5 指令集格式的设计 操作码 地址码1 地址码2 指令集格式的设计原则 指令= 操作码+地址 格式优化设计的目标有两个: (1)节省程序的存储空间;(短) (2)指令格式要尽量规整,以减少硬件译码的复杂度。(整) 影响以上设计目标的可能有哪些因素? 操作码 地址码1 地址码2
(2)地址码域长度 个数、操作数大小类型、寻址方式 2.5 指令集格式的设计 矛盾的焦点 : (1)操作码长度 |指令集|、编码方法 (2)地址码域长度 个数、操作数大小类型、寻址方式
2.5 指令集格式的设计 2. 操作码的设计和优化 操作码的表示方法通常有三种: 固定长度操作码 Huffman编码法 扩展编码法
2.5 指令集格式的设计 Huffman压缩的思想 高概率指令的操作码用较短的位数表示,低概率指令的操作码用较长的位数表示,就可以使得指令操作码的平均长度较短。所以指令操作码的优化的前提是知道各条指令在程序中出现的概率。
补充: Huffman编码法 操作码表示的信息冗余量 其中H是信息熵 采用固定长度操作码时 信息冗余量=(3-2.17)/3=0.28
1)将所有指令的使用频度由小到大排序,每个频度作为一个节点: 补充: Huffman编码法 Huffman树的生成方法: 1)将所有指令的使用频度由小到大排序,每个频度作为一个节点: 2)选择其中频度最小的两个节点,将它们合并成一个新的节点,新节点的频度是这两个节点频度的和;3)将新节点按频度大小插入未合并的节点中; 4)再从未合并的节点中选择两个频度最小节点,将它们合并成一个新的节点; 5)如此继续进行,直至全部节点合并完成形成根节点; 6)之后,从根节点开始,向下延伸,分出两个分支,分别用一位代码的“0”和“1”来表示。
补充: Huffman编码法 I7 0.03 I6 I5 0.04 I4 0.05 I3 0.15 I2 0.30 I1 0.40 0.09 0.06 0.60 1.00 1 从根节点开始,沿线到达各指令所经过的代码序列就构成该指令的操作码。短码不可能是长码的前缀。 I1:0 I2:10 I3:110 I4:11100 I5:11101 I6:11110 I7:11111
无法达到理论值2.17,是因为操作码必须用整数位表示。 补充: Huffman编码法 Huffman编码指令平局长度 L=0.40×1+0.30×2+0.15×3+0.05×5 +0.04×5+0.03×5+0.03×5 =2.20 信息冗余量为 (2.20-2.17)÷2.20≈1.36% 无法达到理论值2.17,是因为操作码必须用整数位表示。
补充: Huffman编码法 扩展Huffman编码 介于固定长度操作码编码和Huffman编码之间的一种编码方式,操作码长度虽不是定长的,但是只有几种码长,但仍然是概率高的指令用短操作码表示,概率低的指令用短操作码表示。仍然符合Huffman压缩的思想。
扩展Huffman编码 扩展Huffman编码指令平局长度 L=0.40×2+0.30×2+0.15×2+ I1:00 I2:01 I3:10 I4:1100 I5:1101 I6:1110 I7:1111 扩展Huffman编码 扩展Huffman编码指令平局长度 L=0.40×2+0.30×2+0.15×2+ 0.05×4+0.04×4+0.03×4+0.03×4 =2.30 信息冗余量为 (2.30-2.17)÷2.30≈5.65% 加虚拟节点,概率为0
B-1700计算机操作码编码方式比较 编码方式 整个操作系统所用指令总位数 改进的百分比 8位定长编码 301248 4-6-10扩展编码 184966 39% 全Huffman编码 172346 43%
(1)将寻址方式编码于操作码中,由操作码在描述指令操作的同时,也描述了相应操作的寻址方式; 2.5 指令集格式的设计 3. 寻址方式的表示方法 (1)将寻址方式编码于操作码中,由操作码在描述指令操作的同时,也描述了相应操作的寻址方式; (2)为每个操作数设置一个地址描述符,由该地址描述符表示相应操作数的寻址方式。
操作数所存放的存储设备(通用寄存器、主存储器、堆栈等) 补充:地址码的优化表示 – 供参考自学 地址码的优化表示 与地址码域长度相关的主要因素: 地址码的个数 (3、2、1、0) 操作数所存放的存储设备(通用寄存器、主存储器、堆栈等) 寻址方式 编址方式 存储设备的寻址空间大小
表达式x=(a*b+c-d)/(e+f)的不同实现 补充:地址码的优化表示 – 供参考自学 表达式x=(a*b+c-d)/(e+f)的不同实现 三地址 二地址 R型二地址 一地址 零地址 MUL X,A,B ADD X,X,C SUB X,X,D ADD Y,E,F DIV X,X,Y MOVE X,A MUL X,B ADD X,C SUB X,D MOVE Y,E ADD Y,F DIV X,Y MOVE R1,A MUL R1,B ADD R1,C SUB R1,D MOVE R2,E ADD R2,F DIV R1,R2 MOVE X,R1 LOAD E ADD F STORE X LOAD A MUL B ADD C SUB D DIV X PUSH A PUSH B MUL PUSH C ADD PUSH D SUB PUSH E PUSH F DIV POP X 三地址:取指令要访问存储器,直接访问存储器方式 二地址:取指令访存,直接访问存储器 R地址:第一个操作数位置保存结果,Rx代表寄存器。使用寄存器。 一地址:累加寄存器 零地址:这个应该是假定了堆栈在内存中
用不同地址个数指令编写的程序的存储容量和执行速度 补充:地址码的优化表示 – 供参考自学 用不同地址个数指令编写的程序的存储容量和执行速度 地址数目 指令条数 访存次数 程序存储量 执行速度(访存信息量) 三地址 5 20 5P+15A=65B 5P+15A+15D=185B 二地址 7 26 7P+14A=63B 7P+14A+19D=215B 一地址 9 18 9P+9A=45B 9P+9A+9D=117B 零地址 12 41 12P+7A=40B 12P+7A+29D=272B 寄存器型 8 15 8P+7A+9R=40B 8P+7A+9R+7D=96B P表示操作码长度,A表示地址码长度,D表示数据长度,R表示通用寄存器的地址码长度,B表示字节数 并取:D=2A=8P=16R=8B
各种不同地址数指令的特点及实用场合 地址数 程序长度 程序存储量 执行速度 适用场合 三地址 短 最大 一般 向量、矩阵运算为主 二地址 补充:地址码的优化表示 – 供参考自学 各种不同地址数指令的特点及实用场合 地址数 程序长度 程序存储量 执行速度 适用场合 三地址 短 最大 一般 向量、矩阵运算为主 二地址 很大 很低 一般不宜采用 一地址 较长 较快 连续运算,硬件结构简单 零地址 最长 最小 最低 嵌套、递归、变量较多 二地址R型 最快 多累加器,数据传送较多
缩短地址码长度的目的是要用一个比较短的地址码表示一个比较大的逻辑地址空间,同时要求有比较灵活的寻址方式。 补充:地址码的优化表示 – 供参考自学 缩短地址码长度的方法: 缩短地址码长度的目的是要用一个比较短的地址码表示一个比较大的逻辑地址空间,同时要求有比较灵活的寻址方式。 (1)用间接寻址方式缩短地址码长度; (2)用变址寻址方式缩短地址码长度; (3)用寄存器间接寻址方式缩短地址码长度。
(1)变长编码格式;当有多种寻址方式和操作类型时,常采用这种格式。 2.5 指令集格式的设计 4. 指令集格式的选择 有三种指令集编码格式: (1)变长编码格式;当有多种寻址方式和操作类型时,常采用这种格式。 (2)固定长度编码格式;将操作类型和寻址方式组合编码在操作码中,当寻址方式和操作类型非常少时,常采用这种格式。 (3)混合型编码格式,其目的是提供一定类型的指令字长,期望能够兼顾降低目标代码长度和降低译码复杂度两个目标。
2.6 MIPS指令集结构 2.6.1 MIPS的寄存器 1. 32个64位通用寄存器(GPRs) R0,R1,…,R31 也被称为整数寄存器 R0的值永远是0 2. 32个64位浮点数寄存器(FPRs) F0,F1,…,F31 单精度、双精度 3. 一些特殊寄存器
2.6.2 MIPS的数据表示 MIPS的数据表示 整数 浮点数 不足填充0 字节(8位) 半字(16位) 字(32位) 双字(64位) 浮点数 单精度浮点数(32位) 双精度浮点数(64位) 不足填充0 字节、半字或者字在装入64位寄存器时,用零扩展或者用符号位扩展来填充该寄存器的剩余部分。装入以后,对它们将按照64位整数的方式进行运算。
2.6.3 MIPS的数据寻址方式 立即数寻址与偏移量寻址 寄存器间接寻址是通过把0作为偏移量来实现的 立即数字段和偏移量字段都是16位的。 寄存器间接寻址是通过把0作为偏移量来实现的 16位绝对寻址是通过把R0(其值永远为0)作为基址 寄存器来完成的 MIPS的存储器是按字节寻址的,地址为64位 所有存储器访问都必须是边界对齐的 5:所有存储空间访问都必须是边界对齐。 我这么理解,指令中给出的访问存储器的地址必须是存储字的整数倍,也就是地址后两位必须为00. 原因:指令长度是32位的,偏移量也要是存储字的整数倍。
2.6.4 MIPS的指令格式 寻址方式编码到操作码中 所有的指令都是32位的 操作码占6位 3种指令格式,对应I类指令、R类指令和J类指令
I类指令 2.6 MIPS指令集结构 包括所有的load和store指令、立即数指令、,分支指令、寄存器跳转指令、寄存器链接跳转指令。 立即数字段为16位,用于提供立即数或偏移量。
2.6 MIPS指令集结构 load指令 访存有效地址:Regs[rs]+immediate 从存储器取来的数据放入寄存器rt store指令 要存入存储器的数据放在寄存器rt中 立即数指令 Regs[rt] ← Regs[rs] op immediate 分支指令 转移目标地址:Regs[rs]+immediate,rt无用 寄存器跳转、寄存器跳转并链接 转移目标地址为Regs[rs]
R类指令 2.6 MIPS指令集结构 包括ALU指令、专用寄存器读/写指令、move指令等。 ALU指令 Regs[rd]← Regs[rs] funct Regs[rt] func为具体的运算操作编码
J类指令 2.6 MIPS指令集结构 包括跳转指令、跳转并链接指令、自陷指令、异常返回指令。 在这类指令中,指令字的低26位是偏移量,它与PC值相加形成跳转的地址。
2.6.5 MIPS的操作 MIPS指令可以分为四大类 符号的意义 x ←n y:从y传送n位到x(注意:n是作用在下标上) load和store ALU操作 分支与跳转 浮点操作 符号的意义 x ←n y:从y传送n位到x(注意:n是作用在下标上) x,y←z:把z传送到x和y
下标:表示字段中具体的位; Mem:表示主存; 上标:用于表示对字段进行复制的次数。 2.6 MIPS指令集结构 对于指令和数据,按从最高位到最低位(即从左到右)的顺序依次进行编号,最高位为第0位,次高位为第1位,依此类推。 下标可以是一个数字,也可以是一个范围。 例如:Regs[R4]0:寄存器R4的符号位 Regs[R4]56..63:R4的最低字节 Mem:表示主存; 按字节寻址,可以传输任意个字节。 上标:用于表示对字段进行复制的次数。 例如:0 32:一个32位长的全0字段
符号##:用于两个字段的拼接,并且可以出现在数据传送的任何一边。 2.6 MIPS指令集结构 符号##:用于两个字段的拼接,并且可以出现在数据传送的任何一边。 举例:R8、R6:64位的寄存器,则 Regs[R8]32..63 ←32 (Mem [Regs[R6]]0)24 ## Mem [Regs[R6]]表示的意义是: 以R6的内容作为地址访问内存,得到的字节按符 号位扩展为32位后存入R8的低32位,R8的高32位(即 Regs[R8]0..31)不变。
load和store指令 指令举例 指令名称 含 义 LD R2,20(R3) 装入双字 Regs[R2]←64 Mem[20+Regs[R3]] LW R2,40(R3) 装入字 Regs[R2]←64 (Mem[40+Regs[R3]]0)32 ## Mem[40+Regs[R3]] LB R2,30(R3) 装入字节 Regs[R2]←64 (Mem[30+Regs[R3]]0)56 ## Mem[30+Regs[R3]] LBU R2,40(R3) 装入无符号字节 Regs[R2]←64 056 ## Mem[40+Regs[R3]] LH R2,30(R3) 装入半字 Regs[R2]←64 (Mem[30+Regs[R3]]0)48 ## Mem[30+Regs[R3]]## Mem[31+Regs[R3]] L.S F2,60(R4) Regs[F2]←64 Mem[60+Regs[R4]] ## 032 L.D F2,40(R3) 装入双精度浮点数 Regs[F2]←64 Mem[40+Regs[R3]] SD R4,300(R5) 保存双字 Mem[300+Regs[R5]]←64 Regs[R4] SW R4,300(R5) 保存字 Mem[300+Regs[R5]]←32 Regs[R4] S.S F2,40(R2) 保存单精度浮点数 Mem[40+Regs[R2]]←32 Regs[F2] 0··31 SH R5,502(R4) 保存半字 Mem[502+Regs[R4]]←16 Regs[R5] 48··.63
ALU指令 寄存器-寄存器型(RR型)指令或立即数型 算术和逻辑操作:加、减、与、或、异或和移位等 指令举例 指令名称 含义 DADDU R1,R2,R3 无符号加 Regs[R1]← Regs[R2]+ Regs[R3] DADDIU R4,R5,#6 加无符号立即数 Regs[R4]← Regs[R5]+6 LUI R1,#4 把立即数装入到一个字的高16位 Regs[R1]← 032 ## 4 ## 016 DSLL R1,R2,#5 逻辑左移 Regs[R1]← Regs[R2]<<5 DSLT R1,R2,R3 置小于 If(Regs[R2]< Regs[R3]) Regs[R1]← 1 else Regs[R1]←0
R0的值永远是0,它可以用来合成一些常用的操作。 例如: 2.6 MIPS指令集结构 R0的值永远是0,它可以用来合成一些常用的操作。 例如: DADDIU R1,R0,#100 //给寄存器R1装入常数100 DADD R1,R0,R2 //把寄存器R2中的数据传送到寄存器R1
2.6 MIPS指令集结构 2.6.6 MIPS的控制指令 由一组跳转和一组分支指令来实现控制流的改变 典型的MIPS控制指令
指令举例 指令名称 含义 J name 跳转 PC 36··63← name<<2 JAL name 跳转并链接 Regs[R31]←PC+4;PC 36··63←name<<2; ((PC+4)-227)≤name<((PC+4)+227) JALR R3 寄存器跳转并链接 Regs[R31]←PC+4;PC← Regs[R3] JR R5 寄存器跳转 PC← Regs[R5] BEQZ R4,name 等于零时分支 if(Regs[R4]== 0) PC←name ; ((PC+4)-217)≤name<((PC+4)+217) BNE R3,R4,name 不相等时分支 if(Regs[R3]!= Regs[R4]) PC←name MOVZ R1,R2,R3 等于零时移动 if(Regs[R3]==0) Regs[R1]← Regs[R2]
根据跳转指令确定目标地址的方式不同以及跳转时是否链接,可以把跳转指令分成4种。 确定目标地址的方式 2.6 MIPS指令集结构 跳转指令 根据跳转指令确定目标地址的方式不同以及跳转时是否链接,可以把跳转指令分成4种。 确定目标地址的方式 把指令中的26位偏移量左移2位(因为指令字长都是4个字节)后,替换程序计数器的低28位。 间接跳转:由指令中指定的一个寄存器来给出转移目标地址。 跳转的两种类型 简单跳转:把目标地址送入程序计数器。 跳转并链接:把目标地址送入程序计数器,把返回地址(即顺序下一条指令的地址)放入寄存器R31。
提供一组比较指令,用于比较两个寄存器的值。 有的分支指令可以直接判断寄存器内容是否为负,或者比较两个寄存器是否相等。 分支的目标地址。 2.6 MIPS指令集结构 分支指令(条件转移) 分支条件由指令确定。 例如:测试某个寄存器的值是否为零 提供一组比较指令,用于比较两个寄存器的值。 例如:“置小于”指令 有的分支指令可以直接判断寄存器内容是否为负,或者比较两个寄存器是否相等。 分支的目标地址。 由16位带符号偏移量左移两位后和PC相加的结果来决定 一条浮点条件分支指令:通过测试浮点状态寄存器来决定是否进行分支。
2.6.7 MIPS的浮点操作 由操作码指出操作数是单精度(SP)或双精度(DP) 后缀S:表示操作数是单精度浮点数 包括加、减、乘、除,分别有单精度和双精度指令。 浮点数比较指令 根据比较结果设置浮点状态寄存器中的某一位,以便于后面的分支指令BC1T(若真则分支)或BC1F(若假则分支)测试该位,以决定是否进行分支。