Step #4 : Le jeu d`instructions Objectif de l`étape 3 : en terme de
Transcription
Step #4 : Le jeu d`instructions Objectif de l`étape 3 : en terme de
SFO 2010-2011 Étape #4 : Le jeu d'instructions Step #4 : Le jeu d'instructions Objectif de l'étape 3 : en terme de compétences Outils : – Rien de plus que vous ne sachiez déjà Concepts de SFO : – – – – – Déterminer un jeu d'instructions minimal Comprendre les formats de codage et le codage d'instructions Mettre en œuvre l'opération de décodage d'instructions Mettre en œuvre les instructions conditionnelles Mettre en place un contrôleur de bus (pour le multi-cœur ou la DMA...) Jeu d'instructions minimal ou étendu ? La machine que vous venez de réaliser est capable d'exécuter des programmes composés uniquement de l'instruction de saut « Branch ». Ce jeu d'instructions ne permet pas beaucoup d'applications voire aucune. Dans la suite vous allez identifier le jeu d'instructions minimal permettant de réaliser le programme du TD 1 d'assembleur (voir page suivante). Vous pourrez ensuite ajouter des instructions étendues ( push/pop, BL, etc.) qui sont réalisables à partir du jeu minimal mais qui permettront soit d'accélérer le temps d'exécution, soit de réduire la taille du code... Step_4_jeu_v2011a.odt 1/8 SFO 2010-2011 Étape #4 : Le jeu d'instructions #define IN 0x8 // input with pulldown #define OUT 0x2 // output 2MHz with push/pull #define CR ((volatile unsigned int *) 0x40010C00) // pointeur to CRL of GPIOB (STM32f10x) #define IDR ((volatile unsigned int *) 0x40010C08) // IDR #define ODR ((volatile unsigned int *) 0x40010C0C) // ODR unsigned char Boutons_Lus; // mÈmorise la valeur des boutons lu sur IDR (bit .3 et .0) void Wait(int); // mouline un peu pour temporiser int main(void) { unsigned char Pas_Appuye ; // boulÈen pour stopper l'attente de l'appuis // configure |PORT.3 |PORT.2 |PORT.1 |PORT.0 // as |In |Out |Out |In //___________|____________|_____________|_____________|___________ // for |Player1 |Player1 |Player 2 |Player 2 // |Button |Led |Led |Button unsigned int mask; mask = (IN<<(3*4)) +(OUT<<(2*4)) +(OUT<<(1*4)) +(IN<<(0*4)); *CR = mask; while(1) // LE jeu ne fini jamais { Pas_Appuye = 'R'; // "Run" car les joueurs n'ont pas encore appuyÈ sur une touche // Fait clignoter les LEDs en attendants que les players appuient while (Pas_Appuye) // rappel : 0=> false ; tout le reste (et donc 'R') => true { // Teste si au moins un bouton est appuyÈ : on teste donc si IDR.0 (bouton player 1) // ou IDR.3 (bouton player 2 ) est ‡ 1 gr‡ce au masque binaire 2_00001001 = 0x9 Boutons_Lus = *IDR & 0x9 ; // mets tous les bits ‡ 0 sauf les bits .0 et .3 // Boutons_Lus vaut 0 (!False) si aucun bouton appuyÈ et true sinon if (Boutons_Lus) Pas_Appuye =0; } // Change Ètat des diodes avec un XOR bit ‡ bit du masque 2_00000110 *ODR ^= 0x6 ; //éteindre les diodes *ODR &= ~(6); //~ est l'inversion de chaque bits // affiche le vainqueur ou ex-aequo if (Boutons_Lus & (1<<0)) *ODR |= (1<<1); if (Boutons_Lus & (1<<3)) *ODR |= (1<<2); // attends qu'ils aient vu le resultat Wait(1000000) ; //etteinds les diodes *ODR &= ~(6); //~ est l'inversion de chaque bits }//Main // les joueurs attendent le signal pour appuyer Wait(3000000) ; }// while Toujours // Boucle de temporisation void Wait( int N) { volatile int cpt ; } cpt=0; for (cpt=0;cpt<N;cpt++); Step_4_jeu_v2011a.odt 2/8 SFO 2010-2011 Étape #4 : Le jeu d'instructions Codage et format d'instruction Nous allons voir dans la suite comment l'instruction de saut peut être réalisée en utilisant les 3 formats de codage prévus par le chemin des données : • format court immédiat : 8 bits de poids forts de code opération et 8 bits de poids faibles de donnée immédiate ; • format court par registre : les 8 bits de poids faibles sont utilisés pour indiquer les registres opérandes et l'éventuelle indirection ; • format long 32 bits (avec un demi-mot de 16 bits supplémentaire) : les 8 bits de pf sont inutilisés ou indiquent un registre et 16 bits sont ajoutés à la suite pour coder la donnée immédiate. L'instruction de saut « Branch » de mnémonique « B » a été codée dans un format long, nous vous montrons comment la réaliser selon les deux autres formats. Format long 32 bits : Le format long est constitué par deux demi-mots de 16 bits avec : – bits 15..12 COP : le code opération (identifie une famille d'instruction) – bits 11..8 SCO : le sous-code opération (identifie l'élément de la famille) – bits 7..0 ???? : inutilisés ou registre Ra et Rb (voir le format court par registre) L'instruction « B imm16 » que vous avez réalisée et testée est codée sur 32 bits par « 0xBEEF » suivi de « imm16 ». Le COP « 0xB » peut être celui de la famille des instructions de saut et le sous-code opération 0xE identifie l'instruction notée « B imm16 ». Le 0xEF n'est pas utilisé dans cette instruction. Une instruction de format long doit lors de son exécution corriger la valeur PC calculée lors du fetch (PC ← PC + 2 pointe sur imm16 et non sur l'instruction suivante) de manière à positionner le PC sur la prochaine instruction. Format court immédiat : Le format court immédiat est constitué de 16 bits avec : – bits 15..12 COP : le code opération (identifie une famille d'instruction) – bits 11..8 SCO : le sous-code opération (identifie l'élément de la famille) – bits 7..0 imm8 : donnée immédiate entière signée en complément à 28 Pour utiliser les bits « imm8 » de ce format, le chemin des données doit transmettre la donnée du RI immédiatement vers l'ALU (ce qui explique le terme adressage immédiat en assembleur) comme le montre la figure 1. Comme 8 bits ne suffisent pas à coder une adresse absolue (du moins pas toutes) on peut effectuer un saut relatif « BR imm8 » où la donnée immédiate est ajoutée à PC pour effectuer le saut : PC ← PC + ExS(imm8). Afin de permettre des sauts à des adresse inférieures (pour faire des boucles en assembleur) la donnée immédiate est étendue à 16 bits en convention signée de manière à pouvoir ajouter une valeur négative. Step_4_jeu_v2011a.odt 3/8 SFO 2010-2011 Étape #4 : Le jeu d'instructions Figure 1: L'adressage immédiat utilisé pour faire un saut relatif de type "PC ← PC + ExS(imm8)" où ExS désigne l'extension signée Ainsi un saut relatif « BR -6 » codé à l'adresse 0x12 permet de remonter à l'adresse 0xE (comme PC vaut 0x14 lors de l'exécute de BR, on saute à l'adresse 0x14 – 6 = 0xE). Il est codé par 0xBDFA sur 16 bits où B indique la famille des sauts, D précise le saut relatif BR, et la donnée immédiate 8 bits FA code la valeur -6 en complément à 28 . La figure montre comment le chemin des données permet d'extraire imm8 du RI, de l'étendre et de l'ajouter à PC pour exécuter le saut. Step_4_jeu_v2011a.odt 4/8 SFO 2010-2011 Étape #4 : Le jeu d'instructions Format court par registres : Le format court par registre est constitué de 16 bits avec : – bits 15..12 COP : le code opération (identifie une famille d'instruction) – bits 11..8 SCO : le sous-code opération (identifie l'élément de la famille) – bits 7 indA: indirection ou non sur Ra. Transfert sur Ra ou [Ra]. – Bits 6..4 Ra : numéro de registre de l'opérande A sur 3 bits ! R0 à R7... – bits 3 indB: indirection sur RB – Bits 2..0 Rb : registre de l'opérande B sur 3 bits. Ce format permet de coder des instructions entre deux opérandes A et B qui peuvent être chacune un registre Rx ou un accès indirect avec ce registre [Rx]. On peut donc coder des instructions de type LD [Ra],[Rb], LDR Ra,[Rb] et MOV Ra,Rb. L'instruction LD [Ra],[Rb] n'existe pas sur le cortex-M3 car son architecture load/store n'autorise qu'un accès mémoire par instruction. Notre architecture l'autorise en consommant deux bits IndA et IndB dans le codage. Cela limite à 3 bits le codage des registres Ra et Rb rendant les registres R8 à R15 invisible au programmeur ! Grâce à ce format, le µ-programmeur peut faire un seul µ-programme générique pour une instruction de type MOV Ra,Rb par exemple. Cela évite de faire 8x8=64 µprogrammes légèrement différents pour coder les combinaisons du types MOV R1,R4 ; MOV R1,R5, etc. Ce format permet de coder un saut à l'adresse contenue dans un registre de type « Branch Register » notée « BX Ra » signifiant PC ← Ra. Ainsi un saut à l'adresse R1 pourrait être codé par « BC01 » où B indique la famille des sauts, C précise le saut de type BX, 0 est inutilisé et 1 (Rb) indique qu'il s'agit de BX R1. La figure 2 montre comment le champ Rb permet de sélectionner le registre R1 dans la banque de registre. Step_4_jeu_v2011a.odt 5/8 SFO 2010-2011 Étape #4 : Le jeu d'instructions Figure 2: Le champ Rb utilisé pour sélectionner un registre de la banque. Le champ IndB est relié au séquenceur et lui permet de "µ-sauter" l'indirection du µprogramme Step_4_jeu_v2011a.odt 6/8 SFO 2010-2011 Étape #4 : Le jeu d'instructions Le transcodage Lorsque vous allez ajouter des instructions votre séquence de µ-adresses 0-1-2-3-[4-10] va devoir s'adapter à l'instruction chargée : en effet comme jusqu'alors seule l'instruction BEEF était chargée dans l'IR lors du fetch (µ@ 4) on sautait systématiquement vers la µ@10 où se trouvait la phase execute de l'instruction « B imm16 » codée en 32 bits par 0xBEEF + imm16. Il est alors nécessaire d'effectuer un décodage d'instruction chargé d'identifier la µ@ où sauter pour faire l'exécution de l'instruction en fonction de son COP et SCO contenu dans le RI. Pour cela on utilise une ROM, dite « ROM de transcodage », qui prend en entrée du bus d'adresse la valeur de COP et SCO issu du RI et envoi en sortie la µ@ du µ-programme correspondant vers le séquenceur. La figure 3 illustre le transcodage de l'instruction « BR #imm8 ». Figure 3: L'instruction "BR -6" codée par "FD#imm8" est µ-programmée à la µ@7. Lors du fetch, la valeur 0xBD des champs COP et SCO du RI est reliée à la ROM de transcodage. La ROM de transcodage lue à l'adresse 0xBD fournit la valeur 7 en entrée externe du séquenceur. Le séquenceur peut ainsi sauter à la µ@7 pour exécuter la bonne instruction. Step_4_jeu_v2011a.odt 7/8 SFO 2010-2011 Étape #4 : Le jeu d'instructions Déroulement Vous enrichirez le jeu d'instructions de votre machine au fur et à mesure. Ainsi vous traduirez petit à petit le programme C en assembleur de votre machine. Pour chaque instruction d'assembleur du programme, vous déterminerez son format de code machine, vous ajouterez ce code machine dans la ROM, vous remplirez la ROM de transcodage et µ-programmerez cette instruction. Les tests s'effectueront avec le simulateur LILAS (puisque vos périphériques ont été intégrés lors de l'étape 3). Vous effectuerez un test final avec vos périphériques sur FPGA et pourrez ainsi tester vos réflexes ! Q1 Fabriquez votre machine et faites fonctionner le programme de jeu de réflexe sur votre machine avec vos périphériques. Vous êtes totalement libre quand aux instructions d'assembleur à réaliser, le format de codage etc. Q2 Innovez selon votre humeur et le temps qu'il vous reste. Prenez en compte l'interruption BussError, ajoutez des périphériques et des interruptions. Step_4_jeu_v2011a.odt 8/8