自己动手写CPU(6)简单算术操作指令

指令说明

MIPS32指令集架构定义的所有算术操作指令,共有三类,分别是:

  • 简单算术指令
  • 乘累加、乘累减指令
  • 除法指令

本博客先记录简单算术操作指令

简单算术操作指令一共有15条指令分别是:add、addi、addiu、addu、sub、subu、clo、clz、slt、slti、sltiu、sltu、mul、mult、multu

1.add、addu、sub、subu、slt、sltu指令

         1.png

(1)add指令 --加法运算

用法:add rd,rs,rt

作用:rd <- rs+rt

将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行加法运算,结果保存到地址为rd的通用寄存器中。当加法运算溢出,那么会产生溢出异常,同时不保存结果

(2)addu指令 --加法运算

用法:addu rd,rs,rt

作用:rd <-rs+rd

将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行加法运算,结果保存到rd的通用寄存器中。不进行溢出检查,总是将结果保存到目的寄存器

(3)sub指令 --减法运算

用法:sub rd,rs,rt

作用:rd <- rs-rt

将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行减法运算,结果保存到地址为rd的通用寄存器中。如果减法运算溢出,那么产生溢出异常,同时不保存结果

(4)subu指令 --减法运算

用法:subu rd,rs,rt

作用:rd <- rs-rt

将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行减法运算,结果保存到地址为rd的通用寄存器中。不进行溢出检查,总是将结果保存到目的寄存器

(5)slt指令 --比较运算

用法:slt rd,rs,rt

作用:rd <- (rs<rt)

将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值按照有符号数进行比较,若前者小于后者,那么将1保存到地址为rd的通用寄存器;若前者大于后者,则将0保存到地址为rd的通用寄存器中。

(6)sltu指令 --比较运算

用法:sltu rd,rs,rt

作用:rd <- (rs<rt)

将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值按照无符号数进行比较,若前者小于后者,那么将1保存到地址为rd的通用寄存器,若前者大于后者,则将0保存到地址为rd的通用寄存器中。

2. addi、addiu、slti、sltiu指令

         2.png

(1)addi指令 --加法运算

用法:addi rt,rs,immediate

作用:rt <- rs+(sign_extended)immediate

将指令中16位立即数进行符号扩展,与地址为rs的通用寄存器进行加法运算,结果保存到地址为rt的通用寄存器。如果加法运算溢出,则产生溢出异常,同时不保存结果

(2)addiu指令 --加法运算

用法:addiu rt,rs,immediate

作用:rt <- rs+(sign_extended)immediate

将指令中16位立即数进行符号扩展,与地址为rs的通用寄存器进行加法运算,结果保存到地址为rt的通用寄存器。不进行溢出检查,总是将结果保存到目的寄存器。

(3)slti指令 --比较运算

用法:slti rt,rs,immediate

作用:rt <- (rs<(sign_extended)immediate)

将指令中的16位立即数进行符号扩展,与地址为rs的通用寄存器的值按照有符号数进行比较,若前者小于后者,那么将1保存到地址为rt的通用寄存器,若前者大于后者,则将0保存到地址为rt的通用寄存器中。

(4)sltiu指令 --比较运算

用法:sltiu rt,rs,immediate

作用:rt <- (rs<(sign_extended)immediate)

将指令中的16位立即数进行符号扩展,与地址为rs的通用寄存器的值按照无符号数进行比较,若前者小于后者,那么将1保存到地址为rt的通用寄存器,若前者大于后者,则将0保存到地址为rt的通用寄存器中。

3. clo、clz指令

          3.png

(1)clz指令 --计数运算

用法:clz rd,rs

作用:rd <- coun_leading_zeros rs

对地址为rs的通用寄存器的值,从最高位开始向最低位方向检查,直到遇到值为“1”的位,将该为之前“0”的个数保存到地址为rd的通用寄存器中,如果地址为rs的通用寄存器的所有位都为0(即0x00000000),那么将32保存到地址为rd的通用寄存器中。

(2)clo指令 --计数运算

用法:clo rd,rs

作用:rd <- coun_leading_zeros rs

对地址为rs的通用寄存器的值,从最高位开始向最低位方向检查,直到遇到值为“0”的位,将该为之前“1”的个数保存到地址为rd的通用寄存器中,如果地址为rs的通用寄存器的所有位都为1(即0xFFFFFFFF),那么将32保存到地址为rd的通用寄存器中。

4. multu、mult、mul指令

         4.png

(1)mul指令 --乘法运算

用法:mul,rd,rs,st

作用:rd <- rs * rt

将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为有符号数相乘,乘法结果的低32bit保存到地址为rd的通用寄存器中。

(2)mult指令 --乘法运算

用法:mult,rs,st

作用:{hi,lo} <- rs * rt

将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为有符号数相乘,乘法结果低32bit保存到LO寄存器中,高32bit保存到HI寄存器中。

(3)multu指令 --乘法运算

用法:multu,rs,st;

作用:{hi,lo} <- rs * rt

将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为无符号数相乘,乘法结果低32bit保存到LO寄存器中,高32bit保存到HI寄存器中。

代码的修改

  • 在译码阶段根据是否需要读第一个和第二个寄存器和是否需要写寄存器设置reg1_read_o、reg2_read_o和wreg_o
  • 修改执行阶段的EX模块

 修改执行阶段的EX模块

1.计算如下几个值

1.1若为减法或有符号运算则reg2_i_mux等于第二个操作数的补码,其他则reg2_i_mux等于第二个操作数

1.2结果result_sum = reg1_i + reg2_i_mux

若为加法,此时reg2_i_mux为reg2_i,所以结果为加法结果

若为减法,此时reg2_i_mux为reg2_i的补码,所以结果为加法结果

若为有符号比较,此时reg2_i_mux为reg2_i的补码,所以看结果大于0还是小于0进而判断第一个操作数大于还是小于零

1.3计算是否溢出

两种情况,当reg1_i和reg2_i都为正的时候结果为负,当reg1_i和reg2_i都为负的时候结果为正

1.4计算操作数1是否小于操作数2

a.1为负数,2为正数

b.同号但相减小于零

c.无符号比较时直接比较

1.5对操作数1逐位取反

2.依据不同算术运算类型,给出值

3.进行乘法运算

3.1分别取被乘数和乘数,若为有符号数且为负数那么取补码

3.2得到临时结果保存到hi、lo中

3.3修正临时结果

若两者异号,则结果为临时结果的补码

若为无符号惩罚或同号,则结果为临时结果

4.确定要写入的目的寄存器数据

若结果溢出,看指令设置wreg_o的值

若乘法以外的数值将arithmetirces作为写入目的寄存器的值

若乘法指令,将低32位写入

5.确定HI、LO寄存器数据

比如HI存结果的高32位,LO存低32位

总结

本节才体验到看仿真的波形图的重要性,可以直接根据波形图看出计算后的寄存器值,继续加油!

猜你喜欢

转载自blog.csdn.net/weixin_52259822/article/details/124617383