Вложений: 2
Проектирование процессора
Как обладатель РЛК "Электроника КР-03", после освоения принципов программирования вообще и изучения схемы, как-то быстро вдруг родилось желание:
- Разработать компьютер на своей архитектуре
- Использовать процессор собственной архитектуры
Что превратилось в хобби на всю последующую жизнь.
Изучив много справочников по процессорным системам многих отечественных серий, к концу 90-х появились первые наброски эмуляторов собственных моделей процессоров. Однако, везде всплывали проблемы разного рода. То загрузка данных в регистры не была проработана, то ветвления не продуманы.
И все 20 лет просто не приносили никакого результата, хотя я и написал несколько рабочих эмуляторов РАДИО-86РК и эмулятор процессора i8086.
Из опытов с i8086 с его странным машинным кодом 00 как команда ADD, а не NOP, был выработан основной постулат, что:
- Как и с текстом, код 00 должен означать "терминацию" цепочки - HLT (Останов)
И вот в 2019 году удалось, наконец-то, сформировать некий концепт.
Глядя на шестнадцатеричный дамп с его чередованием цифр с буквами, была предпринята попытка разработать архитектуру такого процессора, система команд которого была бы ближе к восприятию человеком именно на уровне шестнадцатеричного кодирования. То есть, что человеческое восприятие при беглом просмотре успевает вырвать из контекста, то должен делать и дешифратор команд.
- Коды A0..A9 воспринимаются как "один из десяти Аккумуляторов" - пусть они будут командами активации одного из Аккумуляторов
- Коды B0..B9 воспринимаются как "одна из десяти Баз/Буферов" - пусть они будут командами активации одного из Буфера
- Коды C0..C9 воспринимаются как "один из десяти Счётчиков" - пусть они будут командами активации одного из Счётчиков
- Коды D0..D9 воспринимаются как "один из десяти Девайсов" - пусть они будут командами активации одного из Устройств Ввода-Вывода
Получается всего 30 Регистров Общего Назначения + 10 УВВ.
Для нормального функционирования АЛУ-операций требуется, как минимум, пара операндов. Здесь очень кстати подходят коды:- AA/AB/AC/AD - как операнды (A,A) / (A,B) / (A,C) и (A,D)
- BA/BB/BC/BD - как операнды (B,A) / (B,B) / (B,C) и (B,D)
- CA/CB/CC/CD - как операнды (C,A) / (C,B) / (C,C) и (C,D)
- DA/DB/DC/DD - как операнды (D,A) / (D,B) / (D,C) и (D,D)
И здесь остаётся лишь найти группу кодов под АЛУ-Операции. В самой АЛУ-операции необходимо выбирать индекс правого операнда, так как левый - выбирается до АЛУ-операции как приёмник результата:- 0A..9A - операция Add, где цифра - индекс правого операнда
- 0B..9B - операция suB, где цифра - индекс правого операнда
- 0C..9C - операция and(Conjunct), где цифра - индекс правого операнда
- 0D..9D - операция or(Disjunct), где цифра - индекс правого операнда
- 0E..9E - операция Eor(Xor), где цифра - индекс правого операнда
- 0F..9F - пересылка mov(For), где цифра - индекс правого операнда
Тем самым:- код "CB C1 2A" означает "ADD C1,B2"
- код "BA B2 3E" означает "EOR B2,A3"
Легко вникнуть, легко освоиться, легко кодировать!
Вот полная таблица:
Код:
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| .0 | .1 | .2 | .3 | .4 | .5 | .6 | .7 | .8 | .9 | .A | .B | .C | .D | .E | .F |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| 0. | HLT | | | | | | | | | | ADD | SUB | AND | OR | EOR | MOV |
| | | D0+1 | D0+2 | D0+3 | D0+4 | D0+5 | D0+6 | D0+7 | D0+8 | D0+9 | R,T0 | R,T0 | R,T0 | R,T0 | R,T0 | R,T0 |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| 1. | | | | | | | | | | | ADD | SUB | AND | OR | EOR | MOV |
| | D1+0 | D1+1 | D1+2 | D1+3 | D1+4 | D1+5 | D1+6 | D1+7 | D1+8 | D1+9 | R,T1 | R,T1 | R,T1 | R,T1 | R,T1 | R,T1 |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| 2. | | | | | | | | | | | ADD | SUB | AND | OR | EOR | MOV |
| | D2+0 | D2+1 | D2+2 | D2+3 | D2+4 | D2+5 | D2+6 | D2+7 | D2+8 | D2+9 | R,T2 | R,T2 | R,T2 | R,T2 | R,T2 | R,T2 |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| 3. | | | | | | | | | | | ADD | SUB | AND | OR | EOR | MOV |
| | D3+0 | D3+1 | D3+2 | D3+3 | D3+4 | D3+5 | D3+6 | D3+7 | D3+8 | D3+9 | R,T3 | R,T3 | R,T3 | R,T3 | R,T3 | R,T3 |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| 4. | | | | | | | | | | | ADD | SUB | AND | OR | EOR | MOV |
| | D4+0 | D4+1 | D4+2 | D4+3 | D4+4 | D4+5 | D4+6 | D4+7 | D4+8 | D4+9 | R,T4 | R,T4 | R,T4 | R,T4 | R,T4 | R,T4 |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| 5. | | | | | | | | | | | ADD | SUB | AND | OR | EOR | MOV |
| | D5+0 | D5+1 | D5+2 | D5+3 | D5+4 | D5+5 | D5+6 | D5+7 | D5+8 | D5+9 | R,T5 | R,T5 | R,T5 | R,T5 | R,T5 | R,T5 |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| 6. | | | | | | | | | | | ADD | SUB | AND | OR | EOR | MOV |
| | D6+0 | D6+1 | D6+2 | D6+3 | D6+4 | D6+5 | D6+6 | D6+7 | D6+8 | D6+9 | R,T6 | R,T6 | R,T6 | R,T6 | R,T6 | R,T6 |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| 7. | | | | | | | | | | | ADD | SUB | AND | OR | EOR | MOV |
| | D7+0 | D7+1 | D7+2 | D7+3 | D7+4 | D7+5 | D7+6 | D7+7 | D7+8 | D7+9 | R,T7 | R,T7 | R,T7 | R,T7 | R,T7 | R,T7 |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| 8. | | | | | | | | | | | ADD | SUB | AND | OR | EOR | MOV |
| | D8+0 | D8+1 | D8+2 | D8+3 | D8+4 | D8+5 | D8+6 | D8+7 | D8+8 | D8+9 | R,T8 | R,T8 | R,T8 | R,T8 | R,T8 | R,T8 |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| 9. | | | | | | | | | | | ADD | SUB | AND | OR | EOR | MOV |
| | D9+0 | D9+1 | D9+2 | D9+3 | D9+4 | D9+5 | D9+6 | D9+7 | D9+8 | D9+9 | R,T9 | R,T9 | R,T9 | R,T9 | R,T9 | R,T9 |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| A. | REG | REG | REG | REG | REG | REG | REG | REG | REG | REG | ARG | ARG | ARG | ARG | CLR | NOT |
| | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A,A | A,B | A,C | A,D | AF | AF |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| B. | REG | REG | REG | REG | REG | REG | REG | REG | REG | REG | ARG | ARG | ARG | ARG | CLR | NOT |
| | B0 | B1 | B2 | B3 | B4 | B5 | B6 | B7 | B8 | B9 | B,A | B,B | B,C | B,D | BF | BF |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| C. | REG | REG | REG | REG | REG | REG | REG | REG | REG | REG | ARG | ARG | ARG | ARG | CLR | NOT |
| | C0 | C1 | C2 | C3 | C4 | C5 | C6 | C7 | C8 | C9 | C,A | C,B | C,C | C,D | CF | CF |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| D. | REG | REG | REG | REG | REG | REG | REG | REG | REG | REG | ARG | ARG | ARG | ARG | CLR | NOT |
| | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D,A | D,B | C,D | D,D | DF | DF |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| E. | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT |
| | E000 | E100 | E200 | E300 | E400 | E500 | E600 | E700 | E800 | E900 | EA00 | EB00 | EC00 | ED00 | EE00 | EF00 |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| F. | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT | INT |
| | F000 | F100 | F200 | F300 | F400 | F500 | F600 | F700 | F800 | F900 | FA00 | FB00 | FC00 | FD00 | FE00 | FF00 |
+----+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
Где:- коды E0..FF работают как программное прерывание на адреса E000..FF00, при этом в регистрах B0 и C0 сохраняется "адрес возврата"
- код CF буквально инвертирует "Флаг CF"
Регистр A0 выполняет функцию PSW для хранения флагов:
- AF - Арифметический Флаг (аналог SF)
- BF - Буферный Флаг (Арифметическое переполнение, аналог OF)
- CF - Флаг Переноса
- DF - Дифференциальный Флаг (аналог ZF, только наоборот - NZ)
Практически, это - весь набор команд.
Чтобы начать программировать, даже в таблицу заглядывать не стоит: Всё "на своих местах" в буквальном смысле.
Причём, коды BCD с 01 по 99 работают как префиксы адресации ячейки памяти, где D0-D9 - "Двойной регистр" / "Регистровая пара" B0:C0..B9:C9.
- код "CB C1 2A" означал "ADD C1,B2", а с префиксом "CB C1 54_2A" означает "ADD C1,[D5+4],B2"
- код "BA B2 3E" означал "EOR B2,A3", а с префиксом "BA B2 54_3E" означает "EOR B2,[D5+4],A3"
- код "CF" означал "NOT CF" (CMC), а с префиксом "54 CF" означает "JCF [D5+4]"
- код "C1" означал активацию регистра C1 как приёмника результата для АЛУ, а с префиксом "54_C1" означает "MOV [D5+4],C1"
Как можно заметить, префиксы вносят значительную гибкость, а флаговые операции становятся командами ветвления.
Для фанатов программирования машинного кода освоить кодирование под такой процессор будет как никогда легко!
Вот схема рабочего прототипа 2019 года:
Вложение 79047
А вот аккуратный эскиз процессора (отсутствуют блок регистрового файла и блок АЛУ).
Вложение 79048
JavaScript-эмулятор доступен здесь.
Эмулятор моего процессора под РАДИО-86РК - здесь.
Как можно видеть, этот процессор легко эмулируется даже на ВМ80.
(Концептуально, правда, эмуляторы устарели за прошедшие годы. Но для ознакомления - вполне подходят.)
P.S.: Далее перейду к более серьёзным работам - разработанным Verilog-моделям и "маргинальным указателям", с помощью которых появились команды LEA и XLAT.
Вложений: 2
Ещё не 16-битный, но уже не 8-битный...
Цитата:
Сообщение от
UncleDim
(где взять не преклонного возраста людей, согласных кодить в кодах?))
Изначально всё проектировалось, чтобы ПЗУ с программой заменить на макетные платы и шестнадцатеричные тумблеры (ссылка) в количестве от 512 штук (под табло механического дампа на ввод программы из 256 байтов).
Цитата:
Сообщение от
i8088
Alikberov, а NOP какой код у Вас?
Очень любопытный вопрос!
С одной стороны, под NOP'ом может использоваться любая операция:- коды A0..D9 (REG A0..D0) для активации левого операнда-приёмника могут повторяться много раз
- коды AA..DD (ARG A,A..D,D) для определения АЛУ-операндов могут повторяться много раз
- коды AE..DF (CLC/CMC и т.д.) могут повторяться много раз
Но, это - только в изначальном варианте. Так как сейчас работаю над "строгим дешифратором команд", который не допускает повторения однотипных инструкций:
- последовательность операций REG A7 и REG A5 составляются в одну - REG A75 (нужен регистровый файл побольше)
- последовательность операций CMC и CLC, так как CMC перед CLC бессмысленна, образует новую операцию
- последовательность операций CMC и CMC, так как двойная CMC бессмысленна, образует новую операцию
То есть, процессор хоть и не "нейросеть", но вполне способен в таком контексте выполнять "скрытые операции".
Цитата:
Сообщение от
i8088
А переходы?
Выше я привёл пример же:- код "CF" означал "NOT CF" (CMC), а с префиксом "54 CF" означает "JCF [D5+4]"
То есть, CMC с префиксом - условный переход.
Так как имеется 32 INT'а (коды E0..FF), в подпрограммах (в JavaScript-эмуляторе с "Гонками") реализованы "нормальные" JC/JNC на абсолютные адреса (или относительные).
МАРГИНАЛЫ
В знакомой всем IA-32 / x86 имеются механизмы вычисления абсолютного адреса:- LEA EBX,[EBX+EBX*2+3] - эквивалент EBX += EBX * 2 + 3
- ADD EBX,[EBX+EBX*2+3] - а вот здесь такой указатель не сработает и выдаст исключение
Инженеры Intel переложили всю ответственность за использование подобных указателей на программиста. Хотя, можно было бы подправить их интерпретацию:- ADD EBX,[EBX+EBX*2+3] мог бы работать как ADD EBX,(EBX+EBX*2+3) - EBX += EBX*3+3
- ADD [EBX+EBX*2+3],EBX - вот тут проблема, так как нельзя выполнить как EBX*3+3 += EBX
В таких случаях, так как "ADD EBX,[EBX+EBX*2]" использует адресацию "из ряда вон!", условно она стала обозначаться как "маргинальная".
Также в x86 инструкцию можно составить искусственно и так:
- MOV EAX,CS: DS: ES: FS: GS:[EBX] - указано целых пять префиксов, четыре из которых - игнорируются (маргинальные префиксы?)
Программе это ничего путного не даст, но внутреннему отладчику исключений может нести некую закодированную информацию (в зависимости от порядка префиксов).
И я много внимания уделил механизмам отлова "маргиналов", чтобы исключить вообще такие неприятные ситуации.
То есть, из таблицы выше, вот такие примеры:- код "CB C1 2A" означал "ADD C1,B2", а с префиксом "CB C1 54_2A" означает "ADD C1,[D5+4],B2"
- код "CB C1 2A" означал "ADD C1,B2", а с префиксами "CB C1 54_58_2A" означает "ADD C1,[D5+D5+48],B2" с "маргиналом"
- код "BA B2 3E" означал "EOR B2,A3", а с префиксом "BA B2 54_3E" означает "EOR B2,[D5+4],A3"
- код "BA B2 3E" означал "EOR B2,A3", а с префиксами "BA B2 54_58_3E" означает "EOR B2,[D5+D5+48],A3" с "маргиналом"
То есть, количество префиксов перед инструкцией ничем не ограничивается и может достигать десятков и сотен. Правая тетрада префикса, как уже можно догадаться, как часть BCD накапливается в аккумуляторе смещения.
А вот левая - указывает на регистровую пару B:C под псевдонимом D. И если указывать нулевое смещение, можно "маргинализировать" адрес (подавлять его):- код "CB C1 50_2A" работает как "ADD C1,[D5+0],B2"
- код "CB C1 50_50_2A" как "ADD C1,[D5+D5+0],B2" уже не работает: Цепочка "50_50" - "маргинальна" и указатель "подавлен". Операция работает как "ADD5 C1,B2"
- код "CB C1 50_50_50_2A" как "ADD C1,[D5+D5+D5+0],B2" уже не работает: Цепочка "50_50" - "маргинальна" и указатель "подавлен", но указан в третьем префиксе. Операция работает как "ADD5 C1,[D5+0],B2"
Думаю, основную суть уже уловить можно.
Но, что такое этот "ADD5"? Как работает эта "маргинализованная" инструкция?
Лично я пока ещё не определился. Формально - это команда "внешнего АЛУ#5". Обращение к сопроцессору.
То есть, технически код "80_80_70_70_0A" как "ADD87" можно использовать с сопроцессором i8087 как "FADD" - все "маргиналы" процессор (модель на Verilog) пока никак не обрабатывает, а лишь сигнализирует на выводе "MRG" для внешнего буфера, как "M1" - машинный цикл выборки операции.
То есть, масштабируемость архитектуры уже поддерживается на самом базовом уровне.
ДЕШИФРАТОР АЛУ
Обычно в процессорах допускаются бессмысленные операции, типа "MOV A,A", "CMP A" и т.д.
Так как у меня регистр A0 выполняет функцию PSW, операции типа "ADD A0,A0" как "ADD PSW,PSW" бессмысленны и на аппаратном уровне помечаются особыми признаками.
Всего получается восемь таких признаков:- M - наличие "маргинала" перед инструкцией
- V - наличие "нормального указателя"
- A_rcv - используется A0/PSW как приёмник результата
- D_rcv - используется Порт (Device) как приёмник результата
- E - признак эквивалентности операндов ("приёмник" и "источник" - один регистр/порт)
- A_trs - используется A0/PSW как источник
- D_trs - используется Порт (Device) как источник
- F_bit - признак не АЛУ операции - FOR/MOV
На этом фоне, с учётом всех исключений, получается солидная таблица АЛУ-команд.
Изначально их было шесть - ADD / SUB / AND / OR / EOR и MOV. А стало:
Вложение 79052
Вот скриншот прогона отладки дешифратора команд на Verilog HDL:
Вложение 79054
Как можно заметить, многие инструкции (ситуации) ещё не определены и появились инструкции LEA, LEX (аналог XLAT) и ORD (аналог сортировочной перестановки регистров совмещённой с SHR).
Ознакомиться с кодированием инструкций, используя сложные "указатели" и "маргиналы", можно по ссылке.
P.S.: Нетрудно заметить, что с префиксами и "маргиналами" система команд стала значительно сложнее и серьёзнее. А как 8-битная архитектура уже близко подошла к i8086.
640 тысяч Аккумуляторов хватит всем!
Обычно процессор устроен чисто как исполнительное вычислительное устройство, выполняющее во времени одну конкретную операцию, не оглядываясь назад с разбором контекста кода.
Например, у i8080 последовательность
как цепочка
Код:
MOV A,A
MOV A,B
MOV A,C
MOV A,D
MOV A,E
Просто бессмысленна и работает чисто декоративными NOP'ами на 20 тактов перед ключевой «MOV A,E».
Чисто гипотетически можно представить инструкцией «MOV A,ABCDE» с операндом «ABCDE» в качестве регистра-транслятора…
Процессор просто последовательно выполняет цепочку команд, не задумываясь дальше одной операции.
А что, если…
Научить дешифратор команд учитывать предыдущий код?
РЕЗИНОВЫЙ РЕГИСТРОВЫЙ ФАЙЛ
Для читателя темы, который уже чуточку вник в парадигму архитектуры, будет легче понять кодирование инструкций.
Приведу небольшой пример…
Как написано в самом начале, шестнадцатеричные коды A0…A9 служат для выборки конкретного одноимённого аккумулятора.
- код «A1» активирует регистр-аккумулятор A1
- код «A1 A2» активирует сначала регистр-аккумулятор A1, а затем активирует A2
- код «A1 A2 A3» активирует сначала регистр-аккумулятор A1, а затем активирует A2, но в конце-концов активирует A3
Что происходит? Это - те самые любимые NOP'ы???
Так быть не должно: Эзотерикой пахнуть просто недопустимо!
Так, при добавлении довольно нехитрой процедуры проверки ближайшего недавнего кода, дешифратор команд теперь может аккумулировать индексы самого регистра:- код «A1 A2» активирует регистр-аккумулятор A12
- код «A1 A2 A3» активирует регистр-аккумулятор A123
Продолжив совершенствовать дешифратор команд, можно ключевую команду доработать в том же ключе:- код «6F» является командой «MOV A123,A6»
- код «6F 7F» является сначала командой «MOV A123,A6», а затем «MOV A123,A7»
- код «6F 7F 8F» является сначала командой «MOV A123,A6», а затем «MOV A123,A7», но в конце-концов «MOV A123,A8»
Теперь такой поток команд интерпретируется как:- код «6F» является командой «MOV A123,A6»
- код «6F 7F» является командой «MOV A123,A67»
- код «6F 7F 8F» является командой «MOV A123,A678»
Тем самым, теперь можно сказать:
Код:
A1 A2 A3 A4 A5 6F 7F 8F 9F 0F
Это составная инструкция «MOV A12345,A67890»…
То есть, процессор хоть и 8-битный, но количество регистров в нём практически ничем не ограничивается и может достигать сотен, тысяч и миллионов…
P.S.: Новое слово в концепции «процессорных секций»???