Sistemas de Multiprocesamiento Práctica 2004 - 2005 REALIZACIÓN DEL MODELO EN SIMULINK DE UNA ARQUITECTURA DE PROCESAMIENTO EN PARALELO TIPO NUMA 1. Introducción y objetivos La práctica consiste en desarrollar en Simulink el modelo de comportamiento de una arquitectura de procesamiento paralelo de acceso no uniforme a memoria (NUMA), basada en el microprocesador uP1232a. El procesador uP1232 ha sido desarrollado en el Departamento de Tecnología Electrónica de la Universidad de Valladolid por D. Santiago de Pablo, dentro de su proyecto abierto “OpenUP”. En la dirección web http://www.dte.eis.uva.es/OpenProjects/OpenUP/indice.htm se encuentra la información sobre dicho proyecto abierto, así como el código en VHDL e información detallada sobre el uP1232. Con esta práctica se pretende que el alumno: - Conozca con detalle la arquitectura y el modo de funcionamiento de los microprocesadores sencillos. - Conozca la problemática hardware asociada al funcionamiento paralelo de varios microprocesadores. - Tenga una herramienta de simulación de un sistema paralelo en la cual pueda ejecutar código paralelo, ensayar algoritmos, modelos de consistencia de memoria compartida, etc. Además de la información contenida en este enunciado, los alumnos tienen a su disposición una serie de ficheros “plantilla” sobre los que trabajar. 2. Descripción de la arquitectura La arquitectura a desarrollar en Simulink consistirá en dos microprocesadores uP1232a conectados a cuatro bloques de memoria compartida de 1Kb cada uno, mediante un bus de datos, de direcciones y de control común. Aunque el uP1232a es capaz de direccionar 64Kb de memoria externa, sólo utilizaremos 4Kb de memoria compartida, para que la ejecución de la simulación sea rápida. Página 1 Sistemas de Multiprocesamiento Práctica 2004 - 2005 El esquema en Simulink de la arquitectura propuesta es el siguiente: Figura 1 : Esquema general del sistema Se recomienda trabajar sobre un único procesador y sobre un único bloque de memoria, hasta que el modelo del microprocesador esté completamente terminado. Figura 2 : Esquema de trabajo Página 2 Sistemas de Multiprocesamiento Práctica 2004 - 2005 En los ficheros “plantilla” que se proporcionan se encuentra el modelo del microprocesador bastante avanzado. El trabajo que tiene que realizar el alumno se limita a completar el modelo del microprocesador y de las memorias, obtener el circuito lógico del chipset y conectar los bloques. El sistema debe ser capaz de ejecutar código en paralelo correctamente. 3. El microprocesador uP1234a 3.1. Características generales El uP1232 es un procesador de propósito general de 8 bits con arquitectura CISC. En su diseño se ha buscado simultáneamente reducir el tamaño del procesador y aportar la flexibilidad suficiente para facilitar la programación y el desarrollo rápido de aplicaciones. La velocidad de ejecución, en cambio, no ha sido una prioridad, ni a nuestro juicio lo es en las aplicaciones hacia las que está orientado. Las principales características del procesador son las siguientes: - Contiene 32 registros internos de 8 bits, actuando todos ellos como acumuladores. Su código ejecutable, dependiendo de la versión, varía entre 4 KB y 64 KB. Accede a 64 KB de memoria externa (datos, código ejecutable y puertos de E/S) Dispone internamente de hasta 256 bytes de RAM, con un mínimo de 32 bytes. La pila también es interna, tiene sólo 32 palabras, pero es ampliable. Su código de instrucciones dispone de 33 operaciones distintas. Las instrucciones requieren sólo uno o dos bytes en su codificación. Su ALU de 8 bits puede realizar 16 operaciones distintas sobre cualquier registro. Responde a cuatro flags: cero, acarreo, signo y paridad. Atiende tres interrupciones priorizadas y enmascarables individualmente. En su momento, dispondrá de 15 puertos de entrada/salida. Ocupa unas 200 CLBs en una XC4000E (unas 5000 puertas equivalentes). Comparado con otros procesadores, el uP1232 dispone de 32 registros internos en vez de 8, y todos ellos actúan como acumuladores, y no sólo uno. 3.2. Código de instrucciones Las 33 instrucciones del uP1232 se organizan alrededor de 16 instrucciones básicas, las cuales se identifican a través de cuatro bits del código de instrucción: 0000 NOP 0001 RET 0010 LD Rn, nn 0011 POP Rn 0100 GOTO nnn 0101 CALL nnn 0110 JP flag, nn 0111 PUSH Rn 1000 LD/INC/DEC Rm, Sm 1001 SHR/RR Rm, Sm 1010 AND/OR Rm, Sm 1011 ADD/SUB Rm, Sm 1100 LDI Rn, (Sn + n) 1101 LDI (Sn + n), Rn 1110 LDI Rn, (Sn, Tn) 1111 LDI (Sn, Tn), Rn Las instrucciones de la primera columna (00xx) requieren dos ciclos de reloj para su ejecución, uno dedicado a leer el código de instrucción y otro a ejecutarlo. Las instrucciones de la cuarta columna, dedicadas al movimiento de datos entre los registros y/o la memoria externa, son más complejas y requieren cuatro ciclos o cinco ciclos. Las demás instrucciones emplean tres ciclos de reloj. Página 3 Sistemas de Multiprocesamiento Práctica 2004 - 2005 En la notación seguida, "Rm" y "Sm" indican cualquiera de los 32 registros internos (R0 a R31), mientras "Rn", "Sn" y "Tn" indican únicamente uno de los 16 primeros (R0 a R15). Como se puede observar, las operaciones aritméticas y lógicas se pueden efectuar directamente sobre cualquier registro interno, sin las limitaciones que introducen otros procesadores al emplear para esta tarea un único registro acumulador. Veamos a continuación las instrucciones de forma más detallada: Instrucción NOP BREAK MODEL {A..E} RET IRET IMASK {0..7} PUSH Rn POP Rn LD Rn, nn GOTO nnn CALL nnn JP flag, nn LD Rm, Sm INC Rm [,Sm] DEC Rm [,Sm] CLRCF SETCF SHR Rm [,Sm] DIV2 Rm [,Sm] RR Rm [,Sm] RRC Rm [,Sm] NOT Rm, Sm OR Rm, Sm AND Rm, Sm XOR Rm, Sm Codificación Descripción 0000 0000 No hace nada. Equivale a NOP, pero le indica una pausa al 0000 0001 simulador/emulador. Equivale a NOP, e indica el modelo de 0000 01nn procesador usado. 0001 0000 Vuelve de una subrutina. 0001 1000 Vuelve de una rutina de atención a interrupción. Indica qué interrupciones (IRQ3 a IRQ1) se 0000 1MMM pueden atender. 0111 RRRR Pone un dato (y los flags) en la pila. 0011 RRRR Recupera un dato (y los flags) de la pila. 0010 RRRR Asigna un dato de 8 bits (0 a 255) a un registro (de nnnn nnnn R0 a R15). 0100 nnnn Salta a otra posición de memoria, dentro del nnnn nnnn código ejecutable. 0101 nnnn Llama a una subrutina, de la que volverá con RET. nnnn nnnn 0110 FFFF Salto relativo (-128 a +127) si el flag señalado está nnnn nnnn activado. 100S SSSS Asigna a un registro el valor de otro (y desactiva 000R RRRR el acarreo). 100S SSSS Incrementa el valor de un registro (Rm = Rm + 1 ó 001R RRRR Rm = Sm + 1). 101S SSSS Decrementa el valor de un registro (Rm = Rm - 1 ó 000R RRRR Rm = Sm - 1). 1000 0000 Desactiva el flag de acarreo (CFF = 0). 0000 0000 1010 0000 Activa el flag de acarreo (CFF = 1). 0010 0000 100S SSSS Desplaza un bit hacia la derecha añadiendo 010R RRRR ceros (b7 = '0'). 100S SSSS Desplaza hacia la derecha manteniendo el bit de 011R RRRR signo (b7 = b7). 101S SSSS Rota un bit hacia la derecha sin contar con el 010R RRRR acarreo (b7 = b0). 101S SSSS Rota hacia la derecha conjuntamente con el 011R RRRR acarreo (b7 = CFF). 100S SSSS Operación NOT (Rm = NOT Sm). 100R RRRR 100S SSSS Operación OR (Rm = Rm OR Sm). 101R RRRR 101S SSSS Operación AND (Rm = Rm AND Sm). 100R RRRR 101S SSSS Operación XOR (Rm = Rm XOR Sm). 101R RRRR Página 4 Sistemas de Multiprocesamiento ADD Rm, Sm SUB Rm, Sm ADC Rm, Sm SBC Rm, Sm LDI Rn, (Sn + n) LDI (Sn + n), Rn LDI Rn, (Sn, Tn) LDI (Sn, Tn), Rn 100S SSSS 110R RRRR 100S SSSS 111R RRRR 101S SSSS 110R RRRR 101S SSSS 111R RRRR 1100 SSSS RRRR nnnn 1101 SSSS nnnn RRRR 1110 SSSS RRRR TTTT 1111 SSSS RRRR TTTT Práctica 2004 - 2005 Operación SUMA (Rm = Rm + Sm). Operación RESTA (Rm = Rm - Sm). Operación SUMA con acarreo (Rm = Rm + Sm + CFF). Operación RESTA con acarreo (Rm = Rm - Sm CFF). Accede a un registro apuntado por otro con offset (0 a 15). Escribe en un registro apuntándolo con otro y un offset. Lee de memoria externa, apuntando con dos registros. Escribe en memoria externa, apuntando con dos registros. Como se puede observar, en las instrucciones de salto absoluto se emplean sólo 12 bits para indicar la dirección de destino ("GOTO nnn" y "CALL nnn"). Esto es característico de este procesador y limitaría, en principio, el tamaño del código ejecutable a 4 KB: con 12 bits no se pueden direccionar más de 4.096 posiciones de memoria. Para evitar esta limitación se crean varias versiones del uP1232: el más pequeño, denominado uP1232a, salta a cualquier dirección entre 0x0000 y 0x0FFF (es decir, hasta 4 KB de código); el siguiente, el uP1232b, sólo salta a las posiciones pares entre 0x0000 y 0x1FFF, por lo que consigue extender el código ejecutable a 8 KB; el uP1232c salta a una de cada cuatro posiciones, ejecutando hasta 16 KB de programa; el uP1232d ejecuta hasta 32 KB mientras el mayor de todos, el uP1232e, ejecuta hasta 64 KB, pero sólo puede saltar a una de cada 16 posiciones de memoria. Por defecto, se considera que el procesador es el uP1232a, salvo que la orden "MODEL {A,B,C,D,E}" ejecutada como primera instrucción indique lo contrario. Las instrucciones de salto condicional ("JP flag, nn") se limitan, como es habitual, a saltos cercanos. Dedicando 8 bits para señalar la dirección de destino se pueden producir saltos en un entorno de -128 a +127 posiciones de memoria cercanas, lo cual es más que suficiente. Las comparaciones que puede efectuar, y que definen los cuatro bits restantes de la instrucción, son las siguientes: Z (0000) y NZ (0001) que evalúan el flag "Cero", el cual se activa si el resultado de una operación es nulo; C (0010) y NC (0011) que mira el flag de "Acarreo"; NEG (0100) y POS (0101) usan el bit de "Signo" mientras IMPAR u ODD (0110) y PAR o EVEN (0111) usan el bit de "Paridad". Las ocho combinaciones restantes (1xxx) serán usadas por los periféricos. Al igual que se observa una elevada flexibilidad en las operaciones aritméticas y lógicas, pues se puede emplear directamente cualquiera de los 32 registros internos de ocho bits, también se dispone de suficientes modos de direccionamiento: Inmediato Directo Indirecto a registro Indirecto a memoria LD Rn, nn ADD Rm, Sm LDI Rn, (Sn + n) LDI Rn, (Sn, Tn) Asigna cualquier número de 0 a 255 Opera directamente con hasta 32 registros Puede usar hasta 256 registros internos Hasta 64 KB de memoria externa Aunque sus operaciones se limiten a 8 bits (el Z80, por ejemplo, opera con 8 y con 16 bits), el uP1232 no tiene nada que envidiar a otros procesadores, pues al usar el Página 5 Sistemas de Multiprocesamiento Práctica 2004 - 2005 acarreo puede extender su aritmética a números con 16, 24, 32 ó más bits de precisión (por ejemplo, mientras "ADD R0,R10" podría sumar los 8 bits menos significativos, "ADC R1,R11" sumaría los ocho bits siguientes usando el acarreo producido en la suma anterior, y así sucesivamente). En las instrucciones PUSH y POP se ponen y retiran, respectivamente, datos de la pila. Como es habitual, estas operaciones se realizan con frecuencia en las subrutinas, para preservar el valor de los registros intermedios que se utilizan y restaurarlos antes de volver al programa principal. Una característica añadida en este procesador es que en todas las instrucciones PUSH y POP se guardan y recuperan, respectivamente, el valor de los "flags": esto es especialmente importante, y de hecho imprescindible, en las rutinas de atención a las interrupciones, pues pueden ser llamadas en cualquier punto de la ejecución de un programa. La última instrucción que comentaremos, posiblemente la más llamativa por no estar presente (o documentada) en la mayoría de los procesadores conocidos, es la orden "BREAK". Hace lo mismo que "NOP", es decir, no hace nada, pero en el caso de una puesta a punto puede ser empleada tanto por el simulador como el emulador. El primero puede utilizarla como punto de parada en la ejecución simulada del programa, para visualizar el estado interno del procesador; el emulador, en cambio, puede habilitar señales externas que permitan interrumpir temporalmente la ejecución. 3.3. Arquitectura interna El diseño interno del uP1232 se basa en una estructura de dos buses (implementados internamente con multiplexores), un Banco de Registros, una Pila y una ALU. También tiene diversos registros especiales El Banco de Registros, donde se almacenan los valores de R0 a R31, es una memoria SRAM de tamaño 32x8 con escritura síncrona (con el flanco de subida del reloj) y lectura asíncrona (inmediata a la presentación de cada dirección). Tanto Xilinx como Atmel y Lucent implementan de forma muy eficiente este tipo de memorias, lo cual es básico en el diseño del procesador. La Pila, de 32 posiciones ampliables, es otra memoria síncrona de tamaño 32x12 en el uP1232a y de tamaño 32x16 en el uP1232e. Su anchura de palabra permite tanto el almacenamiento de direcciones de retorno (para CALL y RET) como el almacenamiento de datos (para PUSH y POP). En este último caso, siempre quedan al menos 4 bits libres que permiten retener el estado de los FLAGs, lo cual es imprescindible para poder atender las interrupciones. La ALU (Unidad Aritmético-Lógica) es la encargada de efectuar las operaciones. Como se podrá apreciar, su diseño está directamente vinculado a las instrucciones de la tercera columna (10xx). De hecho, la ALU efectúa hasta 16 operaciones Página 6 Sistemas de Multiprocesamiento Práctica 2004 - 2005 distintas, que se corresponden biunívocamente con las 16 instrucciones de la citada tercera columna. Sus entradas son dos valores de 8 bits, una procedente del Banco de Registros y otra de un registros intermedio denominado Acumulador (ACC). También recibe otros cuatro bits de entrada, procedentes de los registros de instrucciones IR e IRb, los cuales le indican directamente qué operación debe realizar. La salida es puramente combinacional y depende de las entradas y de la operación solicitada. Los registros especiales son los siguientes: PC SP IR e IRb ACC AUX FLAGS El Contador de Programa se usa para leer las instrucciones de la memoria externa El Puntero de Pila controla la ubicación del último valor puesto en la Pila Los Registros de Instrucciones retienen el código de la instrucción que se ejecuta El Acumulador es un registro intermedio usado, principalmente, en la ALU Junto con el Acumulador se utiliza para efectuar accesos a la memoria externa Retienen valores característicos de los resultados de las operaciones (cero, acarreo, ...). 3.4. Programa interno de control El "Programa de Control" es el que se encarga de que el microprocesador realice las tareas necesarias para que sea operativo, y consiste en un circuito algorítmico que, usando la arquitectura anterior, lee e interpreta secuencialmente las instrucciones para ejecutarlas. Evoluciona por tanto a través de diversos estados, pero su funcionamiento es completamente cíclico: lee de la memoria externa el primer byte de una instrucción, dedicando para ello un ciclo de reloj; si la instrucción es de dos bytes, dedica otro ciclo a leer la segunda palabra; seguidamente lee los registros necesarios, opera con ellos y guarda el resultado, quedando preparado para ejecutar la siguiente instrucción. El programa de Página 7 Sistemas de Multiprocesamiento Práctica 2004 - 2005 control, al fin y al cabo, define casi por completo la arquitectura interna del microprocesador. Una versión simple del programa de control, el cual interpreta y ejecuta todas las instrucciones del uP1232a empleando la arquitectura interna descrita anteriormente, pero que no atiende de momento las interrupciones, podría ser el siguiente: Est '0' '1' '1' '1' '1' '1' '3' '1' '3' '1' '3' '1' '3' '1' '5' '1' IR(7..4) xxxx 0000 0001 0010 0011 0100 xx00 0101 xx01 0110 xx10 0111 xx11 10xx xxxx 1100 Sig. '1' '0' '0' '0' '0' '3' '0' '3' '0' '3' '0' '3' '0' '5' '0' '7' '7' xx00 '6' '6' '1' xx00 1101 '0' '7' '7' xx01 '6' '6' '1' xx01 1110 '0' '7' '7' xx10 '6' '6' '1' xx10 1111 '4' '7' '7' xx11 '6' '6' '4' '2' xx11 xxxx xxxx '4' '0' '0' Operaciones IR(7..0) = Memo[PC++]; NOP PC(11..0) = Pila[SP++]; Reg[IR(3..0)] = Memo[PC++]; FLAGs | Reg[IR(3..0)] = Pila[SP++]; IRb(7..0) = Memo[PC++]; PC(11..0) = IR(3..0) | IRb(7..0); IRb(7..0) = Memo[PC++]; SP--; Pila[SP] = PC; PC(11..0) = IR(3..0) | IRb(7..0); IRb(7..0) = Memo[PC++]; PC(11..0) = PC(11..0) + IRb(7..0) & Flag; SP--; ACC = Reg[IR(3..0)]; Pila[SP] = PFF | SFF | CFF | ZFF | ACC(7..0); IRb = Memo[PC++]; ACC = Reg[IR(4..0)]; Reg[IRb(4..0)] = Reg[IRb(4..0)] ALU ACC; IRb = Memo[PC++]; ACC = Reg[IR(3..0)]; ACC = Reg[IRb(3..0) + ACC]; IRb(7..0) = 0000 | IRb(7..4); Reg[IRb(7..0)] = ACC; IRb = Memo[PC++]; ACC = Reg[IR(3..0)]; ACC = Reg[IRb(3..0)]; IRb(7..0) = 0000 | IRb(7..4) + ACC; Reg[IRb(7..0)] = ACC; IRb = Memo[PC++]; AUX = Reg[IR(3..0)]; ACC = Reg[IRb(3..0)]; IRb(7..0) = 0000 | IRb(7..4); Reg[IRb(7..0)] = Memo[AUX, ACC]; IRb = Memo[PC++]; AUX = Reg[IR(3..0)]; ACC = Reg[IRb(3..0)]; IRb(7..0) = 0000 | IRb(7..4); Memo[AUX, ACC] = Reg[IRb(7..0)]; Estado de espera NOP - Será usado para las interrupciones. Comentario OPCODE FETCH NOP / BREAK / ... RET / IRET LD Rn, nn POP Rn GOTO nnn CALL nnn JP flag, nn PUSH Rn Rm = Rm ALU Sm LDI Rn, (Sn + n) LDI (Sn + n) = Rn LDI Rn, (Sn, Tn) LDI (Sn, Tn) = Rn El procesador siempre parte del estado '0', en donde lee el primer byte de la instrucción sobre el registro especial IR, de ocho bits, y pasa sin más al estado '1'. Allí se ejecutan las instrucciones sencillas (las del grupo 00xx), pero las demás son más complejas, por lo que requieren ciclos adicionales: unas siguen la secuencia '0'-'1''3', las que usan la ALU evolucionan según '0'-'1'-'5', mientras las últimas hacen '0'-'1''7'-'6' ó '0'-'1'-'7'-'6'-'4'. El estado '2' queda, de momento, reservado. Una instrucción como "GOTO nnn", que efectúa un salto en la secuencia del programa modificando el contador de programa PC con un nuevo valor de doce bits, se realiza en tres ciclos de reloj: Página 8 Sistemas de Multiprocesamiento Práctica 2004 - 2005 1) IR(7..0) = Memo[PC]; PC = PC + 1; // Lee el primer byte de la instrucción en '0'. 2) IR = IR; IRb(7..0) = Memo[PC]; PC = PC + 1; //Lee el segundo byte, manteniendo IR, en '1'. 3) PC(11..8) = IR(3..0); PC(7..0) = IRb(7..0); //Efectúa el salto modificando PC en '3'. Posiblemente esta instrucción se podría completar en tan sólo dos ciclos (IR = Memo[PC++] y PC(11..0) = IR(3..0) | Memo[PC]), pero entonces el diseño no tendría tanta simetría como la que se ha conseguido, y se complicaría notablemente la Unidad de Control. También se podría evitar el incremento del contador de programa del segundo ciclo, pero de nuevo se ha hecho así por simetría, en este caso con la instrucción CALL. Las operaciones aritméticas y lógicas también necesitan tres ciclos de reloj, y todas ellas son iguales para el programa de control: la distinción entre unas operaciones y otras se realiza directamente en la ALU, que usando bits específicos de los registros de instrucciones decide qué resultado mostrar. 1) IR(7..0) = Memo[PC++]; //Carga la instrucción sobre IR en '0'. 2) IR = IR; IRb(7..0) = Memo[PC++]; ACC = Reg[IR(4..0)]; //Carga un operando sobre ACC en '1'. 3) Reg[IRb(4..0)] = Reg[IRb(4..0)] ALU ACC; //Opera: Rm = Rm ALU Sm en '5'. En este punto se observa cómo el código de instrucciones, la arquitectura interna del procesador y el programa de control están estrechamente relacionados. De hecho, los tres han sido diseñados y optimizados de forma conjunta y partiendo de cero (from scratch), lo que nos ha permitido adaptarnos a la estructura interna de las FPGAs mejor que otros diseños basados en procesadores ya existentes. 4. Resumen del funcionamiento de la unidad de control Figura 3: Diagrama de Estados de la Unidad de Control Página 9 Sistemas de Multiprocesamiento Instrucción: NOP Descripción: No hace nada Diagrama de Estados: Práctica 2004 - 2005 Codificación: 0000 0000 Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: EST = 0 Instrucción: BREAK Descripción: Interrumpe la simulación Diagrama de Estados: Codificación: 0000 0001 Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: PARAR SIMULACIÓN Instrucción: RET Descripción: Vuelve de una subrutina Diagrama de Estados: Codificación: 0001 0000 Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: SP++ PC = PILA(SP) EST = 0 Página 10 Sistemas de Multiprocesamiento Práctica 2004 - 2005 Instrucción: LD Rn, nn Descripción: Asigna un dato de 8 bits (0 a 255) a un registro (R0 a R15) Diagrama de Estados: Codificación: 0010 RRRR nnnn nnnn Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: PC++ Reg[IR(3,...,0)] = CACHE(PC) EST = 0 Instrucción: POP Rn Descripción: Recupera un dato y los flags de la pila Diagrama de Estados: Codificación: 0011 RRRR Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: SP++ FLAGs | Reg[IR(3,...,0)] = PILA(SP) EST = 0 Página 11 Sistemas de Multiprocesamiento Práctica 2004 - 2005 Instrucción: GOTO nnn Descripción: Salta a otra posición de memoria, dentro del código ejecutable Diagrama de Estados: Codificación: 0100 nnnn nnnn nnnn Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: PC++ IRb = CACHE(PC) EST = 3 3: PC = IR(3,...,0) | IRb EST = 0 Instrucción: CALL nnn Descripción: Llama a una subrutina, de la que volverá con RET Diagrama de Estados: Codificación: 0101 nnnn nnnn nnnn Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: SP-PC++ IRb = CACHE(PC) EST = 3 3: PILA(SP) = PC PC = IR(3,...,0) | IRb EST = 0 Página 12 Sistemas de Multiprocesamiento Práctica 2004 - 2005 Instrucción: JP flag, nn Descripción: Salto relativo (-128 a +127) si el flag está activado Diagrama de Estados: Codificación: 0110 FFFF nnnn nnnn Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: PC++ IRb = CACHE(PC) EST = 3 3: PC = PC + IRb & Flag EST = 0 Instrucción: PUSH Rn Descripción: Pone un dato y los flags en la pila Diagrama de Estados: Codificación: 0111 RRRR Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: SP-ACC = Reg[(IR(3,...,0)] EST = 3 3: PILA = FLAGS | ACC EST = 0 Página 13 Sistemas de Multiprocesamiento Instrucción: Descripción: LD/INC/DEC Rm,Sm Codificación: 10xS SSSS 00xR RRRR LD: Asigna a un registro el valor de otro y desactiva el acarreo INC: Incrementa el valor de un registro DEC: Decrementa el valor de un registro SHR/DIV2/RR/RRC Rm,Sm Descripción: Práctica 2004 - 2005 Codificación: 10xS SSSS 01xR RRRR SHR: Desplaza un bit hacia la derecha añadiendo ceros DIV2: Desplaza hacia la derecha manteniendo el bit de signo RR: Rota un bit hacia la derecha sin contar con el acarreo RRC: Rota hacia la derecha conjuntamente con el acarreo NOT/OR/AND/XOR Rm,Sm Codificación: 10xS SSSS 10xR RRRR Descripción: NOT: Operación NOT (Rm = NOT Sm) OR: Operación OR (Rm = Rm OR Sm) AND: Operación AND (Rm = Rm AND Sm) XOR: Operación XOR (Rm = Rm XOR Sm) ADD/SUB/ADC/SBC Rm,Sm Descripción: Codificación: 10xS SSSS 11xR RRRR ADD: Operación suma (Rm = Rm + Sm) SUB: Operación resta (Rm = Rm - Sm) ADC: Operación suma con acarreo (Rm = Rm + Sm + CFF) SBC: Operación resta con acarreo (Rm = Rm - Sm - CFF) Diagrama de Estados: Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: PC++ IRb = CACHE(PC) ACC = Reg[IR(4,...,0)] EST = 5 5: Reg[IRb(4,...,0)] = Reg[IRb(4,...,0)] ALU ACC EST = 0 Página 14 Sistemas de Multiprocesamiento Instrucción: Descripción: LDI Rn, (Sn + n) Descripción: Codificación: 1100 SSSS RRRR nnnn Accede a un registro apuntado por otro con offset (0 a 15) Diagrama de Estados: Instrucción: Práctica 2004 - 2005 LDI (Sn + n),Rn Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: PC++ IRb = CACHE(PC) ACC = Reg[IR(3,...,0)] EST = 7 7: ACC = Reg[(IRb(3,...0)] + ACC IRb = 0000|IRb(7,...,4) EST = 6 6: Reg[IRb(7,...,0)] = ACC EST = 0 Codificación: 1101 SSSS nnnn RRRR Escribe en un registro apuntándolo con otro y un offset (0 a 15) Diagrama de Estados: Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: PC++ IRb = CACHE(PC) ACC = Reg[IR(3,...,0)] EST = 7 7: ACC = Reg[(IRb(3,...0)] IRb = 0000|IRb(7,...,4) + ACC EST = 6 6: Reg[IRb(7,...,0)] = ACC EST = 0 Página 15 Sistemas de Multiprocesamiento Instrucción: Descripción: LDI Rn, (Sn, Tn) Descripción: Codificación: 1110 SSSS RRRR TTTT Lee de memoria externa, apuntando con dos registros Diagrama de Estados: Instrucción: Práctica 2004 - 2005 LDI (Sn, Tn), Rn Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: PC++ IRb = CACHE(PC) AUX = Reg[IR(3,...,0)] EST = 7 7: ACC = Reg[(IRb(3,...0)] IRb = 0000|IRb(7,...,4) EST = 6 6: Reg[IRb(7,...,0)] = Memo (AUX, ACC) EST = 4 4: EST = 0 Codificación: 1111 SSSS RRRR TTTT Escribe en memoria externa, apuntando con dos registros Diagrama de Estados: Operaciones: 0: PC++ IR = CACHE(PC) EST = 1 1: PC++ IRb = CACHE(PC) AUX = Reg[IR(3,...,0)] EST = 7 7: ACC = Reg[(IRb(3,...0)] IRb = 0000|IRb(7,...,4) EST = 6 6: Memo (AUX, ACC) = Reg[IRb(7,...,0)] EST = 4 4: EST = 0 Página 16