一个Branch Delay Slot的问题
在毛德操《嵌入式系统》中有这样的内容:
SUB r2, r3, r2
BEQ r2, 0, finished
ADD r2, r4, r2
...........
这里的意图是从寄存器r2的内容减去r3的内容,如果结果为0,就转移到标号为finished的程序段,而那段程序则因此而可以假定开始时r2的内容必定为0。……可是这里的条件转移指令BEQ在完成转移,CPU开始从finished处取下一条指令之际,流水线中紧跟在后面的ADD指令也已经执行完毕了,于是当开始执行finished时r2的内容不为0……这里的原因在于ADD指令的位置恰好在转移空当上。最简单的解决办法就是在每条转移指令后面放上一条NOP指令。可是这样就浪费了,所以实际上总是把转移目标(在这里是finished)处的第一条指令移过来,放在转移指令后面……
有两个问题:
1、按照3级流水线,转移后面的ADD指令应该处于decode阶段,而不是execute阶段,怎么会已经执行完毕从而改变r2的内容呢?
2、把标号finished处的第一条指令移到转移指令BEQ的后面,如果BEQ指令执行的结果是跳转到finished处当然是对了;如果条件比较的结果不是跳转而是继续向下执行,结果不就有问题了吗?
谁能解释一下,谢谢
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
1.流水线互锁下,不会有逻辑上的冲突。如果不互锁,则不能这么写代码。
2.这属于分支预测,如果预测错误,为了保证结果正确,是要被“惩罚”的
“惩罚”是将流水线上错误分支上的指令清洗掉,再重新载入正确分支上的指令吗?如果是这样,如果流水线上错误分支上的指令已经造成了对寄存器的更改,如何保证被正确恢复?
流水线互锁下好像相关资料很少。我关心的是,这种分支预测错误带来的问题对程序设计是否透明?从程序员的角度,什么时候应该注意这种分支预测错误带来的问题。
分支预测错误一般来说是CPU全权代理了
可以做一点软流水方面的,不过也是编译器代理。用汇编的话,可以用有用的指令填充延时槽。
跳转指令需要2个指令周期完成分支预测,而add等指令需要1个指令周期就可以完成。这样它的第二个指令周期刚好作为延时槽执行一条add指令。
所以要看程序是否允许这样了。实际上大多数情况下,都是放nop在延时槽内!
这边问一下, 类似这种Delay Slot处放指令的处理, 是在C语言等高级语言在被编译为汇编代码时由编译器处理的, 还是说在汇编代码级别由汇编器(as, gas)把汇编代码编译为二进制代码时处理的?
如果是第二种, 则手工书写汇编代码就要考虑delay slot等这些东西了(岂不是很烦?).
还有就是LZ说的三级流水线, 这种假定不太准, 5级流水的RISC CPU, X86有更深级的流水线.
如果有大大给我能详细讲一下分支预测, 就非常感谢了.
是在C语言等高级语言在被编译为汇编代码时由编译器处理的
但是,手工书写汇编代码就要考虑delay slot等这些东西,烦不烦看个人感受,你要是说只有汇编程序员才是真正的程序员我也认同你
某个版本的ARM好像有9级流水,经典的MIPS是5级流水的。x86_64有10几-20几吧?(这个不知道,瞎猜的 )你看一下Intel的手册就知道了
上面各位的回复中两种意见都有
一种认为分支预测错误的恢复由硬件管理,因而对程序完全透明
一种认为在汇编一级要加以处理。
到底哪种对呢?
X86流水线更长,但好像以前没有听说需要在汇编中考虑分支预测的问题的。此外还有乱序并发执行,但似乎乱序执行的前提是相邻指令没有干扰。
恢复由硬件管理(即逻辑上正确,损失的只有惩罚),但有些硬件并不可恢复,即便可以恢复,你也不可坐视不管。