天天看点

【自己动手写CPU】加载存储指令的实现指令说明加载指令用法示例

指令说明

加载指令

31-26 25-21 20-16 15-0 useage function
LB(100000) base rt offset lb rt,offset(base) 从内存中指定加载处,读取一个字节,然后符号扩展到32位,保存到地址为rt的寄存器中
LBU(100100) base rt offset lbu rt,offset(base) 同上,除有符号变无符号外
LH(100001) base rt offset lh rt,offset(base) 从内存中指定加载处,读取一个半字,然后无符号扩展到32位,保存到地址为rt的寄存器中,该指令有地址对齐要求,要求加载地址的最低位为0
LHU(100101) base rt offset lhu rt,offset(base) 同上,除有符号变为无符号外
LW(100011) base rt offset lw rt,offset(base) 从内存中指定的加载地址处,读取一个字,保存到地址为rt的通用寄存器中。该指令有地址对齐要求,要求加载地址的最低位为00
LWL(100010) base rt offset lwl rt,offset(base) 从内存中指定的加载地址处,加载一个字的最高有效部分lwl指令对加载地址没有要求,允许地址非对齐加载
LWR(100110) base rt offset lwr 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-26 25-21 20-16 15-0 useage function
SB(101000) base rt offset sb rt,offset(base) 将地址为rt的通用寄存器的最低字节存储到内存中的指定地址
SH(101001) base rt offset sh rt offset(base) 将地址为rt的通用寄存器的最低两个字节存储到内存中的指定地址。该指令有地址对齐要求,要求计算出来的存储地址最低位为0
SW(101011) base rt offset sw rt,offset(base) 将地址为rt的通用寄存器的值存储到内存中的指定地址。该指令有地址对齐要求,要求计算出来的存储地址的最低位为00
SWL(101010) base rt offset swl rt,offset(base) 将地址为rt的通用寄存器的高位部分存储到内存中指定的地址处,存储地址的最后两位确定了要存储rt通用寄存器的哪几个字节。swl指令对存储地址没有对齐要求
SWR(101110) base rt offset swr 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)

【自己动手写CPU】加载存储指令的实现指令说明加载指令用法示例

0x8281高位0x82在低地址0x54处存储,低位0x81在低地址0x55处存储。

sb

使用sb指令在0x50处存储0x81。

sb指令(将地址为rt的通用寄存器的最低字节存储到内存中的指定地址

【自己动手写CPU】加载存储指令的实现指令说明加载指令用法示例

sw

使用sw指令在0x58处存储0x84838281。

sw指令(将地址为rt的通用寄存器的值存储到内存中的指定地址。该指令有地址对齐要求,要求计算出来的存储地址的最低位为00)

【自己动手写CPU】加载存储指令的实现指令说明加载指令用法示例

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的通用寄存器的高位,低位保持不变。

【自己动手写CPU】加载存储指令的实现指令说明加载指令用法示例

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字节。

【自己动手写CPU】加载存储指令的实现指令说明加载指令用法示例

swl

【自己动手写CPU】加载存储指令的实现指令说明加载指令用法示例
【自己动手写CPU】加载存储指令的实现指令说明加载指令用法示例

swr

【自己动手写CPU】加载存储指令的实现指令说明加载指令用法示例
【自己动手写CPU】加载存储指令的实现指令说明加载指令用法示例

浅记一下。

继续阅读