¿Por qué se interpretan los microprogramas en lugar de compilarse?

La idea detrás de la mayoría de los esquemas de microprogramación es implementar el conjunto de instrucciones “macro” que los compiladores de la computadora suelen generar (por ejemplo, código de máquina x86). Las macro instrucciones se almacenan en la computadora, para ejecutarse a pedido.

Puede compilar las macroinstrucciones y producir microinstrucciones. Surgen varios problemas:

  1. ¿Dónde vive el compilador?
  2. ¿Dónde se coloca el microcódigo compilado y qué lo colocó allí?
  3. ¿Necesita mantener las macro instrucciones si están compiladas?

Dependiendo de sus respuestas a estas preguntas, obtendrá diferentes arquitecturas de sistema.

La aplicación clásica de la microprogramación es interpretar las macro instrucciones de manera eficiente directamente en / en el chip de la CPU (las máquinas x86 son un buen ejemplo de esto) no tienen mucho espacio para un compilador “real”. Los compiladores normales que pueden hacer todo tipo de optimizaciones son enormes bestias y no caben en el chip de la CPU. Entonces, una respuesta es el compilador más trivial que puedas imaginar: la maquinaria de obtención de instrucciones recoge cada macroinstrucción y produce una secuencia corta y enlatada de microinstrucciones que implementan la macroinstrucción, cada vez que se obtiene una nueva instrucción. En este caso, el “compilador” vive en la lógica de obtención de instrucciones. “Produce” es un término divertido: en la microprogramación clásica, las microinstrucciones no se generan realmente; se almacenan en alguna ROM interna en el momento de la fabricación del chip y simplemente se buscan en tiempo de ejecución. Esto responde a la pregunta de dónde vive el código compilado y cómo llegó allí. Este enfoque es técnicamente sencillo y es la forma común de implementar un esquema de microprogramación.

Las CPU de Transmeta (ahora una empresa muerta) tenían un esquema más complicado para implementar el conjunto de instrucciones x86. (Mi memoria sobre esto es inestable ya que solo escuché sobre esto desde lejos; se aceptaron correcciones). Cuando se toca por primera vez una página VM de código, un compilador especial integrado en el chip traduciría toda la página de códigos en micro instrucciones, las almacenaría donde la micro CPU podría verlas y luego se ejecutarían. El compilador en chip no era muy grande, por lo que podría enviarse como parte de la CPU. No sé “dónde” se colocó el microcódigo compilado; debe haber habido alguna forma para que el compilador estacione el código compilado donde el micro motor pueda verlo / ejecutarlo. Pero esa área no puede haber sido grande porque los chips de CPU siempre tienen recursos limitados y deben haber actuado como un caché. Por lo tanto, las instrucciones de macro se conservan porque la ejecución de otro código de macro podría hacer que el caché se vacíe, y es posible que las instrucciones de macro originales deban volver a compilarse más adelante.

Si está dispuesto a lanzar un gran compilador al código, puede simplemente compilar todo el programa macro en un conjunto de instrucciones “micro” equivalente. Creo que hay emuladores x86 para compilar con otros conjuntos de instrucciones nativas (por ejemplo, viene a la mente el IA64 de Intel). En teoría, no necesita el código de macro después de hacer esto. En la práctica, debido a que uno no siempre puede estar seguro de si un byte en la aplicación de macro es código o datos, es probable que tenga que guardarlo y compilar en línea cuando un byte de datos se descubre de repente como un código de operación.

Entonces, sí, puedes compilar microcódigo. En una variedad de formas interesantes.

Sospecho que hace referencia a un libro tan antiguo porque hay copias digitales en varios lugares de Internet y, por lo tanto, no necesariamente tendrá que pagar por ellas.

Puede compilar en microcódigo, pero no es muy útil, ya que requiere que, como escritor del compilador, comprenda la microarquitectura del hardware, hasta el punto de que su código no sería portátil entre las CPU, que de lo contrario pueden presentar la misma macroarquitectura.

Y, de hecho, hemos estado construyendo compiladores de microcódigos durante muchas décadas. Aquí hay un artículo sobre uno de ellos de 1981, hace unos 36 años:

Sobre el diseño de un compilador de microcódigo para un lenguaje de alto nivel independiente de la máquina

Es solo que no venderías muchos de ellos a nadie.

Pero, de hecho, se usaron para computadoras VAX Architecture de Digital Equipment Corporation a fines de los años 70 y principios de los 80. Muchas de las instrucciones más complejas, como la instrucción CRC32, sobre las piezas de hardware más baratas, como la serie MicroVAX, se implementaron en microcódigo en lugar de implementarse en hardware físico, ya que estaban en hierro más grande, como el VAX 11/780 y los VAX 8600 y 8800 “Super Minis”.

Tenga en cuenta que el libro de Tanenbaum, Structured Computer Organization , se publicó por primera vez en 1976. Si bien ha tenido algunas modificaciones, está bastante anticuado en términos de información sobre cosas como el microcódigo.

La mayoría del hardware DSP ( Procesamiento de señal digital ) está, efectivamente, ejecutando microcódigo compilado, como lo es la mayoría del hardware SDR ( Radio definida por software ) en estos días.

El propósito de la unidad de traducción en la mayoría de los sistemas modernos es convertir a lenguaje ensamblador de nivel superior a microcódigo sobre la marcha, similar a cómo funciona un JIT. Esta fue, de hecho, la base del procesador Transmeta Crusoe.

Algunas máquinas de arquitectura x86, específicamente las más recientes, han vuelto a hacer microcódigo. Pero no es el microcódigo de tu abuelo.

Si desea ver ejemplos de microcódigo de cuando Tanenbaum escribió el libro, este es un sitio bastante bueno para ello:

Ejemplos de microcódigo

Allí, podrá ver varios ejemplos del microcódigo DEC PDP-11.

Obviamente, a menos que esté programando un DSP o SDR, es poco probable que toque el microcódigo directamente.

Otro artículo interesante es este de 2014, que realiza un análisis de seguridad del uso del microcódigo de Intel como vector de ataque:

Análisis de seguridad del microcódigo del procesador x86

Obviamente, los JIT y la arquitectura Crusoe, así como gran parte de la conversión de CISC a RISC y, en menor medida, la traducción Rosetta de Apple de PPC en Intel, que estuvo disponible durante algunos años por compatibilidad binaria, son todos posteriores 1976, cuando ese libro fue escrito inicialmente.

Porque no están implementados en hardware.

Un “microprograma” es un programa. Por lo general (no siempre) escrito en una rom integrada en la CPU. Un programa siempre es interpretado por el ciclo de instrucción que DEBE implementarse en el hardware. Un “microprograma” solo extiende la capacidad de la CPU base al definir / implementar instrucciones que no son parte de la CPU base.

Externo a la CPU, no puede distinguir la diferencia entre una instrucción de microprograma y una instrucción implementada en hardware.

De alguna manera, creo que esto es solo una visión confusa de las cosas y de la pregunta.

El microcódigo no está “interpretado”, es “ejecutado” por el hardware.

Ahora se podría decir que el macrocódigo es interpretado por el microcódigo en ejecución, o que el microcódigo representa un intérprete para el macrocódigo. (Si la máquina está microcodificada. De lo contrario, el código del objeto es “ejecutado”, no “interpretado” por el hardware).

Tanenbaum pregunta si uno podría comenzar con el código fuente y compilar directamente en microcódigo. Espero que la respuesta sea técnicamente sí, pero con muchas advertencias sobre el entorno de hardware y muchas razones prácticas por las que no tiene sentido hacerlo. Dejo la elaboración como un ejercicio para el lector, pero le daré dos pistas: memoria y ejecución condicional.