axe_expressions.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * Andrea Di Biagio
  3. * Politecnico di Milano, 2007
  4. *
  5. * axe_expressions.c
  6. * Formal Languages & Compilers Machine, 2007/2008
  7. *
  8. */
  9. #include "axe_expressions.h"
  10. #include "axe_gencode.h"
  11. #include "axe_errors.h"
  12. #include "axe_utils.h"
  13. static t_axe_expression handle_bin_numeric_op_Imm
  14. (int val1, int val2, int binop);
  15. static t_axe_expression handle_bin_comparison_Imm
  16. (int val1, int val2, int condition);
  17. static t_axe_expression normalize(t_program_infos *program,
  18. t_axe_expression exp);
  19. t_axe_expression handle_bin_numeric_op (t_program_infos *program
  20. , t_axe_expression exp1, t_axe_expression exp2, int binop)
  21. {
  22. int output_register;
  23. t_axe_expression result;
  24. /* initialize result */
  25. result.expression_type = INVALID_EXPRESSION;
  26. /* we have to test if one (or both) of
  27. * the two operands is an immediate value */
  28. if ( (exp2.expression_type == IMMEDIATE)
  29. && (exp1.expression_type == IMMEDIATE) )
  30. {
  31. return handle_bin_numeric_op_Imm(exp1.value, exp2.value, binop);
  32. }
  33. exp1 = normalize(program, exp1);
  34. exp2 = normalize(program, exp2);
  35. /* at first we have to ask for a free register
  36. * where to store the result of the operation. */
  37. output_register = getNewRegister(program);
  38. if (exp2.expression_type == IMMEDIATE)
  39. {
  40. /* we have to produce an instruction */
  41. switch(binop)
  42. {
  43. case ADD : gen_addi_instruction (program, output_register
  44. , exp1.value, exp2.value); break;
  45. case ANDB : gen_andbi_instruction (program, output_register
  46. , exp1.value, exp2.value); break;
  47. case ORB : gen_orbi_instruction (program, output_register
  48. , exp1.value, exp2.value); break;
  49. case SUB : gen_subi_instruction (program, output_register
  50. , exp1.value, exp2.value); break;
  51. case MUL : gen_muli_instruction (program, output_register
  52. , exp1.value, exp2.value); break;
  53. case SHL : gen_shli_instruction (program, output_register
  54. , exp1.value, exp2.value); break;
  55. case SHR : gen_shri_instruction (program, output_register
  56. , exp1.value, exp2.value); break;
  57. case DIV :
  58. if (exp2.value == 0){
  59. printWarningMessage(WARN_DIVISION_BY_ZERO);
  60. }
  61. gen_divi_instruction (program, output_register
  62. , exp1.value, exp2.value);
  63. break;
  64. default :
  65. notifyError(AXE_INVALID_EXPRESSION);
  66. }
  67. }
  68. else if (exp1.expression_type == IMMEDIATE)
  69. {
  70. int other_reg;
  71. /* we have to produce an instruction */
  72. switch(binop)
  73. {
  74. case ADD : gen_addi_instruction (program, output_register
  75. , exp2.value, exp1.value); break;
  76. case ANDB : gen_andbi_instruction (program, output_register
  77. , exp2.value, exp1.value); break;
  78. case ORB : gen_orbi_instruction (program, output_register
  79. , exp2.value, exp1.value); break;
  80. case SUB :
  81. gen_subi_instruction (program, output_register
  82. , exp2.value, exp1.value);
  83. /* we have to produce a NEG instruction */
  84. gen_neg_instruction (program, output_register
  85. , output_register, CG_DIRECT_ALL);
  86. break;
  87. case MUL : gen_muli_instruction (program, output_register
  88. , exp2.value, exp1.value); break;
  89. case DIV :
  90. /* we have to load into a register the immediate value */
  91. other_reg = getNewRegister(program);
  92. /* In order to load the immediate inside a new
  93. * register we have to insert an ADDI instr. */
  94. gen_addi_instruction (program, other_reg
  95. , REG_0, exp1.value);
  96. /* we have to produce a DIV instruction */
  97. gen_div_instruction (program, output_register
  98. , other_reg, exp2.value, CG_DIRECT_ALL);
  99. break;
  100. case SHL :
  101. /* we have to load into a register the immediate value */
  102. other_reg = getNewRegister(program);
  103. /* In order to load the immediate inside a new
  104. * register we have to insert an ADDI instr. */
  105. gen_addi_instruction (program, other_reg
  106. , REG_0, exp1.value);
  107. /* we have to produce a SHL instruction */
  108. gen_shl_instruction (program, output_register
  109. , other_reg, exp2.value, CG_DIRECT_ALL);
  110. break;
  111. case SHR :
  112. /* we have to load into a register the immediate value */
  113. other_reg = getNewRegister(program);
  114. /* In order to load the immediate inside a new
  115. * register we have to insert an ADDI instr. */
  116. gen_addi_instruction (program, other_reg
  117. , REG_0, exp1.value);
  118. /* we have to produce a SHR instruction */
  119. gen_shr_instruction (program, output_register
  120. , other_reg, exp2.value, CG_DIRECT_ALL);
  121. break;
  122. default :
  123. notifyError(AXE_INVALID_EXPRESSION);
  124. }
  125. }
  126. else
  127. {
  128. /* we have to produce an instruction */
  129. switch(binop)
  130. {
  131. case ADD : gen_add_instruction (program, output_register
  132. , exp1.value, exp2.value, CG_DIRECT_ALL);
  133. break;
  134. case ANDB : gen_andb_instruction (program, output_register
  135. , exp1.value, exp2.value, CG_DIRECT_ALL);
  136. break;
  137. case ORB : gen_orb_instruction (program, output_register
  138. , exp1.value, exp2.value, CG_DIRECT_ALL);
  139. break;
  140. case SUB : gen_sub_instruction (program, output_register
  141. , exp1.value, exp2.value, CG_DIRECT_ALL);
  142. break;
  143. case MUL : gen_mul_instruction (program, output_register
  144. , exp1.value, exp2.value, CG_DIRECT_ALL);
  145. break;
  146. case DIV : gen_div_instruction (program, output_register
  147. , exp1.value, exp2.value, CG_DIRECT_ALL);
  148. break;
  149. case SHL : gen_shl_instruction (program, output_register
  150. , exp1.value, exp2.value, CG_DIRECT_ALL);
  151. break;
  152. case SHR : gen_shr_instruction (program, output_register
  153. , exp1.value, exp2.value, CG_DIRECT_ALL);
  154. break;
  155. default :
  156. notifyError(AXE_INVALID_EXPRESSION);
  157. }
  158. }
  159. /* assign a value to result */
  160. return create_expression (output_register, REGISTER);
  161. }
  162. t_axe_expression handle_bin_numeric_op_Imm
  163. (int val1, int val2, int binop)
  164. {
  165. switch(binop)
  166. {
  167. case ADD : return create_expression ((val1 + val2), IMMEDIATE);
  168. case ANDB : return create_expression ((val1 & val2), IMMEDIATE);
  169. case ORB : return create_expression ((val1 | val2), IMMEDIATE);
  170. case SUB : return create_expression ((val1 - val2), IMMEDIATE);
  171. case MUL : return create_expression ((val1 * val2), IMMEDIATE);
  172. case SHL : return create_expression ((val1 << val2), IMMEDIATE);
  173. case SHR : return create_expression ((val1 >> val2), IMMEDIATE);
  174. case DIV :
  175. if (val2 == 0){
  176. printWarningMessage(WARN_DIVISION_BY_ZERO);
  177. }
  178. return create_expression ((val1 / val2), IMMEDIATE);
  179. default :
  180. notifyError(AXE_INVALID_EXPRESSION);
  181. }
  182. return create_expression (0, INVALID_EXPRESSION);
  183. }
  184. t_axe_expression handle_bin_comparison_Imm
  185. (int val1, int val2, int condition)
  186. {
  187. switch(condition)
  188. {
  189. case _LT_ : return create_expression ((val1 < val2), IMMEDIATE);
  190. case _GT_ : return create_expression ((val1 > val2), IMMEDIATE);
  191. case _EQ_ : return create_expression ((val1 == val2), IMMEDIATE);
  192. case _NOTEQ_ : return create_expression ((val1 != val2), IMMEDIATE);
  193. case _LTEQ_ : return create_expression ((val1 <= val2), IMMEDIATE);
  194. case _GTEQ_ : return create_expression ((val1 >= val2), IMMEDIATE);
  195. default :
  196. notifyError(AXE_INVALID_EXPRESSION);
  197. }
  198. return create_expression (0, INVALID_EXPRESSION);
  199. }
  200. t_axe_expression normalize(t_program_infos *program, t_axe_expression exp)
  201. {
  202. if (exp.expression_type == IMMEDIATE && !is_int16(exp.value))
  203. {
  204. int tmp_reg = gen_load_immediate(program, exp.value);
  205. return create_expression(tmp_reg, REGISTER);
  206. }
  207. return exp;
  208. }
  209. t_axe_expression handle_binary_comparison (t_program_infos *program
  210. , t_axe_expression exp1, t_axe_expression exp2, int condition)
  211. {
  212. t_axe_expression result;
  213. int output_register;
  214. /* initialize result */
  215. result.expression_type = INVALID_EXPRESSION;
  216. /* we have to test if one (or both) of
  217. * the two operands is an immediate value */
  218. if ( (exp2.expression_type == IMMEDIATE)
  219. && (exp1.expression_type == IMMEDIATE) )
  220. {
  221. return handle_bin_comparison_Imm
  222. (exp1.value, exp2.value, condition);
  223. }
  224. exp1 = normalize(program, exp1);
  225. exp2 = normalize(program, exp2);
  226. /* at first we have to ask for a free register
  227. * where to store the result of the comparison. */
  228. output_register = getNewRegister(program);
  229. if (exp2.expression_type == IMMEDIATE)
  230. {
  231. /* we have to produce a SUBI instruction */
  232. gen_subi_instruction (program, output_register
  233. , exp1.value, exp2.value);
  234. }
  235. else if (exp1.expression_type == IMMEDIATE)
  236. {
  237. gen_subi_instruction (program, output_register
  238. , exp2.value, exp1.value);
  239. /* we have to produce a NEG instruction */
  240. gen_neg_instruction (program, output_register
  241. , output_register, CG_DIRECT_ALL);
  242. }
  243. else
  244. {
  245. /* we have to produce a SUB instruction */
  246. gen_sub_instruction (program, output_register
  247. , exp1.value, exp2.value, CG_DIRECT_ALL);
  248. }
  249. /* generate a set instruction */
  250. switch(condition)
  251. {
  252. case _LT_ : gen_slt_instruction (program, output_register); break;
  253. case _GT_ : gen_sgt_instruction (program, output_register); break;
  254. case _EQ_ : gen_seq_instruction (program, output_register); break;
  255. case _NOTEQ_ : gen_sne_instruction (program, output_register); break;
  256. case _LTEQ_ : gen_sle_instruction (program, output_register); break;
  257. case _GTEQ_ : gen_sge_instruction (program, output_register); break;
  258. default :
  259. notifyError(AXE_INVALID_EXPRESSION);
  260. }
  261. /* return the new expression */
  262. return create_expression (output_register, REGISTER);
  263. }