Cuando los ingenieros diseñan una arquitectura de conjunto de instrucciones, según qué procedimiento o protocolo, si corresponde, siguen al designar ciertos códigos binarios como instrucciones. Por ejemplo, si tengo un ISA que dice que 10110 es una instrucción de carga, ¿de dónde vino ese número binario? ¿Fue modelado a partir de una tabla de estados para una máquina de estados finitos que representa una operación de carga?
Editar: después de investigar más, creo que lo que estoy tratando de preguntar se refiere a cómo se asignan los códigos de operación para las diversas instrucciones de la CPU. ADD podría designarse con un código de operación de 10011; una instrucción de carga podría designarse como 10110. ¿Qué proceso de pensamiento entra para asignar estos códigos de operación binarios para el conjunto de instrucciones?
fuente
Respuestas:
En muchos casos, la elección es bastante arbitraria o se basa en "donde sea que se ajuste mejor" a medida que los ISA crecen con el tiempo. Sin embargo, el MOS 6502 es un maravilloso ejemplo de un chip donde el diseño de ISA fue fuertemente influenciado al tratar de exprimir lo más posible de los transistores limitados.
Echa un vistazo a este video que explica cómo se diseñó la ingeniería inversa del 6502 , especialmente a partir de las 34:20 en adelante.
El 6502 es un microprocesador de 8 bits introducido en 1975. Aunque tenía un 60% menos de puertas que el Z80, era dos veces más rápido, y aunque era más limitado (en términos de registros, etc.), lo compensaba con un Elegante conjunto de instrucciones.
Contiene solo 3510 transistores, que fueron extraídos a mano por un pequeño equipo de personas que se arrastra sobre unas grandes láminas de plástico que luego se redujeron ópticamente, formando las diversas capas del 6502.
Como puede ver a continuación, el 6502 pasa el código de operación de la instrucción y los datos de temporización a la ROM de decodificación, luego los pasa a un componente de "lógica de control aleatorio" cuyo propósito es probablemente anular la salida de la ROM en ciertas situaciones complejas.
A las 37:00 en el video puede ver una tabla de la ROM de decodificación que muestra qué condiciones deben cumplir las entradas para obtener un "1" para una salida de control dada. También puedes encontrarlo en esta página .
Puede ver que la mayoría de las cosas en esta tabla tienen X en varias posiciones. Tomemos por ejemplo
Esto significa que los primeros 3 bits del código de operación deben ser 011 y G debe ser 2; Nada más importa. Si es así, la salida llamada RORRORA se hará realidad. Todos los códigos de operación ROR comienzan con 011; pero hay otras instrucciones que comienzan con 011 también. Probablemente, estos deben ser filtrados por la unidad de "lógica de control aleatorio".
Básicamente, se eligieron los códigos de operación de modo que las instrucciones que debían hacer lo mismo que el otro tenían algo en común en su patrón de bits. Puede ver esto mirando una tabla de código de operación ; todas las instrucciones OR comienzan con 000, todas las instrucciones de Store comienzan con 010, todas las instrucciones que usan direccionamiento de página cero tienen el formato xxxx01xx. Por supuesto, algunas instrucciones no parecen "encajar", porque el objetivo no es tener un formato de código de operación completamente regular, sino más bien proporcionar un poderoso conjunto de instrucciones. Y es por eso que la "lógica de control aleatorio" era necesaria.
La página que mencioné anteriormente dice que algunas de las líneas de salida en la ROM aparecen dos veces: "Suponemos que esto se ha hecho porque no tenían forma de enrutar la salida de alguna línea donde querían, por lo que pusieron la misma línea en una línea diferente ubicación de nuevo ". Me imagino a los ingenieros dibujando a mano esas puertas una por una y de repente se dan cuenta de una falla en el diseño e intentan encontrar una manera de evitar reiniciar todo el proceso.
fuente
Depende de la antigüedad de la ISA.
En los primeros días del diseño manual, y aún más cuando las CPU se ensamblaron a partir de lógica discreta, el diseño lógico habría sido lo primero, y se habría minimizado ampliamente, y luego los patrones de bits ISA habrían sido los valores necesarios para hacer que ese mínimo trabajo de lógica
Por lo tanto, puede haber un patrón particular de señales de control que permita que algunos multiplexores conecten la salida de ALU a la entrada del archivo de registro GP, algunas señales de control más que indiquen a la ALU que sume, reste, AND, OR, etc., y algunas bits de dirección en el archivo de registro. Estos tres grupos de señales formarán campos dentro de la instrucción. Cada grupo se mantendrá unido, y su significado detallado surge del diseño de esa unidad (ALU, etc.), pero los grupos pueden estar en cualquier orden, hasta que diseñe el decodificador de instrucciones. (El x86 es lo suficientemente antiguo como para que pueda detectar algo de esto si mira en el lugar correcto; no era un diseño totalmente nuevo, sino que se inspiró en el antiguo 8080)
Los ISA posteriores pueden "limpiarse" y hacerse más regulares y fáciles de usar, con hardware para traducir entre ellos y las señales de control de nivel de hardware reales, a veces a través de "microcódigo". Estos se denominan "CISC" o "Codificación de conjunto de instrucciones complejas". El prefijo de instrucción x86 "Rep" es un ejemplo simple de esto: hace que la siguiente instrucción se repita varias veces, para evitar tener que escribir un bucle FOR.
Más tarde (en la década de 1980) llegó un movimiento hacia un estilo más simple de codificación directa (RISC - Codificación de conjunto de instrucciones reducido) que puede ver en los procesadores ARM. Esto fue impulsado por el pequeño tamaño de los ASIC en ese momento y el deseo de poner CPU de 32 bits en ellos, por lo tanto, no había capacidad disponible para decodificadores de conjuntos de instrucciones complejos, para reducir la CPU completa a aproximadamente 20,000 puertas. (También hubo un aumento temporal del rendimiento, porque la gente aún no había desarrollado técnicas para hacer que los decodificadores CISC fueran rápidos, eso ocurrió alrededor de 1995 con el Pentium Pro)
Y hoy en día no importa: las CPU leen varias instrucciones a la vez y dedican millones de transistores a decodificarlas, reordenarlas y ejecutar tantas como sea posible a la vez, para acelerar los programas que pueden haberse escrito para los más antiguos. estilo de ISA.
fuente
Si agrupa instrucciones similares, surgirán patrones. Esto es muy obvio en ARM, donde el manual ISA realmente muestra qué bit de una palabra de instrucción corresponde a función, elección de registro, etc. Pero también se puede inferir para X86 .
En última instancia, la parte de "función" de los códigos de operación entra en un decodificador binario a un disparo que realmente activa una función o secuencia particular de operaciones canalizadas. Por lo general, no están relacionados con el contenido de ninguna máquina de estado, a menos que estemos considerando instrucciones de longitud variable que requieren una máquina de estado para decodificar.
fuente
Alguien en algún momento se sentó y los definió.
Un buen ISA hará que el decodificador sea lo más simple posible.
Por ejemplo, con una instrucción ALU, puede permitir que algunos bits del código de operación se envíen directamente a las líneas de control de la ALU.
fuente
Por lo general, dividiría su ISA en grupos funcionales. Tiene sentido (ya sea para la optimización lógica o simplemente para ser ordenado) que los pares complementarios se diferencian por un solo cambio de bit (carga frente a almacenamiento), y que tiene alguna jerarquía de bits que afecta el árbol de decisión de decodificación.
Al final del día, una asignación arbitraria de bits para el bloque de funciones (en lugar de colocar los campos de 'datos' en la instrucción solo tendrá un pequeño impacto en la eficiencia general de su diseño, pero tiene muchas opciones sobre cómo 'optimizar' su codificación ISA dependiendo de lo que considere que es un parámetro importante.
fuente
La codificación de instrucciones es un compromiso feo entre.
Simplificando la decodificación, para esto desea un conjunto simple de campos, cada uno de los cuales puede decodificarse por separado y enrutarse a una parte separada del motor de ejecución.
Empaquetar tanta funcionalidad como sea posible en un tamaño limitado de palabra de instrucción. Esto lleva a cosas como formatos constantes especiales que pueden codificar una variedad de números comunes.
Compatibilidad hacia adelante y hacia atrás. Si asigna funcionalidad a cada código de operación posible, no tendrá espacio para expandir la arquitectura más adelante. Si está agregando a una arquitectura existente, debe insertar sus nuevas instrucciones en los códigos de operación de reserva.
fuente
El excelente (aunque algo anticuado) de Randy Hyde The Art of Assembly entra en el conjunto de instrucciones x86 con cierto detalle en el capítulo 3.3.4 La unidad de control y los conjuntos de instrucciones y siguientes.
Luego demuestra bastante pegadizo y, por fin, cómo los primeros enchufes representan la instrucción, los siguientes enchufes codifican el origen y el destino. Por supuesto, hoy ya nadie se "conecta", pero para los ISA realmente antiguos, los bits en el código de operación básicamente hacen el mismo trabajo que los enchufes anteriores.
Terminas con algo como esto:
fuente