自己动手写CPU(3)逻辑、移位操作与空指令
指令说明
MIPS32指令集架构中定义的逻辑操作指令有8条: and、andi、or、ori、xor、xori、nor、lui,其中 ori指令已经实现。
MIPS32指令集架构中定义的移位操作指令有6条: sll、sllv、sra、srav、srl、srlv。
MIPS32指令集架构中定义的空指令有2条: nop、ssnop。其中 ssnop是一种特殊类型的空操作,在每个周期发射多条指令的CPU中,使用ssnop指令可以确保单独占用一个发射周期。OpenMIPS 设计为标量处理器,也就是每个周期发射一条指令,所以ssnop 的作用与nop相同,可以按照nop指令的处理方式来处理ssnop指令。
此外还有sync、pref这两条指令,其中sync指令用于保证加载、存储操作的顺序,但对于OpenMIPS而言,它是严格按照指令顺序执行的,加载、存储操作也是按照操作顺序进行的,所以可以将sync指令当做nop指令处理;pref指令用于缓存预取,OpenMIPS未实现缓存,所以也将该指令当做nop指令处理。
指令格式
and、or、xor、nor指令格式
-
and指令,功能码是6’b100100,逻辑“与”运算。
指令用法:and rd, rs,rt (rd <- rs AND rt)
-
or指令,功能码是6’b100101,逻辑“或”运算。
指令用法:or rd, rs,rt (rd <- rs OR rt)
-
xor指令,功能码是6’b100110,异或运算。
指令用法:xor rd, rs,rt (rd <- rs XOR rt)
-
nor指令,功能码是6’b100111,或非运算。
指令用法:nor rd, rs,rt (rd <- rs NOR rt)
andi、xori指令格式
-
andi指令,指令码是6’b001100,逻辑“与”运算。
指令用法:andi rt, rs,imm ( rt <- rs AND zero_extended(imm) )
-
xori指令,指令码是6’b01110,逻辑“异或”运算
指令用法:xori rt, rs,imm ( rt <- rs XORI zero_extended(imm) )
lui指令格式
指令用法:lui rt,imm ( rt <- imm || 0^16 , 即将指令中的16bit立即数保存到地址为rt的通用寄存器的高16位,低16位用0填充)
sll、srl、sra、sllv、srlv、 srav指令格式
-
sll指令,功能码是6’b000000,逻辑左移
指令用法:sll rd,rt,sa ( rd <- rt << sa(logic) rt的值向左移位sa位,空出来的位置用0填充,结果保存到地址为rd的通用寄存器中)
-
srl指令,功能码是6’b000010,逻辑右移
指令用法:srl rd,rt,sa ( rd <- rt >> sa(logic) rt的值向右移位sa位,空出来的位置用0填充,结果保存到地址为rd的通用寄存器中)
-
sra指令,功能码是6’b000011,算术右移
指令用法:sra rd,rt,sa ( rd <- rt >> sa(arithmetic) rt的值向右移位sa位,空出来的位置用rt[31]的值填充,结果保存到地址为rd的通用寄存器中)
-
sllv指令,功能码是6’b000100,逻辑左移
指令用法:sllv rd,rt,rs ( rd <- rt << rs[4:0] rt的值向左移位rs[4:0]位,空出来的位置用0填充,结果保存到地址为rd的通用寄存器中)
-
srlv指令,功能码是6’b000110,逻辑右移
指令用法:srlv rd,rt,rs ( rd <- rt >> rs[4:0] rt的值向右移位rs[4:0]位,空出来的位置用0填充,结果保存到地址为rd的通用寄存器中)
-
srav指令,功能码是6’b000111,算术右移
指令用法:srav rd,rt,rs ( rd <- rt >> rs[4:0] rt的值向右移位rs[4:0]位,空出来的位置用rt[31]填充,结果保存到地址为rd的通用寄存器中)
nop、ssnop、sync、pref指令格式
指令说明:空指令
修改代码
为了实现逻辑、移位操作与空指令(其中 nop、ssnop不用特意实现,可以认为是特殊的逻辑左移指令sll),只需要修改OpenMIPS 的如下两个模块。
- 修改译码阶段的ID模块,用以实现对上述指令的译码。
- 修改执行阶段的EX模块,使其按照译码结果进行运算。
确定指令种类的过程
疑问之处:书上提供的sync指令的op[10:6]=00001
,但代码中判断认为op[10:6]=00000
,查阅MIPS32手册后发现,op[10:6]
为stype码,可以指定多种类型,全0和00001都在其中,如下图
仿真结果
逻辑功能测试波形图
移位功能测试波形图
与书上提供的汇编代码结果进行核验后完全正确,功能正常实现。其中调试逻辑功能波形图时,寄存器出现X的情况,调试了近两个小时发现是顶层连线连错了,真是个低级错误,希望大家认真仔细,不要重蹈我的覆辙。