2

我正在为大学写一些 MIPS 代码,看看函数中的函数是如何工作的,一开始一切都很好。我正在使用WinMIP64 模拟器

然后,在我打开 BTB 之后,一切都崩溃了(它在第二个函数中陷入了无限循环)。

我快疯了,直到意识到这是因为 BTB(其中一个函数中有 ab,我想减少一些因此出现的 Branch Taken Stalls)。当我关掉它时,一切都恢复正常了。

我在下面包含了一些代码。

.data
tabla:  .byte 1,4,5
res:    .space 3 
cont:   .word 3
num:    .word 0

.text

       daddi $a0, $0, tabla  # offset element table
       daddi $a1, $0, res    # offset results table
       lb $a2, cont($0)      # $a2 = 3 (array size)
       daddi $sp, $0, 0x400  # $sp = 0x400
       jal dobles            # $ra = 0x14
       sd $v1, num($0)       # offset element count
       halt

dobles:                      #first function 

       daddi $sp, $sp, -8    # make space in stack $sp = 0x3f8
       sd $ra, 0($sp)        # 0x3f8 = $ra (0x14) 

loop:
       lb $s0, 0($a0)        # saving element from table in $s0
       daddi $a0, $a0, 1     # add 1 byte displacement to $a0  

       daddi $sp, $sp, -8    # $sp = 0x3f0
       sd $s0, 0($sp)        # 0x3f0 = tabla element 

       jal multi             # $ra = 0x38 
       sb $v0, 0($a1)        # saving result to res
       daddi $a1, $a1, 1     # displacement + 1 byte 

       daddi $a2, $a2, -1    # counter -1 
       bnez $a2, loop        # loop till counter is 0 

       ld $ra, 0($sp)        # load $ra from stack
       daddi $sp, $sp, 8     
       jr $ra 

multi:                       # second function
       ld $t0, 0($sp)        # load element from stack
       daddi $sp, $sp, 8     
       daddi $v1, $v1, 1     # count numer of elements
       dadd $v0, $t0, $t0    # element * 2
       jr $ra 

为什么会这样?对函数的调用是否对缓冲区有某种影响(我认为它只是用于分支)?如果我打开 BTB,是否可以在函数中调用函数并且没有问题?如果我想在函数中使用 BTB 和函数调用,我需要更改什么?

这不在我们的计划中,所以我在这里问。

4

1 回答 1

2

BTB 是一种分支预测结构。它对正确性的影响为零,只有性能。它在建筑上不可见。

我的猜测与 Jester 的猜测相同:您实际上(也?)启用了架构分支延迟槽:无论是否采用分支,一条bXXor指令之后的指令都会运行,从而在早期 MIPS 上隐藏分支延迟(短有序流水线,而不是超标量)。j/jXX

但实际上我在您的代码中看不到任何会在有或没有分支延迟槽的情况下中断的内容。Jester 测试并发现在第二次执行时jal multi设置$ra为;multi这是一个模拟器错误。$ra无论有无分支延迟槽,都无法正确执行代码。


根据WinMIPS64 页面

如果需要,可以实施延迟槽。使用 V1.30 还可以模拟一个简单的分支目标缓冲区。跳转或分支指令旁边的代码窗口中的 << 表示它被预测为被采用。

也许 GUI 将 BTB 和延迟槽选项联系在一起?

与往常一样,在调试器中单步执行您的代码以查看其执行方式。

如果您确定 WinMIP64 正在模拟 BTB 但没有分支延迟槽,那么您可能已经在 WinMIP64 本身中发现了一个错误。由于 BTB(以及一般的分支预测)在架构上不可见1,因此无论有无它,您的代码都必须运行相同的代码。

(除非你做了一些 MIPS ISA 允许导致“不可预测的行为”的事情,比如将两个分支背靠背放置,或者mult在执行后在几条指令中修改一条指令的输入。或者对于经典的 MIPS I,使用结果加载太早,在加载延迟槽中。)

脚注 1:在 Spectre 之外:使用侧通道使微架构状态在架构上可见。

于 2019-11-11T01:16:52.840 回答