Просмотр полной версии : x80: CISC - уже не i8080, ещё не i8086
Радио-86РК
14.05.2020, 19:31
Легенда
Eщё со школы имею мечту построить собственный компьютер на собственном процессоре. Причём, архитектуру процессора 15 лет безуспешно пытался разработать с нуля. Но дальше RISC-процессора в LogiSim дело не сдвинулось.
Хотя, схему выборки CISC-команды из памяти разработать удалось.
Сейчас разрабатываю эмулятор средствами HTML5 на JavaScript, чтобы никому ничего не нужно было скачивать и работало онлайн.
Если первый эмулятор строился на «switch-case» и это значительно усложняло разработку системы команд, то потом разработал движок с использованием шаблона на принципах «casex» Verilog, где вся система команд описывается в таблице, а скрипт при инициализации парсит её и генерирует массив из тысяч комбинаций команд. Конечно, память расходуется значительно и наблюдаются существенные просадки производительности, но именно такой эмулятор удобен, когда окончательная таблица команд всё ещё не готова и постоянно модифицируется.
Идеология
Опыт коллег (PICO-8 (https://www.lexaloffle.com/pico-8.php), MegaProcessor (http://www.megaprocessor.com/), MyCPU (http://www.mycpu.eu/), Gigatron (https://gigatron.io/) и т.д…) вдохновляет меня и собственными окольными путями пытаюсь построить собственный процессор без предрассудков: Мне не нужно экономить на простоте, чтобы где-то какой-то проводочек стал короче на миллиметр. И я не тороплюсь запустить архитектуру с колена, чтобы состряпать хоть что-нибудь и это поехало лампочками мигать или фракталы Мандельброта строить…
План прост по-идее, но сложен в перспективе, так как локально планируется переразработать всю линейку архитектуры Intel с нуля. А именно, так как i8080 и i8086 программно никак не совместимы, а система команд обоих оставляет желать лучшего, то поставил план разработать 8-битную архитектуру с расширением до 16 бит или до 32, причём с программной совместимостью в обе стороны…
Ошибки Intel прослеживаются с самого начала:
На уровне машинного кода i8080 и i8086 абсолютно несовместимы
На уровне ассемблера совместимость частичная, хоть и заявлялось о ней
Поддерживаются рудиментарные команды (i8080: 32/3A - STA/LDA; i8086: A0/A1/A2/A3), которые все не перечислишь, но в современном защищённом режиме их наличие - бессмысленно
Гибриды типа NEC V20 (https://ru.wikipedia.org/wiki/NEC_V20) пытались поправить ситуацию, но всё оказалось безнадёжным
Тем самым, был просто взят процессор i8080 во всей его красе и система команд была перераспределена из восьмеричной в шестнадцатеричную и удалены команды с 16-битными константами. И даже можно увидеть ту же систему команд i8080:
Если внимательно присмотреться, то за основу я взял тактику i8080, где инструкцию «MOV M,M» превратили в «HLT»: Всю группу MOV-блока я сдвинул в начало и перегруппировал, чтобы та самая «HLT» заняла код «00». Так как в i8086 код «00» печальным образом занимает команда «ADD», что позднее в Windows разрослось в кучу ловушек, это послужило ценным опытом, как не надо делать на стадии проектирования дешифратора команд в угоду экономии проводочков, так как сейчас дешифрацией x86-кода занимается RISC-ядро и тактические экономические трюки инженеров в 70-х просто навсегда изувечили всю систему команд!
Также и имена регистров переименованы в стиль i8086, что значительно упрощает написание кода под мой процессор в стандартных отладчиках, как та же Visual Studio…
Тем самым, у меня получилось, что:
00: MOV M,M = HLT
11: MOV BH,BH = Prefix BH/BP
22:MOV CH,CH = Prefix CH/SI
33:MOV DH,DH = Prefix DH/DI
44:MOV AL,AL = Prefix SP
55:MOV BL,BL = Prefix BL/BX
66:MOV CL,CL = Prefix CL/CX
77:MOV DL,DL = Prefix DL,DX
Чем для приложения даны 7 префиксов.
Для супервизора имеется «супер-префикс» с кодом «00», так как в «режиме ядра» операция «HLT» не нужна. Чем я убил двух зайцев:
Нету никаких привилегированных команд, которые приложению нельзя использовать. Тем самым, все коды таблицы команд приложение может использовать
Только в «режиме ядра» этот «супер-префикс» доступен и не болтается мусорным защищённым кодом в системе команд у приложений
Архитектура
Хоть процессор и походит на продвинутый вариант i8080, но это не совсем так.
В режиме супервизора «супер-префикс» 00 даёт доступ к служебному регистру #0, который переключает регистровый файл процессора. Всего предусмотрено до 128 страниц регистрового файла и процессор может выполнять до 128 задач в кольце.
Регистровый файл предусмотрен как внешняя память статического ОЗУ из отдельных регистров. Можно использовать как интегральное ОЗУ одной микросхемой памяти на 32 Кб, а можно и организовать 256 отдельных регистров/ОЗУ на 128 байтов. То есть, в отладочном стенде файл контекста можно организовать из 256 регистров, чтобы в любой момент видеть его содержимое (как в Мегапроцессоре). А в практическом исполнении просто обойтись одной микросхемой памяти…
Как уже понятно, для доступа к РОН хранящихся во внешнем статическом ОЗУ требуются такты. В этом плане процессор работает как тот же 6502 и на простые операции требуется много тактов. С другой стороны, я над этим не беспокоюсь, так как систему кешов и конвейеров никто не отменял, что никак не мешает в перспективе ускорить архитектуру в разы.
(Я уже выше сказал, что не буду совершать ошибки Intel и искать оптимальные пути на этапе проектирования, так как RISC-ядро с лёгкостью может сгладить любые издержки производительности.
А так как это - CISC-процессор, то по-любому архитектура может быть довольно сложной и затратной. Оптимизировать я её не собираюсь!)
Процессор имеет несколько особенностей, которые усложняют его архитектуру, но приближает его к уровню 16-битных.
Так, используются «запретные комбинации» статуса АЛУ, которые никогда в нормальных условиях не встречаются:
ZF PF - SKIP-режим холостого чтения команд
ZF SF - LOOP-режим выполнения команды несколько раз, один из РОН используется за счётчик
ZF SF PF - WAIT-режим, тот же LOOP-режим с прерыванием
Так, операции с портами IN/OUT доступны лишь под режимом WAIT и порт, если он существует, вернёт сигнал готовности и прервёт WAIT-цикл. Если же порта аппаратно не существует и сигнала готовности нет, режимом WAIT будет использован один из РОН в качестве счётчика. Программа по обнулённому счётчику может знать, ответил порт или нет…
Так и цикл WAIT+SUB может использоваться как операция деления, так как WAIT прерывается по флагу CF. Аппаратно легко перехватить комбинацию WAIT+SUB или LOOP+ADD внешним сопроцессором и выполнить операции DIV/MUL быстро аппаратно. Тем самым, системой команд предусматривается внешний сопроцессор, но для его операций используются трюковые комбинации стандартных команд.
Режим SKIP упрощает описание «ленивых выражений» и условных кейсов. Если Вы помните DOS с его «INT 21h» с подфункцией через код в AH, то здесь SKIP работает примерно также. Например, комбинация «LOOP 5 + INT 21» не станет вызывать «INT 21» пять раз, а вызовет один раз, но переключится в режим «SKIP 5». Тем самым, если в подпрограмме имеется стопка из «JMP», то будет пропущено 5 «JMP» режимом «SKIP». Это делает решение гораздо изящнее…
Прерывания
Процессор при любом событии всегда переходит в одну заданную точку программы, но с разной SKIP-величиной.
Обращение к INT 0-79
Переключение памяти
Переключение задач
Запрос к устройству ввода-вывода
Внешние маскируемые прерывания
Сигнал немаскируемых прерываний
Запуск ядра по сигналу RESET
Тем самым, по сигналу СБРОС процессор перепрыгнет в стандартную точку входу и пропустит семь JMP'ов в режиме «SKIP 7». Причём, СБРОС происходит не сразу, а по истечению интервала в служебных регистрах с отсчётом до 65535 тактов. Тем самым, сначала RESET срабатывает как немаскируемое прерывание и управление получает ядро. Если ядро нормально функционирует, то оно предустановит служебные счётчики и предотвратит СБРОС системы. Иначе, спустя указанное число от счётов управление снова получит ядро, но через точку запуска.
Приложения не могут напрямую обращаться к устройствам и операции «WAIT+IN/OUT» генерируют событие #4 ядру, которое уже само должно разбираться.
RISC vs RISC
Хоть процессор разрабатывается по принципам CISC-технологии (городи что хочешь), но он из неё умудрился вылезти!
И я просто переименовал его в RISC, который нужно читать не как «Reduced Instruction Set Computer», а «Rebused Instruction Set Computer». То есть, «Ребусная Система Команд», так как комбинации префиксов достигают уровня головоломки, которую тяжело переварить ассемблером и дизассемблером. Хотя эмулятор их исполняет корректно.
Потому, если Вы любитель простоты, то Вам моя технология не понравится и её можете игнорировать.
С другой стороны, если Вы - любитель головоломок и не прочь сломать мозг машинным кодом, то Вам может понравится сахар…
Сахар в машинном коде
LOOP n + SKIP => SKIP n ; Цикл из n-раз превращается в игнорирование n-инструкций
LOOP n + JMP => JMP & SKIP n ; Переход на метку и игнорирование n-инструкций
LOOP n + CALL => CALL & SKIP n ; Вызов подпрограммы и игнорирование n-инструкций внутри подпрограммы
LOOP n + INT => INT & SKIP n ; Вызов программного прерывания и игнорирование n-инструкций внутри подпрограммы
LOOP n + RET => RET & SKIP n ; Возврат из подпрограммы и игнорирование n-инструкций
LOOP n + MOV R,[IX±offset] => MOV R,[IX+Rn±offset] ; Вместо цикла индексный адрес формируется в индексно-относительный
LOOP n + MOV [IX±offset],R => MOV [IX+Rn±offset],R ; Вместо цикла индексный адрес формируется в индексно-относительный
LOOP n + NOP m => NOP n×m ; Команда NOP с задержкой на m-тактов выполняется n-раз
LOOP n + ADD => MUL n ; Без сопроцессора умножение достигается сложением в цикле
WAIT n + SUB => DIV n ; Без сопроцессора деление достигается циклом вычитания с прерыванием
WAIT n + MOV => IN/OUT ; В ожидании команды межрегистровых пересылок превращаются в команды обращения к УВВ с ожиданием готовности
LOOP n + MOV => MOV ctx ; В цикле команды межрегистровых пересылок обращаются к ячейкам регистрового файла активного контекста
HLT + MOV M,R => MOV ctrl,R ; Под «супер-префиксом» можно записать регистр страницы контекста и переключить задачу
LOOP n + HLT => EXIT n ; Запрос системы с выходом и передачей кода результата
WAIT n + HLT => SYSCALL n ; Обращение к API системы
LOOP + LOOP => reserved ; Теоретически работает, но назначения и логики не имеет
LOOP + WAIT => reserved ; Теоретически работает, но назначения и логики не имеет
WAIT + LOOP => reserved ; Теоретически работает, но назначения и логики не имеет
WAIT + WAIT => reserved ; Теоретически работает, но назначения и логики не имеет
Можно видеть, что подобные трюки увели концепцию далеко от i8080/z80 и подтянули возможности до i80286…
Система команд напоминает ребус и не понравится тем, кто любит простые решения…
LOOP 3 ; Режим повтора 3 раза
CALL MyFn ; Повторить вызов нельзя - будет пропуск SubFn0, SubFn1, SubFn2
JMP Error ; Если подфункция отсутствует, RET вернётся на этот JMP
... ; Иначе - нормальное продолжение программы
MyFn:
JMP SubFn0 ; Выполнится по CALL MyFn
JMP SubFn1 ; Выполнится по LOOP 1 + CALL MyFn
JMP SubFn2 ; Выполнится по LOOP 2 + CALL MyFn
ADD AL,DL ; Выполнится по LOOP 3 + CALL MyFn
LOOP 1 ; Пропустим JMP Error
RET
Эмуляция
Одна из первых версий эмулятора (http://htmlpreview.github.io/?https://github.com/Alikberov/x80/blob/master/emulator.old.html?speed=10&reset=1000&cycle=1024&debug=FFFF) с Монитором в стиле РАДИО-86РК. Автоматически выводится дамп, прыгает шарик с очищением поля и построением рамки, после чего выводится фигурка Тетриса, управляемая клавиатурой
Другая версия (http://htmlpreview.github.io/?https://github.com/Alikberov/x80/blob/master/emulator.html?speed=10&reset=1000&cycle=1024&debug=FFFF) эмулятора. Клавиша F4 запускает эмуляцию. Сначала выводится дамп по «D000,3BF», затем выводится подсказка по директивам, а потом запускается режим эха клавиатуры, которое глючит. Баг очень сложен и связан с неполным пониманием механизма переключения контекста от Супервизора к приложению. Ядро эмуляции спланировано неверно и его нужно полностью перерабатывать. (Если буфер клавиатуры чист, чтение порта приводит к ожиданию циклом Wait без флага CF. Приложению этот флаг нужно передать в контекст, но на уровне JavaScript теряется контроль над синхронностью и приложению возвращаются неверные флаги…)
В данный период дорабатывается версия эмулятора с путаницей переключения контекстов, так как я занимался внедрением «супер-префикса». Пустяковая доработка заняла три дня отладки и доработок алгоритмов ассемблера, дизассемблера и эмулятора. Но сама проблема пока не решена. Лишь упростились некоторые команды…
Наращивание
Как выше уже сказано, процессор спланирован как восьмибитный, но с перспективой расширения до 16 и 32.
Уже на восьми битах планируются трюки, где АЛУ может работать с 16 и 32 битами. Разница лишь в том, что в 8-битном прототипе на 32-битную операцию может уйти десятки тактов, тогда как в 32-битном прототипе - один такт.
Тем самым, на 8-битном прототипе уже можно разрабатывать 32-битные приложения и запускать их. Разница будет лишь в производительности, так как размер команд останется тем же: В отличии от i8080/z80 здесь нету 16-битных операндов, типа «LD SP,addr». Всё - 8-битное. И на 32-битном прототипе все индексы операндов - один байт.
Способы адресации
07 :MOV DL,[BX] ; Косвенно-регистровая адресация
67 :MOV DL,CL ; Регистровая адресация
A7 89:MOV DL,0x89 ; Непосредственная адресация
55 A7 89:MOV DL,[BX-119] ; Относительная адресация
E4 55 A7 89:MOV DL,[BX+AL-119] ; Индексная адресация
B8 FE 55 A7 89:MOVX DL,[BX+XX-119] ; Чтение в режиме X по индексу XX
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0A :ADD AL,[BX] ; Косвенно-регистровая адресация
6A :ADD AL,CL ; Регистровая адресация
AA 89:ADD AL,0x89 ; Непосредственная адресация
55 AA 89:ADD BL,0x89 ; Непосредственная адресация
E4 55 AA 89:ADD4 BL,0x89 ; Сложение в режиме #4
B8 FE 55 AA 89:ADDX BL,0x89 ; Сложение в цикле режима X
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
81 23:PUSH 0x0123 ; Помещение константы в стек
91 23:PUSH 0xF123 ; Помещение константы в стек
55 81 23:PUSH 0x5123 ; Помещение константы в стек
55 91 23:PUSH 0xA123 ; Помещение константы в стек
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
55 A0 23:PUSH [BX+35] ; Относительная адресация
55 B0 23:POP [BX+35] ; Относительная адресация
E4 55 A0 23:PUSH [BX+AL+35] ; Индексная адресация
E4 55 B0 23:POP [BX+AL+35] ; Индексная адресация
B8 FE 55 A0 23:PUSX [BX+XX+35] ; Индексная адресация X по XX
B8 FE 55 B0 23:POPX [BX+XX+35] ; Индексная адресация X по XX
FPGA
Естественно, есть и Verilog-модель (http://www.edaplayground.com/x/2pm6), выполняющая несколько команд.
Но, из-за плохого владения принципами Verilog, эскиз модели получился тупиковым и всё нужно переписывать с нуля…
Почему x80?
Почему из всего богатства архитектур я выбрал именно Intel?
Во-первых, с i8080 я знаком с самого детства через ВМ80 в любимом РАДИО-86РК.
Во-вторых, тот же ZX-Spectrum и GameBoy построены на Z80.
В-третьих, система команд CISC более дружелюбна, а i8086 намного легче реализовать, чем изучать 68000, так как с ним я никогда не работал непосредственно.
В-четвёртых, я не так силён в электронике, чтобы городить свой RISC с перспективой конвейерного исполнения 32 команд за такт.
Сотрудничество
Если Вы имеете возможность и способность управиться с Verilog/FPGA/CPLD, буду очень рад формированию хоть какого-то коллектива разработчиков линейки x80, x180, x280, x380…
Lethargeek
14.05.2020, 22:38
Тем самым, был просто взят процессор i8080 во всей его красе и система команд была перераспределена из восьмеричной в шестнадцатеричную и удалены команды с 16-битными константами. И даже можно увидеть ту же систему команд i8080:
Вложение 72596
"Вложение не существует или не указан идентификатор (номер). Если вы уверены, что использовали правильную ссылку, свяжитесь с администрацией"
но скажу сразу, восьмибитке нужно минимум два стека (или хотя бы команда быстрого обмена указателя стека с другими парами)
В-третьих, система команд CISC более дружелюбна,
вот категорически не согласен, всё зависит от конкретной реализации
приблизительная имха:
ARM - красава
6809 - красава
M68k - норм
Z80 - норм
PDP-11 - норм
MIPS - уныл
SPARC - ужос
8080 - ужос
x86 - ужос и кабздец
и это при том, что больше всего опыта ассемблерокодерства у меня как раз с x86
HardWareMan
15.05.2020, 07:07
https://jpegshare.net/images/02/57/0257b867c2266beaea019892b5ba9cf9.png
Эм...
https://s.fishki.net/upload/users/2019/05/22/703323/3f362e1677f727d447aaac7589a42022.gif
ИМХО
Система команд процессора должна быть дружелюбна к тому языку, который будет основным для разработки под процессор.
В данном случае, очевидно, предполагается программирование на ассемблере, но дружелюбности - не наблюдается. Болеe того, несмотря на фразу:
тактические экономические трюки инженеров в 70-х просто навсегда изувечили всю систему команд!
автор и сам попал в эту ловушку
Нету никаких привилегированных команд, которые приложению нельзя использовать.
Приложения не могут напрямую обращаться к устройствам и операции «WAIT+IN/OUT» генерируют событие #4 ядру, которое уже само должно разбираться.
Это называется скрытый запрет. Например, в PDP-11 в пользовательском режиме команда HALT запрещена и генерирует событие (прерывание), которое обрабатывает ядро и должно уже само разбираться. Слова другие, смысл тот же.
Для супервизора имеется «супер-префикс» с кодом «00», так как в «режиме ядра» операция «HLT» не нужна.
То есть, «Ребусная Система Команд», так как комбинации префиксов достигают уровня головоломки, которую тяжело переварить ассемблером и дизассемблером.
Потому, если Вы любитель простоты, то Вам моя технология не понравится и её можете игнорировать.
С другой стороны, если Вы - любитель головоломок и не прочь сломать мозг машинным кодом, то Вам может понравится сахар…
А теперь подумайте о том - сколько будет ОШИБОК в программе из за СЛОМАННОГО МОЗГА программиста?
Или может всё таки стоит облегчить написание программ человеку?
В данный период дорабатывается версия эмулятора с путаницей переключения контекстов, так как я занимался внедрением «супер-префикса». Пустяковая доработка заняла три дня отладки и доработок алгоритмов ассемблера, дизассемблера и эмулятора. Но сама проблема пока не решена. Лишь упростились некоторые команды…
Ч.И.Т.Д. Это называется - сломать МОЗГ, только не человек, а ПРОЦЕССОРУ. Хотя нет, человеку тут мозг тоже уже вынесли. Вам.
Если Вы имеете возможность и способность
буду очень рад формированию хоть какого-то коллектива разработчиков линейки x80, x180, x280, x380…
Крик души - ХОТЬ КАКОГО-ТО КОЛЛЕКТИВА.
Но существует очень хороший шанс, что в коллективе так и останется один человек
Будущее за радиационно-стойкими микросхемами. Поэтому в проектировании архитектуры надо идти только от технологии! Чтобы при прочих равных себестоимость производства у вас была ниже, чем у конкурентов. Сегодня проектировать нечто ниже 64 бит - затрачивать усилия впустую. Еще одно перспективное направление проектирование масштабируемых вычислителей. Чтобы при прочих равных обойти конкурентов по соотношению производительность/потребление, производительность/себестоимость. Ну и совсем в десятку сочетание в одной архитектуре двух вышеперечисленных! Хотя я сам балуюсь со старыми 8 битными архитектурами, но не со столь глобальными целями как у Вас. А если исходить из удобства программиста, то ассемблер для архитектуры должен получаться максимально простым и прозрачным.
надо идти только от технологии!
Будущее за радиационно-стойкими микросхемами.
себестоимость производства у вас была ниже, чем у конкурентов.
Аха - выберите любые две цели из трёх. Ибо что бы получить все три цели сразу - боюсь, придётся выложить, как минимум, несколько миллиардов у.е. для НИОКР на непонятно какой срок и помнить, что даже после истечения этого срока отбить вложения получится очень далеко не сразу. И отбить их получится - если вы угадали с тем, куда вложились.
И если брать деньги на это дело у какого-то инвестора, то все это время с плюсом - его придётся убеждать, что те хайпы, которые будут постоянно подниматься о всяких новых фишках в этих темах - это хайпы на предмет - выбить деньги у инвесторов и спустить их без результата - а вот ваша идея - это о-го-го и когда она, наконец, ещё при его и вашей жизни, начнёт приносить ....ллиарды - вы будете купаться в собственном озере на ранчо на спутнике Сатурна, любуюсь надписью "Самому крутому инвесторы тысячелетия" на его кольцах, отбиваясь от других инвесторов.
Радио-86РК
15.05.2020, 11:07
Эм...Всe инструкции видеть можно только в эмуляторе.
В архиве выложил скриншоты с таблицей команд, где можно чуточку посмотреть на некоторые комбинации и сочетания с префиксами.
Скриншоты, естественно, не все, так как комбинаций очень много. Некоторые инструкции я вручную перечеркнул графически, так как эмулятором они представлены как недокументированные и их нужно глушить как побочные.
Ещё в архив добавил весь файл эмулятора, где…
в строках 4160…4274 описывается вся система команд шаблоном
в строках 4276…4377 описываются регистры, флаги и АЛУ-операции
в строках 4653…4780 представлен знакогенератор РАДИО-86РК
строками 4867…6386 описывается ассемблером некий программный код, но много под комментарием, так как скопировано из прошлой версии эмулятора и сейчас может не работать
В общем, если браузер позволит использовать функциональные клавиши, то…
F1 делает один шаг в отладке
F4 запускает эмуляцию до точек отладки, помеченных розовым
F6/F7/F8 настраивают производительность эмуляции
ALT+P и ALT+T позволяет редактировать память или ячейки контекста
клавиш много, но они полезны только мне, как активному разработчику…
Думаю, если просто любопытно глянуть на всё это, то увидите, сколько вложено усилий и никаких «copy-paste» из интернета. Успел понаписать столько, что самому жутко всё это отлаживать.
А если вздумаете вникнуть в этот исходник, то ничего не поймёте, так как и сам уже в нём теряюсь и правлю с опаской по принципу «работает - не трожь!»: Написано местами изящно (парсер шаблона всех команд), но в общем - очень безобразно!
если вздумаете вникнуть в этот исходник, то ничего не поймёте, так как и сам уже в нём теряюсь и правлю с опаской по принципу «работает - не трожь!»
Ч.И.Т.Д.
Аха - выберите любые две цели из трёх. Ибо что бы получить все три цели сразу - боюсь, придётся выложить, как минимум, несколько миллиардов у.е. для НИОКР на непонятно какой срок и помнить, что даже после истечения этого срока отбить вложения получится очень далеко не сразу. И отбить их получится - если вы угадали с тем, куда вложились.
И если брать деньги на это дело у какого-то инвестора, то все это время с плюсом - его придётся убеждать, что те хайпы, которые будут постоянно подниматься о всяких новых фишках в этих темах - это хайпы на предмет - выбить деньги у инвесторов и спустить их без результата - а вот ваша идея - это о-го-го и когда она, наконец, ещё при его и вашей жизни, начнёт приносить ....ллиарды - вы будете купаться в собственном озере на ранчо на спутнике Сатурна, любуюсь надписью "Самому крутому инвесторы тысячелетия" на его кольцах, отбиваясь от других инвесторов. А вы в курсах, что несмотря ни на какие санкции в России живет и здравствует, не взирая ни на какие санкции американская фирма Actel(Microsemi)? Знаете за сколько нашим приходится покупать у них микросхемы себестоимостью в несколько центов? Правильно, за многие сотни долларов! И хотя ракетоносители электронику эту выводят на орбиту российские, но делать свою радиационно-стойкую микроэлектронику ни-ни! Это как установка для местных аборигенов. Я уж молчу кто там директорствует, чтобы не сочли за сведение личных счетов. Поэтому Вы конечно правы, но правда эта России не сулит ничего хорошего. Стратегическая же цель легко отслеживаемая - с помощью своей мэ держать Россию "на кукане" в деле промышленного освоения Космоса.
- - - Добавлено - - -
Крик души - ХОТЬ КАКОГО-ТО КОЛЛЕКТИВА.
Но существует очень хороший шанс, что в коллективе так и останется один человек коллективу нужны финансовые перспективы. Ну хотя бы по $50 000/год на первое время, разумеется каждому :)
А вы в курсах,
Вы даже не поняли - про что я.
Удачи.
Радио-86РК
15.05.2020, 11:51
Кстaти, если считаете, что дешифрация всех этих команд аппаратно слишком сложно реализуется и без RISC-ядра и микрокода не обойтись, то вот набросок схемы узла выборки кода команды под LogiSim и Proteus.
Узел считывает полный код команды вместе с префиксами, выдавая те же биты, что используются в шаблоне JavaScript-эмулятора.
Естественно, имеется схема (устаревшая), которая считывает из памяти команды и переводит их в текст - аппаратный дизассемблер.
Но из-за сложности работы с регистровым файлом, схемы частичного симулятора процессора пока не удалось разработать - не хватает опыта работы с кешом, чтобы расписать по тактам…
P.S.: Это чтобы не быть голословным.
Хоть какие-то наработки электронными узлами да имеются…
Но опыта в целом - нет.
Вы даже не поняли - про что я.
Удачи.
да понял я, в .опе наша российская радиационно-стойкая мэ...а сведения как её проектировать гостайна, чтобы американцам бабки на нас делать не мешать.
да понял я, в .опе наша российская радиационно-стойкая мэ
Как я и сказал - не поняли.
Радио-86РК
15.05.2020, 14:58
В данном случае, очевидно, предполагается программирование на ассемблере, но дружелюбности - не наблюдается. Болеe того, автор и сам попал в эту ловушкуСистемa команд того же z80 полна всяких исключений. Например, «LD A,» неочевидным образом удлиняет команду на 1 байт для указания индекса смещения.
То есть, последовательнее было бы под IX-префиксом расширять не «LD r,(HL)», а «LD r,d8». Тогда бы с добавлением префикса IX перед командой её размер не увеличивался бы. Что у меня и сделано:
A4 7F|MOV AL,0x7F
44 A4 7F|MOV AL,[SP+0x7F]
E4 44 A4 7F|MOV AL,[SP+AL+0x7F]
/\ /\
|| ||
|| |+--\ Код
|| +---/ префикса SP
||
|+-----\ Код
+------/ префикса LOOP ALА так как в самом начале разработки у меня не было опыта построения ассемблера, то первые пробные программы под свой процессор я набирал голым дампом. Потому и система команд изначально у меня и сформировалась по принципу «сам код - и есть мнемоника.
Где «A4» - «LOAD R4», а «AA» - «ALU:ADD» и «AB» - «ALU:SUB».
Следовательно, «BC» - «BRANCH IF CARRY» и «BE» - «BRANCH IF EQUAL».
Потому я и уверенно говорю, что код - дружелюбный! Конечно, если Вы решите программировать прямо дампом.
А если синтаксис ассемблера не нравится, то он легко перебивается в строчках 4160…4274, где описаны все команды. То есть, под стиль z80 достаточно потратить минут 5 и перебить 95 строк из «MOV» в «LD», сменив квадратные скобки на круглые. А также и переименовать регистры. Это - дело вкуса. Я уже сказал, что вместо эмулятора у меня получился реальный движок, в котором и 68000 можно описать шаблоном…
[I]P.S.: Вы не внимательно читали: С самого начала я сказал, что решил попробовать сделать «перезагрузку процессоров Intel» и попытаться сделать так, каким мог быть сам i8080, а i8086 был бы обратно совместимым с i8080 на бинарном уровне.
Если Вы ждали чуда, то чудо здесь не найдёте: В теме я поделился опытом «перезагрузки» изначально кривой архитектуры Intel с целью 8-битное сделать 16- и 32-битным.
(Я читал документацию по z280 и ужаснулся тем же костылям, что сделали и с i8086, когда «за уши» тянули его в IA-32 и в IA-64…
В IA-32 поддержка IA-16 почти искусственна в самом ядре. В моём x80 32-бит нет технически, но они поддерживаются уже в принципе…)
Системa команд того же z80 полна всяких исключений
Я сказал, что она замечательная? Или что надо ей следовать?
С самого начала я сказал, что решил попробовать сделать «перезагрузку процессоров Intel» и попытаться сделать так, каким мог быть сам i8080, а i8086 был бы обратно совместимым с i8080 на бинарном уровне.
Если Вы ждали чуда, то чудо здесь не найдёте: В теме я поделился опытом «перезагрузки» изначально кривой архитектуры Intel с целью 8-битное сделать 16- и 32-битным.
Я внимательно читал. И Вы сделали изначально кривое ещё более кривым.
- - - Добавлено - - -
Потому я и уверенно говорю, что код - дружелюбный! Конечно, если Вы решите программировать прямо дампом.
Где «A4»
ADD 4
Вот и вся дружелюбность.
Потому и система команд изначально у меня и сформировалась по принципу «сам код - и есть мнемоника.
Поэтому это Вам привычно. А другим сходу будет нихера не понятно.
Пример понятного
MOV R0, R1
ADD R0, R1
Можете не отвечать, это было моё последнее сообщение здесь.
Радио-86РК
15.05.2020, 20:47
Можете не отвечать, это было моё последнее сообщение здесь.Тeм не менее, я отвечу, как минимум для тех, кто думает так же, но не ставит крест на интересе к данной теме…
Поэтому это Вам привычно. А другим сходу будет нихера не понятно.
Пример понятногоЗдесь критикуете именно синтаксис, так как в RISC-архитектурах традиционно и регистры не именуются, а индексируются. Так поступили и в IA-64 вводом регистров R8…R15.
Однако, здесь важно внимательнее присмотреться к примеру:
A4 7F|MOV R4,0x7F
55 A4 7F|MOV R4,[P5+0x7F]
E6 55 A4 7F|MOV R4,[P5+R6+0x7F]Причём, в исходниках это прямо так и указано:
// Register descriptions
// Pointers
P1 BP BP BP
P2 SI SI SI
P3 DI DI DI
P4 SP SP SP
P5 BX BX DX
P6 CX CX CX
P7 DX DX DX
// Regular
R0 [BX] _BX_ [BX]
R1 BH BH BH
R2 CH CH CH
R3 DH DH DH
R4 AL AL AL
R5 BL BL BL
R6 CL CL CL
R7 DL DL DLТем самым, в эмуляторе синтаксис «ALU7 R4,R0» заменяется на «CMP AL,[BX]». И алгоритм там прорабатывался несколько лет /!\, чтобы индексы регистров привести к Intel-стилю и АЛУ-код представить именами операций.
Потому и код
MOV R0, R1
ADD R0, R1изначально генерируется, но я приложил максимум усилий и трюков JavaScript с регулярными выражениями, чтобы нигде не чувствовался привкус RISC.
В этом плане, моя система команд не хуже того же байт-кода Java-машины. Но, если Java-апплет голым дампом вручную очень сложно набить, то как виртуальная байт-машина мой x80 всё же на порядок дружелюбнее!
Кстати, сейчас добавил пару строчек для экспорта шаблона…
Как результат, вот дешифратор всех команд на:
// 18b'0XX_0XX_0000_0000_0000:
if(0x0000 == ($IC & 0x4FFF)} {
// HLT
(CR(0,CR(0)|128)),_.EV = DO_ACCLAIM;
} else
// 18b'XXX_1XX_0000_0000_0000:
if(0x4000 == ($IC & 0x4FFF)} {
// PREFIX SUPER
return 0;
} else
// 18b'1XX_XXX_0000_0XXX_0XXX:
if(0x0000 == ($IC & 0x0F88)} {
// PREFIX R$X/P$Y
return 0;
} else
// 18b'XXX_X00_0XXX_0000_0000:
if(0x0000 == ($IC & 0x38FF)} {
// HLT R$Z
FH($Z | 0);
} else
// 18b'111_X00_0XXX_0XXX_0XXX:
if(0x8000 == ($IC & 0xB888)} {
// HLT P$Z/$Z
FH($Z | 8);
} else
// 18b'XXX_X00_0100_0000_0000:
if(0x0400 == ($IC & 0x3FFF)} {
// .$Y$X
return 0;
} else
// 18b'XXX_X00_1000_0000_0000:
if(0x0800 == ($IC & 0x3FFF)} {
// .$Y$X
return 0;
} else
// 18b'XXX_X00_1000_0XXX_0000:
if(0x0800 == ($IC & 0x3F8F)} {
// MOV [0],R$Y
CR(0,R$Y())+ FL(0),_.IE=0;
} else
// 18b'XXX_X10_0100_0XXX_0000:
if(0x2400 == ($IC & 0x3F8F)} {
// .$Y$X
return 0;
} else
// 18b'XXX_X10_1000_0XXX_0000:
if(0x2800 == ($IC & 0x3F8F)} {
// .$Y$X
return 0;
} else
// 18b'XXX_X10_0100_0000_0XXX:
if(0x2400 == ($IC & 0x3FF8)} {
// MOV R$X,[$Y]
R$X(CR($Y))+ FL(0),_.IE=0;
} else
// 18b'1XX_X10_0100_0XXX_0XXX:
if(0x2400 == ($IC & 0x3F88)} {
// MOV R$X,[R$Y]
R$X(CTX(R$Y()))+ FL(0),_.IE=0;
} else
// 18b'XXX_X10_0100_0XXX_0XXX:
if(0x2400 == ($IC & 0x3F88)} {
// MOV [R$X],R$Y
CTX(R$X(), R$Y())+ FL(0),_.IE=0;
} else
// 18b'101_X00_0XXX_0XXX_0XXX:
if(0x8000 == ($IC & 0xB888)} {
// XCHG R$Z,R$Y
$1=R$Z(),R$Z(R$Y()),R$Y($1);
} else
// 18b'110_X00_0XXX_0XXX_0XXX:
if(0x0000 == ($IC & 0xB888)} {
// XCHG P$Z,P$Y
$1=P$Z(),P$Z(P$Y()),P$Y($1);
} else
// 18b'XXX_X11_X100_0XXX_0000:
if(0x3400 == ($IC & 0x378F)} {
// .$Y$X
return 0;
} else
// 18b'XXX_X11_X100_0000_0XXX:
if(0x3400 == ($IC & 0x37F8)} {
// .$Y$X
return 0;
} else
// 18b'1XX_X11_X100_0XXX_0XXX:
if(0x3400 == ($IC & 0x3788)} {
// IN R$X
R$X(PORT(R$X()));
} else
// 18b'XXX_X11_X100_0XXX_0XXX:
if(0x3400 == ($IC & 0x3788)} {
// OUT R$X,R$Y
PORT(R$X(),R$Y());
} else
// 18b'XXX_XXX_0100_0XXX_1XXX:
if(0x0408 == ($IC & 0x0F88)} {
// BIT R$X,$Y
$1=FL(),FL($1&0xFE)|((R$X()>>$Y)&1),R$X(~(~R$X()|(1<<$Y)))/*>*/;
} else
// 18b'0XX_X00_0000_0XXX_0XXX:
if(0x0000 == ($IC & 0x3F88)} {
// MOV R$X,R$Y
R$X(R$Y());
} else
// 18b'XXX_X00_0XXX_0000_0XXX:
if(0x0000 == ($IC & 0x38F8)} {
// MOV R$X,[$Z]
R$X(CR($Z));
} else
// 18b'XXX_X00_0XXX_0XXX_0000:
if(0x0000 == ($IC & 0x388F)} {
// MOV [$Z],R$Y
CR($Z,R$Y());
} else
// 18b'0XX_X00_0100_0XXX_0XXX:
if(0x0400 == ($IC & 0x3F88)} {
// MOV P$X,P$Y
P$X(P$Y());
} else
// 18b'XXX_X10_0100_0XXX_1XXX:
if(0x2408 == ($IC & 0x3F88)} {
// -- Z$Y
$1=ALU$X(DROP($Y),REG($Y)),REG($Y,$1),FL($1.hi());
} else
// 18b'XXX_XXX_0XXX_0XXX_1XXX:
if(0x0008 == ($IC & 0x0888)} {
// ALU$X Z$Z,R$Y
$1=ALU$X(Z$Z(),R$Y()),Z$Z($1),FL($1.hi());
} else
// 18b'XXX_XXX_0100_1010_1XXX:
if(0x04A8 == ($IC & 0x0FF8)} {
// ADC P$X,IB
$1=ALU$X(DROP(FH()),_.B),ACC($1),FL($1.hi());
} else
// 18b'XXX_XXX_0XXX_1010_1XXX:
if(0x00A8 == ($IC & 0x08F8)} {
// ALU$X Z$Z,IB
$1=ALU$X(Z$Z(),_.B),Z$Z($1),FL($1.hi());
} else
// 18b'XXX_X00_0XXX_100X_XXXX:
if(0x0080 == ($IC & 0x38E0)} {
// PUSH $VIB
HEAP(0x$V00 + _.B);
} else
// 18b'XXX_XXX_0000_1110_1110:
if(0x00EE == ($IC & 0x0FFF)} {
// NOP
$Z;
} else
// 18b'XXX_XXX_0XXX_1110_1110:
if(0x00EE == ($IC & 0x08FF)} {
// NOP $Z
$Z;
} else
// 18b'XXX_X0X_0000_1111_1110:
if(0x00FE == ($IC & 0x2FFF)} {
// DBG 0
HEAP(_.IP)+IP(JP(10>$T?0:1));
_.IF=true;
} else
// 18b'XXX_X0X_0000_1111_1111:
if(0x00FF == ($IC & 0x2FFF)} {
// DBG
HEAP(_.IP)+IP(JP(10>$T?0:1));
_.IF=true;
} else
// 18b'111_XXX_0000_1100_1XXX:
if(0x80C8 == ($IC & 0x8FF8)} {
// INC Q$X
Q$X(Q$X()+1);
} else
// 18b'111_XXX_0000_1101_1XXX:
if(0x80D8 == ($IC & 0x8FF8)} {
// DEC Q$X
Q$X(Q$X()-1);
} else
// 18b'XXX_X00_0000_1100_1111:
if(0x00CF == ($IC & 0x3FFF)} {
// CMC
FL(FL() ^ 2);
} else
// 18b'111_XXX_0XXX_1100_1XXX:
if(0x80C8 == ($IC & 0x88F8)} {
// ADD Q$X,P$Z
$1=Q$X()+P$Z()+(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q$X($1);
} else
// 18b'111_XXX_0XXX_1101_1XXX:
if(0x80D8 == ($IC & 0x88F8)} {
// SUB Q$X,P$Z
$1=Q$X()-P$Z()-(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q$X($1);
} else
// 18b'XXX_XXX_0000_1101_1110:
if(0x00DE == ($IC & 0x0FFF)} {
// DOZ
CND7?(FH(1 | 8), FL((FL() & 0x02) | 0x05)):0;
} else
// 18b'XXX_XXX_0000_1101_1111:
if(0x00DF == ($IC & 0x0FFF)} {
// DONZ
CND6?(FH(1 | 8), FL((FL() & 0x02) | 0x05)):0;
} else
// 18b'XXX_XXX_0XXX_1101_111X:
if(0x00DE == ($IC & 0x08FE)} {
// ---
return 0;
} else
// 18b'XXX_XXX_0100_110X_1XXX:
if(0x04C8 == ($IC & 0x0FE8)} {
// ---
$1=ACC(ALU$W(ACC())),FL($1.hi());
} else
// 18b'XXX_XXX_0XXX_1100_1110:
if(0x00CE == ($IC & 0x08FF)} {
// ALU1F Z$Z
$1=Z$Z(ALU1F(Z$Z())),FL($1.hi());
} else
// 18b'XXX_XXX_0XXX_110X_1XXX:
if(0x00C8 == ($IC & 0x08E8)} {
// ALU$W Z$Z
$1=Z$Z(ALU$W(Z$Z())),FL($1.hi());
} else
// 18b'XXX_X00_0000_1010_0XXX:
if(0x00A0 == ($IC & 0x3FF8)} {
// MOV R$X,IB
R$X(_.B);
} else
// 18b'XXX_X00_X100_1011_0000:
if(0x04B0 == ($IC & 0x37FF)} {
// PUSH $+IB
HEAP(IP()+_.A);
} else
// 18b'XXX_X0X_0000_1011_0XXX:
if(0x00B0 == ($IC & 0x2FF8)} {
// CCND$X $+IB
CND$X?HEAP(IP())+IP(IP()+_.A):0;
_.IF=true;
} else
// 18b'XXX_XXX_0000_1100_0XXX:
if(0x00C0 == ($IC & 0x0FF8)} {
// INC R$X
$1=ADD(R$X(),1),R$X($1),FL($1.hi());
} else
// 18b'XXX_XXX_0000_1101_0XXX:
if(0x00D0 == ($IC & 0x0FF8)} {
// DEC R$X
$1=SUB(R$X(),1),R$X($1),FL($1.hi());
} else
// 18b'XXX_XXX_0XXX_1100_0XXX:
if(0x00C0 == ($IC & 0x08F8)} {
// ADD P$Z,R$X
$1=(P$Z()+R$X()),P$X($1),FL($1.hi());
} else
// 18b'XXX_XXX_0XXX_1101_0XXX:
if(0x00D0 == ($IC & 0x08F8)} {
// SUB P$Z,R$X
$1=(P$Z()+R$X()),P$X($1),FL($1.hi());
} else
// 18b'XXX_XXX_0XXX_1101_0XXX:
if(0x00D0 == ($IC & 0x08F8)} {
// DEC R$X
$1=SUB(R$X(),1),R$X($1),FL($1.hi());
} else
// 18b'XXX_X00_0XXX_1010_0000:
if(0x00A0 == ($IC & 0x38FF)} {
// POP [P$Z+IB]
DW(P$Z()+_.C,HEAP());
} else
// 18b'XXX_X00_0XXX_1010_0XXX:
if(0x00A0 == ($IC & 0x38F8)} {
// MOV R$X,[P$Z+IB]
R$X(DB(P$Z()+_.C));
} else
// 18b'XXX_X00_111X_1011_0000:
if(0x0EB0 == ($IC & 0x3EFF)} {
// PUSH [P$Z+IB]
HEAP(DW(P$Z()+_.C));
} else
// 18b'XXX_X00_0XXX_1011_0000:
if(0x00B0 == ($IC & 0x38FF)} {
// PUSH [P$Z+IB]
HEAP(DW(P$Z()+_.C));
} else
// 18b'XXX_X00_0XXX_1011_0XXX:
if(0x00B0 == ($IC & 0x38F8)} {
// MOV [P$Z+IB],R$X
DB(P$Z()+_.C,R$X());
} else
// 18b'XXX_X10_0000_1010_0XXX:
if(0x20A0 == ($IC & 0x3FF8)} {
// --- IB
return 0;
} else
// 18b'XXX_X10_0000_1011_0XXX:
if(0x20B0 == ($IC & 0x3FF8)} {
// --- IB
return 0;
} else
// 18b'XXX_X10_0XXX_1010_0XXX:
if(0x20A0 == ($IC & 0x38F8)} {
// MOV R$X,[P$Z+ACC+IB]
R$X(DB(P$Z()+ACC()+_.C)),FL(0),_.IE=0;
} else
// 18b'XXX_X10_0XXX_1011_0XXX:
if(0x20B0 == ($IC & 0x38F8)} {
// MOV [P$Z+ACC+IB],R$X
DB(P$Z()+ACC()+_.C,R$X()),FL(0),_.IE=0;
} else
// 18b'XXX_XXX_X100_1011_1XXX:
if(0x04B8 == ($IC & 0x07F8)} {
// --- IB
return 0;
} else
// 18b'XXX_X00_X100_1011_1010:
if(0x04BA == ($IC & 0x37FF)} {
// LEA +IB
DST(DST()+_.B);
} else
// 18b'XXX_X00_X100_1011_1XXX:
if(0x04B8 == ($IC & 0x37F8)} {
// MOV [U$X],IB
DB(U$X(),_.B);
} else
// 18b'XXX_X00_1110_1011_1000:
if(0x0EB8 == ($IC & 0x3FFF)} {
// WAIT
FL((FL() & 0x02) | 0x0D),trace.expression=0;
} else
// 18b'XXX_X00_1111_1011_1000:
if(0x0FB8 == ($IC & 0x3FFF)} {
// RET
IP(HEAP());
} else
// 18b'XXX_X0X_0XXX_1011_1000:
if(0x00B8 == ($IC & 0x28FF)} {
// JMP $+$UIB
IP(IP()+_.A);
_.IF=true;
} else
// 18b'XXX_XXX_0XXX_1011_1XXX:
if(0x00B8 == ($IC & 0x08F8)} {
// JCND$X $+$UIB
CND$X?IP(IP()+_.A):0;
_.IF=true;
} else
// 18b'XXX_XXX_1111_1011_1XXX:
if(0x0FB8 == ($IC & 0x0FF8)} {
// RCND$X
CND$X?IP(HEAP()):0;
} else
// 18b'1X1_X00_0000_1110_1XXX:
if(0x80E8 == ($IC & 0xBFF8)} {
// PUSH U$X
HEAP(U$X());
} else
// 18b'1X1_X00_0000_1111_1XXX:
if(0x80F8 == ($IC & 0xBFF8)} {
// POP U$X
U$X(HEAP());
} else
// 18b'XXX_X00_XXXX_1110_1111:
if(0x00EF == ($IC & 0x30FF)} {
// XCHG P$Z,[SP]
$1=P$Z(),P$Z(DW(SP())), DW(SP(), $1);
} else
// 18b'XXX_X00_0000_1110_0000:
if(0x00E0 == ($IC & 0x3FFF)} {
// SKIP
FH(1 | 8), FL((FL() & 0x02) | 0x05);
} else
// 18b'XXX_X10_0000_1110_0000:
if(0x20E0 == ($IC & 0x3FFF)} {
// SKIP ACC
FH(1 | 8), FL((FL() & 0x02) | 0x05);
} else
// 18b'XXX_X00_0000_1110_0XXX:
if(0x00E0 == ($IC & 0x3FF8)} {
// LOOP $X/R$X
FH($X | 8), FL((FL() & 0x02) | 0x09);
} else
// 18b'XXX_X00_0000_1110_1000:
if(0x00E8 == ($IC & 0x3FFF)} {
// DOC
CND5?(FH(1 | 8), FL((FL() & 0x02) | 0x05)):0;
} else
// 18b'XXX_X00_0000_1110_1001:
if(0x00E9 == ($IC & 0x3FFF)} {
// DONC
CND4?(FH(1 | 8), FL((FL() & 0x02) | 0x05)):0;
} else
// 18b'XXX_X00_0XXX_1110_1011:
if(0x00EB == ($IC & 0x38FF)} {
// LOOP [R$Z]
FH(R$Z()|8),FL((FL() & 0x02) | 0x09);
} else
// 18b'XXX_X00_0XXX_1110_1100:
if(0x00EC == ($IC & 0x38FF)} {
// LOOP R$Z
FH($Z), FL((FL() & 0x02) | 0x09);
} else
// 18b'XXX_X00_0XXX_1111_1011:
if(0x00FB == ($IC & 0x38FF)} {
// SKIP [R$Z]
FH(R$Z()|8),FL((FL() & 0x02) | 0x05);
} else
// 18b'XXX_X00_0XXX_1111_1100:
if(0x00FC == ($IC & 0x38FF)} {
// SKIP R$Z
FH($Z), FL((FL() & 0x02) | 0x05);
} else
// 18b'XXX_X00_0XXX_1111_1101:
if(0x00FD == ($IC & 0x38FF)} {
// SKIP $Z
FH($Z | 8), FL((FL() & 0x02) | 0x05);
} else
// 18b'100_X0X_0XXX_1111_XXXX:
if(0x00F0 == ($IC & 0xA8F0)} {
// INT $T
HEAP(_.IP)+IP(JP(10>$T?0:1));
_.IF=true;
} else
// 18b'XXX_XXX_1000_10XX_XXXX:
if(0x0880 == ($IC & 0x0FC0)} {
// Y$Y_X$X IB
return 0;
} else
// 18b'XXX_XXX_XXXX_XXXX_XXXX:
if(0x0000 == ($IC & 0x0000)} {
// Y$Y_X$X ($M)
0;
}Или на System Verilog:
case(IC)
18b'0XX_0XX_0000_0000_0000: // HLT
//(CR(0,CR(0)|128)),_.EV = DO_ACCLAIM;
18b'XXX_1XX_0000_0000_0000: // PREFIX SUPER
//return 0;
18b'1XX_XXX_0000_0XXX_0XXX: // PREFIX R$X/P$Y
//return 0;
18b'XXX_X00_0XXX_0000_0000: // HLT R$Z
//FH($Z | 0);
18b'111_X00_0XXX_0XXX_0XXX: // HLT P$Z/$Z
//FH($Z | 8);
18b'XXX_X00_0100_0000_0000: // .$Y$X
//return 0;
18b'XXX_X00_1000_0000_0000: // .$Y$X
//return 0;
18b'XXX_X00_1000_0XXX_0000: // MOV [0],R$Y
//CR(0,R$Y())+ FL(0),_.IE=0;
18b'XXX_X10_0100_0XXX_0000: // .$Y$X
//return 0;
18b'XXX_X10_1000_0XXX_0000: // .$Y$X
//return 0;
18b'XXX_X10_0100_0000_0XXX: // MOV R$X,[$Y]
//R$X(CR($Y))+ FL(0),_.IE=0;
18b'1XX_X10_0100_0XXX_0XXX: // MOV R$X,[R$Y]
//R$X(CTX(R$Y()))+ FL(0),_.IE=0;
18b'XXX_X10_0100_0XXX_0XXX: // MOV [R$X],R$Y
//CTX(R$X(), R$Y())+ FL(0),_.IE=0;
18b'101_X00_0XXX_0XXX_0XXX: // XCHG R$Z,R$Y
//$1=R$Z(),R$Z(R$Y()),R$Y($1);
18b'110_X00_0XXX_0XXX_0XXX: // XCHG P$Z,P$Y
//$1=P$Z(),P$Z(P$Y()),P$Y($1);
18b'XXX_X11_X100_0XXX_0000: // .$Y$X
//return 0;
18b'XXX_X11_X100_0000_0XXX: // .$Y$X
//return 0;
18b'1XX_X11_X100_0XXX_0XXX: // IN R$X
//R$X(PORT(R$X()));
18b'XXX_X11_X100_0XXX_0XXX: // OUT R$X,R$Y
//PORT(R$X(),R$Y());
18b'XXX_XXX_0100_0XXX_1XXX: // BIT R$X,$Y
//$1=FL(),FL($1&0xFE)|((R$X()>>$Y)&1),R$X(~(~R$X()|(1<<$Y)))/*>*/;
18b'0XX_X00_0000_0XXX_0XXX: // MOV R$X,R$Y
//R$X(R$Y());
18b'XXX_X00_0XXX_0000_0XXX: // MOV R$X,[$Z]
//R$X(CR($Z));
18b'XXX_X00_0XXX_0XXX_0000: // MOV [$Z],R$Y
//CR($Z,R$Y());
18b'0XX_X00_0100_0XXX_0XXX: // MOV P$X,P$Y
//P$X(P$Y());
18b'XXX_X10_0100_0XXX_1XXX: // -- Z$Y
//$1=ALU$X(DROP($Y),REG($Y)),REG($Y,$1),FL($1.hi());
18b'XXX_XXX_0XXX_0XXX_1XXX: // ALU$X Z$Z,R$Y
//$1=ALU$X(Z$Z(),R$Y()),Z$Z($1),FL($1.hi());
18b'XXX_XXX_0100_1010_1XXX: // ADC P$X,IB
//$1=ALU$X(DROP(FH()),_.B),ACC($1),FL($1.hi());
18b'XXX_XXX_0XXX_1010_1XXX: // ALU$X Z$Z,IB
//$1=ALU$X(Z$Z(),_.B),Z$Z($1),FL($1.hi());
18b'XXX_X00_0XXX_100X_XXXX: // PUSH $VIB
//HEAP(0x$V00 + _.B);
18b'XXX_XXX_0000_1110_1110: // NOP
//$Z;
18b'XXX_XXX_0XXX_1110_1110: // NOP $Z
//$Z;
18b'XXX_X0X_0000_1111_1110: // DBG 0
//HEAP(_.IP)+IP(JP(10>$T?0:1));
//_.IF=true;
18b'XXX_X0X_0000_1111_1111: // DBG
//HEAP(_.IP)+IP(JP(10>$T?0:1));
//_.IF=true;
18b'111_XXX_0000_1100_1XXX: // INC Q$X
//Q$X(Q$X()+1);
18b'111_XXX_0000_1101_1XXX: // DEC Q$X
//Q$X(Q$X()-1);
18b'XXX_X00_0000_1100_1111: // CMC
//FL(FL() ^ 2);
18b'111_XXX_0XXX_1100_1XXX: // ADD Q$X,P$Z
//$1=Q$X()+P$Z()+(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q$X($1);
18b'111_XXX_0XXX_1101_1XXX: // SUB Q$X,P$Z
//$1=Q$X()-P$Z()-(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q$X($1);
18b'XXX_XXX_0000_1101_1110: // DOZ
//CND7?(FH(1 | 8), FL((FL() & 0x02) | 0x05)):0;
18b'XXX_XXX_0000_1101_1111: // DONZ
//CND6?(FH(1 | 8), FL((FL() & 0x02) | 0x05)):0;
18b'XXX_XXX_0XXX_1101_111X: // ---
//return 0;
18b'XXX_XXX_0100_110X_1XXX: // ---
//$1=ACC(ALU$W(ACC())),FL($1.hi());
18b'XXX_XXX_0XXX_1100_1110: // ALU1F Z$Z
//$1=Z$Z(ALU1F(Z$Z())),FL($1.hi());
18b'XXX_XXX_0XXX_110X_1XXX: // ALU$W Z$Z
//$1=Z$Z(ALU$W(Z$Z())),FL($1.hi());
18b'XXX_X00_0000_1010_0XXX: // MOV R$X,IB
//R$X(_.B);
18b'XXX_X00_X100_1011_0000: // PUSH $+IB
//HEAP(IP()+_.A);
18b'XXX_X0X_0000_1011_0XXX: // CCND$X $+IB
//CND$X?HEAP(IP())+IP(IP()+_.A):0;
//_.IF=true;
18b'XXX_XXX_0000_1100_0XXX: // INC R$X
//$1=ADD(R$X(),1),R$X($1),FL($1.hi());
18b'XXX_XXX_0000_1101_0XXX: // DEC R$X
//$1=SUB(R$X(),1),R$X($1),FL($1.hi());
18b'XXX_XXX_0XXX_1100_0XXX: // ADD P$Z,R$X
//$1=(P$Z()+R$X()),P$X($1),FL($1.hi());
18b'XXX_XXX_0XXX_1101_0XXX: // SUB P$Z,R$X
//$1=(P$Z()+R$X()),P$X($1),FL($1.hi());
18b'XXX_XXX_0XXX_1101_0XXX: // DEC R$X
//$1=SUB(R$X(),1),R$X($1),FL($1.hi());
18b'XXX_X00_0XXX_1010_0000: // POP [P$Z+IB]
//DW(P$Z()+_.C,HEAP());
18b'XXX_X00_0XXX_1010_0XXX: // MOV R$X,[P$Z+IB]
//R$X(DB(P$Z()+_.C));
18b'XXX_X00_111X_1011_0000: // PUSH [P$Z+IB]
//HEAP(DW(P$Z()+_.C));
18b'XXX_X00_0XXX_1011_0000: // PUSH [P$Z+IB]
//HEAP(DW(P$Z()+_.C));
18b'XXX_X00_0XXX_1011_0XXX: // MOV [P$Z+IB],R$X
//DB(P$Z()+_.C,R$X());
18b'XXX_X10_0000_1010_0XXX: // --- IB
//return 0;
18b'XXX_X10_0000_1011_0XXX: // --- IB
//return 0;
18b'XXX_X10_0XXX_1010_0XXX: // MOV R$X,[P$Z+ACC+IB]
//R$X(DB(P$Z()+ACC()+_.C)),FL(0),_.IE=0;
18b'XXX_X10_0XXX_1011_0XXX: // MOV [P$Z+ACC+IB],R$X
//DB(P$Z()+ACC()+_.C,R$X()),FL(0),_.IE=0;
18b'XXX_XXX_X100_1011_1XXX: // --- IB
//return 0;
18b'XXX_X00_X100_1011_1010: // LEA +IB
//DST(DST()+_.B);
18b'XXX_X00_X100_1011_1XXX: // MOV [U$X],IB
//DB(U$X(),_.B);
18b'XXX_X00_1110_1011_1000: // WAIT
//FL((FL() & 0x02) | 0x0D),trace.expression=0;
18b'XXX_X00_1111_1011_1000: // RET
//IP(HEAP());
18b'XXX_X0X_0XXX_1011_1000: // JMP $+$UIB
//IP(IP()+_.A);
//_.IF=true;
18b'XXX_XXX_0XXX_1011_1XXX: // JCND$X $+$UIB
//CND$X?IP(IP()+_.A):0;
//_.IF=true;
18b'XXX_XXX_1111_1011_1XXX: // RCND$X
//CND$X?IP(HEAP()):0;
18b'1X1_X00_0000_1110_1XXX: // PUSH U$X
//HEAP(U$X());
18b'1X1_X00_0000_1111_1XXX: // POP U$X
//U$X(HEAP());
18b'XXX_X00_XXXX_1110_1111: // XCHG P$Z,[SP]
//$1=P$Z(),P$Z(DW(SP())), DW(SP(), $1);
18b'XXX_X00_0000_1110_0000: // SKIP
//FH(1 | 8), FL((FL() & 0x02) | 0x05);
18b'XXX_X10_0000_1110_0000: // SKIP ACC
//FH(1 | 8), FL((FL() & 0x02) | 0x05);
18b'XXX_X00_0000_1110_0XXX: // LOOP $X/R$X
//FH($X | 8), FL((FL() & 0x02) | 0x09);
18b'XXX_X00_0000_1110_1000: // DOC
//CND5?(FH(1 | 8), FL((FL() & 0x02) | 0x05)):0;
18b'XXX_X00_0000_1110_1001: // DONC
//CND4?(FH(1 | 8), FL((FL() & 0x02) | 0x05)):0;
18b'XXX_X00_0XXX_1110_1011: // LOOP [R$Z]
//FH(R$Z()|8),FL((FL() & 0x02) | 0x09);
18b'XXX_X00_0XXX_1110_1100: // LOOP R$Z
//FH($Z), FL((FL() & 0x02) | 0x09);
18b'XXX_X00_0XXX_1111_1011: // SKIP [R$Z]
//FH(R$Z()|8),FL((FL() & 0x02) | 0x05);
18b'XXX_X00_0XXX_1111_1100: // SKIP R$Z
//FH($Z), FL((FL() & 0x02) | 0x05);
18b'XXX_X00_0XXX_1111_1101: // SKIP $Z
//FH($Z | 8), FL((FL() & 0x02) | 0x05);
18b'100_X0X_0XXX_1111_XXXX: // INT $T
//HEAP(_.IP)+IP(JP(10>$T?0:1));
//_.IF=true;
18b'XXX_XXX_1000_10XX_XXXX: // Y$Y_X$X IB
//return 0;
18b'XXX_XXX_XXXX_XXXX_XXXX: // Y$Y_X$X ($M)
//0;
Естественно, это лишь примерный набросок / скелет, по которому уже нужно, так или иначе, описывать алгоритм работы каждой операции.
(Хотя, знатоки JavaScript уже поняли, что «R$X(…)» синтаксически легальна и может учитывать «X» как младшие 3 бита кода инструкции. Тем самым, немного пошаманив, можно допилить эмулятор так, чтобы всё работало именно как и описано в шаблоне - без всяких конвертаций «R$X()» -> «R4()» -> «AL()», что занимает уйму времени при открытии эмулятора.
Просто многие фишки JavaScript я не знал на момент разработки эмулятора и не догадался их использовать…)
Естественно, это значительно упростит в дальнейшем разработку, так как от порядка описания команд зависит вся работа в целом и нельзя перепутать местами несколько условий из-за строжайшего мажоритарного приоритета.
(В LogiSim-модели я немало мучался с индексированием инструкций, так как вручную тяжело придерживаться нужного логического порядка кодирования их…)
P.S.: Чтобы было легче проникнуться затеей, относитесь к ней к подобию виртуальной Java-машины с дружественным байт-кодом и легко реализуемой в FPGA или ТТЛ.
(В отличии от Java-процессора, который разрабатывали монстры индустрии и так до конца не справились с изначально поставленной задачей. Хоть первоначально и нацеливались на аппаратную реализацию с конкуренцией с Intel. Здесь я ни с кем конкурировать не собираюсь и систему команд продумываю без оглядки на ограничения в FPGA/ТТЛ. Хоть и реализация на ТТЛ-рассыпухие в перспективе и предусматривается…)
Пример понятного
MOV R0, R1
Ага, очень понятно: из R1 в R0 записать, или наоборот :)
Ага, очень понятно: из R1 в R0 записать, или наоборот
А это зависит от того, кто смотрит - пидипишник или кто другой :) Но даже в этом случае понятней, чем извращение A4 - LOAD R4
К тому же у PDP - MOV R0, R1 - move r0 to r1 выглядит логичней, чем в варианте move r1 to r0 - скользим слева направо взглядом - и всё выглядит логичным.
Тогда надо (from to) FT R1,R0 и если аккумулятор один FT R1, а указателей памяти если два FT M1,M0. Если же аккумулятором могут быть все регистры FTA R1,R0 R1+R0->R0
FTS R1,R0 R1-R0->R0 FTSJZ IF( R1-R0=0) JMP адрес.
С "аккумулятором" же дополнительно можно выполнять умножение и деление.
В общем с архитектурами 8008, 8080 можно экспериментировать сколько угодно за счет того, что не все 256 кодов операций задействовано
move r0 to r1 выглядит логичней
move to r0 from r1 тоже логично
Не фига - придётся или запоминать - куда перемещаем, или взглядом возвращаться - прерывается плавность восприятия. Это примерно как в немецком, где отрицание ставится в конце - радостно так - Вы здоровы - а потом хлобысь - думаете вы
- - - Добавлено - - -
Логичней выглядит так R1 := R0 - куда - операция - что
Логичней выглядит так R1 := R0 - куда - операция - что
Ну или так. Главное, куда - это налево :)
Дело, конечно, привычки, но язык ассемблера PDP-11 выглядит гораздо продуманней и дружественней для программиста. Когда я с ним столкнулся (после Фортрана) - мне хватило пяти минут, что бы въехать в принцип, а дальше было дело только в том, что бы запомнить редкие(!) команды, потому что часто использовавшиеся легли сразу. И помню, когда начал читать про язык ассемблера для XT - первая мысль - мля, как это всё в памяти удержать. В этом плане система команд 8080 (с ней столкнулся раньше XT) была даже понятней, хотя и не настолько логичней, как у PDP-11
- - - Добавлено - - -
Ну или так. Главное, куда - это налево
Главное - плавность восприятия, а не скакание по тексту вперёд назад
- - - Добавлено - - -
Именно поэтому пакет макросов для ассемблера PDP-11 воспринялся сразу, несмотря на то, что там
MOV R0, R1
выглядит как
LET R1 := R0
Когда я начинал (на 8080), я вообще без мнемоник писал - прямо кодами ;)
- - - Добавлено - - -
Пишешь процедуру в хексе, а после неё несколько нулей, на случай если её исправлять придется. Во как.
Система команд PDP-11 тоже хорошо ложится на коды, только восьмеричные. Сейчас вожусь с отладкой FPGA части, в принципе, более сложный код можно прям в FPGA RAM|ROM загнать, но есть пульт - и не слишком сложное прям из головы в пульт, даже на бумаге не пишу. И да - шпаргалки по командам под рукой нет :)
Когда я начинал (на 8080), я вообще без мнемоник писал - прямо кодами ;)
- - - Добавлено - - -
Пишешь процедуру в хексе, а после неё несколько нулей, на случай если её исправлять придется. Во как.
а у меня на МСУВТ В7 пультовом мониторе по другому вообще никак нельзя было ввести программу при открывании из коробки с завода. Чтобы подключить кассетный магнитофон пришлось колдовать над схемой 8251, а набивать ленту на телетайпе РТА-80 тоже еще-то удовольствие. Особенно весело было перемещать код вручную с заменой всех адресов на бумаге( из головы не получалось). И еще вывод текста на семисегментном индикаторе веселое занятие.
- - - Добавлено - - -
Система команд PDP-11 тоже хорошо ложится на коды, только восьмеричные. Сейчас вожусь с отладкой FPGA части, в принципе, более сложный код можно прям в FPGA RAM|ROM загнать, но есть пульт - и не слишком сложное прям из головы в пульт, даже на бумаге не пишу. И да - шпаргалки по командам под рукой нет :)
в 23 года я запомнил все коды команд 8080 где-то через 3 месяца тырканья на пультовом мониторе( мембранная клавиатура+8 семисегментных индикаторов), но если бы и кнопок не было и пульт как у СМ-4, то точно бы пришлось голову лечить
и пульт как у СМ-4, то точно бы пришлось голову лечить
И и щас могу с переключателей простую прогу набрать. Типа загрузчика.
Время разное. Для пульта с шестнадцатиричными цифрами на кнопках пусть даже пластиковых мембранных вертикальных(МСУВТ В7) одно нажатие -тетрада. Адрес вводится за 3 нажатия в пределах 2Кбайт, команда 3 байтная 6 нажатий(прикосновений). У клавишного пульта СМ-4 клавиши с фиксацией( и по моему даже с 3 состояниями?), 1 манипуляция - 1бит. Набрать программу даже на десять команд уже уйма времени. А с другой стороны терминалы штатно включены в заводской конфигурации, на МСУВТ В7 фрязинский дисплей приходилось подумать куда включать и как. Да и на самом терминале нужно было выставить правильные настройки для обмена, на абы каких он за комп не цеплялся. Но потом конечно небо и земля. Для МСУВТ В7 бытовой кассетный магнитофон и ввод с/на него через монитор и никаких дисков( хотя памяти можно набрать 64к озу с затеняемым пзу, но батарею твари забыли подключить( да и на 565ру3 пришлось бы большую батарею иметь), операционка только RMX-80, а в пзу только ассемблер и строчный редактор. А на СМ-4 любые носители и под каждого пользователя индивидуальный том 5 мбайтная "кастрюля". В 1982-83 гг это реально КРУТО! Ну и систем с разными ЯВУ у наших пронырливых сисадминов было любых!
Радио-86РК
16.05.2020, 15:47
Но даже в этом случае понятней, чем извращение A4 - LOAD R4Прояснитe момент?
Почему «A4» - извращение?
Если оглядеть многие архитектуры, то зубрить машинный код нужно везде.
Понимаю, если пользователь начал с Бейсика, потом перешёл на Паскаль и дальше - в Си, то машинный код - до лампочки!
А вот потом идёт Ассемблер, когда слишком узкие места.
Но здесь не надо смотреть с высока современных достижений!
Например, если забыть про файлы, дампы и даже перфоленту, а также убрать из процессора блок автоматической выборки команд, как это было в самом начале, то можно представить нечто, как пульты прошлого века:
http://informat444.narod.ru/museum/picture/ru/besm-2.jpg
Вот тут бинарное представление команды очень сильно влияет на скорость разработки кода и количество опечаток/ошибок.
Понятно, что в RISC систему команд гуманизировать сложно. А вот CISC бинарно можно за уши притянуть к человеку.
Раз критика сосредоточилась вокруг кода «A4», то разберу пример с ним.
Если в 70-х популярна было восьмеричная система счисления, то в i8080 она и прослеживается:
0000…0077 - группа загрузки и инкрементов (0000 - NOP)
0100…0177 - группа команд пересылок MOV (0166 - HLT)
0200…0277 - группа операций АЛУ
0300…0377 - группа управления ходом исполнения
Система команд i8080 достаточно проста (для детей 80-х с РАДИО-86РК / ЮТ-88) и чем-то походит даже на RISC: Бывают трюки написания алгоритмов из одних однобайтовых команд в «спортивных задачах»…
У меня ушли долгие годы на переработку команд i8080, чтобы человеком машинный код читался легче.
0x12 - загрузить R1 в R2: Варианты - «T12», «MOVE R1,R2», «LD R2,R1», «MOV CH,BH»
0x1A - сложить R1 к Аккумулятору: Варианты - «ADD R1», «ADD A,R1», «ADD AL,BH»
0x1B - Вычесть R1 из Аккумулятора: Варианты - «SUB R1», «SUB A,R1», «SUB AL,BH»
0x1C - конъюнкция R1 над Аккумулятором: Варианты - «CONJUNCT R1», «AND A,R1», «AND AL,BH»
0x1D - дизъюнкция R1 с Аккумулятором: Варианты - «DISJUNCT R1», «OR A,R1», «OR AL,BH»
0x1E - эксклюзивное ИЛИ R1 с Аккумулятором: Варианты - «EOR R1», «EOR A,R1», «XOR AL,BH»
0x1F - флаги по сравнению R1 с Аккумулятором: Варианты - «SUB F,A,R1», «FLAGS A,R1», «CMP AL,BH»
0xA2 - Аккумуляция Аргумента в R2: Варианты - «APLY R2,BYTE», «ACCUMULATE R2,BYTE», «ARGUMENT R2,BYTE», «MOV R2,ARG»
0xAA - Аргумент сложить к Аккумулятору: Варианты «ADD ARG», «ADD A,ARG», «ADD AL,ARG»
0xAB - Аргумент Вычесть из Аккумулятора: Варианты - «SUB ARG», «SUB A,ARG», «SUB AL,ARG»
0xAC - конъюнкция Аргумента над Аккумулятором: Варианты - «CONJUNCT ARG», «AND A,ARG», «AND AL,ARG»
0xAD - дизъюнкция Аргумента с Аккумулятором: Варианты - «DISJUNCT ARG», «OR A,ARG», «OR AL,ARG»
0xAE - эксклюзивное ИЛИ Аргумента с Аккумулятором: Варианты - «EOR ARG», «EOR A,ARG», «XOR AL,ARG»
0xAF - флаги по сравнению Аргумента с Аккумулятором: Варианты - «SUB F,A,ARG», «FLAGS A,ARG», «CMP AL,ARG»
0xB8 - безусловное Ветвление с 8-битным смещением: Варианты - «BRANCH $±127», «JMP $±127»
0xBC - условное Ветвление по CF: Варианты - «BRCS LABEL», «BCS LABEL», «JC LABEL»
0xBE - условное Ветвление по ZF (EF): Варианты - «BREQ LABEL», «BEQ LABEL», «JE LABEL»
0xBF - условное Ветвление по Фиктивному ZF (EF): Варианты - «[B]BRNE LABEL», «BNE LABEL», «BRFE LABEL», «JNE LABEL»
0xC1 - инкремент R1: Варианты - «INC R1», «INC BH»
0xC2 - инкремент R2: Варианты - «INC R2», «INC CH»
0xC3 - инкремент R3: Варианты - «INC R3», «INC DH»
0xCB - инкремент указателя: Варианты - «INC BX»
0xCC - инкремент указателя: Варианты - «INC CX»
0xCD - инкремент указателя: Варианты - «INC DX»
0xD4 - декремент R4: Варианты - «DEC R4», «DEC AL»
0xD5 - декремент R5: Варианты - «DEC R5», «DEC BL»
0xD6 - декремент R6: Варианты - «DEC R6», «DEC CL»
0xDB - декремент указателя: Варианты - «DEC BX»
0xDC - декремент указателя: Варианты - «DEC CX»
0xDD - декремент указателя: Варианты - «DEC DX»
0xF1 - прерывание на Функцию #1: Варианты - «RST 1», «FN 1», «INT 1»
0xF2 - прерывание на Функцию #2: Варианты - «RST 2», «FN 2», «INT 2»
0xF3 - прерывание на Функцию #3: Варианты - «RST 3», «FN 3», «INT 3»
0xF9 - прерывание на Функцию #9: Варианты - «RST 9», «FN 9», «INT 9»
Тем самым, просто прочитав этот список, Вы уже научились кодировать весь машинный код x80!
Сколько времени у человека уйдёт на заучивание машинного кода любого другого процессора?
Чтобы дампом написать свою первую программу, Вам потребуются считанные минуты!
На одном форуме задумку так и обозвали - Процессор Акына: Что вижу, то и значит…
Это ли ни тот самый WYSYWYG-Процессор?
То есть, любой из Вас с лёгкостью уже может понять, что делает этот программный код:
x80: .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F
0000 A1 76 A5 D0 A4 4E CB D4 BF FC 00
Z80: .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F
0000 26 76 2E D0 3E 4E 23 3D 20 FC 76
P.S.: Тем самым, в своём минимальном исполнении мой x80 - тот же i8080, но с WYSYWSYG-машинным кодом.
А с другой, как я вижу, здесь критикуете именно синтаксис Ассемблера, а не мою концепцию организации системы команд…
Если оглядеть многие архитектуры, то зубрить машинный код нужно везде.
И нахера ориентироваться на сложности?
Это ли ни тот самый WYSYWYG-Процессор?
Это лично ваше мнение.
А с другой, как я вижу, здесь критикуете именно синтаксис Ассемблера
Синтаксиса ассемблера не бывает, ассемблер - это программа, которая понимает ЯЗЫК ассемблера.
Фиговый он потому что
не мою концепцию организации системы команд
как и система команд
Lethargeek
16.05.2020, 15:58
Понятно, что в RISC систему команд гуманизировать сложно. А вот CISC бинарно можно за уши притянуть к человеку.
Непонятно. Наоборот, в рисках меньше вариантов дешифрации, проще правила.
Радио-86РК
16.05.2020, 16:35
Напримeр, данный машинный код в 80-х любой школьник мог бы усвоить на раз-два:
x80: .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F
0000 A1 76 A5 D0 A4 4E CB D4 BF FC 00
Z80: .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F
0000 26 76 2E D0 3E 4E 23 3D 20 FC 76
0000 A1 76:ARG R1,0x76
0002 A5 D0:ARG R5,0xD0
0004 A4 4E:ARG R4,0x4E
0006 CB :INC BX
0007 D4 :DEC R4
0008 BF FC:BRF 0x0006
000A 00 :NUL/HLT(Всё равно, что на Z80 в цикле M1 код команды пропускать через ПЗУ с таблицей перекодировки - x80 так и планировался на первых парах…)
То есть, я как любитель дампов потратил десятилетия на проработку системы команд по принципу паззла: Смысл и логику не менял, но переставлял по ячейкам таблицы команд.
Просто, если человек не хочет ради прикола программировать дампом - это личный интерес каждого…
P.S.: Я всего лишь сделал то, как было бы в древние времена, когда микроскоп украшался узорами (пруф (https://ru.wikipedia.org/wiki/%D0%9E%D0%BF%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D 0%B8%D0%B9_%D0%BC%D0%B8%D0%BA%D1%80%D0%BE%D1%81%D0 %BA%D0%BE%D0%BF#%D0%98%D1%81%D1%82%D0%BE%D1%80%D0% B8%D1%8F_%D0%BC%D0%B8%D0%BA%D1%80%D0%BE%D1%81%D0%B A%D0%BE%D0%BF%D0%B0)) и радиоприёмники были украшением (пруф (https://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D0%B4%D0%B8%D0%BE%D0%BF%D1%80%D0%B8%D 1%91%D0%BC%D0%BD%D0%B8%D0%BA#%D0%9A%D0%BB%D0%B0%D1 %81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B 8%D1%8F_%D1%80%D0%B0%D0%B4%D0%B8%D0%BE%D0%BF%D1%80 %D0%B8%D1%91%D0%BC%D0%BD%D0%B8%D0%BA%D0%BE%D0%B2)) .
Я подошёл к принципу реорганизации таблицы команд i8080 как эстет. Не более!
За это критикуете?
(Кто-то любит систему команд по-Пикассо, а я собрал систему команд по-Вангогу!)
Проходит ли данная архитектура по "лезвию Оккама"? Для чего создается? В чём её преимущества перед другими?
Проходит ли данная архитектура по "лезвию Оккама"?
Набор команд - это не архитектура - ни компа ни процессора. Как максимум - часть архитектуры
Для набора команд бритва Оккама - это вопрос - под какой язык создаётся система команд (с прицелом на лёгкость написания программ на этом языке).
Пока тут лёгкостью и не пахнет
- - - Добавлено - - -
В общем - классический случай - автор придумал что то под себя (причём придумывал явно не один день), у него за это время всё это хорошо отложилось в голове и памяти - и вдруг - облом - другим это таким же лёгким не кажется. А вот убедить других - уделите этому - три месяца - и вам тоже покажется лёгким и понятным - особенно современно поколение, привыкшее тратить на освоение нового (язык С за 24 часа) минимум времени, а если не получается - нахнах - ну вот никак - все такие упёртые и не хотят увидеть Брульянт.
В целом, как я уже сказал и судя по комментам - впечатлить пока не удалось.
Радио-86РК
16.05.2020, 18:39
В чём её преимущества перед другими?Кaк выше я и сказал: x80 - архитектура i8080, но с красивой таблицей команд.
Тем самым, преимущество, в первую очередь, именно в красоте.
А так как я никаким боком не инженер, то просто реинженерю i8080. Сначала я переделал известный (http://rk86.ru/) эмулятор и переписывался с его автором. В его эмуляторе я просто добавил «case 0x40: case 0x49: case 0x52: …», то есть все холостые MOV-пересылки: mov b,b; mov c,c; mov d,d и т.д…
И эти холостые MOV я превратил в префиксы, чтобы код «40 86» работал как «add b,m» без участия аккумулятора.
Кто-то сказал, что идея - не плохая, так как куролесица с аккумуляторным АЛУ жутко напрягала. Но, на кристалле это выполнить в 70-е невозможно. Слишком дорого бы обошлось перехватывать коды холостых MOV. Потому обошлись инженеры лишь тем, что «mov m,m» превратили в «hlt».
Для чего создается?Чисто из интереса!
Сначала я пробовал накидать схему перехвата MOV-префиксов, чтобы проверить, правда ли сложно?
Потом решил причесать таблицу команд и вскоре понял, что переделывать эмулятор перебивкой сотен case каждый раз - очень тяжело.
Написал свой эмулятор с генератором команд по шаблону.
Так и «mov m,m» (hlt) переместился в позицию 00 и я начал активно прорабатывать идею уже как отдельную архитектуру.
Я выбросил все команды с адресом: «ld sp,addr», «ld hl,addr», «ld bc,addr», «ld de,addr», «ld a,addr», «ld a,(addr)», «ld hl,(addr)», «ld (addr),a», «ld (addr),hl» и «jp addr».
Если в мою таблицу вглядеться внимательнее, то по-своему - это совершенный i8080, каким он мог быть в 70-е с самого начала…
Система команд более ортогональна, чем у z80, так как префиксами там достигается вся гибкость почти уровня i8086.
Проходит ли данная архитектура по "лезвию Оккама"?С трудом догадываюсь, в чём вопрос.
Если не обращать внимания на префиксы, то x80 - тот же i8080, но, как выше сказал, без команд с кодами 01, 11, 21, 22, 2A, 31, 32, 3A, C2, C3, C4, CA, CC, D2, D4, DA, D4, E2, E4, EA, EC, F2, F4, FA, FC.
А так же и без кодов C0, C8, D0, D8, E0, E8, F0, F8 и D3, DB, F3, FB, 09, 19, 29, 39.
То есть, слишком редуцированный i8080, так как все те команды доступны уже через префикс.
Не проверял, проходит ли тест по Тьюрингу мой процессор в этом случае, так как схематически получается гораздо проще i8080 в реализации собачником.
По теме
Тему можно было назвать «i8080/8086 - перезагрузка!», так как я именно занимаюсь перезагрузкой этих архитектур, как Вы уже поняли.
Это как из i8086 вытрясти все 16-битные команды и сделать ремейк i8080, который может выполнять программы i8086.
То есть, из 16-битного i8086 сделать 8-битник (не i8088).
(А не гибрид типа NEC V20 (https://ru.wikipedia.org/wiki/NEC_V20)…)
Регистровый файл
Все регистры у аппаратного x80 должны быть во внешнем регистровом файле в виде статического ОЗУ.
Тем самым, даже команда «NOP» будет занимать десятки тактов из-за активного доступа к внешней статике.
То есть, сначала прочитать младший байт регистра адреса команды IP, затем - старший байт. Уже 4 такта.
Затем, выдать IP на шину адреса, прочитать код команды - ещё 8 тактов.
Потом выполнить инкремент IP и записать его в статику - ещё 12 тактов.
Как видите, прототип x80 в FPGA или ТТЛ будет очень медленным.
Здесь в пору заметить: Если Вы ждёте от прототипа x80 супер скорости, можете выходить из темы…
Резюме
Цель: Перезагрузить саму систему команд i8080, чтобы она могла в последствии стать 32-битной или 64-битной.
Причём, совместимость в обе стороны: 64-битные x80-программы можно запускать и на 8-битном x80, но производительность упадёт в сто раз!!!
Это сделано с той целью, что, используя современные технологии с супер-кешом, по-идее в перспективе можно будет добиться доступа к регистровому файла за 1 такт. А введя конвейер, ускорить исполнение команд в несколько раз. То есть, это уже уровень мастерства.
Сейчас главное (для меня) - просто добиться функциональной полноты системы команд, чтобы хотя бы в эмуляторе работало гладко.
Система команд PDP-11 тоже хорошо ложится на коды, только восьмеричные.
Самое прикольное, что и система команд 8080 тоже хорошо ложится на восьмеричные коды. Формат опкода побитно: ggRRRrrr, где gg - группа команд, RRR - регистр назначения, rrr - регистр источника, а в командах где в группе нет регистра источника или назначения, эта восьмиричная цифра означает код операции. Но Интел почему-то решил, что 16-ричная система лучше и всё пошло наперекосяк.
Самое прикольное, что и система команд 8080 тоже хорошо ложится на восьмеричные коды. Формат опкода побитно: ggRRRrrr,
Вполне возможно, я уже давно не касался 8080 (хотя в загашнике лежат Радио-86 и Микроща), так что просто не помню свои разборки в то давнее время, когда Микроша стала моим первым домашним компам. Но и провозился я с ней относительно не долго - в продаже появился БК-0010.01 - и против PDP-11 совместимого я, ессссенно (первая любоф) - не устоял. После чего Микроша.. просто лежала :) А потом появился УК-НЦ (с флопами) - и стало лежать два компа :) А потом мне предложили их продать - и я не устоял :) Малолетний идиот :) Ну а теперь - лежат как ностальгия - может и повожусь :)
Микроша, кстати, была продана уже с моей доработкой - расширил ОЗУ до 48 кб и некоторые программы (точно - редактор и ассемблер) - перенес в верхние 16 кб, что дало мне аж почти 32 кб свободной памяти :) Но вот ПЗУ тогда прошивать не было на чём, поэтому монитор не умел использовать верхний блок :)
Но Интел почему-то решил, что 16-ричная система лучше и всё пошло наперекосяк.
Я так и не научился её воспринимать нормально :) В восьмеричной и складываю и вычитаю и слово делю на байты в уме, а hex - только слово на байты могу - остальное - калькулятор из Win :)
Радио-86РК
16.05.2020, 22:10
Самое прикольное, что и система команд 8080 тоже хорошо ложится на восьмеричные коды.O чём я и говорю. Когда в справочниках отца по микропроцессорам изучал комплекты серий типа 1801 и т.д…, то путался всегда в этих их восьмеричных адресах и вообще не понимал ничего.
(Вроде бы операции умножения проглядываются, но выглядело (после дампов РК) всё как-то несерьёзно: Спорное заявление, но это - дело вкуса…)
А с РАДИО-86РК и ASCII-таблицу вызубрил быстро, и в адресации стал разбираться.
Это наверное дело вкуса. Но, как я уже сказал, здесь x80 имеет редуцированную систему команд i8080, которая из восьмеричного порядка комплектации команд в таблице была приведена к шестнадцатеричному виду.
Не забывайте, что…https://img-fotki.yandex.ru/get/9816/22857638.5/0_db53b_f2b148f0_XXXL.bmp (https://zx-pk.ru/threads/22922-yut-88-faq.html?p=687663&viewfull=1#post687663)…представляла ь именно шестнадцатеричной таблицей. Да и дамп в Hex-представлении куда удобнее и компактнее на экране с 52 символами на строку.
И адрес F803 выглядит красивее и запоминается легче, чем 174003.
Человек, прежде всего, мыслит словами и звуками: F803 - Функция #8-03.
Наверное, здесь ещё играет роль особенности памяти индивидуума: Кто-то номера телефонов запоминает легко цифрами, а кто-то - буквами:
http://3.bp.blogspot.com/-EXb88SeTF-E/U7JgMhcvYYI/AAAAAAAACPM/cuGVzEMtsV0/s1600/%D0%BD%D0%BE%D0%BC%D0%B5%D1%80%D0%BE%D0%BD%D0%B0%D 0%B1%D0%B8%D1%80%D0%B0%D1%82%D0%B5%D0%BB%D1%8C+%D1 %82%D0%B0%D0%BD-6.jpgНапример, у моего знакомого номер сотового я помню только потому, что он представляется как «-BABNIK» - «-222645». А своей племяннице сим-карту покупал на «-DOLLY-» - «-36559-».
(На владельцев блатных номеров, типа 111-11-11, я смотрю как на безграмотных гопников из 90-х…)
Даже в системе команд x86 меня напрягает поле «md-reg-r/m» как восьмеричное.
Пытался делать эмулятор i8086 с шестнадцатеричным полем операндов как «h-reg-l-r/m», чтобы голым дампом не нужно было в уме индекс регистра из восьмеричной системы переводить в нормальный Hex-вид…
P.S.: Потому, как ответвление от i8080, этот x80 именно шестнадцатеричный.
HardWareMan
17.05.2020, 09:57
Например, у моего знакомого номер сотового я помню только потому, что он представляется как «-BABNIK» - «-222645». А своей племяннице сим-карту покупал на «-DOLLY-» - «-36559-».
(На владельцев блатных номеров, типа 111-11-11, я смотрю как на безграмотных гопников из 90-х…)
А мой телефонный номер состоит из полного количества строк SECAM стандарта и даты моего рождения. :)
Радио-86РК
17.05.2020, 15:08
Вчерa накидал пример всех способов адресации и расстроился.
Вот смотрите:
07 :MOV DL,[BX] ; Косвенно-регистровая адресация
67 :MOV DL,CL ; Регистровая адресация
A7 89:MOV DL,0x89 ; Непосредственная адресация
55 A7 89:MOV DL,[BX-119] ; Относительная адресация
E4 55 A7 89:MOV DL,[BX+AL-119] ; Индексная адресация
B8 FE 55 A7 89:MOVX DL,[BX+XX-119] ; Чтение в режиме X по индексу XX - ломается эстетика
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
0A :ADD AL,[BX] ; Косвенно-регистровая адресация
6A :ADD AL,CL ; Регистровая адресация
AA 89:ADD AL,0x89 ; Непосредственная адресация
55 AA 89:ADD BL,0x89 ; Непосредственная адресация
E4 55 AA 89:ADD4 BL,0x89 ; Сложение в режиме #4
B8 FE 55 AA 89:ADDX BL,0x89 ; Сложение в цикле режима X - ломается эстетика
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
81 23:PUSH 0x0123 ; Помещение константы в стек
91 23:PUSH 0xF123 ; Помещение константы в стек
55 81 23:PUSH 0x5123 ; Помещение константы в стек
55 91 23:PUSH 0xA123 ; Помещение константы в стек
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
55 A0 23:PUSH [BX+35] ; Относительная адресация
55 B0 23:POP [BX+35] ; Относительная адресация
E4 55 A0 23:PUSH [BX+AL+35] ; Индексная адресация
E4 55 B0 23:POP [BX+AL+35] ; Индексная адресация
B8 FE 55 A0 23:PUSHX[BX+XX+35] ; Индексная адресация X по XX - ломается эстетика
B8 FE 55 B0 23:POPX [BX+XX+35] ; Индексная адресация X по XX - ломается эстетикаЕсли Вы не обращаете внимания на издержки технологий с уродством команд x86, то ничего не заметите и не поймёте…
А я - попал в тупик. Так как «MOV DL,[BX+AL-119]» кодируется последовательно (следите за лесенкой: Система префиксов проста), а вот закодировать «MOVW DL,[BX+AL-119]» я уже не смог - ломается эстетика!
Да, именно эстетика для ручного восприятия и набития байт-кода!
Что такое здесь за «MOVX», «PUSHX» и «POPX»?
В регистровом файле регистр BL имеет адрес 0x00B0, регистр BH - адрес 0x00B8, где BX - соответственно 0x00B8:0x00B0.
Промежутки 0x00B1…0x00B7 и 0x00B9…0x00BF не используются, но подразумеваются.
То есть:
В 8-битном x80 регистр BL - ячейка 0x00B0
В 16-битном x80 регистр BL - ячейки 0x00B0 и 0x00B1
В 24-битном x80 регистр BL - ячейки 0x00B0, 0x00B1 и 0x00B2
В 32-битном x80 регистр BL - ячейки 0x00B0, 0x00B1, 0x00B2 и 0x00B3
В 64-битном x80 регистр BL - ячейки 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6 и 0x00B7
То есть, в отличии от x86 с именами «BX», «EBX» и «RBX», здесь у меня «BX» - всегда «BX».
А вот «ADD», «PUSH» или «MOV» может меняться на «ADD8», «ADD16», «ADD32» или «ADD64».
То есть 8-битный x80 будет исполнять 32-битное x80-приложение очень медленно, последовательно читая и перезаписывая аккумулятор AL по ячейкам 0x00A0, 0x00A1, 0x00A2 и 0x00A3 с затратой кучи тактов (эффект бутылочного горлышка).
Тогда как 32-битный x80 сразу прочтёт целое слово 0x00A0…0x00A3 за такт, выполнит АЛУ-операцию и за такт перезапишет слово.
То есть, формально в эмуляторе я уже могу написать и запустить 64-битный код, но не хочу.
На счёт остального…
Читаем VLIW (https://ru.wikipedia.org/wiki/VLIW):
Преимущества и недостатки (https://ru.wikipedia.org/wiki/VLIW#%D0%9F%D1%80%D0%B5%D0%B8%D0%BC%D1%83%D1%89%D0 %B5%D1%81%D1%82%D0%B2%D0%B0_%D0%B8_%D0%BD%D0%B5%D0 %B4%D0%BE%D1%81%D1%82%D0%B0%D1%82%D0%BA%D0%B8)
Архитектура VLIW выглядит довольно экзотической и непривычной для программиста. Из-за сложных внутренних зависимостей кода программирование вручную, на уровне машинных кодов для VLIW-архитектур, является достаточно сложным. Приходится полагаться на оптимизацию компилятора.Ясно, что ничего общего у моего x80 не имеется ни с RISC, ни с VLIW.
Но, из «Из-за сложных внутренних зависимостей кода программирование вручную, на уровне машинных кодов для VLIW-архитектур, является достаточно сложным. Приходится полагаться на оптимизацию компилятора» видно, что программиста всё-таки нельзя оставлять в изоляции от машинного кода с барьером в лице компилятора!
Тем самым, так как изначально мною курс был взят за «Даёшь байт-код народу», то любое отклонение от него - крах всего концептульного плана.
P.S.: Не смотря на возмущения и критику многих, в данной теме нужно просто принять за де-факто то, что здесь обсуждаются проблемы разработки процессора с прозрачным байт-кодом так, как видит его автор. То есть - я…
Вам выбирать, подключаться ли к проекту или игнорировать - архитектура моего процессора от этого не изменится. Вы и сами это понимаете, так как форум для того и существует.
Как «художник-технарь», я вижу идеальный процессор именно так!
Если видите иначе - откройте другую ветку.
Smalovsky
17.05.2020, 15:18
MIPS - уныл
Mi amigo, ¿tienes algo contra MIPS?
Радио-86РК
18.05.2020, 21:41
Кстaти, так как x80 задумывался в идеале как CISC-процессор на ТТЛ, в силу своей сложности рассматривался вариант с RISC-ядром, как это сделали с i486.
(Если помните, то i486 в сравнении с i386 стал чуточку медленнее (уже забыл, где, но по-моему, команды LOOP, IN, OUT пострадали). Но здесь я не буду вкапываться в историю Intel…)
А чтобы не зависеть от топовых решений индустрии, ядром x80 я решил сделать собственную архитектуру (https://zx-pk.ru/threads/31817-x80-risc-yadro-s-intuitivnoj-sistemoj-komand-dlya-x80-cisc.html) со сквозным кодированием команд методом акына: Что вижу, то и кодирую.
Тем самым, так как в эмуляторе используются 18 бит кодируемой команды и схема узла выборки команды (https://zx-pk.ru/threads/31789-x80-cisc-uzhe-ne-i8080-eshchjo-ne-i8086.html?p=1063185&viewfull=1#post1063185) выдаёт эти биты, то прямым кодированием можно закодировать в лоб 262144 микропрограмм.
Например:
; Код B8 FF - Команда RET
;
; 18-битный внутренний бинарный индекс подпрограммы:
; 0x00FB8
; 0x04FB8
; 0x08FB8
; 0x0CFB8
; 0x10FB8
; 0x14FB8
; 0x18FB8
; 0x1CFB8
; 0x20FB8
; 0x24FB8
; 0x28FB8
; 0x2CFB8
; 0x30FB8
; 0x34FB8
; 0x38FB8
; 0x3CFB8
;
; Примерный дамп микропрограммы команды RET
000FB800 A9 AA 01 - A9 = 1
000FB803 CB C4 B4 AD - AD = B4:C4
000FB807 CA 0A - C4 += A9
000FB809 BA DC 0A - DC B4 += A9
000FB80B CC C9 BE - C9 = [AD]
000FB80E CB C4 B4 AD - AD = B4:C4
000FB812 CA 0A - C4 += A9
000FB814 BA DC 0A - DC B4 += A9
000FB817 BB B9 BE - B9 = [AD]
000FB81A CB C9 B9 AD EBТо есть, тем самым, x80-команда RET разворачивается всего в 31 RISC-команду по 2 такта на каждую и требует 62 такта!
Это - чудовищный результат!
Не смотря на чудовищное обилие микропрограмм в четверть миллиона, каждая микропрограмма будет жрать по несколько десятков тактов!
P.S.: Вот так я стараюсь не ограничиваться одним JavaScript-эмулятором, а прощупываю более-менее приемлемые способы реализации не отступая от курса концепции: Не искажая общую таблицу всех команд.
Мне ведь не дипломную работу защищать, где худо-бедно хоть какой-то процессор пинком запустить лампочками моргать.
Потому и не торопясь десятилетиями двигаюсь крайне медленно к реализации всей концепции в целом, чтобы x80-Linux запустить в перспективе.
(Это для тех, кто хотел бы увидеть результат и прототип хотя бы к 2038 году: Не дождётесь!)
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot