Pregunta

Quiero probar algunos cambios de arquitectura en una arquitectura ya existente (x86) utilizando simuladores. Sin embargo, para probarlos correctamente y ejecutar puntos de referencia, podría tener que hacer algunos cambios en el conjunto de instrucciones, ¿hay alguna manera de agregar estos cambios a GCC o cualquier otro compilador?

¿Fue útil?

Solución

Solución simple:

Un enfoque común es agregar ensamblaje en línea y codificar los bytes de instrucción directamente.

Por ejemplo:

int main()
{
    asm __volatile__ (".byte 0x90\n");
    return 0;
}

Compila (GCC -O3) en:

00000000004005a0 <main>:
  4005a0:       90                      nop
  4005a1:       31 c0                   xor    %eax,%eax
  4005a3:       c3                      retq

Así que simplemente reemplace 0x90 con sus bytes instancia. Por supuesto, no verá la instrucción real en un objdump regular, y el programa probablemente no se ejecutaría en su sistema (a menos que use una de las combinaciones NOP), pero el simulador debe reconocerlo si se implementa correctamente allí.

Tenga en cuenta que no puede esperar que el compilador le optimice bien cuando no conozca esta instrucción, y debe tener cuidado y trabajar con opciones de clobber/entrada/salida de ensamblaje en línea si cambia de estado (registros, memoria), a Asegurar la corrección. Use optimizaciones solo si es necesario.


Solución complicada

El enfoque alternativo es implementar esto en su compilador: se puede hacer en GCC, pero como se indica en los comentarios, LLVM es probablemente uno de los mejores para jugar, ya que está diseñado como una plataforma de desarrollo del compilador, pero aún es muy complicado Como LLVM es más adecuado para las etapas de optimización IR, y es algo menos amigable cuando se trata de modificar los backends específicos del objetivo.
Aún así, es factible, y debe hacerlo si también planea que su compilador decida cuándo emitir esta instrucción. Sin embargo, sugeriría comenzar desde la primera opción, para ver si su simulador incluso funciona con esta adición, y solo entonces pasar tiempo en el lado del compilador.

Si decide implementar esto en LLVM, su mejor opción es definirlo como una función intrínseca, hay relativamente más documentación sobre esto aquí, http://llvm.org/docs/extendingllvm.html

Otros consejos

Puede agregar nuevas instrucciones o cambiar existentes modificando el grupo de archivos en GCC llamado "Descripción de la máquina". Patrones de instrucciones en <target>.md archivo, algún código en <target>.c Archivo, predicados, restricciones, etc. Todos estos se encuentran en $GCCHOME/gcc/config/<target>/ carpeta. Todas estas cosas usando el código ASM de la generación de RTL. También puede cambiar los casos de instrucciones emitentes al cambiar algunos otros archivos de origen general de GCC, cambiar la generación de árboles SSA, generación RTL, pero todo esto es un poco complicado. Una explicación simple de lo que sucedió:

https://www.cse.iitb.ac.in/grc/slides/cgotut-gcc/topic5-mdintro.pdf

Es factible, y lo he hecho, pero es tedioso. Básicamente es el proceso de portamiento del compilador a una nueva plataforma, utilizando una plataforma existente como modelo. En algún lugar de GCC hay un archivo que define el conjunto de instrucciones, y pasa por varios procesos durante la compilación que generan más código y datos. Han pasado más de 20 años desde que lo hice, así que he olvidado todos los detalles, lo siento.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top