搞明白后觉得还是挺简单的,不知道之前是自己太笨了,英语没学好没有领会手册上讲的含义,还是这个概念太抽象。

以下代码抄自安腾体系架构软件开发手册之应用卷第二部分第五章:
L1:
  ld4   r35 = [r4] , 4   //通过寄存器r4间接寻址存储器,加载4个字节至寄存器r35后,r4+4
  st4  [r5] = r37 , 4   //将寄存器r37的值存入4字节至寄存器r5给出的存储器地址中,再将r5+4
  swp_branch L1;;   //这是个伪指令,意思就是跳转回L1循环执行,在这里这个转移指令特指是个软件流水线循环专用的特殊转移指令,会导致寄存器轮换。

在安腾当中,机器内部所实际引用的寄存器与二进制代码中给出的寄存器并不象IA-32那样是直接关系,而是由二进制代码中给出的寄存器号和一个叫做寄存器重命名基(Register Rename Base)的寄存器(RRB)共同决定的,安腾的通用、符点、谓词寄存器池均有分为静态区和轮换区。其中静态区的寄存器号不受寄存器RRB的影响,和IA-32那样。而轮换区中被实际引用的寄存器号会受到寄存器RRB中值的影响,跟随其变化而变化。没记错的话通用寄存器的轮换区是从r32到r127。

有些概念真的真正明白后就觉得很简单,象上面那行代码,swp_branch这条特殊转移指令有一个副作用,就是每转移一次,寄存器RRB的值会被递减,所以上面这行代码的实际效果会是这样:

第一次循环时,由于寄存器RRB的值没变,所以实际的代码执行效果与程序中写的一样;
第二次循环时,由于寄存器RRB的值通过转移指令减了1,所以表面上看ld4指令中引用的寄存器是r35,实际上机器内部所引用的寄存器却是r34。第二次循环时整个实际执行的代码应该看起来象这样:
 L1:
  ld4   r34 = [r4] , 4   
  st4  [r5] = r36 , 4   
  swp_branch L1;;[/COLOR]
同样当第三次循环时,整个实际执行的代码看起来是这样的:
 L1:
  ld4   r33 = [r4] , 4   
  st4  [r5] = r35 , 4   
  swp_branch L1;;[/COLOR]

由此可以看出,表面上看代码没变,实际上,由于特殊转移指令导致寄存器RRB的值递减,因此在不同的循环当中,机器内部实际引用的寄存器是不同的。因此,回到最初的代码当中,表面上看第一条ld4指令所用的r35与第二条st4中所用的r37不一样,两条指令毫无关联性,其实,由于寄存器轮换,第三次循环时,st4指令在机器内部实际引用的寄存器就不是r37而是r35了。也就是说,第三次循环时,机器就开始把第一次循环时从内存中加载保存到寄存器r35的值存入内存的另一位置。利用寄存器轮换这一特性的第一个好处,就是在安腾中用短短几条指令,就可以达到在IA-32当中写一大片指令的效果。当然,其实寄存器轮换是与软件流水线、谓词执行、存储器猜测加载一起混用的。那当然是题外话了。

当时安腾手册上是这样讲的,“由于寄存器轮换,原本存储在寄存器Rx中的值被保存在寄存器Rx+1中”,这话那时令我很费解,所以寄存器轮换这一块卡了我好长时间,其实只要说,“由于寄存器轮换,代码中原本引用的是Rx,而机器内部实际引用的寄存器是Rx-1”。这样一下子就懂了。感觉安腾的手册上的话非常精练,看起来很吃力,而那本《理解安腾EPIC体系结构》(书名不准确)中流水线循环一节也没有彻底讲清楚,看了还是不懂。