forked from pfaure/CrossAssembleur
Compare commits
2 commits
6631ca437b
...
712e686699
Author | SHA1 | Date | |
---|---|---|---|
712e686699 | |||
5f88839a5b |
10 changed files with 569 additions and 317 deletions
14
.gitignore
vendored
14
.gitignore
vendored
|
@ -1,6 +1,8 @@
|
|||
*.o
|
||||
lex.yy.c
|
||||
as.tab.*
|
||||
output.asm
|
||||
output_bin.txt
|
||||
cross_assembleur
|
||||
Lex_Yacc/as.tab*
|
||||
Lex_Yacc/as.dot
|
||||
Lex_Yacc/as.output
|
||||
Lex_Yacc/lex.yy.*
|
||||
Tables/tables.o
|
||||
rondoudou_cross_assembleur
|
||||
Inputs/*
|
||||
Outputs/*
|
||||
|
|
50
Lex_Yacc/al.lex
Normal file
50
Lex_Yacc/al.lex
Normal file
|
@ -0,0 +1,50 @@
|
|||
%{
|
||||
#include "as.tab.h"
|
||||
int yywrap(void){return 1;}
|
||||
void
|
||||
yyerror (char const *s)
|
||||
{
|
||||
|
||||
fprintf (stderr, "%s\n", s);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
"ADD" { return tADD ;}
|
||||
"SOU" { return tSUB;}
|
||||
"MUL" { return tMUL; }
|
||||
"DIV" { return tDIV; }
|
||||
"INF" { return tINF; }
|
||||
"SUP" { return tSUP; }
|
||||
"EQU" { return tEQU; }
|
||||
|
||||
"AFC" { return tAFC; }
|
||||
"COP" { return tCPY; }
|
||||
"AFCA" { return tAFCA; }
|
||||
|
||||
|
||||
"READ" { return tREAD; }
|
||||
"WR" { return tWR; }
|
||||
|
||||
"JMP" { return tJMP; }
|
||||
"JMF" { return tJMF; }
|
||||
|
||||
"GET" { return tGET; }
|
||||
"PRI" { return tPRI; }
|
||||
|
||||
"CALL" { return tCALL; }
|
||||
"RET" { return tRET; }
|
||||
|
||||
"STOP" { return tSTOP; }
|
||||
|
||||
[0-9]+ { yylval.nombre = atoi(yytext); return tNB; }
|
||||
|
||||
"\n" {}
|
||||
" " {}
|
||||
"\t" {}
|
||||
|
||||
%%
|
||||
|
||||
|
158
Lex_Yacc/as.y
Normal file
158
Lex_Yacc/as.y
Normal file
|
@ -0,0 +1,158 @@
|
|||
%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
|
||||
|
||||
%%
|
||||
|
||||
Programme : Instruction Programme;
|
||||
Programme : Instruction;
|
||||
|
||||
Instruction : tMUL 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(MUL, reg_dest, reg_src1, reg_src2);
|
||||
new_instruction(added_instruction + 1);};
|
||||
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);};
|
||||
|
||||
|
||||
Instruction : tAFC tNB tNB {increment_time();
|
||||
int added_instruction = 0;
|
||||
int reg_dest = get_reg_write($2, &added_instruction);
|
||||
add_instruction(AFC, reg_dest, $3, 0);
|
||||
new_instruction(added_instruction + 1);};
|
||||
Instruction : tCPY tNB tNB {increment_time();
|
||||
int added_instruction = 0;
|
||||
int reg_src = get_reg_read($3, &added_instruction);
|
||||
int reg_dest = get_reg_write($2, &added_instruction);
|
||||
add_instruction(CPY, reg_dest, reg_src, 0);
|
||||
new_instruction(added_instruction + 1);};
|
||||
Instruction : tAFCA tNB tNB {increment_time();
|
||||
int added_instruction = 0;
|
||||
int reg_aux = get_reg_write(-1, &added_instruction);
|
||||
add_instruction(AFC, reg_aux, $3, 0);
|
||||
add_instruction(STOREA, $2, reg_aux, 0);
|
||||
unlink($2);
|
||||
new_instruction(added_instruction + 2);};
|
||||
|
||||
|
||||
Instruction : tJMP tNB {increment_time();
|
||||
add_instruction(JMP, $2, 0, 0);
|
||||
new_instruction(1);};
|
||||
Instruction : tJMF tNB tNB {increment_time();
|
||||
int added_instruction = 0;
|
||||
int reg_src = get_reg_read($2, &added_instruction);
|
||||
int reg_aux = get_reg_write(-1, &added_instruction);
|
||||
add_instruction(SUB, reg_aux, reg_aux, reg_src);
|
||||
add_instruction(JMZ, $3, 0, 0);
|
||||
new_instruction(added_instruction + 2);};
|
||||
|
||||
Instruction : tREAD tNB tNB {increment_time();
|
||||
int added_instruction = 0;
|
||||
int reg_addr = get_reg_read($3, &added_instruction);
|
||||
int reg_dest = get_reg_write($2, &added_instruction);
|
||||
add_instruction(LOADI, reg_dest, reg_addr, 0);
|
||||
new_instruction(added_instruction + 1);};
|
||||
Instruction : tWR tNB tNB {increment_time();
|
||||
int added_instruction = 0;
|
||||
int reg_addr = get_reg_read($2, &added_instruction);
|
||||
int reg_value = get_reg_read($3, &added_instruction);
|
||||
add_instruction(STOREI, reg_addr, reg_value, 0);
|
||||
new_instruction(added_instruction + 1);};
|
||||
|
||||
|
||||
Instruction : tGET tNB {increment_time();
|
||||
int added_instruction = 0;
|
||||
int reg_dest = get_reg_write($2, &added_instruction);
|
||||
add_instruction(GET, reg_dest, 0, 0);
|
||||
new_instruction(added_instruction + 1);};
|
||||
Instruction : tPRI tNB {increment_time();
|
||||
int added_instruction = 0;
|
||||
int reg_src = get_reg_read($2, &added_instruction);
|
||||
add_instruction(PRI, reg_src, 0, 0);
|
||||
new_instruction(added_instruction + 1);};
|
||||
|
||||
|
||||
Instruction : tCALL tNB tNB {increment_time();
|
||||
int added_instruction = flush_and_init(file);
|
||||
add_instruction(CALL, $2, $3, 0);
|
||||
new_instruction(added_instruction + 1);};
|
||||
Instruction : tRET {increment_time();
|
||||
int added_instruction = flush_and_init(file);
|
||||
add_instruction(RET, 0, 0, 0);
|
||||
new_instruction(added_instruction + 1);};
|
||||
|
||||
Instruction : tSTOP tNB {increment_time();
|
||||
add_instruction(STOP, $2, 0, 0);
|
||||
new_instruction(1);};
|
||||
|
||||
%%
|
||||
|
||||
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;
|
||||
}
|
61
Makefile
61
Makefile
|
@ -1,7 +1,54 @@
|
|||
build :
|
||||
gcc -Wall -c tables.c -o tables.o
|
||||
bison -d -t as.y
|
||||
flex -o lex.yy.c al.lex
|
||||
gcc -Wall -c as.tab.c -o as.tab.o
|
||||
gcc -Wall -c lex.yy.c -o lex.yy.o
|
||||
gcc as.tab.o lex.yy.o tables.o -o cross_assembleur
|
||||
default :
|
||||
@echo "Spécifiez une cible"
|
||||
|
||||
|
||||
|
||||
###########################
|
||||
### NETTOYAGE ###
|
||||
###########################
|
||||
clean_all : clean clean_Inputs clean_Outputs
|
||||
|
||||
clean: clean_Lex_Yacc clean_Tables
|
||||
@rm -f rondoudou_cross_assembleur
|
||||
|
||||
clean_Tables:
|
||||
@rm -f Tables/*.o
|
||||
|
||||
clean_Lex_Yacc:
|
||||
@rm -f Lex_Yacc/as.output Lex_Yacc/as.tab.* Lex_Yacc/lex.yy.* Lex_Yacc/as.dot
|
||||
|
||||
clean_Inputs:
|
||||
@rm -f Inputs/*
|
||||
|
||||
clean_Outputs:
|
||||
@rm -f Outputs/*
|
||||
|
||||
|
||||
|
||||
###########################
|
||||
### COMPILATION ###
|
||||
###########################
|
||||
build : clean build_Tables build_Lex_Yacc
|
||||
gcc Lex_Yacc/as.tab.o Lex_Yacc/lex.yy.o Tables/tables.o -ll -o rondoudou_cross_assembleur
|
||||
|
||||
build_Tables: clean_Tables
|
||||
gcc -c Tables/tables.c -o Tables/tables.o
|
||||
|
||||
build_Lex_Yacc: clean_Lex_Yacc
|
||||
bison -g -v -d -t -b Lex_Yacc/as Lex_Yacc/as.y
|
||||
flex -o Lex_Yacc/lex.yy.c Lex_Yacc/al.lex
|
||||
gcc -c Lex_Yacc/as.tab.c -o Lex_Yacc/as.tab.o
|
||||
gcc -c Lex_Yacc/lex.yy.c -o Lex_Yacc/lex.yy.o
|
||||
|
||||
|
||||
|
||||
###########################
|
||||
### EDITION ###
|
||||
###########################
|
||||
edit_Lex_Yacc:
|
||||
pluma Lex_Yacc/al.lex Lex_Yacc/as.y &
|
||||
|
||||
edit_Tables:
|
||||
pluma Tables/tables.c Tables/tables.h &
|
||||
|
||||
edit: edit_Lex_Yacc edit_Tables
|
||||
|
|
|
@ -1,27 +1,24 @@
|
|||
|
||||
/*
|
||||
----------------------------------------
|
||||
| Adresse | Registre | Modifié |
|
||||
----------------------------------------
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |
|
||||
| i | 0x777756b8 | int |
|
||||
| size | 0x777756b8 | int |
|
||||
----------------------------------------
|
||||
*/
|
||||
|
||||
#include "tables.h"
|
||||
#include <stdlib.h>
|
||||
#define NB_REG 16
|
||||
#define MEM_SIZE 256
|
||||
#define NB_INSTRUCTIONS 256
|
||||
#define MEM_INST_SIZE 256
|
||||
#define NB_BITS_INSTRUCTION 8
|
||||
#define NB_REG 4
|
||||
#define MEM_SIZE 16
|
||||
#define MEM_INST_SIZE 128
|
||||
#define NB_BITS_INSTRUCTION 5
|
||||
#define NB_BITS 8
|
||||
|
||||
int traduction_JMP[NB_INSTRUCTIONS];
|
||||
|
||||
|
||||
/**************************************************/
|
||||
/**************************************************/
|
||||
/***************** Initialisation *****************/
|
||||
/**************************************************/
|
||||
/**************************************************/
|
||||
|
||||
// Buffer to patch Jumps difference due to adding LOAD and STORE
|
||||
int traduction_JMP[MEM_INST_SIZE];
|
||||
// Index of the buffer
|
||||
int last_instruction = 0;
|
||||
|
||||
// Structure coding an instruction
|
||||
struct str_instruction {
|
||||
enum instruction_t instruction;
|
||||
int param1;
|
||||
|
@ -29,115 +26,23 @@ struct str_instruction {
|
|||
int param3;
|
||||
};
|
||||
|
||||
int last_instruction = 0;
|
||||
struct str_instruction buffer[3*NB_INSTRUCTIONS];
|
||||
|
||||
void add_instruction(enum instruction_t inst, int param1, int param2, int param3) {
|
||||
struct str_instruction my_instruction = {inst, param1, param2, param3};
|
||||
buffer[last_instruction] = my_instruction;
|
||||
last_instruction++;
|
||||
}
|
||||
|
||||
void write_asm(FILE * file) {
|
||||
int i = 0;
|
||||
while (i<MEM_INST_SIZE) {
|
||||
printf("Writing instruction: %d\n", buffer[i].instruction);
|
||||
if (buffer[i].instruction == ADD) {
|
||||
fprintf(file, "ADD %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
|
||||
} else if (buffer[i].instruction == NOP) {
|
||||
fprintf(file, "NOP 0 0 0\n");
|
||||
} else if (buffer[i].instruction == SUB) {
|
||||
fprintf(file, "SUB %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
|
||||
} else if (buffer[i].instruction == MUL) {
|
||||
fprintf(file, "MUL %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
|
||||
} else if (buffer[i].instruction == DIV) {
|
||||
fprintf(file, "DIV %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
|
||||
} else if (buffer[i].instruction == AFC) {
|
||||
fprintf(file, "AFC %d %d\n", buffer[i].param1, buffer[i].param2);
|
||||
} else if (buffer[i].instruction == CPY) {
|
||||
fprintf(file, "CPY %d %d\n", buffer[i].param1, buffer[i].param2);
|
||||
} else if (buffer[i].instruction == LOAD) {
|
||||
fprintf(file, "LOAD %d %d\n", buffer[i].param1, buffer[i].param2);
|
||||
} else if (buffer[i].instruction == STORE) {
|
||||
fprintf(file, "STORE %d %d\n", buffer[i].param1, buffer[i].param2);
|
||||
} else {
|
||||
printf("Error: unexpected instruction: %d\n", buffer[i].instruction);
|
||||
exit(1);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void int_2_bin(char * buff, int n) {
|
||||
int _m = n;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
buff[31 - i] = ((_m & (1 << 31)) ? '1' : '0');
|
||||
_m = _m << 1;
|
||||
}
|
||||
}
|
||||
|
||||
void convert_to_binary_on_N(int value, int N, char * buff) {
|
||||
char tampon[33];
|
||||
int_2_bin(tampon, value);
|
||||
int i;
|
||||
for (i = N-1; i>=0; i--) {
|
||||
buff[N-1-i] = tampon[i];
|
||||
}
|
||||
buff[N] = '\0';
|
||||
}
|
||||
|
||||
void write_instruction_binary(FILE * file, struct str_instruction instr, int compact, int printSeparator) {
|
||||
char buff1[33];
|
||||
char buff2[33];
|
||||
char buff3[33];
|
||||
char buff4[33];
|
||||
convert_to_binary_on_N(instr.instruction, NB_BITS_INSTRUCTION, buff1);
|
||||
|
||||
convert_to_binary_on_N(instr.param1, NB_BITS, buff2);
|
||||
|
||||
convert_to_binary_on_N(instr.param2, NB_BITS, buff3);
|
||||
convert_to_binary_on_N(instr.param3, NB_BITS, buff4);
|
||||
if (compact) {
|
||||
fprintf(file, "%s%s%s%s", buff1, buff2, buff3, buff4);
|
||||
} else {
|
||||
fprintf(file, "\"%s%s%s%s\"", buff1, buff2, buff3, buff4);
|
||||
if (printSeparator) {
|
||||
fprintf(file, ", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void write_code_machine(FILE * file) {
|
||||
int i = MEM_INST_SIZE - 1;
|
||||
fprintf(file, "signal memory: MEMORY_TYPE := (");
|
||||
while (i >= 0) {
|
||||
write_instruction_binary(file, buffer[i], 0, i != 0);
|
||||
i--;
|
||||
}
|
||||
fprintf(file, ");");
|
||||
}
|
||||
|
||||
void write_code_machine_compact(FILE * file) {
|
||||
fprintf(file, "\"");
|
||||
int i = MEM_INST_SIZE - 1;
|
||||
while (i >= 0) {
|
||||
write_instruction_binary(file, buffer[i], 1, 0);
|
||||
i--;
|
||||
}
|
||||
fprintf(file, "\"\n");
|
||||
}
|
||||
|
||||
// Buffer to store registers oriented instructions
|
||||
struct str_instruction buffer[3*MEM_INST_SIZE];
|
||||
|
||||
// Structure coding an address and the correpondance with a register
|
||||
struct case_adresse {
|
||||
int adresse;
|
||||
int registre;
|
||||
char modifie;
|
||||
};
|
||||
|
||||
// Buffer of addresses (Memory)
|
||||
struct case_adresse tableau[MEM_SIZE];
|
||||
|
||||
// Buffer to manage priority policy
|
||||
int registres[NB_REG];
|
||||
|
||||
// Initialise all : the addresses-registers association table, the registers priority table, the instructions buffer, the instruction address association table
|
||||
void init (void) {
|
||||
int i;
|
||||
struct case_adresse case_courante = {0, -1, 0};
|
||||
|
@ -154,10 +59,20 @@ void init (void) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************/
|
||||
/**************************************************/
|
||||
/************** Registers Management **************/
|
||||
/**************************************************/
|
||||
/**************************************************/
|
||||
|
||||
// INTERN FUNCTION
|
||||
// Print a case address
|
||||
void print_case_adresse(struct case_adresse case_courante) {
|
||||
printf("{addr : %d ; reg : %d ; modi : %d}\n", case_courante.adresse, case_courante.registre, (int)case_courante.modifie);
|
||||
}
|
||||
|
||||
// Print the adresses-registers correspondance table
|
||||
void print() {
|
||||
int i;
|
||||
for (i=0; i<MEM_SIZE; i++) {
|
||||
|
@ -165,11 +80,14 @@ void print() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// INTERN FUNCTION
|
||||
// return the case corresponding to the given address
|
||||
struct case_adresse get_info(int adresse) {
|
||||
return tableau[adresse];
|
||||
}
|
||||
|
||||
// INTERN FUNCTION
|
||||
// return the address corresponding to the given register
|
||||
int get_adresse (int registre) {
|
||||
int i = 0;
|
||||
while (i < MEM_SIZE && tableau[i].registre != registre) {
|
||||
|
@ -182,14 +100,19 @@ int get_adresse (int registre) {
|
|||
}
|
||||
}
|
||||
|
||||
// INTERN FUNCTION
|
||||
// Set the given register to the given address
|
||||
void set_registre(int adresse, int registre) {
|
||||
tableau[adresse].registre = registre;
|
||||
}
|
||||
|
||||
// INTERN FUNCTION
|
||||
// Set modifie to the address (0 the value in the memory is up to date, 1 the value in the register is more recent)
|
||||
void set_modifie(int adresse, char modifie) {
|
||||
tableau[adresse].modifie = modifie;
|
||||
}
|
||||
|
||||
// Increment the register priority policy buffer
|
||||
void increment_time() {
|
||||
int i;
|
||||
for (i=0; i<NB_REG; i++) {
|
||||
|
@ -197,10 +120,14 @@ void increment_time() {
|
|||
}
|
||||
}
|
||||
|
||||
// INTERN FUNCTION
|
||||
// Specifie that the given register have been used
|
||||
void refresh_registre(int registre) {
|
||||
registres[registre] = 0;
|
||||
}
|
||||
|
||||
// INTERN FUNCTION
|
||||
// Return the LRU register
|
||||
int get_register() {
|
||||
int i;
|
||||
int index_max = 0;
|
||||
|
@ -212,6 +139,48 @@ int get_register() {
|
|||
return index_max;
|
||||
}
|
||||
|
||||
/* Ask for a register to read the value
|
||||
|
||||
@param :
|
||||
- adresse : The address of value wanted
|
||||
- added_instruction : Address of an int storing the number of added_instructions
|
||||
@return : The number of the register corresponding to the given address
|
||||
*/
|
||||
int get_reg_read(int adresse, int * added_instruction) {
|
||||
struct case_adresse ma_case = get_info(adresse);
|
||||
if (ma_case.registre == -1) {
|
||||
int dispo = get_register();
|
||||
int previous_addr = get_adresse(dispo);
|
||||
if (previous_addr != -1) {
|
||||
struct case_adresse ancienne_case = get_info(previous_addr);
|
||||
if (ancienne_case.modifie == 1) {
|
||||
*added_instruction = (*added_instruction) + 1;
|
||||
add_instruction(STORE, previous_addr, dispo, 0);
|
||||
set_modifie(previous_addr, 0);
|
||||
}
|
||||
set_registre(previous_addr, -1);
|
||||
}
|
||||
*added_instruction = (*added_instruction) + 1;
|
||||
add_instruction(LOAD, dispo, adresse, 0);
|
||||
set_registre(adresse, dispo);
|
||||
refresh_registre(dispo);
|
||||
return dispo;
|
||||
} else {
|
||||
refresh_registre(ma_case.registre);
|
||||
return ma_case.registre;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ask for a register to write the value
|
||||
|
||||
@param :
|
||||
- adresse : The address of value (if -1 return a free register without associating it to any address)
|
||||
- added_instruction : Address of an int storing the number of added_instructions
|
||||
@return : The number of the register corresponding to the given address
|
||||
|
||||
WARNING : The value of the address will not be LOADED in the register
|
||||
Always ask READ registers before the WRITE register
|
||||
*/
|
||||
int get_reg_write(int adresse, int * added_instruction) {
|
||||
if (adresse == -1) {
|
||||
int dispo = get_register();
|
||||
|
@ -251,35 +220,12 @@ int get_reg_write(int adresse, int * added_instruction) {
|
|||
}
|
||||
}
|
||||
|
||||
int get_reg_read(int adresse, int * added_instruction) {
|
||||
struct case_adresse ma_case = get_info(adresse);
|
||||
if (ma_case.registre == -1) {
|
||||
int dispo = get_register();
|
||||
int previous_addr = get_adresse(dispo);
|
||||
if (previous_addr != -1) {
|
||||
struct case_adresse ancienne_case = get_info(previous_addr);
|
||||
if (ancienne_case.modifie == 1) {
|
||||
*added_instruction = (*added_instruction) + 1;
|
||||
add_instruction(STORE, previous_addr, dispo, 0);
|
||||
set_modifie(previous_addr, 0);
|
||||
}
|
||||
set_registre(previous_addr, -1);
|
||||
}
|
||||
*added_instruction = (*added_instruction) + 1;
|
||||
add_instruction(LOAD, dispo, adresse, 0);
|
||||
set_registre(adresse, dispo);
|
||||
refresh_registre(dispo);
|
||||
return dispo;
|
||||
} else {
|
||||
refresh_registre(ma_case.registre);
|
||||
return ma_case.registre;
|
||||
}
|
||||
}
|
||||
|
||||
// Broke the association between adresse and its corresponding register
|
||||
void unlink(int adresse) {
|
||||
set_registre(adresse, -1);
|
||||
}
|
||||
|
||||
// Store used register, init the association table between addresses and registers
|
||||
int flush_and_init() {
|
||||
int i;
|
||||
int added_instruction = 0;
|
||||
|
@ -301,6 +247,25 @@ int flush_and_init() {
|
|||
return added_instruction;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************/
|
||||
/**************************************************/
|
||||
/************** Instructions Writing **************/
|
||||
/**************************************************/
|
||||
/**************************************************/
|
||||
|
||||
// Add a new Registers oriented instruction
|
||||
void add_instruction(enum instruction_t inst, int param1, int param2, int param3) {
|
||||
struct str_instruction my_instruction = {inst, param1, param2, param3};
|
||||
buffer[last_instruction] = my_instruction;
|
||||
last_instruction++;
|
||||
}
|
||||
|
||||
// Specifie the number of Register oriented instructions corresponding to the memory oriented instruction
|
||||
void new_instruction(int nb_inst) {
|
||||
static int last_intruction_adresse = 0;
|
||||
static int current_instruction = 0;
|
||||
|
@ -308,21 +273,122 @@ void new_instruction(int nb_inst) {
|
|||
current_instruction++;
|
||||
last_intruction_adresse += nb_inst;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Write the new assembly in the given file
|
||||
void write_asm(FILE * file) {
|
||||
int i = 0;
|
||||
while (i<MEM_INST_SIZE) {
|
||||
if (buffer[i].instruction == ADD) {
|
||||
fprintf(file, "ADD %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
|
||||
} else if (buffer[i].instruction == SUB) {
|
||||
fprintf(file, "SUB %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
|
||||
} else if (buffer[i].instruction == MUL) {
|
||||
fprintf(file, "MUL %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
|
||||
} else if (buffer[i].instruction == DIV) {
|
||||
fprintf(file, "DIV %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
|
||||
} else if (buffer[i].instruction == INF) {
|
||||
fprintf(file, "INF %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
|
||||
} else if (buffer[i].instruction == SUP) {
|
||||
fprintf(file, "SUP %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
|
||||
} else if (buffer[i].instruction == EQU) {
|
||||
fprintf(file, "EQU %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
|
||||
|
||||
} else if (buffer[i].instruction == AFC) {
|
||||
fprintf(file, "AFC %d %d\n", buffer[i].param1, buffer[i].param2);
|
||||
} else if (buffer[i].instruction == CPY) {
|
||||
fprintf(file, "CPY %d %d\n", buffer[i].param1, buffer[i].param2);
|
||||
|
||||
} else if (buffer[i].instruction == LOAD) {
|
||||
fprintf(file, "LOAD %d %d\n", buffer[i].param1, buffer[i].param2);
|
||||
} else if (buffer[i].instruction == STORE) {
|
||||
fprintf(file, "STORE %d %d\n", buffer[i].param1, buffer[i].param2);
|
||||
} else if (buffer[i].instruction == LOADI) {
|
||||
fprintf(file, "LOADI %d %d\n", buffer[i].param1, buffer[i].param2);
|
||||
} else if (buffer[i].instruction == STOREI) {
|
||||
fprintf(file, "STOREI %d %d\n", buffer[i].param1, buffer[i].param2);
|
||||
} else if (buffer[i].instruction == STOREA) {
|
||||
fprintf(file, "STOREA %d %d\n", buffer[i].param1, buffer[i].param2);
|
||||
|
||||
} else if (buffer[i].instruction == JMP) {
|
||||
fprintf(file, "JMP %d\n", traduction_JMP[buffer[i].param1]);
|
||||
} else if (buffer[i].instruction == JMZ) {
|
||||
fprintf(file, "JMZ %d\n", traduction_JMP[buffer[i].param1]);
|
||||
} else if (buffer[i].instruction == GET) {
|
||||
fprintf(file, "GET %d\n", buffer[i].param1);
|
||||
} else if (buffer[i].instruction == PRI) {
|
||||
fprintf(file, "PRI %d\n", buffer[i].param1);
|
||||
|
||||
} else if (buffer[i].instruction == CALL) {
|
||||
fprintf(file, "CALL %d %d\n", traduction_JMP[buffer[i].param1], buffer[i].param2);
|
||||
} else if (buffer[i].instruction == RET) {
|
||||
fprintf(file, "RET\n");
|
||||
} else if (buffer[i].instruction == STOP) {
|
||||
fprintf(file, "STOP %d\n", buffer[i].param1);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// INTERN FUNCTION
|
||||
// Write binary value of n in buff
|
||||
void int_2_bin(char * buff, int n) {
|
||||
int _m = n;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
buff[31 - i] = ((_m & (1 << 31)) ? '1' : '0');
|
||||
_m = _m << 1;
|
||||
}
|
||||
}
|
||||
|
||||
// INTERN FUNCTION
|
||||
// Write binary value of value in buff on N bits
|
||||
void convert_to_binary_on_N(int value, int N, char * buff) {
|
||||
char tampon[33];
|
||||
int_2_bin(tampon, value);
|
||||
int i;
|
||||
for (i = N-1; i>=0; i--) {
|
||||
buff[N-1-i] = tampon[i];
|
||||
}
|
||||
buff[N] = '\0';
|
||||
}
|
||||
|
||||
// INTERN FUNCTION
|
||||
// Write a binary instruction in the given file
|
||||
// If not compact ("010..10" & ) else only (010..10)
|
||||
void write_instruction_binary(FILE * file, struct str_instruction instr, char compact) {
|
||||
char buff1[33];
|
||||
char buff2[33];
|
||||
char buff3[33];
|
||||
char buff4[33];
|
||||
convert_to_binary_on_N(instr.instruction, NB_BITS_INSTRUCTION, buff1);
|
||||
if (instr.instruction == JMP || instr.instruction == JMZ || instr.instruction == CALL) {
|
||||
convert_to_binary_on_N(traduction_JMP[instr.param1], NB_BITS, buff2);
|
||||
} else {
|
||||
convert_to_binary_on_N(instr.param1, NB_BITS, buff2);
|
||||
}
|
||||
convert_to_binary_on_N(instr.param2, NB_BITS, buff3);
|
||||
convert_to_binary_on_N(instr.param3, NB_BITS, buff4);
|
||||
if (compact) {
|
||||
fprintf(file, "%s%s%s%s", buff1, buff2, buff3, buff4);
|
||||
} else {
|
||||
fprintf(file, "\"%s%s%s%s\" & ", buff1, buff2, buff3, buff4);
|
||||
}
|
||||
}
|
||||
|
||||
// Write the binary code in the given file
|
||||
void write_code_machine(FILE * file, char compact) {
|
||||
if (compact) {
|
||||
int i = MEM_INST_SIZE - 1;
|
||||
while (i>=0) {
|
||||
write_instruction_binary(file, buffer[i], 0);
|
||||
i--;
|
||||
}
|
||||
} else {
|
||||
fprintf(file, "\"");
|
||||
int i = MEM_INST_SIZE - 1;
|
||||
while (i>=0) {
|
||||
write_instruction_binary(file, buffer[i], 1);
|
||||
i--;
|
||||
}
|
||||
fprintf(file, "\"\n");
|
||||
}
|
||||
}
|
79
Tables/tables.h
Normal file
79
Tables/tables.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#ifndef TABLE_H
|
||||
#define TABLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
// Initialise all : the addresses-registers association table, the registers priority table, the instructions buffer, the instruction address association table
|
||||
void init(void);
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************/
|
||||
/**************************************************/
|
||||
/************** Registers Management **************/
|
||||
/**************************************************/
|
||||
/**************************************************/
|
||||
|
||||
// Print the addresses-registers association table
|
||||
void print();
|
||||
|
||||
// Increment the input instruction counter
|
||||
void increment_time();
|
||||
|
||||
/* Ask for a register to read the value
|
||||
|
||||
@param :
|
||||
- adresse : The address of value wanted
|
||||
- added_instruction : Address of an int storing the number of added_instructions
|
||||
@return : The number of the register corresponding to the given address
|
||||
*/
|
||||
int get_reg_read(int adresse, int * added_instruction);
|
||||
|
||||
/* Ask for a register to write the value
|
||||
|
||||
@param :
|
||||
- adresse : The address of value (if -1 return a free register without associating it to any address)
|
||||
- added_instruction : Address of an int storing the number of added_instructions
|
||||
@return : The number of the register corresponding to the given address
|
||||
|
||||
WARNING : The value of the address will not be LOADED in the register
|
||||
Always ask READ registers before the WRITE register
|
||||
*/
|
||||
int get_reg_write(int adresse, int * added_instruction);
|
||||
|
||||
// Broke the association between adresse and its corresponding register
|
||||
void unlink(int adresse);
|
||||
|
||||
// Store used register, init the association table between addresses and registers
|
||||
int flush_and_init();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************/
|
||||
/**************************************************/
|
||||
/************** Instructions Writing **************/
|
||||
/**************************************************/
|
||||
/**************************************************/
|
||||
|
||||
|
||||
// Enum of the register oriented instruction (warning order correspond to the binary code)
|
||||
enum instruction_t {NOP, ADD, MUL, SUB, DIV, INF, SUP, EQU, CPY, AFC, LOAD, STORE, LOADI, STOREI, STOREA, JMP, JMZ, PRI, GET, CALL, RET, STOP};
|
||||
|
||||
// Add a new Registers oriented instruction
|
||||
void add_instruction(enum instruction_t inst, int param1, int param2, int param3);
|
||||
|
||||
// Specifie the number of Register oriented instructions corresponding to the memory oriented instruction
|
||||
void new_instruction(int nb_inst);
|
||||
|
||||
// Write the new assembly in the given file
|
||||
void write_asm(FILE * file);
|
||||
|
||||
// Write the binary code in the given file
|
||||
void write_code_machine(FILE * file, char compact);
|
||||
|
||||
#endif
|
32
al.lex
32
al.lex
|
@ -1,32 +0,0 @@
|
|||
%{
|
||||
#include "as.tab.h"
|
||||
int yywrap(void){return 1;}
|
||||
void
|
||||
yyerror (char const *s)
|
||||
{
|
||||
|
||||
fprintf (stderr, "%s\n", s);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
"ADD" { return tADD ;}
|
||||
"MUL" { return tMUL; }
|
||||
"SOU" { return tSUB;}
|
||||
"DIV" { return tDIV; }
|
||||
|
||||
"COP" { return tCPY; }
|
||||
"AFC" { return tAFC; }
|
||||
|
||||
|
||||
[0-9]+ { yylval.nombre = atoi(yytext); return tNB; }
|
||||
|
||||
"\n" {}
|
||||
" " {}
|
||||
"\t" {}
|
||||
|
||||
%%
|
||||
|
||||
|
74
as.y
74
as.y
|
@ -1,74 +0,0 @@
|
|||
%union {
|
||||
int nombre;
|
||||
}
|
||||
%{
|
||||
#include "tables.h"
|
||||
#include <stdio.h>
|
||||
|
||||
FILE * file;
|
||||
FILE * file2;
|
||||
|
||||
%}
|
||||
|
||||
%token tMUL tDIV tADD tSUB
|
||||
%token tAFC tCPY
|
||||
%token<nombre> tNB
|
||||
|
||||
%%
|
||||
|
||||
Programme : Instruction Programme;
|
||||
Programme : Instruction;
|
||||
|
||||
Instruction : tMUL 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(MUL, reg_dest, reg_src1, reg_src2);
|
||||
new_instruction(added_instruction + 1);};
|
||||
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 : tAFC tNB tNB {increment_time();
|
||||
int added_instruction = 0;
|
||||
int reg_dest = get_reg_write($2, &added_instruction);
|
||||
add_instruction(AFC, reg_dest, $3, 0);
|
||||
new_instruction(added_instruction + 1);};
|
||||
Instruction : tCPY tNB tNB {increment_time();
|
||||
int added_instruction = 0;
|
||||
int reg_src = get_reg_read($3, &added_instruction);
|
||||
int reg_dest = get_reg_write($2, &added_instruction);
|
||||
add_instruction(CPY, reg_dest, reg_src, 0);
|
||||
new_instruction(added_instruction + 1);};
|
||||
|
||||
%%
|
||||
|
||||
int main(void) {
|
||||
file = fopen("output.asm", "w");
|
||||
file2 = fopen("output_bin.txt", "w");
|
||||
init();
|
||||
yyparse();
|
||||
flush_and_init();
|
||||
write_asm(file);
|
||||
write_code_machine(file2);
|
||||
return 0;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
AFC 99 2
|
||||
COP 0 99
|
||||
AFC 98 3
|
||||
AFC 97 3
|
||||
ADD 96 98 97
|
||||
ADD 95 96 0
|
||||
COP 1 95
|
||||
AFC 94 3
|
||||
COP 0 94
|
35
tables.h
35
tables.h
|
@ -1,35 +0,0 @@
|
|||
#ifndef TABLE_H
|
||||
#define TABLE_H
|
||||
|
||||
/*
|
||||
----------------------------------------
|
||||
| Adresse | Registre | Modifié |
|
||||
----------------------------------------
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |
|
||||
| i | 0x777756b8 | int |
|
||||
| size | 0x777756b8 | int |
|
||||
----------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
enum instruction_t {NOP, ADD, MUL, SUB, DIV, CPY, AFC, LOAD, STORE};
|
||||
|
||||
void init(void);
|
||||
void print();
|
||||
void increment_time();
|
||||
int get_reg_read(int adresse, int * added_instruction);
|
||||
int get_reg_write(int adresse, int * added_instruction);
|
||||
void unlink(int adresse);
|
||||
int flush_and_init();
|
||||
void new_instruction(int nb_inst);
|
||||
void write_asm(FILE * file);
|
||||
void write_code_machine(FILE * file);
|
||||
void add_instruction(enum instruction_t inst, int param1, int param2, int param3);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue