Files
Sprinter-SDCC/libc/irq/_irq_state.c
T
snark13 2c6f4e33c3 libc/irq: цепочка кадровых обработчиков + all-modes W1-remap
_irq_user → _irq_chain[4]+_irq_chain_n (W2-BSS); трамплин tr_frame
проходит слоты (один тяжёлый сейв на всю цепь, пустой слот пропуск).
API irq_chain_add (0/-1+ENOMEM) / irq_chain_remove(h); irq_install →
обёртка chain_add (EBUSY исчез), irq_remove() рвёт всю цепь; refcount
таблицы на первом/последнем слоте, мутации под IRQ_DISABLE. Лимит
4 кадровых + 1 CTC.

All-modes: трамплин copy-safe (только jr/djnz + литерал jp 0x0038),
_irq_table_ref копирует его в _irq_tramp_w2buf (W2) когда оригинал в W1
(small/huge), вектор → на копию; вокруг вызова хендлеров восстанавливает
базовую W1-страницу (_irq_app_w1_page = IN 0xA2). Хендлер может лежать
где угодно в плоском 0x4000-0xBFFF.

Проверено в MAME (tests/irqtest, 2 хендлера): tiny/big/huge — chain
h1=h2 → remove h2 → h1 жив/h2=0; huge = код в W1, remap работает.
Follow-up: CTC в small/huge = EINVAL (нужна W2-копия _irq_ctc_tramp);
small для мелких программ (BSS в W1) = irq_install EINVAL, safe.

Доки: im2_isr_design (цепочка), sprite-api §9е (делитель поверх цепи),
fast_ram §8. rpgprof: gfx_sprite_ysort в профиль (+230 Б baseline).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 10:23:39 +03:00

44 lines
3.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* _irq_state — данные IM2-модуля. Только данные.
*
* Кадровый обработчик теперь ЦЕПОЧКА (_irq_chain[]) вместо одного слота
* (см. docs/im2_isr_design.md «Цепочка кадровых обработчиков»).
*
* Всё, к чему трамплин обращается ВО ВРЕМЯ прерывания, обязано жить в
* W2 (0x8000-0xBFFF) — единственное окно, которое DSS не перемапливает
* (там стек). В tiny/big/huge вся BSS садится в W2 (code-loc W2 либо
* data-loc 0x8000); в small для маленьких программ BSS может оказаться
* в W1 — тогда _irq_table_ref вернёт EINVAL (safe). Полное снятие
* этого ограничения (резерв area _IM2) — отдельный follow-up.
*/
#include "_irq.h"
uint8_t _irq_vec_buf[_IRQ_VEC_BUF_SIZE];
/* Цепочка кадровых обработчиков. Пустой слот = NULL. Порядок вызова =
* порядок индексов; после remove/add взаимный порядок НЕ гарантирован
* (переиспользуется первая дыра) — хендлеры обязаны быть независимы. */
isr_t _irq_chain[IRQ_CHAIN_MAX];
uint8_t _irq_chain_n; /* число занятых слотов (быстрый выход) */
isr_t _irq_ctc_user; /* CTC-handler; NULL = нет */
isr_t _irq_cbl_hook; /* хук CBL-насоса; NULL = нет */
uint8_t _irq_old_i; /* I до захвата таблицы */
uint8_t _irq_refs; /* счётчик пользователей таблицы */
/* --- W1-remap для all-modes (см. трамплин) ---------------------------
* В small/huge базовый код приложения в W1 (статическая страница).
* Трамплин (в W2) вокруг вызова хендлеров восстанавливает эту страницу
* в W1, чтобы хендлер, лежащий где угодно в плоском 0x4000-0xBFFF, был
* адресуем; на выходе возвращает прочитанное на входе (что было —
* возможно DSS-страница, если прервали сисколл). */
uint8_t _irq_app_w1_page; /* базовая W1-страница (IN 0xA2 при install) */
uint8_t _irq_saved_w1; /* W1 на входе в прерывание (для restore) */
/* W2-копия трамплина: в small/huge сам _irq_tramp лежит в W1-коде и в
* момент прерывания может быть перемаплен — _irq_table_ref копирует его
* байты сюда (BSS=W2) и направляет вектор на копию. В tiny/big копия не
* нужна (трамплин уже в W2), буфер не используется. */
uint8_t _irq_tramp_w2buf[_IRQ_TRAMP_BUF_SIZE];