Когда load [PC] (на одном операнде X рассмотрим) отрабатывает он сперва в X грузит PC, а уже потом из-за бита indirect замещает X на [X]. Это совсем не то же самое что сперва загрузить в X [PC++], а потом заменить X на [X].
что совсем не повод так бездарно тратить номер регистра
load imm = load [pc++]
load [imm] = load [[pc++]]
второй случай можно закодировать через номер регистра флагов
(потому что, ну кому и зачем мб нужен косвенный доступ через флаги))

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

Регистров на самом деле хватает чтобы сделать memmove/memcopy полностью на регистрах, а это я считаю эталонным кодом для проверки на нехватку регистров.
а я считаю это разновидностью подхода «и так сойдёт» :P

Такую оптимизацию можно проделать в существующей системе команд и без swap:
; вызов процедуры
R3 =+2 PC; адрес возврата (inc2) (команда без immediate)
PC = proc_addr; вызов процедуры
; возврат из процедуры
PC = R3
нет! это совершенно не то же самое! например:
load R3,adr1
(вычисления)
(условный переход)
load R3,adr2
(вычисления)
swap PC,R3

Чем же он уродлив?
тем, что повторяет функцию универсального сложения с любой константой
собс-но, даже инкремент на 1 — пережиток неортогональных восьмибитных процов
(но он хотя бы нужен бывает часто, и его наличие мб оправданным)
у обмена же гораздо шире функционал

В эти годы уже просто для поддержки CP/M могли целый процессор Z80 засадить в какой нибудь Commodore XXL (не помню точно модели) — какая уж тут гонка за примитивизмом?
засадить могли, а в нормальную производительность z80 не шмогли
и это тормозное в cp/m режиме угрёбище справедливо было непопулярно
тем более, что и стоило вдвое дороже c64 того же года

Я уже говорил — команда типа SWAP BYTES внутри регистра (опять таки с логикой Y = swap bytes of X) делает такой сценарий маловероятным. Ну и вообще соединять комп с устройством которое плюётся данными быстрее чем или даже соизмеримо чем скорость с которой процессор отрабатывает memfill — это сомнительно и вряд ли такое вообще есть/было на практике.
на практике поддерживали 8 и 16 бит девайсы одновременно очень недешёвые песюки
причём в них не было полного отказа от 8 бит
  • avatar aa-dav
  • 0
а ну да, собственно 128Кб и есть, точно! :)
  • avatar nyuk
  • 1
>Commodore XXL (не помню точно модели)

Commodore 128
  • avatar aa-dav
  • 0
только частных случаев очень много и эффект заметный от ускорения
Такую оптимизацию можно проделать в существующей системе команд и без swap:
; вызов процедуры
R3 =+2 PC; адрес возврата (inc2) (команда без immediate)
PC = proc_addr; вызов процедуры
; возврат из процедуры
PC = R3
Как видно никакого SWAP и стека в таких хвостовых функциях можно реально не использовать.
Теоретически можно было бы использовать какую нибудь из запрещенных комбинаций регистров в операндах или псевдо-nop-ы как расширители команд, но повторюсь — мне здесь нравится именно простота.

а для «компа мечты» должно быть эффективней и удобнее, а не «проще»
В том то и дело, что я нахожу такую систему команд довольно эффективной и удобной. Тут само мышление прямолинейно как стрела — всё есть пересылка данных с опциональной операцией с высокой степенью ортогональности. Не нужно задумываться над перекладыванием данных по регистрам как в Z80 или тем какие режимы адресации есть а каких нет и в каких операциях как в 6502.

ну, уродливый inc2 протащил же :)
Чем же он уродлив? inc2 (реализовать можно как ADD с загрузкой константы 2 в Y на первых фазах выполнения команды) часто нужен, потому и сделан — экономит код программы хорошо. Он полностью укладывается в парадигму X ?= Y и уродливым в ней быть не может — inc1 разве чем то уродлив? Тоже часто нужен, потому и полезен — абсолютно та же фигня и даже в тот же профиль.

с чего такой вывод?
В эти годы уже просто для поддержки CP/M могли целый процессор Z80 засадить в какой нибудь Commodore XXL (не помню точно модели) — какая уж тут гонка за примитивизмом?

например, девайс подкидывает байты высоким темпом, нужно успевать выгребать

Я уже говорил — команда типа SWAP BYTES внутри регистра (опять таки с логикой Y = swap bytes of X) делает такой сценарий маловероятным. Ну и вообще соединять комп с устройством которое плюётся данными быстрее чем или даже соизмеримо чем скорость с которой процессор отрабатывает memfill — это сомнительно и вряд ли такое вообще есть/было на практике.
  • avatar aa-dav
  • 0
P.S. блин, какая то комбинация клавиш сработала на enter и запостила посередине набора, сейчас еще будет продолжение ответа.
  • avatar aa-dav
  • 0
это почему еще?
Когда load [PC] (на одном операнде X рассмотрим) отрабатывает он сперва в X грузит PC, а уже потом из-за бита indirect замещает X на [X]. Это совсем не то же самое что сперва загрузить в X [PC++], а потом заменить X на [X]. Система команд очень прямолинейна.

поэтому нужен swap
Swap регистров обычно нужен когда они существенно неортогональны и ради аккумулятора надо перестановки делать. Тут такой острой необходимости нет.
Регистров на самом деле хватает чтобы сделать memmove/memcopy полностью на регистрах, а это я считаю эталонным кодом для проверки на нехватку регистров.
Immediate сам может быть тоже indirect и таким образом операции можно проводить непосредственно над памятью не загрязняя регистры. С чтением через PC так уже не получится
это почему еще? сам же пишешь:
значение в X замещается значением ячейки памяти по адресу X
то есть load [PC],[PC] это X=[PC++]; Y=[PC++]; X=[X]; [Y]=X
что эквивалентно load [imm1],[imm2]
Т.к. регистров действительно немного,
вооот, в том числе еще поэтому нужен swap, а у тебя и регистров меньше, и свопа нет
а в самом обобщённом случае Link Register таки нужно пихать в стек,
только частных случаев очень много и эффект заметный от ускорения
плюс содержимое линк-регистра может служить указателем на данные процедуры
(после обработки данных с инкрементом получается корректный адрес возврата)
то делать так всегда имхо проще для системы команд
а для «компа мечты» должно быть эффективней и удобнее, а не «проще»
В ней есть только одна операция X ?= Y с лёгкими вариациями. Swap уже не пролазит и не знаю как его протащить без вреда для внутренней красоты.
ну, уродливый inc2 протащил же :)
Только до тех лет когда начали делать 128Кб-ные машины.
с чего такой вывод? это просто посадить на ту же шину больше микросхем
а не разрабатывать весь микропроцессорный комплект, а не только проц
Да ну, не вижу ни трудностей ни тем более невозможностей.
например, девайс подкидывает байты высоким темпом, нужно успевать выгребать и складывать их, а складывать ты можешь только словами; будешь выделять блок вдвое больше, а потом корячиться с утаптыванием? + удорожание в любом случае
Вот можно было бы и послушать, если есть конкретные образы и идеи. :)
пока некогда :)
  • avatar aa-dav
  • 0
Зря лишил себя одного регистра из-за непосредственного операнда, всё равно его читаешь через PC, вот и кодируй (с индиректом) тоже через PC.
Immediate сам может быть тоже indirect и таким образом операции можно проводить непосредственно над памятью не загрязняя регистры. С чтением через PC так уже не получится и поэтому такой лишний регистр, имхо, только усложнит в итоге программы.

И зачем адрес возврата обязательно пихать в память?
Т.к. регистров действительно немного, а в самом обобщённом случае Link Register таки нужно пихать в стек, то делать так всегда имхо проще для системы команд. В ней есть только одна операция X ?= Y с лёгкими вариациями. Swap уже не пролазит и не знаю как его протащить без вреда для внутренней красоты. :D

Для 80-х все шины ширины 16 (и все вспомогательные микрухи!) в домашней машине дороговато
Только до тех лет когда начали делать 128Кб-ные машины.
Далее получилось что истинным 16-биткам уже не хватало и этого и в них перекочевали банкинги и свитчинги в лучшем случае реализованные как сегментные регистры. Байты, правда, конечно, уже к тому времени стали вещью безальтернативной.

плюс доступную восьмибитную периферию трудно или невозможно использовать

Да ну, не вижу ни трудностей ни тем более невозможностей.
Несомненно раз уж есть мощная 8-битная предыстория, то разумно предусмотреть команды типа обмена/сдвига/зануления в слове байт, но уж куда подвести проводки от 8-битной периферии к 16-битной шине данных — по моему дело просто вкуса, но никак не трудностей.

Это уже был бы компик моей мечты))
Вот можно было бы и послушать, если есть конкретные образы и идеи. :)
  • avatar aa-dav
  • 2
На форуме откуда я пришёл — gamedev.ru есть энтузиасты написавшие продолжение игры Gradius: gamedev.ru/projects/forum/?id=244656
Это само по себе было бы не особо интересно даже, если бы не список платформ на которые это продолжение было портировано.
Кроме очевидных Windows и Linux есть порт на DOS (!) (причём использующий DOS4/GW о чём отдельная песня у них есть: gamedev.ru/flame/forum/?id=245611)
Но кроме этого есть два порта на самодельные (!) портативные игровые консоли Black Prism и EMU Pocket! :D

Не удивлюсь если это широко известные люди в узких кругах. :D
Зря лишил себя одного регистра из-за непосредственного операнда, всё равно его читаешь через PC, вот и кодируй (с индиректом) тоже через PC. И зачем адрес возврата обязательно пихать в память? В рисках, например, он пишется в (обычно специально выделенный) регистр, это дело вызываемой процедуры, сохранять в памяти его или нет. Можно сделать и через РОН, тут тебе пригодилась бы команда обмена, то есть вызов процедуры выглядит так load R,adr + swap PC,R и возврат load/swap PC,R (если обошёлся без стека).

Отказ полный от 8 бит может выглядеть восхитительно удачным только сегодня. Для 80-х все шины ширины 16 (и все вспомогательные микрухи!) в домашней машине дороговато, плюс доступную восьмибитную периферию трудно или невозможно использовать. И по мне, тогда уж лучше Форт-процессор на них сажать. Это уже был бы компик моей мечты))
Согласен про клоны, достойны отдельного разбора и списка. На PC Engine я как-то скачивал близкий к полному архив игр и просто по вечерам сидел и по алфавиту пробовал одну за другой. Их немного, штук 500-600 всего уникальных, так вот там действительно безумное количество шмапов, особенно вертикальных.
Я думал сделать еще пост, где подразобрать как раз клоны, о которых упомянул Shiru, да накидать материалов и упоминаний. Постараюсь собраться еще с силами и сделать, там есть чего рассказать любопытного.
Очень интересно, я не знал что у R-Type было столько сиквелов (хотя сам я никогда по-настоящему не проникся этой игрой — мне было слишком сложно). Отличная статья, спасибо!

Кроме того, думаю что ссылку на книжку Bob Pape нужно добавить в основной пост; да, конечно она на английском, но как книжка о реальной жизни разработчика для спектрума в 1990-е лучше её я ничего ещё не читал.
Ещё интересное явление — клоны R-Type.
  • avatar Shiru
  • 4
До R-Type на горизонтальные шмапы очень сильно повлияли Defender и Scramble (обе 1981), у них были несметные полчища клонов. Но это было на поколение раньше. Жанр оформился в Gradius (1985), а R-Type сделал примерно то же, что Galaga относительно Space Invaders или Arkanoid относительно Breakout — поднял планку на качественно новую высоту.

Ещё интересное явление — клоны R-Type. Их не так много, но хватает. Из классных, которые вспоминаются сходу — Pulstar и Blazing Star на Neo-Geo, они вполне на уровне Leo.

И надо отметить что платформа PC Engine помимо двух портов R-Type известна тем, что попала в самый пик популярности горизонтальных и вертикальных шмапов. Там днём с огнём не найти платформеров типа Mario, зато наверное каждая третья игра — шмап, и многие очень высокого качества.
Мне стало интересно, и я погуглил. Да, такое действительно было в оригинальном релизе, об этом пишет Bob Pape в своей книге о разработке R-Type на ZX. www.bizzley.com/
Кратко говоря, на кассету ставилась защита Speedlock, и кто-то из разработчиков перепутал уровни при сборке защищенной версии. Activision якобы даже обещала заменять битые копии.
Не читайте русскоязычной википедии до обеда. Сомневаюсь, что в официальном релизе была подобная проблема. А вот то, что пиратская версия ходила без последнего уровня (два раза подряд на пленке был записан предпоследний) это факт. Но нервные клетки исчезали раньше, рядовой игрок дальше 6 уровня вряд ли мог пройти.
на амиге геймплей упирался в джойстик, соответственно был труднопроходим, и почти сразу закинут в дальний угол.
«Первый кассетный релиз игры содержал ошибку — вместо восьмого уровня был дважды записан седьмой, из за чего игра становилась непроходимой.»
Даже не представляю каким числом можно измерить тонны нервных клеток, которые были убиты этим раздолбайством. Жесть.
В свое время был в полнейшем восторге увидев на SMD Bio-Hazard Battle ))