Despues del 6502 le toca el turno al Z80, un procesador que formo parte de sistemas como:

  • Sinclair ZX81 y ZX Spectrum.
  • Familia MSX.
  • Familia Amstrad CPC.
  • Colecovision
  • Familia de 8 bits de Sega incluyendo la Game Gear.
  • Game Boy y Game Boy Color

El Z80 al ser un clon del 8080 es un precursos de la familia 80×86 y es un procesador con un set de instrucciones más complejo que el del 6502 por lo que su coste era más alto pero a cambio el hecho de tener instrucciones más complejas hacía que ciertas operaciones que en el 6502 necesitaban la concatenación de varias instrucciones en el Z80 se pudieran hacer con un menor número de instrucciones dado que para ciertas funciones el Z80 tenía instrucciones que el 6502 necesitaba la concatenación de varias más simples. Es decir, el Z80/8080 es el precursor de lo que acabarían siendo los chips CISC y si queréis ver la tabla de instrucciones y compararla con la del 6502 la podéis ver aquí.instructionset8085_8080

Pero el Z80 no es una version tal cual del 8080 sino que la gente de Zilog añadió una serie de instrucciones adicionales:

  • Direcciones de memoria de 1 bit.
  • Soporte para Loops de programa (le marca al procesador que a partir una dirección de memoria concreta ha de volver hacía una dirección de memoria anteror).
  • Mover bloques de datos de una sección de memoria a la otra.
  • Mover bloques de de datos desde y hacía periféricos de entrada y salida.
  • Instrucciones de búsqueda de bytes.

En el caso del Z80 y al contrario del 6502 existen registros tanto de 16 bits como de 8 bits y para ciertas operaciones se pueden concatenar registros de 8 bits, pero existen una serie de registros en común en todos los procesadores como son el contador de programa y el el status (llamado F en el caso del Z80), en el caso del contador de programa su funcionalidad es la misma pero en vez de estar compuesto por dos registros de 8 bits es uno solo de 16 bits por lo que el Z80 no ve la memoria como grupos de pilas como la familia del 6502 sino que toda la memoria del sistema es una «pila» que puede tener un tamaño de hasta 64KB y lo pongo entre comillas porque la forma de tratar la memoria por parte del procesador no es esa. Como apunte el Z80 es una CPU little-endian por lo que la primera dirección de memoria que carga en su contador de programa es la $0 al arrancar el procesador, por lo demás el contador de programa funciona como el del 6502 y como el de cualquier otro procesador.

Una de las particularidades del Z80 es su soporte para una unidad DMA externa, estas se encargan de mover datos de un lado al otro de la memoria sin necesidad de que intervenga la CPU en el proceso. Obviamente tiene que parar la CPU para realizar el movimiento de los datos a través del registro de interrupción pero la magia aquí es que lo hace en menos tiempo (menos ciclos de la CPU) que no la CPU misma. Aunque no todos los sistemas con un Z80 tienen dicha unidad por motivos de coste.

El registro “A” es el registro “Acumulador” y es necesario para las operaciones aritméticas con 8 bits, para algunas instrucciones se puede combinar con el registro «F» que es el de status pero no es recomenable pero no es el único registro conectado a la ALU sino que hay cuatro registros más que se suelen utilizar de manera combinada que son el B,C, D,E siendo la combinación BC y DE. Cada uno de estos registros es de 16 bits por lo que pueden almacenar instrucciones más complejas que en el registro A. Se pueden utilizar los pares de registros para comparar números entre si y activar el bit de paridad. F en cambio es el registro de status, utiliza unos 7 bits de sus 8 bits en total para marcar condiciones concretas de la CPU.

  1. El bit de signo: Nos marca si el número es negativo o positivo, 0 para si el número es positivo y 1 si el número es negativo. Esto es sumamente útil porque en realidad el Z80 no sabe restar y lo que hace es invertir los bits del número negativo y sumarlo.
  2. El bit de sobrecarga: Si el número obtenido es más grande que 2^8 (255) o de 2^16 (65535) este bit se activa indicando que la cifra supera la cantidad con la que el Z80A puede trabajar.
  3. Zero Flag: Nos marca si el resultado de la operación es 0.
  4. El bit de acarreo: “Tal por Cual hacen… Y me llevo 1”… marca si la operación lleva un acarreo consigo.
  5. El bit de ajuste: Nos marca si el acarreo viene de una operación con los 4 bits más bajos, se usa para simular operaciones con decimales en una arquitectura que no tiene unidad para trabajar con estos.
  6. El bit de del modo debug: Hace que el procesador haga las instrucciones de un programa una por una de un programa y después se pare, si los datos en los registros son correctos se sigue hacía adelante sino se aborta la operación. Es útil a la hora de compilar y comprobar que el código del programa este bien.
  7. El bit de paridad: Se activa si la comprobación de dos números es la misma, en el Z80A este y no el bit de cero es utilizado para comprobar si dos números son el mismo y activar un salto.

Mientras que F se combina con A para ciertas instrucciones aritméticas, hay ciertas instrucciones que toman los datos de F y de D.

El Stack Pointer, curiosamente el Z80 al igual que el 6502 tiene instrucciones PUSH y POP pero la diferencia es como funcionan estas. El Stack Pointer en este almacena la dirección de memoria actual y si hacemos una instrucción PUSH lo que hace es restar dos números a esa cifra y se la pasa al Contador de Programa como si fuese un salto, la instrucción POP añade dos números a esa cifra y después el número del Stack Pointer es copiado, hay que tener en cuenta que el Stack Pointer tiene un mecanismo que va incrementando de manera paralela al contador de programa.

Los registros indice son el IXL, IXH, IYL e IYH todos de 8 bits que se pueden combinar en IX e IY. Esto es algo más complejo de explicar pero hay instrucciones que se realizan utilizando la pareja BC solamente, en especial las instrucciones de petición de salto. Antes de cambiar el contenido del Contador de Programa lo que hace en esas instrucciones en concreto es mirar en el registro IX donde se almacena la dirección de memoria donde se va a producir el salto, es decir, la instrucción BC copia a través de direccionamiento directo el contenido de una dirección de memoria concreta en el IX donde se encuentra la dirección de memoria del salto. El registro IY se utiliza como referencia para ciertas instrucciones que utilizan de manera combinada los registros F y D pero también se utiliza para realizar saltos de memoria. Existe un registro adicional llamado WZ que no es accesible al programador y que almacena el último resultado, en este caso es como el registro Y del 6502 pero con la diferencia que no es accesible al código.

El registro HL se utiliza para las instrucciones de direccionamiento directo en el programa, el direccionamiento directo nos dice en que parte de la memoria esta un dato en concreto. Así pues si una instrucción es de ese tipo lo que hará será mirar el registro HL que será siempre de 16 bits.

Para terminar, si os habéis fijado falta el bit de interrupción en el de status, esto es debido a que los periféricos pueden parar a la CPU enviando datos a los pin de interrupción.

z80a_pinout

Dichos pin son el INT y el IRQ, el primero marca el tipo de interrupción a realizar, el segundo marca la petición de interrupción. Si el IRQ esta en 0 es igual cual sea el status de INT por el hecho que no va a haber petición de interrupción. El primer tipo simple y llanamente cuando se activa realiza un salto a la dirección de memoria 38 que se encuentra en la parte reservada al firmware o el SO dependiendo del sistema y procede desde allí. El segundo tipo utiliza el registro de interrupción como referencia, en este modo se para la ejecución del programa y se copia primero en el registro de instruccion los 8 primeros bits de la dirección de memoria y estos se copian en el contador de programa, luego se hace lo mismo con los otros 8 bits y cuando el periférico que ha terminado de captar la memoria para si ha terminado su rutina le devuelve el control al Z80 de nuevo que empezará a procesar esta vez desde la dirección de memoria que tendrá ya en su Contador de Programa.

Acceso a Memoria e Instrucción Wait

Hay que tener en cuenta que el tiempo de acceso a la memoria no es el tiempo que dura una instrucción ya que algunas en concreto pueden durar varios ciclos. El tiempo de acceso es 0 si el dato se encuentra en el registro acumulador, si esta en la RAM entonces se añaden tres ciclos de latencia.

La instrucción WAIT si se activa hace que la CPU tarde unos 6 ciclos adicionales de acceso a la memoria, esto es ideal para cuando esta tiene que compartir el acceso a la memoria con un períférico o un procesador de apoyo.

Con esto creo que es suficiente para definir como funciona el Z80.