自己动手写CPU之第八阶段(1)——转移指令介绍

将陆续上传本人写的新书《自己动手写CPU》,今天是第34篇,我尽量每周四篇

感兴趣的朋友可以在亚马逊、当当、京东等查找。

另外,开展晒书评送书活动,在亚马逊、京东、当当三大图书网站上,发表《自己动手写CPU》书评的前十名读者,均可获赠《步步惊芯——软核处理器内部设计分析》一书,大家踊跃参与吧!活动时间:2014-9-11至2014-10-20

本章将为OpenMIPS处理器添加转移指令,转移指令包括跳转、分支两种,区别在于前者是绝对转移,后者是相对转移,但实现方法是相似的。转移指令涉及延迟槽,所以首先在8.1节介绍了延迟槽的概念,接着在8.2节对MIPS32指令集架构中定义的所有转移指令的格式、作用、用法进行了说明。在8.3节介绍了OpenMIPS实现转移指令的思路,以及对数据流图、系统结构的修改。8.4节通过修改代码实现了转移指令,最后通过两个测试程序,验证转移指令是否实现正确。

8.1 延迟槽

在实现转移指令之前,先介绍一下延迟槽的概念。在第5章已经介绍了流水线中存在的三种相关:数据相关、结构相关、控制相关。其中控制相关是指流水线中的转移指令或者其他需要改写PC的指令造成的相关。这些指令改写了PC的值,所以导致后面已经进入流水线的几条指令无效,比如:如果转移指令在流水线的执行阶段进行转移条件判断,在发生转移时,会导致当前处于取指、译码阶段的指令无效,需要重新取指。如图8-1所示。

也就是在流水线执行阶段进行转移判断,并且转移发生,那么会有2条无效指令,导致浪费了两个时钟周期。为了减少损失,规定转移指令后面的指令位置为“延迟槽”,延迟槽中的指令被称为“延迟指令”(也可称之为“延迟槽指令”)。延迟指令总是被执行,与转移发生与否没有关系。引入延迟槽后的指令执行顺序如图8-2所示。OpenMIPS处理器就计划使用延迟槽技术。

但是,即使引入延迟槽,在转移发生时仍然会导致已经进入取指阶段的指令无效,也就是仍浪费一个时钟周期,要解决这个问题,可以在译码阶段进行转移判断,这样就可以避免浪费时钟周期。OpenMIPS处理器就设计为在译码阶段进行转移判断。

8.2 转移指令说明

MIPS32指令集架构中定义的转移指令共有14条,可分为如下两类。

  • 跳转指令: jr 、jalr 、j 、jal
  • 分支指令:b、bal、beq、bgez、bgezal、bgtz、blez、bltz、bltzal、bne

其中,跳转指令是绝对转移,分支指令是相对转移。本节分别介绍这两类指令。

      1、跳转指令

跳转指令的格式如图8-3所示。

从图8-3可知,j、jal指令可以通过指令码进行判断,jr、jalr指令的指令码为SPECIAL,还需要依据功能码进一步判断。

  • 当指令中的指令码为SPECIAL,功能码为6‘b001000时,表示是jr指令

指令用法为:jr rs

指令作用为:pc <- rs,将地址为rs的通用寄存器的值赋给寄存器PC,作为新的指令地址。

  • 当指令中的指令码为SPECIAL,功能码为6‘b001001时,表示是jalr指令

指令用法为:jalr rs 或者jalr rd, rs

指令作用为:rd <- return_address, pc <- rs,将地址为rs的通用寄存器的值赋给寄存器PC,作为新的指令地址,同时将跳转指令后面第2条指令的地址作为返回地址保存到地址为rd的通用寄存器,如果没有在指令中指明rd,那么默认将返回地址保存到寄存器$31。

  • 当指令中的指令码为6‘b000010时,表示是j指令

指令用法为:j target

指令作用为:pc <- (pc+4)[31,28] || target || ‘00’,转移到新的指令地址,其中新指令地址的低28位是指令中的target(也就是图8-3中的instr_index)左移两位的值,新指令地址的高4位是跳转指令后面延迟槽指令的地址高4位。

  • 当指令中的指令码为6‘b000011时,表示是jal指令

指令用法为:jal target

指令作用为:pc <- (pc+4)[31,28] || target || ‘00’,转移到新的指令地址,新指令地址与指令j相同,不再解释。但是,指令jal还要将跳转指令后面第2条指令的地址作为返回地址保存到寄存器$31。

j、jal、jr、jalr指令在转移之前都要先执行延迟槽指令。

      2、分支指令

分支指令的格式如图8-4所示。

从图8-4可知,前5条指令beq、b、bgtz、blez、bne可以直接依据指令中的指令码进行判断,确定是哪一条指令,而后5条指令bltz、bltzal、bgez、bgezal、bal的指令码都是REGIMM,这是一个宏定义,值为6‘b000001,需要根据指令中16-20bit的值进一步判断,从而确定是哪一条指令。

从图8-4还可知,所有分支指令的0-15bit存储的都是offset,如果发生转移,那么将offset左移2位,并符号扩展至32位,然后与延迟槽指令的地址相加,加法的结果就是转移目的地址,从该地址取指令。

转移目标地址 = (signed_extend)( offset || ‘00’ ) + (pc+4)

  • 当指令中的指令码为6‘b000100时,表示是beq指令

指令用法为:beq rs, rt, offset

指令作用为:if rs = rt then branch,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行比较,如果相等,那么发生转移。

  • 当指令中的指令码为6‘b000100,且16-25bit为0时,表示是b指令

指令用法为:b offset

指令作用为:无条件转移,从图8-4可知,b指令可以认为是beq指令的特殊情况,当beq指令的rs、rt都等于0时,即为b指令,所以在OpenMIPS实现的时候不需要特意实现b指令,只需要实现beq指令即可。

  • 当指令中的指令码为6‘b000111时,表示是bgtz指令

指令用法为:bgtz rs, offset

指令作用为:if rs > 0 then branch,如果地址为rs的通用寄存器的值大于零,那么发生转移。

  • 当指令中的指令码为6‘b000110时,表示是blez指令

指令用法为:blez rs, offset

指令作用为:if rs ≤ 0 then branch,如果地址为rs的通用寄存器的值小于等于零,那么发生转移。

  • 当指令中的指令码为6‘b000101时,表示是bne指令

指令用法为:bne rs, rt, offset

指令作用为:if rs ≠ rt then branch,如果地址为rs的通用寄存器的值不等于地址为rt的通用寄存器的值,那么发生转移。

  • 当指令中的指令码为REGIMM,且16-20bit为5‘b00000时,表示是bltz指令

指令用法为:bltz rs, offset

指令作用为:if rs < 0 then branch,如果地址为rs的通用寄存器的值小于0,那么发生转移。

  • 当指令中的指令码为REGIMM,且16-20bit为5‘b10000时,表示是bltzal指令

指令用法为:bltzal rs, offset

指令作用为:if rs < 0 then branch,如果地址为rs的通用寄存器的值小于0,那么发生转移,并且将转移指令后面第2条指令的地址作为返回地址,保存到通用寄存器$31。

  • 当指令中的指令码为REGIMM,且16-20bit为5‘b00001时,表示是bgez指令

指令用法为:bgez rs, offset

指令作用为:if rs ≥ 0 then branch,如果地址为rs的通用寄存器的值大于等于0,那么发生转移。

  • 当指令中的指令码为REGIMM,且16-20bit为5‘b10001时,表示是bgezal指令

指令用法为:bgezal rs, offset

指令作用为:if rs ≥ 0 then branch,如果地址为rs的通用寄存器的值大于等于0,那么发生转移,并且将转移指令后面第2条指令的地址作为返回地址,保存到通用寄存器$31。

  • 当指令中的指令码为REGIMM,且21-25bit为0,16-20bit为5‘b10001时,表示是bal指令

指令用法为:bal offset

指令作用为:无条件转移,并且将转移指令后面第2条指令的地址作为返回地址,保存到通用寄存器$31。从图8-4的指令格式可知,bal指令是bgezal指令的特殊情况,当bgezal指令的rs为0时,就是bal指令,所以在OpenMIPS实现时,不用特意考虑bal指令,只要实现bgezal指令即可。

综上,b、bal指令不用单独实现,需要OpenMIPS实现的分支指令只有8条。

所有的分支指令在转移到目标地址前都要先执行延迟槽中的指令。

时间: 2024-10-22 23:28:52

自己动手写CPU之第八阶段(1)——转移指令介绍的相关文章

自己动手写CPU之第八阶段(4)——转移指令实现过程2

将陆续上传本人写的新书<自己动手写CPU>,今天是第36篇,我尽量每周四篇 开展晒书评送书活动,在亚马逊.京东.当当三大图书网站上,发表<自己动手写CPU>书评的前十名读者,均可获赠<步步惊芯--软核处理器内部设计分析>一书,大家踊跃参与吧!活动时间:2014-9-11至2014-10-20 8.4.3 修改执行阶段的EX 模块 参考图8-6可知,EX模块需要增加一些接口,增加的接口描述如表8-4所示. EX模块的代码主要修改如下,完整代码请参考本书附带光盘Code\C

自己动手写CPU之第八阶段(3)——转移指令实现过程1

将陆续上传本人写的新书<自己动手写CPU>,今天是第35篇,我尽量每周四篇 开展晒书评送书活动,在亚马逊.京东.当当三大图书网站上,发表<自己动手写CPU>书评的前十名读者,均可获赠<步步惊芯--软核处理器内部设计分析>一书,大家踊跃参与吧!活动时间:2014-9-11至2014-10-20 转移指令的实现过程比较长,分两次介绍,今天是第一次 8.4 修改OpenMIPS以实现转移指令 8.4.1 修改取指阶段的PC模块 参考图8-6可知,PC模块需要增加接口,增加的接

自己动手写CPU之第八阶段(2)——转移指令实现思路

将陆续上传本人写的新书<自己动手写CPU>,今天是第35篇,我尽量每周四篇 8.3 转移指令实现思路 8.3.1 实现思路 根据8.1节的论述,为了尽量减少转移指令带来的损失,OpenMIPS在译码阶段进行转移条件的判断,如果满足转移条件,那么修改PC为转移目标地址. 8.3.2 数据流图的修改 为了实现转移指令,修改数据流图如图8-5所示. 从图中可知,在译码阶段多了转移判断的步骤,此外,PC的取值变为三种情况. 情况一:PC等于PC+4.这属于一般情况,每个时钟周期PC加4,指向下一条指令

自己动手写CPU之第七阶段(2)——简单算术操作指令实现过程

将陆续上传本人写的新书<自己动手写CPU>,今天是第25篇,我尽量每周四篇 亚马逊的预售地址如下,欢迎大家围观呵! http://www.amazon.cn/dp/b00mqkrlg8/ref=cm_sw_r_si_dp_5kq8tb1gyhja4 China-pub的预售地址如下: http://product.china-pub.com/3804025 7.2 简单算术操作指令实现思路 虽然简单算术操作指令的数目比较多,有15条,但实现方式都是相似的,与前几章逻辑.移位操作指令的实现方式也

自己动手写CPU之第七阶段(3)——简单算术操作指令实现过程(续)

将陆续上传本人写的新书<自己动手写CPU>,今天是第26篇,我尽量每周四篇 China-pub的预售地址如下(有目录.内容简介.前言): http://product.china-pub.com/3804025 亚马逊的预售地址如下,欢迎大家围观呵! http://www.amazon.cn/dp/b00mqkrlg8/ref=cm_sw_r_si_dp_5kq8tb1gyhja4 为了实现简单算术指令,需要修改译码阶段的ID模块.执行阶段的EX模块,上一篇博文中已经介绍了对译码阶段ID模块的

自己动手写CPU之第六阶段(2)——移动操作指令实现思路

将陆续上传本人写的新书<自己动手写CPU>(尚未出版),今天是第21篇,我尽量每周四篇 6.2 移动操作指令实现思路 6.2.1 实现思路 这6条移动操作指令可以分为两类:一类是不涉及特殊寄存器HI.LO的指令,包括movn.movz:另一类是涉及特殊寄存器HI.LO的指令,包括mfhi.mflo.mthi.mtlo.前一类很好实现,基本思路与第5章实现逻辑.移位操作指令时类似,只需要修改ID.EX模块即可.后一类涉及到特殊寄存器HI.LO,需要为OpenMIPS添加HI.LO寄存器,以及相应

自己动手写CPU之第七阶段(1)——简单算术操作指令说明

将陆续上传本人写的新书<自己动手写CPU>(尚未出版),今天是第24篇,我尽量每周四篇 本章将实现MIPS32指令集架构定义的所有算术操作指令,共有21条,按照OpenMIPS实现这些指令的方式,可以分为三类,分别介绍如下. (1)简单算术操作指令 共有15条,包括加法.减法.比较.乘法等指令,这些指令在流水线的执行阶段都只需要一个时钟周期,而且实现思路很直观,与第4章添加逻辑操作指令类似,只需修改译码阶段的ID模块.执行阶段的EX模块,即可实现. (2)乘累加.乘累减指令 共有4条:乘累加m

自己动手写CPU之第五阶段(4)——逻辑、移位与空指令的实现

将陆续上传本人写的新书<自己动手写CPU>(尚未出版),今天是第18篇,我尽量每周四篇 5.5 修改OpenMIPS以实现逻辑.移位操作与空指令 为了实现逻辑.移位操作与空指令(其中nop.ssnop不用特意实现,可以认为是特殊的逻辑左移指令sll),只需要修改OpenMIPS的如下两个模块. 修改译码阶段的ID模块,用以实现对上述指令的译码. 修改执行阶段的EX模块,使其按照译码结果进行运算. 5.5.1 修改译码阶段的ID模块 首先给出如下宏定义,都在文件defines.v中定义,读者可以

自己动手写CPU之第五阶段(2)——OpenMIPS对数据相关问题的解决措施

将陆续上传本人写的新书<自己动手写CPU>(尚未出版),今天是第16篇,我尽量每周四篇 5.2 OpenMIPS对数据相关问题的解决措施 OpenMIPS处理器采用数据前推的方法来解决流水线数据相关问题.通过补充完善图4-4原始的数据流图,添加部分信号使得可以完成数据前推的工作,如图5-7所示.主要是将执行阶段的结果.访存阶段的结果前推到译码阶段,参与译码阶段选择运算源操作数的过程. 图5-8给出了为实现数据前推而对OpenMIPS系统结构所做的修改.有两个方面. (1)将处于流水线执行阶段的