229 lines
14 KiB
Text
229 lines
14 KiB
Text
%union {
|
|
int nombre;
|
|
}
|
|
%{
|
|
#include "../Tables/tables.h"
|
|
#include <stdio.h>
|
|
|
|
FILE * file;
|
|
FILE * file2;
|
|
|
|
%}
|
|
|
|
%token tMUL tDIV tADD tSUB tINF tSUP tEQU
|
|
%token tAFC tCPY tAFCA
|
|
%token tREAD tWR
|
|
%token tJMP tJMF
|
|
%token tGET tPRI
|
|
%token tCALL tRET
|
|
%token tSTOP
|
|
%token<nombre> tNB
|
|
|
|
%%
|
|
|
|
// Un programme est une suite d'au moins une instruction
|
|
Programme : Instruction Programme;
|
|
Programme : Instruction;
|
|
|
|
|
|
// Liste de toutes les instructions et conversion
|
|
|
|
// MUL, ADD, DIV.... -> 3 arguments
|
|
Instruction : tMUL tNB tNB tNB {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
int added_instruction = 0; // On initialise le compteur d'instruction ajoutées (pour la traduction des sauts
|
|
int reg_src1 = get_reg_read($3, &added_instruction); // On demande un registre en lecture pour l'argument B de l'instruction (adresse)
|
|
// On passe l'adresse de la variable added_instruction pour savoir combien d'instruction ont été rajoutées
|
|
int reg_src2 = get_reg_read($4, &added_instruction); // On demande un registre en lecture pour l'argument C de l'instruction (adresse)
|
|
// On passe l'adresse de la variable added_instruction pour savoir combien d'instruction ont été rajoutées
|
|
int reg_dest = get_reg_write($2, &added_instruction); // On demande un registre en écriture pour l'argument A de l'instruction (adresse)
|
|
// On le fait après la demande en lecture TOUJOURS DEMANDER L'ECRITURE APRES LA LECTURE
|
|
add_instruction(MUL, reg_dest, reg_src1, reg_src2); // On ajoute la traduction de l'instruction MUL
|
|
new_instruction(added_instruction + 1);}; // On déclare le nombre d'instruction ajoutées
|
|
Instruction : tADD tNB tNB tNB {increment_time();
|
|
int added_instruction = 0;
|
|
int reg_src1 = get_reg_read($3, &added_instruction);
|
|
int reg_src2 = get_reg_read($4, &added_instruction);
|
|
int reg_dest = get_reg_write($2, &added_instruction);
|
|
add_instruction(ADD, reg_dest, reg_src1, reg_src2);
|
|
new_instruction(added_instruction + 1);};
|
|
Instruction : tDIV tNB tNB tNB {increment_time();
|
|
int added_instruction = 0;
|
|
int reg_src1 = get_reg_read($3, &added_instruction);
|
|
int reg_src2 = get_reg_read($4, &added_instruction);
|
|
int reg_dest = get_reg_write($2, &added_instruction);
|
|
add_instruction(DIV, reg_dest, reg_src1, reg_src2);
|
|
new_instruction(added_instruction + 1);};
|
|
Instruction : tSUB tNB tNB tNB {increment_time();
|
|
int added_instruction = 0;
|
|
int reg_src1 = get_reg_read($3, &added_instruction);
|
|
int reg_src2 = get_reg_read($4, &added_instruction);
|
|
int reg_dest = get_reg_write($2, &added_instruction);
|
|
add_instruction(SUB, reg_dest, reg_src1, reg_src2);
|
|
new_instruction(added_instruction + 1);};
|
|
Instruction : tINF tNB tNB tNB {increment_time();
|
|
int added_instruction = 0;
|
|
int reg_src1 = get_reg_read($3, &added_instruction);
|
|
int reg_src2 = get_reg_read($4, &added_instruction);
|
|
int reg_dest = get_reg_write($2, &added_instruction);
|
|
add_instruction(INF, reg_dest, reg_src1, reg_src2);
|
|
new_instruction(added_instruction + 1);};
|
|
Instruction : tSUP tNB tNB tNB {increment_time();
|
|
int added_instruction = 0;
|
|
int reg_src1 = get_reg_read($3, &added_instruction);
|
|
int reg_src2 = get_reg_read($4, &added_instruction);
|
|
int reg_dest = get_reg_write($2, &added_instruction);
|
|
add_instruction(SUP, reg_dest, reg_src1, reg_src2);
|
|
new_instruction(added_instruction + 1);};
|
|
Instruction : tEQU tNB tNB tNB {increment_time();
|
|
int added_instruction = 0;
|
|
int reg_src1 = get_reg_read($3, &added_instruction);
|
|
int reg_src2 = get_reg_read($4, &added_instruction);
|
|
int reg_dest = get_reg_write($2, &added_instruction);
|
|
add_instruction(EQU, reg_dest, reg_src1, reg_src2);
|
|
new_instruction(added_instruction + 1);};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// AFC @ val -> AFC Ri val
|
|
Instruction : tAFC tNB tNB {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
int added_instruction = 0; // On initialise le compteur d'instruction ajoutées (pour la traduction des sauts
|
|
int reg_dest = get_reg_write($2, &added_instruction); // On demande un registre en écriture pour l'argument A de l'instruction (adresse)
|
|
add_instruction(AFC, reg_dest, $3, 0); // On ajoute la traduction de l'instruction AFC
|
|
new_instruction(added_instruction + 1);}; // On déclare le nombre d'instruction ajoutées
|
|
// CPY @ @ -> CPY Ri Rj
|
|
Instruction : tCPY tNB tNB {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
int added_instruction = 0; // On initialise le compteur d'instruction ajoutées (pour la traduction des sauts
|
|
int reg_src = get_reg_read($3, &added_instruction); // On demande un registre en lecture pour l'argument B de l'instruction (adresse)
|
|
// On passe l'adresse de la variable added_instruction pour savoir combien d'instruction ont été rajoutées
|
|
int reg_dest = get_reg_write($2, &added_instruction); // On demande un registre en écriture pour l'argument A de l'instruction (adresse)
|
|
// On le fait après la demande en lecture TOUJOURS DEMANDER L'ECRITURE APRES LA LECTURE
|
|
add_instruction(CPY, reg_dest, reg_src, 0); // On ajoute la traduction de l'instruction CPY
|
|
new_instruction(added_instruction + 1);}; // On déclare le nombre d'instruction ajoutées
|
|
// AFCA @ val -> AFC Rlamda val; STOREA @ Rlamda
|
|
Instruction : tAFCA tNB tNB {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
int added_instruction = 0; // On initialise le compteur d'instruction ajoutées (pour la traduction des sauts
|
|
int reg_aux = get_reg_write(-1, &added_instruction); // On demande un registre en écriture
|
|
// On ne veut pas un registre associé a une adresse, juste un buffer d'où le -1
|
|
add_instruction(AFC, reg_aux, $3, 0); // On affecte la valeur dans un registre lamda, elle sera tout de suite enregistré en mémoire
|
|
add_instruction(STOREA, $2, reg_aux, 0); // On store la valeur en mémoire (avec un STOREA car AFCA, nous sommes donc obligé de le faire tout de suite)
|
|
unlink($2); // On casse l'eventuel lien entre l'adresse et un registre
|
|
// Si un registre était déjà associé a cette adresse, la valeur qu'il contient est obsolète, on le libère
|
|
new_instruction(added_instruction + 2);}; // On déclare le nombre d'instruction ajoutées
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// JMP Ins -> JMP Ins
|
|
Instruction : tJMP tNB {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
add_instruction(JMP, $2, 0, 0); // On traduit le JMP sans rien changer
|
|
new_instruction(1);}; // On déclare le nombre d'instruction ajoutées
|
|
// JMF @ Ins -> AFC Rlamda 0; SUB Rlamda Rlamda Ri; JMZ Ins
|
|
Instruction : tJMF tNB tNB {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
int added_instruction = 0; // On initialise le compteur d'instruction ajoutées (pour la traduction des sauts
|
|
int reg_src = get_reg_read($2, &added_instruction); // On demande un registre en lecture pour l'argument A de l'instruction (adresse)
|
|
int reg_aux = get_reg_write(-1, &added_instruction); // On demande un registre en écriture
|
|
// On ne veut pas un registre associé a une adresse, juste un buffer d'où le -1
|
|
add_instrcution(AFC, reg_aux, 0, 0); // On affecte 0 à un registre
|
|
add_instruction(SUB, reg_aux, reg_aux, reg_src); // On Soustrait la valeur à 0, flag 0 levé si la valeur vallait 0 donc condition fausse
|
|
add_instruction(JMZ, $3, 0, 0); // On ajoute le JMZ
|
|
new_instruction(added_instruction + 3);}; // On déclare le nombre d'instruction ajoutées
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// READ @1 @2 -> LOADI @1 @2
|
|
Instruction : tREAD tNB tNB {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
int added_instruction = 0; // On initialise le compteur d'instruction ajoutées (pour la traduction des sauts
|
|
int reg_addr = get_reg_read($3, &added_instruction); // On demande un registre en lecture pour l'adresse de la lecture en mémore
|
|
int reg_dest = get_reg_write($2, &added_instruction); // On demande un registre en écriture pour loader la valeur depuis la mémoire
|
|
add_instruction(LOADI, reg_dest, reg_addr, 0); // On traduit le READ
|
|
new_instruction(added_instruction + 1);}; // On déclare le nombre d'instruction ajoutées
|
|
// WR @1 @2 -> STOREI @1 @2
|
|
Instruction : tWR tNB tNB {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
int added_instruction = 0; // On initialise le compteur d'instruction ajoutées (pour la traduction des sauts
|
|
int reg_addr = get_reg_read($2, &added_instruction); // On demande un registre en lecture pour l'adresse de l'écriture en mémore
|
|
int reg_value = get_reg_read($3, &added_instruction); // On demande un registre en lecture pour la valeur à écrire en mémoire
|
|
add_instruction(STOREI, reg_addr, reg_value, 0); // On traduit le WR
|
|
new_instruction(added_instruction + 1);}; // On déclare le nombre d'instruction ajoutées
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// GET @ -> GET Ri
|
|
Instruction : tGET tNB {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
int added_instruction = 0; // On initialise le compteur d'instruction ajoutées (pour la traduction des sauts
|
|
int reg_dest = get_reg_write($2, &added_instruction); // On demande un registre en ecriture pour écrire la valeur lue
|
|
add_instruction(GET, reg_dest, 0, 0); // On traduit le GET
|
|
new_instruction(added_instruction + 1);}; // On déclare le nombre d'instruction ajoutées
|
|
// PRI @ -> PRI Ri
|
|
Instruction : tPRI tNB {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
int added_instruction = 0; // On initialise le compteur d'instruction ajoutées (pour la traduction des sauts
|
|
int reg_src = get_reg_read($2, &added_instruction); // On demande un registre en lecture pour sortir la valeur à afficher
|
|
add_instruction(PRI, reg_src, 0, 0); // On traduit le PRI
|
|
new_instruction(added_instruction + 1);}; // On déclare le nombre d'instruction ajoutées
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// CALL Ins Val -> CALL Ins Val
|
|
Instruction : tCALL tNB tNB {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
int added_instruction = flush_and_init(file); // On Store tous les registre en mémoire et réinitialise les correspondances
|
|
add_instruction(CALL, $2, $3, 0); // On traduit le CALL
|
|
new_instruction(added_instruction + 1);}; // On déclare le nombre d'instruction ajoutées
|
|
// RET -> RET
|
|
Instruction : tRET {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
int added_instruction = flush_and_init(file); // On Store tous les registre en mémoire et réinitialise les correspondances
|
|
add_instruction(RET, 0, 0, 0); // On traduit le RET
|
|
new_instruction(added_instruction + 1);}; // On déclare le nombre d'instruction ajoutées
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// STOP Val -> STOP -> Val
|
|
Instruction : tSTOP tNB {increment_time(); // On incrémente le temps, c'est a dire, une instruction de plus a été traduite (pour la politique LRU)
|
|
add_instruction(STOP, $2, 0, 0); // On traduit le STOP
|
|
new_instruction(1);}; // On déclare le nombre d'instruction ajoutées
|
|
|
|
%%
|
|
|
|
int main(void) {
|
|
file = fopen("output.asm", "w");
|
|
file2 = fopen("output.bin", "w");
|
|
init();
|
|
yyparse();
|
|
write_asm(file);
|
|
write_code_machine(file2, 0);
|
|
return 0;
|
|
}
|