polycope tp - 3

6
TP3 Exemple de jeu d’instruction du processeur C6x Manipulation N°1 : appel d’une fonction en assembleur à partir d’un programme en C Calcul de la somme de n + (n - 1) + (n - 2) + . . . + 1 Cet exemple illustre la possibilité d’exécuter une fonction écrite en assembleur à partir d’un programme en C. Le programme sum.c fait appel à la fonction sumfunc.asm //sum.c - calcul de la somme n+(n-1)+...+1. Appel de la fonction sumfunc.asm #include <stdio.h> main() { short n=6; short resultat; resultat = sumfunc(n); //appel de la fonction en assembleur sumfunc printf(―somme = %d‖, resultat); } ;sumfunc.asm fonction assembleur pour la calcul de n+(n-1)+...+1 .def _sumfunc ;fonction appelée depuis le prog. en C _sumfunc: MV .L1 A4,A1 ;compteur (n) dans A1 SUB .S1 A1,1,A1 ;décrémentation de n LOOP: ADD .L1 A4,A1,A4 ;addition et accumulation dans A4 SUB .S1 A1,1,A1 ;décrémentation du compteur [A1] B .S2 LOOP ;branchement à LOOP si A1#0 NOP 5 ;5 NOPs pour le délai associé à B B .S2 B3 ;retour à la routine d’appel (C) NOP 5 ;5 NOPs pour le délai associé à B .end Dans le programme sumfunc.asm la valeur de n, spécifiée dans le programme en C, est passée au programme assembleur à l’aide du registre A4 (par convention). Pour faire passer plus de valeurs il est possible d’utiliser d’autres registres A4, B4, A6, … . Le nom de la fonction est précédé par le symbole ‘_’ par convention (seulement si la fonction est appelée à partir d’un programme en C). La valeur de n, placée dans le registre A4, est ensuite déplacée dans le registre A1 (Instruction MV, A1 jouera le rôle du compteur). Le registre A1 est ensuite décrémenté (SUB). La boucle du programme commence avec le label (ou adresse) LOOP et

Upload: arctanx

Post on 22-Oct-2015

42 views

Category:

Documents


6 download

DESCRIPTION

DSP

TRANSCRIPT

Page 1: Polycope TP - 3

TP3 – Exemple de jeu d’instruction du processeur C6x

Manipulation N°1 : appel d’une fonction en assembleur à partir d’un programme en C

Calcul de la somme de n + (n - 1) + (n - 2) + . . . + 1

Cet exemple illustre la possibilité d’exécuter une fonction écrite en assembleur à partir d’un programme en C. Le programme sum.c fait appel à la fonction sumfunc.asm //sum.c - calcul de la somme n+(n-1)+...+1. Appel de la fonction sumfunc.asm

#include <stdio.h>

main()

{

short n=6;

short resultat;

resultat = sumfunc(n); //appel de la fonction en assembleur sumfunc

printf(―somme = %d‖, resultat);

}

;sumfunc.asm fonction assembleur pour la calcul de n+(n-1)+...+1

.def _sumfunc ;fonction appelée depuis le prog. en C

_sumfunc: MV .L1 A4,A1 ;compteur (n) dans A1

SUB .S1 A1,1,A1 ;décrémentation de n

LOOP: ADD .L1 A4,A1,A4 ;addition et accumulation dans A4

SUB .S1 A1,1,A1 ;décrémentation du compteur

[A1] B .S2 LOOP ;branchement à LOOP si A1#0

NOP 5 ;5 NOPs pour le délai associé à B

B .S2 B3 ;retour à la routine d’appel (C)

NOP 5 ;5 NOPs pour le délai associé à B

.end

Dans le programme sumfunc.asm la valeur de n, spécifiée dans le programme en C, est passée au programme assembleur à l’aide du registre A4 (par convention). Pour faire passer plus de valeurs il est possible d’utiliser d’autres registres A4, B4, A6, … . Le nom de la fonction est précédé par le symbole ‘_’ par convention (seulement si la fonction est appelée à partir d’un programme en C). La valeur de n, placée dans le registre A4, est ensuite déplacée dans le registre A1 (Instruction MV, A1 jouera le rôle du compteur). Le registre A1 est ensuite décrémenté (SUB). La boucle du programme commence avec le label (ou adresse) LOOP et

Page 2: Polycope TP - 3

Page 2 sur 6

termine avec la première instruction de branchement B. Cette boucle inclut deux instructions, ADD pour le calcul de la somme et SUB pour la décrémentation du compteur. La condition de branchement sur la boucle ne se fait que si la donnée dans le registre A1 est différentes de zéro ([A1] B). A noter que seuls les registres A1, A2, B0, B1 et B2 peuvent être utilisés comme registre conditionnel. La seconde instruction de branchement sert au retour à l’adresse B3 (par convention) du programme en C. Le résultat de la somme est contenu dans le registre A4 et est passé à la variable « resultat » du programme C. Les 5 NOPs (no operation) suivent les deux instructions de branchement et permettent d’insérer 5 délais associé à cette instruction. Les unités .S et .L sélectionnées sont données à titre indicatif mais ne sont pas nécessaires dans ce programme (elles peuvent être utilisées pour le débogage du programme). Compiler et exécuter le programme

Ajouter aux deux fichiers précédents les fichiers suivants o csl6713.lib o dsk6713bsl.lib o rts6700.lib o c6713dsk.cmd (dossier support)

utiliser les options de compilation standards

Calcul du factoriel de n

Les deux programmes factoriel.c et factfunc.asm calculent le factoriel d’un nombre n //factoriel.c : calcul du factoriel de n. appel de la fonction factfunc.asm

#include <stdio.h> //pour l’affichage

void main()

{

short n=7;

short resultat;

resultat = factfunc(n); // appel de la fonction en assembleur sumfunc factfunc

printf(―factoriel = %d‖, resultat);

}

;factfunc.asm – fonction assembleur appelée depuis le programme C

.def _factfunc ;fonction asm appelée depuis le prog. C

_factfunc: MV A4,A1 ;compteur (n) dans A1

SUB A1,1,A1 ; décrémentation de n

LOOP: MPY A4,A1,A4 ;produit et accumulation dans A4

;(A4xA1->A4)

NOP ;délai de 1 associé avec MPY

SUB A1,1,A1 ;décrémentation du compteur

[A1] B LOOP ;branchement à LOOP si A1#0

Page 3: Polycope TP - 3

Page 3 sur 6

NOP 5 ;5 NOPs pour le délai associé à B

B B3 ;retour à la routine d’appel (C)

NOP 5 ;5 NOPs pour le délai associé à B

.end

Tester le programme. Utiliser les mêmes indications que pour le premier exemple (fichiers à ajouter et options de compilation)

Programme assembleur appelant un autre programme assembleur

Le projet suivant permet de calculer la somme de produit de deux vecteurs x,y (ici x=[1 2 3 4] et y=[0 2 4 6] soit 1*0 + 2*2 + 3*4 + 4*6 = 40) ;sommeproduit_init.asm - programme ASM pour l’initialisation des

;des variables. Appel le fichier spfunc.asm

.def init ;adresse de début

.ref spfunc ;fonction ASM appelée

.text ;réserve une section de la mémoire pour

;le code

x_addr .short 1,2,3,4 ;valeurs pour le vecteur x

y_addr .short 0,2,4,6 ;valeurs pour le vecteur y

result_addr .short 0 ;initialise le résultat

init MVK result_addr,A4 ;A4 = lower 16-bit addr -->A4

MVKH result_addr,A4 ;A4 = higher 16-bit addr-->A4

MVK 0,A3 ;A3 = 0

STH A3,*A4 ;initialise le résultat à 0

MVK x_addr,A4 ;A4 = 16 LSBs adresse de x

MVK y_addr,B4 ;B4 = 16 LSBs adresse de y

MVKH y_addr,B4 ;B4 = 16 MSBs adresse de y

MVK 4,A6 ;A6 = taille des vecteurs

B spfunc ;branchement à la fonction spfunc

MVK ret_addr,B3 ;B3 = adresse retournée depuis spfunc

MVKH ret_addr,B3 ;B3 = adresse retournée depuis spfunc

NOP 3 ;3 délais (après branchement)

ret_addr MVK result_addr,A0 ;A0 = 16 LSBs result_addr

MVKH result_addr,A0 ;A0 = 16 MSBs result_addr

STW A4,*A0 ;store result

wait B wait ;pause

NOP 5 ;délai associé à l’instruction de

;branchement

;spfunc.asm – Multiplication de deux vecteurs. Appelée depuis

;sommeproduit_init.asm

;A4=adresse de x, B4=adresse de y, A6=conteur(taille des vecteurs)

;B3=adresse retournée

Page 4: Polycope TP - 3

Page 4 sur 6

.def spfunc ;la fonction somme des produits

.text ;inclus le code suivant dans la section

;text (c’est une directive pour le

; compilateur)

spfunc MV A6,A1 ;move compteur de boucle --> A1

ZERO A7 ;init A7 pour l’accumulation

loop LDH *A4++,A2 ;A2=adresse de x

LDH *B4++,B2 ;B2=adresse de y

NOP 4 ;4 délais pour LDH

MPY A2,B2,A3 ;A3 = x * y

NOP ;1 délai pour MPY

ADD A3,A7,A7 ;somme des produits dans A7

SUB A1,1,A1 ;décrémentation du compteur

[A1] B loop ;branchement à loop si A1#0

NOP 5 ;5 delais pour B

MV A7,A4 ;A4=resultat

B B3 ;retour à l’adresse dans B3 (ret_addr)

NOP 5 ;5 delais pour B

;vectors_sp.asm – fichier Vector pour le projet sommeproduit

.ref init ;adresse de début dans le fichier

;d’initialisation

.sect ―vectors‖ ;in section vectors

rst: mvkl .s2 init,b0 ;init addr 16 LSB ——>B0

mvkh .s2 init,b0 ;init addr 16 MSB ——>B0

b b0 ;branchement à addr init

nop 5

Créer un projet et ajoutez-y :

Les trois fichiers asm (sommeproduit_init.asm ; spfunc.asm et vectors_sp.asm

Le fichier c6713dsk.cmd (dossier support) Au niveau des options de compilation seule l’option suivante du linker doit être changée (pour ne pas avoir un warning)

Linker Basic Autoinit Model : No Autoinitialization

Compilez et testez le programme

Analyse du programme

Le programme assembleur « sommeproduit_init.asm » initialise les valeurs des vecteurs x et y et fait appel à la fonction assembleur « spfunc.asm », les adresses des vecteur x et y (x_addr et y_addr) ainsi que la taille des vecteurs sont envoyés à cette fonction grâce aux registres A4, B4 et A6. La fonction « spfunc » calcul la somme des produits de x et y et retourne à l’adresse indiquée dans le registre B3 (ce registre contient l’adresse de « ret_addr »). Le résultat du calcul (40) est stocké dans un premier temps dans le registre A4 puis la valeur est enregistrée dans la case mémoire indiquée par result_addr.

Page 5: Polycope TP - 3

Page 5 sur 6

Le programme « vectors_sp.asm » envoie à l’adresse du début de programme (l’adresse init du programme sommeproduit_init.asm), ceci se fait avec la commande de branchement « b » comme indiqué ci-dessous : mvkl .s2 init,b0

mvkh .s2 init,b0

b b0

Pour un fonctionnement correcte le code du programme « vectors_sp.asm » doit être placé en début de la mémoire. La directive «.sect » indique justement où la fonction « rst » doit être placée, l’indication est dans l’opérande de cette directive, soit le terme « ―vectors‖ ». Le quatrième fichier de notre projet est le fichier C6713dsk.cmd, ce fichier comporte en fait des directives (MEMORY et SECTIONS (en majuscule)) au compilateur lui indiquant les plages mémoire disponibles. En retrouve dans ce fichier le terme ‘’vectors’’ qui fait référence à la plage mémoire IVECS (adresse de début 0h et de longueur 220 octets) /*C6713dsk.cmd Linker command file*/

MEMORY

{

IVECS: org = 0h, len = 0x220

IRAM: org = 0x00000220, len = 0x0002FDE0

SDRAM: org = 0x80000000, len = 0x01000000

FLASH: org = 0x90000000, len = 0x00020000

}

SECTIONS

{

.EXT_RAM :> SDRAM

.vectors :> IVECS

.text :> IRAM

.bss :> IRAM

.cinit :> IRAM

.stack :> IRAM

.sysmem :> IRAM

.const :> IRAM

.switch :> IRAM

.far :> IRAM

.cio :> IRAM

.csldata :> IRAM

}

Finalement la ligne, .sect ―vectors‖

indique tout simplement au compilateur (c’est une directive) que le code qui vient après, soit : rst: mvkl .s2 init,b0

Page 6: Polycope TP - 3

Page 6 sur 6

mvkh .s2 init,b0

b b0

nop 5

doit être placé en début de mémoire de sorte qu’à l’exécution (lecture du code à partir de l’adresse 0h) le branchement à init ce fait. Comme le programme n’affiche aucun résultat (pas d’instruction printf !) il est nécessaire de vérifier le bon fonctionnement de notre programme directement en lisant les valeurs dans les registres et les cases mémoire utilisées. Pour ce faire, procédé comme suit :

1. Visualisation des valeurs des différents registres a. Allez au menu « View » puis « Registers » puis sélectionnez « Core Registers » b. Sinon cliquez sur l’icône « Register Window » (à gauche)

2. Visualisation des adresses mémoires utilisées a. Allez au menu « View » puis « Memory » b. Dans la fenêtre qui apparaît (Memory Window Options)

i. Indiquez dans le champ « Title » la fonction « spfunc » ii. Pour « Format » : choisissez « 16-Bit Signed Int »

3. Vous pouvez visualiser le code assembleur généré par le compilateur en : a. Cliquant sur l’icône « View disassembly » b. Ou bien à partir du menu « View » puis « Disassembly »

Analysez les valeurs des différents registres ainsi que les données (et programmes) de la mémoire utilisée. Visualisez le code généré et vérifiez que le code :

rst: mvkl .s2 init,b0

est mis à l’adresse de début de mémoire « 0000 0000 », avec la valeur de init = 0000 0234 qui correspond à l’adresse de l’instruction :

init MVK result_addr,A4

Exercice

Concevez un programme en C qui fait appel à une fonction en assembleur pour le calcul du terme [a2 + (a+1)2 + (a+2)2 + … + (2a-1)2] – [b2 + (b+1)2 + (b+2)2 + … + (2b-1)2]. Le programme en C doit passer les valeurs de a et b au sous programme et afficher le résultat.