123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- #include "tables.h"
- #define NB_REG 16 // Nombre de registre dans le processeur
- #define MEM_SIZE 64 // Taille de la mémoire de données
- #define MEM_INST_SIZE 256 // Taille de la mémoire d'instruction
- #define NB_BITS_INSTRUCTION 5 // Nombres de bits codant une instruction
- #define NB_BITS 8 // Taille d'un mot du processeur
-
-
-
- /**************************************************/
- /**************************************************/
- /***************** 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;
- int param2;
- int param3;
- };
-
- // 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};
- for (i=0; i<MEM_SIZE; i++) {
- case_courante.adresse = i;
- tableau[i] = case_courante;
- }
- for (i=0; i<NB_REG; i++) {
- registres[i] = 0;
- }
- struct str_instruction nop = {NOP, 0, 0, 0};
- for (i=0; i<MEM_INST_SIZE; i++) {
- buffer[i] = nop;
- }
- }
-
-
- /**************************************************/
- /**************************************************/
- /************** 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++) {
- print_case_adresse(tableau[i]);
- }
- }
-
- // 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) {
- i++;
- }
- if (i == MEM_SIZE) {
- return -1;
- } else {
- return tableau[i].adresse;
- }
- }
-
- // 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++) {
- registres[i]++;
- }
- }
-
- // 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;
- for (i=0; i<NB_REG; i++) {
- if (registres[index_max] < registres[i]) {
- index_max = i;
- }
- }
- 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();
- int previous_addr = get_adresse(dispo);
- if (previous_addr != -1) {
- struct case_adresse ancienne_case = get_info(previous_addr);
- if (ancienne_case.modifie == 1) {
- add_instruction(STORE, previous_addr, dispo, 0);
- *added_instruction = (*added_instruction) + 1;
- set_modifie(previous_addr, 0);
- }
- set_registre(previous_addr, -1);
- }
- return dispo;
- } else {
- set_modifie(adresse, 1);
- 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);
- }
- 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;
- for (i = 0; i<MEM_SIZE; i++) {
- if (tableau[i].registre != -1) {
- if (tableau[i].modifie == 0) {
- tableau[i].registre = -1;
- } else {
- add_instruction(STORE, i, tableau[i].registre, 0);
- added_instruction++;
- tableau[i].registre = -1;
- tableau[i].modifie = 0;
- }
- }
- }
- for (i=0; i<NB_REG; i++) {
- registres[i] = 0;
- }
- 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;
- traduction_JMP[current_instruction] = last_intruction_adresse;
- 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");
- }
- }
|