Почему целевой буфер филиала влияет на возврат из вызовов функций? [WinMIPS64] - PullRequest
2 голосов
/ 11 ноября 2019

Я писал код MIPS для колледжа, чтобы посмотреть, как работают функции внутри функций, и сначала все работало нормально. Я использую WinMIP64 симулятор .

Затем, после того, как я включил BTB, все ломалось (он застрял в бесконечном цикле во второй функции).

Я сходил с ума, пока не понял, что это произошло из-за BTB (в одной из функций была буква ab, и я хотел уменьшить количество возникающих в результате остановок Branch Taken). Когда я его выключил, все снова заработало нормально.

Я включил часть кода ниже.

.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 и вызовы функций внутри функций?

Это не было включено в нашу программу, поэтому я спрашиваю здесь.

1 Ответ

0 голосов
/ 11 ноября 2019

BTB - это структура с предсказанием ветвлений. Это не влияет на правильность, только производительность. Это архитектурно не видно.

Мое предположение было таким же, как у Шута: вы фактически (также?) Включили архитектурную ветвь delay slot: инструкция после инструкции bXX или j/jXXзапускается независимо от того, берется ветвь или нет, скрывает задержку ветки на ранних MIPS (короткий конвейер в порядке, не суперскалярный).

Но на самом деле я не вижу в вашем коде ничего, чтосломался бы или без слота задержки ветвления. Шут проверил и обнаружил, что jal multi устанавливает $ra в multi при втором выполнении;это ошибка эмулятора. Никакое правильное выполнение вашего кода не может установить $ra таким образом, со слотами задержки ветвления или без них.


Согласно странице WinMIPS64

При желании может быть реализован временной интервал задержки. С V1.30 можно также смоделировать простой целевой буфер ветвления. << в окне кода рядом с инструкцией перехода или перехода указывает, что она прогнозируется как принимаемая. </p>

Возможно, графический интерфейс пользователя связывает воедино параметры BTB и задержки слота?

Как всегда, пошаговый код в отладчике, чтобы увидеть, как он выполняется.

Если вы уверены, что WinMIP64 имитирует BTB, но без слотов задержки ветвления, тогда, возможно, вы нашли ошибку в самом WinMIP64 . Так как BTB (и прогноз ветвления в целом) не является архитектурно видимым 1 , ваш код должен выполняться одинаково с ним или без него.

(Если вы что-то не сделаличто ISA MIPS позволяет вызвать «непредсказуемое поведение», например, поставить две ветви подряд или модифицировать входы инструкции mult в паре инструкций после ее выполнения. Или для классического MIPS I, используя результат загрузкислишком рано, в слоте задержки загрузки.)

Сноска 1: за пределами Spectre: использование бокового канала для придания микроархитектурного состояния архитектурно видимым.

...