В современных микроархитектурах с переименованием регистров стоимость реализации флагов или не флагов очень похожа. Основное различие, о котором я могу думать, состоит в том, что некоторые флаги указывают характеристики значения (является ли значение отрицательным? Является ли значение нулевым? Имеет ли значение четное или нечетное четность?), В то время как некоторые представляют событие, которое произошло во время предыдущей операции (имела ли инструкция add выполнение или переполнение?) Это привело к неидеальной ситуации на MIPS, когда вы хотели симулировать 64-битное сложение на 32-битной архитектуре (или 128-битное сложение на 64-битная архитектура.) На большинстве архитектур с флагом переноса имеется специальныйadd-with-carry
инструкция, которая включает флаг переноса из предыдущей инструкции добавления. Это делает моделирование арифметики с высокой точностью относительно недорогим на многих архитектурах с регистрами флагов.
С другой стороны, тестирование N-битного регистра на ноль или не на ноль на самом деле удивительно дорого. Чтобы проверить N-битный регистр на ноль, вам нужно выполнить N-битную операцию NOR, которая требует уровней логики для вычисления. На архитектурах с регистрами флагов дополнительная логика для вычисления нуля / не нуля в конце этапа ALU может привести к замедлению тактового генератора (или заставить ALU выполнять две операции цикла). По этой причине, я думаю, некоторые В архитектурах, как в SPARC, было две версии каждой арифметической операции: одна для установки флагов, а другая - нет.O ( журналN)
Но MIPS здесь ничего не сохраняет. Они просто перенесли проблему в другое место. На MIPS есть branch-on-equal
инструкция. Это означает, что на самом деле инструкция ветвления должна иметь этап ALU (включая что-то вроде побитовой xor
операции, за которой nor
следует сокращение до одного равного / не равного бита), прежде чем определять, каким образом идет ветвление.
Архитектура DEC Alpha пыталась разделить разницу, используя хитрость. У DEC Alpha не было регистров флагов, но также не было branch-on-equal
инструкции. Вместо этого все инструкции перехода смотрят на состояние единого регистра общего назначения. Там будет branch-on-zero
, branch-on-not-zero
, branch-on-less-than-zero
и т.д. Хитрость заключается в том, что вы можете дать каждый общего назначения зарегистрировать дополнительный бит 65 - й , который говорит вам ли остальные 64 бита равны нулю или нет. Это больше похоже на наличие регистра флагов: все инструкции перехода смотрят на один бит (который уже рассчитан), чтобы принять свое решение, но теперь вы вернулись к выяснению, как вычислить этот дополнительный нулевой бит индикатора во время обычного АЛУ цикл. (И вы все еще не можете сделать арифметику с высокой точностью, просто взглянув на флаг переноса из предыдущей операции.)
Блуждающая логика
источник
1 С точки зрения ISA
Наличие инструкций по тестированию, которые устанавливают только флаги, - это просто способ уменьшить давление в регистре в архитектурах с отсутствием регистра. Если у вас достаточно регистров, просто измените один из них и проигнорируйте результат. Хитрость в том, чтобы иметь регистр 0 с входным значением 0, это всего лишь уловка кодирования, удобная, когда у вас достаточно регистров, что фиксация одного из них в 0 лучше, чем увеличение количества инструкций. Тогда его удобно использовать и в качестве цели (это уменьшает количество ложных зависимостей).
Кодировка снова. Если вы закодируете условие в прыжках, у вас будут прыжки с 3 операндами (два сравниваемых объекта и цель перехода), два из которых вы хотите использовать в качестве непосредственных значений, один из которых вы хотите иметь большой размер возможно (переходы часто имеют свой собственный формат кодирования, чтобы цель могла использовать как можно больше битов). Или вы отбрасываете возможности.
Использование флагов дает вам больше возможностей для их установки. Не только операции сравнения могут устанавливать флаги, но и все, что вы хотите. (С учетом того, что чем больше у вас операций, которые устанавливают флаги, тем тщательнее вы должны быть уверены, что последняя операция, которая устанавливает флаги, является той, которую вы хотите). Если у вас есть флаги, вы можете протестировать количество условий (часто 16), умноженных на количество инструкций, которые могут установить флаги (Если вы не используете флаги, вы получите примерно столько же условных переходов, сколько вы есть вещи для тестирования или есть вещи, которые вы не позволяете тестировать так же легко (например, переносить или переполнять).
2 С точки зрения исполнителя
Тестирование флагов легко и может быть сделано быстро. Чем сложнее ваш тест, тем больше он будет влиять на время цикла (или структуру конвейера, если вы конвейерны). Это особенно верно для более простых реализаций: когда вы переходите к высокопроизводительному процессору, используя все приемы книги, эффект довольно минимален.
Наличие флагов означает, что многие инструкции имеют несколько результатов (естественный результат и каждый из измененных флагов). А из микроархитектуры POV многократные результаты плохие (вы должны следить за их связью). Когда у вас есть только один набор флагов, которые вводят зависимости (ненужные, если флаг не используется), вы должны обрабатывать так или иначе. Опять же, это особенно верно для более простых реализаций: когда вы переходите к высокопроизводительному процессору, использующему все приемы книги, дополнительные трудности затмеваются остальной частью процессора.
источник
На 32-битном компьютере команда «добавить с переносом», используемая как часть последовательности сложения с множественной точностью, должна принимать операнды на 65 битов и вычислять сумму в 33 бита. Спецификации регистра источника будут определять, откуда должны поступить 64 бита операнда, а спецификация регистра назначения скажет, куда должны идти младшие 32 бита результата, но что делать с операндом «добавить один дополнительный» или старшим битом. результата? Разрешить указывать в качестве части инструкции, откуда должен поступать дополнительный операнд и куда должен идти дополнительный результирующий бит, было бы умеренно полезно, но, как правило, это было бы не так полезно, чтобы оправдать дополнительное поле в коде операции. Наличие фиксированного «местоположения» для обработки флага переноса может быть немного неудобным с точки зрения планирования команд, но это '
Если кто-то пытался создать набор команд, чтобы разрешить арифметику с множественной точностью, но каждая команда была ограничена двумя 32-разрядными операндами и одним 32-разрядным операндом-адресатом, можно было бы реализовать 64-разрядное «добавление» в четырех инструкциях: «набор От r5 до 1, если r0 + r2 будет нести или обнулять иначе; вычислить r4 = r1 + r3; вычислить r5 = r4 + r5; вычислить r4 = r0 + r2 ", но для выхода за пределы этого потребуется три инструкции для каждого дополнительного слова. Наличие флага переноса в качестве дополнительного источника и места назначения снижает стоимость до одной инструкции на слово.
Отметим, между прочим, что наличие бита инструкции, управляющего тем, обновляет ли команда регистр флага, может способствовать выполнению не по порядку, поскольку команды, которые используют или модифицируют биты флага, должны сохранять свою последовательность относительно друг друга, но инструкции, которые не могут ни того, ни другого не могут быть свободно переставленным. Учитывая последовательность:
исполнительный модуль может довольно легко распознать, что третья инструкция может быть выполнена без необходимости ждать чтения данных
[r1]
, но если бы была вторая инструкция, это былоadds r0,r0,r2
бы возможно только в том случае, если исполнительный модуль мог гарантировать, что к тому времени что-либо попытается использовать В флагах нулевой флаг будет содержать значение, установленное в третьей инструкции, но флаг переноса будет содержать значение во второй.источник
Простой ответ ... быстрая дешевая операция с памятью, которая не требует абсолютно никакого внутреннего использования, кроме самой инструкции. Его можно использовать как bool-стек без стека или бита процесса, без памяти.
источник