Нет, я говорил именно про архитектуру фон Неймана. Там данные могут находиться как и в ОЗУ, так и вместе с кодом (в отдельном куске памяти, но все равно). И поэтому мне кажется, что дублировать придется.
В архитектуре фон Неймана и данные и код лежат в общем адресном пространстве и команды доступа к ним одинаковы (за исключением операции записи в ROM кода, которая может не выполняться или выполняться очень разными способами) и соответственно ничего дублировать не нужно вообще.
мультиплексоры "обхода" регистров (с выбором из четырех вариантов: исходный байт, байт 0000 0000, байт 0000 0001, байт 1111 1111),
Подача констант вместо данных из регистра или шины это интересно и полезно, но я вообще-то имел в виду проще, только лишь замену байта из регистра на байт с шины.
сейчас делаю битовые операции и сдвиги в ALU. Битовых операций я решил сделать восемь (not a, not b, a and b, a or b, a xor b, a nand b, a nor b, a xnor b).
Не очень понятно зачем так много битовых операций, но если хочется ... Кстати, Вы в курсе что
на мультиплексоре 4-в-1 можно реализовать произвольную (т.е. все возможные) логическую функцию двух переменных (ссылка не фонтан, но на нормальный учебник быстро не нашлась)? Просто подачей на его 4 входа одного из 16-ти кодов, получите 16 разных логических функций (включая и обнуление и все единицы и инверсии обоих операндов). А на мультиплексоре 8-в-1 любую (из 256 возможных) логическую функцию трёх переменных. Плюс, если не гнаться за удобством программиста, то произвольную логическую функцию можно реализовать всего одной операцией (например 2ИЛИ-НЕ или 2И-НЕ, к ней требований всего два: 1) не менее двух входов, 2) наличие инверсии хоть где-то), муторно, но можно. Обычно в процессорах ограничиваются классикой (2И, 2ИЛИ, 2XOR, 1НЕ).
На практике, из битовых операций кроме логических весьма полезны: нахождение левого/правого нулевого (или единичного, и то и другое уже излишество, решается предварительной инверсией) бита, подсчёт количества единичных битов в слове (или хотя бы чётно оно или нет), объединение двух переменных по маске из третьей (blend в командах intel), вырезание/вставка одной переменной в/из другой по индексу в третьей, сжатие/разжатие переменной по маске из другой. Всё это можно сделать и обычными логическими командами, но очень муторно. И тут важно найти баланс между усложнением процессора (а оно для этих операций огромно) и упрощением и ускорением кода (почти все эти операции выполняются редко и обычно не критичны к скорости).
Зачем Вам команда определения наличия ровно одного единичного бита в слове не очень понятно. Или это не команда, а схема в АЛУ для выполнения каких-то других команд?
Из сдвигов принципиально наличие лишь сдвигов вправо, сдвиги влево легко реализуются как сложение само с собой. Сдвиги вправо бывают двух типов: арифметические (с дублированием знакового бита) и логические (с заполнением нулями или другим операндом для длинных сдвигов). Сдвиги влево и те и другие ничем друг от друга не отличаются.
Очень желательно наличие длинных сдвигов (или через перенос, или с взятием вдвигаемых битов из другого операнда). Без них грустно и код разрастается.
Приятно наличие сдвигов более чем на один бит, но это заметно усложняет схемотехнику.
Очень востребованы команды умножения, причём часто (при соответствующей реализации) они способны заменить команды сдвига. Очень желательно иметь возможность перемножать длинные числа (т.е. получать не только младшее слово результата умножения, но и старшее).
Приятно наличие команд деления (и тоже особенно с возможностью расширения операндов), но их реальная востребованность спорна, хотя программная реализация обычно на порядок-полтора тормознее аппаратной.
Вы в курсе что взяв ПЗУ 64Кх8 можно на нём реализовать
абсолютно любую функцию двух 8-ми битных переменных? Просто подав обе переменные на адресные входы и корректно заполнив ПЗУ получим на его выходах что нам угодно. Добавив ещё адресов (увеличив объем ПЗУ) можно и переключать функции входных переменных в зависимости от кода коамнды. Добавив ещё адресную линию и несколько выходных линий у ПЗУ (увеличив объём и разрядность) можно задействовать и входной перенос и формирование флагов результата. А включив вместо или вместе с ПЗУ и ОЗУ соответствующего объёма (не менее 64К байтов) и организовав его загрузку откуда-то можно получить
перестраиваемое прямо во время работы АЛУ. Это конечно профанация упрощения процессора, однако возможно и такое.
Вообще стоило бы поинтересоваться какие вообще обычно команды реализуют аппаратно (и чего это стоит в плане затрат аппаратуры). Сделать CISC систему типа Intel x86 с её расширениями AVX и прочими у Вас не получится (места в комнате не хватит), потому в любом случае придётся как-то ограничиваться. И этим вопросом занимались очень много и долго и грамотные товарищи (включая и множество научных исследований по оптимальным вариантам реализации очень разных алгоритмов на разных системах команд), стоит если не изучить их опыт, то хотя бы глянуть какими критериями и почему они руководствовались. Готовых ссылок у меня нет, но например меня в своё время очень впечатлил выбор одних проектировщиков между аппаратной реализацией сдвигателя на любое количество битов или умножителя, они занимают почти одинаковое количество аппаратуры, а возможности и полезность заметно разная (на тех задачах, под которые проектировался процессор! не любых!), а вместе они не влезали в кристалл. Аналогично и с логическими функциями АЛУ, можно поставить 8 одинаковых мультиплексоров 4-в-1, добавить в управляющее слово 4 бита и получить реализацию
всех возможных логических функций двух переменных. Без всяких отдельных схем реализаций И, ИЛИ, НЕ, XOR, И-НЕ, ИЛИ-НЕ, НЕ-ИЛИ, НЕ-И и логикой объединения их выходов в АЛУ.
проблема состоит в минимизации числа бинарных AND и OR, и унарных NOТ.
Это противоречивое (или неполное) условие, часто можно минимизировать одни
за счёт других. А ещё есть микросхемы с числом входов более двух, что тоже позволяет минимизировать
количество корпусов микросхем (обычно ставят именно это условие, а не Ваше, они сильно не совпадают), даже за счёт усложнения логического выражения.