Banner 728x90px

jeudi 4 octobre 2018

thumbnail

C2-Microprocesseur MIPS R3000

CHAP2 

Microprocesseur MIPS R3000
Architecture externe

1. Introduction

  MIPS (de l'anglais Microprocessor without interlocked pipeline stages) est une architecture de microprocesseur de type RISC. Elle fut développée par la compagnie MIPS Computer Systems Inc., basée à Mountain View en Californie. Les processeurs fabriqués selon cette architecture sont utilisés dans plusieurs systèmes. On les retrouve dans plusieurs systèmes embarqués (embedded systems en anglais), comme les ordinateurs de poche, les routeurs Cisco et les consoles de jeux vidéo (Nintendo 64 et Sony PlayStation, PlayStation 2 et PSP). Vers la fin des années 1990, on estimait que les processeurs dérivés de l'architecture MIPS occupaient le tiers des processeurs RISC produits.
  Les premières implémentations de l'architecture MIPS étaient de 32 bits (autant au niveau des registres que des chemins de données), mais par la suite, on a développé des implémentations de 64 bits.
  Il existe plusieurs jeux d'instructions MIPS qui sont rétro compatibles (backward compatible): MIPS I, MIPS II, MIPS III, MIPS IV, et MIPS V ainsi que MIPS32 et MIPS64. MIPS32 et MIPS64, qui se basent sur MIPS II et MIPS V, ont étés introduites comme jeux d'instructions normalisés. Des extensions sont aussi disponibles telles que : MIPS-3D, une unité à virgule flottante (FPU) simplifiée de type SIMD pour les calculs 3D de base.
    Les jeux d'instructions de base (en particulier MIPS I) sont efficaces qu'un bon nombre de cours d'architecture des ordinateurs, autant dans les universités que les écoles techniques, se portent sur l'étude de l'architecture MIPS. Cette architecture est suffisamment simple pour présenter les principes de base de l'architecture des processeurs, et suffisamment puissante pour supporter un système d'exploitation multi-tâches tel qu'UNIX.

2. Caractéristiques

 L'architecture externe est l'interface entre le processeur et le programmeur. Ce cours sera plus orienté vers l'architecture interne. Une architecture externe est composée de : 
  •  Les registres visibles. 
  •  L'adressage de la mémoire. 
  •  Le jeu d'instructions. 
  •  Les mécanismes de traitement des interruptions et exceptions.

2.1. Organisation de la mémoire 

  Dans l’architecture MIPS R3000, l’espace adressable est divisé en deux segments: le segment utilisateur, et le segment système (noyau). Un programme utilisateur utilise généralement trois sous-segments (appelés sections) dans le segment utilisateur:

  1. la section text contient le code exécutable en mode utilisateur. Elle est implantée conventionnellement à l’adresse 0x00400000. Sa taille est fixe et calculée lors de l’assemblage. La principale tâche de l’assembleur consiste à générer le code binaire correspondant au programme source décrit en langage d’assemblage, qui sera chargé en mémoire dans cette section.
  2. la section data contient les données globales manipulées par le programme utilisateur. Elle est implantée conventionnellement à l’adresse 0x10000000. Sa taille est fixe et calculée lors de l’assemblage. Les valeurs contenues dans cette section peuvent être initialisées grâce à des directives contenues dans le programme source en langage d’assemblage.
  3. la section stack contient la pile d’exécution du programme utilisateur. Sa taille varie au cours de l’exécution. Elle est implantée conventionnellement à l’adresse 0x7FFFF000. La pile s’étend vers les adresses décroissantes.


Trois sections sont également définies dans le segment noyau (kernel):
  1. la section ktext contient le code exécutable en mode noyau. Elle est implantée conventionnellement à l’adresse 0x80000000. Sa taille est fixe et calculée lors de l’assemblage.
  2. la section kdata contient les données globales manipulées par le système d’exploitation en mode noyau. Elle est implantée conventionnellement à l’adresse 0xC0000000. Sa taille est fixe et calculée lors de l’assemblage.
  3. la section kstack contient la pile d’exécution du noyau. Sa taille varie au cours de l’exécution. Elle est implantée conventionnellement. l’adresse 0xFFFFF000. Cette pile s’étend vers les adresses décroissantes.

2.2. Registres visibles du logiciel

 Le processeur MIPS possède 32 registres de travail accessibles au programmeur. Chaque registre est connu par son numéro, qui varie entre 0 et 31, et est préfixé par un $. Par exemple, le registre 31 sera noté $ra dans l’assembleur. En dehors du registre $zero qui contient toujours la valeur 0, tous les registres sont identiques du point de vue de la machine. Ils sont directement adressés par les instructions, et permettent de stocker des résultats de calculs intermédiaires. Afin de normaliser et de simplifier l’écriture du logiciel, des conventions d’utilisation des registres sont définies. Ces conventions sont particulièrement nécessaires lors des appels de fonctions.

  • PC Registre compteur de programme (Program Counter). Ce registre contient l'adresse de l’instruction en cours d’exécution. Sa valeur est modifiée par toutes les instructions.
  • HI et LO Registres pour la multiplication ou la division Ces deux registres 32 bits sont utilisés pour stocker le résultat d'une multiplication ou d'une division, qui est un mot de 64 bits.

2.3. Registres protégés

 L’architecture MIPS définit 32 registres (numérotés de 0 à 31), qui ne sont accessibles, en lecture comme en écriture, que par les instructions privilégiées (c’est à dire les instructions qui ne peuvent être exécutées qu’en mode superviseur). On dit qu’ils appartiennent au "coprocesseur système". En pratique, cette version du processeur MIPS R3000 en utilise 4 pour la gestion des interruptions et des exceptions.
 SR: Registre d’état (Status Register). Il contient en particulier le bit qui définit le mode : superviseur ou utilisateur, ainsi que les bits de masquage des interruptions. (Ce registre possède le numéro 12)
 CR : Registre de cause (Cause Register). En cas d’interruption ou d’exception, son contenu définit la cause pour laquelle on fait appel au pro-gramme de traitement des interruptions et des exceptions. (Ce registre possède le numéro 13).
 EPC : Registre d’exception (Exception Program Counter). Il contient l’adresse de retour (PC+4) en cas d’interruption. Il contient l’adresse de l’instruction fautive en cas d’exception (PC). (Ce registre possède le numéro 14)
 BAR: Registre d’adresse illégale (Bad Address Register). En cas d’exception de type "adresse illégale", il contient la valeur de l’adresse mal formée. (Ce registre possède le numéro 8)

 Les arguments d'une instruction :

  La plupart des instructions nécessitent un ou plusieurs arguments. Si une instruction nécessite plusieurs arguments, ces arguments sont séparés par des virgules. Dans une instruction assembleur, on aura en général comme premier argument le registre dans lequel est mis le résultat de l’opération, puis ensuite le premier registre source, puis enfin le second registre source ou une constante.

 Exemple 1:                add $v1, $v0, $at        # équivalent à:  $v1 ← $v0 + $at

 Règle syntaxique 

 On définit ci-dessous les principales règles d’écriture d'un programme source.
-Les noms de fichiers: Contenant un programme source en langage d’assemblage doivent être suffixé par « .asm ». Exemple: mips1.asm
-Les commentaires: Ils commencent par un # et s’achèvent à la fin de la ligne courante.

  Exemple 2:           # Premier programme, Bonjour tout le monde!
                                            .data      # Segment de données
                                entier :  .byte 5   # case mémoire contenant 5 
-Les entiers : Une valeur entière décimale est notée,par exemple, 250 (sans préfixe), une valeur entière octale est notée 0372 (préfixée par un zéro) et une valeur entière hexadécimale est notée 0xFA (préfixée par zéro suivi de x). En hexadécimal, les lettres de A à F peuvent être écrites en majuscule ou en minuscule.

-Les chaînes de caractères: Elles sont simplement entre guillemets, et peuvent contenir les caractères d’échappement du langage C. Exemple : "Oh la jolie chaîne avec retour à la ligne\n".

-Les labels: Ce sont des mnémoniques correspondant à des adresses en mémoire. Ces adresses peuvent être soit des adresses de variables stockées en mémoire (principalement dans la section data), soit des adresses de sauts (principalement dans la section text). Ce sont des chaînes de caractères qui commencent par une lettre, majuscule ou minuscule, un "$", un "_", ou un "."  suivi par un nombre quelconque de ces mêmes caractères auxquels on peut ajouter des chiffres. Lors de la déclaration, ils doivent être suffixés par le caractère « : ». Pour y référer, on supprime le « : ».

Exemple 3:                             .data
                               message:  .asciiz "Ceci est une chaîne de caractères...\n"
                               entier :      .word 250, 0372, 0xfa         # trois valeurs identiques
                                               .text
                               _main:
                                               li $v0,4                # charger 4 dans $v0
                                               la $a0, message  # charger @message dans $a0
                                               syscall                # afficher le contenu de message

-Types de données/tailles:   Les types de données de base comprennent les nombres entiers, les nombres à virgule flottante et les caractères.
  L’architecture I prend en charge les formats de stockage de données de l'octet, demi-mot, ou la taille des mots. La virgule flottante doit être de taille mot (32 bits) ou double mot (64 bits). Les données de caractère sont généralement un octet et une chaîne est une série d'octets séquentiels.
L'architecture MIPS prend en charge les types de données/tailles suivantes:
  • byte     : entier de 8 bits
  • half      : entier 16 bits
  • word    : entier 32 bits
  • float     : nombre à virgule flottante 32 bits
  • double : nombre à virgule flottante de 64 bits
  Des listes ou des tableaux peuvent être réservés dans l’un de ces types. De plus, un nombre arbitraire d'octets peut être défini avec la directive ".space".
  De plus, l'architecture MIPS telle que simulée sur Mars est little-endian. Cela signifie que le plus petit octet (LSB) est stocké dans l'adresse de mémoire la plus basse. L'octet le plus significatif (MSB) est stocké dans l'emplacement de mémoire le plus élevé.
  Pour un mot (32 bits), le MSB et LSB sont attribués comme indiqué ci-dessous.

31
30
29
28
27
26
25
24
23
22
21
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
                      MSB                                                                                                      LSB

Par exemple, en supposant les déclarations suivantes:
                                              .data
                                    num1: .word 0x0000002A
                                    num2: .word 0x004C4B40

Pour une architecture little-endian, l'image de la mémoire serait comme suit:

Nom de la variable
Valeur
Adresse

?
0x1001000C

00
0x1001000B

4C
0x1001000A

4B
0x10010009
num2 à
40
0x10010008

00
0x10010007

00
0x10010006

00
0x10010005
num1 à
2A
0x10010004

?
0x10010003

-Les immédiats : Ce sont les opérandes contenus dans l’instruction. Ce sont des constantes. Ce sont soit des entiers, soit des labels. Ces constantes doivent respecter une taille maximum qui est fonction de l’instruction qui l’utilise : 16 ou 26 bits.

-Les arguments : Si une instruction nécessite plusieurs arguments, comme par exemple l’addition entre deux registres, ces arguments sont séparés par des virgules. Dans une instruction assembleur, on aura en général comme argument en premier le registre dans lequel est mis le résultat de l’opération, puis ensuite le
premier registre source, puis enfin le second registre source ou une constante.
   Exemple:       add $3, $2, $1          #  $3←$2+$1
-Adressage mémoire : Le MIPS ne possède qu’un unique mode d’adressage : l’adressage indirect registre avec déplacement. Ainsi l’accès à une case mémoire à partir de l’adresse présente dans un registre se note par le déplacement, c.-à-d. un entier comme défini précédemment, suivi du registre entre parenthèses.
  Exemples : 11($12), 013($12) 0xB($12).
  Ces trois exemples indiquent la case mémoire ayant comme adresse le contenu du registre $12 plus 11.
S’il n’y a pas d’entier devant la parenthèse ouvrante, le déplacement est nul.

  En revanche, il n’est pas possible d’écrire des sauts à des adresses absolues ou relatives constantes,
comme par exemple un j 0x400000 ou un bnez $3, -12. Il faut nécessairement utiliser des labels.

3. Jeu d’instructions 

  Une instruction MIPS est un mot de 32 bits. Il y a trois catégories (formats) d’instruction :

Format :  
31            26
25           21
20           16
15              11
10              6
5                 0
opcode
rs
rt
rd
sh
func



Format I :
31            26
25           21
20           16
15                  
               
                   0
opcode
rs
rt
imm16




Format J :
31             26
25               
              
                
               
                   0
opcode
imm26



  Dans ce qui suit, nous notons rd la valeur du champs rd, c’est à dire un entier entre 0 et 31 car rd est codé sur 5 bits, et indiquons par $rd le registre indexé par ce champs. Si $rd est le membre de  gauche d’une affectation, alors nous en imposons la valeur, si il fait parti du membre de droite, nous en lisons la valeur. Nous ne pouvons en aucun cas modifier rd qui est une constante décidée lors de la compilation.

 Notons qu’un registre source peut être le registre destination d’une même instruction assembleur. Un opérande immédiat sera noté imm, et sa taille sera spécifié dans la description de l’instruction. 

 Les instructions de saut prennent comme argument une étiquette, où label, qui est utilisée pour calculer l’adresse de saut. Toutes les instructions modifient implicitement ou explicitement un registre non accessible du logiciel, le program counter noté $pc. Pour lever l’ambiguïté liée aux calculs des sauts relatifs au $pc, nous noterons que l’adresse de l’instruction en cours d’exécution est toujours égale à $pc-4, car $pc est incrémenté (pour passer à l’instruction suivante) en même temps que l’instruction à exécutée est chargée. Le $pc à droite d’une affectation est donc toujours égal à l’adresse de l’instruction courante plus 4.

 Attention : le MIPS R3000 est un processeur pipeline tel que l’instruction qui suit un branchement (relatif ou absolu) est toujours exécutée.On appel cet emplacement le delay slot et on dit que le branchement effectif est retardé d’une instruction.
   Le résultat d’une multiplication ou d’une division est mis dans deux registres spéciaux, $hi pour les poids forts (multiplication) ou le reste (division), et $lo pour les poids faibles (multiplication) ou le quotient (division).

Exemple 3.1: Programme pour lire un entier donné par l'utilisateur

# Program to read an integer number from a user, and  print that number back to the console.
       .text
main:
       # Prompt for the integer to enter
       li $v0, 4
       la $a0, prompt
       syscall
       # Read the integer and save it in $s0
       li $v0, 5
       syscall
       move $s0, $v0
       # Save  number in memory
       sw $s0, number
       # Output the text
       li $v0, 4
       la $a0, output
       syscall
       # Output the number
       li $v0, 1
       move $a0, $s0
       syscall
       # Exit the program
       li $v0, 10
       syscall
      .data
number:  .word 0
prompt: .asciiz "\nPlease enter an integer: "
output: .asciiz "\nYou typed the number "

Exemple 3.2: Programme pour lire une chaine de caractères donnée par l'utilisateur

# Program to read a string from a user, and  print that string back to the console.
       .text
main:
       # Prompt for the string to enter
       li $v0, 4
       la $a0, prompt
       syscall
       # Read the string.
       li $ v0, 8
       la $a0, input
       lw $a1, inputSize
       syscall
       # Output the text
       li $v0, 4
       la $a0, output
       syscall
       # Output the string
       li $v0, 4
       la $a0, input
       syscall
       # Exit the program
       li $v0, 10
       syscall
.data
input: .space 11
inputSize: .word 12
prompt: .asciiz "\nPlease enter an string: "
output: .asciiz "\nYou typed the string: "

- Instructions d’entrées/sorties : MIPS permet de communiquer avec le système de façon simple par la ` commande syscall. La fonction utilisée est déterminée selon la valeur de : $v0.

Commandes
Code syscall  
Arguments
Résultats
print integer
1
$a0 = value
(none)
print float
2
$f12 = float value
(none)
print double
3
$f12 = double value
(none)
print string
4
$a0 = address of string
(none)
read integer
5
(none)
$v0 = value read
read float
6
(none)
$f0 = value read
read double
7
(none)
$f0 = value read
read string
8
$a0 = address where string to be stored
$a1 = number of characters to read + 1
(none)
memory allocation
9
$a0 = number of bytes of storage desired
$v0 = address of block
exit (end of program)
10
(none)
(none)
print character
11
$a0 = integer
(none)
read character
12
(none)
char in $v0


3.1 Assemblage d’une instruction R-type:

R
Op
Rs
Rt
Rd
Shamt
Funct


op          6 bits       toujours  zéro!
rs            5 bits      1er  registre argument (de données)
rt            5 bits       2eme  registre argument (de données)
rd           5 bits       registre destination  (résultat)
shamt      5 bits      utiliser dans les  instructions de décalage   (toujours  0)
funct        6 bits      code de l’opération à effectuer.

Noter que le registre destination est   le troisième  registre  dans le code  machine

Exemple :   add $t1, $t2, $t3

                rs = 10(10)= 01010(2)   ($t2 = $10)
                rt = 11(10)= 01011(2)  ($t3 = $11)
                rd = 9(10)) = 01001(2)  ($t1 = $9)
                funct = 32(10) = 100000(2) (code fonction pour add)
                shamt = 0(10) = 00000(2) (n’est pas une instruction de decalage)

R
0
10
11
9
0
32
 


R
000000
01010
01011
01001
00000
1000000


                        0000   0001  0100   1011    0100 1000   0010   0000
                                                 0x014B4820

Instruction
funct
add
32
sub
34
mult
24
div
26
jr
 8

3.2 Assemblage d’une instruction I-type:


I
Op
Rs
Rt
Address/immediate


           op             6 bits       code de l’opération à effectuer.
           rs              5 bits       1er  registre argument (de données)
           rt               5 bits       destination ou 2eme  registre argument
            ad/imm    16 bits      valeur de la constante ou de l'adresse contenu dans l’instruction

Noter que le registre destination est  dans le deuxième registre  dans le code  machine

Exemple addi $t4, $t5, 0x43


                op = 8(10)) = 1000(2)  (voir code pour addi)
                rs = 13(10)= 01101(2)   ($t5= $13)
                rt = 1210)= 01100(2)  ($t4 = $12)
                imm = 67(10)= 43(16) = 0000 0000 0100 0011 (2)  (Valeur de la constante)
:  
I
8
13
12
67


I
001000
01101
01100
0000 0000 0100 0011


                      0010   0001   1010   1100   0000   0000   0100   0011
                                                  0x21AC0043

Instruction
op
addi
8
andi
12
beq
4
bne
5
ori
13
slti
10
xori
14

3.2.1 Instructions de branchement Conditionnel :

                                            beq $t0, $t1, label

I :
op
rs
rt
address/immediate


        op          6 bits     code de l’opération à effectuer.
        rs            5 bits     1er  registre argument (de données)
        rt            5 bits     destination ou 2eme  registre argument
        imm      16 bits      valeur de l’offset contenu dans l’instruction


a) Calcule du saut positif (offset) : Nombre d‘instructions à partir de l’instruction suivante

                  beq $t0, $t1, skip                                      
                  nop                                    # 0 (ici début)                   
                  nop                                    # 1                   
                  nop                                    # 2                   
skip:          nop                                    # 3                   
                                                  offset = 3

b) Calcule du saut négatif (offset) :

loop:         nop                                     # -5                  
                 nop                                    # -4                  
                 nop                                    # -3                  
                 nop                                    # -2                  
                 beq $t0, $t1, loop                # -1                  
                 nop                                    #  0 (ici début)                   
                                                 offset = -5

3.2.2 Assemblage d’une instruction de branchement Conditionnel:

                 beq $t0, $t1, label                                    
                 nop                                     #0                                    
                 nop                                     #1                                    
label:          nop                                    #2                                    
                op = 4(10)) = 0100(2)  (voir code pour beq)
                rs = 8(10)= 01000(2)   ($t0= $8)
                rt = 910)= 01001(2)  ($t1 = $9)
                imm = 2(10)= 2(16) = 0000 0000 0000 0010 (2)  (Valeur de l’offset)

I :
4
8
9
2


I :
000100
01000
01001
0000000000000010



                0001  0001   0000  1001  0000   0000  0000  0010
                                    0x11090002

3.2 Assemblage d’une instruction J-type:

J :
op
target address


                op              6 bits             code de l’opération à effectuer.
target address           26 bits             valeur de l’adresse absolue contenu dans l’instruction

 jr : est une  instruction R-type
 j, jal : instructions de saut (instructions J-type)
 b, beq, bgez, bgezal, bgtz, blez, bltz, bltzal, bne : instructions de branchement (instructions J-type)

-adressage Relative vs. Absolu :

                Instructions de Branchements – (offset est relative) : PC = PC + 4 + offset x4
                Instructions de Sauts – (): PC = (PC & 0xF0000000) | (adresse x 4)
Noter que “adresse absolue” s’étend sur une  région  mémoire de  256 Mo = 2^28 Mo.

Exemple :

0x0200 0000
. . . . . .
0x0200 00A4
. . . . . .
0x0204 C100
                        j label
                        . . . . . .
label:              nop
                        . . . . . .
                        j label

J :
J
target address


         op = 2(10)) = 00010(2)  (voir code pour J
          target address =  200 00A4(16) /4     (Enlever le 1er chiffre Hex.et les deux derniers bits)
                                = 0010  0000  0000  0000  0000  1010  0100(2)  (Valeur Bin de target address)
                                = 00  1000  0000  0000  0000  0010  1001(2)  (Valeur Bin de target address)
                                = 0800029(16) (Valeur Hexde target address)

J :
J
label


   J :
2
0x800029

J :
0000 10
00  1000  0000  0000  0000  0010  1001


                      0000  1000  1000  0000  0000  0000  0010  1001
                                                0x08800029

Subscribe by Email

Follow Updates Articles from This Blog via Email

No Comments