No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tables.c 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. #include "tables.h"
  2. #define NB_REG 16 // Nombre de registre dans le processeur
  3. #define MEM_SIZE 64 // Taille de la mémoire de données
  4. #define MEM_INST_SIZE 256 // Taille de la mémoire d'instruction
  5. #define NB_BITS_INSTRUCTION 5 // Nombres de bits codant une instruction
  6. #define NB_BITS 8 // Taille d'un mot du processeur
  7. /**************************************************/
  8. /**************************************************/
  9. /***************** Initialisation *****************/
  10. /**************************************************/
  11. /**************************************************/
  12. // Buffer to patch Jumps difference due to adding LOAD and STORE
  13. int traduction_JMP[MEM_INST_SIZE];
  14. // Index of the buffer
  15. int last_instruction = 0;
  16. // Structure coding an instruction
  17. struct str_instruction {
  18. enum instruction_t instruction;
  19. int param1;
  20. int param2;
  21. int param3;
  22. };
  23. // Buffer to store registers oriented instructions
  24. struct str_instruction buffer[3*MEM_INST_SIZE];
  25. // Structure coding an address and the correpondance with a register
  26. struct case_adresse {
  27. int adresse;
  28. int registre;
  29. char modifie;
  30. };
  31. // Buffer of addresses (Memory)
  32. struct case_adresse tableau[MEM_SIZE];
  33. // Buffer to manage priority policy
  34. int registres[NB_REG];
  35. // Initialise all : the addresses-registers association table, the registers priority table, the instructions buffer, the instruction address association table
  36. void init (void) {
  37. int i;
  38. struct case_adresse case_courante = {0, -1, 0};
  39. for (i=0; i<MEM_SIZE; i++) {
  40. case_courante.adresse = i;
  41. tableau[i] = case_courante;
  42. }
  43. for (i=0; i<NB_REG; i++) {
  44. registres[i] = 0;
  45. }
  46. struct str_instruction nop = {NOP, 0, 0, 0};
  47. for (i=0; i<MEM_INST_SIZE; i++) {
  48. buffer[i] = nop;
  49. }
  50. }
  51. /**************************************************/
  52. /**************************************************/
  53. /************** Registers Management **************/
  54. /**************************************************/
  55. /**************************************************/
  56. // INTERN FUNCTION
  57. // Print a case address
  58. void print_case_adresse(struct case_adresse case_courante) {
  59. printf("{addr : %d ; reg : %d ; modi : %d}\n", case_courante.adresse, case_courante.registre, (int)case_courante.modifie);
  60. }
  61. // Print the adresses-registers correspondance table
  62. void print() {
  63. int i;
  64. for (i=0; i<MEM_SIZE; i++) {
  65. print_case_adresse(tableau[i]);
  66. }
  67. }
  68. // INTERN FUNCTION
  69. // return the case corresponding to the given address
  70. struct case_adresse get_info(int adresse) {
  71. return tableau[adresse];
  72. }
  73. // INTERN FUNCTION
  74. // return the address corresponding to the given register
  75. int get_adresse (int registre) {
  76. int i = 0;
  77. while (i < MEM_SIZE && tableau[i].registre != registre) {
  78. i++;
  79. }
  80. if (i == MEM_SIZE) {
  81. return -1;
  82. } else {
  83. return tableau[i].adresse;
  84. }
  85. }
  86. // INTERN FUNCTION
  87. // Set the given register to the given address
  88. void set_registre(int adresse, int registre) {
  89. tableau[adresse].registre = registre;
  90. }
  91. // INTERN FUNCTION
  92. // Set modifie to the address (0 the value in the memory is up to date, 1 the value in the register is more recent)
  93. void set_modifie(int adresse, char modifie) {
  94. tableau[adresse].modifie = modifie;
  95. }
  96. // Increment the register priority policy buffer
  97. void increment_time() {
  98. int i;
  99. for (i=0; i<NB_REG; i++) {
  100. registres[i]++;
  101. }
  102. }
  103. // INTERN FUNCTION
  104. // Specifie that the given register have been used
  105. void refresh_registre(int registre) {
  106. registres[registre] = 0;
  107. }
  108. // INTERN FUNCTION
  109. // Return the LRU register
  110. int get_register() {
  111. int i;
  112. int index_max = 0;
  113. for (i=0; i<NB_REG; i++) {
  114. if (registres[index_max] < registres[i]) {
  115. index_max = i;
  116. }
  117. }
  118. return index_max;
  119. }
  120. /* Ask for a register to read the value
  121. @param :
  122. - adresse : The address of value wanted
  123. - added_instruction : Address of an int storing the number of added_instructions
  124. @return : The number of the register corresponding to the given address
  125. */
  126. int get_reg_read(int adresse, int * added_instruction) {
  127. struct case_adresse ma_case = get_info(adresse);
  128. if (ma_case.registre == -1) {
  129. int dispo = get_register();
  130. int previous_addr = get_adresse(dispo);
  131. if (previous_addr != -1) {
  132. struct case_adresse ancienne_case = get_info(previous_addr);
  133. if (ancienne_case.modifie == 1) {
  134. *added_instruction = (*added_instruction) + 1;
  135. add_instruction(STORE, previous_addr, dispo, 0);
  136. set_modifie(previous_addr, 0);
  137. }
  138. set_registre(previous_addr, -1);
  139. }
  140. *added_instruction = (*added_instruction) + 1;
  141. add_instruction(LOAD, dispo, adresse, 0);
  142. set_registre(adresse, dispo);
  143. refresh_registre(dispo);
  144. return dispo;
  145. } else {
  146. refresh_registre(ma_case.registre);
  147. return ma_case.registre;
  148. }
  149. }
  150. /* Ask for a register to write the value
  151. @param :
  152. - adresse : The address of value (if -1 return a free register without associating it to any address)
  153. - added_instruction : Address of an int storing the number of added_instructions
  154. @return : The number of the register corresponding to the given address
  155. WARNING : The value of the address will not be LOADED in the register
  156. Always ask READ registers before the WRITE register
  157. */
  158. int get_reg_write(int adresse, int * added_instruction) {
  159. if (adresse == -1) {
  160. int dispo = get_register();
  161. int previous_addr = get_adresse(dispo);
  162. if (previous_addr != -1) {
  163. struct case_adresse ancienne_case = get_info(previous_addr);
  164. if (ancienne_case.modifie == 1) {
  165. add_instruction(STORE, previous_addr, dispo, 0);
  166. *added_instruction = (*added_instruction) + 1;
  167. set_modifie(previous_addr, 0);
  168. }
  169. set_registre(previous_addr, -1);
  170. }
  171. return dispo;
  172. } else {
  173. set_modifie(adresse, 1);
  174. struct case_adresse ma_case = get_info(adresse);
  175. if (ma_case.registre == -1) {
  176. int dispo = get_register();
  177. int previous_addr = get_adresse(dispo);
  178. if (previous_addr != -1) {
  179. struct case_adresse ancienne_case = get_info(previous_addr);
  180. if (ancienne_case.modifie == 1) {
  181. *added_instruction = (*added_instruction) + 1;
  182. add_instruction(STORE, previous_addr, dispo, 0);
  183. set_modifie(previous_addr, 0);
  184. }
  185. set_registre(previous_addr, -1);
  186. }
  187. set_registre(adresse, dispo);
  188. refresh_registre(dispo);
  189. return dispo;
  190. } else {
  191. refresh_registre(ma_case.registre);
  192. return ma_case.registre;
  193. }
  194. }
  195. }
  196. // Broke the association between adresse and its corresponding register
  197. void unlink(int adresse) {
  198. set_registre(adresse, -1);
  199. }
  200. // Store used register, init the association table between addresses and registers
  201. int flush_and_init() {
  202. int i;
  203. int added_instruction = 0;
  204. for (i = 0; i<MEM_SIZE; i++) {
  205. if (tableau[i].registre != -1) {
  206. if (tableau[i].modifie == 0) {
  207. tableau[i].registre = -1;
  208. } else {
  209. add_instruction(STORE, i, tableau[i].registre, 0);
  210. added_instruction++;
  211. tableau[i].registre = -1;
  212. tableau[i].modifie = 0;
  213. }
  214. }
  215. }
  216. for (i=0; i<NB_REG; i++) {
  217. registres[i] = 0;
  218. }
  219. return added_instruction;
  220. }
  221. /**************************************************/
  222. /**************************************************/
  223. /************** Instructions Writing **************/
  224. /**************************************************/
  225. /**************************************************/
  226. // Add a new Registers oriented instruction
  227. void add_instruction(enum instruction_t inst, int param1, int param2, int param3) {
  228. struct str_instruction my_instruction = {inst, param1, param2, param3};
  229. buffer[last_instruction] = my_instruction;
  230. last_instruction++;
  231. }
  232. // Specifie the number of Register oriented instructions corresponding to the memory oriented instruction
  233. void new_instruction(int nb_inst) {
  234. static int last_intruction_adresse = 0;
  235. static int current_instruction = 0;
  236. traduction_JMP[current_instruction] = last_intruction_adresse;
  237. current_instruction++;
  238. last_intruction_adresse += nb_inst;
  239. }
  240. // Write the new assembly in the given file
  241. void write_asm(FILE * file) {
  242. int i = 0;
  243. while (i<MEM_INST_SIZE) {
  244. if (buffer[i].instruction == ADD) {
  245. fprintf(file, "ADD %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
  246. } else if (buffer[i].instruction == SUB) {
  247. fprintf(file, "SUB %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
  248. } else if (buffer[i].instruction == MUL) {
  249. fprintf(file, "MUL %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
  250. } else if (buffer[i].instruction == DIV) {
  251. fprintf(file, "DIV %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
  252. } else if (buffer[i].instruction == INF) {
  253. fprintf(file, "INF %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
  254. } else if (buffer[i].instruction == SUP) {
  255. fprintf(file, "SUP %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
  256. } else if (buffer[i].instruction == EQU) {
  257. fprintf(file, "EQU %d %d %d\n", buffer[i].param1, buffer[i].param2, buffer[i].param3);
  258. } else if (buffer[i].instruction == AFC) {
  259. fprintf(file, "AFC %d %d\n", buffer[i].param1, buffer[i].param2);
  260. } else if (buffer[i].instruction == CPY) {
  261. fprintf(file, "CPY %d %d\n", buffer[i].param1, buffer[i].param2);
  262. } else if (buffer[i].instruction == LOAD) {
  263. fprintf(file, "LOAD %d %d\n", buffer[i].param1, buffer[i].param2);
  264. } else if (buffer[i].instruction == STORE) {
  265. fprintf(file, "STORE %d %d\n", buffer[i].param1, buffer[i].param2);
  266. } else if (buffer[i].instruction == LOADI) {
  267. fprintf(file, "LOADI %d %d\n", buffer[i].param1, buffer[i].param2);
  268. } else if (buffer[i].instruction == STOREI) {
  269. fprintf(file, "STOREI %d %d\n", buffer[i].param1, buffer[i].param2);
  270. } else if (buffer[i].instruction == STOREA) {
  271. fprintf(file, "STOREA %d %d\n", buffer[i].param1, buffer[i].param2);
  272. } else if (buffer[i].instruction == JMP) {
  273. fprintf(file, "JMP %d\n", traduction_JMP[buffer[i].param1]);
  274. } else if (buffer[i].instruction == JMZ) {
  275. fprintf(file, "JMZ %d\n", traduction_JMP[buffer[i].param1]);
  276. } else if (buffer[i].instruction == GET) {
  277. fprintf(file, "GET %d\n", buffer[i].param1);
  278. } else if (buffer[i].instruction == PRI) {
  279. fprintf(file, "PRI %d\n", buffer[i].param1);
  280. } else if (buffer[i].instruction == CALL) {
  281. fprintf(file, "CALL %d %d\n", traduction_JMP[buffer[i].param1], buffer[i].param2);
  282. } else if (buffer[i].instruction == RET) {
  283. fprintf(file, "RET\n");
  284. } else if (buffer[i].instruction == STOP) {
  285. fprintf(file, "STOP %d\n", buffer[i].param1);
  286. }
  287. i++;
  288. }
  289. }
  290. // INTERN FUNCTION
  291. // Write binary value of n in buff
  292. void int_2_bin(char * buff, int n) {
  293. int _m = n;
  294. for (int i = 0; i < 32; i++) {
  295. buff[31 - i] = ((_m & (1 << 31)) ? '1' : '0');
  296. _m = _m << 1;
  297. }
  298. }
  299. // INTERN FUNCTION
  300. // Write binary value of value in buff on N bits
  301. void convert_to_binary_on_N(int value, int N, char * buff) {
  302. char tampon[33];
  303. int_2_bin(tampon, value);
  304. int i;
  305. for (i = N-1; i>=0; i--) {
  306. buff[N-1-i] = tampon[i];
  307. }
  308. buff[N] = '\0';
  309. }
  310. // INTERN FUNCTION
  311. // Write a binary instruction in the given file
  312. // If not compact ("010..10" & ) else only (010..10)
  313. void write_instruction_binary(FILE * file, struct str_instruction instr, char compact) {
  314. char buff1[33];
  315. char buff2[33];
  316. char buff3[33];
  317. char buff4[33];
  318. convert_to_binary_on_N(instr.instruction, NB_BITS_INSTRUCTION, buff1);
  319. if (instr.instruction == JMP || instr.instruction == JMZ || instr.instruction == CALL) {
  320. convert_to_binary_on_N(traduction_JMP[instr.param1], NB_BITS, buff2);
  321. } else {
  322. convert_to_binary_on_N(instr.param1, NB_BITS, buff2);
  323. }
  324. convert_to_binary_on_N(instr.param2, NB_BITS, buff3);
  325. convert_to_binary_on_N(instr.param3, NB_BITS, buff4);
  326. if (compact) {
  327. fprintf(file, "%s%s%s%s", buff1, buff2, buff3, buff4);
  328. } else {
  329. fprintf(file, "\"%s%s%s%s\" & ", buff1, buff2, buff3, buff4);
  330. }
  331. }
  332. // Write the binary code in the given file
  333. void write_code_machine(FILE * file, char compact) {
  334. if (compact) {
  335. int i = MEM_INST_SIZE - 1;
  336. while (i>=0) {
  337. write_instruction_binary(file, buffer[i], 0);
  338. i--;
  339. }
  340. } else {
  341. fprintf(file, "\"");
  342. int i = MEM_INST_SIZE - 1;
  343. while (i>=0) {
  344. write_instruction_binary(file, buffer[i], 1);
  345. i--;
  346. }
  347. fprintf(file, "\"\n");
  348. }
  349. }