空指令(1条)
nop指令
逻辑运算指令(8条)
and、or、xor、nor指令
- 当功能码是6b100100时,表示是and指令,逻辑“与”运算。
指令用法为:and rd,rs,rt。
指令作用为:rd ← rs AND rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行逻辑“与”运算,运算结果保存到地址为rd的通用寄存器中。
- 当功能码是6b100101时,表示是or指令,逻辑“或”运算。
指令用法为:or rd,rs,rt。
指令作用为:rd ← rs OR rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行逻辑“或”运算,运算结果保存到地址为rd的通用寄存器中。
- 当功能码是6b100110时,表示是xor指令,异或运算。
指令用法为:xor rd,rs,rt。
指令作用为:rd ← rs XOR rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行逻辑“异或”运算,运算结果保存到地址为rd的通用寄存器中。
- 当功能码是6b100111时,表示是nor指令,或非运算。
指令用法为:nor rd,rs,rt。
指令作用为:rd ← rs NOR rt,将地址为rs的通用寄存器的值,与地址为rt的通用寄存器的值进行逻辑“或非”运算,运算结果保存到地址为rd的通用寄存器中。
andi、xori、ori指令
- 当指令码是6b001100,表示是andi指令,逻辑“与”运算。
指令用法为:andi rt,rs,immediate。
指令作用为:rt ← rs AND zero extended(immediate),将地址为rs的通用寄存器的值与指令中立即数进行零扩展后的值进行逻辑“与”运算,运算结果保存到地址为rt的通用寄存器中。
- 当指令码是6b001110,表示是xori指令,异或运算。
指令用法为:xori rt,rs,immediate。
指令作用为:rt ← rs XOR zero_extended(immediate),将地址为rs的通用寄存器的值与指令中立即数进行零扩展后的值进行逻辑“异或”运算,运算结果保存到地址为rt的通用寄存器中。
- 当指令码是6b001101,表示是ori指令,或运算。
指令用法为:ori rs,rt,immediate,作用是将指令中的16位立即数进行无符
号扩展至32位,然后与索引为rs的通用寄存器的值进行逻辑“或”运算,运算结果保存到索引为rt的通用寄存器中。
lui指令
- 指令用法为:lui rt,immediate。
指令作用为:rt ← immediate ll 016,将指令中的16bit立即数保存到地址为rt的通用寄存器的高16位。另外,地址为rt的通用寄存器的低16位使用0填充。
移位指令(6条)
sll、sllv,sra、srav、srl、srlv 指令
- 当功能码是6b000000,表示是sll指令,逻辑左移。
指令用法为:sll rd,rt,sa。
指令作用为:rd ← rt << sa(logic),将地址为rt的通用寄存器的值向左移sa位,空出来的位置使用0填充,结果保存到地址为rd的通用寄存器中。
- 当功能码是6b000010,表示是srl指令,逻辑右移。
指令用法为:srl rd,rt,sa。
指令作用为:rd ← rt >> sa(logic),将地址为rt的通用寄存器的值向右移sa位,空出来的位置使用0填充,结果保存到地址为rd的通用寄存器中。
- 当功能码是6b000011,表示是sra指令,算术右移。
指令用法为:sra rd,rt,sa。
指令作用为:rd ← rt >> sa(arithmetic),将地址为rt的通用寄存器的值向右移sa位,空出来的位置使用r[31]的值填充,结果保存到地址为rd的通用寄存器中。
- 当功能码是6b000100,表示是sllv指令,逻辑左移。
指令用法为:sllv rd,rt,rs。
指令作用为:rd ← rt << rs[4:0](logic),将地址为rt的通用寄存器的值向左移位,空出来的位置使用0填充,结果保存到地址为rd的通用寄存器中。移位位数由地址为rs的寄存器值的第0-4bit确定。
- 当功能码是6b000110,表示是srlv指令,逻辑右移。
指令用法为:srlv rd,rt,rs。
指令作用为:rd ← rt >> rs[4:0](logic),将地址为rt的通用寄存器的值向右移位,空出来的位置使用0填充,结果保存到地址为rd的通用寄存器中。移位位数由地址为rs的寄存器值的第0-4bit确定。
- 当功能码是6b000111,表示是srav指令,算术右移。
指令用法为:srav rd,rt,rs。
指令作用为:rd ← rt >> rs[4:0](arithmetic),将地址为rt的通用寄存器的值向右移位,空出来的位置使用rt[31]填充,结果保存到地址为rd的通用寄存器中。移位位数由地址为rs的寄存器值的第0-4bit确定。
总结来说,这6条移位操作指令可以分为两种情况:sllv、srav、srlv这3条指令的助记符最后有“v”,表示移位位数是通过寄存器的值确定的,sl、sra、srl这3条指令的助记符最后没有“v”,表示移位位数就是指令中第6-10bit的sa值。
移动操作指令(6条)
movn、movz、mfhi、mthi、mflo、mtlo指令
- 当功能码为6b001011时,表示是movn指令。
指令用法为:movn rd,rs,rt。
指令作用为:if rt ≠ 0 then rd ← rs,判断地址为rt的通用寄存器的值。如果不为零,那么将地址为rs的通用寄存器的值赋给地址为rd的通用寄存器;反之,保持地址为rd的通用寄存器不变。movn是Move Conditional on Not Zero的意思。
- 当功能码为6b001010时,表示是movz指令。
指令用法为:movz rd,rs,rt。
指令作用为:if rt = 0 then rd ← rs,与上面movn指令的作用正好相反,判断地址为rt的通用寄存器的值。如果为零,那么将地址为rs的通用寄存器的值赋给地址为rd的通用寄存器;反之,保持地址为rd的通用寄存器不变。movz是Move Conditional on Zero的意思。
- 当功能码为6b010000时,表示是mfhi指令。
指令用法为:mfhi rd。
指令作用为:rd ← hi,将特殊寄存器HI的值赋给地址为rd的通用寄存器。
- 当功能码为6b010010时,表示是mflo指令。
指令用法为:mflo rd。
指令作用为:rd ← lo,将特殊寄存器LO的值赋给地址为rd的通用寄存器。
- 当功能码为6b010001时,表示是mthi指令。
指令用法为:mthi rs。
指令作用为;hi ← rs,将地址为rs的通用寄存器的值赋给特殊寄存器HI。
- 当功能码为6b010011时,表示是mtlo指令。
指令用法为:mtlo rs。
指令作用为:lo ← rs,将地址为rs的通用寄存器的值赋给特殊寄存器LO。
算术操作指令(21条)
add、addu、sub、subu、slt,sltu 指令
- 当功能码是6b100000时,表示add指令,加法运算。
指令用法为:add rd,rs,rt。
指令作用为:rd ← rs+rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行加法运算,结果保存到地址为rd的通用寄存器中。但是有一种特殊情况:如果加法运算溢出,那么会产生溢出异常,同时不保存结果。
- 当功能码是6b100001时,表示addu指令,加法运算。
指令用法为:addu rd,rs,rt。
指令作用为:rd ← rs+rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行加法运算,结果保存到地址为rd的通用寄存器中。add指令的不同之处在于addu指令不进行溢出检查,总是将结果保存到目的寄存器。
- 当功能码是6b100010时,表示sub指令,减法运算。
指令用法为:sub rd,rs,rt。
指令作用为:rd ← rs-rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行减法运算,结果保存到地址为rd的通用寄存器中。但是有一种特殊情况:如果减法运算溢出,那么产生溢出异常,同时不保存结果。
- 当功能码是6b100011时,表示subu指令,减法运算。
指令用法为:subu rd,rs,rt。
指令作用为:rd ← rs-rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行减法运算,结果保存到地址为rd的通用寄存器中。与sub指令的不同之处在于:subu指令不进行溢出检查,总是将结果保存到目的寄存器。
- 当功能码是6b101010时,表示slt指令,比较运算。
指令用法为:slt rd,rs,rt。
指令作用为:rd ←(rs<rt),将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值按照有符号数进行比较,如果前者小于后者,那么将1保存到地址为rd的通用寄存器中;反之,将0保存到地址为rd的通用寄存器中。
- 当功能码是6b101011时,表示sltu指令,比较运算。
指令用法为:sltu rd,rs,rt。
指令作用为:rd ←(rs<rt),将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值按照无符号数进行比较,如果前者小于后者,那么将1保存到地址为rd的通用寄存器中;反之,将0保存到地址为rd的通用寄存器中。
addi,addiu、slti、sltiu 指令
- 当指令码是6b001000时,表示addi指令,加法运算。
指令用法为:addi rt,rs,immediate。
指令作用为:rt ← rs+(sign_extended)immediate,将指令中的16位立即数进行符号扩展,与地址为rs的通用寄存器的值进行加法运算,结果保存到地址为rt的通用寄存器中。但是有一个特殊情况:如果加法运算溢出,那么产生溢出异常,同时不保存结果。
- 当指令码是6b001001时,表示addiu指令,加法运算。
指令用法为:addiu rt,rs,immediate。
指令作用为:rt ← rs+(sign_extended)immediate,将指令中的16位立即数进行符号扩展,与地址为rs的通用寄存器的值进行加法运算,结果保存到地址为rt的通用寄存器中。与addi指令的区别在于:addiu指令不进行溢出检查,总是将结果保存到目的寄存器。
- 当指令码是6b001010时,表示slti指令,比较运算。
指令用法为:slti rt,rs,immediate。
指令作用为:rt ←(rs <(sign_extended)immediate),将指令中的16位立即数进行符号扩展,与地址为rs的通用寄存器的值按照有符号数进行比较,如果前者大于后者,那么将1保存到地址为rt的通用寄存器中;反之,将0保存到地址为rt的通用寄存器中。
- 当指令码是6b001011时,表示sltiu指令,比较运算。
指令用法为:sltiu rt,rs,immediate。
指令作用为:rt ←(rs <(sign_extended)immediate),将指令中的16位立即数进行符号扩展,与地址为rs的通用寄存器的值按照无符号数进行比较,如果前者大于后者,那么将1保存到地址为rt的通用寄存器中;反之,将0保存到地址为rt的通用寄存器中。
clo、clz指令
- 当功能码是6b100000时,表示clz指令,计数运算。
指令用法为:clz rd,rs。
指令作用为:rd ← count_leading_zeros rs,对地址为rs的通用寄存器的值,从其最高位开始同最低位方向检查,直到遇到值为“1”的位,将该位之前“0”的个数保存到地址为rd的通用寄存器中,如果地址为rs的通用寄存器的所有位都为0(即0x00000000),那么将32保存到地址为rd的通用寄存器中。
- 当功能码是6b100001时,表示clo指令,计数运算。
指令用法为:clo rd,rs。
指令作用为:rd ← count_leading_ones rs,对地址为rs的通用寄存器的值,从其最高位开始向最低位方向检查,直到遇到值为“0”的位,将该位之前“1”的个数保存到地址为rd的通用寄存器中,如果地址为rs的通用寄存器的所有位都为1(即OxFFFFFFFF),那么将32保存到地址为rd的通用寄存器中。
multu、mult,mul 指令
- 当指令码为SPECIAL2,功能码为6b000010时,表示mul指令,乘法运算。
指令用法为:mul rd,rs,st。
指令作用为:rd ← rs×rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为有符号数相乘,乘法结果的低32bit保存到地址为rd的通用寄存器中。
- 当指令码为SPECIAL,功能码为6b011000时,表示mult指令,乘法运算。
指令用法为:mult rs,st。
指令作用为:{hi,lo} ← rs×rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为有符号数相乘,乘法结果的低32bit保存到LO寄存器中,高32bit保存到HI寄存器中。
- 当指令码为SPECIAL,功能码为6b011001时,表示multu指令,乘法运算。
指令用法为:multu rs,st。
指令作用为:{hi,lo} ← rs×rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为无符号数相乘,乘法结果的低32bit保存到LO寄存器中,高32bit保存到HI寄存器中。与mult指令的区别在于:multu指令执行中将操作数作为无符号数进行运算。
madd、maddu、msub、msubu指令(复杂)
- 当功能码是6b000000时,表示是madd指令,有符号乘累加运算。
指令用法为:madd rs,rt。
指令作用为:{HL,LO} ← {HI,LO}+rs×rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为有符号数进行乘法运算,运算结果与{HI,LO}相加,相加的结果保存到{HI,LO}中。此处{HI,LO}表示HI、LO寄存器连接形成的64位数,HI是高32位,LO是低32位。
- 当功能码是6b000001时,表示是maddu指令,无符号乘累加运算。
指令用法为:maddu rs,rt。
指令作用为:{HI,LO} ← {HI,LO}+rs×rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为无符号数进行乘法运算,运算结果与{HI,LO}相加,相加的结果保存到{HI,LO}中。
- 当功能码是6b000100时,表示是msub指令,有符号乘累减运算。
指令用法为:msub rs,rt。
指令作用为:{HI,LO} ← {HI,LO}-rs×t,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为有符号数进行乘法运算。然后使用{HI,LO}减去乘法结果,相减的结果保存到{HI,LO}中。
- 当功能码是6b000101时,表示是msubu指令,无符号乘累减运算。
指令用法为:msubu rs,rt。
指令作用为:{HI,LO} ← {Hl,LO}-rs×rt,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为无符号数进行乘法运算。然后使用{HI,LO}减去乘法结果,相减的结果保存到{H1,LO}中。
div、divu指令
- 当功能码是6b011010时,表示是div指令,有符号除法运算。
指令用法为:div rs,rt。
指令作用为:{HI,LO} ← rs/rt,将地址为rs的通用寄存器的值,与地址为rt的通用寄存器的值,作为有符号数进行除法运算,将商保存到寄存器LO,余数保存到寄存器HI。
- 当功能码是6b011011时,表示是divu指令,无符号除法运算。
指令用法为:divu rs,rt。
指令作用为:{HI,LO} ← rs/rt,将地址为rs的通用寄存器的值,与地址为rt的通用寄存器的值,作为无符号数进行除法运算,将商保存到寄存器LO,余数保存到寄存器HI。
转移指令(14条)
jr、jalr、j、jal(跳转指令)
- 当指令中的指令码为SPECIAL,功能码为6b001000时,表示jr指令。
指令用法为:jr rs。
指令作用为:pc ← rs,将地址为rs的通用寄存器的值赋给寄存器PC,作为新的指令地址。
- 当指令中的指令码为SPECIAL,功能码为6b001001时,表示jalr指令。
指令用法为:jalr rs或者jalr rd,rs。
指令作用为:rd ← return address,pe ← rs,将地址为rs的通用寄存器的值赋给寄存器PC,作为新的指令地址,同时将跳转指令后面第2条指令的地址作为返回地址保存到地址为rd的通用寄存器,如果没有在指令中指明rd,那么默认将返回地址保存到寄存器$31。
- 当指令中的指令码为6b000010时,表示j指令。
指令用法为:j target。
指令作用为:pc ←(pc+4)[31,28]|| target || ‘00',转移到新的指令地址,其中新指令地址的低28位是指令中的target(也就是上图中的instr_index)左移两位的值,新指令地址的高4位是跳转指令后面延迟槽指令的地址高4位。
- 当指令中的指令码为6b000011时,表示jal指令。
指令用法为:jal target。
指令作用为:pc ←(pc+4)[31,28]||target||‘00’,转移到新的指令地址,新指令地址与指令j相同,不再解释。但是,指令jal还要将跳转指令后面第2条指令的地址作为返回地址保存到寄存器$31。
b、bal、beq、bgez、bgezal、bgtz、blez、bltz、bltzal、bne(分支指令)
从图中可知,前5条指令beq、b、bgtz、blez、bne可以直接依据指令中的指令码进行判断,确定是哪一条指令,而后5条指令bltz、bltzal、bgez、bgezal、bal的指令码都是REGIMM,这是一个宏定义,值为6b000001,需要根据指令中16-20bit的值进一步判断,从而确定是哪一条指令。
从图中还可知,所有分支指令的第0-15bit存储的都是offset,如果发生转移,那么将offset左移2位,并符号扩展至32位,然后与延迟槽指令的地址相加,加法的结果就是转移目的地址,从该地址取指令。
转移目标地址=(signed_extend)(offset ||“00”)+(pc+4)
- 当指令中的指令码为6b000100时,表示beq指令。
指令用法为:beq rs,rt,offset。
指令作用为:if rs=rt then branch,将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行比较,如果相等,那么发生转移。
- 当指令中的指令码为6b000100,且16-25bit为0时,表示b指令。
指令用法为:b offset。
指令作用为:无条件转移,从图中可知,b指令可以认为是beq指令的特殊情况,当beq指令的rs、rt都等于0时,即为b指令,所以在实现的时候不需要特意实现b指令,只需要实现beq指令即可。
- 当指令中的指令码为6b000111时,表示bgtz指令。
指令用法为:bgtz rs,offset。
指令作用为:if rs>0 then branch,如果地址为rs的通用寄存器的值大于零,那么发生转移。
- 当指令中的指令码为6b000110时,表示blez指令。
指令用法为:blez rs,offset。
指令作用为:if rs≤0 then branch,如果地址为rs的通用寄存器的值小于等于零,那么发生转移。
- 当指令中的指令码为6b000101时,表示bne指令。
指令用法为:bne rs,rt,offset。
指令作用为:if rs≠rt then branch,如果地址为rs的通用寄存器的值不等于地址为rt的通用寄存器的值,那么发生转移。
- 当指令中的指令码为REGIMM,且第16-20bit为5b00000时,表示bltz指令。
指令用法为:bltz rs,offset。
指令作用为:if rs<0 then branch,如果地址为rs的通用寄存器的值小于0,那么发生转移。
- 当指令中的指令码为REGIMM,且第16-20bit为5b10000时,表示bltzal指令。
指令用法为:bltzal rs,offset。
指令作用为:if rs<0 then branch,如果地址为rs的通用寄存器的值小于0,那么发生转移,并且将转移指令后面第2条指令的地址作为返回地址,保存到通用寄存器$31。
- 当指令中的指令码为REGIMM,且第16-20bit为5b00001时,表示bgez指令。
指令用法为:bgez rs,offset。
指令作用为:if rs≥0 then branch,如果地址为rs的通用寄存器的值大于等于0,那么发生转移。
- 当指令中的指令码为REGIMM,且第16-20bit为5b10001时,表示bgezal指令。
指令用法为:bgezal rs,offset。
指令作用为:if rs≥0 then branch,如果地址为rs的通用寄存器的值大于等于0,那么发生转移,并且将转移指令后面第2条指令的地址作为返回地址,保存到通用寄存器$31。
- 当指令中的指令码为REGIMM,且第21-25bit为0,第16-20bit为5b10001时,表示bal指令。
指令用法为:bal offset。
指令作用为:无条件转移,并且将转移指令后面第2条指令的地址作为返回地址,保存到通用寄存器$31。从上图的指令格式可知,bal指令是bgezal指令的特殊情况,当bgezal指令的rs为0时,就是bal指令,所以在实现时,不用特意考虑bal指令,只要实现bgezal指令即可。
综上,b、bal指令不用单独实现,需要实现的分支指令只有8条。
加载存储指令(14条)
加载指令lb、lbu、Ih、Ihu、lw说明
从图9-1可知,这5条加载指令可以根据指令中26-31bit的指令码加以区分,另外,加载指令的第0-15bit是offset、第21-15bit是base,加载地址的计算方法如下,先将16位的offset符号扩展至32位,然后与地址为base的通用寄存器的值相加,即可得到加载地址。
加载地址=signed_extended(offset)+GPR[base]
下面分别介绍各个加载指令的作用。
- 当指令中的指令码为6b100000时,是lb指令,字节加载指令。
指令用法为:lbrt,offset(base)。
指令作用为:从内存中指定的加载地址处,读取一个字节,然后符号扩展至32位,保存到地址为rt的通用寄存器中。
- 当指令中的指令码为6b100100时,是lbu指令,无符号字节加载指令。
指令用法为:lbu rt,offset(base)。
指令作用为:从内存中指定的加载地址处,读取一个字节,然后无符号扩展至32位,保存到地址为rt的通用寄存器中。
- 当指令中的指令码为6bl00001时,是lh指令,半字加载指令。
指令用法为:lh rt,offset(base)。
指令作用为:从内存中指定的加载地址处,读取一个半字,然后符号扩展至32位,保存到地址为rt的通用寄存器中。该指令有地址对齐要求,要求加载地址的最低位为0。
- 当指令中的指令码为6'b100101时,是lhu指令,无符号半字加载指令。
指令用法为:lhu rt,offset(base)。
指令作用为:从内存中指定的加载地址处,读取一个半字,然后无符号扩展至32位,保存到地址为rt的通用寄存器中。该指令有地址对齐要求,要求加载地址的最低位为0。
- 当指令中的指令码为6b100011时,是lw指令,字加载指令。
指令用法为:lw rt,offset(base)。
指令作用为:从内存中指定的加载地址处,读取一个字,保存到地址为rt的通用寄存器中。该指令有地址对齐要求,要求加载地址的最低两位为00。
存储指令sb、sh、sw说明
从上图可知,这3条存储指令可以根据指令中26-31bit的指令码加以区分,另外,存储指令的第0-15bit是ofset、第21-15bit是base,存储地址的计算方法如下,先将16位的offset符号扩展至32位,然后与地址为base的通用寄存器的值相加,即可得到存储地址。
存储地址=signed_extended(ofset)+GPR[base]
下面分别介绍各个存储指令的作用。
- 当指令中的指令码为6b101000时,是sb指令,字节存储指令。
指令用法为:sb rt,offset(base)。
指令作用为:将地址为rt的通用寄存器的最低字节存储到内存中的指定地址。
- 当指令中的指令码为6b101001时,是sh指令,半字存储指令。
指令用法为:sh rt,offset(base)。
指令作用为:将地址为rt的通用寄存器的最低两个字节存储到内存中的指定地址。该指令有地址对齐要求,要求计算出来的存储地址的最低位为0。
- 当指令中的指令码为6b101011时,是sw指令,字存储指令。
指令用法为:sw rt,offset(base)。
指令作用为:将地址为rt的通用寄存器的值存储到内存中的指定地址。该指令有地址对齐要求,要求计算出来的存储地址的最低两位为00。
加载指令lwl、lwr说明
- 当指令中的指令码为6b100010时,是lwl指令,非对齐加载指令,向左加载。
指令用法为:lwl rt,offset(base)。
指令作用为:从内存中指定的加载地址处,加载一个字的最高有效部分。lwl指令对加载地址没有要求,从而允许地址非对齐加载,这是与前面介绍的lh、lhu、lw指令的不同之处。在大端模式、小端模式下,lwl指令的效果不同,因为OpenMIPS是大端模式,所以此处只介绍在大端模式下lwl指令的效果。假设计算出来的加载地址是loadaddr,loadaddr的最低两位的值为n,将loadaddr最低两位设为0后的值称为loadaddr_align,如下。
加载地址loadaddr=signed_extended(ofset)+GPR[base]
n=loadaddr{1:0]
loadaddr_align=loadaddr-n
例如:假设计算出来的加载地址是5,lwl指令要从地址5加载数据,那么loadaddr就等于5,n等于1,loadaddr_align等于4。
lwl指令的作用是从地址为loadaddr align处加载一个字,也就是4个字节,然后将这个字的最低4-n个字节保存到地址为rt的通用寄存器的高位,并且保持低位不变。
继续上例,此时loadaddr_align为4,所以从地址4处加载一个字,对应的是地址为4、5、6、7的字节,因为n等于1,所以将加载到的字的最低3个字节保存到地址rt的通用寄存器的高3个字节。如下图所示。一个更加通用的描述如下图所示。
- 当指令中的指令码为6b100110时,是lwr指令,非对齐加载指令,向右加载。
指令用法为:lwr rt,offset(base)。
指令作用为:从内存中指定的加载地址处,加载一个字的最低有效部分。还是假设计算出来的加载地址是loadaddr,loadaddr的最低两位的值为n,将loadaddr最低两位设为0后的值称为loadaddr_align,如下。
加载地址loadaddr=signed_extended(offset)+GPR[base]
n=loadaddr[1:0]
loadaddr_align=loadaddr-n
例如:假设计算出来的加载地址是9,lwr指令要从地址9加载数据,那么loadaddr就等于9,n等于1,loadaddr_align等于8。lwr 指令的作用是从地址为loadaddr_align处加载一个字,也就是4个字节,然后将这个字的最高n+l个字节保存到地址为rt的通用寄存器的低位,并且保持高位不变。继续上例,此时loadaddr_align为8,所以从地址8处加载一个字,对应的是地址为8、9、10、11的字节,因为n等于1,所以将加载到的字的最高2个字节保存到地址rt的通用寄存器的低2个字节。如下图所示。一个更加通用的描述如下图所示。lwl与lwr指令配合可以实现从一个非对齐地址加载一个字,而且只需要使用2条指令,提高了效率。例如:使用一般指令从地址7处加载一个字,那么可以使用以下代码实现,共5条指令。
|
存储指令swl、swr说明
- 当指令中的指令码为6b101010时,是swl指令,非对齐存储指令,向左存储。
指令用法为:swl rt,offset(base)。
- 当指令中的指令码为6b101110时,是swr指令,非对齐存储指令,向右存储。
指令用法为:swr rt,offset(base)。
|