【自己动手写CPU】加载存储指令的实现

指令说明

加载指令

31-2625-2120-1615-0useagefunction
LB(100000)basertoffsetlb rt,offset(base)从内存中指定加载处,读取一个字节,然后符号扩展到32位,保存到地址为rt的寄存器中
LBU(100100)basertoffsetlbu rt,offset(base)同上,除有符号变无符号外
LH(100001)basertoffsetlh rt,offset(base)从内存中指定加载处,读取一个半字,然后无符号扩展到32位,保存到地址为rt的寄存器中,该指令有地址对齐要求,要求加载地址的最低位为0
LHU(100101)basertoffsetlhu rt,offset(base)同上,除有符号变为无符号外
LW(100011)basertoffsetlw rt,offset(base)从内存中指定的加载地址处,读取一个字,保存到地址为rt的通用寄存器中。该指令有地址对齐要求,要求加载地址的最低位为00
LWL(100010)basertoffsetlwl rt,offset(base)从内存中指定的加载地址处,加载一个字的最高有效部分lwl指令对加载地址没有要求,允许地址非对齐加载
LWR(100110)basertoffsetlwr rt,offset(base)从内存中指定的加载地址处,加载一个字的最低有效部分非对齐加载指令,向右加载
  • lwl
    加载地址=offset符号扩展到32位的值+地址为base的通用寄存器的值
    假设计算出来的加载地址是loadaddr,loadaddr的最低两位是n,将loadaddr最低两位设为0后的值为loadaddr_align。
    loadaddr=signed_extended(offset)+GPR(base)
    n=loadaddr[1:0]
    loadaddr_align=loadaddr-n
  • lwr
    假设计算出来的加载地址是loadaddr,loadaddr的最低两位的值为n,将loadaddr最低两位设为0后的值称为loadaddr_align。
    loadaddr=signed_extended(offset)+GPR(base)
    n=loadaddr[1:0]
    loadaddr_align=loadaddr-n

存储指令

31-2625-2120-1615-0useagefunction
SB(101000)basertoffsetsb rt,offset(base)将地址为rt的通用寄存器的最低字节存储到内存中的指定地址
SH(101001)basertoffsetsh rt offset(base)将地址为rt的通用寄存器的最低两个字节存储到内存中的指定地址。该指令有地址对齐要求,要求计算出来的存储地址最低位为0
SW(101011)basertoffsetsw rt,offset(base)将地址为rt的通用寄存器的值存储到内存中的指定地址。该指令有地址对齐要求,要求计算出来的存储地址的最低位为00
SWL(101010)basertoffsetswl rt,offset(base)将地址为rt的通用寄存器的高位部分存储到内存中指定的地址处,存储地址的最后两位确定了要存储rt通用寄存器的哪几个字节。swl指令对存储地址没有对齐要求
SWR(101110)basertoffsetswr rt,offset(base)将地址为rt的通用寄存器的低位部分存储到内存中的指定地址处,存储地址的最后两位确定了要存储rt通用寄存器的哪几个字节。swr指令对存储地址没有对齐要求

存储地址=offset符号扩展到32位的值+地址为base的通用寄存器的值

  • swl
    storeaddr=signed_extended(offset)+GPR(base)
    n=storeaddr[1:0]
    storeaddr_align=storeaddr-n
  • swr
    storeaddr=signed_extended(offset)+GPR(base)
    n=storeaddr[1:0]
    storeaddr_align=storeaddr-n

=============================================================
好烦啊 用法真烦。。。真是坠了

加载指令用法示例

OpenMIPS处理器是按字节寻址,且是大端模式。数据的高位保存在存储器的低地址中,而数据的低位保存在存储器的高地址中。

sh

使用sh指令在0x54处存储0x8281
sh指令(将地址为rt的通用寄存器的最低两个字节存储到内存中的指定地址。该指令有地址对齐要求,要求计算出来的存储地址最低位为0)
在这里插入图片描述0x8281高位0x82在低地址0x54处存储,低位0x81在低地址0x55处存储。

sb

使用sb指令在0x50处存储0x81。
sb指令(将地址为rt的通用寄存器的最低字节存储到内存中的指定地址
在这里插入图片描述

sw

使用sw指令在0x58处存储0x84838281。
sw指令(将地址为rt的通用寄存器的值存储到内存中的指定地址。该指令有地址对齐要求,要求计算出来的存储地址的最低位为00)
在这里插入图片描述

lbu

此时使用加载指令lbu从0x58处加载一个字节。
lbu(从内存中指定加载处,读取一个字节,然后无符号扩展到32位,保存到地址为rt的寄存器中)。
读出的字节是0x84,经无符号扩展至32位是0x00000084。

lb

使用指令lb从0x58处加载一个字节。
读出来的字节是0x84,经有符号扩展是0xffffff84。

lhu

使用指令lhu从0x58处加载一个半字。读出来的半字就是0x8483,经无符号扩展至32位就是0x00008483。

lh

使用指令lh从0x58处加载一个半字。读出来的半字就是0x8483,经有符号扩展至32位就是0xffff8483。
字节与半字(32位处理器)
所以一个半字是两个字节。
lh(从内存中指定加载处,读取一个半字,然后无符号扩展到32位,保存到地址为rt的寄存器中,该指令有地址对齐要求,要求加载地址的最低位为0)
使用lh从0x59处加载一个半字,如果不考虑对齐要求,就是0x8382,(32’b00001111_00000011_00001111_00000010)。考虑到加载地址的最低位是0x59(32’b0000_0000_0000_0101_0000_0000_0000_1001)最低位不是0舍去。
使用lh从0x5a处加载一个半字,就是0x8281,无符号扩展至32位就是0x00008281

lw

使用lw从0x58处加载一个字,读出来的字就是4个字节。0x84838281

lwl

假设计算出来的加载地址是5,lwl指令要从地址5加载数据,那么loadaddr=5(0101),n=2’b01=1,loadaddr_align=5-1=4。从4处加载一个字,即4,5,6,7的字节,因为n=1所以将加载到的字的最低3个字节保存到地址为rt的通用寄存器的最高三个字节。从地址为loadaddr_align处加载一个字,4个字节,然后将这个字的最低4-n个字节保存到地址为rt的通用寄存器的高位,低位保持不变。
在这里插入图片描述

lwr

假设计算出来的加载地址是9,lwr指令要从地址9加载数据,那么loadaddr=9,n=1,loadaddr_align=8。从地址为loadaddr_align处加载一个字,4个字节,然后将这个字的最高n+1个字节保存到地址为rt的通用寄存器的低位,并保持高位不变。(和lwl相反)从地址为8处加载一个字,对应的地址是8,9,10,11的字节,n=1,将加载到的字的最高两个字节保存到地址为rt的通用寄存器的低2字节。
在这里插入图片描述

swl

在这里插入图片描述
在这里插入图片描述

swr

在这里插入图片描述
在这里插入图片描述

浅记一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值