?

Log in

простой эмулятор (программистское) - Поклонник деепричастий [entries|archive|friends|userinfo]
Anatoly Vorobey

[ website | Website ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Links
[Links:| English-language weblog ]

простой эмулятор (программистское) [дек. 25, 2013|01:37 am]
Anatoly Vorobey
[Tags|]

x5602 - a simple 6502 CPU emulator

Проект, демонстрирующий очень простой эмулятор микропроцессора 6502 (который широко использовался в самом начале эры персональных компьютеров - Atari, Apple II, Commodore 64...). Если вы знаете язык C даже в общих чертах, и никогда не писали код, симулирующий работу процессора, то этот проект - хорошее введение в то, как к этому вообще подходить.

Я иногда думаю, что должно быть больше обучающего кода - сознательно игрушечных проектов, написанных специально для того, чтобы научить читателя, с чего начинать и как все организовывать в данной области. Таких вот, как этот проект. Наверное, самые обычные примеры этого - разнообразные игрушечные операционные системы и компиляторы, использующиеся в университетских курсах на эти темы.
СсылкаОтветить

Comments:
[User Picture]From: michk
2013-12-24 11:54 pm
XINU? :=-)
(Ответить) (Thread)
[User Picture]From: xxqs
2013-12-25 01:30 am
один большой switch и более сотни case... не уверен, что именно так и надо писать :)
(Ответить) (Thread)
[User Picture]From: archaicos
2013-12-25 02:12 am
Можно сделать разбивку инструкций по:
— кодировке инструкции и операндов
— числу и типу операндов
— типу операции (ADD, XOR, CALL, etc)
Это может несколько сократить switch в декодере инструкций, но взамен получатся большие таблицы (или много маленьких) и логика будет в коде менее явная. Останутся всякие switch'и (или, опять же, будут таблицы) для выполнения той или иной операции по её уникальному номеру.

Далее, в зависимости от крутизны процессора, на котором будет происходить эмуляция, организация кода эмулятора может существенно влиять на скорость эмуляции. Один большой switch может оказаться самым эффективным решением.

Даже для эмуляции очень симметричного и простого для декодирования MIPS'а с четырёхбайтовыми инструкциями нужно поддержать около сотни инструкций общего назначения, и это занимает где-то 600+ строк очень компактного C кода (с длинными строками, за 100 символов:).

Кстати, о большом switch'е и MIPS'е... MIPS на MIPS'е эмулируется (если мы не говорим о виртуализации или продвинутых вещах типа бинарной трансляции) лучше всего (с т.з. производительности) с одним большим switch'ем. Бóльшая часть нужных переменных (в т.ч. временных, создаваемых компилятором) помещается в регистры (штук 20 из 32-х доступны), а если ещё и почти не вызывать ф-ций изнутри этого switch'а, получаются минимальные накладные расходы на переливание из пустого в порожнее и на переходы туда-сюда-обратно. Можно получить всего около 25 инструкций эмулятора на эмуляцию одной инструкции. Сильно структурированный красивый и «правильный» код может раздуть эти 25 до 75-100. Не уверен, что так и надо писать. :)
(Ответить) (Parent) (Thread)
[User Picture]From: spamsink
2013-12-25 02:16 am
Даже для эмуляции очень симметричного и простого для декодирования MIPS'а...

Попробуй предсказать размер программы на Си, эмулирующей писишку (XT), включая какой-нибудь графический режим, чтобы в игрушки можно было играть.
(Ответить) (Parent) (Thread)
[User Picture]From: archaicos
2013-12-25 02:21 am
30+ тысяч строк кода на C.
(Ответить) (Parent) (Thread)
[User Picture]From: spamsink
2013-12-25 02:26 am
По данным разведки, один из победителей недавно завершившегося конкурса IOCCC, объявленный как "IBM PC emulator", умеет и графический режим c помощью SDL, и позволяет играть, в частности, в сьерровские игрушки и во флайт симулятор. Верхний предел размера кода, согласно правилам конкурса - 4096 байт.
(Ответить) (Parent) (Thread)
[User Picture]From: archaicos
2013-12-25 02:55 am
Как я понимаю, чтобы подобное влезло в 4K нужно это делать той же платформе x86, много чего упростить/вырезать/не доделать, использовать особенности и функциональность ОС и сторонних библиотек. Моя оценка была для общего случая, когда халявы минимум и надо делать почти всё самому. Там, поди, порты CGA/EGA/VGA не особо эмулируются внутри этих 4K (кроме портов для установки палитры), а эмулируется сразу int 0x10 для установки режима?
(Ответить) (Parent) (Thread)
[User Picture]From: spamsink
2013-12-25 03:23 am
Через неделю-другую, когда обещали выложить - посмотрим. По-моему, если использовать особенности ОС, код, наоборот, раздувается. Но даже не считая графики, упихать всю систему команд в меньше, чем 4К - очень круто.
(Ответить) (Parent) (Thread)
[User Picture]From: archaicos
2013-12-25 03:45 am
А она не упихана. Там бóльшая часть инструкций исполняется почти напрямую. Иначе — никак.

Ты частично декодируешь инструкцию, немного её модифицируешь (добавляешь или убираешь префиксы размера операнда и адреса, выбрасываешь сегментные префиксы, меняешь адрес, закодированный в инструкции в полях ModR/M, SIB, disp), запихиваешь её в специально подготовленный буфер, где уже есть инструкции до и после, которые загружают регистры значениями из эмулятора и потом выгружают результат обратно. После этого передаёшь управление на буфер. Вот и готова одна инструкция типа ADD AX, [BX] без полного декодирования и полной честной эмуляции.

Понятно, что нужно отлавливать инструкции типа системных и тех, которые трогают вещи, которые нельзя трогать (сегменты, флаги, IP (передача управления), SP и пр.), и их уже честнее эмулировать. И ещё деление нужно специально обрабатывать чтобы эмулятор вдруг не упал сам.

Так ещё можно сделать. Но это трюк не пройдёт на другом железе.
(Ответить) (Parent) (Thread)
[User Picture]From: xxqs
2013-12-25 12:41 pm
я бы скорее подумал, как 256-разрядное дерево запилить для декодинга. Понятно, что без вызова 1-2 функций на каждую инструкцию не обойтись, но по идее это будет дешевле, чем 100 сравнений в switch/case. Ну и это ещё и простенький процессор.
(Ответить) (Parent) (Thread)
[User Picture]From: archaicos
2013-12-25 12:51 pm
Толковые современные компиляторы уже умеют раскладывать switch не на сто сравнений аргумента с сотней констант, а на дерево (или несколько), несколько инструкций и переход(ы) по таблице(-ам). Загляните в код, сгенерированный компилятором.
(Ответить) (Parent) (Thread)
[User Picture]From: xxqs
2013-12-25 12:56 pm
интересно, мерси. Увы, заниматься таким ресерчем некогда, поверю на слово :)
(Ответить) (Parent) (Thread)
[User Picture]From: e2pii1
2013-12-25 03:39 am
> код, симулирующий работу процессора, то этот проект - хорошее введение в то, как к этому вообще подходить

А в чем там принципиальная сложность, и что может быть непонятного в том как к этому подходить ? (процессор ведь без внутренней параллельности выполнения инструкций, что усложнило бы задачу).

Пишем структуру данных соответствуюшую регистрам, флагам и прочему, и реализуем инструкции процессора по документации. Что еще ?
(Ответить) (Thread)
[User Picture]From: archaicos
2013-12-25 03:55 am
Иногда хочется быстро или очень быстро.

Иногда хочется чтобы временные характеристики (или время, наблюдаемое внутри эмулируемого кода, текло ожидаемым образом) максимально сохранялись.

Иногда хочется имеющиеся особенности и глюки существующего железа полностью повторить (например, знаете что именно процессор сделает со сдвигаемым регистром, если счётчик сдвига содержит слишком большое число, и документация на процессор, говорит, что в этой ситуации результат не определён? Или что-то типа MOV EAX, SS — знаете что процессор положит в старшие 16 бит EAX на процессоре более старом, чем Pentium? И т.д.).

Кроме всего этого, документация часто содержит неточности и ошибки. Например, на x86 я сверял документацию Intel с документацией AMD и с тем, что на самом деле делал процессор. Много чего нашёл.

Т.е. вроде так ничего особенного, но часто это прорва работы, и не каждому под силу, особенно начинающему программисту.
(Ответить) (Parent) (Thread)
From: pesec
2013-12-27 03:39 pm
Иногда хочется быстро или очень быстро.

Есть что-то более мощное, чем threaded code или JIT?
(Ответить) (Parent) (Thread)
[User Picture]From: archaicos
2013-12-28 05:18 am
На данный момент, как я понимаю, лучше JIT может быть только лучший JIT. :)
(Ответить) (Parent) (Thread)
[User Picture]From: lyuden
2013-12-25 06:33 am
Не могу не пропиарить

http://pythontutor.com/visualize.html#

Он работает конечно на повыше. Но позволяет пошагово визуализировать исполнение достаточно сложных вещей.

(Ответить) (Thread)
[User Picture]From: begemotv2718
2013-12-25 11:49 am
Надеюсь, все видели
http://www.visual6502.org/JSSim/
(Ответить) (Thread)