延迟槽
延迟槽(Delay slot),是电脑架构中一个指令槽,在前一条指令没有执行完毕的情况下,处理器内部指令流水线上该指令槽的执行不会修改处理器的状态。这种技术常用于DSP与早期的RISC体系结构。最常见的是下文描述的分支延迟槽。另外还有过存储延迟槽,即在存储内存的指令之后跟一个延迟槽,现在已经基本不用了。
分支延迟槽
当一个分支指令之后的延迟槽指令,在指令流水线中被称作分支延迟槽(Branch delay slot)。常见于DSP体系结构与老式的RISC体系结构。MIPS、PA-RISC、ETRAX CRIS、SuperH、SPARC等RISC体系结构在分支后有一个延迟槽。PowerPC、ARM、DEC Alpha没有采用分支延迟槽。DSP具有单个分支延迟槽的有VS DSP、µPD77230、TMS320C3x。SHARC DSP与MIPS-X使用两个分支延迟槽。
采用指令流水线的处理器的目标是每个时钟周期完成一条指令。为此,在任何时刻流水线都应该充满了处于不同执行阶段的指令。分支指令会导致分支冒险,也就是不到分支指令执行完毕被退休(retired),是不能确定哪些后继指令应该继续执行。一个简单办法是在分支指令后面插入流水线迟延(stall),直到新的分支目标地址被求出,并把新的指令地址装入程序计数器。流水线延迟的每个周期都是分支延迟槽。更为复杂的设计是在分支指令后面执行那些不依赖于分支结果的指令。这可以由编译器自动优化。
特定流水线的实现中分支延迟槽的理想数量由流水线阶段数、是否存在寄存器转发、分支条件计算在哪一级流水线、是否使用分支目标缓存(BTB)以及许多其他因素所决定。为了保证软件兼容性,体系结构的迭代不能改变延迟槽的数量。因此这需要新的硬件实现依然包含额外的硬件来确保遵循体系结构规定的行为。
以下示例展示了SHARC DSP汇编语言中对于分支延迟槽的优化。寄存器R0到R9按编号依次清零,并且没有任何指令被执行超过一次。
R0 = 0; CALL fn (DB); /* 调用函数"fn" */ R1 = 0; /* 第一个延迟槽 */ R2 = 0; /* 第二个延迟槽 */ /***** 在此处中断 (调用生效,跳转到"fn") *****/ R6 = 0; /* 调用结束,返回到此处而非"R1 = 0"处 */ JUMP end (DB); R7 = 0; /* 第一个延迟槽 */ R8 = 0; /* 第二个延迟槽 */ /***** 在此处中断 (跳转生效,跳转到"end") *****/ /* 下面 4 条指令是函数"fn" */ fn: R3 = 0; RTS (DB); /* 返回到调用处,并略过调用指令后的延迟槽 */ R4 = 0; /* 第一个延迟槽 */ R5 = 0; /* 第二个延迟槽 */ /***** 在此处中断 (RTS指令生效,返回到调用处) *****/ end: R9 = 0;