Mostrar feed RSS

pSMS WIP

Arquitectura del Z80 (Parte I)

Calificar esta entrada
Vamos a hablar un poco del "cerebro" de la Master System: el Z80. Si bien algunos términos quizá sean algo técnicos o sea de muy bajo nivel, he procurado dar algunas explicaciones que para quien controla del tema serán superfluas, pero pretenden ayudar un poco a quien todo esto le suene a chino pero tenga interés en aprender. Si algo no queda claro, please, avisadme en los comentarios para intentar explicarlo

El Zilog Z80 es un micro catalogado a veces como de 8 bits (todavía no entiendo en base a qué se hace ese tipo de catalogaciones, pero bueno), poseyendo un bus de direcciones de 16 bits y un bus de datos de 8 bits.

Veamos un esquema explicativo:


Como podemos ver, contamos con los siguientes registros accesibles:
  • B, C, D, E, H, L y B', C', D', H', L'. Estos registros son de 8 bits, pero pueden agruparse por pares en registros de 16 bits de la forma BC, DE, HL y B'C', D'E', H'L'. Tienen la particularidad de que solo son accesibles a la vez 6 de ellos, pues están divididos en 2 bancos intercambiables por medio de unas instrucciones.
  • A, F y A', F'. Como en el caso anterior se trata de registros de 8 bits de los que solo dos son accesibles al mismo tiempo por estar divididos en bancos. El registro A es el acumulador que, como podemos ver en el gráfico, siempre será unos de los operandos de la ALU (Unidad Aritmético Lógica). Por su parte, en el registro F se encuentran los flags de la máquina que guardan su estado.
  • PC. Contador de programa, apunta a la dirección de la siguiente instrucción a ejecutar, por lo tanto tiene que ser de 16 bits.
  • SP. Puntero de pila, apunta a la primera dirección libre de la pila de ejecución, por tanto es necesario que también sea de 16 bits.
  • IX e IY. Estos dos registros de 16 bits se usan como dirección base para instrucciones que hacen uso de vectores. Como podemos ver, existe una mini ALU que solo sirve para sumarle un dato de 8 bits a estos registros y volcar el resultado al bus de direcciones.
  • I. Este registro de 8 bits se usa para el tratamiento de interrupciones.
  • R. Este registro de 8 bits se usa como salida para refrescar memorias externas.


A su vez el registro F se divide en:
  • Bit 7: Flag S. Es el flag que indica el signo, es decir, una copia del bit más significativo de la última operación de la ALU.
  • Bit 6: Flag Z. Este flag indica si el resultado de la última operación es cero.
  • Bit 5: Flag 5. Este bit en algunos documentos dicen que tiene un valor aleatorio, pero en otros he leído que guarda una copia del bit 5 del resultado de la última operación.
  • Bit 4: Flag H. Guarda el acarreo del bit 3 al 4 de la operación (supongo que será útil para operaciones en BCD).
  • Bit 3: Flag 3. Este bit en algunos documentos dicen que tiene un valor aleatorio, pero en otros he leído que guarda una copia del bit 3 del resultado de la última operación.
  • Bit 2: Flag P/V. Dependiendo de la operación, en este bit se muestra si el resultado tiene paridad par (existe un número par de 1s en el registro) o bien hubo desbordamiento.
  • Bit 1: Flag N. Se activará si la última operación fue una resta.
  • Bit 0: Flag C. Es el bit de acarreo, se activará si el resultado de la operación no entra en el registro.


Por otro lado, hay otros registros temporales como W y Z que se utilizan para operaciones internas a las instrucciones y, de momento, no he visto que me vayan a ser de utilidad (programaré el resultado final sin hacer uso de ellos a menos que sea necesario).

Una vez visto esto, cabría plantearse cómo implementarlo dentro del emulador.

Mi idea es agruparlo todo, junto a otra información de estado (como los biestables IFF1 y IFF2 que controlan las interrupciones) que vaya viendo más adelante, dentro de una misma estructura de datos. Con esta agrupación sería muy sencillo cargar o salvar el estado interno, útil para transmitir esa información a otra aplicación (como la GUI de la que hablé en la entrada anterior) o bien para los famosos savestates de las partidas.

La siguiente pregunta que me hice fue: ¿qué sería más conveniente para almacenar los registros de 8 bits que pueden agruparse en pares? ¿un tipo de 8 o 16 bits?

La respuesta es sencilla: ambos. En C existe un tipo de estructuras llamadas union en las que puedes declarar varios tipos que comparten la memoria de dicha estructura, es decir, en una estructura union de 16 bits se podría acceder a los 16 bits de golpe (por ejemplo si fuera el par DE) o bien a los 8 bits superiores (D) o los 8 bits inferiores (E).

Creo que esto es suficiente por hoy, mañana, si tengo tiempo, más.

Enviar "Arquitectura del Z80 (Parte I)" a ¡Menéame! Enviar "Arquitectura del Z80 (Parte I)" a Technorati Enviar "Arquitectura del Z80 (Parte I)" a Digg Enviar "Arquitectura del Z80 (Parte I)" a del.icio.us Enviar "Arquitectura del Z80 (Parte I)" a Google Enviar "Arquitectura del Z80 (Parte I)" a Finclu Enviar "Arquitectura del Z80 (Parte I)" a Copada Enviar "Arquitectura del Z80 (Parte I)" a StumbleUpon Enviar "Arquitectura del Z80 (Parte I)" a Reddit Enviar "Arquitectura del Z80 (Parte I)" a FaceBook

Categorías

Comentarios

  1. Avatar de Molondro
    Sabía que existía una razón por la cual estudié arquitectura en lugar de Ingeniería Informática, pero hasta el día de hoy la desconocía.

    Gracias Puck y mucha suerte con el proyecto
  2. Avatar de JoJo_ReloadeD
    Fantastico. Informacion muy interesante.

    Realmente es un micro a caballo entre el 8008, el cual intentaba mejorar, y el 8086, el cual hizo el 8008 obsoleto
  3. Avatar de Puck2099
    JoJo, realmente es un micro casi totalmente equivalente al 8080, tienes hasta tablas de equivalencias de las instrucciones de uno a otro.
  4. Avatar de Jurk
    Los micros son catalogados segun la longitud de palabra que usan... es decir, lo que ocupa una direccion en la memoria Rom. Basicamente, el acumulador del microcontrolador nos dice cual es numero de bits del microcontrolador.


    Por ejemplo, el Z80, es de 8 bits porque la memoria es gestionada mediante 8 bits, aunque tenga algunos registros de 16 bit.
  5. Avatar de JoJo_ReloadeD
    Cierto, queria decir el 8080 y he dicho el 8008.

    De hecho puck, aprovechando que son virtualmente micros casi identicos, pense en hacer un emulador de algun sistema basado en el z80 aprovechando que los v30 tienen un modo de funcionamiento nativo 8080, y asi tener un emulador de uno de estos sistemas en un pc/xt
  6. Avatar de Locke
    Jurk, es al reves, no? Si te fijas el Z80 tiene ub bus de direcciones de 16 bits, las direcciones ocupan 16 bits.

    Lo que define los bits es la longitud del dato con el que trabaja, en este caso 8 bits, que es el tamaño de los registros y de los operandos de la ALU.
  7. Avatar de Jurk
    Locke, veo que no me he explicado demasiado bien...

    Una cosa es cuantas direcciones entran en la memoria rom, y no afecta para nada en la clasificacion, ya que la memoria se puede usar entera o solo a medias... sin embargo, en cada direccion entra una cantifdad determinada de informacion... que en el caso del z80 son 8 bits.

    Otra forma de saber la clasificacion es la siguiente: cada ciclo de reloj (no confundir con pulso del cristal, ya que pueden no se iguales) el microcontrolador es capaz de gestionar una cantidad determinada de informacion.

    Ejemplo con el 8051 (que no es el z80 pero nos sirve para comprender esto)


    CJNE A,#32h,salir
    OPCODE A,valor,etiqueta

    cjne es una instruccion de salto condicional. El micro compara el valor del acumulador con #32h y si no es el mismo salta a la direccion marcada por la etiqueta(salir)siempre y cuando se encuentre +- 128 direcciones en la memoria; es un salto relativo desde la posicion donde se encuentra CJNE. Si el valor concuerda se ejecuta la siguiente instruccion.

    Al meter esta instruccion en la memoria ocurre lo siguiente:
    CJNE(OPCODE): nos dice que instruccion hemos de ejecutar, ocupa
    8 bits, y que tenemos que usar el acumulador.
    A: ya esta integrado en CJNE. Ocupa 0 bits.
    #32h(dato): nos dice con que debemos comparar el acumulador. Ocupa
    8 bits.
    Salir(etiqueta): es una etiqueta a la que se accede de forma relativa. Es decir, el compilador convierte la etiqueta salir en un valor de
    8 bits con signo. Asi se puede saltar hasta 128 direcciones adelante y 128 direcciones atras.

    Por lo tanto 8+8+8, 24 bit ocupa esta instruccion. Y al micro le cuesta realizar esta instruccion 3 ciclos. Por lo tanto cada ciclo es capaz de manejar 24/3 = 8 bit el microcontrolador.

    Y por consiguiente el micro es de 8 bits.
  8. Avatar de nandove
    A ver que me estoy liando hasta yo no se si sera correcto, pero de toda la vida yo siempre he estudiado y creido que los bits de un procesador vienen dados por el numero fisico de "patitas" denominadas "D" (que son E/S, datos entrada salida o I/O Input Output en ingles) que posea, y luego estan las patitas "A" que son las de addressing.

    Y hay que saber que cualquier procesador seria capaz de "trabajar" datos e instrucciones del numero de bits que se quiera, un Z80 podria trabajar con instrucciones de 32bits con un programa de multiplexacion de demultiplexacion de datos y si tubiera memoria suficiente para acumular dichos datos... y perdiendo infinidad de golpes(o ciclos) de reloj para primero componer la palabra completa de 32bits y otro monton de ciclos de reloj para operar con el programa de multiplexacion de datos... pero eso no hace que sea de mas o menos bits.
  9. Avatar de Jurk
    Nandove:

    Cita Iniciado por Jurk
    Una cosa es cuantas direcciones entran en la memoria rom, y no afecta para nada en la clasificacion, ya que la memoria se puede usar entera o solo a medias... sin embargo, en cada direccion entra una cantidad determinada de informacion... que en el caso del z80 son 8 bits.
    Las patitas fisicas del bus de Entrada/Salida D(bus de datos)no determinan por narices el numero de bits de un micro, aunque por lo general suelen coincidir. Lo que determina el numero de bits del micro es la cantidad de lineas del bus de datos interno. Este bus de datos suele ser igual al acumulador. Este bus de datos suele ser utilizado para transferir las instrucciones al micro (solo un byte por ciclo en el Z80).

    Poder manejar datos de mas de 8 bits es normal. Lo de instrucciones de 32 bits es un absurdo... porque los OPCODES del micro son los que son y no puedes generar OPCODES virtuales... Solo se podria si entre el OPCODE virtual y el micro existiese un programa interprete en plan Java(es solo un ejemploooo) que traduciese ese programa con instrucciones de 32 bits a OPCODES.
    Actualizado 03/03/2008 a las 13:08 por Jurk
  10. Avatar de nandove
    A eso mismo me refiero, la catalogacion de un micro viene dada por los las "patitas fisicas", y no por las internas del bus de datos, y te equivocas en una cosa, las E/S de un micro a nivel logico no difieren en nada de las E/S de un puerto paralelo, salvo por el numero de bits. las E/S son un bus de datos con independencia de donde esten, ya sea en un bus ide, en una memoria, en un micro o en un puerto paralelo.

    Si asi fuera, un Z80 seria un micro de 16bits y no lo es, ¿acaso los nuevos dual core son procesadores 64 o 128 bits? al ser dos nucleos de 32bits se podria decir que son de 64bits, pero no es asi por que para empezar este es mal ejemplo, son 2 procesadores semi independientes y aunque a nivel "pastilla" es un solo encapsulado con 64 hilos de E/S la mitad pertenecen a un micro y la otra mitad a otro.

    un ejemplo menos lioso, el 68000 es un micro de 16bits, internamente puede manejar registros de 32 bits. pero no por ello es de 32bits.
  11. Avatar de Jurk
    Si te fijas en el diagrama, se ve claramente internal data bus 8 bit.

    Cita Iniciado por Nandove
    un ejemplo menos lioso, el 68000 es un micro de 16bits, internamente puede manejar registros de 32 bits. pero no por ello es de 32bits.
    Ya, pero de esos 32 bits solo puede gestionar 16 cada vez... (quiza excepto el registro program counter). Con el z80 pasa lo mismo: A y F generan un registro de 16 bit, pero en realidad son dos regstros de 8bits concatenados...
  12. Avatar de Locke
    Os podeis creer que esta noche he soñado con el proyecto de fin de carrera de Puck? xDDD
  13. Avatar de swapd0
    Es de 8 bits, porque la ALU opera con 8 bits de forma simultanea, si queremos sumar numeros mayores lo tenemos que hacer de 8 en 8 bits.

    El 68000 es de 16 bits porque la ALU es de 16 bits, pero hicieron los registros de 32bits pensando en el futuro. Si usas operaciones de 32 bits (add.l d0,d1) se haran en dos pasos, pero si tienes un 68020 o superior lo hara en una.
  14. Avatar de Jurk
    Cita Iniciado por swapd0
    Es de 8 bits, porque la ALU opera con 8 bits de forma simultanea, si queremos sumar numeros mayores lo tenemos que hacer de 8 en 8 bits.

    El 68000 es de 16 bits porque la ALU es de 16 bits, pero hicieron los registros de 32bits pensando en el futuro. Si usas operaciones de 32 bits (add.l d0,d1) se haran en dos pasos, pero si tienes un 68020 o superior lo hara en una.
    A eso iba, el acumulador (el registro del alu donde meter los datos) es de 8 bits...
  15. Avatar de Locke
    Eso ya lo dije yo 10 posts mas arriba, pero como todo el mundo me tiene hignorado... xD
  16. Avatar de Jurk
    que va, Locke, si yo lo que decia era lo mismo... lo que pasa es que no me habias entendido bien... y lo intente explicar mejor

    XD