Autres articles / Other articles

Continuer avec l'assembleur XTENSA

publication: 20 novembre 2022 / mis à jour 20 novembre 2022

Read this page in english

 

Appel à collaboration

Vous développez des montages, simples ou complexes avec ESP32 et ESP32forth.

Partagez-les ici sur ce site.

ESP32forth ne pourra se développer qu'avec la collaboration active de toutes les bonnes volontés.

Vos montages peuvent aider d'autres développeurs.

Les montages des autres développeurs peuvent vous aider.

Pour proposer un article ou un montage, cliquez ici


Préambule

Nous avons vu, dans le précédent article, comment définir des macro-instructions et jouer un peu avec la pile de données. Nous allons approfondir l'accès à la pile de données FORTH depuis l'assembleur Xtensa.

Gestion de la pile FORTH en assembleur Xtensa

La position du pointeur de pile FORTH est accessible par SP@. L'empilement d'un entier 32 bits (taille par défaut pour ESP32forth) incrémente ce pointeur de pile de quatre unités.

Dans le précédent article, nous avons abordé la manière de gérer l'incrémentation ou décrémentation de ce pointeur de pile au travers des macro-instructions sp++, et sp--,. Ces macro-instructions déplacent le pointeur de pile de quatre unités.

Ici, on a empilé troix valeurs, 1 4 et 9. A chaque empilement, le pointeur de pile est incrémenté automatiquement. En assembleur Xtensa, le pointeur de pile se retrouve dans le registre a2. Nous avons vu, dans le précédent article, que nous pouvons manipuler le contenu de ce registre avec els macro-instructions sp++, et sp--,. La manipulation de ce registre a une action directe sur le pointeur de pile géré par ESP32forth.

Voici comment nous avons réécrit en assembleur le mot + en manipulatnt le pointeur de pile au travers de nos macro-instructions arPOP, et arPUSH,:

code my+ 
    a1 32       ENTRY,  
    a7  arPOP, 
    a8  arPOP, 
    a7 a8 a9    ADD, 
    a9  arPUSH,  
            RETW.N,  
end-code 

Il y a un autre moyen pour récupérer les données depuis la pile en utilisant l'instruction L32I.N,. Cette instruction utilise un index immédiat:

code my+ 
    a1 32 ENTRY,  
        sp--, 
    a7 a2 0     L32I.N,  
    a8 a2 1     L32I.N,  
    a7 a8 a9    ADD, 
    a9 a2 0     S32I.N,  
    RETW.N,  
end-code 

Avant de récupérer les données de la pile, on décrémente le pointeur de pile avec notre macro-instruction sp--,. De cette manière, le pointeur recule de 4 unités.

Mais ce n'est pas parce que le pointeur recule que les données préalablement empilées disparaissent. Voyons en détail cette ligne de code:

    a7 a2 0     L32I.N,

Cette instruction charge le registre a7 avec le contenu de l'adresse pointée par (a2)+n*4. Ici, n vaut 0. Cette instruction va mettre la valeur 4 dans notre registre a7.

Voyons la ligne suivante:

    a8 a2 1     L32I.N,

Le registre a8 est chargé avec le contenu pointé par (a2)+1*4. Cette instruction met la valeur 9 dans notre registre a8.

    a9 a2 0     S32I.N,

Ici, le contenu du registre a9 est stocké à l'adresse pointée par (a2)+1*0. En fait, on écrase la valeur 4 avec le résultat de l'addition du contenu des registres a7 et a8.

Voyons un dernier exemple où nous traitons deuix paramètres et en restituons deux sur la pile de données. Dans cet exemple, nous réécrivons le mot /MOD:

code my/MOD ( n1 n2 -- rem quot ) 
    a1 32       ENTRY,  
    a7  arPOP,          \ divider in a7 
    a8  arPOP,          \ value to divide in a8 
    a7 a8 a9    REMS,   \ a9 = a8 MOD a7 
    a9  arPUSH, 
    a7 a8 a9    QUOS,   \ a9 = a8 / a7 
    a9  arPUSH, 
            RETW.N,  
end-code 
 
5 2 my/MOD . .      \ display 2 1 
-5 -2 my/MOD . .    \ display 2 -1 

Dans le mot my/MOD on exploite les mêmes données n1 et n2 placées respectivement dans les registres a8 et a7. Ce sont ensuite les instructions REMS, et QUOT, qui permettent de calculer les résultats restitués par my/MOD.

Efficacité des mots écrits en assembleur XTENSA

Dans notre tout dernier exemple ci-edssus, nous avons réécrit le mot /MOD. La question à se poser est: est-ce que le mot my/MOD est réellement plus rapide en exécution que le mot /MOD?.

Pour ce faire, nous allons compiler le mot measure: dont le code FORTH est accessible ici:
measures the execution time of a FORTH word.

: test1 
    1000000 for 
        5 2 /MOD 
        drop drop 
    next 
  ; 
 
: test2 
    1000000 for 
        5 2 my/MOD 
        drop drop 
    next 
  ; 
 
measure: test1  \ display: execution time: 0.856sec. 
measure: test2  \ display: execution time: 0.600sec. 

Les mots test1 et test2 sont semblables, à la différence que test2 exécute my/MOD. Sur 1 million d'itérations, le gain de temps s'élève à 0.144 seconde. C'est peu, mais le ratio semble quand même significatif.

A contrario, on constate que le langage FORTH est très rapide en temps d'exécution.


Legal: site web personnel sans commerce / personal site without seling