diff options
author | Ludovic Pouzenc <ludovic@pouzenc.fr> | 2010-09-18 08:23:48 +0000 |
---|---|---|
committer | Ludovic Pouzenc <ludovic@pouzenc.fr> | 2010-09-18 08:23:48 +0000 |
commit | 804cac5bcade6e128573d697c70fb23050f823f7 (patch) | |
tree | c6949c5a4651fae005211973635fa7e807b2d591 /misc-test | |
parent | 064ad15bb543f5f6649831f47bd4dfd6cb4262af (diff) | |
download | 2010-netlemmings-804cac5bcade6e128573d697c70fb23050f823f7.tar.gz 2010-netlemmings-804cac5bcade6e128573d697c70fb23050f823f7.tar.bz2 2010-netlemmings-804cac5bcade6e128573d697c70fb23050f823f7.zip |
autres corrections pour que ça compile. Bon, ça compile toujours pas. Ajout pour exemple du compilateur c que j'avais fait à l'insa (et la machine virtuelle pour exec le code aussi)
git-svn-id: file:///var/svn/2010-netlemmings/trunk@32 077b3477-7977-48bd-8428-443f22f7bfda
Diffstat (limited to 'misc-test')
23 files changed, 1334 insertions, 0 deletions
diff --git a/misc-test/compilateur_c_en_c/Makefile b/misc-test/compilateur_c_en_c/Makefile new file mode 100644 index 0000000..407ea8e --- /dev/null +++ b/misc-test/compilateur_c_en_c/Makefile @@ -0,0 +1,14 @@ + +default: compil + +lex.yy.c: compil.lex + flex compil.lex + #flex --debug compil.lex +y.tab.c: compil.yy + yacc -v -d compil.yy + +compil: y.tab.c lex.yy.c table_sym.c table_sym.h reloc.c reloc.h + gcc -g -Wall y.tab.c lex.yy.c table_sym.c reloc.c -ll -o compil + +clean: + rm compil lex.yy.c y.tab.c y.tab.h y.output || true diff --git a/misc-test/compilateur_c_en_c/asm_defs.h b/misc-test/compilateur_c_en_c/asm_defs.h new file mode 100644 index 0000000..6dff988 --- /dev/null +++ b/misc-test/compilateur_c_en_c/asm_defs.h @@ -0,0 +1,26 @@ +#ifndef ASM_DEFS_H +#define ASM_DEFS_H + + +#define I_NOP 0x0 +#define I_ADD 0x1 +#define I_MUL 0x2 +#define I_SOU 0x3 +#define I_DIV 0x4 +#define I_COP 0x5 +#define I_AFC 0x6 +#define I_JMP 0x7 +#define I_JMF 0x8 +#define I_INF 0x9 +#define I_SUP 0xa +#define I_EQU 0xb +#define I_PRI 0xc + +#define PAD '_' +#define UNK 0xff + +char instructionNames[][4] = { + "NOP", "ADD", "MUL", "SOU", "DIV", "COP", "AFC", "JMP", "JMF", "INF", "SUP", "EQU", "PRI" +}; + +#endif /* ASM_DEFS_H */ diff --git a/misc-test/compilateur_c_en_c/compil.lex b/misc-test/compilateur_c_en_c/compil.lex new file mode 100644 index 0000000..f298704 --- /dev/null +++ b/misc-test/compilateur_c_en_c/compil.lex @@ -0,0 +1,80 @@ +%{ + #include "y.tab.h" + #include "reloc.h" /* Pour MAX_LABEL_LEN */ + + #include <string.h> + +%} + +%option nounput + + +CHIFFRE [0-9] +BLANC [ \t\n] +IDENTIFICATEUR [a-zA-Z][a-zA-Z0-9_]* + +%x MLCOMMENT + /* %s : inclusive start condition (inclus aussi les règles sans <cond>) + %x : exclusive start condition (règles sans <cond> inactives) + */ + +%% + +"/*" BEGIN(MLCOMMENT); +<MLCOMMENT>\n yylineno++;; +<MLCOMMENT>"*/" BEGIN(INITIAL); +<MLCOMMENT>. ; + +"//"[^\n]*\n yylineno++; /* Single line Comment*/ + +if return IF; +else return ELSE; +while return WHILE; +do return DO; +for return FOR; +switch return SWITCH; + +main{BLANC}*\({BLANC}*\) return MAIN; +printf return PRINTF; +\{ return '{'; +\} return '}'; +const return CONST; +int return INT; +"*" return '*'; +"/" return '/'; +"+" return '+'; +"-" return '-'; +">" return '>'; +"<" return '<'; +"=" return AFF; +"==" return EGALE; +"!=" return DIFFERENT; +"++" return INCR; +"--" return DECR; +\( return '('; +\) return ')'; +{IDENTIFICATEUR} { + int lg = strlen(yytext); + if ( lg > MAX_LABEL_LEN ) { + return LEXERROR; + } else { + yylval.str = malloc(sizeof(char)*lg); + strcpy(yylval.str, yytext); + return IDENTIFICATEUR; + } + } +{CHIFFRE}+ { + yylval.nb = atoi(yytext); + return ENTIER; + } + +"," return ','; +";" return ';'; +\n yylineno++; /*printf("\n");*/ +{BLANC} /*printf("BLANC");*/ + +[^ \t\n] fprintf(stderr, "LEX : ERROR : unknown char '%c'", yytext[0]); // TODO standardiser le msg d'erreur + /*[ \t] ;*/ +%% + + diff --git a/misc-test/compilateur_c_en_c/compil.yy b/misc-test/compilateur_c_en_c/compil.yy new file mode 100644 index 0000000..2ed4ad4 --- /dev/null +++ b/misc-test/compilateur_c_en_c/compil.yy @@ -0,0 +1,429 @@ +%{ + #include "y.tab.h" + #include "table_sym.h" + #include "reloc.h" + #include "asm_defs.h" + + #include <stdio.h> + #include <stdlib.h> + #include <string.h> + + + symbolStack tableSym = NULL; // Table de symboles initialement vide + extern int yylineno; // Bidouille pour avoir le numero de ligne du lexer ^^ + + int SP = 0; // StackPointer + int contextProf = 0; // Profondeur de contexte + int tempCount = 0; // Compteur pour génerer des noms de temporaires uniques + int structCount = 0; // Compteur pour génerer des noms de labels pour les structures unique + + + int yylex(); + void yyerror(char *s); + void warning(char *msg); + + struct symbolEntry * addSym(char *varName, int contextProf, int readOnly); + void genCode(int opcode, int op1, int op2, int op3); + void genCodeJump(int opcode, int op1, int op2, int op3, char *targetLabel); + void genLabel(char *lbl, char *prefix, int id); + struct symbolEntry * createTempo(); +%} + + +%token LEXERROR + +%token IF +%token ELSE +%token WHILE +%token DO +%token FOR +%token SWITCH + +%token MAIN +%token CONST +%token INT +%token PRINTF + +%token AFF + /* TODO : += -= *= /= */ +%nonassoc EGALE DIFFERENT +%nonassoc '>' '<' +%left '+' '-' +%left '*' '/' + +%token INCR DECR /* TODO : priorité ? */ + /* TODO : affectations conditionnelles : <cond>?<then>:<else> */ + +%token <str> IDENTIFICATEUR +%token <nb> ENTIER + + +%type <nb> Entier + +%type <nb> InitVarLoc +%type <sym> DeclVarLoc1 +%type <sym> DeclConst1 + +%type <sym> Symbole +%type <sym> Constante + +%type <sym> LValue +%type <sym> RValue + +%type <nb> BeginIf +%type <nb> BeginFor +%type <nb> BeginWhile +%type <nb> BeginDoWhile +%type <nb> BeginSwitch + +%union { int nb; char *str; struct symbolEntry *sym; } + +%start Prog +%% + +Prog: MAIN Block { /* printSymTable(tableSym);*/ } +Block: '{' { contextProf++; } + Declarations + Instructions + '}' { /* printf("Block\n");*/ + /*printSymTable(tableSym);*/ + cleanSymStack(&tableSym, --contextProf); + } + +BlockOuInstr: Block + | Instruction + + +Declarations: /*vide*/ { printf("Declaration vide\n"); } + | Decl ';' Declarations + +Decl: INT DeclVarLocList { /*printf("Decl\n");*/ } + | CONST INT DeclConstList + | error /* TODO : essayer de perdre moins d'informations */ + +/*********************** +** Liste de variables ** +***********************/ +DeclVarLocList: DeclVarLoc { /* printf("DeclVarLoc\n");*/ } + | DeclVarLoc ',' DeclVarLocList + + +DeclVarLoc: DeclVarLoc1 { /*printf("Variable non initalisee : '%s'\n", $1->symName);*/ } + | DeclVarLoc1 InitVarLoc { + //printf("Variable initalisee '%s' à %i\n", $1->symName, $2); + if ( $1 == NULL ) + { + yyerror("Symbol already declared"); + YYERROR; + } else { + genCode(I_AFC, $1->address, $2, PAD); + $1->initialized = 1; // oui (et pas peut-être, car nouveau profondeur) + } + } + +DeclVarLoc1: IDENTIFICATEUR { $$ = addSym($1, contextProf, 0); } + +InitVarLoc: AFF Entier { $$=$2; /*printf("Init à la valeur %i\n", $2);*/ } + +/************************ +** Liste de constantes ** +************************/ +DeclConstList: DeclConst + | DeclConst ',' DeclConstList + +DeclConst: DeclConst1 AFF Entier { + if ( $1 == NULL ) { + yyerror("Symbol already declared"); + YYERROR; + } else { + genCode(I_AFC, $1->address, $3, PAD); + $1->initialized = 1; // oui (et pas peut-être, car nouveau profondeur) + } + } + +DeclConst1: IDENTIFICATEUR { $$ = addSym($1, contextProf, 1); } + +/***************** +** Instructions ** +*****************/ +Instructions: /* Vide */ + | Instruction Instructions /* TODO : ajouter gestion d'erreur */ + +Instruction: PRINTF '(' RValue ')' ';' + { + if ( $3->initialized == 0) // non + { + yyerror("Symbol uninitialized"); + YYERROR; + } else { + if ( $3->initialized == 2 ) // peut-etre + { + warning("Symbol may be uninitialized"); + } + genCode(I_PRI, $3->address, PAD, PAD); + } + } + + | LValue AFF RValue ';' { + genCode(I_COP, $1->address, $3->address, PAD); + + if ( contextProf > 0 ) + { + $1->initialized=2; // TODO peut-être (gestion très limitée car nécessiterai un arbre de contextes numerotés au minimum pour être plus fin) + } else { + $1->initialized=1; // oui (on est dans le main) + } + } + + | BeginIf Block/*OuInstr*/ { // TODO : comprendre pourquoi ça génère un décalage/réduction + char lbl[MAX_LABEL_LEN]; + genLabel(lbl, "if1_",$1); + writeLabel(lbl); + } + + + | BeginIf Block/*OuInstr*/ ELSE { + char lbl[MAX_LABEL_LEN]; + genLabel(lbl, "if2_", $1); + genCodeJump(I_JMP, UNK, PAD, PAD, lbl); + + genLabel(lbl, "if1_", $1); + writeLabel(lbl); + } + BlockOuInstr { + char lbl[MAX_LABEL_LEN]; + genLabel(lbl,"if2_",$1); + writeLabel(lbl); + } + + | BeginWhile BlockOuInstr { + char lbl[MAX_LABEL_LEN]; + genLabel(lbl, "wh1_", $1); + genCodeJump(I_JMP, UNK, PAD, PAD, lbl); + + genLabel(lbl, "wh2_", $1); + writeLabel(lbl); + } + + | BeginFor '(' Instruction { + char lbl[MAX_LABEL_LEN]; + genLabel(lbl, "for1_",$1); + } + RValue { + char lbl[MAX_LABEL_LEN]; + genLabel(lbl, "for2_",$1); + //genCodeJump(I_JMF, $4->address, PAD, PAD, lbl); TODO comprendre pourquoi compile pas + } + IDENTIFICATEUR INCR ')' Block /* Bricolage pour pas avoir a différer de la génération de code :S */ + { + //struct symbolEntry *forVar; + /* TODO : choper le symbole de $5 puis genCode... */ + yyerror("For not yet fully implemented !"); + + char lbl1[MAX_LABEL_LEN], lbl2[MAX_LABEL_LEN]; + genLabel(lbl1, "for1_", $1); // FIXME : $1 pointe vers IDENTIFICATEUR ??? + genLabel(lbl2, "for2_", $1); + + genCodeJump(I_JMP, UNK, PAD, PAD, lbl1); + + writeLabel(lbl2); + } + + | BeginDoWhile BlockOuInstr WHILE '(' RValue ')' ';' + { + char lbl1[MAX_LABEL_LEN], lbl2[MAX_LABEL_LEN]; + genLabel(lbl1, "do1_", $1); + genLabel(lbl2, "do2_", $1); + + genCodeJump(I_JMF, $5->address, UNK, PAD, lbl2); + genCodeJump(I_JMP, UNK, PAD, PAD, lbl1); + + writeLabel(lbl2); + } + +BeginFor: FOR { $$=structCount++; } +BeginSwitch: SWITCH { $$=structCount++; } + +BeginIf: IF '(' RValue ')' { + char lbl[MAX_LABEL_LEN]; + $$=structCount++; + genLabel(lbl, "if1_", $$); + genCodeJump(I_JMF, $3->address, UNK, PAD, lbl); + } + +BeginWhile: WHILE '(' RValue ')' { + char lbl[MAX_LABEL_LEN]; + $$=structCount++; + genLabel(lbl, "wh1_", $$); + writeLabel(lbl); + genLabel(lbl, "wh2_", $$); + genCodeJump(I_JMF, $3->address, UNK, PAD, lbl); + } + +BeginDoWhile: DO { + char lbl[MAX_LABEL_LEN]; + $$=structCount++; + genLabel(lbl, "do1_", $$); + writeLabel(lbl); + } + +Symbole: IDENTIFICATEUR { + $$=symbolFind(tableSym, $1, contextProf, contextProf); + if ( $$==NULL ) { + yyerror("Symbol not declared"); + YYERROR; + } + } + +LValue: Symbole { + if ( $1->readOnly ) + { + $$=NULL; + yyerror("Not a valid LValue : is read-only"); + YYERROR; + } else { + $$=$1; + } + } +/* Version de base, sans optimisation de calculs ni constantes composées +RValue: Constante { $$=$1; } + | Symbole { $$=$1; } + | '(' RValue ')' { $$=$2; } + | RValue '+' RValue { $$=createTempo(); genCode(I_ADD, $$->address, $1->address, $3->address); } + | RValue '*' RValue { $$=createTempo(); genCode(I_MUL, $$->address, $1->address, $3->address); } + | RValue '-' RValue { $$=createTempo(); genCode(I_SOU, $$->address, $1->address, $3->address); } + | RValue '/' RValue { $$=createTempo(); genCode(I_DIV, $$->address, $1->address, $3->address); } + | RValue '<' RValue { $$=createTempo(); genCode(I_INF, $$->address, $1->address, $3->address); } + | RValue '>' RValue { $$=createTempo(); genCode(I_SUP, $$->address, $1->address, $3->address); } + | RValue EGALE RValue { $$=createTempo(); genCode(I_EQU, $$->address, $1->address, $3->address); } + + +Constante: ENTIER { $$=createTempo(); genCode(I_AFC, $$->address, $1, PAD); $$->initialized=1; $$->readOnly=1; } +*/ + + +RValue: Constante { $$=$1; } + | Symbole { $$=$1; } + | '(' RValue ')' { $$=$2; } + | AddsOrSubs { $$=$1 } + | Muls { $$=$1 } + | RValue '/' RValue { $$=createTempo(); genCode(I_DIV, $$->address, $1->address, $3->address); } + | RValue '<' RValue { $$=createTempo(); genCode(I_INF, $$->address, $1->address, $3->address); } + | RValue '>' RValue { $$=createTempo(); genCode(I_SUP, $$->address, $1->address, $3->address); } + | RValue EGALE RValue { $$=createTempo(); genCode(I_EQU, $$->address, $1->address, $3->address); } + +AddOrSubs: AddOrSubs '+' RValue + + { $$=createTempo(); genCode(I_ADD, $$->address, $1->address, $3->address); } + + +/* Vieux truc : +// TODO : ça marche pas avec a=2-a; --> obligé d'avoir un GLR parser ? +Entier: ENTIER { $$=$1; } + | '(' Entier ')' { $$=$2; } + | Entier '+' Entier %prec CST_PLUS { $$=$1+$3; } + | Entier '*' Entier %prec CST_MUL { $$=$1*$3; } + | Entier '-' Entier %prec CST_MOINS { $$=$1-$3; } + | Entier '/' Entier %prec CST_DIV { $$=$1/$3; } + | Entier '<' Entier %prec CST_INF { $$=$1<$3; } + | Entier '>' Entier %prec CST_SUP { $$=$1>$3; } + | Entier EGALE Entier %prec CST_EGALE { $$=$1==$3; } + +*/ +%% +void yyerror(char *s) +{ + //fprintf(stderr, "Syntax Error : '%s' at l%d,c%d-l%d,c%d\n", s, @$.first_column, @$.last_line, @$.last_column); // Nécessite l'option %locations et un lexer qui va bien + fprintf(stderr, "(stdin):%i: error: %s\n", yylineno, s); +} + +void warning(char *msg) +{ + fprintf(stderr, "(stdin):%i: warning: %s\n", yylineno, msg); +} + +int main(int argc, char **argv) +{ // Par défaut, c'est l'analyse LEXICALE qui est lancée ! + if ( argc != 2 ) { + fprintf(stderr, "Usage : %s <nom_fichier_sortie>\n", argv[0]); + exit(-1); + } + + printf("Opening...\n"); + openWriteDestFiles(argv[1]); + printf("Parsing...\n"); // TODO : fichier d'entrée + yyparse(); + printf("Closing...\n"); + closeDestFiles(); + printf("Linking...\n"); + linker(argv[1],0); // TODO tester autre que 0 + + return 0; +} + +// TODO : passer &tableSym en param +struct symbolEntry * addSym(char *varName, int contextProf, int readOnly) +{ + struct symbolEntry *sym = NULL; + + if ( symbolFind(tableSym, varName, contextProf, contextProf) == NULL ) + { + sym = malloc(1*sizeof(struct symbolEntry)); + + sym->symName = malloc(strlen(varName) * sizeof(char)); + strcpy(sym->symName,varName); + sym->address = SP++; + sym->readOnly = readOnly; + sym->initialized = 0; + sym->contextProf = contextProf; + + + symbolPush(&tableSym,sym); + } /* else return NULL */ + + + return sym; +} + +void genCode(int opcode, int op1, int op2, int op3) +{ + writeCode(opcode,op1,op2,op3); +} + +void genCodeJump(int opcode, int op1, int op2, int op3, char *targetLabel) +{ + int addr=writeCode(opcode,op1,op2,op3); + switch (opcode) { + case I_JMP: + writeHole(addr+1, targetLabel); + break; + case I_JMF: + writeHole(addr+2, targetLabel); + break; + default: + yyerror("Internal error : genCodeJump called whiout a I_JMP or I_JMF opcode"); + /* YYERROR; TODO : dégager...*/ + break; + } +} + +void genLabel(char *lbl, char *prefix, int id) +{ + sprintf(lbl, "!%s%d", prefix, id); +} + +struct symbolEntry * createTempo() +{ + char tempoName[MAX_LABEL_LEN]; + struct symbolEntry *sym = NULL; + + sprintf(tempoName, "!tempo%d", tempCount++); // TODO : si tempo trop long, bug + sym = addSym(tempoName, contextProf, 1); + if ( sym == NULL ) { + yyerror("Error while declaring a temp variable"); + /*YYERROR;*/ + } + return sym; +} + +// TODO : variable globales en dehors du main ? diff --git a/misc-test/compilateur_c_en_c/reloc.c b/misc-test/compilateur_c_en_c/reloc.c new file mode 100644 index 0000000..511a4ec --- /dev/null +++ b/misc-test/compilateur_c_en_c/reloc.c @@ -0,0 +1,141 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "reloc.h" + +FILE *fdObj, *fdLbl, *fdHol, *fdBin; + + + +void findLabelAddress(char *label, char *buf); + +int openWriteDestFiles(char fileName[]) +{ + char *fnObj = malloc(strlen(fileName)+4+1); + char *fnLbl = malloc(strlen(fileName)+4+1); + char *fnHol = malloc(strlen(fileName)+4+1); + + strcpy(fnObj, fileName); + strcpy(fnLbl, fileName); + strcpy(fnHol, fileName); + + strcat(fnObj, EXT_CODE); + strcat(fnLbl, EXT_LABELS); + strcat(fnHol, EXT_HOLES); + + fdObj = fopen(fnObj, "w"); + fdLbl = fopen(fnLbl, "w"); + fdHol = fopen(fnHol, "w"); + + return (fdObj!=NULL) && (fdLbl!=NULL) && (fdHol!=NULL); +} + +int writeCode(int opcode, int op1, int op2, int op3) +{ + char ins[4]; + int currAddr; + + ins[0]=opcode & 0xFF; + ins[1]=op1 & 0xFF; + ins[2]=op2 & 0xFF; + ins[3]=op3 & 0xFF; // TODO : est-ce bien propre ? Little ou big endian ? + + currAddr = (int) ftell(fdObj); + fwrite(ins, sizeof(char), 4, fdObj); + + return currAddr; +} + +void writeLabel(char *label) +{ + fprintf(fdLbl, "0x%02x\t%s\n", (int)ftell(fdObj), label); +} + +void writeHole(int holeAddr, char *label) +{ + fprintf(fdHol, "0x%02x\t%s\n", holeAddr, label); +} + +void closeDestFiles() +{ + fclose(fdObj); fclose(fdLbl); fclose(fdHol); +} + +/* +int ftellCode(){ + return ftell(fdObj); +}*/ + +void linker(char fileName[], int baseAddress) // Génère le .bin a partir des .obj, .lbl, .hol +{ + char *fnObj = malloc(strlen(fileName)+4+1); + char *fnLbl = malloc(strlen(fileName)+4+1); + char *fnHol = malloc(strlen(fileName)+4+1); + char *fnBin = malloc(strlen(fileName)+4+1); + + strcpy(fnObj, fileName); + strcpy(fnLbl, fileName); + strcpy(fnHol, fileName); + strcpy(fnBin, fileName); + + strcat(fnObj, EXT_CODE); + strcat(fnLbl, EXT_LABELS); + strcat(fnHol, EXT_HOLES); + strcat(fnBin, EXT_EXEC); + + fdObj = fopen(fnObj, "r"); + fdLbl = fopen(fnLbl, "r"); + fdHol = fopen(fnHol, "r"); + fdBin = fopen(fnBin, "w"); + + int holeAddr=0, i; + char label[MAX_LABEL_LEN]; + char buf; + + while ( fscanf(fdHol, "0x%02x\t%s\n", &holeAddr, label) == 2 ) + { + int targetAddr = ftell(fdObj); + + for(i=0; i<holeAddr-targetAddr; i++) + { + fread(&buf, 1, 1, fdObj); + fwrite(&buf, 1, 1, fdBin); + } + fread(&buf, 1, 1, fdObj); // Saute le trou dans le fichier d'entrée + + findLabelAddress(label, &buf); + + fwrite(&buf, 1, 1, fdBin); // Bouche le trou dans le fichier de sortie + + } + + while (fread(&buf, 1, 1, fdObj)) // Ecrit la fin du fichier + { + fwrite(&buf, 1, 1, fdBin); + } + + fclose(fdObj); + fclose(fdLbl); + fclose(fdHol); + fclose(fdBin); +} + +void findLabelAddress(char *label, char *buf) { + + int relAddr, found=0; + char currLabel[MAX_LABEL_LEN]; + + fseek(fdLbl, 0, SEEK_SET); + + while ( !found && fscanf(fdLbl, "0x%02x\t%s\n", &relAddr, currLabel) == 2 ) + { + found = ( strcmp(currLabel, label) == 0 ); + *buf = (char) (relAddr & 0xFF); + } + + if (!found) + { + fprintf(stderr, "linker: ERROR : '%s' not found in .lbl file\n", label); + } +} diff --git a/misc-test/compilateur_c_en_c/reloc.h b/misc-test/compilateur_c_en_c/reloc.h new file mode 100644 index 0000000..684030b --- /dev/null +++ b/misc-test/compilateur_c_en_c/reloc.h @@ -0,0 +1,37 @@ +#ifndef RELOC_H +#define RELOC_H + +#define EXT_CODE ".obj" +#define EXT_LABELS ".lbl" +#define EXT_HOLES ".hol" +#define EXT_EXEC ".bin" +#define MAX_LABEL_LEN 16 + +#include "table_sym.h" +#include <stdio.h> + +struct labels { + char *label; + int relAddr; +}; + +struct holes { + int holeAddr; + char *label; +}; + +int openWriteDestFiles(char fileName[]); + + +int writeCode(int opcode, int op1, int op2, int op3); // Retourne l'adresse relative du debut de l'instruction +void writeLabel(char *label); +void writeHole(int holeAddr, char *label); + +void closeDestFiles(); + +//int ftellCode(); // Retourne l'adresse relative de la prochaine instruction à écrire dans le fichier .obj + +void linker(char fileName[], int baseAddress); // Génère le .bin a partir des .obj, .lbl, .hol + + +#endif /* RELOC_H */ diff --git a/misc-test/compilateur_c_en_c/table_sym.c b/misc-test/compilateur_c_en_c/table_sym.c new file mode 100644 index 0000000..9fa3803 --- /dev/null +++ b/misc-test/compilateur_c_en_c/table_sym.c @@ -0,0 +1,71 @@ +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#include "table_sym.h" + +void symbolPush(symbolStack *symStack, struct symbolEntry *sym) +{ + struct symbolStackCell *newCell = malloc(sizeof(struct symbolStackCell)); + newCell->symbol = sym; + newCell->next = *symStack; + *symStack=newCell; +} + +struct symbolEntry * symbolFind(symbolStack symStack, char *symName, int contextMinProf, int contextMaxProf) +{ + struct symbolEntry *res = NULL; + int trouve = 0; + while (!trouve && symStack != NULL) + { + if ( strcmp(symStack->symbol->symName,symName) == 0 + && symStack->symbol->contextProf >= contextMinProf + && symStack->symbol->contextProf <= contextMaxProf ) + { + trouve=1; + res=symStack->symbol; + } else { + symStack=symStack->next; + } + } + return res; +} + +void printSymTable(symbolStack symStack) +{ + printf("DEBUG :Table des symboles\n"); + printf("const?\t nom variable\taddress\tinit?\tcontextProf\n"); + for(;symStack!=NULL;symStack=symStack->next) + { + if ( symStack->symbol->readOnly ) + { + printf("const\t%20s\t%x\t%i\t%i\n", symStack->symbol->symName, + symStack->symbol->address, + symStack->symbol->initialized, + symStack->symbol->contextProf); + } else { + printf("\t%20s\t%x\t%i\t%i\n", symStack->symbol->symName, + symStack->symbol->address, + symStack->symbol->initialized, + symStack->symbol->contextProf); + } + } + + printf("FIN DEBUG\n"); +} + +void cleanSymStack(symbolStack *symStack, int contextProf) +{ + printf("void cleanSymStack(symbolStack *symStack, %i)\n", contextProf); + while ((*symStack)!=NULL && ((*symStack)->symbol->contextProf > contextProf)) + { + symbolStack next = (*symStack)->next; + + free( (*symStack)->symbol->symName ); + free( (*symStack)->symbol ); + free( (*symStack) ); + + *symStack = next; + } +} + diff --git a/misc-test/compilateur_c_en_c/table_sym.h b/misc-test/compilateur_c_en_c/table_sym.h new file mode 100644 index 0000000..e26977f --- /dev/null +++ b/misc-test/compilateur_c_en_c/table_sym.h @@ -0,0 +1,32 @@ +#ifndef TABLE_SYM_H +#define TABLE_SYM_H + +struct symbolEntry { + char * symName; + unsigned int address; + int readOnly; + int initialized; // 0 : non , 1: oui, 2: peut-être ^^ + unsigned int contextProf; +}; + + +// TODO : déclarer liste chainée d'instructions +struct instruction { +// unsigned int numi; // Numéro d'instruction + char *label; // Label de la ligne courante (0 = pas de label) + unsigned int opcode; // Code operation (cf table correspondance pour avoir la forme textuelle) + unsigned int op1, op2, op3; // Operandes +}; + +struct symbolStackCell { + struct symbolEntry *symbol; + struct symbolStackCell *next; +}; + +typedef struct symbolStackCell* symbolStack; + +void symbolPush(symbolStack *symStack, struct symbolEntry *sym); +struct symbolEntry * symbolFind(symbolStack symStack, char *symName, int contextMinProf, int contextMaxProf); +void printSymTable(symbolStack symStack); +void cleanSymStack(symbolStack *symStack, int contextProf); +#endif /*TABLE_SYM_H*/ diff --git a/misc-test/compilateur_c_en_c/test.sh b/misc-test/compilateur_c_en_c/test.sh new file mode 100755 index 0000000..df83422 --- /dev/null +++ b/misc-test/compilateur_c_en_c/test.sh @@ -0,0 +1 @@ +make clean && make && ./compil out < tests_parse/test4.c && disasm/disasm out.bin diff --git a/misc-test/compilateur_c_en_c/tests_parse/test.c b/misc-test/compilateur_c_en_c/tests_parse/test.c new file mode 100644 index 0000000..9cd70a5 --- /dev/null +++ b/misc-test/compilateur_c_en_c/tests_parse/test.c @@ -0,0 +1,4 @@ +main ( ) { + int a = 3, b, c=4; + const int d = 3, e=5, c=6; +} diff --git a/misc-test/compilateur_c_en_c/tests_parse/test2.c b/misc-test/compilateur_c_en_c/tests_parse/test2.c new file mode 100644 index 0000000..1b5f66c --- /dev/null +++ b/misc-test/compilateur_c_en_c/tests_parse/test2.c @@ -0,0 +1,8 @@ +main ( ) { + int a = 3, b, c=4; +/* const int d = 3, e=5, c=6; + * blabla + */ + const int d = 3, e=5, c=6; + +} diff --git a/misc-test/compilateur_c_en_c/tests_parse/test3.c b/misc-test/compilateur_c_en_c/tests_parse/test3.c new file mode 100644 index 0000000..2905795 --- /dev/null +++ b/misc-test/compilateur_c_en_c/tests_parse/test3.c @@ -0,0 +1,29 @@ +// Coucou +main ( ) { + int a = 3, b, c=4; +/* const int d = 3, e=5, c=6; + * blabla + */ + const int d = 3, e=5, c=6, f=3; + int a = 6; + int za = 6; + + printf(a); + // Pas clop + printf(b); + printf(d); + printf(za); + + a=c; + //a=b; + b=a; + a=b; + + if ( 0 ) { + int c=7; + b=a; + printf(b); // On ne peut pas simplement gérer ce cas pour ne pasafficher de Warning + } + printf(b);// Car ce cas est possible ^^ + +} diff --git a/misc-test/compilateur_c_en_c/tests_parse/test4.c b/misc-test/compilateur_c_en_c/tests_parse/test4.c new file mode 100644 index 0000000..0102947 --- /dev/null +++ b/misc-test/compilateur_c_en_c/tests_parse/test4.c @@ -0,0 +1,13 @@ +// Coucou +main ( ) { + if ( 0 ) { + printf(1); + } + printf(2); + if ( 0 ) { + printf(3); + } else { + printf(4); + } + printf(5); +} diff --git a/misc-test/compilateur_c_en_c/tests_parse/test5.c b/misc-test/compilateur_c_en_c/tests_parse/test5.c new file mode 100644 index 0000000..9afb03c --- /dev/null +++ b/misc-test/compilateur_c_en_c/tests_parse/test5.c @@ -0,0 +1,12 @@ +// Coucou +main ( ) { + if ( 1 ) { + printf(1); + if (2) { printf(2); } + printf(3); + } else { + printf(4); + if (5) { printf(5); } else { printf(6); } + printf(7); + } +} diff --git a/misc-test/compilateur_c_en_c/tests_parse/test6.c b/misc-test/compilateur_c_en_c/tests_parse/test6.c new file mode 100644 index 0000000..f177284 --- /dev/null +++ b/misc-test/compilateur_c_en_c/tests_parse/test6.c @@ -0,0 +1,16 @@ +// Coucou +main ( ) { + if ( 0 ) { + printf(1); + } + printf(2); + while ( 0 ) { + printf(3); + } + + do { + printf(4); + } while (0); + + printf(5); +} diff --git a/misc-test/compilateur_c_en_c/tests_parse/test7.c b/misc-test/compilateur_c_en_c/tests_parse/test7.c new file mode 100644 index 0000000..926dad3 --- /dev/null +++ b/misc-test/compilateur_c_en_c/tests_parse/test7.c @@ -0,0 +1,6 @@ +// Coucou +main ( ) { + int a = 1+2-3*2/2<12*8+4; + a = a*2-a>a*a*a; + printf(a); +} diff --git a/misc-test/compilateur_c_en_c/vm/compil.sh b/misc-test/compilateur_c_en_c/vm/compil.sh new file mode 100755 index 0000000..42d7087 --- /dev/null +++ b/misc-test/compilateur_c_en_c/vm/compil.sh @@ -0,0 +1,2 @@ +gcc -Wall -o vm vm.c +gcc -Wall -g -lpanel -lncurses -o vm_ncurses vm_ncurses.c diff --git a/misc-test/compilateur_c_en_c/vm/pgcd.bin b/misc-test/compilateur_c_en_c/vm/pgcd.bin Binary files differnew file mode 100644 index 0000000..d627e98 --- /dev/null +++ b/misc-test/compilateur_c_en_c/vm/pgcd.bin diff --git a/misc-test/compilateur_c_en_c/vm/toto.bin b/misc-test/compilateur_c_en_c/vm/toto.bin Binary files differnew file mode 100644 index 0000000..0c72cb1 --- /dev/null +++ b/misc-test/compilateur_c_en_c/vm/toto.bin diff --git a/misc-test/compilateur_c_en_c/vm/vm b/misc-test/compilateur_c_en_c/vm/vm Binary files differnew file mode 100755 index 0000000..88697bb --- /dev/null +++ b/misc-test/compilateur_c_en_c/vm/vm diff --git a/misc-test/compilateur_c_en_c/vm/vm.c b/misc-test/compilateur_c_en_c/vm/vm.c new file mode 100644 index 0000000..4e1cf24 --- /dev/null +++ b/misc-test/compilateur_c_en_c/vm/vm.c @@ -0,0 +1,88 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../asm_defs.h" + +#define MEM_SIZE 256 + + +int main(int argc, char *argv[]) +{ + FILE *fdBin; + char buf[4]; + char *mem = calloc(MEM_SIZE, sizeof(char)); + + if ( argc !=2 ) + { + fprintf(stderr, "Usage : %s <bin_file>\n", argv[0]); + return -1; + } + + fdBin = fopen(argv[1], "r"); + if ( fdBin == NULL ) + { + fprintf(stderr, "ERROR : can't open file '%s'\n", argv[1]); + return -1; + } + + while (fread(buf, 4, 1, fdBin)) + { + //TODO : vérification pour l'opCode, ne pas aller en dehors de la table si code erroné + printf("@0x%02x:\t%s\t0x%02x\t0x%02x\t0x%02x\n", + (int) ftell(fdBin), + instructionNames[(int)buf[0]], + (unsigned int) buf[1] & 0xFF, + (unsigned int) buf[2] & 0xFF, + (unsigned int) buf[3] & 0xFF + ); + + switch (buf[0]) + { + case I_NOP: + break; + case I_ADD: + mem[(int)buf[1]] = mem[(int)buf[2]] + mem[(int)buf[3]]; + break; + case I_MUL: + mem[(int)buf[1]] = mem[(int)buf[2]] * mem[(int)buf[3]]; + break; + case I_SOU: + mem[(int)buf[1]] = mem[(int)buf[2]] - mem[(int)buf[3]]; + break; + case I_DIV: + mem[(int)buf[1]] = mem[(int)buf[2]] / mem[(int)buf[3]]; + break; + case I_COP: + mem[(int)buf[1]] = mem[(int)buf[2]]; + break; + case I_AFC: + mem[(int)buf[1]] = buf[2]; + break; + case I_JMP: + fseek(fdBin, (long)buf[1], SEEK_SET); + break; + case I_JMF: + if (!mem[(int)buf[1]]) { fseek(fdBin, (long)buf[2]&0xFF, SEEK_SET); } + break; + case I_INF: + mem[(int)buf[1]] = mem[(int)buf[2]] < mem[(int)buf[3]]; + break; + case I_SUP: + mem[(int)buf[1]] = mem[(int)buf[2]] > mem[(int)buf[3]]; + break; + case I_EQU: + mem[(int)buf[1]] = mem[(int)buf[2]] == mem[(int)buf[3]]; + break; + case I_PRI: + printf("PRI : %x\n", (int) mem[(int)buf[1]]); + break; + default: + break; + } + } + + fclose(fdBin); + + return 0; +} diff --git a/misc-test/compilateur_c_en_c/vm/vm_ncurses b/misc-test/compilateur_c_en_c/vm/vm_ncurses Binary files differnew file mode 100755 index 0000000..f60ca8e --- /dev/null +++ b/misc-test/compilateur_c_en_c/vm/vm_ncurses diff --git a/misc-test/compilateur_c_en_c/vm/vm_ncurses.c b/misc-test/compilateur_c_en_c/vm/vm_ncurses.c new file mode 100644 index 0000000..8ce9be8 --- /dev/null +++ b/misc-test/compilateur_c_en_c/vm/vm_ncurses.c @@ -0,0 +1,325 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <panel.h> // apt-get install libncurses5-dev et ajouter -lpanel -lncurses pour linker +#include <unistd.h> // sleep() + +#include "../asm_defs.h" + +#define MEM_SIZE 256 +#define APP_TITLE "MyCPU Emulator - INSA Toulouse 2009 - Ludovic POUZENC" +#define MIN_COLS 64 +#define MIN_LINES 32 +#define NB_WINS 3 + +struct rect { int w,h,x,y; }; +struct rect wins_coords[NB_WINS]; +struct hint { char *name, key; }; +struct hint hints[] = { {"Help",'H'}, {"Menu",'M'},{"Memory",'e'},{"Code",'C'},{"Step",'S'},{"Quit",'Q'} }; + +FILE *fdBin; +char *mem; +int i_count=0; + +void init_curse(); +void init_wins(WINDOW **wins); +void init_panels(PANEL ** panels, WINDOW **wins); +void win_show(WINDOW *win, char *label, int label_color); +void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); +void draw_head_and_foot(); +void print_hints(struct hint hints[], int n); +void wprinthls(WINDOW *win, char text[]); +void wprintline(WINDOW *win, int lineno, char text[], int text_len); + + +void do_exec_step(WINDOW *dest_win); +void refresh_mem_display(WINDOW *dest_win); + + +int main(int argc, char *argv[]) +{ + WINDOW *my_wins[NB_WINS]; + PANEL *my_panels[NB_WINS]; + int ch; + + mem = calloc(MEM_SIZE, sizeof(char)); + + if ( argc !=2 ) + { + fprintf(stderr, "Usage : %s <bin_file>\n", argv[0]); + return -1; + } + + fdBin = fopen(argv[1], "r"); + if ( fdBin == NULL ) + { + fprintf(stderr, "ERROR : can't open file '%s'\n", argv[1]); + return -1; + } + + init_curse(); + + if ( COLS < MIN_COLS || LINES < MIN_LINES ) { + endwin(); + fprintf(stderr, "ERROR : This application requires at least a %dx%d chars terminal\n", MIN_COLS, MIN_LINES); + return -1; + } + + init_wins(my_wins); + init_panels(my_panels, my_wins); + update_panels(); + draw_head_and_foot(); + doupdate(); + + while((ch = getch()) != 'q') + { + switch(ch) + { + case 's': + do_exec_step(my_wins[2]); + refresh_mem_display(my_wins[1]); + break; + default: + flash(); beep(); + } + update_panels(); + doupdate(); + } + + + fclose(fdBin); + + fflush(stdin); + getch(); + endwin(); + + return 0; +} + +void init_curse() +{ + + /* Initialize curses */ + initscr(); + start_color(); + cbreak(); + noecho(); + keypad(stdscr, TRUE); + + + /* Initialize all the colors */ + init_pair(1, COLOR_RED, COLOR_BLACK); + init_pair(2, COLOR_GREEN, COLOR_BLACK); + init_pair(3, COLOR_CYAN, COLOR_BLACK); + init_pair(4, COLOR_WHITE, COLOR_BLUE); +} + +void init_wins(WINDOW **wins) +{ + int i; + + /* Menu */ + wins_coords[0].h = LINES-2; + wins_coords[0].w = COLS/5; + wins_coords[0].x = 1; + wins_coords[0].y = COLS - COLS/5; + wins_coords[0].y = COLS - COLS/5; + /* Memory */ + wins_coords[1].h = LINES-2-(LINES-2)/3; + wins_coords[1].w = COLS - COLS/5; + wins_coords[1].x = 1; + wins_coords[1].y = 0; + /* Code */ + wins_coords[2].h = (LINES-2)/3; + wins_coords[2].w = COLS - COLS/5; + wins_coords[2].x = 1+LINES-2-(LINES-2)/3; + wins_coords[2].y = 0; + + for(i=0;i<NB_WINS;i++) { wins[i] = newwin(wins_coords[i].h, wins_coords[i].w, wins_coords[i].x,wins_coords[i].y); } + + scrollok(wins[2], TRUE); + wsetscrreg(wins[2],3, wins_coords[2].h-2); + + win_show(wins[0], "Menu", 3); + win_show(wins[1], "Memory", 2); + win_show(wins[2], "Executed Code", 1); +} + +void init_panels(PANEL ** panels, WINDOW **wins) +{ + int i; + /* Attach a panel to each window */ /* Order is bottom up */ + for(i=0;i<NB_WINS;i++) panels[i] = new_panel(wins[i]); +} + +/* Show the window with a border and a label */ +void win_show(WINDOW *win, char *label, int label_color) +{ + int startx, starty, height, width; + getbegyx(win, starty, startx); + getmaxyx(win, height, width); + box(win, 0, 0); + mvwaddch(win, 2, 0, ACS_LTEE); + mvwhline(win, 2, 1, ACS_HLINE, width - 2); + mvwaddch(win, 2, width - 1, ACS_RTEE); + print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color)); + wmove(win,3,0); +} + +void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) +{ + int length, x, y; + float temp; + + if(win == NULL) + win = stdscr; + getyx(win, y, x); + if(startx != 0) + x = startx; + if(starty != 0) + y = starty; + if(width == 0) + width = 80; + + length = strlen(string); + temp = (width - length)/ 2; + x = startx + (int)temp; + wattron(win, color); + mvwprintw(win, y, x, "%s", string); + wattroff(win, color); + refresh(); +} + +void print_hints(struct hint hints[], int n) +{ + int i; + for(i=0;i<n;i++) + { + char *currc = hints[i].name; + while(*currc) + { + int out = *currc; + if ( out == hints[i].key ) { out |= A_STANDOUT; } + addch(out); + currc++; + } + addch(' '); + } +} + +void draw_head_and_foot() +{ + attron(COLOR_PAIR(4)); + attron(A_BOLD); + mvhline(0,0,' ', COLS); + mvhline(LINES-1,0,' ', COLS); + mvprintw(0, (COLS-strlen(APP_TITLE))/2, APP_TITLE, 'H' | A_STANDOUT, 'M', 'E', 'C', 'S'); + mvaddch(LINES-1,0,' '); + print_hints(hints, sizeof(hints)/sizeof(struct hint)); + attroff(A_BOLD); + attroff(COLOR_PAIR(4)); +} + +void wprinthls(WINDOW *win, char text[]) +{ + int i, maxx=getmaxx(win); + + chtype *line=malloc(sizeof(chtype)*(maxx+1)); + + line[0]=ACS_VLINE; + for(i=1;i<maxx-1;i++){line[i]=' ' | A_STANDOUT ;} + line[maxx]=0; + + for(i=0;i<maxx-4 && text[i]!=0;i++) { line[i+2] = text[i] | A_STANDOUT; } + line[maxx-1]=ACS_VLINE; + + mvwchgat(win,3,1,maxx-2, 0, 0, NULL); + wscrl(win,-1); + mvwaddchstr(win,3,0,line); +} + +void wprintline(WINDOW *win, int lineno, char text[], int text_len) +{ + int i, maxx=getmaxx(win); + + chtype *line=malloc(sizeof(chtype)*(maxx+1)); + line[0]=ACS_VLINE; + for(i=1;i<maxx-1;i++){line[i]=' ';} + line[maxx]=0; + + for(i=0;i<maxx-4 && i<text_len;i++) { line[i+2] = text[i]; } + line[maxx-1]=ACS_VLINE; + mvwaddchstr(win,3+lineno,0,line); +} + +void do_exec_step(WINDOW *dest_win) +{ + char *instr = malloc(sizeof(char)*(getmaxx(dest_win)-4)); + char buf[4]; + + if (fread(buf, 4, 1, fdBin)) + { + sprintf(instr, "%7d @0x%02x: %s 0x%02x 0x%02x 0x%02x", + ++i_count, + (int) ftell(fdBin)-4, + instructionNames[(int)buf[0]], + (unsigned int) buf[1] & 0xFF, + (unsigned int) buf[2] & 0xFF, + (unsigned int) buf[3] & 0xFF + ); + wprinthls(dest_win, instr); + + switch (buf[0]) + { + case I_NOP: + break; + case I_ADD: + mem[(int)buf[1]] = mem[(int)buf[2]] + mem[(int)buf[3]]; + break; + case I_MUL: + mem[(int)buf[1]] = mem[(int)buf[2]] * mem[(int)buf[3]]; + break; + case I_SOU: + mem[(int)buf[1]] = mem[(int)buf[2]] - mem[(int)buf[3]]; + break; + case I_DIV: + mem[(int)buf[1]] = mem[(int)buf[2]] / mem[(int)buf[3]]; + break; + case I_COP: + mem[(int)buf[1]] = mem[(int)buf[2]]; + break; + case I_AFC: + mem[(int)buf[1]] = buf[2]; + break; + case I_JMP: + fseek(fdBin, (long)buf[1], SEEK_SET); + break; + case I_JMF: + if (!mem[(int)buf[1]]) { fseek(fdBin, (long)buf[2]&0xFF, SEEK_SET); } + break; + case I_INF: + mem[(int)buf[1]] = mem[(int)buf[2]] < mem[(int)buf[3]]; + break; + case I_SUP: + mem[(int)buf[1]] = mem[(int)buf[2]] > mem[(int)buf[3]]; + break; + case I_EQU: + mem[(int)buf[1]] = mem[(int)buf[2]] == mem[(int)buf[3]]; + break; + case I_PRI: + printf("PRI : %x\n", (int) mem[(int)buf[1]]); // TODO : fenetre out ! + break; + default: + break; + } + } +} + +void refresh_mem_display(WINDOW *dest_win) +{ + int i, disp_width=16; + char *memline = malloc(sizeof(char)*3*MEM_SIZE); + + for (i=0;i<MEM_SIZE;i++) sprintf(memline+3*i, "%02x ", (unsigned int) mem[i] & 0xFF); + for (i=0;i<MEM_SIZE/disp_width;i++) wprintline(dest_win, i, memline+3*disp_width*i, 3*disp_width); +} |