Premiers pas en assembleur XTENSA
publication: 17 novembre 2022 / mis à jour 18 novembre 2022
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
Pourquoi programmer en assembleur?
Le code assembleur n'est pas portable dans un autre environnement, ou alors au prix d'énormes efforts de comprehension et d'adaptation du code assemblé.
Une version FORTH n'est pas complète si elle n'a pas d'assembleur.
La programmation en assembleur n'est pas une obligation. Mais dans certains cas, créer une définition en assembleur peut s'avérer bien plus aisé qu'une version en langage C ou en langage FORTH pur.
Mais surtout, une définition écrite en assembleur aura une rapidité d'exécution inégalable.
Nous allons voir, à partir d'exemples très simples et très courts comment maitriser la programmation de définitions FORTH écrites en assembleur Xtensa.
Invocation de l'assembleur Xtensa
Au démarrage de ESP32forth, impossible de définir des mots en assembleur Xtensa sans invoquer le mot xtensa-assembler
.
Ce mot va charger le contenu du vocabulaire xtensa
. Ce mot ne doit être invoqué qu'une seule fois au démarrage de
ESP32forth et avant toute définition d'un mot en code xtensa:
forth DEFINED? code invert [IF] xtensa-assembler [THEN]
Maintenant, si on tape order
, ESP32forth affiche:
xtensa >> asm >> FORTH
C'est cet ordre de vocabulaires qu'il faudra respecter quand on veut définir un nouveau mot en assembleur Xtensa à l'aide des
mots de définition code
et end-code
.
Xtensa et la pile FORTH
Le processeur Xtensa dispose de 16 registres, a0
à a15
. En réalité, il y a 64 registres, mais on ne
peut accéder qu'à une fenêtre de 16 registres parmis ces 64 registres, accessibles dans l'intervalle 00..15.
Le registre a2
contient le pointeur de pile FORTH.
A chaque empilement de valeur, le pointeur de pile est incrémenté de quatre unités:
SP@ . \ display 1073632236 1 SP@ . \ display 1073632240 2 SP@ . \ display 1073632244 drop drop SP@ . \ 1073632236
Voici comment on pourrait réécrire ce mot SP@
en assembleur Xtensa:
\ get Stack Pointer SP - equivalent for SP@ code mySP@ a1 32 ENTRY, a8 a2 MOV.N, \ copy content of a2 in a8 a2 a2 4 ADDI, \ increment a2 a8 a2 0 S32I.N, \ copy a8 in address pointed by a2+0 RETW.N, end-code
Testons ce nouveau mot mySP@
:
mySP@ . \ display 1073632240 SP@ . \ display 1073632240
Ecriture d'une macro instruction Xtensa
Dans notre définition du mot mySP@
, la séquence a2 a2 4 ADDI,
incrémente de quatre
unités le pointeur de pile. Sans cette incrémentation, impossible de renvoyer une valeur au sommet de la pile
FORTH. Avec FORTH, nous allons écrire une macro qui automatise cette opération.
Pour commencer, nous allons étendre le vocabulaire asm
:
asm definitions : macro: : ;
Notre définition macro:
est redondante avec :
mais à l'avantage de rendre ensuite le code
FORTH un peu plus lisible quand on définit une macro-instruction qui étendra le vocabulaire xtensa
:
xtensa definitions macro: sp++, a2 a2 4 ADDI, ;
Avec cette nouvelle macro-instruction sp++,
, nous pouvons réécrire la définition de mySP@
:
forth definitions asm xtensa \ get Stack Pointer SP - equivalent for SP@ code mySP@ a1 32 ENTRY, a8 a2 MOV.N, \ copy content of a2 in a8 sp++, a8 a2 0 S32I.N, \ copy a8 in address pointed by a2+0 RETW.N, end-code
Il est parfaitement possible d'intégrer une macro dans une autre. Dans le code de
mySP@
, la ligne de code a8 a2 0 S32I.N,
copie le contenu du registre
a8 à l'adresse pointée par a2. Voici cette nouvelle macro instruction:
xtensa definitions
\ increment Stack Pointer and store content of ar in addr pointed by Stack Pointer
macro: arPUSH, { ar -- }
sp++,
ar a2 0 S32I.N,
;
Cette macro instruction utilise une variable locale ar. On aurait pu s'en passer, mais l'intérêt de cette variable est que le code de la macro est plus lisible.
Voici le code de mySP@ avec cette macro-instruction.
forth definitions
asm xtensa
\ get Stack Pointer SP - equivalent to SP@
code mySP@3
a1 32 ENTRY,
a8 a2 MOV.N,
a8 arPUSH,
RETW.N,
end-code
Complétons notre liste de macro instructions:
xtensa definitions \ decrement Stack Pointer macro: sp--, ( -- ) a2 a2 -4 ADDI, ; \ Store content of addr pointed by Stack Pointer in ar and decrement Stack Pointer macro: arPOP, { ar -- } ar a2 0 L32I.N, sp--, ;
Avec ces nouvelles macros, réécrivons swap
:
forth definitions asm xtensa code mySWAP a1 32 ENTRY, a9 arPOP, a8 arPOP, a9 arPUSH, a8 arPUSH, RETW.N, end-code 17 24 mySWAP
Voici la fin de ces premiers pas avec l'assembleur xtensa. Nous n'avons abordé que la toute première page d'un énorme livre.
Legal: site web personnel sans commerce / personal site without seling