Conventions d'appel de procédure
Pour pouvoir correctement gérer la pile, le mécanisme de
fenêtre de registres, et les éventuels besoins du système
en place pour pouvoir sauvegarder les registres lors des débordements
de fenêtre et les commutations entre processus, un minimum de règles
sont à respecter lors de l'exécution de sous-routines:
(Je donne ces recommandations pour le début de la documentation
sur Sparc; dans les sections suivantes (type bidouillage avancé
et autres optimisation pour les démos, je m'autoriserai quelques
entorses...))
-
Ne pas oublier que la pile croît des adresses supérieures
vers les adresses inférieures !
De plus, le pile doit être toujours alignée sur une frontière
de double-mot (8 octets) (Ceci est requis par l'OS, pour qu'il puisse
à tout moment sauver les regitres par paquet de 2 (avec std))
-
Une routine standard doit se charger de demander sa nouvelle fenêtre
de registre, et de reserver au moins 64 octets sur la pile pour le
système, au tout debut de son exécution. On utilisera pour
cela
save %sp,-64,%sp
S'il y a besoin d'allouer de la place sur la pile pour les variables
locales, on incluera leur taille dans l'intruction save en plus des 64
octets minimaux; Il faut cependant un alignement sur double-mots; pour
en être sûr, on peut utiliser l'écriture suivante:
save %sp,(-64-tailleLocal)&(-8),%sp
qui force l'alignement.
Pourquoi ces 64 octets ? Lors des éventuels overflow de
fenetre de registres, l'OS doit liberer une ancienne fenetre de
registre pour la nouvelle procédure. Seuls les registres Locaux
et In ont besoin d'être sauvés (les registres Out sont dans la
fenêtre suivante, les registres Globaux sont... toujours la) - donc 16
registres, donc 64 octets. Ces registres sont sauvés dans
(%sp),(%sp+4) etc.. (%sp de cette fenetre a liberer), c'est à
dire dans (%fp-64)-(%fp-8) de la fenetre suivante, d'où
l'interet de laisser de la place.(Sinon l'OS s'arrange pour vous le
faire regretter, soit en killant votre process, soit en faisant ramer
le programme en raison de la surcharge de travail)
Une routine feuille (Leaf subroutine) est une routine qui ne fait appel
à aucune autre routine, et qui n'utilise que les registres %o0-%o5
de l'appelant pour effectuer ses calculs; un tel type de routine n'a pas
besoin d'effectuer de Save.
-
Par convention, les paramètres de la routines sont transmis dans
%o0-%o5 de l'appelant, soit %i0-%i5 apres l'execution de Save; Il est préférable
de pas modifier ces registres, au cas où l'appelant s'attendrait
à pouvoir s'en resservir.Pour une fonction, la valeur de retour
est renvoyé dans ces mêmes registres (en général
%o0 seul ou %o0-%o1), et la évidemment il vaut mieux les modifier
pour que l'appelant reçoive quelque chose....
Les routines feuilles sont l'exception à cette convention de
conservation; l'appelant ne doit s'attendre à aucune sauvegarde.
-
En fin de routine, le retour s'effectue par
ret
restore <restore est
dans le delay-slot de ret>
pour une routine standard, et
retl
nop
pour une routine feuille.
Au niveau de l'utilisation des registres, quelques rappels:
-
Les registres %i0-%i5 contiennent les paramètres de la fonction, remplis
par l'appelant, et sont eventuellement remplacé par le résultat
de la fonction.
-
%i6=%fp est le frame-pointer ; c'est la valeur de %sp de l'appelant, il
sert de référence immuable pour pouvoir accéder aux
variables locales et aux eventuels paramètres transmis sur la pile
(pour cause de manque de place dans les registre %i0-%i5)
IL NE FAUT PAS Y TOUCHER !
-
%i7 est l'adresse de l'instruction Call ou Jmpl de l'appelant; %o7+8 est
alors l'adresse de retour de la procédure.
IL NE FAUT PAS Y TOUCHER !
-
%l0-%l7 sont les registres locaux de la procédure, on peut en faire
ce que l'on veut
-
%o0-%o5 sont utilisés pour transmettre des paramètres à
d'autre procédures et recevoir des résultats en retour.
Une programmation "propre" ne devrait s'en servir que dans ce but, et pas pour faire des calculs internes comme %l0-%l7...
-
%o6 = %sp, pointeur actuel de la pile. Ne pas s'en servir pour autre chose,
et le garder aligné sur un double-mot.
-
%o7 est réservé pour contenir l'adresse de retour en cas d'appel de procédure.
-
%g0-%g7 sont globaux, tout le monde peut en faire ce qu'il veut.
Par conséquent, il faut considérer qu'après un appel de procédure, leur contenu est indéterminé (sauf %g0 bien sûr...).
Interfaçage avec le C
La convention du C est de remplir tous les registres %o0-%o5 lors d'un
appel de procédure dans l'ordre d'écriture des paramètres:
l'appel de foo(toto1,toto2) avec totox des variables int se fera en
mettant toto1 dans %o0 et toto2 dans %o1.
Les paramètres supplémentaires qui ne tiennent plus dans
les registres sont placés sur la pile, avec la particularité
que le premier qui déborde peut avoir un morceau dans %o5, et le
reste sur la pile (utilisation maximale des registres).