本章将为OpenMIPS处理器添加转移指令,转移指令包括跳转、分支两种,区别是前者是绝对转移,后者是相对转移,但实现方法是相似的。转移指令涉及延迟槽。
8.1 延迟槽
在实现转移指令之前,先介绍一下延迟槽的概念。在第五章已经介绍了流水线中存在的三种相关:数据相关、结构相关、控制相关。其中,控制相关是指流水线中的转移指令或者其他需要改写PC指令造成的相关。这些指令改写了PC的值,所以导致后面已经进入流水线的几条指令无效,比如:如果转移指令在流水线的执行阶段进行转移条件判断,在发生转移时,会导致当前处于取指、译码阶段的指令无效,需要重新取指。
也就是说,在流水线执行阶段进行转移判断,并且转移发生,那么会有2条无效指令,导致浪费了两个时钟周期,为了减少损失,规定转移指令后面的指令位置为“延迟槽”,延迟槽中的指令被称为“延迟指令”(也可称之为“延迟槽指令”)。延迟指令总是被执行,与转移发生与否没有关系。引入延迟槽后的指令执行顺序如图所示。OpenMIPS处理器就计划使用延迟槽技术。
但是,即使引入延迟槽,在转移发生时仍然会导致已经进入取指阶段的指令无效,也就是说,仍浪费一个时钟周期,要解决这个问题,可以在译码阶段进行转移判断,这样就可以避免浪费时钟周期。OpenMIPS处理器就设计为在译码阶段进行转移判断。
8.2 转移指令说明
MIPS32指令集架构中定义的转移指令共有14条,可分为如下两类。
-
跳转指令
跳转指令的格式如图所示。
j、jal指令可以通过指令码进行判断,jr、jalr指令的指令码为SPECIAL,还需要依据功能码进一步判断。
-
分支指令
分支指令的格式如图所示
从图中可知,前5条指令beq、b、bgez、bne可以直接依据指令中的指令码进行判断,确定是哪一条指令,而后5条指令bltz,bltzal,bgez,bgezal,bal指令码都是REGIMM,这是一个宏定义,值为6’b000001,需要根据指令中第16-20bit的值进一步判断,从而确定是哪一条指令。
从图中还可知,所有分支指令的第0-15bit存储的都是offset,如果发生转移,那么将offset左移2位,并符号扩展至32位,然后与延迟槽指令的地址相加,加法的结果就是转移目的地址,从该地址取指令。
8.3 转移指令实现思路
8.3.1 实现思路
为了减少转移指令带来的损失,OpenMIPS在译码阶段进行转移条件的判断,如果满足转移条件,那么修改PC为转移目标地址。
8.3.2 数据流图的修改
为了实现转移指令,修改数据流图。在译码阶段多了转移判断的步骤,此外,PC的取指变为三种情况。
8.3.3 系统结构的修改
8.4 修改OpenMIPS以实现转移指令
8.4.1 修改取指阶段的PC模块
8.4.2 修改译码阶段
- 修改ID模块