Par Wilfrid et Michel
Application : modifier une instruction du FR30
Le schéma présente une vue de l’ensemble des programmes et fichiers rentrant en
jeu pour l’élaboration du compilateur GCC pour une cible particulière. On remarque en vert les fichiers
à modifier, en jaune les fichiers et/ou programmes intermédiaires et finalement les exécutables en
orange.

Voici maintenant un exmple détaillé de modification de code afin d'intégrer une "nouvelle"
instruction à GCC. Dans cette partie, <arch> correspond au FR30 de Fujitsu. Pour cela, nous modifions directement
les fichiers opcodes. Cette procédure aurait pu se faire en modifiant le fichiers '<arch>.cpu'. Mais pour des raisons
de simplicité, nous modifierons directement les fichiers générés.
Nous allons présenter les 4 grands points nécessaires à la réalisation.
1. Modification des fichiers opcode.
2. Compilation des binutils.
3. Modification du fichier de description '<arch>.md' de GCC.
4. Compilation finale de GCC.
La modification des fichiers opcode se fait par l'intermédiaire de '<arch>-desc.c'. Nous
déciderons arbitrairement de modifier la multiplication.
Les fonctions sont représentées par le type CGEN_IBASE. Ces représentations sont structurées
sous formes de tableaux.
typedef struct { int num; const char *name; const char *mnemonic; int bitsize; CGEN_INSN_ATTR_TYPE attr; } CGEN_IBASE;
- num : numéro énumérée des instructions
- name : Nom de l'instruction
- mnemonic : mnemonique apparaissant dansle fichier '.s'
- bitsize : longueur totale de l'instruction en bit
- attr : type des attributs de la fonction
Voici la fonction originale (celle du FR30 ligne 766)
/* mul $Rj,$Ri originale */ { FR30_INSN_MUL, "mul", "mul", 16, { 0|A(NOT_IN_DELAY_SLOT), { (1<<MACH_BASE) } } },
Nous pouvons constater que la fonction est encapsulée par des accolades et des virgules car CGEN a créé un
tableau de fonctions.
Voici maintenant la fonction modifiée.
/* mul $Rj,$Ri modifiée*/ { FR30_INSN_MUL, "ISIMA", "ISIMA", 16, { 0|A(NOT_IN_DELAY_SLOT), { (1<<MACH_BASE) } } },
Ainsi, nous avons uniquement changé le mnémonique
de la multiplication. Nous avons donné le même nom
pour faciliter le travail et éviter les confusions entre nom
et mnémonique. Le numéro de la fonction reste
identique à savoir la valeur énumérée FR30_INSN_MUL.
La deuxième étape consiste à compiler
les sources des binutils. Ci après nous indiquons les
commandes à exécuter. Attention, il faut
respecter la configuration des dossiers. Le temps de compilation peut
être de 10 min à 1 heure en fonction de la
puissance de l'ordinateur.
root@xdoofy:/usr/binutilsFR30# ./binutils-2.16.1/configure --target=fr30-fujitsu-elf --prefix=/usr/gcctemp root@xdoofy:/usr/binutilsFR30# make root@xdoofy:/usr/binutilsFR30# make install
Pendant que l'ordinateur compile les binutils, nous pouvons modifier
les fichiers de description de GCC à savoir 'gcc/config/<arch>/<arch>.md'.
Nous rappelons que les informations contenues dans ces fichiers sont au
format Lisp. Après avoir identifier le vecteur d'expressions
correspondant à la multiplication.
Voici la fonction originale (celle du FR30 ligne 788)
;; Signed multiplication producing 32 bit result from 32 bit inputs (define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "register_operand" "r"))) (clobber (reg:CC 16))] "" "mul %2, %1\\n\\tmov\\tmdl, %0" [(set_attr "length" "4")] )
Maintenant, modifions le mnémonique mul par ISIMA.
;; Signed multiplication producing 32 bit result from 32 bit inputs (define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "register_operand" "r"))) (clobber (reg:CC 16))] "" "ISIMA %2, %1\\n\\tmov\\tmdl, %0" [(set_attr "length" "4")] )
Après cette modification, et une fois la compilation
précédente achevée, nous pouvons
compiler GCC à proprement dit. Pour cela, nous
exécutons les commandes suivantes :
root@xdoofy:/usr/gccFR30# ./gcc-3.4.5/configure --prefix=/usr/gcctemp --enable-languages="c" --target=fr30-fujitsu-elf
Une fois la configuration faite, il faut penser à modifier le PATH en incluant le chemin d'accès du dossier qui
contient les exécutables créés lors de la compilation des binutils.
root@xdoofy:/usr/gccFR30# export PATH=$PATH:/usr/gcctemp/bin/
Ensuite, il ne reste plus qu'à créer l'exécutable GCC.
root@xdoofy:/usr/gccFR30# make root@xdoofy:/usr/gccFR30# make install
Maintenant, nous allons tester notre nouveau compilateur. Pour cela,
nous allons créer un code C utilisant la multiplication.
root@xdoofy:/usr/exemple#Fujitsu-FR30-gcc-3.4.5 -s test.c
Nous allons tester le code suivant :
int main(void){ int a=323; int b=467653; return a*b;}
Voici le résultat avant la manipulation :
... ld @r2, r2 ld @r1, r1 mul r1, r2 mov mdl, r1 mov r1, r4 ...
et après :
... ld @r2, r2 ld @r1, r1 ISIMA r1, r2 mov mdl, r1 mov r1, r4 ...