System timing and wait state generation
FULCRUM MAGAZINE #3
31 de Marzo de 1996
Editorial
Existe cierta tendencia a creer que con un super-procesador se pone al límite la velocidad de la PC y con esto solucionar todos nuestros problemas, pero se pierde el concepto de que la PC no es tan solo un montón de patitas (micro) soldadas a una plaqueta. Es todo un sistema que está compuesto por diversas variantes y calcular la velocidad real es un tarea muy compleja , de nada sirven los Mhz del micro llegada esta hora, y como dijo mi buen filósofo chino, 'un sistema será tan rápido como el más lento de sus componentes'... si esto parece difícil de calcular, en realidad lo será aun más ya que no todos los 'componentes' del sistema se usan por igual. Llendo al grano de la cuestión, hay varios componentes que influyen en la velocidad final y uno de estos es el refresco de memorias; también como complemento existen estados de espera que inserta el micro para compensar la desigualdad de velocidad en el hard, estos temas son los que nos ocuparán en este número y de esta forma mostrar que tener un micro muy rápido no sirve de mucho si es acompañado de un hardware lento. Entonces, el sistema de tiempos de la PC full-full en este número.
Pero cambiando de tema, visto que la cosa va funcionando, ya contamos con un par de bbs más donde pueden sacar la revista, estos son
Raw Power............238-2144
Dionysios II.........253-2096
y para los fidonenses, pueden sacarla de 4:901/325 (o sea el nodo correspondiente a Raw Power)
También a partir de este número se incluye una sección de feedback que son preguntas que me van planteando y que son interesantes ponerlas en esta área para que sean de público conocimiento. Esta saldrá cada tanto, cuando tenga preguntas de ustedes y por que no cuando tengo tiempo para ir contestándolas!!!
Espero que les guste y la verdad que me pongo mucho para sacar día a día algo mejor, así que cualquier sugerencia y/o pregunta me la hacen llegar para que juntos podamos sacar una publicación competente que, en definitiva, nos beneficia a todos.
Suerte y nos vemos en cualquier momento!!
by
[Biggs]
Fundamentos teóricos: "System timing and wait state generation"
En las RAM dinámicas, la información es almacenada como carga, es decir, que el 1 se almacena como una pequeña carga en la juntura gate-source del transistor del tipo MOS. Dicho esto, cabe aclarar que estas memorias están compuestas por una matriz de transistores cada uno de los cuales puede ser direccionado por una fila y una columna de dicha matriz. Pero como dicho elemento posee pérdidas, la carga almacenada debe ser restaurada periódicamente para que dicho valor de tensión nunca supere el nivel umbral y siempre sea reconocido como 1. Esto es así ya que el capacitor ficticio que se forma en realidad en la juntura anteriormente mencionada, posee como cualquier otro pérdidas, en otras palabras no posee un Q infinito. Se llama Q al factor de mérito de los capacitores y se lo define como:
Q=PA/PD
Siendo PA la potencia almacenada por el capacitor y PD la potencia disipada.
Los refrescos de memoria se realizan mediante el uso del canal DMA-0 y este en realidad es un DMA encubierto ya que no lee los datos sino que el direccionarlos los refresca. Dicho ciclo ocurre cada 72 clocks del procesador y dura 5 clk. Por lo tanto ya de movida se piede el 7% del tiempo refrescando la memoria.
Incompatibilidades del Hardware
El tiempo que le lleva al microprocesador para llegar a una celda conteniendo información se llama tiempo de acceso. Las memorias se clasifican según este tiempo que se mide en nanosegundos clasificandoselas según este dato ( 70 Ns , 80 Ns, etc ).
La relación velocidad del procesador - velocidad de memoria es muy importante. Si el procesador es muy rápido y las memorias son lentas, se debe enlentecer el ciclo de acceso a cada celda y esperar uno o más ciclos del procesador. Esto torna notablemente más lento al sistema.
Lo ideal es que el equipo no tenga tiempos de espera (wait-state), es decir que tenga 0 WS para que el procesador funcione a toda su potencia.
Si, por ejemplo, su equipo es un 486 DX 50 Mhz probablemente tenga una performance similar al de un 486 DX 33 Mhz debido a los wait state.
Aunque no todos los equipos los usan, hay ciertos métodos para que no disminuyan su performance:
Memoria entrelazada
La memoria se accede en bancos donde se hallan alma cenadas todas las celdas, pero si a un equipo se le ponen 2 bancos de memoria, ciertos diseñadores utilizan el siguiente truco: Dividir la memoria en dos, donde las direcciones pares estén en un banco y las impares en el otro. Mientras se accede a la posición par, al mismo tiempo se refrescan las direcciones impares. Como generalmente el programa continúa en la próxima dirección el tiempo de acceso se minimiza. Como ejemplo de lo anteriormente dicho, citamos el de una 386 SX 25 Mhz que con un solo banco de memoria tiene una performance medida por el SYSINFO de 13.5 y con dos bancos de memoria esta sube a 19.5. Generalmente la norma es vender la memoria en los módulos más grandes posibles para que se pueda expandir al máximo en un futuro.
Memoria caché externa
Si por cada acceso a la memoria se traen las próximas direcciones y se guardan las últimas en una RAM estática, existen grandes posibilidades de que el programa ejecute o repita las direcciones que se encuentran en la RAM estática ( recordamos que la RAM estática es más veloz que la dinámica ) sin tener que ir a traerlas de la RAM dinámica. Cuanto más datos se ejecuten en la memoria caché (estática) sin tener que ir a la dinámica, más aumentará la velocidad del sistema.
Caché en el procesador
Más rápida que una cahé externa es la caché dentro del procesador. Estos a partir del 486 en adelante poseen una caché interna (el INTEL 486 posee una caché de 8KB). Los compiladores modernos realizan optimizaciones para aprovechar al máximo estas áreas con lo cual logran una mayor velocidad final.
La combinación de caché interna, con caché externa y con memoria entrelazada más el uso de programas que usen estos recursos, optimizan al máximo la performance de su equipo.
SHADOW RAM
También habíamos hablado que las memorias RAM estáticas eran mucho más rápidas que las RAM dinámicas y que estas a su vez más veloces que las ROM. Para que el sistema funcione más rápido, y si la BIOS lo permite, se puede colocar RAM en vez de ROM y copiarle su contenido. De esta forma las rutinas de la BIOS corren más rápido que si estuviesen en la ROM aumentando la performance del sistema. Esta RAM-ROM que el BIOS copia y protege es llamada SHADOW RAM.
Este factor debilita mucho la performance del sistema (wait-state), y por que ocurren??; Si tenes que hacer un intercambio de información entre dos "objetos" y si estos funcionan a una distinta velocidad, el más rápido debe enlenteserce para ponerse a la par del más lento y de esta forma realizar la operación. Dicho en un ejemplo, si yo hablara tan rápido que nadie me pudiera entender tengo dos opciones, o sigo hablando y nadie me entiende un carajo o me freno y hablo a una velocidad que los demás puedan entender. Dicho en otro ejemplo: si tengo un micro de 66Mhz que obiamente posee un pulso de clock cada 15.15 ns y este tiene que leer una posición de memoria, cuyo tiempo de acceso es de 70 ns, quiere decir que el micro se tiene que bajar a dicha velocidad para hacer el intercambio de información (baja agregando "relleno" que son precisamente los Wait-State).
Lo cierto es que tener un micro tan rápido, tan desparejo en velocidad con el resto del hardware hace que este no pueda desarrollar todo su potencial. Ustedes me dirán cuanto depende el micro de estos factores externos... mucho. Si tiene que ejecutar un programa debe leer el HD, (peor que con las memorias ya que el tiempo de acceso está en el orden de los mili-seg.) y luego de cargado en memoria irá buscando instrucción por instrucción y cargandolas en su IR (Registro de instrucciones) para poder ejecutarlas. Hay soluciones que implementan los fabricantes de micro's que tratan de ir zafando estos problemas pero mas que soluciones son parches que van haciendo (en un par de numeros me voy a dedicar un capitulo entero a explicar el funcionamiento interno del micro y veremos que se está implementando).
Dicho esto veamos cual es la lógica para la generación de los famosos WAIT-STATE.
Si recordamos, los ciclos del bus están normalmente compuestos por cuatro ciclos del reloj (T1..T4) pero en ciertas oportunidades se incluía un quinto ciclo llamado TW. Este es el primer ejemplo que podemos citar de Wait State y es insertado automaticamente por el micro. La señal READY del bus (I/O CHANNEL READY) es utilizada para insertar ciclos adicionales en caso de que la placa interfaz necesite de este tiempo para realizar su operación de I/O.
Pero la generación de WS en los ciclos de memoria no es generada por las placas de interfaz sino por un adaptador especialmente utilizado para esta función; El sistema está muestreando el estado de la señal READY con respecto al clock, si no se desea insertar un tiempo de retardo, dicha señal READY debe estar inactiva por lo menos 75 ns antes que se genere el flanco ascendente del pulso T2, si en cambio se desea generarlo, esta señal se debe activar 60 ns antes que dicho pulso de clock. READY debe ser desactivada antes del T3 para que un WS sea generado luego de este. Si se desea generar otro WS, READY debe ser activada antes del flanco del próximo clock para que un segundo WS sea generado.
Retomando el tema de la inserción de WS extras en los ciclos de I/O, estos son generados de manera similar a los de memorias, pero ahora la señal READY será controlada por la interfaz y debe activarse 75 ns antes del pulso T3 para que se genere un WS y caso contrario, debe permanecer inactiva 60 ns para que no se lo genere.
Pero en los ciclos de espera (WS) también pueden ser insertados en los ciclos DMA. Ahora la lógica es diferente ya que en los accesos DMA existe una operación de lectura y otra de escritura, si es una lectura de memoria y escritura de puertos o si es lectura de puerto-escritura de memoria, su modo operando es diferente. Esto es así porque el controlador DMA muestrea la señal READY buscando un flanco respecto del clock; En consecuencia, la PC inserta automaticamente WS en los canales DMA1, DMA2, DMA3. El canal DMA0 nunca sufre la inserción de WS. El controlador DMA utiliza el clock del procesador y el clock de los ciclos de bus, llamándolos "T" y "S" clocks. Cuando la señal AEN se activa, esta indica la presencia de un ciclo DMA. En ese momento, se inserta automaticamente un WS. La señal READY debe permanecer activada 135 ns antes del flanco del pulso SW1 para que se inserte un adicional WS o permanecer inactiva 115 ns antes del próximo ciclo de S clock. Existen tres condiciones diferentes para que un ciclo de espera sea insertado:
- Cuando un canal solicita un DMA
- Cuando el DMA es apuntado a un bloque de memoria específico.
- En el caso de que el DMA tiene que transferir desde un canal especifico al mismo tiempo que apunta a un bloque de memoria.
Esto es todo respecto de los WS en DMA, sin embargo pienso que la idea quedará mas clara cuando tratemos la generación de DMA en una placa de interfaz en un futuro.
Con esto damos por terminado el tema de Wait State y su influencia en la degradación del sistema, pero para cerrar el tema de este numero, vamos a analizar el sistema de tiempos de la PC, el cual es accesible a nosotros mediante el uso del 8253 que ya habíamos mencionado anteriormente. Este es un IC muy utilizado en la PC y de especial ayuda a la programación, cumpliendo además con funciones básicas que mantienen la correcta temporización del sistema; Entonces antes que nada veremos cual es el funcionamiento del TIMER 8253/8254 (son iguales, solo que por una cuestión comercial se los conoce de esta forma, pero genéricamente lo llamaremos 8254).
Antes que nada vamos a ver en que consiste el 8254, bueno, es un TIMER que posee 3 contadores de 16 bits, los cuales son alimentados por 3 señales de clk y poseen sus correspondientes salidas y además una pata de GATE que se utiliza para controlarlos. Está también un registro de control en el cual se programa el modo de trabajo de cada uno de los contadores (hay seis). Así que primero veamos estas características...
Por las patitas de clk soportan 2 Mhz como frec. máxima.
Hay una pata de habilitación (CS) que debe ser controlada por el decodificador de direcciones. Los 4 registros internos se discriminan mediante las señales A0-A1 de la siguiente forma:
A1 A0 Registro
--≈--≈---------------
0 |0 |Acceso al cont. 0
0 |1 |Idem cont. 1
1 |0 |Idem cont. 2
1 |1 |Reg. de control
El proceso de programación implica cargar la palabra de control adecuada, y luego cargar el valor del contador, primero la parte baja y luego la alta.
El reg. de control posee las siguientes posibilidades:
Bits 7-6: eligen el cont. que se desea programar.
Bits 5-4: selecciona la forma de carga
RL1 RL0 Carga
---≈---≈--------
0 | 0 |Se cargan los 2 bytes
0 | 1 |Se carga el B. menos sig.
1 | 0 |Se carga el B. más sig.
1 | 1 |Reservado
Bits 3,2 y 1: Determinan el modo de trabajo
M2 M1 M0 Modo
--≈--≈--≈---------
0 |0 |0 | 0
0 |0 |1 | 1
- |1 |0 | 2
- |1 |1 | 3
1 |0 |0 | 4
1 |0 |1 | 5
Bit 0: especifica si la cuenta se realizará en código binario o en BCD ( si es 0=bin, 1=BCD)
0
⁄---¬---¬---¬---¬---¬---¬---¬---ø
|SC1|SC0|RL1|RL0|M2 |M1 |M0 |BCD|
¿-¬-¡-¬-¡-¬-¡-¬-¡-¬-¡-¬-¡-¬-¡-¬-Ÿ
¿-¬-Ÿ ¿-¬-Ÿ ¿---≈---Ÿ ¿-Cont bin/bcd
| | ¿---------Modo de trabajo
| ¿-------------------Carga del cont.
¿---------------------------Selección de cont.
Resta por lo tanto hablar de los 6 modos de trabajo que posee el 8254:
- Modo 0: La pata OUT pasa a nivel alto cuando la cuenta llega a cero; cuando GATE está en bajo se detiene la cuenta.
- Modo 1: En este modo se espera el flanco ascendente de la señal GATE y una vez pasado esto, con el próximo pulso comienza a decrementar el cont. pasando la salida OUT de nivel alto a bajo. Una vez finalizada la cuenta OUT permanece en alto nuevamente. Con GATE se reinicializa el contador.
- Modo 2: En este modo la salida OUT está en alto y cuando llega el pulso de fin de cuenta, pasa a bajo, pero una vez transcurrido dicho pulso retorna a nivel alto, es decir que se obtiene pulsos por out con un período determinado. GATE Inhibe di cha salida.
- Modo 3: Con este se genera una onda cuadrada, es decir, que OUT estará la mitad del tiempo en alto y la mitad en bajo. Si el valor de cuenta es impar, el tiempo de alto posee un período más que el de bajo.
- Modo 4: La salido OUT pasa a nivel alto y una vez alcanzado el valor de cuenta pasa a un nivel bajo durante el impulso de clock. GATE detiene el conteo.
- Modo 5: Similar al modo 4 solo que no se inicia el conteo hasta que se recibe un flanco ascendente por GATE y cada vez que se lo reciba se reiniciará dicha cuenta.
NOTA: Salvo aclaraciones se considera que una vez llegada a cero la cuenta, se reinicializa automaticamente.
En la PC el 8254 está alimentado en su entrada de clock con una señal de frecuencia de 1193180Hz y este utiliza su contador 0 para generar la int 8h cada vez que llega al período programado, ejecutándose una rutina de control de timing del sistema. El segundo contador (Cont. 1) se encarga de realizar el refresco de memoria por el canal DMA0. El tercer y último contador está conectado al sistema de parlantes y genera un impulso de sonido cada vez que completa un período. Podemos calcular la frec. de trabajo como período=1193180/frec.
Por último, podemos citar que el registro de control está en 43h, mientras que los cont está, en 40h, 41h y 42h.
Pero el último contador, esta conectado al speaker a traves de un port del 8255, presente en el sistema de PC. Veamos pues el sistema de control del parlante en la PC.
Una vez programado el contador, que dará la frecuencia de la señal a sacar por speaker, se debe activarlo para que la señal sea generada. Este canal, es controlado por dos bits del puerto 61h que controla la señal del amplificador del speaker y, como ya dijimos proviene del 8255. Estos dos bits de los que hacemos referencia son los dos menos significativos de la word y el bms controla la tx de pulsos por el 8253 y el otro conmuta la señal de salida al speaker. Un mini ejemplo sería este:
---------------------------------------------------------------
count = 1193280 / 3000 ;calculo "t" para 3000hz
locount = count mod 256 ;calc. parte baja del valor
hicount = count / 256 ;calc. parte alta del valor
out &h43, &hb6 ;setea el 8253
out $h42, locount ;carga parte baja
out &h43, hicount ;carga parte alta
oldport = inp (&h61) ;lee el estado del port
newport = (oldport or &h03) ;calcula el valor del port
out &61, newport ;y lo manda (activa speaker)
...
...
...
oldport = inp (&h61) ;para apagarlo hace lo mismo
newport = (oldport and &h03) ;nada más que pone a 0 los 2
out &61, newport ;bms del word (address 61h)
---------------------------------------------------------------
es muy fácil no, ok ok pero cómo controlar el volumen en el parlante??? es decir el control de la amplitud de la señal de salida??... ok ok, a continuación ...
Por desgracia el speaker no posee un control de volumen, pero como el parlante posee una respuesta alineal, responde de distinta manera a una u otra frecuencia. Era de esperar que no se pueda controlar el volumen ya que lo que se usa como señal (digo lo que se aplica al parlante) es la salida del 8253, no ?? los pulsos de out se originan cuando se alcanza la cuenta y son siempre de una misma amplitud, no tengo la posibilidad de variarla ya que se maneja con niveles lógicos. Ya aclarado esto, y teniendo en cuenta que la respuesta no es lineal, les presento este ejemplo que les va a permitir calcular el mejor sonido que puede reproducir su speaker (levanta la curva de respuesta en frec. )...
--------------------------------------------
play "mf"
frec=37
while frec < 32000
print using "##.###";frec
sound frec,5
frec=frec*1.1
wend
--------------------------------------------
De esta forma, podemos dar por mencionado este, el sistema de tiempos de la PC, quedando cerrado el tema de esta edición; Espero haber sido claro y si no, contáctense a los números que dejé antes, nos vemos en el próximo número de FULCRUM MAGAZINE!!!
by
[Biggs]
FEEDBACK
********
Antenas & TV por cable
En respuesta a varios mensajes que consultaban la posibilidad de la captación de señales de cable mediante una antena orientada a el repartidor zonal, como por ejemplo el de Sergio Marcovecchio entre otros, va un breve repaso del tema:
Las antenas no son otra cosa que un circuito con constantes L-C distribuidas, es decir que se cuenta con una capacidad y una inductancia en un espacio relativamente grande, lo cual no quita que estas posean todas las características de los circuitos L-C. Es decir que dicho circuito se hace resonante cada vez que una onda impacta en ella con una longitud de ´ ldo (longitud de onda). Al hacerse resonante básicamente podemos decir que se hace un corto, que su impedancia cae al valor teóricamente mas bajo posible. Teniendo como base que las ondas se hacen repetitivas cada ´ ldo podemos decir que la antena resonará a ´, 1, 1´, 2, etc ldo. Dicha ldo se calcula como
ldo=c/f
siendo c la velocidad de la luz y f la frecuencia de la onda. Por ejemplo si tengo una antena de .5 m esta resonará a 600 Mhz, 1200, 1800, etc.
Esto significa que dicha onda inducirá una V en el dipolo. Pero si coloco un dipolo, este tendrá un lóbulo de radiación circular, es decir, captará señales que se encuentren a una cierta distancia a la redonda. Si a dicho dipolo le colocamos directores y reflectores, podemos modificar dicho lóbulo de radiación haciéndolo mas directivo, y ganando en distancia. Esto es una antena del tipo yaghi, que es muy usada, similar a las antenas de TV (las antenas de TV son un "engendro" de este tipo de antena, poseen en su forma clásica 5 dipolos que actúan a frec. distintas y un reflector).
No voy a entrar mucho en detalle, este tema lo tocaremos en un futuro en FULCRUM pero en los repartidores del cable, ya sea por mala aislación o por desadaptación de impedancias se generan pérdidas, parte de las cuales son literalmente irradiadas por los contactos y cables que actúan como antenas. Si colocamos una antena y la apuntamos hacia este lugar, probablemente captaremos señal de cable. Dicho esto se entiende que este tema es muy aleatorio, depende de la directibilidad de la antena, de la distancia con el objeto, y de las pérdidas que este irradie. Se puede probar y ver que pasa, pero si el tendido de la red es bueno, si se tiene una buena calidad esto NUNCA será posible, digo, si pueden ver la señal de esta forma deben agradecer el eficiente servicio de cablevisión.
Del tema hay mucho para decir, esto es solo una respuesta puntual a una pregunta, ya hablaremos de esto poniendo todos los puntos a las i en otra oportunidad.
[Biggs]
Coprocesador Matemático
Otro tema en cuestión en este tiempo se dio con Acetilcolina el cual esta interesado sobre la implementación de funciones trigonométricas utilizando el copro de una 486.
Antes que nada, quiero aclarar que al mismo tiempo que se desarrolla un micro, se hace también un copro para interactuar con dicho micro; En respuesta a la preg. , vamos a describir el funcionamiento del 8087 que es el copro para una XT, dejando aclarado que es igual para los copro posteriores, como el 80487 que sería el de la 486. Se lo hace así porque ambos IC interactuan profundamente entre sí y se debe diseñar un copro especialmente para cada micro. Veamos pues, el funcionamiento del 8087.
Los micros están diseñados para el procesamiento de instrucciones de uso general, la aritmética vinculada con este es muy simple, sin embargo hay aplicaciones en las que es conveniente que se puedan procesar fracciones y operaciones aritméticas avanzadas. Estas no son fáciles de implementar, para eso se diseñó el copro que ejecuta operaciones hasta 100 veces más rápido. Este también es llamado Extensión Numérico del Procesador -NPX-.
Al tratar el 8086, se vio la conexión de líneas QS0, QS2, RQ/GT con el 8087. La línea Busy del 8087 indica que la NEU (unidad de ejecución numérica) está ejecutando una instrucción numérica, la cual es conectada a la línea TEST del 8086. Al utilizar el copro, al hacer el prog. se antepone la instrucción WAIT antes de cada instrucción para el 8087. El 8086 encuentra el WAIT y queda en espera hasta que el copro ejecuta su instrucción, entonces la línea Busy del 8087 baja y el 8086 sigue procesando. La línea INT en una salida que indica que hubo un error en el procesamiento de la instrucción, sin embargo esta puede ser enmascarada. En el 8087 los errores se llaman excepciones y pueden ser de distinta naturaleza:
- Overflow: cuando el resultado es grande para la magnitud del formato usado.
- División por cero.
- Underflow: cuando el resultado es demasiado pequeño.
- Operando no normalizado.
- Resultado inexacto.
Un Registro de 16 bits (CONTROL WORD) contiene las máscaras para las excepciones, la interrupción, la precisión (24-64 bits) y el redondeo. Se notan en el gráfico (copro.jpg) 2 secciones bien diferenciadas: la unidad de control y la de ejecución numérica vinculadas por una cola de operandos y un bus interno.
La unidad de Ctrl monitorea las líneas de estado para determinar cuando está siendo tomada una instrucción, y mantiene una de instrucciones igual con el micro. Las instrucciones para el 8087 aparecen mezcladas con el juego de instrucciones del 8086, se diferencian porque las instrucciones del 8087 comienzan con la sig. cadena de bits en el 1ß byte: 11011 lo que corresponde al código de escape del 8086. Ante dicho código, el 8086 sigue con la próxima instrucción (si la previa no fue un WAIT) mientras que el 8087 comienza a ejecutarla.
EL NEU del 8087 contiene 8 registros de 80 bits denominados R1 al R8 sobre los que opera la ALU. Estos registros permiten almacenar números en formatos tales como:
- Enteros cortos de 32 bits
- Enteros largos de 64 bits
- BCD empaquetado de a 8 bits
- Reales cortos de 32 bits
- Reales largos de 64 bits
- Almacenamiento temporario de reales de 80 bits
Los formatos enteros se manejan como el complemento a 2 mientras que los reales en notación mantisa-exponente. EL formato de 80 bits p. ej. consta de 64 bits de mantisa, 15 de exponente y 1 de signo, con lo que pueden representarse hasta 10^4932. Estos registros forman un stack interno al 8087, y al igual que el stack de la memoria, crece hacia los registros de menor número. En la palabra de estado se refleja el estado del 8087. Una palabra de marca (TAG WORD) indica el contenido de cada registro de acuerdo con 4 códigos (Válido, cero, especial y vacío). También contiene registros para almacenar la dirección de la instrucción (INSTRUCTION POINTER) y la del operando (DATA POINTER).
El efecto de usar el 8087 es ampliar el conjunto de instrucciones del 8086 de 2 formas: por un lado a las operaciones que ya existían pero estaban limitadas a 16 bits tales como la comparación, la suma, resta, multiplicación y división que ahora pueden efectuarse hasta con 80 bits y por otro lado agrega las siguientes operaciones:
- Raíz cuadrada
- Valor absoluto
- Cambio de signo
- Tangente
- Arco Tangente
- Logaritmo en base 2
- Exponencial
Hecha ya la presentación del caso, veamos en detalle el funcionamiento interno del copro, y el uso en la programación de sus virtudes.
Para empezar a verle el uso que le podemos dar, hay que saber para que me sirven las palabras de control, tag y estado así que acá va una descripción de estas...
PALABRA DE CONTROL
Mediante esta, se seleccionan las diferentes opciones de proceso del 8087. Como se observa en el gráfico, el byte de menor orden configura las interrupciones y la máscara de excepciones. Los 5-0 de esta palabra contienen la máscara individual de cada uno de los 6 tipos de excepciones y el bit 7 contiene una general para todas. Respecto del byte más significativo, podemos decir que configura el modo de operación del 8087. Los bits de control de precisión (8 y 9) se pueden usar para habilitar la precisión de la operaciones, muy útil a la hora de compatibilizar con micros anteriores. Los valores que pueden adoptar los bits son los siguientes:
00 = 24 bits
01 = reservado
10 = 53 bits
11 = 64 bits
Los bits de control de redondeo (10 y 11) se disponen para el redondeo y corte del resultado en diferentes modos, según el estándar norteamericano IEEE. También se puede recortar el espacio del número por la proximidad al infinito pudiéndose conseguir el recorte con cualquier signo ÒÏ. Los valores que pueden adoptar son los siguientes:
00 = redondeo al valor más cercano
01 = redondeo hacia abajo (-Ï)
10 = redondeo hacia arriba (+Ï)
11 = recorte (cortando a través de 0)
0
⁄---¬---¬---¬---¬---¬---¬---¬---¬---¬---¬---¬---ø
|XXX|IC |RC |PC | M | X |PM |UM |OM |ZM |DM |IM |
¿¬¬¬¡-¬-¡¬¬-¡¬¬-¡-¬-¡-¬-¡-¬-¡-¬-¡-¬-¡-¬-¡-¬-¡-¬-Ÿ
||| | || || | | | | | | | |(1=ENMASC)
||| | || || | | | | | | | ¿OP. INVALIDA
||| | || || | | | | | | ¿----OP. FUERA NORMA
||| | || || | | | | | ¿--------DIV. X 0
||| | || || | | | | ¿------------SOBREPASAMIENTO
||| | || || | | | ¿----------------REVALSAMIENT. X0
||| | || || | | ¿--------------------PRECISI˛N
||| | || || | ¿------------------------RESERVADO
||| | || || ¿----------------------------MASC INTERRUP.
||| | || ¿¡--------------------------------CTROL PRECISI˛N
||| | ¿¡------------------------------------CTROL REDONDEO
||| ¿----------------------------------------CTROL Ï(1=S/SIG)
¿¡¡-------------------------------------------RESERVADO
PALABRA DE ETIQUETA (TAG WORD)
Esta palabra marca el contenido de cada uno de los registros. La función principal del TAG WORD es optimizar el funcionamiento del 8087. Se puede usar para interpretar el contenido de los registros del 8087. Está dividida en 8 partes de 2 bits, indicando el estado de los registros 0..7. Los valores que pueden adoptar son los siguientes:
00 = Válido
01 = Cero
10 = Especial
11 = Vacío
0
⁄------¬------¬------¬------¬------¬------¬------¬------ø
|TAG 7 |TAG 6 |TAG 5 |TAG 4 |TAG 3 |TAG 2 |TAG 1 |TAG 0 |
¿------¡------¡------¡------¡------¡------¡------¡------Ÿ
⁄------ø
2 bits
PALABRA DE ESTADO
La palabra de estado refleja el estado global del 8087, pudiendo ser almacenado en memoria los datos de dicho registro. Dicha palabra está compuesta por un registro de 16 bits, de los cuales el bit 15 indica que la NEU está ocupada, es decir que está ejecutando una instrucción. Los cuatro bits de código de condición numérica (C0-C3 son similares a los flags de la CPU, diversas instrucciones cambiarán sus estados para reflejar el resultado de las operaciones que ha realizado. Sus valores son los siguientes:
⁄------------¬--¬--¬--¬--¬-----------------------------------ø
|Intruc. tipo|C3|C2|C1|C0| Interpretación |
√------------≈--≈--≈--≈--≈-----------------------------------¥
|Comparación,|0 |0 |X |0 | ST>FUENTE O IGUAL A 0 |
|texto |0 |0 |X |1 | ST<FUENTE O IGUAL A 0 |
| |1 |0 |X |0 | ST=FUENTE O IGUAL A 0 |
| |1 |1 |X |1 | ST NO ES COMPARABLE |
√------------≈--≈--≈--≈--≈-----------------------------------¥
|Resto |Q1|0 |Q0|Q2|COMP. REDUC. CON 3 BITS BAJOS COCI.|
| |U |1 |U |U |REDUCCION INCOMPLETA |
√------------≈--≈--≈--≈--≈-----------------------------------¥
|Examinar |0 |0 |0 |0 |VALIDO, POS. SIN NORMALIZACION |
| |0 |0 |0 |1 |NO VALI.,POS., EXPONENTE=0 |
| |0 |0 |1 |0 |VALIDO NEGATIVO SIN NORMALIZACION |
| |0 |0 |1 |1 |NO VALI.,NEG., EXPONENTE=0 |
| |0 |1 |0 |0 |VALIDO, POSITIVO Y NORMALIZADO |
| |0 |1 |0 |1 |INFINITO POSITIVO |
| |0 |1 |1 |0 |VALIDO NEGATIVO NORMALIZADO |
| |0 |1 |1 |1 |INFINITO NEGATIVO |
| |1 |0 |0 |0 |CERO POSITIVO |
| |1 |0 |0 |1 |VACIO |
| |1 |0 |1 |0 |CERO NEGATIVO |
| |1 |0 |1 |1 |VACIO |
| |1 |1 |0 |0 |NO VALIDO, POS., EXPONENTE=0 |
| |1 |1 |0 |1 |VACIO |
| |1 |1 |1 |0 |NO VALIDO, POS., EXPONENTE=0 |
| |1 |1 |1 |1 |VACIO |
¿------------¡--¡--¡--¡--¡-----------------------------------Ÿ
NOTA:
- ST es el punto más alto del stack
- X es un valor que no afecta a la instrucción
- U es un valor indefinido después de la instrucción
- Qn es el bit n del cociente
Los bits 14-12 indican cual de los 8 registros se encuentra en el punto más alto de stack. El bit 7 es el de interrupción. Si este se encuentra en "1" si algún bit de excepción esta activo. Los bits 5-0 indican que la NEU ha encontrado una excepción mientras ejecutaba una instrucción.
0
⁄--¬--¬---¬--¬--¬--¬--¬--¬--¬--¬--¬--¬--¬--ø
|B |C3|TOP|C2|C1|C0|IR|X |PE|UE|OE|ZE|DE|IE|
¿¬-¡¬-¡¬¬¬¡¬-¡¬-¡¬-¡¬-¡¬-¡¬-¡¬-¡¬-¡¬-¡¬-¡¬-Ÿ
| | ||| | | | | | | | | | | |1=Hay excepción
| | ||| | | | | | | | | | | ¿Operación no valida
| | ||| | | | | | | | | | ¿---Operando fuera norma
| | ||| | | | | | | | | ¿------División x cero
| | ||| | | | | | | | ¿---------Sobrepasamiento
| | ||| | | | | | | ¿------------Rebasamiento x cero
| | ||| | | | | | ¿---------------Precisión
| | ||| | | | | ¿------------------Reservado
| | ||| | | | ¿---------------------Petición int
| ¿--≈≈≈-¡--¡--¡------------------------Códig. de condición
| ¿¡¡--------------------------------Puntero del stack
¿----------------------------------------Neu ocupada
Creo que con lo dicho alcanza como para tener una idea de lo que se trata de hacer con un coprocesador, así que si tienen dudas, solamente me las hacen llegar y listo, por mi parte solo resta dar el set de instrucciones que, por una cuestión de actualización, les mando el del 80287 que es prácticamente igual al del 8087 aqui tratado, es decir que todo lo dicho es absolutamente válido,
⁄-----------¬-----------¬------------------------------------ø
|Instrucción| Propósito | Características |
√-----------≈-----------≈------------------------------------¥
|FLD fuente |Carga real |Guarda (push) la fuente de datos |
| | |sobre la parte alta de los reg. del |
| | |stack, la pila ST(0) |
|FST destino|Almacenar |Copia ST(0) en el destino indicado |
| |real |que puede ser una pos. de memoria o |
| | |un registro |
|FSTP destn.|Almacenar y|Copia ST(0) en el destino indicado |
| |botar |y lo pasa automaticamente al stack. |
|FXCH destn.|Intercam. |Intercambia ST con el destn. indica-|
| |st |do |
|FILD fuente|Cargar |Empuja la fuente de datos hacia la |
| |entero |parte alta del stack,ST(0) |
|FIST dest |Almacenar |Almacena ST(0) en el destino indica-|
| |entero |do que debe ser un operando de mem. |
| | |entera |
|FISTP dest.|Almacenar |Idem anterior, solo que lo también |
| |entero |lo pasa automaticamente al stack |
|FBLD fuente|Cargar bcd |Carga un numero (BCD) hacia ST(0) en|
| | |el stack |
|FBSTP dest.|Almacena y |Almacena en ST(0) el número BCD en |
| |bota BCD |el destino y lo bota ST(0) del stack|
√-----------≈-----------≈------------------------------------¥
|FADD |Adición |Asume que ST(1) se adicona a ST(0) |
| |real |con el resultado en ST(0) o con |
| | |referencia explicita a ST(0) |
| | |adicionada a otro registro. |
|FADDP dest,|Adición |La fuente es ST(0) y el destino debe|
| fuente |real y bota|ser otro registro del stack. El |
| | |resultado se deja en este último. |
|FIADD mem- |Adición |El destino, ST(0) se adiciona a la |
| entera | entera |fuente, memoria entera y la suma |
| | |retorna a ST(0) |
√-----------≈-----------≈------------------------------------¥
|FSUB |Subst. real|Asume que el destino es ST(1) y |
| | |ST(0) se resta con él, con el resul.|
| | |en ST(1), con un operando. mem-real |
| | |restado de ST(0) y el resultado en |
| | |ST(0), o con ref. a ST(0) y a otro |
| | |registro explícito. |
|FSUBP dest,|Subst. real|La fuente ST(0) se resta del destino|
| fuente | y botado |, otro reg. del stack, y se almacena|
| | |en el destino. |
|FISUB fuet.|Subst. |EL operando de mem-entera se resta y|
| |entera |guarda en el destino ST(0) |
|FSUBR |Substr. |El destino se resta a la fuente y |
| |invertida |el resultado queda en el destino. La|
| |de reales |config. es igual a FSUB |
|FSUBRP |Substr. |Es igual a FSUBP salvo que el destn.|
| |inversa de |se resta a de la fuente ST(0) que |
| |reales y |aun sirve como aperand. fuente |
| |botados | |
|FISUBR |Subst. |Igual que FISUB, solo que se resta |
| fuente |inversa de |el destino de la fuente, siendo esta|
| |enteros |última un operan. de mem-entera. |
√-----------≈-----------≈------------------------------------¥
|FMUL |Multip. |Se la puede ejecutar sin operndos |
| |real |y asume que la fuente es ST(0) y el |
| | |destino es ST(1) |
|FMULP des, |Multip. |Idem anterior solo que bota el |
| fuente |real y |resultado al stack |
| |botar | |
|FIMUL fuent|Multip. |Multiplica el destino por la fuente |
| |entera |, el primero lo asume como ST(0) y |
| | |la fuente es un operando de memoria |
| | |entera. |
√-----------≈-----------≈------------------------------------¥
|FDIV |Dividir |Si se la opera sin operandos, asume |
| |reales |que la fuente es ST(0) y el destino |
| | |ST(1). Sino, la fuente es la especi-|
| | |ficada y el destino ST(0)-(Dst/Fnt) |
|FDIVP dest,|Dividir |Idem anterior solo que bota el |
|fuente |reales y |resultado al stack. |
| |botar | |
|FIDIV fuent|División |Esta instrucción asume que el desti-|
| |entera |no es ST(0) la fuente un operando |
| | |de memoria entera. |
|FDIVR |División |Idem que FDIV solo que el la fuente |
| |inversa |se divide por el destino. |
| |real | |
|FDIVRP des,|División |Igual que FDIVP solo que divide la |
|fuente |inversa |fuente entre el destino. |
| |real y bot.| |
|FIDIVR funt|División |Edentica a FIDIV salvo que la fuente|
| |inversa |se divide entre el destino. |
| |entera | |
√-----------≈-----------≈------------------------------------¥
|FSQRT |Raíz cuad. |Reemplaza el contenido de ST(0) por |
| | |su raíz cuadrada. |
|FSCALE |Escala |Interpreta el número de ST(1) como |
| | |entero, suma este valor al exp. del |
| | |número ST(0) lo que es igual a : |
| | | ST(0)*(2^ST(1)) |
|FPREM |Residuo |Toma el módulo de ST en relación |
| |parcial |con el número de ST(1), con igual |
| | |signo que ST(0). |
|FRNDINT |Redondear |Redondea ST(0) al entero. |
| |al entero | |
|FXTRACT |Extraer |Reduce el número en ST(0) a un sig. |
| |exp. y |y un exp. para aritmética de 80 bits|
| |significado| |
|FABS |Valor absl.|Genera el valor absoluto de ST(0) |
|FCHS |Cambio de |Invierte el signo de ST(0) |
| |signo | |
√-----------≈-----------≈------------------------------------¥
|FCOM |Comp. real |Compara el operando fuente que se |
| | |puede especif. (sino es ST(1)) con |
| | |el de destino ST(0) |
|FCOMP |Comp. real |Idem anterior solo que además lo |
| |y botar |pasa al stack. |
|FCOMPP |Comp. real |Idem anterior (very bobo no ???) |
| |y botar dos| |
| |veces | |
|FICOM fuet.|Compara |Comp. ST(0) con el operando fuente |
| |entero |que debe ser un opr. de mem. entera.|
|FICOMP fnt.|Compara |Idem anterior solo que ST(0) se re- |
| |entero y |gistra de inmediato despues de la |
| |bota |comparación. |
|FTST |Prueba |Prueba ST(0) en relación con +0.0 |
| | |El resultado el código: |
| | |C3,C1=0,0 => ST +;0,1 => ST - |
| | |1,0 => ST=0 ; 1,1 =>no se puede comp|
| | |ST |
√-----------≈-----------≈------------------------------------¥
|FPTAN |Tangente |Calcula Y/X =tang(z), siendo z=ST(0)|
| |parcial |retorna y en ST(1) y x en ST(0) |
|FPATAN |Arco tgn |Calcula z=ARC TGN(y/x) donde x=ST(0)|
| |parcial |y y=ST(1), Z se retorna en ST(0). |
|F2XM1 |2^x-1 |x se lo especifica en ST(0) y debe |
| | | estar en rango (0.0.5), y el resul-|
| | |tado se retorna por ST(0) |
|FYL2X |Y*log(x) |x=ST(0) y Y=ST(1). El resultado se |
| | |bota al stack y queda nuevamente en |
| | |ST(0) |
|FYL2XP1 |Y*log(X+1) |Las diferencias son taradas no?? lo |
| | |que si hay que aclarar es que x debe|
| | |estar en el rango de 0.1-˚2-2. |
√-----------≈-----------≈------------------------------------¥
|FLDZ |Carga cero |carga 0.0 en ST(0) |
|FLD1 |Carga +1.0 |carga +1.0 en ST(0) |
|FLDP1 |Carga pi |Carga pi en ST(0) |
|FLDL2T |Carga |Carga log10 en ST(0) |
| |log2(10) | |
|FLDL2E |Carga | |
| |log2(e) |Carga log e en ST(0) |
|FLDLG2 |Carga | |
| |log10(2) |Carga log10(2) en ST(0) |
|FLDLN2 |Carga | |
| |loge(2) |Carga log e (2) en ST(0) |
√-----------≈-----------≈------------------------------------¥
|FINIT, |Iniciar |Inicializa el 8287 |
|FNINIT |procesador.| |
|FDISI, |Inactivar |Inactiva al copro para recivir int. |
|FNDISI |Interrup. |de hard. |
|FENI,FNENI |Activa int.|Inversamente a FDISI, activa las int|
|FLDCW fuet.|Carga palb.|Carga la pal. de ctrl definida en el|
| |de ctrl. |operando fuente. |
|FSTCW, |Almacenar |Carga la palabra de ctrl en el |
|FNSTCW dest|pal. ctrl. |operando. |
|FCLEX, |Limpia |Borra todas las banderas de excep- |
|FNCLEX |exepciones.|ciones. |
|FSTENV, |Almacena |Escribe el estado basico y los indi-|
|FNSTENV dst|Ambiente. |cadores de excepciones en la posi- |
| | |cion definida por el usuario. |
|FLDENV fnt.|Carga |Carga el ambiente definido por el |
| |Ambiente |usuario. |
|FSAVE, |Salvar |Escribe el ambiente y el reg. stack |
|FNSAVE, dst|estado |en la localidad de mem. especif. por|
| | |el usuario. |
|FRSTOR, fnt|Reestablece|Vuelve a cargar al copro del operan.|
| |estado |fuente. |
|FINSCTP |Inc. el |very simple no??? |
| |stack | |
|FFREE, dst |Reg. libre |Cambia la etiqueta del destino a |
| | |vacio. |
|FDECSTP |Dec. stack |shhhhhhhhhhhhhhhhhh!!! |
|FNOP |no operat. |sin comentarios! |
|FWAIT |Espera |Hace que el micro espere a que el |
| | |copro termine de ejecutar la instr. |
| | |para poder seguir en lo suyo. |
¿-----------¡-----------¡------------------------------------Ÿ
a .. y de yapa un pequeño ejemplo ....
;Este ejemplo utiliza el copro para multiplicar 100000 por 10 y
;cambiar el resultado dentro y fuera del ST
.8087 ;copro
Stack segment para stack 'stack'
db 64 dup('stack')
stack ends
data segment para public 'data'
hm1 dd 100000
hm2 dd 10
hm3 dd ?
hm4 dd ?
data ends
cseg segment para public 'code'
coproc proc far
assume cd:cseg;DS:data;ss:stack
push ds ;todo este boludeo que
sub ax,ax ;se hace es porque se
push ax ;'toca' el stack al
mov ax,seg data ;usar el copro, por eso
mov ds,ax ;salvo todo.
finit ;inicializo el micro
fild hm2 ;carga 10 en stack (ST)
fimul hm1 ;mult. res y retorna st
fist hm3 ;carga res entero hm3
fst hm4 ;carga res real hm4
ret
coproc endp
cseg ends
end coproc
bye !!!!
Biggs