原创 谈谈SH系列的Delay Slot 和 branch指令

2011-2-25 14:14 2857 3 3 分类: MCU/ 嵌入式
来源:瑞萨单片机论坛

今天在调试SH2A时,CPU很意外的进入了delay slot中断。
对于Delay Slot这个概率,不是很清楚,于是网上搜索了一下资料。
我们可以将Delay Slot翻译为延迟槽。流水线结构的CPU在执行分支branch或者跳转jump指令时,由于此过程时间比较长,需要延迟一下,故可在此段时间内执行下一条指令,这就是branch delay slot的概念。
但如果在延迟槽的时间内执行一条未译码的指令时(也就是该指令来不及译码,延迟槽就结束了),会发生此类中断(SH2A为例)。所以常常可见编译器将高级语言翻译为汇编代码时,插入NOP指令来等待延迟。
-----------------------------------------------------
先看段代码:(取自 linux 2.6.17 for godson2)
801ea9d4: 02202021 move a0,s1
801ea9d8: 27a50014 addiu a1,sp,20
801ea9dc: 0c0ce551 jal 80339544 <pcibios_resource_to_bus>
801ea9e0: 02403021 move a2,s2
801ea9e4: 8e240010 lw a0,16(s1)
...
pcibios_resource_to_bus 的原型是:
void __devinit
pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, struct resource *res);
其中,在有HOTPLUG的情况下
__devinit <===> __init <===> __attribute__ ((__section__ (".init.text")))
表示把该 pcibios_resource_to_bus 生成的机器码置于初始化代码节(详细定义于include/linux/init.h)
jal (jump and link) 类似于x86 的 call
回到最上面的汇编码,很明显在调用 pcibios_resource_to_bus 前,先要向 a0, a1, a2 中置入3个参数, 可是我们看到第三个参数居然在 jal 后面!这就是 branch delay slot,从名字猜测应该是跳转延迟,也就是当执行到 jal 这条指令时,延迟一下,把下面的 move 指令执行完后再执行这条 jal 。
一直以来就这样理解,有点困惑,今天特意查了下:(取自维基百科)
Many of these early RISC designs also shared a not-so-nice feature, the branch delay slot. A branch delay slot is an instruction space immediately following a jump or branch. The instruction in this space is executed whether or not the branch is taken (in other words the effect of the branch is delayed). This instruction keeps the ALU of the CPU busy for the extra time normally needed to perform a branch. Nowadays the branch delay slot is considered an unfortunate side effect of a particular strategy for implementing some RISC designs, and modern RISC designs generally do away with it (such as PowerPC, more recent versions of SPARC, and MIPS).
可以看出,上面的 "move a2, s2" 是位于 branch delay slot 中的,应该是跳转类型的指令执行时间相对来说有点长,需要处于 branch delay slot 中的指令,占据 ALU 来赢去跳转类型指令相对多的执行时间。
如果把 "move a2, s2" 移到 jal 指令前,那处于branch delay slot 的就是 "lw a0,16(s1)", 很明显当CPU执行到"jal 80339544" 时,由于时间稍长,那 "lw a0, 16(s1)" 就会被执行,很明显这将导致传给 pcibios_resource_to_bus 的第一个参数被覆盖.显然这类指令顺序的调整是编译器干的.

文章评论0条评论)

登录后参与讨论
我要评论
0
3
关闭 站长推荐上一条 /3 下一条