давайте покрасим шляпу в желтый цвет, воткнем в нее огурец и придумаем этому этакое крутое название. Для начала неплохо-бы начать с общей концепции, предполагаемой направленности, чего предполагается добиться, каких преимуществ перед аналогами итд. Если это для интереса, то этот интерес надо четко обозначить. Если предполагается ввести ограничения - тоже (можно еще их разделить по строгости). А только потом уже переходить к конкретике. А проговый эмуль хоть на вб на коленке пишется. Проц значительно проще возможностей яву.
Нeт худа без добра… Имея уйму времени, чтобы не свихнуться от безделья и мешка досуга, вернулся к доработке своего x80-прожэкта… Самые торопливые, ленивые или далёкие могут сразу просто нажать и увидеть в действии (F1 - 1 шаг отладки эмуляции, F4 - запуск эмуляции)… Сказать по-правде, два месяца ежедневного усидчивого труда принесли свои плоды. На страничке имеется JS-эмулятор, дизассемблер и ассемблер. Естественно, не подведу тех, кто меня здесь знает долгие годы - всё списывал с потолка, никакого стороннего кода нет ни в строчке. x80-идеалогия Никаких Z80-совместимостей мною не предполагалось. Была взята простота системы команд i8080, вся таблица команд была рассортирована, чтобы интуитивно и голыми руками байт-кодом можно было бить готовый код. Да, многие критикуют, мол, давно уж XXI век и бить дампы руками - жуткое извращение. Тем более, подгонять систему команд и байт-код под эстетическое визуальное восприятие субъекта. Но, считая, что технические издержки сложности устройства дешифратора команд никак не должны надрывать визуально таблицу команд и проглядываться в ней грыжей. Так как это - временные технические издержки. Тем более, что в современных i5/i7 и даже с i486 уж в те времена команды x86 транслируются в RISC-микрокод. Что сводит к нулю актуальность того, что команды hlt/nop/ret и другие получили именно те коды. За 25 лет попыток придумать нечто своё, мечтая и воображая себя инженером программируемых систем, приобрелось мною в большей степени - духовно, а не практически. И я для себя решил: Эстетика - прежде всего! x80-архитектура Никаких привычных адресов под прерывания не предусмотрено. Вообще, наличие внешних прерываний нужно проверять программно и только на уровне ядра Захват шин под ПДП реализуется так же - специальные фрагменты кода отвечают за организацию ПДП. Прозрачного режима ПДП нет и программист сам должен описать командами цикл пересылки Команды с высокой частотой использования кодируются в 1 байт. Более редкие команды требуют больше. Так, относительные call/jmp всего требуют 2-3 байта, тогда как абсолютные - по 3-5 байтов Таблица команд не плоская и множество инструкций меняют принцип работы в совокупности с разными режимами цикла/ожидания или на уровне ядра. Так, прикладной hlt-останов в режиме ядра переключает контекст задач Реликтовые рудименты in/out/ei/di/rcon/stc/daa и многие другие - полностью исключены, но имеются в комплексной доступности. Так, если call/jmp бессмысленно переходят на самих же себя - работает как префикс смены режима Флажки состояния АЛУ частично стали и флажками управления дешифратором команд. Так, невозможное АЛУ-состояние ZF+PF (ноль нечётного паритета) работает как SKIP-префикс для условного пропуска команд без ветвления Все регистры общего назначения имеют стековое устройство. Предыдущее значение изменённого регистра сохраняется в файле его истории глубиной до 4 уровней. И ip/sp имеют историю (для int-ситуаций) Указатели стека всегда должны быть выровненными по модулю 2. Тем самым, младший бит работает как опциональный для особых случаев (push/pop с невыровненным стеком работают с внутренним стеком текущего контекста) Каждая задача имеет собственный контекст из 256 слов. Из которых 64 - стек истории РОН и указателей ip/sp. А 140 слов - буфер пользовательских команд (или ПДП алгоритма) И так… Вас заинтересовало хоть чуточку это? Тогда читайте дальше: Команда, кодируемая парной шестнадцатиричной цифрой восьмиричного диапазона (11h,22h,33h,44h,55h,66h,77h) является префиксом следующей команды. 00h - hlt для приложения или контекстный mov для системного кода Префикс, кодируемый дважды (11h+11h, 22h+22h, ...) управляет индексированием состояния АЛУ. Так, 55h+55h в ассемблере значит hlt 5. Если следующая команда - skip/loop/wait, они продолжатся на 5 итераций Префикс (11h, 22h, ...) перед командами call/jmp расширяет шаг перехода с ±128 до ±1024. Перед командами push/pop - указывают регистр базовой адресации (как push/pop word ptr [r16+im8] в x86) Префикс перед nop указывает длительность холостой операции (nop 1-7) для организации чётких задержек или запуска механизма режима ПДП (не прозрачен же, но управляем) именно в нужных местах Префикс int 0-9 (да, 10 команд) расширяет их до int 10-79. Которые, в свою очередь, не вызывают особую подпрограмму, а запускают механизм обработки прерывания/исключения Команда int с префиксом wait переключает дешифратор команд на внутреннюю память. Позволяя выполнить пользовательские экспресс-инструкции со скоростью до 1 такта на команду (например, команды ПДП-цикла или сравнения строк, как x86-rep) Префикс перед операцией АЛУ просто подменяет аккумулятор нужным регистром. А перед mov с константой - устанавливает базовый регистр для доступа к таблице Обработка исключений и прерываний Так как в процессоре возможны Бейсиковые on n goto переключатели (skip n + восемь jmp), команда переключения контекста после выполнения прикладного кода возвращается режимом пропуска до 8 инструкций. Так, если во время выполнения приложения пришёл запрос на прерывание, запрос на ПДП, запрос от механизма защиты памяти, запрос от узла аварийной ситуации - приложение приостановится, а в ядре выставится счётчик пропуска 1-7 инструкций jmp для перехода к нужному обработчику. (сигнал Reset - тоже событие подобного уровня. обработчик может пассивно обработать до 65535 команд, пока процессор не сбросится. или принудительно обнулять счётчик, чтобы игнорировать Сброс) P.S.: Пытаюсь в Verilog набросать задуманное. Но, пока и в js-эмуляторе есть много проблем: Где-то ассемблер гонет, где-то дизассемблер неадекватно декодирует сложные цепочки, где-то дешифратор команд сбоит (в крайне сложных местах уровеня экспресс-макросов) и требует сложной пошаговой отладки…
Спасибо! Еcли мои танцы с самодельным бубном кому-то интересны, вот наброски документации к придумываемому процессору: Код (Text): Представляемая концепция процессорного устройства базируется на переработанной системе команд прaоцессора i8080 с полной утратой совместимости уровня машинных команд и с частично достигнутой совместимостью с ассемблером процессора i8086. ______________________________________________________________________________ Таблица системы команд процессора была расчитана под интуитивное восприятие на принципе ассоциативных предпосылок субъективного уровня с учитыванием реальной возможной частоты использования различных инструкций в построениях алгоритмов. Некоторые из инструкций, в силу морального устаревания и потерей актуальности, были изначально исключены или получили более комплексный код редкой комбинации обычных команд, чтобы не засорять таблицу и сохранять перспективу наращивания. Регистр статуса процессора был переорганизован и флажки АЛУ получили частичную связь на дешифратор команд с возможностью управлять периодом выполнения команд для явного объявления условно реактивных и ленивых участков программного кода. Код (Text): Инструкции: Система команд процессора Дешифратор команд имеет 18 разрядов, имеющий условно разделённо-группированных восемь проименованных шин и каждая из них имеет своё назначение для дешифрации всех поддерживаемых архитектурой инструкций с перспективой явного наращивания. Всего набор команд представляется таблицей команд с восемью слоями и имеющих в своей структуре до восьми подслоёв, половина из которых доступна лишь основной программе высшего уровня привелегий, выполняющей роль ядра операционной среды. В состав процессора входит сверхоперативный контекстный файл с ёмкостью до 128 страниц, каждая из которых вмещает по 256 слов и обеспечивает сохранность всех значений регистров общего назначения независимо для каждой страницы контекста. Страница контекста имеет до 160 слов хранения операций реактивного исполнений, вызываемых трюковым способом из любого места программы и требующих как минимум от 1 такта на своё выполнение, позволяющих организовывать комплексные команды. Код (Text): Регистры Общего Назначения (РОН) Каждой исполняемой задаче доступен собственный независимый набор регистров, из которых можно выделить несколько особенных, имеющих механизмы контроля ошибок, автоматического инкремента/декремента и организации ленивых вычислений/циклов. Так, регистры BH:BL / CH:CL / DH:DL составляют набор регистровых пар BX/CX/DX, позволяющих организовывать косвенную и индексную адресацию для доступа к любой из всех ячеек предоставляемой операционной средой памяти в оперативном режиме. Несколько иначе организован регистр аккумулятора AL, имеющий условную половину AH(FX) косвенно-условной доступности, позволяющего обеспечивать условные петли и безусловные циклы, а также и опциональные линейные селекторы или вычисления. +----------------+ +-----------------+ +-----------------+ +-----------------+ | AX | | BX | | CX | | DX | +---------+------+ +--------+--------+ +--------+--------+ +--------+--------+ | AH(FX) | AL | | BH | BL | | CH | CL | | DH | DL | +----+----+------+ +--------+--------+ +--------+--------+ +--------+--------+ | FH | FL | | == | == \__________ |0:--|0000: ------- \____________________________________________ |1:BH|0001:-- -- ZF # Zeroed result | |2:CH|0010:-- CF -- # Carry Flag | |3:DH|0011:-- CF ZF # Zero with Carry | |4:AL|0100:PF -- -- # Odd Parity Flag | |5:BL|0101:{SKIP FH}# Skip mode (register counter / x1..x7 times) | |6:CL|0110:PF CF -- # Odd Parity with Carry | |7:DL|0111:{SKIP FH}# Skip mode (register counter / x1..x7 times) | |8:--|1000:SF -- -- # Signed result | |9:x1|1001:{LOOP FH}# Loop mode (register counter / x1..x7 times) | |A:x2|1010:SF CF -- # Signed result with Carry | |B:x3|1011:{LOOP FH}# Loop mode (register counter / x1..x7 times) | |C:..|1100:SF PF -- # Signed result with odd Parity | |D:BX|1101:{ ----- }# | |E:CX|1110:SF PF CF # Signed result with odd Parity and Carry | |F:DX|1111:{WAIT FH}# Wait mode (register counter / x1..x7 times) | +----+------------------------------------------------------------ Код (Text): Регистровые указатели Указатель инструкций IP имеет опциональный указатель JP, у стековых указателей SP и BP младший бит имеет опциональное назначение для отслеживания критических ситуаций или управления автоматическим инкрементом/декрементом значений SI/DI. +----------------+ +---------------+-+ +---------------+-+ +-----------------+ |______ IP ______| | SP /EF| | BP /FF| |_____ SI/DI _____| | \__/ | | +-----+ / | | +-----+ / | | \++|--/ | | JP | | /Error-Flag| | /Fault-Flag| |Auto-Inc|Auto-Dec| +----------------+ | / /increment| +-----+-----------+ +-----------------+ +----+------------+ Код (Text): Флаги: Регистр состояния процессора/АЛУ Регистр состояния FX является старшим AH в AX, разделён на два ниббла FH и FL. Старшим нибблом хранится индекс опционального регистра/указателя или итерации. Младшим нибблом отражается комбинация режима дешифратора инструкций с флажками результата действий команд АЛУ. Правилами постулатов исполнения вычислительных операций исключаются вариации нуля нечётного паритета или отрицательного нуля. Ноль нечётного паритета запрещает регистрирование результата выполнения потока дешифрируемых инструкций на период с декрементацией опционального регистра или итерации в старшем ниббле, позволяя опционально пропускать цепочку инструкций. Отрицательный ноль приостанавливает считывание следующих инструкций, организуя цикл на период с полной или условной декрементацией опционального регистра или итерации в старшем ниббле, позволяя опционально ставить цикл и режим ожидания. Через режим условного ожидания организуется возможность доступа к интерфейсным устройствам ввода/вывода или внешней шине состояния сигналов событий ресурсов, чтобы описывать алгоритмы своевременной обработки всех допускаемых прерываний. Код (Text): Обработка программных и аппаратных прерываний Архитектурой процессора не предусматривается возможность оперативной реакции в режиме реального времени на любые внешние сигналы от периферии с генерацией по их запросам определённых прерываний на обращение к соответствующим процедурам. После включения ядра процессора и аппаратного сброса, управление передаётся на нулевой контекст программы по вектору 0xFF00 с возможностью прямого доступа ко всем ресурсам среды системы, всем контекстным файлам и к регистрам управления. В обязанности кода основного процесса входит необходимость настройки периферии и соответствующего реагирования на любые внешние сигналы с её стороны, а также организации поддержки интерфейса с другим прикладным программным обеспечением. Процесс ядра системы не имеет возможность непосредственного опроса внешних шин и считывания их состояния без организации исполнения кода прикладного уровня с поддержанием его нормального исполнения и надлежащего предоставления ресурсов. Код (Text): Доступ к внешним устройствам и регистрам контекстного файла Системой команд не предусматриваются непосредственные команды доступа к портам ввода/вывода для взаимодействия с устройствами периферии или доступа к ячейкам контекстного файла и управляющим регистрам представления контекстной проекции. Подобные операции находятся за пределами области задач прикладного уровня и не засоряют таблицу команд как специализированные инструкции, используемые крайне редко в зонах временной необходимости сервисных процедур операционной системы. Процессором имеется достаточное количество префиксов для организации трюкового достижения необходимых системных ресурсов в рамках кода операционной системы и ограниченного контролируемого прикладного трюкового доступа к нужным ресурсам. В момент попытки доступа приложения к порту ввода/вывода, исполнение программы временно приостанавливается и управление передаётся ядру системы с загрузкой в историю регистра-приёмника индекса порта, байта данных и режимом доступа в CF. Код (Text): Регистр селектора контекста (CS - Context Select Register) Для непосредственного доступа к контексту любой имеющейся прикладной задачи на уровне системного процесса доступен регистр CS, служащего переключателем задач в системной среде и управляющего привелегиями для текущего активного процесса. Базовая реализация процессора поддерживает от трёх независимых контекстов, под которыми может выполняться непосредственно код системного ядра, код диспетчера системных ресурсов с аппаратным интерфейсом и другой код прикладной программы. Контекст ядра всегда имеет индекс с базой 0, диспетчерам ресурсов определяются контексты с индексами от 127 до 100 в сторону уменьшения номера, тогда как все приложения индексируются контекстами от 1 до 99 в сторону возрастания номеров. Код (Text): Математические вычисления Операции умножения/деления изначально отсутствуют в системе команд процессора, но достигаются трюковым способом посредством режима цикла условного ожидания с элементарной арифметической операцией с пошаговыми приближениями к результату. Если вычислительная периферия в системе присутствует и поддерживает инструкции аппаратно, итеративного испольнения цикла не будет и он будет линейно прерван, позволяя программно определить наличие соответствующей поддерживающей системы.
Код (Text): Счётчик выдержки исполнения прикладного кода (TX - Ticks Counter: TL & TH) =========================================================================== Старший бит регистра CS управляет блокировкой прохождения тактов к регистру TX и на уровне приложений ведётся обратный отсчёт, окончание которого установит в CS бит блокировки счёта с переключением контекста в высокий системный уровень. Если при переключении с ядра к приложению счётчик TX был обнулён, ни один байт прикладного кода не будет выполнен и управление получит вновь ядро с возвратом кода состояния внешней периферийной шины через аккумклятор и флаг переноса CF. Если в момент переключения на контекст приложения счётчик TX готов отсчитать 1 такт, будет выполнена одна единственная операция приложения и управление снова получит ядро, что позволяет организовывать пошаговый режим отладчика программ. Код (Text): ..::: Context File Layout :::::::::::::::::::::::::::::::::::::::::::::::::::: .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F 00:-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --|INT 0:Up to 7 opcodes A0:AL>>LO>>Стек истории --|AH>>HI>> ++ .. -- -- --|AX-Stack B0:BL>>LO>>модификации- --|BH>>HI>> ++ .. -- -- --|BX-Stack C0:CL>>LO>>всех РОН- -- --|CH>>HI>> ++ .. -- -- --|CX-Stack D0:DL>>LO>> ++ .. -- -- --|DH>>HI>> ++ .. -- -- --|DX-Stack E0:SP>LO/BP>LO/SI>LO/DI>LO|SP>HI/BP>HI/SI>HI/DI>HI|SP/BP/SI/DI-Stack F0:IP>>LO>> ++/.. ../JP.LO|IP>>HI>> ++/.. ../JP.HI|IP/JP +0:CS -- -- -- -- -- TL.TH |Control Registers Код (Text): ;;; Примерная трюковая цепочка ;;; Макрос псевдонима мнемоники с описанием ;;; ;;;;;;; MOV [0],DL ;;; Запись индекса проекции контекста HLT DL ; Указываем регистр источника индекса WAIT ; Приступаем к ожиданию системной операции HLT ; Инструкция работает лишь в проекции системы ;;;;;;; MOV DL,[0] ;;; Чтение индекса проекции контекста HLT ; Выбираем индекс считываемого регистра WAIT ; Приступаем к ожиданию системной операции HLT DL ; Считываем в регистр индекс проекции ;;;;;;; MOV DL,[DL] ;;; Читаем байт файла контекста HLT DL ; Указываем принимающий регистр WAIT ; Готовимся читать данные HLT DL ; В регистр DL ;;;;;;; MOV [DL],AL ;;; Пишем байт в файл контекста HLT DL ; Указываем регистр выбора ячейки WAIT ; Готовимся писать данные HLT AL ; в ячейку DL из регистра AL ;;;;;;; MOV DL,[1] ;;; Читаем байт регистра контроля HLT 1 ; Указываем индекс считываемого регистра WAIT ; Готовимся читать данные HLT DL ; Указываем принимающий регистр ;;;;;;; MOV [1],DL ;;; Пишем байт в регистр контроля HLT DL ; в ячейку из регистра DL WAIT ; Готовимся писать данные HLT 1 ; Указываем регистр контроля ;;;;;;; IN DH ;;; Читаем данные с порта HLT 1 ; Вибираем индекс регистра BH с индексом порта WAIT ; Готовимся читать данные HLT 1 ; В регистр BH ;;;;;;; OUT [DH],CH ;;; Пишем данные в порт HLT 1 ; Выбираем регистр BH с записуемым байтом WAIT ; Готовимся писать данные HLT 2 ; в порт CH из регистра BH Код (Text): ;;; Примеры инструкций с расширением их возможностей опциональными битами ;;;; MOV AL,[DI+1] ; Считывает данные с базовым смещением, ; работает во всех стандартных режимах (EF==0) MOV AL,[DI+1] ; Считывает данные без смещения, но производит ; пост-инкремент указателя, лишь когда (EF==1) Код (Text): ;;; Примеры трюковых цепочек для выполнения вычислений с проверкой ускорения ; ;;;;;;; MUL AL,CH,CL ; Умножение с суммированием: AL+=CH*CL HLT CL ; Указываем регистр множителя CL WAIT ; Готовимся к вычислению ADD AL,CH ; Приближаемся к результату через множимое CH AND CL,CL ; Проверка участия регистра множителя в цикле JZ .software ; Если он обнулён - аппаратной поддержки нет ;;;;;;; DIV AL,CH,CL ; Деление: CL=255 :: CL-=AL/CH HLT CL ; Указываем регистр дополненного частного CL WAIT ; Готовимся к вычислению SUB AL,CH ; Приближаемся к результату через делитель CH JC .software ; Если признак CF - аппаратной поддержки нет Код (Text): ;;; Примерный набросок кода запуска управляющего ядра операционной системы ;;; ORG 0xFEFB ; Следующий макрос занимает 5 байтов KERNEL: ;;;;;;;;;;;;;;;;;;;;;;;;; Переключатель контекста на прикладной код .yield: MOV [0],AL ; Макрос переключения контекста регистром CR0 ;HLT AL ; Регистр AL указывает контекст/принимает код ;WAIT ; JMP $ - Переход в условный цикл ;HLT 0 ; HLT - Привелегированная операция для CR[0] ;;;;;;;;;;;;;;;;;;;;;;;;; ; Здесь располагается селектор с пропуском до 7 инструкций и передачей ; управления соответствующей ситуации процедуре .body: ;;;;;;;;;;;;;;;;;;;;;;;;; Тело обработчика прерываний - адрес : FF00h JMP .overhead ; Запрос к стандартному API JMP .acclaim ; Обращение к программным прерываниям INT 0-79 JMP .buffer ; Буферная зона - прослойка диспетчера памяти JMP .context ; Диспетчер переключения контекстов процессов JMP .device ; Запрос ко внешнему устройству ввода/вывода JMP .error ; Обработчик программных/аппаратных ошибок JMP .force ; Внешние форсированные события/прерывания JMP .garret ; Загрузочная область поверхностного уровня .context: ;;;;;;;;;;;;;;;;; Тело диспетчера контекста XOR AL,AL ; Подготавливаем регистр к чтению регистра CR HLT AL ; Определяем его как приёмник WAIT ; Переход в условный цикл HLT 7 ; Считываем содержимое CR[7] в AL ;;; ;;; ;;; ; Оперативные действия с контекстом MOV AL,0x01 ; Выставляем индекс выбираемого контекста CMP AL,AL ; Сброс флага переноса CF CMC ; Устанавливаем флаг, если требуется протокол JMP .yield ; .device: ;;;;;;;;;;;;;;;;; Тело диспетчера периферии Список некоторых команд (небрежный пробный набросок) Код (Text): HLT 00 :HLT ;Останов. Команда не работает на системном уровне nn 00 :HLT Rn ;Захват регистра за опциональный nn nn :HLT Pn/n ;Захват указателя или числового индекса ~~~ MOV yx :MOV Rx,Ry ;Пересылка между регистрами 44 yx :MOV Px,Py ;Пересылка между указателями Ax ii:MOV Rx,i ;Загрузка непосредственной константы в регистр nn Ax ii:MOV Rx,[Pn+i] ;Загрузка с базовым смещением nn Bx ii:MOV [Pn+i],Rx ;Выгрузка в базовое смещение r# nn Bx ii:MOV [Pn+=i],Rx ;Выгрузка по смещению и итерационным шагом w# xx :MOV Rx,[Rx] ;Чтение с контекста w# yx :MOV [Rx],Ry ;Запись в контекст w# nn nn :MOV Rw,[n] ;Чтение управляющего регистра w# ?? 00 :MOV [?],Rw ;Запись в управляющий регистр w# 00 :MOV [0],Rw ;Переключение контекста ~~~ JMP B8 ii:JMP $+i ;Ветвление с относительной адресацией -128..+127 nn B8 ii:JMP $+n+i ;Ветвление с относительной адресацией -1024..+1023 nn mm ii FF:JMP n+m+i ;Ветвление с абсолютной адресацией 0..65535 w# 00 :JMP Rw ;Переключение контекста --- WAIT B8 FE:WAIT ;Ветвление с замыканием в режим условного ожидания nn nn B8 FE:WAIT n ;Пример режима ожидания с указанием длительности nn 00 B8 FE:WAIT Rn ;Пример режима ожидания с указанием счётчика ______________________________________________________________________________ ii - непосредственный байт mm - байты с 80h по 9Fh, расширяющие байт до слова (nnnmmmmm iiiiiiii) nn - префикс 11h/22h/33h/44h/55h/66h/77h ?? - префикс может отсутствовать (тогда по-умолчанию он - 00h) y/x- совокупность двух восьмиричных чисел в нибблах (12h/13h..76h/77h) r# - означает префикс повтора командами LOOP n/Rn/[Rn] w# - означает префикс ожидания командами WAIT n/Rn Код (Text): ПРИМЕРЫ 44 00 B8 FE 55 55:MOV AL,[5] ;Чтение управляющего регистра 44 00 B8 FE 55 00:MOV [5],AL ;Запись в управляющий регистр 44 00 B8 FE 00 :JMP AL ;Переключение на контекст задачи 44 FС 22 B6 03 :MOV [SI+=3],CL ;Запись с итерационным шагом счётчика AL 44 FC 22 A6 7D :MOV CL,[BX+2*AL];Чтение с двойной шириной по базе Из прикреплённой анимированной таблицы можно заметить, что разрабатываемая система команд довольно усложнённая версия классической i8080. P.S.: Конечно, сам не верю, что кто-то осилит данный текст. А тем более, хоть что-то поймёт из этого. Но, тем не менее, это - хоть какой-то материал, показывающий, что я достаточно серъёзно подошёл к вопросу реализации "мечты детства". Надеюсь, что доживу до той фазы, когда прожэкт превратится в реальный FPGA-проект и я почувствую тепло от микросхемы, вентили которой греются от разработанных мною цепей
Вам бы для начала доку по ARM почитать. Много интересного можно было бы вытащить оттуда. А так получается какая-то сложная мешанина флагов и регистров вместе + непонятно откуда взятая необходимость обрабатывать прерывания только из ядра (риалтаймом и не пахнет в принципе). К тому же: - Если вы выкинули in/out-инструкции, как ваш процессор будет работать с устройствами ввода-вывода? Сферический процессор в вакууме никому не нужен. - Зачем реализовывать стековое устройство регистров? Не проще ли сделать shadowing? То есть, решения вроде какие-то приняты, но адекватность их вызывает серьёзные вопросы.
Мнe не в первый советуют ARM курить. Да, купил недавно ATtiny, но программатор дорогой, а симулятор, пишут, очень глючный. Отложил до лучших времён. Кстати, в детстве я перечитал все справочники отца по микропроцессорам. И не мог понять, почему вместо продвинутых процессоров, серий типа К584 и К1801 (не помню точно) со встроенными операциями работы с плавающей запятой, везде только и твердят про совместимость с К580 и К1810. Вы, надеюсь, удосужились эмулятор погонять? Хотябы минуты 2-4. Больше не требуется. (Грузите страничку, включаете полноэкранку - F11, жмёте F4 - и наблюдаете) В дизассемблере видно - синтаксис подобия x86-инструкций. Флаги? Мне всегда не нравилось, что у Интел флаги всегда под маской: 1 и два 0. И долбанутый AC для DAA. В прошлых годах я наконец забил на наследие Интел и расписал флаги как мне удобно (как программисту низкого уровня) Не выкинул их. В эмуляторе они таки проскакивают и имеются. Достаточно исходник пролистать. Или просто остановить эмуляцию (нажав F1) во время чтения порта клавиатуры в процедуре консоли. Там чтение порта имеется в двух видах: Доступ к портам из-под "переполнение стека" (mov al,[sp+0fdh] при sp=0ffffh - получаем 100fdh, что больше, чем 65535, значит - порт Доступ через "портовое окно". Нельзя, чтобы указатели sp и ip пересекались. Стек не может накладываться на код. В таком случае открывается окно к портам Доступ через wait+mov - wait+mov al,[bx] - бесполезное чтение из памяти раз 100. Потому работает как ожидание готовности чтения с порта циклом в 100 итераций Выше я же представил таблицу "трюков", как обычными командами получит доступ к УВВ. (Думаю, что не вчитывались, но решили покритиковать ) При отладке очень не хватает раскрутить не только стек, но и историю регистров (где-то здесь обсуждали, что при отладке этого очень не хватает). Тем более, у меня это не для шейдинга сделано, а для других целей. Просто, как программиста-школьника, меня всегда мучал вопрос: Почему rep+movsb писать можно, а rep+mov dx,[si] например, нельзя! В разрабатываемой системе команд можно всё. Тем более, ассемблерно - она x86-совместима. Что облегчает значительно портировать многие ключевые алгоритмы (линии/круги Брезенххэма, извлечения корня и т.д.) исходниками как есть с лёгкими поправками P.S.: Спасибо за критику, однако
Чего чего? "5 проводков" на коленке делается и прошивается через PonyProg. В китае готовые копеечные можно заказать. Либо я не понял посыл, тогда извиняюсь, но такая команда не имеет смысла, а вообще писать можно так, просто префикс игнорируется.
Дa, пролистывал, куча схем "5 проводков". Только, "отпугивают" некоторые ньюансы. Например, левый софт для прошивки или немаленькая вероятность "подпалить" всё Да-да, посыл не поняли. Это как "под юбку" технологиям заглядывать: В справочниках писалось, что wait, rep, lods, stos, movs, cmps, cli, sti кодируются коротким одним байтом для повышения производительности алгоритмов, что было очень-очень важно в те годы! Однако, сейчас эти однобайтовые команды не так актуальны. Тем самым, rep+mov dx,[bx+17] могла бы работатать как rep+lodsw, но читать mov dx,[bx] с пост-инкрементом add bx,17. Т.е. читается из [bx], но bx+17 происходит потом. Пост-инкремент с гибким шагом (±32767). В таком бы плане rep-префиксы стали бы более функциональны. Например, rep+add dh,[eax-400] или rep+xor dword ptr [eax+4],-1. P.S.: До сих пор не понимаю: Либо я так мутно всегда пишу, либо многие ленятся чуточку включить фантазию и понять с полуслова, что я хотел сказать.
Вот вот.... Самообразование надо повышать! ...Ведь тут то всё понятно.... Первый класс, вторая четверть!!! Шучю конечно...
Можнo ли обсудить техническую сторону вопроса? Сейчас в шаблоне дешифратора команд насчитывается около 78 инструкций. Понятное дело, что реализовывать всё это "чудо" в железе - слишком "прикольно". Если бегло сравнить два шаблона Спойлер: Шаблон i8080 Код (Javascript): 00XXX000C NOP : 00XX0001E LXI P#Z,IW :P_#Z=iw, ctx.IP+=2 00XX0011E INX P#Z :P_#Z=(P_#Z+1)&65535 00XXX100A INR R#Y :$1=ctx.alu(R_#Y, 1, 2), R_#Y=$1 00XXX101A DCR R#Y :$1=ctx.alu(R_#Y, 1, 3), R_#Y=$1 00XX1001E DAD P#Z :$1=P_02+P_#Z,F_LG=(($1>65535?2:0)|(($1&65535)>32767?8:0)),P_02=($1&65535) 00XX1011E DCX P#Z :P_#Z=(P_#Z-1)&65535 00XXX110F MVI R#Y,IB :R_#Y=ib 01110110C HLT :ctx.IP-- 01XXXXXXF MOV R#Y,R#X :R_#Y=R_#X 10XXXXXXA ALU#Y R#X :$1=ctx.alu(R_07,R_#X,#Y), R_07=$1 11XXX000B R_C#Y :ctx.IP= 11000011B JMP IW :ctx.IP=iw 11001001B RET :ctx.NIP=(ctx.IP=ctx.stack()) 11001101B CALL IW :ctx.IP+=2, ctx.stack(ctx.IP), ctx.IP=iw 11100011E XTHL :$1=Q_02, Q_02=ctx.mem_16(P_03), ctx.mem_16(P_03, $1) 11101011E XCHG :$1=Q_02, Q_02=Q_01, Q_01=Q_02 11XXX110A ALI#Y IB :$1=ctx.alu(R_07,ib,#Y), R_07=$1 11XXX010B J_C#Y IW :ctx.IP+=((ctx["R" + ctx.CI + "0"]>>(8|(#X>>1)))^(#X&1))&1?ssb:0,ctx.DIP=ctx.LIP=ctx.NIP=ctx.IP 11XXX100B C_C#Y IW :ctx.IP+=((ctx["R" + ctx.CI + "0"]>>(8|(#X>>1)))^(#X&1))&1?[ctx.stack(ctx.IP),sb][1]:0,ctx.DIP=ctx.LIP=ctx.NIP=ctx.IP 11XX0101E PUSH Q#Z :ctx.stack(Q_#Z) 11XXX111B INT #Y : 11XX0001E POP Q#Z :Q_#Z=ctx.stack() XXXXXXXXC --- : Спойлер: Шаблон x80 Код (Javascript): +----------------=> $M[17:15]:Mask | +-------------=> $L[14:12]:Loop mode(0:Normal; 1:Wait+Fn; 2:Loop; 3:Wait; 4+:System+...) (asm: LOOP/WAIT) | | +-----------=> $K[ 11 ]:Keep open(1:$Z==FH/$B==-2) (asm: HLT $Z + WAIT) | | | +---------=> $Z[10:8 ]:PREFIX $Z | | | | +-------=> $J[ 7 ]: | | | | | +-----=> $Y[ 6:4 ]: | | | | | | +---=> $I[ 3 ]: | | | | | | | +-=> $X[ 2:0 ]: | | | | | | | | /|\/|\|/|\|/|\|/|\ MMMLLLKZZZJYYYIXXX_ XXXX00X00000000000C HLT :return 0 //HALT 111X00XXXX0XXX0XXXC HLT P$Z/$Z :FH($Z | 8) //Hold P$Z!/$Z 1XXX00XXXX00000000C HLT R$Z :FH($Z | 0) //Hold R$Z! XXX111XXXX00000000C MOV [$Z],ACC :CR($Z, ACC()) //CR[$Z] = ACC 111111XXXX0XXX0XXXC MOV ACC,[$Z] :ACC(CR($Z)) //ACC = CR[$Z] 1XXXXXX0000XXX0XXX_ PREFIX R$X/P$Y :return 0 //Prefix 101X00XXXX0XXX0XXXF XCHG R$Z,R$Y :$1=R$Z(),R$Z(R$Y()),R$Y($1) //Exchange R$Z! and R$Y! 110X00XXXX0XXX0XXXF XCHG P$Z,P$Y :$1=P$Z(),P$Z(P$Y()),P$Y($1) //Exchange P$Z! and P$Y! XXXX11XXXX0XXX0000X .Y$Y :0 //reserved XXXX11XXXX00000XXXX .X$X :0 //reserved 1XXX11X1000XXX0XXXC IN R$X :R$X(PORT(R$X())) //Input from port XXXX11X1000XXX0XXXC OUT R$X,R$Y :PORT(R$X(),R$Y()) //Output to port 001X11X0000XXX0000F .Y$Y R$X;[R$Y] :0 //reserved 010X11X00000000XXXF .X$X [R$X];R$Y :0 //reserved 0XXX11X0000XXX0XXXF MOV [R$X],R$Y :CTX(R$X(), R$Y())+ FL(0),$IE=0 //Context 1XXX11X0000XXX0XXXF MOV R$X,[R$X] :R$X(CTX(R$X()))+ FL(0) //Context XXXXXXX0000XXX0XXXF MOV R$X,R$Y :R$X(R$Y()) //Move R$Y! to R$X! 100XX0XXXX1111XXXXB INT $T :HEAP($IP)+IP(JP(10>$T?0:1)),$IF=true //Interruption 1X1X00X00011101XXXE PUSH U$X :HEAP(U$X()) //Push U$X! into stack 1X1X00X00011111XXXE POP U$X :U$X(HEAP()) //Pop U$X! from stack XXXX00XXXX11111110C NOP {$Z} :$Z //Hollow operation XXXX00X10010101XXXA ALU$X IB :$1=ALU$X(DROP(FH()),$B),ACC($1),FL($1.hi()) //ALU$X! with retained and immediate XXXX00XXXX10101XXXA ALU$X Z$Z,IB :$1=ALU$X(Z$Z(),$B),Z$Z($1),FL($1.hi()) //ALU$X! with Z$Z! and byte XXXX00X1000XXX1XXXA ALU$X Z$Y :$1=ALU$X(DROP($Y),REG($Y)),REG($Y,$1),FL($1.hi()) //ALU$X! with Z$Y! and retained XXXX00XXXX0XXX1XXXA ALU$X Z$Z,R$Y :$1=ALU$X(Z$Z(),R$Y()),Z$Z($1),FL($1.hi()) //ALU$X! with Z$Z! and R$Y! XXXX00XXXX100XXXXXE PUSH $VIB :HEAP(0x$V00 + $B) //Push immediate data into stack 111XXXX00011001XXXD INC Q$X :Q$X(Q$X()+1) //Increment Q$X! 111XXXX00011011XXXD DEC Q$X :Q$X(Q$X()-1) //Decrement Q$X! XXXXXXX00011001111A CMC :FL(FL() ^ 2) //Complement carry flag XXXXXXXXXX11001110D ADC BX,T$Z :$1=BX()+T$Z()+(_CF?1:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), BX($1) //Addition register pair with carry 111XXXXXXX11001XXXD ADD Q$X,T$Z :$1=Q$X()+T$Z()+(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q$X($1) //Addition register pair XXXXXXXXXX11011110D SBB BX,T$Z :$1=BX()-T$Z()-(_CF?1:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), BX($1) //Subtraction register pair with borrow 111XXXXXXX11011XXXD SUB Q$X,T$Z :$1=Q$X()-T$Z()-(_CF?0:0),$2=($1>>15)&2,FL((FL()& 0xD)|$2), Q$X($1) //Subtraction register pair XXXXXXX00011001010A XCHG :$1=ACC(); for($2=0,$0=0;8>$0;++$0,$1>>=1) $2=($2<<1)+($1&1); ACC($2)>0 //Exchange retained bits by mirror XXXXXXXXXX11001010A XCHG P$Z :$1=DST(),DST(P$Z()),P$Z($1) //Exchange P$Z! with retained pair XXXXXXXXXX11001111A XCHG R$Z :$1=ACC(),ACC(R$Z()),R$Z($1) //Exchange R$Z! with retained register XXXXXXX100110X1XXXA ALU$W :$1=ACC(ALU$W(ACC())),FL($1.hi()) //ALU$W! with retained XXXXXXXXXX110X1XXXA ALU$W Z$Z :$1=Z$Z(ALU$W(Z$Z())),FL($1.hi()) //ALU$W! with Z$Z! 0XXX00X1000XXX0XXXF MOV P$X,T$Y :P$X(T$Y()) //Move T$Y! vector to P$X! XXXX00X00010100XXXF MOV R$X,IB :R$X($B) //Move immediate data into R$X! ... XXXX00X10010111XXXF MOV [U$X],IB :DB(U$X(),$B) //Load immediate data into memory by U$X XXXX00100010111000C WAIT ACC :FL((FL() & 0x02) | 0x0D) //Wait XXXX000XXX10111000B JMP $+$UIB :$A==-2?(FL((FL() & 0x02) | 0x0D),trace.expression=0):IP(IP()+$A) //Unonditional relative branching XXXX000XXX10111001B CALL $+$UIB :$A==-2?0:HEAP(IP(IP()+$A)) //Unconditional relative call XXXX001XXX10111XXXC DCND$X :CND$X?0:FL((FL() & 0x02) | 0x05) //Conditional do XXXX00100010111001X . :0 //reserved XXXX00100010111XXXX . :0 //reserved XXXX000XXX10111XXXB BCND$X $+$UIB :CND$X?IP(IP()+$A):0 //Branching if CND$X! XXXXXXXXXXXXXXXXXXX Y$Y_X$X ($M) :0 //reserved Сразу можно заметить, что разрабатываемая система команд довольно усложнённая версия классической i8080. Ментально (только в воображении) схему дешифратора я набросал и пришёл к выводу, что лучше иметь как раз ПЗУ на эти 78 инструкций с микрокодом. Существуют ли промышленные экземпляры контроллеров для подобных целей? Ну, чтобы на их базе построить любой выдуманный процессор было бы достаточно легко. Естественно, и с конвейером, и т.п. Что-то типа Эльбруса с динамической эмуляцией кода. Только попроще. Без всяких там "чудес" технологий. P.S.: По-идее, должны же существовать какие-то готовые решения "в помощь радиолюбителю"
Автору топика: Как пытающийся сделать, пописывающий эмуль x86 (пусть не 25 лет, но уж точно лет 5), выражаю огромный респект вашему багажу знаний. Еще раз советую - тема имеет полное право быть в Wasm.Projects. В тред призывается R71MT (сейчас под ником Коцит) - по "радиолюбительским" аспектам.
_edge, если ТС молчит, значит ему и не нужно -- перенос темы в другой раздел сложности не представляет
Если вы хотите модель - можно все создать в Proteus . ММУ АЛУ память .. и тп. все можно там реализовать. Если вы хотите аппаратно, то на ум приходит какая нить FPGA не слишком дорогая (Циклон 4 - вам хватит я думаю). Используются в промышленности. Но порог вхождения там высок (как и цена). Но с вашими знаниями - вы справитесь 100 процентов.
Багaж, не багаж… Но, опыт имеется. Правда, с Verilog всё ещё не разобрался. Трудно переделать собственное сознание от вертикального представления решения задачи (команда за командой) к горизонтальному (все команды - сразу и параллельно) Имеется ввиду вот это? Давно мечтаю купить, но боюсь, что не справлюсь и зря только приобрету. У меня позиция "Афони". Как общественность считает - так пусть и поступают. Если тема считается информативной - можно попросить и перенести P.S.: Лишь бы потом не вышвырнули…
Да, но есть подешевле Altera Cyclone V Если не справитесь - продадите, я уверен найдутся желающие в вашем городе.
Думaю, лучше не мелочиться: Купить подороже, но с избыточным функционалом (с видео входом/выходом, звуком, сетью, гироскопами, зуммерами и погремушками), чем сожалеть о нехватке чего-то. Смoтрю вот, а дата создания темы то - 22 дек 2008. Практически, 7 лет ушло (в github опубликовался год назад) на написание собственного универсального движка эмуляции (да-да, раньше были классические switch(код) case команда1 и т.д. пока не решил замахнуться на персер шаблона). Из исходников эмулятора можете увидеть, что ассемблер-дизассемблер-эмулятор - почти универсальны: Стоит поменять что-то в шаблоне - везде всё изменится (и код бут-стартера меня приходится местами править). Хотелось бы иметь хоть какой-то плагин, чтобы фрагменты Verilog можно было бы интегрировать прямо в систему (где-то я видел платные утилиты, которые синтезируют схемки в USB-девайс) под браузер (Скрэтч позволяет управлять в браузере физическими Лего-механизмами). Идеально было бы иметь просто PCI-карточку с FPGA, в котором можно было бы и состряпать свой процессор, и открыть ему доступ к памяти компьютера, как бы сделав ещё одно ядро к основному процессору В JavaScript не хватает того, что фундаментально имеется в Verilog: Меняя одну переменную, необходимо форсировать перерасчёт некоторых значений, так-как электрически они менялись бы пассивно. P.S.: Опять-таки, опасаюсь, что не подниму своими силами своё же творение Ещё с операционкой проблемы: Публично нужно представлять нормальную среду с консолью, менеджерами и всяческими демками. Ещё лучше - простенький сервер, подобный этому, для наглядности. (у автора сайта, всё же, проще: он серийный процессор собрал с полной совместимостью с компиляторами, трансляторами и утилитами)
Paguo_86PK, за ссылку на дядьку со своим CPU - спасибо - интересно почитать. на счет плагина не знаю - но видел крутую штуку Vivado Design Suite правда стоимость такого пакета вам не понравится. На сколько я понял - это то что вас интересует
Тaк ссылку эту мне тут и дали! Пользовался как-то этой утилитой - у неё ещё какой-то "Velleman k8055 USB experiment board plug-in" есть (не получилось завести), другие - платны. Хотя, симуляторов - пруд прудить. P.S.: Самое сложное в дешифраторе у меня - его нелинейность. Многие команды имеют смежные коды, но выполняться должны лишь те, кто по позиции - выше. Тем самым, требуется "лесенька" с обратной связью, что вызовет значительные задержки. Как выход - просто использовать ПЗУ за дешифратор. Но, на входе - порядка 18 бит. Т.е. на целый 256кб прошивка для каких-то восьми десятков команд - что крайне не экономно. Нечто среднее - мажорительные цепи, что требует стробирования. А значит, выделения тактов - опять задержка (в x86 дешифратор путанный, но однозначный). Это лишь малая доля сложностей, о которые я споткнулся. Но, меня всю организацию позиций команд в угоду облегчения цепей дешифратора не считаю разумным (говорю же, RISC-конвейерами динамической эмуляции все сложности снялись бы). Хотя меня уже призывали ориентироваться таки из самого устройства дешифратора, а не из субъективно-эстетических соображений… На дворе - XXI век! Первые микроскопы были с резными корпусами, как предмет декора. Радиоприёмники 100 лет назад имели деревянные лакированные корпуса, ни хуже скрипок Страдивари А сейчас? Всё одноликое и однообразное: Планшеты продают, вон, с двумя цветами корпуса - розовый и серый. Нет, чтобы как шкатулку их расписывать Потому я - противник того, чтобы процессоры XXI века имели байт-код "лишь бы быстро и надёжно". Пора возвращаться к искусству и строить ещё "красиво и эстетично", Господа!