Architecture MIPS
L'architecture MIPS (de l'anglais : microprocessor without interlocked pipeline stages) est une architecture de processeur de type Reduced instruction set computer (RISC) développée par la société MIPS Technologies (alors appelée MIPS Computer Systems), basée à Mountain View en Californie.
Type |
Jeu d'instructions, plateforme informatique, RISC ISA (d) |
---|
Les processeurs fabriqués selon cette architecture ont surtout été utilisés dans les systèmes SGI. On les retrouve aussi dans plusieurs systèmes embarqués, 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.
De nos jours cette architecture reste populaire dans le marché de l'informatique embarquée où elle subit une intense concurrence de la part de l'architecture ARM.
Les MIPS sont aussi présents dans des routeurs ou des NAS, mais ils deviennent aussi de plus en plus rares dans ce domaine face à la concurrence des ARM, PowerPC et x86 basse consommation.
Malgré tout, les MIPS reviennent peu à peu dans le marché de l'informatique à haute performance grâce aux recherches menées par la Chine avec les processeurs Loongson qui ont été utilisés pour la création du supercalculateur Dawning 5000L et 6000.
En 2015, la Russie annonce vouloir remplacer les processeurs conçus par des sociétés des États-Unis par des processeurs locaux dans les systèmes informatiques nationaux. Les processeurs d'architecture MIPS, Baikal T1 de la société russe spécialisée dans les supercalculateurs T-Platforms (en) sont alors choisis. Leur conception est soutenue par le conglomérat de la défense Rostec et co-financée par l'entreprise publique russe Rosnano (Роснано)[1].
Architecture
Les premières versions de l'architecture MIPS étaient 32-bits (autant au niveau des registres que des chemins de données), mais par la suite, des versions 64-bits sont apparues.
Le R4000 sorti en 1991 serait le premier processeur 64 bits. Il a été supporté par Microsoft de Windows NT 3.1 jusqu'à Windows NT 4.0
Il existe plusieurs jeux d'instructions MIPS qui sont rétrocompatibles (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, et ont été introduits 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, MDMX, qui pousse plus loin l'utilisation des instructions SIMD et qui permet l'utilisation de registres à virgule flottante de 64 bits, MIPS16, qui compresse le flot d'instructions pour diminuer la taille des programmes (créée en réponse au codage Thumb introduit dans l'architecture ARM), et plus récemment, MIPS MT, qui permet le traitement de deux processus simultanément par un seul cœur de manière similaire à l'Hyper-Threading présent dans les récents processeurs d'Intel.
Les jeux d'instructions de base (en particulier MIPS I) sont si simples et efficaces qu'un bon nombre de cours d'architecture des ordinateurs, autant dans les universités que les écoles techniques, portent sur l'étude de l'architecture MIPS.
Exemple de code
Voici une implémentation des indicatrices d'Euler en assembleur MIPS :
.text
.globl main
main:
la $a0, query # Load Address : charge l'adresse de la requête
li $v0, 4 # Load Immediate : charge la valeur
syscall # appel du système d’exploitation
li $v0, 5 # lit l’entrée
syscall
move $t0, $v0 # stocke la valeur dans une variable temporaire
# stocke les valeurs de base dans $t1, $t2
sub $t1, $t0, 1 # $t1 itère de m-1 à 1
li $t2, 0 # $t2 maintient un compteur des premiers entre eux inférieurs à m
tot:
blez $t1, done #termination condition
move $a0, $t0 #Argument passing
move $a1, $t1 #Argument passing
jal gcd #to GCD function
sub $t3, $v0, 1
beqz $t3, inc #checking if gcd is one
addi $t1, $t1, -1 #decrementing the iterator
b tot
inc:
addi $t2, $t2, 1 #incrementing the counter
addi $t1, $t1, -1 #decrementing the iterator
b tot
gcd: #recursive definition
addi $sp, $sp, -12
sw $a1, 8($sp)
sw $a0, 4($sp)
sw $ra, 0($sp)
move $v0, $a0
beqz $a1, gcd_return #termination condition
move $t4, $a0 #computing GCD
move $a0, $a1
remu $a1, $t4, $a1
jal gcd
lw $a1, 8($sp)
lw $a0, 4($sp)
gcd_return:
lw $ra, 0($sp)
addi $sp, $sp, 12
jr $ra
done: #print the result
#first the message
la $a0, result_msg
li $v0, 4
syscall
#then the value
move $a0, $t2
li $v0, 1
syscall
#exit
li $v0, 10
syscall
.data
query: .asciiz "Input m = "
result_msg: .asciiz "Totient(m) = "
Registres
Description des registres généraux
Il y a 32 registres généraux[2].
Le registre 0 ($zero) est toujours égal à zero.
Le registre 1 ($at) est réservé par l'assembleur.
Les registres 2 et 3 ($v0 et $v1) permettent de stocker des résultats des fonctions[3].
Les registres 4 à 7 ($a0 à $a3) permettent de stocker les 4 premiers arguments du sous-programme [3].
Les registres 8 à 15 ($t0 à t7) sont des registres temporaires.
Les registres 16 à 23 ($s0 à s7) sont des registres sauvegardés et utilisés plus tard[3].
Les registres 24 et 25 ($t8 et $t9) sont des registres temporaires.
Les registres 26 et 27 ($k0 et $k1) sont des registres réservés au système.
Le registre 28 ($gp) correspond au global pointer.
Le registre 29 ($sp) correspond au stack pointer.
Le registre 30 ($fp) correspond au frame pointer.
Le registre 31 ($ra) correspond à l'adresse de retour.
Description de quelques registres particuliers
Parmi les registres spéciaux, on peut parler des registres lo
(où on trouve les résultats des divisions et des multiplications) et hi
(où on trouve le reste lors des divisions)[4].
Dans le cas où le résultat d'une multiplication serait sur 64 bits, les 32 bits supérieurs seraient stockés dans hi
et les 32 bits inférieurs seraient stockés dans lo
[4]. On peut récupérer les valeurs de hi
et lo
avec respectivement, les instructions mfhi
et mflo
[4].
Par exemple pour les divisions, on peut donner l'exemple suivant :
addi $t3, $0, 37
addi $t4, $0, 2
div $t3, $t4
mflo $t0 #équivaut à 37 / 2 équivaut à 18 (le quotient)
mfhi $t1 #équivaut à 37 % 2 équivaut à 1 (le reste)
Et pour les multiplications, on peut donner l'exemple suivant :
addi $t3, $0, 37
addi $t4, $0, 2
mult $t3, $t4
mflo $t1 #on y trouve le produit mais il faut que le produit soit sur 32 bits