Intel, AMD及VIA CPU的微架构(9)

来源:互联网 发布:2k15更新球队数据 编辑:程序博客网 时间:2024/06/05 08:47

4.      Pentium 1与PentiumMMX流水线

P1与PMMX处理器不能乱序处理。但通过下面描述的指令成对机制,它们可以同时执行两条相邻的指令。

4.1.      整数指令成对

预取成对

P1与PMMX有两条流水线用于指令执行,称为U-管道及V-管道。在某些情形下,同时执行两条指令是可能的。一个在U-管道,一个在V-管道。这几乎可以使深度加倍。因此,重排指令使它们成对是有利的。

在任一管道中,以下指令是可成对的:

·        MOV寄存器、内存或立即数到寄存器或内存

·        PUSH寄存器或立即数,POP寄存器

·        LEA,NOP

·        INC,DEC,ADD,SUB,CMP,AND,OR,XOR

·        某些形式的TEST(参考手册4:指令表)。

以下指令仅在U-管道中可成对:

·        ADC,SBB

·        带有立即数的SHR,SRA,SHL,SAL

·        带一个立即数的ROR,ROL,RCR,RCL

以下指令可在任一管道中执行,但仅在V-管道中可成对:

·        近程调用

·        短程及近程跳转

·        短程及近程条件跳转

所有其他整形指令仅在U-管道中执行,且不可成对。

在满足以下条件时。两条连续指令将成对:

1.      第一条指令在U-管道中可成对的,第二条指令在V-管道中可成对。

2.      第二条指令不读写第一条指令写的寄存器。例如:

;Example 4.1a. P1/PMMX pairing rules

moveax, ebx / mov ecx, eax ; Read after write, do not pair

moveax, 1 / mov eax, 2 ; Write after write, do not pair

movebx, eax / mov eax, 2 ; Write after read, pair ok

movebx, eax / mov ecx, eax ; Read after read, pair ok

movebx, eax / inc eax ; Read and write after read, pair ok

3.       在规则2中,部分寄存器被视为完整寄存器。例如:

;Example 4.1b. P1/PMMX pairing rules

moval, bl / mov ah, 0

写入同一个寄存器不同部分,不能成对。

4.      尽管有规则2与规则3,都写入标记寄存器部分的两条指令可以成对。例如:

;Example 4.1c. P1/PMMX pairing rules

shreax, 4 / inc ebx ; pair OK

5.       不管规则2,一条写入标记的指令可以与一个条件跳转成对。例如:

;Example 4.1d. P1/PMMX pairing rules

cmpeax, 2 / ja LabelBigger ; pair OK

6.       以下指令组合可以成对,而不管它们都修正栈指针的事实:

;Example 4.1e. P1/PMMX pairing rules

push+ push, push + call, pop + pop

7.      对带有前缀的指令成对存在限制。许多不实现在8086处理器上的指令有一个两字节操作码,其中第一个字节是0FH。在P1上0FH字节作为一个前缀。在PMMX及更新的处理器上,0FH字节作为操作码的部分。带有0FH前缀最常见的指令有:MOVZX,MOVSX,PUSH FS,POP FS,PUSH GS,POP GS,LFS,LGS,LSS,SETcc,BT,BTC,BTR,BTS,BSF,BSR,SHLD,SHRD及带有两个操作数且没有立即数操作数的IMUL。

在P1上,带前缀指令仅能在U-管道中执行,除了条件近程跳转。

在PMMX上,带有操作数大小或地址大小前缀的指令可以在任一管道中执行,而带有段、重复或锁前缀的指令仅能在U-管道中执行。

8.      具有位移及立即数的指令在P1上不可成对,在PMMX上仅在U-管道中可成对:

;Example 4.1f. P1/PMMX pairing rules

movdword ptr ds:[1000], 0 ; Not pairable or only in u-pipe

cmpbyte ptr [ebx+8], 1 ; Not pairable or only in u-pipe

cmpbyte ptr [ebx], 1 ; Pairable

cmpbyte ptr [ebx+8], al ; Pairable

在PMMX上,具有位移及立即数指令的另一个问题是,这样的指令可能超过7个字节,这意味着每时钟周期仅有一条指令可以被解码。

9.      这两条指令必须被预先载入及解码。在P1上这不会发生,除非第一条指令仅有一字节。

10.  对PMMX上的MMX指令,有特殊的成对规则:

·     MMX shift,pack或unpack指令可以在任一管道中执行,但不能与其他MMXshift,pack或unpack指令成对。

·     MMX乘法指令可以在任一管道中执行,但不能与其他MMX乘法指令成对。它们需要3个时钟周期,且以浮点指令相同的方式,最后2个周期可与后续指令重叠(参考第37页)。

·     一条访问内存或整数寄存器的MMX指令仅可以在U-管道中执行,不能与一个非-MMX指令成对。

不完美成对

存在情形,在一对中的两条指令不能同时执行,或时间上仅能部分重叠。不过它们仍然被视为一对,因为第一条指令在U-管道中执行,第二条在V-管道。在这个不完美对里的指令都完成前,后续指令不能开始执行。

在以下情形里,将发生不完美成对:

1.      如果第二条指令遭受了一个AGI暂停(参考第34页)。

2.      两条指令不能同时访问同一个DWORD内存。

以下例子假定ESI可被4整除:

;Example 4.2a. P1/PMMX imperfect pairing

moval, [esi] / mov bl, [esi+1]

两个操作数都在同一个DOWRD中,因此它们不能同时执行。这个对需要2个时钟周期。

;Example 4.2b. P1/PMMX perfect pairing

moval, [esi+3] / mov bl, [esi+4]

这次,两个操作数在一个DWORD边界的两边,因此,它们完美成对,仅需1个时钟周期。

3.      前面的规则被扩展到在两个地址中2-4个比特是相同的情形(缓存行冲突)。对于DWORD地址,这意味着两个地址间的差值不应该是32的倍数。

不访问内存的可成对整数指令,需要1时钟周期执行,除了误预测的跳转。至或自内存的MOV指令也需要1时钟周期,如果数据区域在缓存中且正确对齐。对复杂取址模式的使用,比如比例索引寄存器,没有速度上的惩罚。

一个读内存、执行某些计算、将结果保存进一个寄存器或标记的可成对整型指令,需要2个时钟周期(读/修改指令)。

一个读内存、执行某些计算、将结果保存回内存的可成对整型指令,需要3个时钟周期(读/修改/写指令)。

4.      如果一条读/修改/写指令与一条读/修改或读/修改/写指令成对,它们将是不完美成对。

使用的时钟周期数如下标所示:

第一条指令

第二条指令

 

仅MOV或寄存器

读/修改

读/修改/写

仅MOV或寄存器

1

2

3

读/修改

2

2

3

读/修改/写

3

4

5

表4.1. 复杂指令成对

例如:

;Example 4.3. P1/PMMX pairing complex instructions

add[mem1], eax / add ebx, [mem2] ; 4 clock cycles

addebx, [mem2] / add [mem1], eax ; 3 clock cycles

5.      当由于缓存不命中、不对齐或跳转误预测,两条成对指令都需要额外时间时,该对将需要比每条指令更多的时间,但小于两者的总和。

6.      一条后接FXCH的可成对浮点指令,如果下一条指令不是浮点指令,将形成不完美成对。

为了避免不完美成对,你必须知道哪些指令进入U-管道,哪些进入V-管道。在你的代码中往回看,查找不可成对指令、仅可在其中一个管道成对的指令,或由于上面的规则不能成对的指令,可以找到答案。

不完美成对通常可以通过重排指令来避免。例如:

;Example 4.4. P1/PMMX reorder instructions to improve pairing

L1:mov eax, [esi]

          mov ebx, [esi]

          inc ecx

这里两条MOV指令形成了一个不完美对,因为它们都访问相同的内存位置,结果需要3个时钟周期。你可以通过重排指令,使得INCECX与其中一个MOV指令成对,改进代码。

;Example 4.5. P1/PMMX reorder instructions to improve pairing

L2:mov eax,offset a

          xor ebx, ebx

          inc ebx

          mov ecx, [eax]

          jmp L1

INC EBX / MOV ECX,[EAX]对是不完美的,因为后者有一个AGI暂停。这个序列需要4个时钟周期。如果你插入一条NOP或其他指令,使得MOVECX, [EAX]与JMP L1成对,那么这个序列仅需要3个时钟周期。

下一个例子是16位模式,假定SP被4整除:

;Example 4.6. P1/PMMX imperfect pairing, 16 bit mode

L3:push ax

          push bx

          push cx

          push dx

          call Func

这里PUSH指令构成两个不完美对,因为每对中的操作数都进到相同的内存DWORD。PUSH BX可能可以与PUSHCX完美成对(因为它们进入一个DWORD边界的两边),但没有,因为它已经与PUSHAX成对。因此这个序列需要5个时钟周期。如果你插入一条NOP或其他指令,使得PUSHBX与PUSHCX,PUSHDX与CALLFUNC成对,那么这个序列将仅需要3个时钟周期。解决这个问题的另一个方式是确保SP不是4的倍数。知道SP是否为4的倍数,或者不在16位模式中是困难的,因此避免这个问题最好的方式是使用32位模式。

4.2.      地址生成互锁

计算一条访问内存指令所需地址需要1时钟周期。通常,这个计算在之前的指令或指令对正在执行时,在流水线的一个独立阶段完成。但如果该地址依赖于在之前·时钟周期执行的一条指令的结果,计算这个地址,我们必须等待一个额外时钟周期。这称为一个AGI暂停。

;Example 4.7a. P1/PMMX AGI

addebx, 4

moveax, [ebx] ; AGI stall

在这个例子中可以去除这个暂停,通过在这两者之间插入其他一些指令,或把代码重写为:

;Example 4.7b. P1/PMMX AGI removed

moveax, [ebx+4]

addebx, 4

使用隐含使用ESP取址的指令,比如PUSH,POP,CALL与RET,如果ESP已经在前面的周期里被比如MOV,ADD或SUB这样的指令改变了,你也会得到一个AGI暂停。P1与PMMX有特殊的电路来预测一个栈操作后ESP的值,使得你不会在PUSH,POP或CALL改变了ESP后遭遇一个AGI延迟。仅在RET有加到ESP的立即数后,你会得到一个AGI暂停。例如:

;Example 4.8. P1/PMMX AGI

addesp,4 / pop esi                    ; AGIstall

popeax / pop esi                       ; nostall, pair

movesp,ebp / ret                      ; AGIstall

callF1 / F1: mov eax,[esp+8]   ; no stall

ret/ pop eax                               ;no stall

ret8 / pop eax                            ;AGI stall

LEA指令也会遭受AGI暂停,如果它使用一个在前面时钟周期里被改变的基址或索引寄存器。例如:

;Example 4.9. P1/PMMX AGI

incesi / lea eax, [ebx+4*esi] ; AGI stall

PPro,P2与P3的内存读与LEA没有AGI暂停,但对内存写有AGI暂停。这不是非常重要,除非后续代码必须等待这个写结束。