Aide Mémoire du Programmeur

publicité
18/5/2015
Aide Mémoire du Programmeur - Cortex M3
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
LDR, STR
LDM, STM
PUSH, POP
de registre à registre ou immédiat vers registre
Load (RAM vers registre), Store (registre vers RAM)
Load et Store multiples (liste de registres), indirects
cas particuliers de STM et LDM
Copie et manipulation de byte (8 bits) et half-word (16 bits)
LDR, STR
MOVT
REV
SXT, UXT
avec suffixes B, H, SB, SH
T=Top, affecte seulement les 16 MSBs
permutation de bytes
extension à 32 bits signée ou non-signée (suff. B et H)
Manipulation de bits
BFC, BFI, SBFX, UBFX
CLZ, RBIT
bit fields (Clear, Insert, Extract)
comptage des zéros en tête, permutation de bits
Arithmétique
ADD, ADC
SUB, SBC, RSB
MUL, MLA, MLS
UMULL, UMLAL
SMULL, SMLAL
SDIV, UDIV
SSAT, USAT
C=Carry (inclusion dans la somme)
C=Carry, R=reverse ( Rm-Rn au lieu de Rn-Rm )
résultat modulo 2^32 (débordement possible), A=Accumulation
résultat 64 bits (débordement impossible), A=Accumulation
résultat 64 bits (débordement impossible), A=Accumulation
AND, BIC
ORR, ORN
EOR
MVN
BIC = AND NOT
ORN = OR NOT
XOR
NOT
LSL, LSR, ASR, ROR
RRX
décalage constant ou variable, de 1 à 31 positions
rotation de 1 position via le flag C
saturation taille arbitraire < 32 bits
Logique
Décalages
Tests sur data
TST, TEQ
CMP, CMN
CBZ, CBNZ
comme ANDS et EORS mais resultat non conservé (pas de Rd)
comme SUBS et ADDS mais resultat non conservé (pas de Rd)
Comparaison registre avec zéro puis branch
Sauts "Branch"
B, BX
BL, BLX
CBZ, CBNZ
TBB, TBH
X=Indirect
L=Link (sauvegarde PC dans LR)
Comparaison registre avec zéro puis branch
Table Branch : branchement indirect par table d'adresses
NOP
IT
SVC
MSR, MRS
WFE, WFI
ADR
If-Then
interruption soft
accés au registre des flags
mise en veille
Divers
file:///F:/memo_cm3.html
1/6
18/5/2015
Aide Mémoire du Programmeur - Cortex M3
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 dû à un codage homogène pour LDR et STR :
LDR
STR
r0, [r1, #4]
r0, [r1, #4]
; Load : registre <-- mémoire
; Store : registre --> mémoire
La seconde instruction fait l'opération inverse de la première.
2.3 Forme simplifiée 2 opérandes 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
file:///F:/memo_cm3.html
Rd, Rd, Rm
; Rd += Rm
2/6
18/5/2015
Aide Mémoire du Programmeur - Cortex M3
2.4 Modes d'adressage immediat ou littéral
constante ou expression constante (signe '#')
MOV
MOV
MOV
r0, #0x4F
r1, #112
r2, #(12*3+5)
; hexa
; decimal
; 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
MOVT
r0, #0x2013
r0, #0x1963
; 0x00002013 dans r0 (imm16)
; 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
MOV
MOV
r0, r1, LSL #4 ; copie de r1, décalé de 4 bits a gauche, dans r0
r0, r1, LSR r5 ; copie de r1, décalé de r5 bits a droite, dans r0
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 très 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
LDR
LDR
r1, [r6, r7]
r1, [r6, r7, LSL #2]
r1, [r6, r7]!
; adresse = r6 + r7, par exemple base + index
; adresse = r6 + r7 * 4
; 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
LDR
LDR
r1, [r6, #120]
r1, [r6, #4]!
r1, [r6], #4
; acces à un membre d'une structure ou objet C++
; pré-indexation, le '!' signale mise a jour de r6 = 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)
r1 = *(r6++)
file:///F:/memo_cm3.html
// comme on l'écrirait en C
3/6
18/5/2015
Aide Mémoire du Programmeur - Cortex M3
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
...
LDR
0x0561559513
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}
LDM
STM
r7!, {r0, r1, r2, r4}
r7, {r0, r1, r2, r4}
STM
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
; idem, puis mettre a jour r7
; stocker le contenu des registres de la liste en mémoire,
à partir de l'adresse de base donnée par r7
; 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
STMDB
POP
LDM
{r1, r2}
SP!, {r1, r2}
{r1, r2}
SP!, {r1, r2}
; empiler r1 et r2 (r2 en premier, c'est a dire à l'adresse max)
; idem, DB choisi pour "full descending stack"
; dépiler r1 et r2 (r2 en dernier, c'est a dire de l'adresse max)
; 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
...
...
POP
{r4, r5, r6, LR}
; au début du sous-programme
{r4, r5, r6, PC}
; retour du sous-programme
2.7 Instruction de saut : "Branch"
B
Bcc
BL
BX
BX
BLX
unlabel ; un saut direct (codé en relatif)
unlabel ; saut conditionnel, cc est une condition parmi les 14 possibles (voir suffixes ci-dessus)
unlabel ; appel de sous programme (adresse retour copiée dans LR)
r3
; saut indirect par registre (par exemple r3)
LR
; retour de sous programme simple
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.
file:///F:/memo_cm3.html
4/6
18/5/2015
Aide Mémoire du Programmeur - Cortex M3
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é ajoutée, 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
ADDPL
SUBMI
r0, r1
r0, r1
; l'assembleur insérera automatiquement l'instruction ITE PL
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 différé (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]
{LR}
; empiler l'adresse de retour
fonction quelconque
PUSH
...
BL
...
POP
myfunction2
{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).
file:///F:/memo_cm3.html
5/6
18/5/2015
Aide Mémoire du Programmeur - Cortex M3
3.2 Arguments et registres
Résumé très simplifié de l'AAPCS (ARM Architecture Procedure Call Standard) :
arguments : les premiers sont passés dans R0 à R3, les suivants dans la pile si nécessaire
(les arguments de 64 bits peuvent être passés dans 2 registres consécutifs)
valeur de retour : elle est passée dans R0
(ou R0 et R1 si 64 bits)
registres dont le contenu doit être préservé : R4 à R11, SP et LR
Par conséquent, dans le corps d'une fonction :
R0 à R3 et R12 peuvent être utilisés librement comme stockage temporaire entre les appels de fonctions, par contre leur contenu rsique d'être
altéré par les fonctions appelées,
R4 à R11 peuvent être utilisés comme stockage temporaire à condition de les sauvegarder (push) pour les restituer (pop) avant le retour,
LR doit être sauvegardé si la fonction doit en appeler une autre,
SP doit être restitué dans son état initial, en particulier tout ce qui a été empilé doit être dépilé avant le retour.
4. Directives d'assemblage
RealView (Keil)
Entête
Commentaire
as (GNU)
thumb
; ... fin de ligne
.syntax unified
.arch armv7-m
.cpu cortex-m3
.thumb
;@ ...fin de ligne
/* ou comme en C */
Inclusion de fichier
include myfile
.include
Sections
area
area
area
.text
.section
.section
moncode,code,readonly
mesdata,data,readonly
maram,data,readwrite
align
Alignement
monlabel
Création label
Création constante maconst equ 0x1234
Donnée initialisée
dcd
dcw
dcb
Export
export myfunc
Import
Procédure
(pour le debugger)
Fin
0x1234abcd
0x1234
0x12
extern hisfunc
import hisfunc
myfunc proc
myfile
.align
monlabel:
maconst = 0x1234
.long 0x1234abcd
.short 0x1234
.byte 0x12
.global myfunc
.func myfunc
endp
end
.end
Attention : avec l'assembleur GNU as :
les directives commencent par un point '.'
les labels doivent avoir un ':' à l'endroit de leur création, mais pas lorsqu'on y fait référence.
file:///F:/memo_cm3.html
6/6
Téléchargement