32 bits, et nous posons un axiome pour spécifier que la valeur désignée par un
int32 est toujours dans cet intervalle.
Afin de représenter des nombres flottants, nous réutilisons le modèle des
nombres flottants en 32 et en 64 bits qui est défini par Ayad and Marché [1].
Ce modèle introduit les types abstraits single and double. Nous pouvons
également représenter le type binary80 pour un nombre flottant en 80 bits.
Voici le modèle pour les nombres flottants en 64 bits:
type mode = nearest_even | to_zero | up | down | nearest_away
type double
logic double_value : double -> real
logic round_double : mode, real -> real
predicate no_overflow_double(m:mode,x:real) =
abs(round_double(m,x)) <= 0x1.FFFFFFFFFFFFFp1023
Un type énuméré mode est défini pour cinq modes possibles d’arrondi. Le
type abstrait double pour les nombres flottants en 64 bits est déclaré, avec une
fonction double_value retournant la valeur réelle qu’il désigne. La fonction
logique round_double(m, x)retourne le nombre représentable en 64 bits après
avoir arrondi avec le mode m. Le prédicat no_overflow_double(m, x) vérifie
si un réel xarrondi en 64 bits avec le mode mest débordé.
Registres Une caractéristique importante de notre approche est comment
modéliser les registres que les instructions assembleurs utilisent. Le problème
est qu’un registre n’enregistre qu’une séquence des bits, qui peut être interpreter
comme un entier, un nombre flottant ou une adresse mémoire. En plus, nous
considérons qu’il n’y a pas de différence entre un registre en 64 bits et sa valeur
en 32 bits enregistrée dans la partie inférieure. Par exemple: il n’y a pas de
différence entre les registres rax et eax dans l’architecture x86.
Pour modéliser cet comportement, nous introduisons un type abstrait
register équipé avec quelques symboles d’accessibilité. Chaque symbole
désigne une “vue” différente de la valeur enregistrée dans le registre. Par exem-
ple, afin de modéliser \exact, le symbole sel_exact est la vue pour le calcul
avec la précision illimitée.
type register
logic sel_int32 : register -> int32
logic sel_int64 : register -> int64
logic sel_single : register -> single
logic sel_double : register -> double
logic sel_80 : register -> binary80
logic sel_exact : register -> real
Pour chaque registre, nous introduisons une variable Why avec le type
register.
5