Я что имею ввиду. Во-первых практически все операции трёхадресные.
A=B+C, например. И каждый аргумент может располагаться в своей банке.
Да, конечно, если банки по 16 килобайт каждая, то в четвёртой может
остаться и код... Но... см. ниже.
Во-вторых медленно. Переключаться банки будут постоянно, если работа
идёт с большими объёмами данных. И вариант типа LD BC, xxx: LD A, xxx:
OUT (C), A -- это ж 40 тактов где-то. Нужно что-то вроде OUT (#XX), A.
Разумеется, после разрешения этого порта каким-то битиком в каком-то
регистре... чтоб обычные программы не глючили. И, кстати, не факт, что
OUT. Можно подумать о недокументированной команде, например. Да что
угодно. Лишь бы аналогичное что-то можно было изобразить на мелкой
логике. LD B,B, LD C,C и т.п. даже без префикса по-моему вполне
вариант. Декодируется просто: 8-битный код в цикле М1. И скорость
космическая просто. Но скорей требования такие: во-первых возможность
работы из ПЗУ (не самомодифицирующийся код), во-вторых возможность
работать с переменным аргументом из регистра, в-третьих нужно порядка 16
переназначаемых окон по ~256 банок в каждом. Вопрос для обдумывания.
Теперь про код и память и данные. Какая может быть стратегия. Такая
как использовалась в своё время в старых макинтошах и вин-3.11. Т.е.
есть функция выделения памяти, например. Она выделяет. Где-то в банке,
но тебе отдаёт не ссылку, а ключ. Потом есть функция которая ключ
превращает в ссылку -- и в этот момент включается банка. Причём не факт,
что каждый раз в одном и том же месте или адресе (см. дальше). Потом
когда попользовался -- вызываешь функцию, которая отключает банку и
указатель тут перестаёт существовать. До следующего включения можно этот
кусок памяти как угодно по-памяти перемещать даже -- не важно. В
следующий раз по-ключу даст верный указатель, даже при перемещении
данных. Зачем так. Во-первых чтобы дать возможность переключать банки,
во-вторых чтобы дать возможность работать с более чем одним ключём
одновременно (тогда, при разных включениях, разные участки памяти в
разных страницах/адресах могут включаться, иначе ж никак). В-третьих
это собственно альтернатива ручному переключению, когда нужно не забыть,
со всеми последствиями.
Про код. С кодом та же история. Кода может быть больше, чем адресное
пространство. Это наверняка. И встанет вопрос как быть. Опять же есть
вариант руками включать банку и что-то там вызывать. Плохой вариант.
Можно поступить, как это делают в контроллерах профессионального уровня
-- proxy функцию для каждой C функции. Которая располагается во всегда
доступном сегменте кода и данных (вот уже аргумент, почему только 4
области памяти для банок -- мало). И эта прокси-функция включает нужную
банку и вызывает уже нужную функцию. При возврате возвращает всё на
место. Проблема с longjmp -- должен сохранять банку.
А из сказанного выше вытекают такие вещи, что ни выделяемая память, ни
код какой-либо функции не должны пересекать границы банки. Маленькие
банки невыгодны для больших объектов -- поэтому большие банки хороши.
Но совсем уж большие объекты можно вручную обрабатывать. А большинство
типовых объектов (данные и код функций) меньше 4-х килобайт -- практика
такова. А с другой стороны нужно где-то 3 банки под данные (а, на самом
деле, возможно и больше, потому, что не хочется оказаться в ситуации,
когда вызываеся подряд несколько функций и каждая получает банку с
адресом по-ключу, не высвобождает, и вызывает вложенную функцию...),
нужна банка под код текущей вызванной функции, нужна уже большая банка
под общий код и общие данные, включая стек. И с 16-килобайтовыми банками
становится сильно грустно. При наличии же 16шт 4-килобайтовых банок
гораздо веселее. Допустим, штук 8 уйдут под данные (до 8 разных объектов
с доступом через ключ, 3 вложенные функции например), 1-2 под текущую
функцию, 3 общий сегмент кода и 3-4 общий сегмент данных. Тогда как-то
можно вырваться за рамки 64кБайт и для кода и для данных более-менее
цивилизованным способом. Ну и, наконец, если окна для банок маленькие,
то можно выкрутиться и включать сразу по 2 шт. А наоборот уже никак.
Что я предлагаю. Сделать переключение 256шт (больше неудобно из-за
8-битности, да и мегабайта достаточно для ПО, остальное -- диск или
доступ вручную) банок по 4кБайта в окна соответствующего размера (16шт).
Переключение должно быть быстрое и не обязательно через OUT. Должно
работать из ПЗУ. Номер окна может быть фиксированный (выберется через
switch, если что, в функции переключения) в команде процессору, а номер
банки должен быть переменный из регистра. Каким методом это сделать не
знаю. OUT (#xx),A самый очевидный. Но не OUT (C) который аж три регистра
портит.
Зачем. Для программирования на языке C. С большими объёмами
(говно)кода, с большими объёмами данных, с динамически распределяемой
(стек и malloc() с учётом банок и доступа по-ключу) памятью.