123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- /*
- * Andrea Di Biagio
- * Politecnico di Milano, 2007
- *
- * axe_expressions.c
- * Formal Languages & Compilers Machine, 2007/2008
- *
- */
- #include "axe_expressions.h"
- #include "axe_gencode.h"
- #include "axe_errors.h"
- #include "axe_utils.h"
- static t_axe_expression handle_bin_numeric_op_Imm
- (int val1, int val2, int binop);
-
- static t_axe_expression handle_bin_comparison_Imm
- (int val1, int val2, int condition);
- static t_axe_expression normalize(t_program_infos *program,
- t_axe_expression exp);
- t_axe_expression handle_bin_numeric_op (t_program_infos *program
- , t_axe_expression exp1, t_axe_expression exp2, int binop)
- {
- int output_register;
- t_axe_expression result;
- /* initialize result */
- result.expression_type = INVALID_EXPRESSION;
- /* we have to test if one (or both) of
- * the two operands is an immediate value */
- if ( (exp2.expression_type == IMMEDIATE)
- && (exp1.expression_type == IMMEDIATE) )
- {
- return handle_bin_numeric_op_Imm(exp1.value, exp2.value, binop);
- }
- exp1 = normalize(program, exp1);
- exp2 = normalize(program, exp2);
-
- /* at first we have to ask for a free register
- * where to store the result of the operation. */
- output_register = getNewRegister(program);
- if (exp2.expression_type == IMMEDIATE)
- {
- /* we have to produce an instruction */
- switch(binop)
- {
- case ADD : gen_addi_instruction (program, output_register
- , exp1.value, exp2.value); break;
- case ANDB : gen_andbi_instruction (program, output_register
- , exp1.value, exp2.value); break;
- case ORB : gen_orbi_instruction (program, output_register
- , exp1.value, exp2.value); break;
- case SUB : gen_subi_instruction (program, output_register
- , exp1.value, exp2.value); break;
- case MUL : gen_muli_instruction (program, output_register
- , exp1.value, exp2.value); break;
- case SHL : gen_shli_instruction (program, output_register
- , exp1.value, exp2.value); break;
- case SHR : gen_shri_instruction (program, output_register
- , exp1.value, exp2.value); break;
- case DIV :
- if (exp2.value == 0){
- printWarningMessage(WARN_DIVISION_BY_ZERO);
- }
- gen_divi_instruction (program, output_register
- , exp1.value, exp2.value);
- break;
- default :
- notifyError(AXE_INVALID_EXPRESSION);
- }
- }
- else if (exp1.expression_type == IMMEDIATE)
- {
- int other_reg;
- /* we have to produce an instruction */
- switch(binop)
- {
- case ADD : gen_addi_instruction (program, output_register
- , exp2.value, exp1.value); break;
- case ANDB : gen_andbi_instruction (program, output_register
- , exp2.value, exp1.value); break;
- case ORB : gen_orbi_instruction (program, output_register
- , exp2.value, exp1.value); break;
- case SUB :
- gen_subi_instruction (program, output_register
- , exp2.value, exp1.value);
- /* we have to produce a NEG instruction */
- gen_neg_instruction (program, output_register
- , output_register, CG_DIRECT_ALL);
- break;
- case MUL : gen_muli_instruction (program, output_register
- , exp2.value, exp1.value); break;
- case DIV :
- /* we have to load into a register the immediate value */
- other_reg = getNewRegister(program);
- /* In order to load the immediate inside a new
- * register we have to insert an ADDI instr. */
- gen_addi_instruction (program, other_reg
- , REG_0, exp1.value);
- /* we have to produce a DIV instruction */
- gen_div_instruction (program, output_register
- , other_reg, exp2.value, CG_DIRECT_ALL);
- break;
- case SHL :
- /* we have to load into a register the immediate value */
- other_reg = getNewRegister(program);
- /* In order to load the immediate inside a new
- * register we have to insert an ADDI instr. */
- gen_addi_instruction (program, other_reg
- , REG_0, exp1.value);
- /* we have to produce a SHL instruction */
- gen_shl_instruction (program, output_register
- , other_reg, exp2.value, CG_DIRECT_ALL);
- break;
- case SHR :
- /* we have to load into a register the immediate value */
- other_reg = getNewRegister(program);
- /* In order to load the immediate inside a new
- * register we have to insert an ADDI instr. */
- gen_addi_instruction (program, other_reg
- , REG_0, exp1.value);
- /* we have to produce a SHR instruction */
- gen_shr_instruction (program, output_register
- , other_reg, exp2.value, CG_DIRECT_ALL);
- break;
- default :
- notifyError(AXE_INVALID_EXPRESSION);
- }
- }
- else
- {
- /* we have to produce an instruction */
- switch(binop)
- {
- case ADD : gen_add_instruction (program, output_register
- , exp1.value, exp2.value, CG_DIRECT_ALL);
- break;
- case ANDB : gen_andb_instruction (program, output_register
- , exp1.value, exp2.value, CG_DIRECT_ALL);
- break;
- case ORB : gen_orb_instruction (program, output_register
- , exp1.value, exp2.value, CG_DIRECT_ALL);
- break;
- case SUB : gen_sub_instruction (program, output_register
- , exp1.value, exp2.value, CG_DIRECT_ALL);
- break;
- case MUL : gen_mul_instruction (program, output_register
- , exp1.value, exp2.value, CG_DIRECT_ALL);
- break;
- case DIV : gen_div_instruction (program, output_register
- , exp1.value, exp2.value, CG_DIRECT_ALL);
- break;
- case SHL : gen_shl_instruction (program, output_register
- , exp1.value, exp2.value, CG_DIRECT_ALL);
- break;
- case SHR : gen_shr_instruction (program, output_register
- , exp1.value, exp2.value, CG_DIRECT_ALL);
- break;
- default :
- notifyError(AXE_INVALID_EXPRESSION);
- }
- }
-
- /* assign a value to result */
- return create_expression (output_register, REGISTER);
- }
- t_axe_expression handle_bin_numeric_op_Imm
- (int val1, int val2, int binop)
- {
- switch(binop)
- {
- case ADD : return create_expression ((val1 + val2), IMMEDIATE);
- case ANDB : return create_expression ((val1 & val2), IMMEDIATE);
- case ORB : return create_expression ((val1 | val2), IMMEDIATE);
- case SUB : return create_expression ((val1 - val2), IMMEDIATE);
- case MUL : return create_expression ((val1 * val2), IMMEDIATE);
- case SHL : return create_expression ((val1 << val2), IMMEDIATE);
- case SHR : return create_expression ((val1 >> val2), IMMEDIATE);
- case DIV :
- if (val2 == 0){
- printWarningMessage(WARN_DIVISION_BY_ZERO);
- }
- return create_expression ((val1 / val2), IMMEDIATE);
- default :
- notifyError(AXE_INVALID_EXPRESSION);
- }
-
- return create_expression (0, INVALID_EXPRESSION);
- }
- t_axe_expression handle_bin_comparison_Imm
- (int val1, int val2, int condition)
- {
- switch(condition)
- {
- case _LT_ : return create_expression ((val1 < val2), IMMEDIATE);
- case _GT_ : return create_expression ((val1 > val2), IMMEDIATE);
- case _EQ_ : return create_expression ((val1 == val2), IMMEDIATE);
- case _NOTEQ_ : return create_expression ((val1 != val2), IMMEDIATE);
- case _LTEQ_ : return create_expression ((val1 <= val2), IMMEDIATE);
- case _GTEQ_ : return create_expression ((val1 >= val2), IMMEDIATE);
- default :
- notifyError(AXE_INVALID_EXPRESSION);
- }
- return create_expression (0, INVALID_EXPRESSION);
- }
- t_axe_expression normalize(t_program_infos *program, t_axe_expression exp)
- {
- if (exp.expression_type == IMMEDIATE && !is_int16(exp.value))
- {
- int tmp_reg = gen_load_immediate(program, exp.value);
- return create_expression(tmp_reg, REGISTER);
- }
- return exp;
- }
- t_axe_expression handle_binary_comparison (t_program_infos *program
- , t_axe_expression exp1, t_axe_expression exp2, int condition)
- {
- t_axe_expression result;
- int output_register;
-
- /* initialize result */
- result.expression_type = INVALID_EXPRESSION;
- /* we have to test if one (or both) of
- * the two operands is an immediate value */
- if ( (exp2.expression_type == IMMEDIATE)
- && (exp1.expression_type == IMMEDIATE) )
- {
- return handle_bin_comparison_Imm
- (exp1.value, exp2.value, condition);
- }
- exp1 = normalize(program, exp1);
- exp2 = normalize(program, exp2);
-
- /* at first we have to ask for a free register
- * where to store the result of the comparison. */
- output_register = getNewRegister(program);
- if (exp2.expression_type == IMMEDIATE)
- {
- /* we have to produce a SUBI instruction */
- gen_subi_instruction (program, output_register
- , exp1.value, exp2.value);
- }
- else if (exp1.expression_type == IMMEDIATE)
- {
- gen_subi_instruction (program, output_register
- , exp2.value, exp1.value);
- /* we have to produce a NEG instruction */
- gen_neg_instruction (program, output_register
- , output_register, CG_DIRECT_ALL);
- }
- else
- {
- /* we have to produce a SUB instruction */
- gen_sub_instruction (program, output_register
- , exp1.value, exp2.value, CG_DIRECT_ALL);
- }
- /* generate a set instruction */
- switch(condition)
- {
- case _LT_ : gen_slt_instruction (program, output_register); break;
- case _GT_ : gen_sgt_instruction (program, output_register); break;
- case _EQ_ : gen_seq_instruction (program, output_register); break;
- case _NOTEQ_ : gen_sne_instruction (program, output_register); break;
- case _LTEQ_ : gen_sle_instruction (program, output_register); break;
- case _GTEQ_ : gen_sge_instruction (program, output_register); break;
- default :
- notifyError(AXE_INVALID_EXPRESSION);
- }
- /* return the new expression */
- return create_expression (output_register, REGISTER);
- }
|