Le mips
This presentation is the property of its rightful owner.
Sponsored Links
1 / 140

Le MIPS PowerPoint PPT Presentation


  • 56 Views
  • Uploaded on
  • Presentation posted in: General

Le MIPS. Microprocesseur RISC débuts en 1985, gamme de processeurs : R2000 / R3000 / R4000 / R8000 / R10000 Équipe de nombreux types de machine Playstation, Nintendo 64, stations Silicon Graphics (dédiées à la 3D), société MIPS filiale de SGI machine à chargement/rangement

Download Presentation

Le MIPS

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Le mips

Le MIPS

Microprocesseur RISC

débuts en 1985, gamme de processeurs :

R2000 / R3000 / R4000 / R8000 / R10000

Équipe de nombreux types de machine

Playstation, Nintendo 64, stations Silicon Graphics (dédiées à la 3D), société MIPS filiale de SGI

machine à chargement/rangement

machine à registres généraux


Application de l approche risc

Application de l'approche RISC

Performances d'un processeur sur l'exécution de plusieurs instructions :

approche CISC : plusieurs cycles pour une instruction.

Instruction simple

Instruction complexe


Application de l approche risc1

Fetch instruction

Opération UAL

Accès Mémoire

Ecriture Résultat

Application de l'approche RISC

Utilisation intéressante du temps : instructions simples effectuées en peu de cycles, instructions complexes en plus de cycles (le nombre de cycles nécessaires).

Mais complique énormément une gestion de pipelines éventuels, car les instructions n'ont pas le même format ni la même séquence d'exécution.

Approche RISC : toute instruction s'exécute de manière similaire, en suivant un chemin de données bien défini : Fetch, UAL , Mémoire, Résultat.

cycle 1

cycle 2

cycle 3

cycle 4


Ex cution en pipeline

Exécution en pipeline

Amélioration potentielle du nombre d'instructions par cycle en utilisant un pipeline :

chaque cycle de l'instruction utilise une partie du processeur. A chaque cycle, on choisit de commencer le traitement d'une nouvelle instruction :

M

R

F

UAL

R

F

UAL

M

M

R

F

UAL

Flot d'instructions

R

F

UAL

M

cycle


Ex cution en pipeline1

4 cycles

8 cycles

8 cycles

12 cycles

4 cycles

8 cycles

Exécution en pipeline

Suppose que le pipeline contienne toujours des instructions utiles et qu'il n'y ait pas besoin de rajouter des cycles vides pour synchronisation.

Exemple d'un pipeline CISC, utilisé sur 6 instructions

En gris : utilisation exclusive d'une ressource, ici l'UAL.


Ex cution en pipeline2

Exécution en pipeline

Sans pipeline : en tout 44 cycles pour 6 instructions : 7,33 cycles/instruction. Avec pipeline : cycles de délai lorsqu'une ressource n'est pas utilisable, matérialisé par :

29 cycles


Ex cution en pipeline3

Exécution en pipeline

Avec pipeline, même s'il y a du remplissage : 29 cycles, soit 4,83 cycles/instruction .

Gain contrebalancé par :

gestion du pipeline pour tenir compte des cycles vides, des instructions de longueur variable : compliqué

évènements qui perturbent le déroulement séquentiel du programme : sauts conditionnels, interruptions

compilateur a du mal à ordonner les instructions pour tirer le meilleur parti du pipeline.


Machine chargement rangement

Machine à chargement/rangement

Efficacité du découpage si les 4 phases F, UAL, M, R consomment une quantité de temps à peu près comparable.

Or les accès mémoire sont longs :

calcul de l'adresse, accéder aux opérandes en mémoire, les traiter, les ranger.

Choix d'une architecture à chargement/rangement (instructions LOAD et STORE). Seules ces instructions permettent un accès à la mémoire.

Gain en terme de bande passante (réduction des accès)

Jeu d'instructions plus simple

Optimisation de l'utilisation des registres par compilateur


Machine chargement rangement1

Machine à chargement/rangement

Chargement retardé (delayed LOAD).

Lors d'une opération de chargement, la donnée à charger dans un registre n'est pas disponible immédiatement pour l'instruction suivante si l'on utilise un pipeline :

Donnée chargée disponible comme opérande

LOAD

M

F

UAL

R

R

F

UAL

M

M

R

F

UAL

R

F

UAL

M


Machine chargement rangement2

Machine à chargement/rangement

Chargement retardé (delayed LOAD).

Solution : insérer des cycles d'attente lors de l'exécution de l'instruction 2, entre les phases F et UAL :

lors de la phase UAL, l'instruction 2 peut avoir besoin de la donnée de l'instruction 1.

Technique simple : faire apparaître cette dépendance au compilateur, toute instruction de chargement à un délai de latence de 1 cycle, qui correspond au début de traitement d'une nouvelle instruction.

L'instruction suivant une instruction de chargement est dite dans la fenêtre ou intervalle de retard de chargement.(Load delay slot)


Machine chargement rangement3

Machine à chargement/rangement

Si cela apparaît au niveau du compilateur : pas de dépendance dans le pipeline entre l'instruction de chargement et celle qui est dans son load delay slot.

Il existe une instruction qui n'a aucune dépendance avec les autres : NOP !

Pas besoin de faire un contrôle matériel du pipeline. Mais utilisation du NOP augmente la taille du code, augmente le délai d'exécution sans faire de tâche utile !

Autre solution : utiliser une instruction utile dans le load delay slot, optimisation faite par un compilateur.


Machine chargement rangement4

Machine à chargement/rangement

Exemple : code pour C=A+B; F=D

Load R1,A

Load R2,Bdans le load delay slot de Load R1,A : pas de dépendance

Add R3,R1,R2 dans le load delay slot de Load R2,B : dépendance à R2 : attente

Load R4,D

autre version :

Load R1,A

Load R2,Bdans le load delay slot de Load R1,A : pas de dépendance

Load R4,D dans le load delay slot de Load R2,B : pas de dépendance

Add R3,R1,R2 dans le load delay slot de Load R4,D : pas de dépendance


Branchements retard s

Branchements retardés

Les instructions de branchement/sauts introduisent aussi des délais dans le pipeline car il faut calculer l'adresse de destination avant de procéder à la phase F (Fetch) de l'instruction suivante.

Lorsqu'un accès à la mémoire d'instructions nécessite un cycle entier, et que l'instruction de saut correspondante indique l'adresse de destination, il est impossible de faire tout de suite la phase F de l'instruction suivante sans insérer un délai d'un cycle

SAUT

M

F

UAL

R

Branch delay slot

M

R

F

UAL

R

F

UAL

M

adresse trouvée disponible pour phase F suivante


Branchements retard s1

Branchements retardés

Les instructions de branchement conditionnels peuvent causer des retards supplémentaires : condition à évaluer.

Technique choisie : comme pour le chargement retardé, on exécute, dans le branch delay slot, une ou plusieurs instructions avant d'effectuer le saut.

Si cela n'est pas possible, insertion de NOPs, mais un compilateur est capable de réordonner des instructions pour remplir efficacement le branch delay slot.

On cherche à mettre dans ce branche delay slot une instruction écrite avant dans le programme assembleur, et qui ne présente pas de dépendance avec le saut.


Branchements retard s2

Branchements retardés

Illustration : programme avec saut

première version : avec branchements retardés explicitement

A:move s0,a0transfert de registre à registre

move s1,a1idem

addius0,s0,1addition s0 s0+1

beqs0,$0,SUITEsaut à suite si S0=0

nopbranch delay slot 'rempli' avec nop

B:move a0,s0

move a1,s1

SUITE: store A,t3autres instructions

syscall

jal FIN


Branchements retard s3

Branchements retardés

Illustration : programme avec saut

deuxième version : branch delay slot 'intelligemment rempli'

A:move s0,a0transfert de registre à registre

addius0,s0,1addition s0 s0+1

beqs0,$0,SUITEsaut à suite si S0=0

move s1,a1 branch delay slot avec instruction indépendante du saut et des valeurs testées par le saut.

B:move a0,s0

move a1,s1

SUITE: store A,t3autres instructions

syscall

jal FIN


Branchements retard s4

Branchements retardés

Souvent, une instruction qui se situe avant un branchement peut être exécuté après le début de traitement du branchement sans affecter la logique du programme ou le branchement lui-même.


Temps d acc s aux instructions

Temps d'accès aux instructions

Le temps nécessaire à accéder à une instruction dépend très largement du système physique de mémoire utilisé et devient le facteur limitant dans la conception des processeurs à cause de la vitesse à laquelle il est nécessaire de fournir des instructions au CPU.

Utilisation de caches mémoires pour accélérer ces traitements :

séparation en

cache pour les instructions : joue le rôle de mémoire d'instruction (schéma de contrôle du MIPS de l'année dernière)

cache pour les données : joue le rôle de mémoire de données


Temps d acc s aux instructions1

Temps d'accès aux instructions

CPU

@

données

Cache d'instructions

Cache de données

données

@

Mémoire principale


Le syst me de gestion de m moire

Le système de gestion de mémoire

Système de gestion de la mémoire de type MMU (Memory Management Unit) intégré au coprocesseur CP0 (contrôle, pas arithmétique)

selon le mode utilisé (utilisateur ou noyau), adresses référencées sont ou non traduites en adresses physiques à l'aide d'un TLB (buffer de traduction d'adresse virtuelle vers physique).

Invisible la plupart du temps pour le programmeur, mais une mauvaise utilisation d'adresses (mauvaises valeurs) peut provoquer des erreurs du TLB.

Ce ne sont pas des erreurs de bus ou d'alignement !


Le mips1

Le MIPS

Respecte entièrement la philosophie RISC

registres : 32 registres de 32 bits

instructions : toutes codées sur 32 bits, découpage cohérent pour un traitement rapide

registre PC et adresses codées sur 32 bits

la mémoire est adressable par octet, transferts de 8, 16 ou 32 bits possibles

mémoire maximale adressable : 232 octets = 22.210.210.210 octets = 4 Go


Le mips2

Le MIPS

Constitué de deux parties distinctes

le CPU :registres généraux

registres HI et LO

UAL

PC

le CP0 : processeur de contrôle système intégrant

TLB pour la gestion de mémoire virtuelle

registres de gestion mémoire

registres de traitement des exceptions

registres d'état


Le mips3

Le MIPS

Registres généraux :

nommage particulier :

$0 à $31

$0 : vaut toujours 0 (câblage)

$31 : utilisé par certaines instructions comme sauvegarde

ne pas utiliser $31 comme un registre général

autre convention de nommage, plus pertinente mais contredit le caractère général des registres


Format des instructions mips

Format des instructions MIPS

Toutes les instruction du R2000 sont des instructions 32 bit, et il y a 3 formats d'instruction différents, cela pour simplifier le décodage et utiliser un séquenceur câblé.

Les opérations plus complexes peuvent être simulées grâce à une suite d'instructions simples, on les trouvera sous la forme de pseudo-instructions.

Exemple : un transfert de registre à registre n'est pas implémenté, mais la pseudo-instruction move réalise cette opération.

Lorsque l'on écrit move Rsource,Rdest, en fait on réalise l'instruction MIPS : addRdest,Rsource,$0


Format des instructions mips1

Format des instructions MIPS

  • On distingue 3 formats d'instructions :

  • les instructions de type I : opérande de type valeur immédiate;

  • les instructions de type R, les opérandes sont des registres

  • les instructions de type J, (Jump, saut), l'opérande est l'adresse choisie

  • Ces formats ne correspondent pas aux différentes catégories d'instructions


Cat gories des instructions mips

Catégories des instructions MIPS

  • répartition en 6 catégories :

    • Load/Store

    • calculatoires : arithmétiques, logiques, décalages/rotations

    • sauts et branchements

    • instructions du coprocesseur arithmétique (R2010 FPA)

    • instructions du coprocesseur de contrôle CP0 (gestion de la mémoire virtuelle, gestion des interruptions et exceptions)

    • instructions spéciales : appels système, points d'arrêt


Retour sur les formats d instruction

Retour sur les formats d'instruction

Type I

op

rs

rt

immediate

Type J

op

target

Type R

op

rs

rt

rd

shamt

funct


Retour sur les formats d instruction1

Retour sur les formats d'instruction

Avec : op : opcode sur 6 bits

rs : n° de registre source sur 5 bits

rt : n° de registre de transit sur 5 bits

rd : n° de registre de destination sur 5 bits

immediate : valeur immédiate 16 bits

target : adresse cible sur 26 bits

shamt : valeur de décalage sur 5 bits (pour les instructions de décalage, rotations)

funct : champ de fonction sur 6 bits


Le langage assembleur

Le langage Assembleur

En fait, leS langageS d'assemblage. A chaque architecture son langage (dommage).

Produit le code réputé le plus efficace en rapidité d'exécution

proche de la machine (quoique…)

donc hélas éloigné du programmeur

productivité plus faible en assembleur qu'en C

code produit par les compilateurs de plus en plus sophistiqués.

Utilité pour certaines applications (temps réel)


Le langage assembleur1

Le langage Assembleur

Au départ : traduction quasi-directe en langage machine

(traduction 'à la main' en hexadécimal, en binaire, en trous ! avec des tables de conversion)

des programmes :

010101000011111101010101001001010101001001111010100011101010010101000101111010100000111111100001111100000101000000111111000000000000001101000011111000001

0x6461425b 0x64646120 0x73736572 0x206e6920 0x61746164 0x6174732f 0x72206b63 0x5d646165 0x20200020 0x7272455b 0x6920726f 0x7973206e

0x6c616373 0x00205d6c 0x425b2020 0x6b616572 0x6e696f70 0x00205d74 0x525b2020 0x72657365 0x20646576


Le langage assembleur2

Le langage Assembleur

Aujourd'hui, langage assembleur traduit en langage machine de manière plus complexe

une instruction assembleur : plusieurs instructions du microprocesseur

ex du MIPS :

0x3c011001 lui $1, 4097 [mess1] la $a0,mess1

0x34240016 ori $4, $1, 22 [mess1]

Instructions du microprocesseur

Instructions en assembleur

Code + opérandes en hexadécimal


Le langage assembleur3

Le langage Assembleur

Aujourd'hui, langage assembleur traduit en langage machine de manière plus complexe :

existence de pseudo-instructions (qui ne sont pas comprises par tous les assembleurs MIPS).

Piège pour l'évaluation de performances, en nombre de cycles/instructions :

cycles / instructions en langage machine, et non cycles / instructions en assembleur !

En général, pseudo-instructions très bien traduites : utilisation naturelle, pas de précaution à prendre pour leur emploi.


Le langage assembleur4

Le langage Assembleur

Pas de typage fort des données : emploi sans contrôle des octets ou groupes de 16 ou 32 bits selon les besoins

Pas de protection du code vis-à-vis des données :

localisation mémoire différente (explicite)

mais accès indifférent

code auto-modifiable

un programme peut écrire dans la zone mémoire où sont stockées ses instructions !

(très simple en MIPS !)


Le langage assembleur5

Le langage Assembleur

  • Connaissance du "modèle de la mémoire" du processeur ou de l'assembleur.

  • Attention aux différences possibles entre :

    • Simulation d'un processeur : interprétation du code binaire ou des instructions assembleur

    • Exécution du programme en code binaire sur une cible (processeur + carte)

  • Simulateur : tentation de faire plus simple que la réalité ! C'est le cas avec le MIPS !


Le langage assembleur6

Le langage Assembleur

Modèle de mémoire simplifié : segment de donnée (DATA) / segment de code (TEXT)

0x7fffffff

STACK

adresses

DYNAMIC (heap)

DATA

STATIC

0x10000000

TEXT

0x00400000

Réservé


Mod le des registres

Modèle des registres

Noms associé à un rôle que jouent les registres lors de programmes comportant plusieurs langages source (C et ASM le plus souvent)

noms normaux noms conventionnelsremarque

$0$0vaut 0

$1$atne pas utiliser

$2 - $3$v0 - $v1 valeur de retour de procédures

$4 … $7$a0 … $a3 4 premiers arguments de fonctions

$8 .. $15 et $24,$25$t0 … $t9valeurs temporaires

$16-$23$s0 … $s9ne doivent pas être modifiés par fonctions

$26 - $27$k0 - $k1ne pas utiliser

$28$gppointeur global : accès valeurs statiques

$29$sppointeur de pile

$30$fppointeur de haut de zone de pile (frame)

$31$rane pas utiliser


Mod les des registres

Modèles des registres

En pratique : utiliser, pour des programmes simples :

$0, $v0, $v1, $a0 … $a3, $t0 … $t9 (16 registres)

Modes d'utilisation :

mode utilisateur (ou U / User)

mode noyau (ou K / Kernel)

protection de ressources, accès au mode noyau facile cependant !

Modèle mémoire différent selon le mode

U : 2 Go

K : jusqu'à 4 Go


Forme d un programme

Forme d'un programme

  • Un programme en assembleur est constitué d'instructions et de directives

    • Instruction :ordre donné au processeur pour effectuer une action lors de l'exécution du programme

    • Directive :ordre donné à l'assembleur pour préparer la traduction du code source en langage machine


Forme d un programme1

Forme d'un programme

Exemples d'instructions :

addu$t0,$t1,$t6effectue $t0  $t1+$t6 (registres)

j$raeffectue : saut à l'adresse donnée par $ra

bgezal$s4,destinationcompliquée !

exemple de directives :

.textindique que les lignes suivantes seront rangées dans le segment TEXT

.dataindique que les lignes suivantes seront rangées dans le segment DATA

.byte 6stocke la valeur 6 dans un octet de la mémoire


Crire un programme

Écrire un programme

Exemple avec un programme affichant "hello world !"

.data

hello:.asciiz "hello world\n"

.text

.globl main

main:

li$v0,4

la$a0,hello

syscall

j $ra

directives

instructions

labels


Crire un programme1

Écrire un programme

Les lignes indispensables : programme minimal

.data (directive)segment de données

.text (directive)segment de programme

.globl main(directive)exportation du label 'main'

main:(label) repère de début de programme

j$ra(instruction)retour au système (fin du prog)

Données ajoutées dans le segment de données, instructions dans le segment de texte.


Crire un programme2

Écrire un programme

Choix de la zone mémoire à utiliser avec les directives .data et .text:

possibilité de préciser l'adresse de départ de la zone en l'ajoutant à la suite des directives .data ou .text

syntaxe :.dataadresse

.text adresse

équivalent de ORG en 68000, il est possible d'utiliser plusieurs directives .data ou plusieurs directives .text dans un même programme source en assembleur.

Par défaut : .data :adresse 0x10010000

.text:adresse 0x00400000


Quelques directives

Quelques directives

Mettre des valeurs dans la mémoire : principalement insérer des constantes, ou initialiser des "variables".

À utiliser dans le segment de données .data ! Ne sont pas des instructions exécutables la plupart du temps.

Principe : l'octet (les octets) situé(s) à une certaine adresse mémoire a la valeur précisée.

Syntaxe

.byteb1[,b2,…,bn] : stocke les valeurs 8 bits listées dans des octets consécutifs

.halfh1[,h2,…,hn] : stocke les valeurs 16 bits listées dans des octets consécutifs

.wordw1[,w2,…,wn] : stocke les valeurs 32 bits listées dans des mots consécutifs


Quelques directives1

Quelques directives

  • .floatf1[,f2,…,fn] : stocke les valeurs float (32 bits) listées dans des mots consécutifs

  • .double d1[,d2,…,dn] : stocke les valeurs float (32 bits) listées dans des mots consécutifs

  • .ascii[z]"chaîne":stocke les codes ascii des caractères de la chaîne en mémoire à des adresses consécutives. Stocke un 0 à la fin si asciiz est employé.

  • Notations : utilisation de constantes numériques

    • notation en base 10 par défaut, avec signe possible

    • notation en base 16 possible en faisant précéder le nombre de '0x', nombre non signés en hexadécimal !


Directives de remplissage de ram

Directives de remplissage de RAM

Exemples

.data

.byte0xff,

.byte0x3e, 12,-5

donnera en mémoire, avec la présentation utilisée par le simulateur (attention, les PC sont des machines petit-boutistes !)

[0x10010000]0xfb0c3eff 0x00000000 0x00000000 0x00000000

Mots de 32 bits

adresse


Directives de remplissage de ram1

Directives de remplissage de RAM

Exemples

.data

.half0xa5a5,0xb6b7

donnera en mémoire, avec la présentation utilisée par le simulateur (attention, les PC sont des machines petit-boutistes !)

[0x10010000]0xb6b7a5a5 0x00000000 0x00000000 0x00000000

Mots de 32 bits

adresse


Directives de remplissage de ram2

Directives de remplissage de RAM

Ces directives peuvent aussi préciser le nombre de fois où ces valeurs doivent être écrites en RAM.

Syntaxe :

.formatval1:nb1

écrit nb1 fois de suite la valeur val1 en RAM

Dans ce cas, on ne précisera qu'une seule valeur par ligne. (erreur du simulateur sinon)


Directives de remplissage de ram3

Directives de remplissage de RAM

exemple :

.data

.half0xa5a5:3

.half 0xb6b7

.byte12:3

.byte0xfb:2

donnera en mémoire :

[0x10010000]0xa5a5a5a5 0xb6b7a5a5 0xfb0c0c0c 0x000000fb


Les constantes virgule

Les constantes à virgule

Écriture des nombres en virgule flottante, formats .float et .double : on utilise une notation scientifique

exemples :

.data

.float1.1

.float-1.1e-24

donnera en mémoire

[0x10010000]0x3f8ccccd 0x97aa377d

ne pas utiliser de notation en hexadécimal pour les constantes à virgule : pour ces notations, utiliser .word

avec les constantes à virgule, on ne peut pas utiliser les répétitions de placement en mémoire.


R servation d octets

Réservation d'octets

La directive .space permet de "réserver" un certain nombre d'octets, comme le permettait la directive DS.B du 68000.

L'espace 'réservé' est rempli avec des 0.


Adresse courante labels directives

Adresse courante, labels, directives

La directive .data indique que les directives suivantes auront une action dans le segment de données. Avec le simulateur que nous utiliserons (PCspim), cela correspond à l'adresse 0x10010000.

Un label est un nom associé à l'adresse à laquelle la directive agit.

Exemple

.datatravail dans le segment de données. L'adresse courante est donc 0x10010000 (simulateur)

start_data :label, vaut l'adresse courante, donc 0x10010000

.half0x520b0x520b est écrit dans les octets 0x1001000 et 0x10010001 (en petit-boutiste), l'adresse courante devient 0x10010002

.byte5555 est écrit à l'adresse 0x10010002

l'adresse courante devient 0x10010003


Adresse courante labels directives1

Adresse courante, labels, directives

Il est possible d'associer un label à chaque directive, on n'est pas obligé d'utiliser un label dans un programme en assembleur.

Il n'y a pas de directives ORG ou END avec le langage d'assemblage du MIPS.


Instructions de base et exemples

Instructions de base et exemples

Instructions et pseudo-instructions de l'assembleur, et non du langage machine.

instructions de chargement LOAD :

LB[U]Load Byte [Unsigned]

lb / lbu : chargement de registre par une valeur contenue dans un octet.

Syntaxe :

lb[u]destination,adresse

l'octet contenu à l'adresse donnée par la deuxième opérande est étendu sur 32 bits puis rangé dans le registre de destination.


Instructions de base et exemples1

Instructions de base et exemples

Extension de la valeur 8 bits :

si l'instruction est lb :

extension de signe de 8 à 32 bits : les 24 bits restants du registre prennent la valeur du bit de signe de l'octet lu en mémoire

si l'instruction est lbu :

extension par zéro de 8 à 32 bits : les 24 bits restants du registre prennent la valeur 0.


Instructions de base et exemples2

Instructions de base et exemples

data

valeur1:

.byte1

.byte-1# ou .byte 0xff

.text

.globl main

main:

lb$t0,valeur1# valeur : 1

lb$t1,valeur1+1# valeur : -1 étendue

lbu$t2,valeur1# valeur : 1

lbu$t3,valeur1+1# valeur : -1 non étendue

li$v0,10

syscall

$t0 :00000001

$t1 :ffffffff

$t2 :00000001

$t3 :000000ff


Instructions de base et exemples3

Instructions de base et exemples

Instruction lh/lhu

syntaxe : lhdestination, adresse

même principe que l'instruction lb pour les extensions de signe, les valeurs transférées sont des valeurs 16 bits situées à des adresses paires.

En cas d'adressage à une adresse impaire pou lh/lhu : erreur d'adressage (exception), fait planter le programme

instruction lw : load word, chargement de 32 bits suivant le même principe

syntaxe : lwdestination, adresse

l'adresse donnée en opérande doit être multiple de 4.


Instructions de base et exemples4

Instructions de base et exemples

Instructions de chargement avec des valeurs non alignées en mémoire :

lwl : load word left : charge les x octets de plus haut numéro d'un mot mémoire dans les 24 bits de poids fort d'un registre.

lwr : load word right : charge les x octets de numéro le plus bas d'un mot mémoire dans l'octet de poids faible d'un registre.

Utilité : charger des mots non alignés en 2 étapes. La numérotation des octets lus en mémoire se fait en fonction de la représentation gros ou petit-boutiste de la machine concernée.


Instructions de base et exemples5

Instructions de base et exemples

Autres affectations qui ne sont pas des chargements (pas de référence en mémoire)

lui : load upper immediate

syntaxe : LUIdestination, immédiate (16 bits)

stocke la valeur immédiate 16 bit dans les 16 bits de poids fort du registre destination, les 16 bits de poids faible sont mis à 0.

Ex : lui$t0,0x1234

$t0

12

34

00

00


Instructions de base et exemples6

Instructions de base et exemples

Autres affectations qui ne sont pas des chargements (pas de référence en mémoire)

li : load immediate (pseudo-instruction)

syntaxe : LIdestination, immédiate (32 bits)

stocke la valeur immédiate 32 bits dans le registre destination

Ex:li$t4,0xfedcba98

réalisé par : lui : pour charger les 16 bits de poids fort du registre,

ori (OU logique avec une valeur immédiate) pour charger les 16 bits de poids faible du registre


Instructions de base et exemples7

Instructions de base et exemples

Autres affectations qui ne sont pas des chargements (pas de référence en mémoire)

la : load address (pseudo-instruction)

syntaxe : LAdestination,valeur d'une adresse (32 bits)

même pseudo-instruction que li : le but est d'initialiser un registre avec une valeur immédiate 32 bits qui est considérée, par le programmeur, comme une adresse : seule l'utilisation du registre

Le MIPS ne fait aucune différence !

Parallèle avec les instructions MOVE et MOVEA du 68000.


Adresses absolu ou indirect

Adresses : absolu ou indirect ?

Instructions de chargement avec adresses non détaillées :

on peut utiliser de l'adressage absolu ou de l'adressage indirect !

A priori, tous les registres (à l'exception de $0, qui est câblé à 0) peuvent servir de registre d'adresse pour accéder à une cellule mémoire.

Pour distinguer adressage absolu et adressage indirect : syntaxes différentes.


Adressage absolu

Adressage absolu

Pour les instructions de chargement, l'adressage absolu est utilisé lorsque l'adresse est donnée sous forme d'une constante numérique, au format décimal ou hexadécimal (précédé de 0x)

exemples :

lh$t0,0x1000

a pour effet de stocker dans le registre $t0 le mot (16 bits) située à l'adresse 0x1000 en mémoire (puisqu'il s'agit d'une partie de mot mémoire, attention à la représentation little endian ou big endian)

il est possible d'utiliser un label (de même qu'avec le 68000) pour réaliser un chargement en adressage absolu.


Adressage absolu1

Adressage absolu

Exemple :

.data

sample:

.half0xa5b4

.half0x1234

.text

.globlmain

main:

lh$t0,sample#compris comme lh $t0,0x10010000

lh$t1,sample+2#compris comme lh $t0,0x10010002

li$v0,10

syscall


Adressage indirect avec d placement

Adressage indirect avec déplacement

Pour les instructions de chargement, l'adressage indirect est utilisé lorsque l'adresse est donnée sous forme d'un registre noté entre parenthèses.

Exemple :

lhu$t0,($t1)

charge dans le registre $t0 le mot 16 bits (sans extension de signe) situé à l'adresse "pointée" par le registre $t1.

On peut faire précéder cette notation d'une constante numérique (notée en décimal ou en hexadécimal) indiquant un offset ou déplacement à appliquer au contenu du registre avant de lire la mémoire.

Il faut toujours que le registre utilisé comme registre d'adresse soit initialisé !


Adressage indirect avec d placement1

Adressage indirect avec déplacement

Exemples :

.data

samples:

.word0x12345678

.word0xfedbca98

.text

.globl main

main:

la$t1,samples# la : load address : adressage direct et immédiat

lw$t0,($t1)# lw : load word :adressage direct et indirect

lw$t2,4($t1)#lw : adressage direct et indirect avec déplacement

li$v0,10

syscall

le déplacement étant une constante numérique, il peut être remplacé par un label (qui sera traduit par l'assembleur en une valeur numérique)


Adressage indirect avec d placement2

Adressage indirect avec déplacement

  • Équivalent de la directive EQU du 68000

  • il est possible de définir des symboles non comme des adresses (labels), mais comme des constantes numériques, comme la directive EQU du 68000 ou le #define du langage C.

  • syntaxe :

    • symbole = expression

  • ou

    • symbole = registre

  • lorsque l'on veut renommer un registre pour des facilités de programmation.

  • Utile pour les décalages utilisés avec l'adressage indirect du MIPS.


Adressage indirect avec d placement3

Adressage indirect avec déplacement

Reprise de l'exemple précédent :

offset = 4

.data

samples:

.word0x12345678

.word0xfedbca98

.text

.globl main

main:

la$a1,samples# la : load address : adressage direct et immédiat

lw$t0,($a1)# lw : load word :adressage direct et indirect

lw$t2,offset($a1)

li$v0,10

syscall


Instructions de rangement

Instructions de rangement

Permettent de transférer le contenu de registres vers des octets, mots 16 bits ou mots 32 bits.

Instructions de base :

sb (store byte), sh, sw

syntaxe :

SB registre,adresse : concerne les 8 bits de poids faible du registre

SH registre, adresse : concerne les 16 bits de poids faible du registre

SW registre, adresse : concerne tout le registre

attention : la représentation little ou big endian ne concerne pas les registres, mais seulement les mots mémoire !


Instructions de rangement1

Instructions de rangement

L'alignement des adresses doit être respecté :

sb à toutes les adresses

sh seulement à des adresses paires

sw seulement à des adresse multiples de 4

dans le cas contraire : erreur d'adressage, le programme plante.

Il est possible, comme pour les chargements, d'utiliser l'adressage indirect avec déplacement (même syntaxe) pour ranger une valeur en mémoire.


Instructions de rangement2

Instructions de rangement

Exemple : ranger en mémoire, à l'adresse 0x2000, les 16 bits de poids faible du registre $t6.

On utilise les registres $t2 et $s3 comme registres d'adresse (on peut utiliser n'importe lequel, à l'exception de $0), pour montrer deux manières différentes d'arriver au même résultat

.text

.globl main

main:li$t6,0xfedcba98 # initialisation de $t6

la$s3,0x2000 # adressage direct et immédiat

la$t2,0x1000 # adressage direct et immédiat

sh$t6,($s3) # adressage direct et indirect

sh$t6,0x1000($t2) # adressage direct et indirect

j $ra


Instructions de rangement3

Instructions de rangement

Il n'est par contre pas possible de ranger en mémoire des valeurs immédiates avec une instruction. Pour cela, on utilisera 2 instructions :

chargement d'un registre avec la valeur immédiate concernée

rangement du contenu du registre en mémoire.

Il est possible, par contre de stocker 64 bits situés dans deux registres consécutifs grâce à la pseudo-instruction Store Doubleword.

Syntaxe : SD registre_n°_n,adresse

stocke les valeurs des registres numéro n et n+1 dans les cellules mémoires situées à l'adresse mentionnée.


Autres affectations

Autres affectations

Réalisation de transferts de registre à registre.

Syntaxe :

movedestination,source (pseudo-instruction)

transfère sur 32 bits le contenu du registre source vers le registre destination.

Réalisée en faisant une addition entre le registre source et le registre $0, addition dont le résultat est rangé dans le registre destination.

Autres instructions concernent les résultats d'opérations arithmétiques et logiques.


Instructions al

Instructions AL

En nombre entiers : utilisation de l'UAL du MIPS pour les opérations les plus courantes.

Rappel : opérations systématiquement réalisées entre registres, jamais d'adressage absolu ou indirect !

Prise de valeur absolue (au sens mathématique) :

syntaxe :absdestination,source (pseudo-instruction)

calcule la valeur absolue du registre source (à partir de la représentation signée en complément à 2) et la range dans le registre destination.


Instructions al1

Instructions AL

Additions : toujours entre trois registres, 2 registres source et un registre destination

addition avec ou sans prise en compte de l'overflow (équivalent du flag V de dépassement arithmétique)

syntaxe : adddestination,source1,source2

réalise : destination  source1+source2

syntaxe : addudestination,source1,source2

réalise : destination  source1+source2, overflow ignoré

l'oVerflow arithmétique, lorsqu'il apparaît, se traduit par la manifestation d'une exception (pas simplement le flag V) : traitement spécial !


Instructions al2

Instructions AL

Exemples :

.text

.globl main

main :

li$t0,0x40000000

li$t1,0x40000000

addu$t2,$t1,t0

#affichage 1

add$t2,$t1,$t0

#affichage 2

affichage 1 : 1073741824+1073741824 = -2147483648

affichage 2 : Exception 12 [Arithmetic overflow] occurred and ignored

1073741824+1073741824 = -2147483648

add provoque une exception : dans le simulateur, affichage d'un message (par le noyau) et poursuite du programme.


Instructions al3

Instructions AL

Addition avec des valeurs immédiates (16 bits).

Rappel : instruction codée sur 32 bits, donc pas de possibilité d'avoir des constantes (valeurs immédiates) sur 32 bits !

La valeur immédiate, codée sur 16 bits, est étendue sur 32 bits avec son signe, puis ajoutée à un registre source. Le résultat est stocké dans un registre destination. Un dépassement arithmétique peut se produire.

Syntaxe :

addi destination,source,immédiate

ou

addiu destination,source,immédiate

avec addiu, un éventuel dépassement est ignoré.


Instructions al4

Instructions AL

Soustraction : possible seulement avec des registres. Il faut utiliser l'addition (addi ou addiu) pour soustraire des valeurs immédiates.

Il en existe aussi deux versions, avec prise en compte ou non du dépassement.

Syntaxe :

sub destination,source1,source2

ou

subu destination,source,source2


Instructions al5

Instructions AL

Opérateurs logiques AND, OR, XOR, NOR

avec valeur immédiate : syntaxe

ANDI (ORI , XORI) destination, source, immédiate

effet : étend la valeur immédiate 16 bits avec des 0 sur 32 bits, puis effectue :

destination  source AND (OR, XOR) immédiate 32 bits

avec registres : syntaxe

AND (OR, XOR, NOR) destination, source1, source2

effectue :

destination  source1 AND (OR, XOR, NOR) source2


Instructions al6

Instructions AL

Exemples :

récupérer l'octet de poids faible du registre $t3 et le ranger dans le registre $t4

andi$t4,$t3,0x00ff

extension de 0x00ff en 0x000000ff, puis application de l'opérateur logique : $t4  $t3 AND 0x000000ff

réalisation du non logique : on utilise un XOR.

li$t0,-1# réalise : $t0  0xffffffff

li $t3,0xfedcba98

xor$t4,$t3,$t0


Instructions al7

Instructions AL

Les décalages de bits : Shitf Left/Right Logical/Arithmetic

décalages logiques ou arithmétiques de registres.

Décalage arithmétique effectué vers la droite seulement ! Car cette opération a un sens arithmétiquement : division entière par 2.

Nombre de décalages à faire : précisé par une valeur immédiate shamt pour SHift AMounT codée sur 5 bits (car 25 = 32, valeur maximale du décalage) ou par un registre (les 5 bits de poids faible du registre).

Lors des décalages logiques, les bits 'entrants' sont des 0.


Instructions al8

Instructions AL

Les décalages de bits : Shitf Left/Right Logical/Arithmetic

décalages logiques avec valeur immédiate 5 bits

SLL (SRL) destination,source,shamt

effectue : destination  source décalé de shamt bits

décalage logique avec registre, le décalage est Variable

SLLV (SRLV) destination,source,décalage

effectue : destination  source décalé de décalage bits


Instructions al9

Instructions AL

Exemples de décalages logiques :

.data

.text

.globl main

main:li$t0,-1

sll$t1,$t0,12

srl$t2,$t1,1

li$t4,6

srlv$t1,$t0,$t4

fin:li$v0,10

syscall


Instructions al10

Instructions AL

Décalages arithmétiques :

lors d'un décalage arithmétique à droite, les bits entrants sont égaux au bit de signe du registre à décaler

syntaxe :

SRAdestination, source, shamt

ou

SRAV destination, source, décalage

le traitement du bit entrant permet d'effectuer une division entière par 2 quel que soit le signe de la valeur traitée par décalage !


Instructions al11

Instructions AL

Multiplications, divisions : se font toujours entre registres, donc entre quantités 32 bits, peuvent donner des résultats sur 64 bits !

Utilisation de deux registres spéciaux : HI et LO, de 32 bits chacun.

Avec la multiplication : HI et LO contiennent le résultat sur 64 bits (HI : 32 bits de poids fort; LO : 32 bits de poids fiable du résultat)

Le division est traitée comme une division entière

HI contient le reste de la division

LO contient le quotient de cette division

possibilité de travailler avec des valeurs considérées comme signées ou non signées.


Instructions al12

Instructions AL

Multiplication :

MULTsource1,source2 : multiplication signée

MULTU source1,source2 : multiplication non signée

Division

DIVdividende,diviseur : division signée

DIVUdividende,diviseur : division non signée

les registres HI et LO ne sont pas des registres généraux, on peut cependant y accéder par des instructions spéciales réservées à cet effet.


Instructions al13

Instructions AL

Accès aux registres HI et LO :

possibilité de transferts de et vers HI et LO à partir des registres généraux du MIPS :

instructions :

Move To :MTHI/ MTLO et Move From : MFHI/MFLO

syntaxe :

MTHI (MTLO) source

effectue HI (LO)  source

MFHI (MFLO) destination

effectue : destination  HI (LO)


Instructions al14

Instructions AL

Exemple :

.data

.text

.globl main

main:li $t0,16# 0x10

li $t1,22# 0x16

multu $t0,$t1# HI contient 0, LO contient 0x160

divu $t1,$t0# HI contient 6, LO contient 1

mflo $t2# transfert de LO dans le registre $t2

fin:li$v0,10

syscall


Branchements

Branchements

Possibilités de branchements avec des instructions de type I, R ou J (J : Jump).

Adresse de destination de saut donnée par :

registre

immédiat 16 bits (décalage)

immédiat 26 bits (instructions de type J)

4 variantes pour cette instruction Jump


Branchements1

Branchements

Saut absolu à une adresse donnée sur 26 bits :

Jump, Jump And Link.

Syntaxe :

J target

JAL target

effet : saut à l'adresse spécifiée en opérande.

Transformation de cette opérande de 26 bits  32 bits : décalage de 2 bits vers la gauche, complétion des 4 bits de poids fort en recopiant ceux du registre PC.


Branchements2

Branchements

Instruction J : saut simple vers la destination spécifiée : équivalent de GOTO.

Instruction JAL : Link : lien avec l'instruction de saut. Possibilité de revenir à l'instruction suivante.

Principe : lorsqu'un saut est effectué, sauvegarde de l'adresse à laquelle se situe l'instruction suivante. Possibilité de sous-programme réutilisable à partir de plusieurs appels :

réalisation de fonctions.

Effet de JAL : sauvegarde de l'adresse de retour dans le registre $ra (qui est le registre $31).

Système simpliste et mal adapté aux fonctions.


Branchements3

Branchements

Saut avec registres :

JR rs: saut à l'adresse contenue dans le registre rs.

JALR rd, rs :saut à l'adresse contenue dans le registre rs. De plus, l'adresse de l'instruction suivante est placée dans le registre rd pour offrir une possibilité de retour de fonction/sous-programme.

Exemples : sauts avec Jump

.text

.globl main

main :j suite

fin :li $v0,10

syscall

suite :j fin


Branchements4

Branchements

Exemples (suite) : Jump And Link

.data

message :.asciiz "coucou"

.text

.globl main

main :la $a0,message

jal affiche

la $a0,message+2

jal affiche

li $v0,10

syscall

affiche:li $v0,4

syscall

jr $ra


Branchements5

Branchements

Exemples (suite) : Jump Register (sans link)

.data

message :.asciiz "coucou"

.text

.globl main

main :la $a0,message

la $a1,affiche

jr $a1

fin:li $v0,10

syscall

affiche:li $v0,4

syscall

la $a1,fin

jr $a1


Branchements6

Branchements

Exemples (suite) : Jump And Link register

.data

message :.asciiz "coucou"

.text

.globl main

main :la $a0,message

la $a1,affiche

jalr $a2,$a1

la $a0,message+2

jalr $a2,$a1

fin:li $v0,10

syscall

affiche:li $v0,4

syscall

jr $a2


Branchements7

Branchements

Sauts relatifs et sauts conditionnels : utilisation de l'instruction branch et de ses variantes.

La valeur du saut effectué correspond toujours à un offset ou décalage par rapport à la valeur du registre PC indiquant l'adresse de l'instruction en cours de traitement.

Peu d'instructions de branchement conditionnels (approche RISC), se basent sur deux tests : égalité et nullité.

6 instructions à retenir (6 codes de conditions pour les branchements)


Branchements8

Branchements

Branch on EQual :

BEQsource1,source2,offset

effectue :offset décalé de deux bits à gauche et étendu sur 32 bits

PC PC+offset si source1=source2

BNEsource1,source2,offset

effectue le saut si source1  source2

BLEZ source,offset : effectue le saut si source  0

BGTZ source,offset : effectue le saut si source  0

BLTZ source,offset : effectue le saut si source  0

BGEZsource,offset : effectue le saut si source  0


Branchements9

Branchements

Saut conditionnel et lien :

BGEZAL : BGEZ And Link (registre $ra)

BLTZAL :BLTZ And Link (registre $ra)

Réalisation de saut inconditionnel :

BEQ$0,$0,offset


Branchements10

Branchements

Réalisation de boucles avec les sauts conditionnels.

While condition

{

instructions

}

faite 0 fois ou plus, test de condition effectué avant instructions

se traduit par :

si condition fausse saut après la boucle

instructions

retour au test

instructions après la boucle


Branchements11

Branchements

Réalisation de boucles avec les sauts conditionnels.

i=1;

while (i<1000)

{

printf("%ld\n",i);

i=i+1;

}

faite 0 fois ou plus, test de condition effectué avant instructions

se traduit par :

li $t0,1

li $t1,1000

deb_bouc:

beq $t0,$t1,fin_bouc

# instructions d'affichage

addiu $t0,$t0,1

beq $0,$0,deb_bouc

fin_bouc:instructions après la boucle


Branchements12

Branchements

Idem pour do … while, la traduction ici est plus simple : si la condition est vraie, on retourne en début de boucle.

Instructions de boucle

si condition vraie retour au début de boucle

instructions après la boucle

La traduction d'une boucle for se fait en notant qu'une boucle for est strictement équivalente à une boucle while : on reprend donc la traduction de la première boule while.


Appels syscall

Appels SYSCALL

Sur le simulateur : mini système d'exploitation permettant d'appeler des services 'minimaux' pour les entrées/sorties de base : affichages et saisies.

Il faut sélectionner le service que le système va rendre et indiquer les éventuels paramètres à fournir, appeler le système, puis éventuellement récupérer le résultat.

Principe : le registre $v0 doit contenir le numéro du service. Selon la valeur de $v0, c'est une saisie ou un affichage qui sera fait; avec un certain format de données : entier, nombre à virgule, chaîne de caractères.


Appels syscall1

Appels SYSCALL

Opération effectuéeServicecode d’appelargumentsretour

Afficher un entierprint_int1$a0 : entier

Afficher un floatprint_float2$f12 : float

Afficher un doubleprint_double3$f12 : double

Afficher une chaîneprint_string4$a0 : chaîne

Saisir un intread_int5Entier dans $v0

Saisir un floatread_float6Float dans $f0

Saisir un doubleread_double7Double dans $f0

Saisir une chaîneread_string8$a0 : buffer, $a1 :longueur

Allocation dynamiquesbrk9$a0 : nb d’octets Adresse de la zone dans $v0

Fin de programmeexit10


Exemples syscall

exemples SYSCALL

Exemple : affichage

.data

hello:.asciiz "hello\n" # asciiz ajoute un octet nul en mémoire pour repérer la fin de chaîne

.text

.globl main

main:

li$v0,4# code : affiche une chaîne

la$a0,hello# $a0 pointe sur le début de chaîne

syscall# appel système : demande d'affichage de chaîne

jr $ra

autre exemple : fin de programme

li$v0,10# code : exit

syscall# appel système : demande de fin de programme


Affichage en hexa

Affichage en HEXA

Exemple : affichage en hexa : conversion

.data 0x10010100

donnee:.word0xfedcba98# valeur exemple numéro 1

.word0x0000af04 # valeur exemple numéro 2

str_hex:.ascii "0x"# début de la chaîne a afficher après conversion

.space 8

.byte0

.align 2

converts:.ascii "0123456789ABCDEF"

.text

.globl main

main:lw$a0,donnee

li$v0,1

syscall

jalconvert

la$a0,str_hex

li $v0,4

syscall

li $v0,10

syscall


Affichage en hexa1

Affichage en HEXA

convert :

addi $sp,$sp,-4# déplacer pointeur de pile

sw $ra,($sp)# empilement adresse de retour

lw$t0,donnee+4# $t0 contient la donnée à convertir

la$a0,str_hex+9# pointeur sur la zone à remplir avec les caractères hexa

la$a1,converts# pointeur sur la zone contenant les caractères de conversion

li$t2,16# valeur du diviseur pour convertir en base 16

li$t5,8# compte le nombre de chiffres restant à traiter

bouc_chif:

beq$t5,$0,fin_conv# est-on en fin de boucle ?

divu$t0,$t2# division par 16

mfhi$t1# t1 contient le reste (à afficher)

mflo$t0# to contient le quotient à traiter

addu$a2,$a1,$t1# $a2 pointe sur le caractère voulu

lbu$t3,($a2)# récupéré dans $t3

sb$t3,($a0)# et mis dans la chaîne

addu$a0,$a0,-1# on pointe l'octet précédent de la chaîne

addiu$t5,$t5,-1# décrémentation $t5

jbouc_chif# retour début de boucle

fin_conv:

lw $ra,($sp)# dépilement adresse de retour

addi $sp, $sp,4# incrémentation du pointeur de pile

jr $ra# retour à l'appelant


Programmation de la fpu cp1

Programmation de la FPU (CP1)

Accès aux registres en virgule flottante

FPU : Floating Point Unit : unité en virgule flottante, appelé aussi coprocesseur mathématique : possible de lui faire réaliser des opérations complexes.

Philosophie RISC : ne pas compliquer la tâche du CPU (processeur 'principal'), préférence pour utilisation d'instructions d'interfaçage avec des coprocesseurs.

Le coprocesseur arithmétique dispose de 32 registres 32 bits pouvant stocker chacun une valeur au format float.

Peuvent aussi être utilisés comme 16 registres 64 bits pour stocker des doubles.


Programmation de la fpu

Programmation de la FPU

FPU aussi appelée CP1, coprocesseur anonyme dont on manipule les registres en faisant des transferts grâce à des instructions spécialisées du MIPS :

chargement / rangement vers les registres de la FPU

transferts entre registres du CPU et registres de la FPU

appels à des calculs de la FPU (add, sub, mul, div)

note sur la présentation : les instructions spécifiques aux coprocesseurs ne précisent pas le numéro du coprocesseur choisi. Syntaxe de la forme :

OPCODEz, avec z à remplacer par 1 pour la FPU que nous utilisons. Il peut y avoir plusieurs FPUs !


Programmation de la fpu1

Programmation de la FPU

Accès aux registres de la FPU :

32 registres 32 bits stockant chacun une valeur float, ce format est aussi nommé s pour Single precision

groupés par 2 pour 16 valeurs au format double, ce format est aussi nommé d.

registres accessibles par leur numéro, précédé d'un $f (parfois…)

exemple : $f0, $f17

Choix entre un registre du CPU et un registre de la FPU fait selon le contexte : on utilise des instructions spéciales (opcodes dédiés à ces instructions) : l'assembleur sait quel registre choisir.


Programmation de la fpu2

Programmation de la FPU

Exemples avec transferts :

instructions :

MTCz source,dest

Move To Coprocessor z (z précise le numéro du coprocesseur)

source : registre du CPU

dest : registre de la FPU

MFCz dest, source

dest : registre du CPU

source : registre de la FPU


Affichage de pi

Affichage de PI

Application : affichage d'un nombre en virgule flottante, on choisit la valeur 3.141592654 stockée en mémoire à une certaine adresse.

Regarder la description du service système associé :

Afficher un floatprint_float2$f12 : float

donc il faut ranger la valeur à afficher dans le registre $12 de la FPU.

Exemple avec deux stratégies :

a)charger cette valeur dans un registre du CPU, le transférer dans le registre $12 de la FPU puis faire l'appel système correspondant

b)charger cette valeur directement dans le registre $12 de la FPU, puis faire l'appel système correspondant.


Affichage de pi1

Affichage de PI

.data

valeur_pi:.float 3.141592654

.text

.globl main

stratégie a)

main:la $a0,valeur_pi# $a0 pointe sur le mot contenant la valeur

lw$t0,($a0)# récupération de la valeur

mtc1$t0,$f12# transfert

li$v0,2

syscall

j $ra

pour la stratégie b), il faut employer de nouvelles instructions : chargement vers registres de la FPU, rangements depuis registres de la FPU


Affichage de pi2

Affichage de PI

LWCzregistre,adresse

charge le registre de la FPU avec le mot situé à l'adresse fournie.

SWCz registre,adresse

range la valeur du registre de la FPU à l'adresse fournie

stratégie b)

main:la$a0,valeur_pi

lwc1$f12,($a0)

li$v0,2

syscall

j $ra


Op rations avec la fpu

Opérations avec la FPU

Utilisation pour des calculs en virgule flottante : instructions spécifiques, avec :

un opcode

un format (s ou d)

des opérandes

programme exemple : calcul du périmètre d'un cercle dont le rayon est saisi par l'utilisateur.

Algorithme :afficher texte d'accueil

saisir la valeur du rayon R

faire la calcul de 2*PI*R avec la FPU

afficher le résultat (avec un message)


Op rations avec la fpu1

Opérations avec la FPU

.data

valeur_pi:.float 3.141592654

const_R:.float 2.0

text_acc:.asciiz"Entrez le rayon:"

text_res:.asciiz "périmètre du cercle :"

.text

.globl main

main:la$a0,text_acc

jalaff_text

li $v0,6

syscall

la$a0,valeur_pi

lwc1$f1,($a0)

lwc1$f2,4($a0)

mul.s$f12,$f0,$f1

mul.s$f12,$f12,$f2

la$a0,text_res

jalaff_text

li$v0,2

syscall

li $v0,10

syscall

aff_text:

li $v0,4

syscall

j $ra


Autres instructions de la fpu

Autres instructions de la FPU

ABS.fmt dest,source: valeur absolue

ADD.fmtdest,source1,source2 : addition

SUB.fmtdest,source1,source2 : soustraction dest <- source1-source2

DIV.fmtdest,source1,source2 : division dest <- source1/source2

MOV.fmtdest,source : transfert de registres


Les appels aux sous programmes

Les appels aux sous-programmes

Avec le programme précédent : problème avec les appels aux sous-programmes.

On doit absolument terminer le programme avec les instructions

li$v0,10

syscall

plutôt qu'en utilisant l'instruction

jr $ra (ou j $ra)

sinon…le programme affiche tout le temps le résultat du calcul, c'est une boucle sans fin !

explication :

le simulateur utilise un morceau de programme pour interfacer l'assembleur avec le langage C, et appelle le programme principal (label main).


Les appels aux sous programmes1

Les appels aux sous-programmes

Principe de l'appel de sous-programme :

au moment de l'appel, sauvegarde de l'adresse où reprendre, avec l'instruction jal (Jump And Link), cette sauvegarde s'effectue dans le registre $31 (nommé aussi $ra).

Forme d'un programme :

0x00400000 : instructions insérées par le simulateur

0x00400014 : appel au prog : jal main

0x00400018 : nop

0x0040001c : li $v0,10

0x00400020 : syscall


Les appels aux sous programmes2

Les appels aux sous-programmes

0x00400000 : instructions insérées par le simulateur

0x00400014 : appel au prog : jal main

sauvegarde de l'adresse 0x00400018 dans le registre $ra

0x00400018 : nop

0x0040001c : li $v0,10

0x00400020 : syscall

0x00400024 : main: instructions du programme

0x0040???? : jal $ra : retour, saut à l'adresse sauvée dans $ra

donc ici, retour à 0x00400018

problème si on effectue dans le programme un autre saut avec l'instructions JAL : la valeur de $ra est effacée ! Pas de retour possible pour terminer le programme, il faut donc utiliser le service système exit. (syscall avec $v0=10)

0x00400018

$31 ($ra)


Les appels aux sous programmes3

Les appels aux sous-programmes

Autres solutions prévues : préciser le registre dans lequel on sauvegarde la valeur de retour lors d'un saut (appel)

instructions JALR

deux syntaxes :

JALR registre : saut à l'adresse donnée par le registre, adresse de retour sauvegardée dans $ra

JALR registre de lien, registre de saut : saut à l'adresse donnée par le registre de saut, sauvegarde de l'adresse de retour dans le registre de lien

problème là encore d'utilisation de registres : ils ne doivent pas être modifiés, or les registres sont équivalents à des variables globales...


Les appels aux sous programmes4

Les appels aux sous-programmes

Il faudrait sauvegarder l'adresse de retour avec chaque saut dans un espace temporaire.

il faudrait, pour revenir du sous-programme , restaurer l'adresse de retour.

Idée : utiliser la pile pour sauvegarder cette adresse.

On pourrait connaître cette adresse avant l'appel :

si une instruction d'appel (saut inconditionnel) se situe en mémoire à une certaine adresse, alors l'adresse de retour est celle de l'instruction suivante.

Lorsque l'on cherche à exécuter le saut : PC indique l'adresse de l'instruction de saut, donc il faut sauvegarder PC+4.

Problème : pas d'accès à ce registre PC avec le MIPS !


Les appels aux sous programmes5

Les appels aux sous-programmes

Mais on peut tout de même connaître cette adresse de retour une fois le saut effectué (avec la bonne instruction) dès que le sous-programme commence à s'exécuter (en fait dès que l'instruction de saut est terminée).

Si on utilise l'instruction JAL pour effectuer le saut, alors l'adresse de retour est stockée dans le registre $ra. Il suffit alors d'empiler cette adresse.

Juste avant de revenir au programme appelant le sous-programme en cours d'exécution, il suffit de dépiler cette valeur de $ra et de faire un saut à cette adresse avec l'instruction jr $ra (ou j $ra).


Gestion de la pile

Gestion de la pile

Illustration avec le programme précédent : en début de programme : empiler $ra (cela permet qu'il soit maintenant écrasé, par l'utilisation d'un autre JAL, mais qu'on puisse le récupérer), appeler un sous-programme d'affichage, qui utilise $ra.

A la fin du programme : dépiler $ra (on récupère sa valeur de début de programme), et rendre proprement la main au système.

Accès à la pile simple, grâce à un registre qui est prévu à cet effet :

c'est le registre $sp ($29 pour l'assembleur).

Pas obligatoire, possibilité d'avoir une autre pile, une pile est juste une zone de mémoire !

Zone de pile du MIPS gérée en 'descendant' dans la mémoire.


Gestion de la pile1

Gestion de la pile

Empiler et dépiler : (par analogie avec le 68000)

lorsqu'on empile une valeur (le plus souvent 32 bits), il faut :

mettre à jour le pointeur de pile $sp : décrémenter sa valeur de 4 octets, afin qu'il ait de la place pour accueillir la valeur sauvegardée

transférer la valeur voulue à l'adresse contenue dans $sp

illustration : pour sauvegarder $ra:

addi$sp,$sp,-4# $sp  $sp-4

sw$ra,($sp)# store word $ra par adressage indirect

répéter ces deux lignes au début de chaque prog/sous-prog


Gestion de la pile2

Gestion de la pile

Empiler et dépiler : (par analogie avec le 68000)

lorsque l'on dépile une valeur :

transférer la valeur depuis la pile vers le registre concerné

incrémenter le pointeur de pile pour 4 octets (si la valeur restaurée est 32 bits)

illustration avec restauration de $ra :

lw$ra,($sp)# load word $ra par adressage indirect

addi$sp,$sp,4# $sp  $sp-4

système très souple et adaptable : valeurs autres que 32 bits, autres registre que $ra pour empiler/dépiler, autre registre que $sp pour utiliser une zone mémoire comme une pile, etc.


Gestion de la pile3

Gestion de la pile

Illustration complète de l'exemple choisi : progression du pointeur de pile et des valeurs sauvegardées.

Symbolisation de la zone de pile : en partant des adresse hautes (en bas de la zone), vers les adresse basses : permet d'empiler vers le 'haut' et dépiler vers le 'bas'. On symbolisera aussi le registre $ra.

Adresse de bas de zone

$sp

Taille en bits(8 ou 16 ou 32)


Exemple

Exemple

0x00400000 : instructions insérées par le simulateur

0x00400014 : appel au prog : jal main

0x00400018 : nop

0x0040001c : li $v0,10

0x00400020 : syscall

0x00400024 : main : addi $sp,$sp,-4# ici $ra contient 0x00400018

0x00400028 : sw $ra,($sp)

$sp

0x00400018

0x7fffeffc

32 bits

$ra

0x00400018


Exemple suite

Exemple (suite)

0x00400028 :la $a0,text_acc

0x0040002c: jal aff_text

0x00400030: li $v0,6

0x00400034: syscall

# calculs

$sp

0x00400018

0x7fffeffc

32 bits

$ra

0x00400030


Exemple suite1

Exemple (suite)

0x0040007c: aff_text:li $v0,4

0x00400080: syscall

0x00400084: j $ra

$sp

0x00400018

0x7fffeffc

32 bits

$ra

0x00400030


Exemple fin

Exemple (fin)

li$v0,2

syscall

lw $ra,($sp)

addi $sp,$sp,4

j $ra

0x00400018

0x7fffeffc

$sp

32 bits

$ra

0x00400018


Passage de param tres

Passage de paramètres

Structuration : pas de variables globales.

Utiliser des registres pour transmettre des valeurs : prendre le risque de modifications dans les sous-programmes !

Procéder en deux étapes :

a)rendre les sous-programmes transparents pour les registres vis-à-vis du programme ou sous-programme appelant.

Ex : un sous-prog A manipule les registres $t2,$v0,$s4,$a0 et $a2 : pas visible lors du saut par JAL.

Principe : le sous-programme 'sauvegarde' les valeurs des registres qu'il manipule après avoir sauvegardé son @ de retour.

Utilisation de la pile suivant le même principe.


Ind pendance des registres

Indépendance des registres

Ex du sous-programme A :

A:addi $sp,$sp,-4

sw$ra,($sp)

addi$sp,$sp,-4

sw$v0,($sp)

….

# manipulations des registres

lw$v0,($sp)

addi$sp,$sp,4

lw$ra,($sp)

addi$sp,$sp,4

jr $ra

Registres empilés dans l'ordre :

$ra, $v0, $t2, $s4, $a0, $a2

Registres dépilés dans l'ordre :

$ra, $v0, $t2, $s4, $a0, $a2


Ind pendance des registres1

Indépendance des registres

Illustration : soit le sous-programme FOO qui modifie le registre $v0.

.data

donnee : .word 35

.text

.globl main

main:li $v0,3lw $v0,($sp)

jal FOOaddi $sp,$sp,4

li $v0,10lw $ra,($sp)

syscalladdi $sp,$sp,4

jr $ra

FOO :addi $sp,$sp,-4

sw $ra,($sp)

addi $sp,$sp,-4

sw $v0,($sp)

lw $v0,donnee

syscall


Ind pendance des registres2

Indépendance des registres

Empilement 1

$sp

$ra

32 bits

Empilement 2

$sp

$v0

$ra

32 bits


Ind pendance des registres3

Indépendance des registres

Cas général

registre

$sp

1 cellule mémoire

par registre sauvegardé

registre

$ra

32 bits


Les param tres

Les paramètres

Etape b) : utiliser des paramètres et non des registres pour communiquer.

Ne dispense pas de l'étape a) car dans le sous-programme, il peut y avoir des calculs, des transferts, qui ne se font qu'avec des registres et non des 'variables' : les variables sont des cellules mémoires et donc peu manipulables avec le MIPS !

On utilise un espace de stockage temporaire pour stocker les paramètres (valeurs ou adresse) avant l'appel au sous-programme;

On récupère les paramètres (valeurs ou adresses) dans le sous-programme à partir de cet espace de stockage intermédiaire qui est partagé.

Cet espace = la pile.


Les param tres1

Les paramètres

Note : l'utilisation d'une pile n'est pas a priori limitée à la seule pile prévue par le système et pointée par le registre $sp. Méthode d'empilement/dépilement décrite avec $sp fonctionnne avec n'importe quel autre registre.

Passage par valeur/par adresse :

on appellera variable un octet, une valeur 16 bits ou un mot mémoire auquel on aura attribué un label. Un nom de variable, dans ce cas, n'est qu'un raccourci donnant une adresse.

Par extension, une déclaration de variable sera une directive de stockage précédée d'un label.


Les param tres2

Les paramètres

Exemples :

.data0x10010180

a:.space 4# espace de 4 octets nuls

b:.byte62# octet initialisé

on cherche à écrire un sous-programme qui stockera dans a la valeur de b+1, en choisissant que b soit passée par valeur et que a soit passée par adresse, car elle va être modifiée.

On peut bien sur directement modifier le contenu des cellules mémoires à l'adresse repérée par le label a !

Avant l'appel du sous-programme : empilement des paramètres.


Les param tres3

Les paramètres

Traitement de la valeur b:

pour des questions de régularité, on choisit de ne manipuler que des valeurs 32 bits lorsqu'il s'agit d'empiler/dépiler.

lb $t0,b

addi $sp,$sp,-4

sw $t0,($sp)

la$t0,a

addi $sp,$sp,-4

sw $t0,($sp)

jalsous_prog

Chargement : lecture de mémoire :

accès à la valeur de la 'variable'

initialisation avec une valeur immédiate

accès à l'adresse de la 'variable'


Tat de la pile

État de la pile

sous-prog : addi $sp,$sp,-4

sw $ra,($sp)

# autres instructions

$sp

$ra

Adresse de a : 0x10010180

Valeur de b : 62

32 bits


L allocation dynamique

L'allocation dynamique

Appel système avec $v0=9 permet de réserver de la mémoire dynamiquement dans la zone de tas pour les applications ayant au fur et à mesure des besoins en mémoire.

Après l'appel système (l'instruction syscall),


  • Login