К сожаленинию у меня сейчас нет времени и возможностей вести какие-либо реальные разработки (хотя чем больше это длится тем острее желание вернуться и заделать что-нибудь этакое...)
Так вот, очередная крейзи-идея на тему Flat Address Space на Z80. Это не детальная проработка, но возможно кто-то сможет на основе этого сделать нечто реальное.
Итак, давайте вспомним i8086 Его регистры тоже были 16-разрядными, и адресовать можно было тоже 64 кб. Чтобы преодолеть этот барьер, использовались сегментные регистры. Их было 4: CS (код), DS (данные), SS (стек), ES (дополнительный). Они содержали старшую часть адреса.
На Z80 сегментных регистров нет. А что если мы реализуем их, используя порты ввода/вывода, вместо переключения банков? Разумеется, нам понадобится самый настоящий северный мост - схема, связывающая между собой внешнюю шину, CPU и контроллер памяти.
Как известно, Z80 имеет линии M1 (указывает что по указанному адресу мы читаем команду), WR и RD (соответственно запись и чтение в память).
Итого, внешними средствами мы можем различить три состояния:
1. CPU читает код команды.
2. CPU производит чтение данных.
3. CPU производит запись данных.
Теперь вводим три порта ввода вывода:
1. CSP - Command segment port.
2. RSP - Read data segment port.
3. WSP - Write data segment port.
Получаем сегментированную модель, в которой, в отличие от страничной, мы не заперты в пределах страницы в 16 кб. Мы можем иметь целых 64 кб исполняемого кода, еще 64 кб данных, и при этом можем осуществлять межсегментный трансфер данных путем записи в WSP значения, отличного от RSP.
Проблема №1: стек. Очевидно, что при RSP != WSP пользоваться стеком затруднительно. Перед возвратом нужно установить RSP равное WSP на момент вызова, иначе приедем совсем не туда.
Проблема №2: прерывания. Собственно к предыдущей проблеме прибавляется то, откуда мы будем брать вектор. К сожалению тут я не знаток ибо тема прерываний Z80 в Спектрум-практике была освящена крайне слабо. Однако стоит вспомнить об устройстве под названием "Контроллер прерываний", которое упоминается в литературе по Z80 и служит для реализации IM 0. Следовательно - есть возможность извне определить, что CPU собирается перейти на обработчик прерывания.
А если так, то можно предусмотреть следующие меры:
1. Должна быть возможность в любой момент прочитать значение CSP, RSP и WSP.
2. Вводим ISP - Interrupt segment port. Северный мост, обнаружив, что CPU перешел в режим обработки прерывания, выставляет значение ISP в качестве указателя на сегмент команд вместо CSP и CPU начинает работать в этом сегменте. Все регистры уже сохранены в стеке сегмента RSP, можно работать. Выход из режима обработки прерываний (обратная замена ISP на CSP) может производиться по команде RETI/RETN, а может и просто какой-либо манипуляцией с одним из управляющих портов северного моста.
Проблема №3: межсегментные переходы. Это достаточно просто решить, добавив в северный мост еще чуточку интеллекта. Можно заставить его срабатывать скажем следующим образом:
Код:
007F54 LD A,#01
007F56 OUT(CSR),A ; Установили новый сегмент
007F57 JP 9E3B ; Следующая команда выполняется все еще в
; старом сегменте. Это не обязательно JP, это может
; быть JR, CALL, RST, хоть NOP.
019E3B ; Все, приехали в новый сегмент.
В качестве вкусности можно добавить автоматический инкремент значения CSR при считывании процессором КОП по адресу 0xFFFF. Таким образом можем позволить себе спокойно выполнять программы длиннее 64 кб.
Кто что скажет?