MIPS 分支延迟与加载延迟

 分支延迟 与   加载延迟
-----------------------------


分支延迟
-----------
这是顺应流水效果的一种机制吧!
  由于流水所以在分支指令开始进入流水的第二个阶段时,他的下一条指令也开始。 而一般是否跳转以及跳转的目标地址的获取都是在ALU阶段开始在决定了(流水级引用五级流水), 而在这时刚好来得及获取目标地址是下下条指令,而不是下一条指令。
  为了利用这一点,MIPS规定,分支指令之后的指令 总是在分支目标指令之前执行。而分支指令之后的位置称为延迟槽在函数调用的时候,这个位置经常用于对行参的传递。 在这里,我们也就知道在跳转指令执行后ra寄存器的值现在其实是延迟槽位置之后的那条指令的地址值。

.......
.......
jal  48      <---- 48 代表跳转的目标地址 jal会置ra寄存器的值
nop / li a1, 4    <---- 这地方就是一个延迟槽  
.......    <----- ra 寄存器的值变为这个地方的地址
.......

 

//为什么无条件跳转指令还需要设置ra

   其实在这里,可能有点疑问了。现在MIPS的CPU的流水级一般不止五级的了,为什么只有一个延迟槽,而不是几个呢??  现代cpu都倾向于提前预测跳转方向的,如果在执行级才求得跳转方向那以后指令的执行都会白做了,清空流水线代价比较高的。 以龙芯为例,它的流水级是九级包括取指、预译码、译码、寄存器重命名、调度、发射、读寄存器、执行、提交等。 而在第二级预译码级开始对转移指令进行译码并预测跳转的方向。这时插入一个延迟槽刚好保证有效流水。
  
   呵呵  不知道这样理解对不对

 注:无条件跳转延迟槽的有效使用非常容易,而条件分支时延迟槽的使用就要小心了(保证对两条分支路径不会产生不良影响)。
-----------------------------------------------------------------

加载延迟
--------
  在MIPS中,还规定数据加载指令的数据 在下一条指令的ALU阶段启动之后 才能从缓存或者内存取得。这样的话,下一条指令的就不能马上使用加载数据。
  当然如果你非要使用这个数也是可以的,这个时候 cpu将进入互锁: cpu将会停下来,直到数据准备完成 才又开始运行。 在早期的没有实现互锁的MIPS cpu上面 这个行为可能导致不可预料的结果(来自: 《See Mips Run》)。
  (疑问 如果cpu停下来  那么流水线上的其他指令会不会丢掉呢??还有cpu停下来 等待数据准备,数据准备就不要cpu参与吗??)

#include   
#include   

int main()
{
    int a, b;
    a = 1;
    asm volatile(
        ".set mips3 /n"
        ".set noreorder /n"

        "lw  $2, 0x0(%0) /n"
        "addi $2, $2, 1 /n" ---> 这条指令会延迟一下才能执行(不知道怎么验证)
        "sw $2, 0x0(%1) /n"

        ".set reorder /n"
        ".set mips0 /n"
        ::"r"(&a),"r"(&b)
        :"$2","memory"

    );
    printf("%x/n",b);
}


 
 
-----------------------------------------------------------------

 

(转自http://blog.chinaunix.net/u2/63038/showart_517433.html)

你可能感兴趣的:(MIPS)