Хорошее замечание, включу в пример, часть кода. LINK — это регистр в который попадает значение IP для следующей инструкции, в случае записи в IP. То есть в случае с переходом (записью адреса перехода в IP) следующая инструкция на которую будет указывать IP это туда куда надо вернутся.
#label -> IP ; Переход на адрес label и запись адреса следующей инструкции в LINK
R1 -> ALU.A
.........
label:
..............
LINK -> IP ; возврат на команду R1 -> ALU.A
Можно сохранять LINK как и в случае с LR в ARM либо в ОЗУ, либо один из регистров общего назначения. Допустим R4 это стек.
; push LINK
R4 -> ADDR
LINK -> DATA ; LINK 16 битный регистр, будет записан в память как слово за два такта
R4 -> ALU.A
#2 -> ALU.B
ADD -> R4 ; R4 += 2
; pop LINK
R4 -> ALU.A
#-2 -> ALU.B
ADD -> R4
ADD -> ADDR
DATA -> IP ; IP - 16-битный регистр, буден считан за два такта
А вот очень хороший пример! Действительно либо адрес в 16бит и борьба за каждый байт (ЕМНИП, Стив Возняк неплохо это показал запихнув в 256 байт монитор для Apple-I), либо 24/32 бита — «счастье всем и никто не уйдет обиженным». Адресного пространства так много что ARM выделяет в нем области для манипуляцией битами. :)
Недавно были опубликованы исходники порта Doom на SNES созданного Рэнди Линденом считай что своими силами (id software вообще поначалу не была в курсе): gbx.ru/?showtopic=142214
По ссылке я новость написал с минимумом технических подробностей (но история сама, имхо, интересная), но сам же заинтересовался чипом SuperFX — это 16-битный процессор с архитектурой созданной под влиянием идей RISC который на 16-битной SNES позволял эффективно рисовать 3Д-графику — у ЦП SNES с этим есть ряд проблем. А у SuperFX прям как у Z80Next есть команда PutPixel и много прочего. Чип SuperFX впаивался в картридж SNES аки маппер в денди и рулил и педалил 3Д-графоний на 16 битах.
Думаю краткий обзор архитектуры SuperFX станет предметом моей следующей статьи, но тут распишу идею из него которая мне тоже понравилась и которую в таком виде нигде не видел.
Опкоды там как правило однобайтовые, но бывают префиксы.
Шестнадцать 16-битных регистров во многих инструкциях кодируются в четырёх битах как в статье: 0xAB, где A — код инструкции, а B — код регистра. Из этого правила есть немало исключений, но рассмотрим, например, операцию сложения:
ADD R5
В своей первичной форме она рассматривает R0 как аккумулятор и к нему прибавляет указанный в инструкции регистр R5. Т.е. берёт аккумулятор и R5, складывает их и результат записывает обратно в аккумулятор. Окей.
Однако можно временно на одну эффективную инструкцию сменить что будет являться приёмником операции — это делает инструкция TO:
TO R4
ADD R5
Здесь эффект будет таков, что сумма R0 и R5 будет записана в R4. После выполнения ADD приёмник по умолчанию опять станет R0.
Точно так же есть однобайтовая инструкция FROM которая так же меняет временно какой регистр будет служить первым операндом:
FROM R3
TO R4
ADD R5
Выполнит следующее: сумма R5 и R3 запишется в R4, а аккумулятор окажется вообще не при делах.
Для еще больше краткости есть однобайтовая же инструкция WITH которая сразу выставляет и FROM и TO в один и тот же указанный регистр.
Но и это еще не всё — WITH взводит еще один внутренний флаг который модифицирует поведение инструкций FROM и TO если они встречаются после неё. В SuperFX отсутствует специализированная команда MOVE, зато если после WITH сразу же идёт FROM, то происходит копирование из регистра указанного во FROM в регистре запомненном в WITH. И наоборот — инструкция TO скопирует из регистра запомненного по FROM в регистр указанный в себе.
FROM Rn ; код 0xBn - выставляет Sreg в n
TO Rn ; код 0x1n - выставляет Dreg в n
WITH Rn ; код 0x2n - выставляет и Sreg и Dreg в n
Довольно забавная система команд — байтово-ориентированная, но постоянно на каких то полухаках, префиксах и сменах текущих целей и назначений.
Каждый боролся за плотность кода как мог. :)))
Ахаха:D А всё началось с того, что я попросил Виктора впилить ldix и lddx как хоть какую-то альтернативу блиттеру, который они наотрез отказались делать. А дальше всё вышло из под контроля:D
Ну если не лезть внутрь ЦП, то это вполне реальный путь и он всё-равно будет теоретически намного быстрее обычного калькулятора, т.к. процессору останется исполнить ну десяток-два максимум инструкций.
Но вообще надо аккуратно исследовать вопрос — ведь калькулятор это в сути своей пресолиднейший кусок ROM, т.к. он и есть все функции бейсика включая USR которая должна обратно вывалиться в режим процессора.
Калькулятор держит стек в памяти как и ряд переменных в basic vars позволяющих определить где он заканчивается. Поэтому технически можно было бы обставить это дело таким образом, что код в RST 28 каким то образом запускает процесс калькулятора как нечто внешнее (накормив тем же адресом откуда надо выполнять инструкции), а по сигналу завершения берёт HL из известных переменных бейсика как он в общем то и делает скорее всего в оригинале.
Это как? Внешний доступ к памяти возможен, к регистрам — нет, а ведь в них по итогу калькуляторных процедур определённые значения ожидаются. Разве что обманом заставить проц по im0 выполнить команды загрузок, да еще нужные значения им подсунуть. Твой аух сумеет разве такое?
Последнее достаточно забавно, и мне даже нравится. В качестве FPU можно использовать AYX-32 (про который тут когда-нибудь будет статья). Самое простое — код по $0028 поменять на вызовы команд по портам АУ.
Ну насколько я понимаю, пока DMA перебрасывает данные процессор остановлен и прерывание тоже не приходит. Отличие в том, что во время переброски данных z80DMA всегда DI на Z80, а это очень неудобно. И я думаю в zxnDMA более упощенный, хотя не проверял, но вряд ли там всё возможности реализованы.
Это если развернуть фразу — значит в оригинальном z80DMA — этого делать нельзя?? хмм… И в чем же проявляется отличие, если на пальцах?
Так то я все демки для z80DMA написанные пересмотрел, работают в большинстве своем наверное правильно, как авторы задумывали. Но большинство работает и в режиме zxnDMA, иногда даже лучше, чем в нативном.
В эмулях работает DMA пока плоховато :( Хотелось бы поточнее эмууляцию.
Не понял вопроса. Английские тексты по ссылке в посте можно прочитать.
Причём замечу, что основа моего перевода взята по ссылке, но некоторые обороты речи были настолько непонятными, что я нашёл еще один вариант перевода на второго сообщения и понял из него что имеется ввиду, но ссылку на него потерял в итоге. Хотя если искать наверняка вылезет опять в результатах поиска.
Любой кто наткнулся на это — извращенец! Есть еще одно сообщение в Pachi–Com на (компьютере) MSX… Если ты извращенец — купи и посмотри! Однако, там окинавский диалект!
К слову о Си и 8-битных процессорах буквально на днях наткнулся на KickC: forums.nesdev.com/viewtopic.php?f=2&t=20187
Пытаясь максимально сохранять синтаксис Си компилятор просто возвращается к корням — ЭВМ из 60-х и не поддерживает рекурсию. И всё начинает работать гладко и шелковисто и компилироваться в бодрый и довольно рабочий код.
Тот же CC65 на следующем коде (очень для него неудачном):
Весьма впечатляющий результат, хотя видно что еще есть куда работать.
Отсутствие локальных переменных еще позволяет производить оптимизацию с размещением переменных и параметров в одном и том же месте если они не пересекаются в callstack. Тоже недоступная для Си вещь даже если шлёпать static.
Вот такой эффект от того что как в древнем Fortran когда не было там еще ключевого слова RESURSIVE.
Можно сохранять LINK как и в случае с LR в ARM либо в ОЗУ, либо один из регистров общего назначения. Допустим R4 это стек.
И еще по вашему процессору я не понял как делается CALL — LR вроде есть, но непонятно что в него записывать.
P.S. Статья про SuperFX будет крайне интересна!
По ссылке я новость написал с минимумом технических подробностей (но история сама, имхо, интересная), но сам же заинтересовался чипом SuperFX — это 16-битный процессор с архитектурой созданной под влиянием идей RISC который на 16-битной SNES позволял эффективно рисовать 3Д-графику — у ЦП SNES с этим есть ряд проблем. А у SuperFX прям как у Z80Next есть команда PutPixel и много прочего. Чип SuperFX впаивался в картридж SNES аки маппер в денди и рулил и педалил 3Д-графоний на 16 битах.
Думаю краткий обзор архитектуры SuperFX станет предметом моей следующей статьи, но тут распишу идею из него которая мне тоже понравилась и которую в таком виде нигде не видел.
Опкоды там как правило однобайтовые, но бывают префиксы.
Шестнадцать 16-битных регистров во многих инструкциях кодируются в четырёх битах как в статье: 0xAB, где A — код инструкции, а B — код регистра. Из этого правила есть немало исключений, но рассмотрим, например, операцию сложения:
В своей первичной форме она рассматривает R0 как аккумулятор и к нему прибавляет указанный в инструкции регистр R5. Т.е. берёт аккумулятор и R5, складывает их и результат записывает обратно в аккумулятор. Окей.
Однако можно временно на одну эффективную инструкцию сменить что будет являться приёмником операции — это делает инструкция TO:
Здесь эффект будет таков, что сумма R0 и R5 будет записана в R4. После выполнения ADD приёмник по умолчанию опять станет R0.
Точно так же есть однобайтовая инструкция FROM которая так же меняет временно какой регистр будет служить первым операндом:
Выполнит следующее: сумма R5 и R3 запишется в R4, а аккумулятор окажется вообще не при делах.
Для еще больше краткости есть однобайтовая же инструкция WITH которая сразу выставляет и FROM и TO в один и тот же указанный регистр.
Но и это еще не всё — WITH взводит еще один внутренний флаг который модифицирует поведение инструкций FROM и TO если они встречаются после неё. В SuperFX отсутствует специализированная команда MOVE, зато если после WITH сразу же идёт FROM, то происходит копирование из регистра указанного во FROM в регистре запомненном в WITH. И наоборот — инструкция TO скопирует из регистра запомненного по FROM в регистр указанный в себе.
Довольно забавная система команд — байтово-ориентированная, но постоянно на каких то полухаках, префиксах и сменах текущих целей и назначений.
Каждый боролся за плотность кода как мог. :)))
Но вообще надо аккуратно исследовать вопрос — ведь калькулятор это в сути своей пресолиднейший кусок ROM, т.к. он и есть все функции бейсика включая USR которая должна обратно вывалиться в режим процессора.
+ еще загрузить корректный указатель стека кроме HL
как-то не особо «просто» уже всё это
Так то я все демки для z80DMA написанные пересмотрел, работают в большинстве своем наверное правильно, как авторы задумывали. Но большинство работает и в режиме zxnDMA, иногда даже лучше, чем в нативном.
В эмулях работает DMA пока плоховато :( Хотелось бы поточнее эмууляцию.
И надо сказать он во многих очень важных вещах отличается от данного, но проясняет некоторые моменты. Такое ощущение что переводчики с японского были сильны в разных предложениях.
Причём замечу, что основа моего перевода взята по ссылке, но некоторые обороты речи были настолько непонятными, что я нашёл еще один вариант перевода на второго сообщения и понял из него что имеется ввиду, но ссылку на него потерял в итоге. Хотя если искать наверняка вылезет опять в результатах поиска.
А это сообщение есть на английском? :)
Пытаясь максимально сохранять синтаксис Си компилятор просто возвращается к корням — ЭВМ из 60-х и не поддерживает рекурсию. И всё начинает работать гладко и шелковисто и компилироваться в бодрый и довольно рабочий код.
Тот же CC65 на следующем коде (очень для него неудачном):
Рожает следующий тихий ужас:
А вот KickC в своём асмосинтаксисе (как можно догадаться KickAssembler) делает почти оптимально:
Весьма впечатляющий результат, хотя видно что еще есть куда работать.
Отсутствие локальных переменных еще позволяет производить оптимизацию с размещением переменных и параметров в одном и том же месте если они не пересекаются в callstack. Тоже недоступная для Си вещь даже если шлёпать static.
Вот такой эффект от того что как в древнем Fortran когда не было там еще ключевого слова RESURSIVE.