Jeux d`instructions

publicité
Diplôme d'Ingénieur de l'IFSIC
- ARA
Jeux d'instructions
On considère une architecture comportant 16 registres 16 bits. Le jeu d'instructions est le suivant :
mnémonique et opérandes
description
MOV R,C
Met dans les 8 bits de poids faible du registre R
la constante C sur 8 bits codée dans l'instruction
Décale la valeur de R2 de N bits (insertion de zéros) et stocke
le résultat dans R1. N est une constante signée sur 5 bits codée dans
l'instruction. Le signe de N indique le sens du décalage.
Met dans R1 le résultat de R2 OP R3, où OP est une des opérations
suivantes : ADD,SUB,OR,AND,XOR
Lit la valeur 16 bits stockée à l'adresse mémoire R2+DEP et met la
valeur dans R1. DEP est une constante signée sur 8 bits,
codée dans l'instruction
Écrit la valeur de R1 à l'adresse mémoire R2+DEP.
DEP est une constante signée sur 8 bits, codée dans l'instruction
Met la valeur du PC de l'instruction suivante dans R1
et saute à l'adresse lue dans R2
Saute à PC+DEP si R est non nul.
DEP est une constante signée sur 8 bits, codée dans l'instruction.
SH R1,R2,N
OP R1,R2,R3
LD R1,R2,DEP
ST R1,R2,DEP
JMP R1,R2
BNZ R,DEP
1
Questions
1. Calculer le nombre total N d'instructions distinctes, considérant que toutes les combinaisons de registres source
et destination sont valides.
2. Si on utilise un format d'instruction de longueur constante, quelle est la longueur minimum d'une instruction ?
3. Un format d'instruction de longueur variable permet-il d'obtenir une longueur moyenne d'instruction plus petite
qu'un format de longueur constante ?
4. Proposer une modication minimale du jeu d'instruction qui permet un codage de longueur constante sur 16 bits
(il existe plusieurs solutions acceptables). Calculer le nombre total N 0 d'instructions distinctes et vérier qu'il
est compatible avec un codage sur 16 bits.
5. Un codage possible sur 16 bits serait de numéroter les instructions de 0 à N 0 − 1. Cependant, aucune architecture
n'est construite de cette manière car la mise en oeuvre matérielle du décodage nécessiterait une ROM (read-only
memory) très grande. Proposez un codage 16 bits pour le jeu d'instructions modié qui permette une mise en
oeuvre matérielle simple du décodage (il existe plusieurs solutions acceptables).
6. L'architecture décrite jusqu'à présent ne permet d'adresser que 64 Ko de mémoire. Proposez une modication
de l'architecture qui permette d'adresser 4 Go de mémoire et qui autorise la compatibilité binaire avec le jeu
d'instructions décrit précédemment. Les programmes binaires écrits avec l'ancien jeu d'instruction sont toujours
valides (il existe plusieurs solutions acceptables). Décrivez l'impact de cette modication sur la microarchitecture.
7. Tracez le graphe d'appel des procédures du programme suivant. Combien de contexte d'appels sont possibles
pour la procédure f uncA ?
TD ARA
Diplôme d'Ingénieur de l'IFSIC
int
int
{
}
Jeux d'instructions
X = 0;
funcA (
X++;
return
int
argA )
X ∗ argA ;
int funcB ( int argB )
int b ;
b = funcA ( argB ) ;
return b + argB ;
{
}
int
{
}
funcC (
int
return
int
argC )
c;
c = funcA ( argC ) ;
c;
int funcD ( int argD1 , int argD2 )
int d ;
d = funcB ( argD1 ) + funcC ( argD2
return d ;
{
);
}
8. La traduction d'un programme en langage de haut niveau vers un texte en langage assembleur est le processus
compilation. En utilisant le jeu d'instructions du TD, proposer un texte en langage assembleur qui réalise le
programme de la question précédente.
On suppose :
entiers sur 16 bits
argD1 et argD2 initialement stockés dans R0 et R1
adresse de début de f oncD est stockée dans PC
adresse de retour stockée dans R14
pointeur de pile stocké dans R15
résultat de la fonction écrit dans R13
les registres R3 a R12 sont libres
9. Faire une critique du jeu d'instructions sur la base du programme de la question précédente.
10. Voici un simulateur pour le jeu d'instructions décrits dans ce TD. Modiez son code pour acher la trace des
adresses des accès mémoires vers la mémoire (pour les instructions et les données).
TD ARA
2
Diplôme d'Ingénieur de l'IFSIC
Jeux d'instructions
#include <s t d i o . h>
#define TAILLEMEM 65536
#define NREG 16
#define PCFONC 0
#define PCFIN 0xDEAD
#define PTRSTACK 0
enum t y p e _ i n s t {MOV,ADD, SUB,XOR, LD, ST , JMP,BNZ} ;
struct i n s t r u c t i o n {
enum t y p e _ i n s t t ;
int r1 , r2 , r3 , c ;
};
int pc ;
int r e g [NREG ] ;
int memd [TAILLEMEM ] ;
struct i n s t r u c t i o n memi [TAILLEMEM]
};
= {
{XOR, 1 3 , 1 3 , 1 3 , 0 } , {BNZ, 1 , 0 , 0 , 6 } , {MOV, 1 3 , 0 , 0 , 1 } , {JMP, 4 , 1 4 , 0 , 0 } , {XOR, 4 , 0 , 1 , 0 } ,
{BNZ, 4 , 0 , 0 , 6 } , {MOV, 1 3 , 0 , 0 , 1 } , {JMP, 4 , 1 4 , 0 , 0 } , { ST, 0 , 1 5 , 0 , 0 } , { ST , 1 , 1 5 , 0 , 2 } ,
{ST, 1 4 , 1 5 , 0 , 4 } , {XOR, 4 , 4 , 4 , 0 } , {MOV, 4 , 0 , 0 , 6 } , {ADD, 1 5 , 1 5 , 4 , 0 } , {XOR, 4 , 4 , 4 , 0 } ,
{MOV, 4 , 0 , 0 , 1 } , {SUB, 0 , 0 , 4 , 0 } , {JMP, 1 4 , 2 , 0 , 0 } , {XOR, 4 , 4 , 4 , 0 } , {MOV, 4 , 0 , 0 , 6 } ,
{SUB, 1 5 , 1 5 , 4 , 0 } , {LD, 0 , 1 5 , 0 , 0 } , {LD, 1 , 1 5 , 0 , 2 } , {LD, 1 4 , 1 5 , 0 , 4 } , {XOR, 4 , 4 , 4 , 0 } ,
{ST, 1 4 , 1 5 , 0 , 0 } , { ST, 1 3 , 1 5 , 0 , 2 } , {XOR, 4 , 4 , 4 , 0 } , {MOV, 4 , 0 , 0 , 4 } , {ADD, 1 5 , 1 5 , 4 , 0 } ,
{XOR, 4 , 4 , 4 , 0 } , {MOV, 4 , 0 , 0 , 1 } , {SUB, 0 , 0 , 4 , 0 } , {SUB, 1 , 1 , 4 , 0 } , {JMP, 1 4 , 2 , 0 , 0 } ,
{XOR, 4 , 4 , 4 , 0 } , {MOV, 4 , 0 , 0 , 4 } , {SUB, 1 5 , 1 5 , 4 , 0 } , {LD, 1 4 , 1 5 , 0 , 0 } , {LD, 4 , 1 5 , 0 , 2 } ,
{ADD, 1 3 , 1 3 , 4 , 0 } , {JMP, 4 , 1 4 , 0 , 0 }
int main ( int argc , char ∗∗ argv )
int n ,m;
struct i n s t r u c t i o n i n s t ;
{
s c a n f ( "%d %d" ,&n,&m) ;
pc = PCFONC;
reg [ 0 ] = n ;
r e g [ 1 ] = m;
r e g [ 2 ] = PCFONC;
r e g [ 1 4 ] = PCFIN ;
r e g [ 1 5 ] = PTRSTACK;
while
( pc != PCFIN) {
i n s t = memi [ pc ] ;
pc += 1 ;
( inst . t ) {
MOV: r e g [ i n s t . r 1 ] &= ( − 1) ^ 2 5 5 ; r e g [ i n s t . r 1 ] |= i n s t
ADD: r e g [ i n s t . r 1 ] = r e g [ i n s t . r 2 ] + r e g [ i n s t . r 3 ] ;
SUB : r e g [ i n s t . r 1 ] = r e g [ i n s t . r 2 ] − r e g [ i n s t . r 3 ] ;
XOR: r e g [ i n s t . r 1 ] = r e g [ i n s t . r 2 ] ^ r e g [ i n s t . r 3 ] ;
LD: r e g [ i n s t . r 1 ] = memd [ r e g [ i n s t . r 2 ]+ i n s t . c / 2 ] ;
ST : memd [ r e g [ i n s t . r 2 ]+ i n s t . c / 2 ] = r e g [ i n s t . r 1 ] ;
JMP: r e g [ i n s t . r 1 ] = pc ; pc = r e g [ i n s t . r 2 ] ;
;
BNZ:
( r e g [ i n s t . r 1 ] != 0 ) pc += i n s t . c /2 − 1;
;
: p r i n t f ( "non implementee \n" ) ; pc=PCFIN ;
}
switch
case
case
case
case
case
case
case
case
default
}
.c;
break ;
break ;
break ;
break ;
break ;
break
break
if
break ;
p r i n t f ( " r e s u l t a t : %d\n" , r e g [ 1 3 ] ) ;
}
return
0;
11. Quelle fonction mathématique calcule le programme exécuté par le simulateur ?
TD ARA
3
Diplôme d'Ingénieur de l'IFSIC
Jeux d'instructions
XOR R13 , R13 , R13
BNZ R1 , 6
MOV R13 , 1
JMP R4 , R14
XOR R4 , R0 , R1
BNZ R4 , 6
MOV R13 , 1
JMP R4 , R14
ST R0 , R15 , 0
ST R1 , R15 , 2
ST R14 , R15 , 4
XOR R4 , R4 , R4
MOV R4 , 6
ADD R15 , R15 , R4
XOR R4 , R4 , R4
MOV R4 , 1
SUB R0 , R0 , R4
JMP R14 , R2
XOR R4 , R4 , R4
MOV R4 , 6
SUB R15 , R15 , R4
LD R0 , R15 , 0
LD R1 , R15 , 2
LD R14 , R15 , 4
ST R14 , R15 , 0
ST R13 , R15 , 2
XOR R4 , R4 , R4
MOV R4 , 4
ADD R15 , R15 , R4
XOR R4 , R4 , R4
MOV R4 , 1
SUB R0 , R0 , R4
SUB R1 , R1 , R4
JMP R14 , R2
XOR R4 , R4 , R4
MOV R4 , 4
SUB R15 , R15 , R4
LD R14 , R15 , 0
LD R4 , R15 , 2
ADD R13 , R13 , R4
JMP R4 , R14
TD ARA
4
Diplôme d'Ingénieur de l'IFSIC
2
Jeux d'instructions
Réponses
nombre de combinaisons
1.
MOV R,C
SH R1,R2,N
OP R1,R2,R3
LD R1,R2,DEP
ST R1,R2,DEP
JMP R1,R2
BNZ R1,DEP
Total
16 × 256
16 × 16 × 32
5 × 16 × 16 × 16
16 × 16 × 256
16 × 16 × 256
16 × 16
16 × 256
256 × 657
2. Un format de longueur xe nécessite log2 (256) + dlog2 (657)e = 18 bits par instruction.
3. Considérons tous les programmes possibles de longueur P instructions, P étant grand. Il y a N P programmes
diérents. Coder ces N P programmes nécessite log2 (N P ) = P log2 (N ) bits, soit une moyenne de log2 (N ) ≈ 17.36
bits par instruction. Un codage d'instruction de longueur variable permettrait d'obtenir une longueur moyenne
d'instruction légèrement plus petite qu'un format de longueur constante.
4. Les instructions LD,R1,R2,DEP et ST R1,R2,DEP ne peuvent pas être codée sur 16 bits. En eet, R1,R2 et
DEP totalisent 16 bits de code. Il ne reste donc plus aucun bit pour distinguer LD de ST, sans parler des autres
instructions. Pour que le jeu d'instruction puisse être codé sur 16 bits il faut nécessairement modier LD et
ST. Il y a plusieurs manières possibles de modier LD et ST. Par exemple, on pourrait considérer que l'un des
registres R1 ou R2 est xé implicitement. On peut aussi choisir de réduire la longueur du champ DEP. C'est
cette dernière solution que nous considérons ici. Si on restreint DEP à 5 bits, on trouve que N 0 = 256 × 209, qui
est compatible avec un codage sur 16 bits. Augmenter DEP à 6 bits ne permettrait pas un codage sur 16 bits
5. Pour que la mise en oeuvre matérielle du décodage soit simple, il faut que les numéros de registres et les diverses
constantes soient faciles à extraire, le mieux étant qu'ils apparaissent explicitement sous forme de champs dans le
code de l'instruction. Pour trouver un codage "sympathique", on peut grouper les instructions qui se ressemblent.
Les instructions LD,ST et SH forment le groupe 1 (2 registres et une constante sur 5 bits). Les instructions
ADD,SUB,OR,AND,XOR forment le groupe 2 (3 registres). On peut rajouter au groupe 2 l'instruction JMP, qui
n'utilise que 2 registres sur les 3. Les instructions MOV et BNZ forment le groupe 3 (1 registre et une constante
sur 8 bits). Le champ DEP est équivalent en longueur à 2 numéros de registre. On peut donc considérer les 8
instructions des groupes 2 et 3 comme appartenant à une même classe. On a ainsi 2 classes : la classe 1 constituée
par le groupe 1 et la classe 2 constituée par les groupes 2 et 3. On utilise le bit de poids fort de l'instruction pour
identier la classe. 13 des 16 bits des instructions de la classe 1 sont réservées pour les 2 registres et la constante
sur 5 bits. Un bit étant réservé pour spécier la classe, il reste 2 bits, ce qui est susant pour distinguer les 3
instructions de la classe 1. Les instructions de la classe 2 utilisent 12 bits pour spécier les registres et la constante
sur 8 bits. Sans compter le bit de classe, il reste 3 bits, ce qui est susant pour distinguer les 8 instructions de
la classe 2. On obtient le codage suivant (par exemple) :
TD ARA
5
Diplôme d'Ingénieur de l'IFSIC
Jeux d'instructions
LD R1,R2,DEP
0 00
DEP
R1
R2
ST R1,R2,DEP
0 01
DEP
R1
R2
SH R1,R2,N
0 10
N
R1
R2
ADD R1,R2,R3
1 000
R1
R2
R3
SUB R1,R2,R3
1 001
R1
R2
R3
OR R1,R2,R3
1 010
R1
R2
R3
AND R1,R2,R3
1 011
R1
R2
R3
XOR R1,R2,R3
1 100
R1
R2
R3
JMP R1,R2
1 101
R1
R2
0000
MOV R,C
1 110
C
R
BGZ R,DEP
1 111
DEP
R
6. Comme on veut obtenir la compatibilité binaire, nous devons partir du codage 16 bits obtenu à la question
précédente. Le codage n'autorise que des extensions limitées au jeu d'instructions. Les seules parties du codage
qui sont non utilisées sont le code interdit dont les 3 bits de poids fort sont 011 et les 4 bits de poids faible de
l'instruction JMP. Nous proposons 2 solutions, mais on pourrait en imaginer d'autres.
Solution 1.
Une solution simple a priori est de considérer que les registres (y compris le compteur de programme PC) ont une taille de 32 bits au lieu de 16 bits. Ainsi, l'adresse contenu dans le registre R2 des instructions
LD et ST permet d'adresser 4 Go. Les adresses de saut calculées par les instructions JMP et BNZ sont également
des adresses 32 bits. Il faut cependant faire attention. La représentation des entiers signés n'est pas la même sur
16 et sur 32 bits. Par exemple, 0xFFFF représente −1 lorsque les entiers sont sur 16 bits et 65535 lorsqu'ils sont
sur 32 bits. De plus, un ST appliqué à un registre R1 sur 16 bits écrit 2 octets consécutifs en mémoire, alors qu'il
écrit 4 octets lorsqu'il est appliqué à un registre R1 sur 32 bits. Il faut donc distinguer 2 modes d'exécution, un
mode 16 bits et un mode 32 bits. On peut introduire une nouvelle instruction SM (comme switch mode) pour
changer le mode d'exécution de 16 à 32 bits et vice-versa. On peut utiliser le code 011.. pour représenter cette
instruction. Le mode par défaut est le mode 16 bits, ce qui permet d'exécuter les programmes binaires 16 bits
correctement.
Concernant la microarchitecture, il faut un registre sur 1 bit pour stocker le mode d'exécution (16 ou 32 bits).
Dans le mode 16 bits, les 16 bits de poids forts des registres 32 bits sont ignorés la plupart du temps, sauf pour
ADD et SUB, pour lesquelles la microarchitecture doit eectuer une extension de signe (c'est-à-dire mettre les 16
bits de poids fort des registres 32 bits tous à 0 ou tous à 1 selon le signe de l'entier 16 bits) an que l'additionneur
32 bits donne le résultat attendu sur 16 bits. L'instruction ST en mode 16 bits n'écrit que les 2 octets de poids
faible du registre R1.
Solution 2.
Une autre solution possible est de conserver des registres 16 bits mais de rajouter dans l'architecture deux registres spéciaux 16 bits, que nous appelerons ZI et ZD. ZI représente la "zone" (ou "segment")
d'instructions et ZD la zone de données. Sur un accès mémoire, la microarchitecture concatène les 16 bits du
registre de zone et les 16 bits d'adresse "normaux" pour former une adresse 32 bits. Pour que cela soit utile,
il faut introduire des instructions permettant de modier ZI et ZD, que les instruction "normales" ne peuvent
pas accéder. Nous pouvons utiliser le code 011.. pour représenter une instruction NZD R, qui copie le contenu
du registre R dans le registre ZD. Pour changer la valeur de ZI, nous introduisons une instruction NZI R1,R2
qui recopie le contenu du registre R1 dans dans le registre ZI et saute à l'adresse (lue dans) R2 dans la nouvelle
zone. On peut coder l'instruction NZ en utilisant le code du JMP en en mettant les 4 bits de poids faible à 0001
par exemple. Concernant la microarchitecture, la principale modication est l'ajout des registre ZI et ZD.
7.
TD ARA
6
Diplôme d'Ingénieur de l'IFSIC
Jeux d'instructions
8.
9. Nous pouvons remarquer que le jeu d'instructions n'est pas très ecace pour manipuler les constantes. En
particulier, le principal défaut de l'instruction MOV est qu'elle ne force par les 8 bits de poids fort du registre à
zéro. A cause de cela, nous avons du utiliser des XOR R,R,R. On aimerait aussi pouvoir additionner ou soustraire
à un registre une constante codée directement dans l'instruction. Mais cela nécessiterait de changer complètement
le codage du jeu d'instructions.
10.
11.
L1 :
L2 :
XOR R13 , R13 , R13
BNZ R1 , 6
MOV R13 , 1
JMP R4 , R14
XOR R4 , R0 , R1
BNZ R4 , 6
MOV R13 , 1
JMP R4 , R14
ST R0 , R15 , 0
ST R1 , R15 , 2
ST R14 , R15 , 4
XOR R4 , R4 , R4
MOV R4 , 6
ADD R15 , R15 , R4
XOR R4 , R4 , R4
MOV R4 , 1
SUB R0 , R0 , R4
JMP R14 , R2
XOR R4 , R4 , R4
MOV R4 , 6
SUB R15 , R15 , R4
LD R0 , R15 , 0
LD R1 , R15 , 2
LD R14 , R15 , 4
ST R14 , R15 , 0
ST R13 , R15 , 2
XOR R4 , R4 , R4
MOV R4 , 4
ADD R15 , R15 , R4
XOR R4 , R4 , R4
MOV R4 , 1
SUB R0 , R0 , R4
SUB R1 , R1 , R4
JMP R14 , R2
XOR R4 , R4 , R4
MOV R4 , 4
SUB R15 , R15 , R4
LD R14 , R15 , 0
LD R4 , R15 , 2
ADD R13 , R13 , R4
JMP R4 , R14
//
met
0
dans
R13
//
saute
a L1
s i m=0
//
r e s u l t a t =1
//
retour
//
saute
//
r e s u l t a t =1
de
fonction
a L2
de
si
n=m
//
retour
//
sauve
dans
la
pile
//
s a u v e m dans
la
pile
//
sauve
//
incremente
n
fonction
adresse
retour
pointeur
dans
de
//
calcule
n−1
//
appelle
comb ( n − 1 ,m)
//
decremente
//
restaure
la
valeur
//
restaure
la
valeur
//
restaure
l ' adresse
//
sauve
adresse
//
sauve
comb ( n − 1 ,m)
//
incremente
//
calcule
n−1
//
calcule
m−1
//
appelle
comb ( n − 1 ,m−1)
//
decremente
//
restaure
//
recupere
//
calcule
//
retour
le
de
de m
retour
retour
dans
de
de
de
7
pile
retour
comb ( n − 1 ,m)
comb ( n−1)+comb ( n − 1 ,m−1)
i n t comb ( i n t n , i n t m)
{
i f ( (m= = 0 ) | | ( n==m) ) r e t u r n 1 ;
r e t u r n comb ( n − 1,m) + comb ( n − 1,m− 1);
}
TD ARA
pile
pile
pointeur
l ' adresse
pile
n
de
pointeur
le
pile
pointeur
de
pile
Téléchargement