/* * Andrea Di Biagio * Politecnico di Milano, 2007 * * axe_gencode.c * Formal Languages & Compilers Machine, 2007/2008 * */ #include "axe_gencode.h" #include "axe_errors.h" static t_axe_instruction * gen_unary_instruction (t_program_infos *program , int opcode, int r_dest, t_axe_label *label, int addr); static t_axe_instruction * gen_binary_instruction (t_program_infos *program , int opcode, int r_dest, int r_source1, int immediate); static t_axe_instruction * gen_ternary_instruction (t_program_infos *program , int opcode, int r_dest, int r_source1, int r_source2, int flags); static t_axe_instruction * gen_jump_instruction (t_program_infos *program , int opcode, t_axe_label *label, int addr); t_axe_instruction * gen_bt_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BT, label, addr); } t_axe_instruction * gen_bf_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BF, label, addr); } t_axe_instruction * gen_bhi_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BHI, label, addr); } t_axe_instruction * gen_bls_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BLS, label, addr); } t_axe_instruction * gen_bcc_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BCC, label, addr); } t_axe_instruction * gen_bcs_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BCS, label, addr); } t_axe_instruction * gen_bne_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BNE, label, addr); } t_axe_instruction * gen_beq_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BEQ, label, addr); } t_axe_instruction * gen_bvc_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BVC, label, addr); } t_axe_instruction * gen_bvs_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BVS, label, addr); } t_axe_instruction * gen_bpl_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BPL, label, addr); } t_axe_instruction * gen_bmi_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BMI, label, addr); } t_axe_instruction * gen_bge_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BGE, label, addr); } t_axe_instruction * gen_blt_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BLT, label, addr); } t_axe_instruction * gen_bgt_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BGT, label, addr); } t_axe_instruction * gen_ble_instruction (t_program_infos *program, t_axe_label *label, int addr) { return gen_jump_instruction (program, BLE, label, addr); } t_axe_instruction * gen_add_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { return gen_ternary_instruction (program, ADD, r_dest, r_source1, r_source2, flags); } t_axe_instruction * gen_sub_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { return gen_ternary_instruction (program, SUB, r_dest, r_source1, r_source2, flags); } t_axe_instruction * gen_andl_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { return gen_ternary_instruction (program, ANDL, r_dest, r_source1, r_source2, flags); } t_axe_instruction * gen_orl_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { return gen_ternary_instruction (program, ORL, r_dest, r_source1, r_source2, flags); } t_axe_instruction * gen_eorl_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { return gen_ternary_instruction (program, EORL, r_dest, r_source1, r_source2, flags); } t_axe_instruction * gen_andb_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { return gen_ternary_instruction (program, ANDB, r_dest, r_source1, r_source2, flags); } t_axe_instruction * gen_orb_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { return gen_ternary_instruction (program, ORB, r_dest, r_source1, r_source2, flags); } t_axe_instruction * gen_eorb_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { return gen_ternary_instruction (program, EORB, r_dest, r_source1, r_source2, flags); } t_axe_instruction * gen_mul_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { return gen_ternary_instruction (program, MUL, r_dest, r_source1, r_source2, flags); } t_axe_instruction * gen_div_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { return gen_ternary_instruction (program, DIV, r_dest, r_source1, r_source2, flags); } t_axe_instruction * gen_shl_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { /* The SHL operational semantic is: source2 << source1. Because of this we * need to put the value to shift in source2, and the shift-amount in source1 */ return gen_ternary_instruction (program, SHL, r_dest, r_source2, r_source1, flags); } t_axe_instruction * gen_shr_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { /* The SHR operational semantic is: source2 >> source1. Because of this we * need to put the value to shift in source2, and the shift-amount in source1 */ return gen_ternary_instruction (program, SHR, r_dest, r_source2, r_source1, flags); } t_axe_instruction * gen_neg_instruction (t_program_infos *program , int r_dest, int r_source, int flags) { return gen_ternary_instruction (program, SUB, r_dest, REG_0, r_source, flags); } t_axe_instruction * gen_spcl_instruction (t_program_infos *program , int r_dest, int r_source1, int r_source2, int flags) { return gen_ternary_instruction (program, SPCL, r_dest, r_source1, r_source2, flags); } t_axe_instruction * gen_addi_instruction (t_program_infos *program, int r_dest, int r_source1, int immediate) { return gen_binary_instruction(program, ADDI , r_dest, r_source1, immediate); } t_axe_instruction * gen_subi_instruction (t_program_infos *program, int r_dest, int r_source1, int immediate) { return gen_binary_instruction(program, SUBI , r_dest, r_source1, immediate); } t_axe_instruction * gen_andli_instruction (t_program_infos *program, int r_dest, int r_source1, int immediate) { return gen_binary_instruction(program, ANDLI , r_dest, r_source1, immediate); } t_axe_instruction * gen_orli_instruction (t_program_infos *program, int r_dest, int r_source1, int immediate) { return gen_binary_instruction(program, ORLI , r_dest, r_source1, immediate); } t_axe_instruction * gen_eorli_instruction (t_program_infos *program, int r_dest, int r_source1, int immediate) { return gen_binary_instruction(program, EORLI , r_dest, r_source1, immediate); } t_axe_instruction * gen_andbi_instruction (t_program_infos *program, int r_dest, int r_source1, int immediate) { return gen_binary_instruction(program, ANDBI , r_dest, r_source1, immediate); } t_axe_instruction * gen_muli_instruction (t_program_infos *program, int r_dest, int r_source1, int immediate) { return gen_binary_instruction(program, MULI , r_dest, r_source1, immediate); } t_axe_instruction * gen_orbi_instruction (t_program_infos *program, int r_dest, int r_source1, int immediate) { return gen_binary_instruction(program, ORBI , r_dest, r_source1, immediate); } t_axe_instruction * gen_eorbi_instruction (t_program_infos *program, int r_dest, int r_source1, int immediate) { return gen_binary_instruction(program, EORBI , r_dest, r_source1, immediate); } t_axe_instruction * gen_divi_instruction (t_program_infos *program, int r_dest, int r_source1, int immediate) { return gen_binary_instruction(program, DIVI , r_dest, r_source1, immediate); } t_axe_instruction * gen_shli_instruction (t_program_infos *program, int r_dest, int r_source1, int immediate) { return gen_binary_instruction(program, SHLI , r_dest, r_source1, immediate); } t_axe_instruction * gen_shri_instruction (t_program_infos *program, int r_dest, int r_source1, int immediate) { return gen_binary_instruction(program, SHRI , r_dest, r_source1, immediate); } t_axe_instruction * gen_notl_instruction (t_program_infos *program, int r_dest, int r_source1) { return gen_binary_instruction(program, NOTL , r_dest, r_source1, 0); } t_axe_instruction * gen_notb_instruction (t_program_infos *program, int r_dest, int r_source1) { return gen_binary_instruction(program, NOTB , r_dest, r_source1, 0); } t_axe_instruction * gen_read_instruction (t_program_infos *program, int r_dest) { return gen_unary_instruction(program, AXE_READ, r_dest, NULL, 0); } t_axe_instruction * gen_write_instruction (t_program_infos *program, int r_dest) { return gen_unary_instruction(program, AXE_WRITE, r_dest, NULL, 0); } t_axe_instruction * gen_load_instruction (t_program_infos *program, int r_dest, t_axe_label *label, int address) { return gen_unary_instruction(program, LOAD, r_dest, label, address); } t_axe_instruction * gen_store_instruction (t_program_infos *program, int r_dest, t_axe_label *label, int address) { return gen_unary_instruction(program, STORE, r_dest, label, address); } t_axe_instruction * gen_mova_instruction (t_program_infos *program, int r_dest, t_axe_label *label, int address) { return gen_unary_instruction(program, MOVA, r_dest, label, address); } t_axe_instruction * gen_sge_instruction (t_program_infos *program, int r_dest) { return gen_unary_instruction(program, SGE, r_dest, NULL, 0); } t_axe_instruction * gen_seq_instruction (t_program_infos *program, int r_dest) { return gen_unary_instruction(program, SEQ, r_dest, NULL, 0); } t_axe_instruction * gen_sgt_instruction (t_program_infos *program, int r_dest) { return gen_unary_instruction(program, SGT, r_dest, NULL, 0); } t_axe_instruction * gen_sle_instruction (t_program_infos *program, int r_dest) { return gen_unary_instruction(program, SLE, r_dest, NULL, 0); } t_axe_instruction * gen_slt_instruction (t_program_infos *program, int r_dest) { return gen_unary_instruction(program, SLT, r_dest, NULL, 0); } t_axe_instruction * gen_sne_instruction (t_program_infos *program, int r_dest) { return gen_unary_instruction(program, SNE, r_dest, NULL, 0); } t_axe_instruction * gen_halt_instruction (t_program_infos *program) { t_axe_instruction *instr; /* test if program is initialized */ if (program == NULL) notifyError(AXE_PROGRAM_NOT_INITIALIZED); /* create an instance of `t_axe_instruction' */ instr = alloc_instruction(HALT); if (instr == NULL) notifyError(AXE_OUT_OF_MEMORY); /* add the newly created instruction to the current program */ addInstruction(program, instr); /* return the load instruction */ return instr; } t_axe_instruction * gen_nop_instruction(t_program_infos *program) { t_axe_instruction *instr; /* test if program is initialized */ if (program == NULL) notifyError(AXE_PROGRAM_NOT_INITIALIZED); /* create an instance of `t_axe_instruction' */ instr = alloc_instruction(NOP); if (instr == NULL) notifyError(AXE_OUT_OF_MEMORY); /* add the newly created instruction to the current program */ addInstruction(program, instr); /* return the load instruction */ return instr; } t_axe_instruction * gen_unary_instruction (t_program_infos *program , int opcode, int r_dest, t_axe_label *label, int addr) { t_axe_instruction *instr; t_axe_register *reg; t_axe_address *address; int addressType; /* test if program is initialized */ if (program == NULL) notifyError(AXE_PROGRAM_NOT_INITIALIZED); if (r_dest == REG_INVALID) notifyError(AXE_INVALID_REGISTER_INFO); /* test if value is correctly initialized */ if (label != NULL) { if (label->labelID == LABEL_UNSPECIFIED) { notifyError(AXE_INVALID_LABEL); } /* address type is a label type */ addressType = LABEL_TYPE; } else { if (addr < 0) notifyError(AXE_INVALID_ADDRESS); /* address type is a label type */ addressType = ADDRESS_TYPE; } /* test if the opcode is a valid opcode */ if (opcode == INVALID_OPCODE) notifyError(AXE_INVALID_OPCODE); /* create an instance of `t_axe_instruction' */ instr = alloc_instruction(opcode); if (instr == NULL) notifyError(AXE_OUT_OF_MEMORY); /* initialize a register info */ reg = alloc_register(r_dest, 0); if (reg == NULL) { free_Instruction(instr); notifyError(AXE_OUT_OF_MEMORY); } /* update the reg_1 info */ instr->reg_1 = reg; /* initialize an address info */ address = alloc_address(addressType, addr, label); if (address == NULL) { free_Instruction(instr); notifyError(AXE_OUT_OF_MEMORY); } /* update the instruction address info */ instr->address = address; /* add the newly created instruction to the current program */ addInstruction(program, instr); /* return the load instruction */ return instr; } t_axe_instruction * gen_binary_instruction (t_program_infos *program , int opcode, int r_dest, int r_source1, int immediate) { t_axe_instruction *instr; t_axe_register *reg_dest; t_axe_register *reg_source1; /* test if program is initialized */ if (program == NULL) notifyError(AXE_PROGRAM_NOT_INITIALIZED); /* test if value is correctly initialized */ if ( (r_dest == REG_INVALID) || (r_source1 == REG_INVALID) ) { notifyError(AXE_INVALID_REGISTER_INFO); } /* create an instance of `t_axe_instruction' */ instr = alloc_instruction(opcode); if (instr == NULL) notifyError(AXE_OUT_OF_MEMORY); /* initialize a register info */ reg_dest = alloc_register(r_dest, 0); if (reg_dest == NULL) { free_Instruction(instr); notifyError(AXE_OUT_OF_MEMORY); } /* update the reg_1 info */ instr->reg_1 = reg_dest; reg_source1 = alloc_register(r_source1, 0); if (reg_source1 == NULL) { free_Instruction(instr); notifyError(AXE_OUT_OF_MEMORY); return NULL; } /* update the reg_1 info */ instr->reg_2 = reg_source1; /* assign an immediate value */ instr->immediate = immediate; /* add the newly created instruction to the current program */ addInstruction(program, instr); /* return the load instruction */ return instr; } t_axe_instruction * gen_ternary_instruction (t_program_infos *program , int opcode, int r_dest, int r_source1, int r_source2, int flags) { t_axe_instruction *instr; t_axe_register *reg_dest; t_axe_register *reg_source1; t_axe_register *reg_source2; /* test if program is initialized */ if (program == NULL) notifyError(AXE_PROGRAM_NOT_INITIALIZED); /* test if value is correctly initialized */ if ( (r_dest == REG_INVALID) || (r_source1 == REG_INVALID) || (r_source2 == REG_INVALID)) { notifyError(AXE_INVALID_REGISTER_INFO); } /* create an instance of `t_axe_instruction' */ instr = alloc_instruction(opcode); if (instr == NULL) notifyError(AXE_OUT_OF_MEMORY); /* initialize a register info */ reg_dest = alloc_register(r_dest, ((flags & CG_INDIRECT_DEST)? 1 : 0) ); if (reg_dest == NULL) { free_Instruction(instr); notifyError(AXE_OUT_OF_MEMORY); } /* update the reg_1 info */ instr->reg_1 = reg_dest; reg_source1 = alloc_register(r_source1, 0); if (reg_source1 == NULL) { free_Instruction(instr); notifyError(AXE_OUT_OF_MEMORY); } /* update the reg_2 info */ instr->reg_2 = reg_source1; reg_source2 = alloc_register(r_source2, ((flags & CG_INDIRECT_SOURCE)? 1 : 0)); if (reg_source1 == NULL) { free_Instruction(instr); notifyError(AXE_OUT_OF_MEMORY); } /* update the reg_3 info */ instr->reg_3 = reg_source2; /* add the newly created instruction to the current program */ addInstruction(program, instr); /* return the load instruction */ return instr; } t_axe_instruction * gen_jump_instruction (t_program_infos *program , int opcode, t_axe_label *label, int addr) { t_axe_instruction *instr; t_axe_address * address; int addressType; /* test if program is initialized */ if (program == NULL) notifyError(AXE_PROGRAM_NOT_INITIALIZED); /* test if value is correctly initialized */ if (label != NULL) { if (label->labelID == LABEL_UNSPECIFIED) notifyError(AXE_INVALID_LABEL); addressType = LABEL_TYPE; } else { if (addr < 0) notifyError(AXE_INVALID_ADDRESS); addressType = ADDRESS_TYPE; } /* test if the opcode is a valid opcode */ if (opcode == INVALID_OPCODE) notifyError(AXE_INVALID_OPCODE); /* create an instance of `t_axe_instruction' */ instr = alloc_instruction(opcode); if (instr == NULL) notifyError(AXE_OUT_OF_MEMORY); /* initialize an address info */ address = alloc_address(addressType, addr, label); if (address == NULL) { free_Instruction(instr); notifyError(AXE_OUT_OF_MEMORY); } /* update the instruction address info */ instr->address = address; /* add the newly created instruction to the current program */ addInstruction(program, instr); /* return the load instruction */ return instr; }