18/5/2015 Aidemoire du Programmeur - Cortex M3
file:///F:/memo_cm3.html 1/6
Aide Mémoire du Programmeur - Cortex M3
J.L. Noullet - INSA Toulouse - révision 1.3
Le STM32 est une implémentation du Cortex M3, qui exécute un sous-ensemble du jeu d'instructions ARMv7-M ("M" pour "Microcontrôleur").
Ce jeu d'instruction utilise le codage Thumb-2, contenant le jeu simplifié Thumb codé sur 16 bits, et un ensemble de codes complémentaire sur 32
bits.
1. Mnémoniques classés par catégories
Les instructions soulignées acceptent le suffixe S pour mise à jour des flags (NZCV).
Copie de données (32 bits)
MOV de registre à registre ou immédiat vers registre
LDR, STR Load (RAM vers registre), Store (registre vers RAM)
LDM, STM Load et Store multiples (liste de registres), indirects
PUSH, POP cas particuliers de STM et LDM
Copie et manipulation de byte (8 bits) et half-word (16 bits)
LDR, STR avec suffixes B, H, SB, SH
MOVT T=Top, affecte seulement les 16 MSBs
REV permutation de bytes
SXT, UXT extension à 32 bits signée ou non-signée (suff. B et H)
Manipulation de bits
BFC, BFI, SBFX, UBFX bit fields (Clear, Insert, Extract)
CLZ, RBIT comptage des zéros en tête, permutation de bits
Arithmétique
ADD, ADC C=Carry (inclusion dans la somme)
SUB, SBC, RSB C=Carry, R=reverse ( Rm-Rn au lieu de Rn-Rm )
MUL, MLA, MLS résultat modulo 2^32 (débordement possible), A=Accumulation
UMULL, UMLAL résultat 64 bits (débordement impossible), A=Accumulation
SMULL, SMLAL résultat 64 bits (débordement impossible), A=Accumulation
SDIV, UDIV
SSAT, USAT saturation taille arbitraire < 32 bits
Logique
AND, BIC BIC = AND NOT
ORR, ORN ORN = OR NOT
EOR XOR
MVN NOT
Décalages
LSL, LSR, ASR, ROR décalage constant ou variable, de 1 à 31 positions
RRX rotation de 1 position via le flag C
Tests sur data
TST, TEQ comme ANDS et EORS mais resultat non conservé (pas de Rd)
CMP, CMN comme SUBS et ADDS mais resultat non conservé (pas de Rd)
CBZ, CBNZ Comparaison registre avec zéro puis branch
Sauts "Branch"
B, BX X=Indirect
BL, BLX L=Link (sauvegarde PC dans LR)
CBZ, CBNZ Comparaison registre avec zéro puis branch
TBB, TBH Table Branch : branchement indirect par table d'adresses
Divers
NOP
IT If-Then
SVC interruption soft
MSR, MRS accés au registre des flags
WFE, WFI mise en veille
ADR
18/5/2015 Aidemoire du Programmeur - Cortex M3
file:///F:/memo_cm3.html 2/6
2. Syntaxe de codage des instructions
2.1 Suffixes des mnémoniques coller sans espace) :
taille du transfer : B, H, D pour 8 bits (Byte), 16 bits (Half-word), 64 bits (Double-word)
(Attention : conflit avec la notation Microsoft utilisée par Keil : WORD = 16 bits, DWORD = 32 bits)
SB, SH pour les extensions de signe à 32 bits,
16 pour opération effectuée en parallèle sur les deux moitiés d'un mot de 32 bits
mise a jour optionnelle des flags : S
incrémentation ou décrémentation pour les Load et Store Multiples LDM et STM :
IA : Increment After
DB : Decrement Before
codes de condition sur 2 caractères (voir 2.8 traitements conditionnels) : .
EQ Z = 1 Equal
NE Z = 0 Not equal
HI C = 1 and Z = 0 Higher unsigned
CS or HS C = 1 Higher or same unsigned
LS C = 0 or Z = 1 Lower or same unsigned
CC or LO C = 0 Lower unsigned
MI N = 1 Negative signed
PL N = 0 Positive or zero signed
VS V = 1 Overflow signed
VC V = 0 No overflow signed
GT Z = 0 and N = V Greater than signed
GE N = V Greater than or equal signed
LE Z = 1 or N != V Less than or equal signed
LT N != V Less than signed
forçage de taille pour le codage instruction
.W : forcer 32 bits "Wide" (si disponible)
.N : forcer 16 bits "Narrow" (si possible)
2.2 Registre destination
Le premier registre de la liste va recevoir le résultat, SAUF dans le cas STR (Store).
Ce cas particulier est à un codage homogène pour LDR et STR :
LDR r0, [r1, #4] ; Load : registre <-- mémoire
STR r0, [r1, #4] ; Store : registre --> mémoire
La seconde instruction fait l'opération inverse de la première.
2.3 Forme simplifiée 2 orandes au lieu de 3
De nombreuses instructions prennent 2 opérandes sources et 1 opérande destination :
ADD Rd, Rn, Rm ; Rd = Rn + Rm
Si on donne seulement 2 opérandes :
ADD Rd, Rm ; Rd = Rd + Rm soit Rd += Rm
l'assembleur met Rd à la position de Rn :
ADD Rd, Rd, Rm ; Rd += Rm
18/5/2015 Aidemoire du Programmeur - Cortex M3
file:///F:/memo_cm3.html 3/6
2.4 Modes d'adressage immediat ou litral
constante ou expression constante (signe '#')
MOV r0, #0x4F ; hexa
MOV r1, #112 ; decimal
MOV r2, #(12*3+5) ; expression calculee pendant l'assemblage
Attention aux limitations dues au codage sur 12 bits (soit une constante 8 bits décalée ou dupliquée).
Il existe une variante "Wide" acceptant une constante de 16 bits :
MOVW r3, #0x8001 ; (l'assembleur sait remplacer MOV par MOVW si nécessaire)
constante de 32 bits en 2 opérations
MOVW r0, #0x2013 ; 0x00002013 dans r0 (imm16)
MOVT r0, #0x1963 ; 0x19632013 dans r0 (imm16)
macro LDR et litteral pool (signe '=')
LDR r0, =0x19632013
En fonction de la valeur de la constante, l'assembleur va remplacer cette pseudo-instruction (macro) par un MOV, un MOVW, ou un LDR
avec adressage relatif-PC pour chercher la constante dans le litteral pool.
Le litteral pool est une zone de données constantes que l'assembleur peut créer automatiquement dans la section courante, pour faciliter
l'introduction de constantes
2.5 Modes d'adressage registre
Simple :
MOV r0, r1 ; copie de r1 dans r0
avec décalage ou rotation du registre source :
MOV r0, r1, LSL #4 ; copie de r1, décalé de 4 bits a gauche, dans r0
MOV r0, r1, LSR r5 ; copie de r1, décalé de r5 bits a droite, dans r0
MOV r0, r1, RRX ; copie de r1, avec rotation a droite de 1 bit, dans r0
LSL Logic Shift Left
LSR Logic Shift Right (unsigned)
ASR Arithmetic Shift Right (sign extension)
ROR Rotate Right over 32 bits
RRX Rotate Right 1 place over 33 bits (C flag included)
Note : on pourrait donc se passer des instructions LSL, LSR, ASR, ROR, RRX...
Rappel : les décalages permettent de faire des multiplications et divisions par les puissances de 2 ts efficacement.
2.6 Modes d'adressage mémoire
1 registre
LDR r1, [r7] ; les crochets '[' et ']' signalent l'indirection
2 registres ("pre-indexed"), le second (index) peut être décalé à gauche
LDR r1, [r6, r7] ; adresse = r6 + r7, par exemple base + index
LDR r1, [r6, r7, LSL #2] ; adresse = r6 + r7 * 4
LDR r1, [r6, r7]! ; le '!' signale mise a jour de r6 = r6 + r7
Note : dans le 3eme cas, r7 est un incrément plutôt qu'un index, c'est pour parcourir un tableau séquentiellement.
1 registre + 1 constante (déplacement ou offset signé)
LDR r1, [r6, #120] ; acces à un membre d'une structure ou objet C++
LDR r1, [r6, #4]! ; pré-indexation, le '!' signale mise a jour de r6 = r6 + 4
LDR r1, [r6], #4 ; post-indexation, adresse = r6, puis r6 = r6 + 4
Note : dans le 2eme et le 3eme cas, la constante est un decrément plutôt qu'un index, c'est pour parcourir un tableau séquentiellement:
r1 = *(++r6) // comme on l'écrirait en C
r1 = *(r6++)
18/5/2015 Aidemoire du Programmeur - Cortex M3
file:///F:/memo_cm3.html 4/6
application particulière : adressage relatif-PC pour une donnée en ROM
Dans le cas d'un code relogeable, ni l'adresse associée à un label ni celle de l'instruction courante ne sont connues au moment de l'assemblage,
mais la différence l'est, l'assembleur peut donc calculer un déplacement à additionner au contenu du registre PC pour accéder à la donnée :
labul dcd 0x0561559513
...
LDR r0, labul ; copie dans r0 la variable labul stockée en ROM
Le code produit sera équivalent à :
LDR r0, [PC, #(labul-.-K)] ; . = adresse instr. courante, K = constante (2 ou 4)
La valeur de K dépend de l'alignement.
Cette technique est utilisée pour le litteral pool (macro LDR avec sign '=', voir ci-dessus)
Load/Store Multiples (par dérogation au style RISC)
Attention : la syntaxe de ces instructions n'est pas cohérente avec le reste du jeu d'instructions.
LDM r7, {r0, r1, r2, r4} ; charger les registres de la liste avec les valeurs lues en mémoire,
à partir de l'adresse de base donnée par r7
LDM r7!, {r0, r1, r2, r4} ; idem, puis mettre a jour r7
STM r7, {r0, r1, r2, r4} ; stocker le contenu des registres de la liste en mémoire,
à partir de l'adresse de base donnée par r7
STM r7!, {r0, r1, r2, r4} ; idem, puis mettre a jour r7
Ces instructions acceptent les suffixes DB (Decrement Before) et IA (Increment After), qui est le choix par défaut.
La liste de registres entres accolades '{' et '}' peut contenir 1 à 15 registres (tous sauf SP).
Attention : l'ordre des registres stockés ou lus en mémoire par une instruction multiple est toujours tel que les adresses mémoire croissent dans
le sens des indices des registres (c'est indépendant de l'ordre des éléments de la liste, qui est ignoré).
Push et Pop
L'empilage (Push) et le dépilage (Pop) sont des applications de Store Multiple et Load Multiple avec SP et '!'
PUSH {r1, r2} ; empiler r1 et r2 (r2 en premier, c'est a dire à l'adresse max)
STMDB SP!, {r1, r2} ; idem, DB choisi pour "full descending stack"
POP {r1, r2} ; dépiler r1 et r2 (r2 en dernier, c'est a dire de l'adresse max)
LDM SP!, {r1, r2} ; idem, IA choisi pour "full descending stack"
Le dépilage de PC est équivalent à un saut indirect utilisant une valeur prise dans la pile, ce qui peut tenir lieu de retour de sous-programme à
condition d'avoir empilé LR en début de sous-programme. On peut en profiter pour empiler quelques registres :
PUSH {r4, r5, r6, LR} ; au début du sous-programme
...
...
POP {r4, r5, r6, PC} ; retour du sous-programme
2.7 Instruction de saut : "Branch"
B unlabel ; un saut direct (codé en relatif)
Bcc unlabel ; saut conditionnel, cc est une condition parmi les 14 possibles (voir suffixes ci-dessus)
BL unlabel ; appel de sous programme (adresse retour copiée dans LR)
BX r3 ; saut indirect par registre (par exemple r3)
BX LR ; retour de sous programme simple
BLX r3 ; appel de sous programme indirect par registre (adr retour dans LR)
Notes :
Historiquement, le X est pour "exchange" car BX et BLX permettent de changer de jeu d'instruction. En Thumb-2 il n'est pas question de cela,
on peut considérer que le X signifie simplement indirect par registre.
Contrairement à la majorité des autres architectures, l'ARM n'a pas d'intruction de retour de sous programme, le retour se fait avec BX LR si
l'adresse de retour est dans LR, ou POP {PC] si elle est dans le pile.
Contrairement à la majorité des autres architectures, l'ARM n'a pas d'intruction de retour d'interruption, le retour d'interruption se fait comme un
retour de sous-programme ordinaire, c'est dans l'adresse de retour qu'il y a un code spécifique pour appliquer le traitement approprié aux
interruptions.
18/5/2015 Aidemoire du Programmeur - Cortex M3
file:///F:/memo_cm3.html 5/6
2.8 Traitements conditionnels
Dans le jeu d'instructions ARM 32 bits, presque toutes les instructions peuvent être conditionnelles (ce qui encombre 4 bits dans l'encodage des
instruction).
Pour rendre le code plus compact, en Thumb-2 il n'y a que l'instruction B (Branch) qui contienne l'encodage d'une condition parmi les 14 possibles
(voir suffixes ci-dessus). Cela couvre déjà la majorité des besoins en matière de traitement conditionnel.
Pour compenser cette restriction, l'instruction spéciale IT (If-Then) a été ajoue, elle permet de rendre conditionnelles 1 à 4 instructions consécutives :
le nombre de lettres après le I détermine le nombre d'instructions concernées
les lettres permises sont T (Then) et E (Else), la première est toujours T
l'instruction IT prend comme argument 1 code condition parmi les 14 possibles
chaque instruction associée à un T sera exécutée si la condition est vraie
chaque instruction associée à un E sera exécutée si la condition n'est pas vraie
Pour que le langage d'assemblage reste compatible avec le jeu d'instructions ARM classique, on applique les règles suivantes :
L'assembleur génère l'instruction IT lui-même, on peut l'omettre du code source
Chaque instruction du bloc IT est doit être munie d'un suffixe indiquant la condition qui doit lui être appliquée
Exemple : ajouter a r0 la valeur absolue de r1 :
MOVS r1, r1
; l'assembleur insérera automatiquement l'instruction ITE PL
ADDPL r0, r1
SUBMI r0, r1
Indépendamment de cela il existe 2 instructions combinées effectuant comparaison à zéro et branch, celles-ci ne supportent que 2 conditions :
CBZ : compare register with zero, branch if zero
CBNZ : compare register with zero, branch if not zero
3. Conventions d'appel de procédures et fonctions
3.1 Empilage dif (ARM)
L'architecture ARM préconise un registre dédié (LR pour Link Register) pour l'adresse de retour. A charge pour la fonction appelée d'empiler la
valeur de ce registre si elle même doit en appeler une autre.
Le gain d'efficacité concerne seulement les fonctions "feuilles" (leaf subroutines), c'est à dire celles qui n'en appellent aucune autre).
Exemples de code :
appel de fonction (dans tous les cas)
BL myfunction ; branch-and-link, update LR
corps de la fonction
fonction "feuille"
...
...
BX LR ; indirect jump to [LR]
fonction quelconque
PUSH {LR} ; empiler l'adresse de retour
...
BL myfunction2
...
POP {PC} ; dépiler directement dans PC
Note : chez ARM, le bit de faible poids de PC n'est pas utilisé pour accéder aux instructions (dont les adresses sont obligatoirement paires) mais il sert
à signaler l'utilisation du jeu d'instructions Thumb ou Thumb-2 (Cortex M3).
1 / 6 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !