Con las clases no me queda mucho tiempo libre, pero aun así he conseguido avanzar un poco más en la comprensión del Z80, hoy voy a comentar las interrupciones.

Una interrupción es una señal por la cual se interrumpe momentáneamente el secuenciamiento del programa, se trata dicha interrupción mediante una rutina y después se vuelve al punto donde se interrumpió.

Como ya comenté previamente, en el Z80 tenemos 2 biestables (dispositivos que almacenan un bit) llamados IFF1 y IFF2. El primero se usa para indicar si las interrupciones enmascarables (las que pueden ignorarse) están habilitadas (IFF1=1) o inhibidas (IFF1=0) y el segundo nos servirá como respaldo del primero (ya veremos luego como).

Hay dos tipos de interrupciones: enmascarables (INT) y no enmascarables (NMI). La diferencia entre ambas es que las primeras pueden ignorarse si así se configura el computador y las segundas hay que tratarlas obligatoriamente.

Para habilitar las INT se usa la instrucción EI que pone a 1 los biestables IFF1 y IFF2, mientras que para inhibirlas usaremos la instrucción DI que los pone a 0.

Interrupción no enmascarable
Cuando se produce una NMI el procesador sigue los siguientes pasos:

  1. Salvaguarda el contador de programa (PC) en la pila.
  2. Guarda el valor de IFF1 en IFF2 y pone IFF1=0 (inhibe INT).
  3. Pone PC=0×0066 (Salta a la dirección 0×0066).
Una vez realizado este proceso, en la dirección 0×0066 estará la rutina correspondiente a su tratamiento. Cabe fijarse que no se puede interrumpir a una NMI con una INT porque pone IFF1 a 0.

Finalmente, cuando acabe la rutina de tratamiento de interrupción se ejecutará la instrucción RETN que copia IFF2 en IFF1 (restaura el valor guardado) y restaura el PC desde la pila para continuar la ejecución donde se quedó.

Interrupción enmascarable
Hay tres modos diferentes en que puede estar el procesador para atender a las INT, estos modos llamados 0, 1 y 2 se establecen con las instrucciones IM0, IM1 y IM2.

Modo 0
Es similar al modo del 8080 de Intel, el dispositivo que genera la INT pondrá un código de operación de una instrucción en el bus de datos (normalmente una llamada a subrutina) y a partir de ahí seguirá la ejecución.

Modo 1
Es análogo al tratamiento de las NMI, solo que ahora se salta a la dirección 0×0038 y es enmascarable.

Modo 2
En este modo se usan interrupciones vectorizadas.

El dispositivo pone en el bus de datos un byte. Este byte se tratará como la parte baja de una dirección (recordemos de 16 bits) y el valor del registro I como la parte alta de dicha dirección. Finalmente, se pondrá a 0 el bit menos significativo para que sean direcciones pares.

En esta dirección se encontrará la dirección de la rutina de tratamiento de interrupción adecuada a la que se saltará (previa salvaguarda del PC en la pila).

Consideraciones
Eso sería básicamente todo el tema de las interrupciones, cabe destacar que las interrupciones no enmascarables pueden ser anidadas (una interrupción interrumpe a otra), pero no pueden saltar si se está tratando otra no enmascarable.

Finalmente, he buscado en varios libros y no he encontrado ninguna referencia a que se haga un guardado automático del registro de flags (F) en la pila a semejanza de como ocurre con el PC, así que supongo que será cuestión del programador el contemplar su salvaguarda.