CrossAssembleur/Lex_Yacc/as.y

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;
}