Микроконтроллер Nintendo "Game and Watch" или как ускорить инкремент

Тема в разделе "WASM.ARTICLES", создана пользователем aa_dav, 22 ноя 2021.

Метки:
  1. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    248
    В первых наладонных электронных играх Nintendo — Game & Watch (которые в СССР клонировали в виде «Волк ловит яйца» и т.п.) в качестве процессора использовались 4–битные микроконтроллеры Sharp серии SM–5xx.
    [​IMG]
    Например в популярных версиях про Микки–Мауса, морячка Попайя или Donkey Kong–а трудился чип SM–510.
    Счётчик команд в этом чипе был сегментированным и в пределах сегмента адрес команды был 6–битным (значения от 0 до 63).
    Традиционно счётчик команд при переходе к следующей инкрементируется, т.е. увеличивается на единицу и многие сочли бы это одним из самых простых арифметических действий для такой задачи, однако создатели Sharp SM–510 посчитали инкремент шестибитного счётчика слишком долгой операцией и упростили её!

    «Проблема» с инкрементами тут в том, что чтобы вычислить i–ый разряд надо знать произошло переполнение в разряде i–1 или нет — по триггерам счётчика «бежит» электронная волна вот этого вот вычисления переноса и окончательного вычисления разряда. Чем больше бит, тем дольше эта волна бежит и тем большую паузу нужно выдерживать в электронных схемах чтобы быть уверенным что всё число посчиталось до конца. Вот эта пауза разработчикам видимо и не понравилась, т.к. инкременты 4–битных значений в этом микроконтроллере были, но 6–битный счётчик инструкций видимо в них не вписывался.
    Краткий мануал по процессору можно посмотреть тут: bitsavers.org/components/sharp/_dataBooks/1990_Sharp_Microcomputers_Data_Book.pdf

    Очень кратко обрисую его характеристики:
    ROM 2772 x 8 бит
    RAM 128 x 4 бита (из которых 32 x 4 бита VRAM находятся вне чипа)
    49 инструкций
    2 уровня вложенности стека (вызова процедур)
    4-битная RAM и 8-битная ROM — инструкции 8-битные и иногда даже двухбайтовые если нужен операнд. Т.к. почти все регистры были 4-битными, то например чтобы адресовать RAM использовались два индексных регистра Bm и Bl. Последний был 4-битным, а первый 3-битным и в инструкциях например сложения они давали адрес ячейки RAM с которой складывался аккумулятор. Двухбайтовой инструкцией можно было сразу загрузить и Bm и Bl, а однобайтовыми инкрементировать или декрементировать Bl для скорости.
    С ROM всё было еще запутаннее — PC состоял из трёх частей: Pu, Pm и Pl с битностями 2:4:6. Из арифметики по сути были только разные варианты сложения, десятичная коррекция, инверсия бит и прокрутка аккумулятора. В общем минимализм еще тот. Тактовая частота в 32768 Гц и её настраиваемый делитель с обработчиком прерываний прямо таки намекают на 1 прерывание в секунду чтобы обновить новыми цифрами времени LCD. Так что действительно не только Game, но и Watch напрашивался с самого начала.

    Но вернёмся к «инкременту» PC: в документации Sharp этот трюк обозначен как «polynomial counter» и отсылает к Регистрам сдвига с линейной обратной связью.
    Работает это вот как: на каждом шаге регистр сдвигается на 1 бит вправо и при этом новый появляющийся слева бит вычисляется как NOT (X XOR Y), где X и Y — это самые нижние биты счётчика до сдвига. Еще проще это выражение осмысливать как (X == Y), а на Си в эмуляторе MAME куда мне пришлось залезть чтобы до конца осознать документацию это выражается так (здесь — с сокращениями):
    Код (Text):
    1.  
    2. int feed = ((pc >> 1 ^ pc) & 1)? 0 : 0x20;
    3. new_pc = feed | (pc >> 1 & 0x1f);
    4.  
    В результате если начинать считать от нуля, то получается такая вот
    красивая табличка неповторяющихся кодов (в 16–ричной системе исчисления
    «шаг: адрес»):
    Код (Text):
    1.  
    2.  
    3. 00:00 01:20 02:30 03:38 04:3c 05:3e 06:1f 07:2f
    4. 08:37 09:3b 0a:3d 0b:1e 0c:0f 0d:27 0e:33 0f:39
    5. 10:1c 11:2e 12:17 13:2b 14:35 15:1a 16:0d 17:06
    6. 18:03 19:21 1a:10 1b:28 1c:34 1d:3a 1e:1d 1f:0e
    7. 20:07 21:23 22:31 23:18 24:2c 25:36 26:1b 27:2d
    8. 28:16 29:0b 2a:25 2b:12 2c:09 2d:04 2e:22 2f:11
    9. 30:08 31:24 32:32 33:19 34:0c 35:26 36:13 37:29
    10. 38:14 39:2a 3a:15 3b:0a 3c:05 3d:02 3e:01 3f:00
    11.  
    То есть следствием является то, что указатель инструкций «хаотично мечется» по памяти (и действительно главным упором LFSR является ГПСЧ), однако посещая каждую ячейку только один раз… точнее почти каждую, так как на последнем шаге 3f полученным адресом является не ff, а 00 — дело в том, что этот счётчик при затравочном значении ff просто на каждом шаге будет получать результат такой же — ff. Таким образом полный цикл до «проворота» в нём не 64 шага, а 63 и поэтому программы в SM–510 в каждой субстранице тоже имеют максимальный размер в 63 шага.

    Такой код применяется потому что он быстрее честного и тупого как валенок инкремента из–за того, что не надо ждать распространяющейся по разрядам задержки по учёту бита переноса из предыдущего разряда — здесь почти каждый бит зависит только от одного соседнего и только бит feed зависит от двух самых нижних, но тоже в простой зависимости.

    Вот такой лайфхак. xD
     
    Последнее редактирование: 22 ноя 2021
    Artem_N, TermoSINteZ и Thetrik нравится это.
  2. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    347
    Ха, ну тогда и К145ИК можно рассмотреть, хотя хабре уже рассматривали. Там то же максимально примитивно, однобитное АЛУ и т.д.
     
  3. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    248
    Я делал краткий обзор на обзор на хабре :) https://gamedev.ru/flame/forum/?id=226622&page=78&m=5268699#m1165
    Вообще "мир в кольце" вполне логичная для офисного калькулятора штука. Память типа сдвигового регистра - штука дешевая и подходящая тут во всём.
    Такие операции как сложение и вычитание выполняются над цифрами (тетрадами бит) последовательно с последовательным применением тетрады же переноса. Поэтому можно сказать, что АЛУ в МК-51 однобитное, хотя это немного коряво.
    Умножение реализуется обычно "в столбик", что суть есть тоже последовательное умножение на цифру с многократным сложением сдвинутых на одну цифру результатов. Логично, что эту операцию тоже можно делать в кольце.
    Под это в калькуляторах МК и была сделана программа-шаблон которая обрабатывала числа хранимые в кольце по следующим номерам микропрограмм:
    (0, 1, 2), (3, 4, 5), (3, 4, 5), (3, 4, 5), (3, 4, 5), (3, 4, 5), (3, 4, 5), (3, 4, 5), (6, 7, 8), (0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 1, 2, 3, 4, 5)
    Здесь я выделил скобками триады микропрограмм, т.к. они судя по всему трудятся каждое над своей цифрой числа.
    А числа в МК-51 были формата вроде бы такого: знак, 8 цифр мантиссы, знак и две цифры экспоненты.
    И если приглядеться к тому как в одном большом цикле выполняются микропрограммы - то да, видимо первая тетрада (0, 1, 2) как то обрабатывает знак, следующие семь третрад (3, 4, 5) обрабатывают цифры мантиссы и последнее (6, 7, 8) обрабатывает последнюю цифру мантиссы и переключает режим на обработку экспоненты. Далее опять таки (0, 1, 2) - знак экспоненты и две её цифры. Хотя возможно (0, 1, 2) это первое число компоненты, а знак хранится после и обрабатывается в (6, 7, 8). В общем как то так.

    И вот усложнившись до программируемых калькуляторов этот "мир в кольце" уже стал не помогать, а мешать скорее вычислениям, но съехать с него инженеры уже не могли малой кровью и продолжали его усложнять и наворачивать на него не только синусы с косинусами (что тоже раскладывается в ряды последовательных сложений членов ряда), но и алгоритмы последовательного выполнения пользовательской программы, что уже ну никак не выигрывало от постоянной прокрутки кольца и необходимости ждать до "проворота", но проигрывало.
    В результате на момент написания статьи в хабре мозги тех кто пытался это реверсить просто плавились и несмотря на существование полностью корректных эмуляторов понимание как это всё работает было крайне поверхностным! Жесть. Вот он - звериный оскал программно-аппаратного легаси. :D
     
  4. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    347
    Да, конечно, когда дело дошло до программируемых калькуляторов, создателям требовалось создать что-то другое, более эффективное.
    И это было сделано, МК-85, полноценный ПК в маленьком корпусе. Так что в СССР бы смартфоны лепили только так!