peepc30.c
来自「一款拥有一定历史的C语言编译器」· C语言 代码 · 共 2,250 行 · 第 1/5 页
C
2,250 行
/* op_stf_stf */ PAR_DEST_OVERWRITE | FLOAT_INSTR, /* op_sti_sti */ PAR_DEST_OVERWRITE, /* op_ldf_ldf */ PAR_DEST_OVERWRITE | FLOAT_INSTR, /* op_ldi_ldi */ PAR_DEST_OVERWRITE, /* op_absf_stf */ PAR_DEST_OVERWRITE | SET_FLAGS | FLOAT_INSTR, /* op_absi_sti */ PAR_DEST_OVERWRITE | SET_FLAGS, /* op_addf3_stf */ PAR_DEST_OVERWRITE | SET_FLAGS | FLOAT_INSTR, /* op_addi3_sti */ PAR_DEST_OVERWRITE | SET_FLAGS, /* op_and3_sti */ PAR_DEST_OVERWRITE | SET_FLAGS, /* op_ash3_sti */ PAR_DEST_OVERWRITE | SET_FLAGS, /* op_fix_sti */ PAR_DEST_OVERWRITE | SET_FLAGS | FLOAT_INSTR, /* op_float_stf */ PAR_DEST_OVERWRITE | SET_FLAGS | FLOAT_INSTR, /* op_ldf_stf */ PAR_DEST_OVERWRITE | FLOAT_INSTR, /* op_ldi_sti */ PAR_DEST_OVERWRITE, /* op_lsh3_sti */ PAR_DEST_OVERWRITE | SET_FLAGS, /* op_mpyf3_stf */ PAR_DEST_OVERWRITE | SET_FLAGS | FLOAT_INSTR, /* op_mpyi3_sti */ PAR_DEST_OVERWRITE | SET_FLAGS, /* op_negf_stf */ PAR_DEST_OVERWRITE | SET_FLAGS | FLOAT_INSTR, /* op_negi_sti */ PAR_DEST_OVERWRITE | SET_FLAGS, /* op_not_sti */ PAR_DEST_OVERWRITE | SET_FLAGS, /* op_or3_sti */ PAR_DEST_OVERWRITE | SET_FLAGS, /* op_subf3_stf */ PAR_DEST_OVERWRITE | SET_FLAGS | FLOAT_INSTR, /* op_subi3_sti */ PAR_DEST_OVERWRITE | SET_FLAGS, /* op_xor3_sti */ PAR_DEST_OVERWRITE | SET_FLAGS, /* op_divs */ 0, /* op_divu */ 0,#ifdef ASM /* op_asm */ OP_ASM,#endif /* ASM */ /* op_line */ 0, /* op_label */ OP_LABEL, /* op_abort */ 0,};static OPCODE convert_op_to_op3[] = { /* op_absf */ (OPCODE) 0, /* op_absi */ (OPCODE) 0,#ifdef USE_ALL_OPCODES /* op_addc */ op_addc3,#endif /* USE_ALL_OPCODES */ /* op_addf */ op_addf3, /* op_addi */ op_addi3, /* op_and */ op_and3, /* op_andn */ op_andn3, /* op_ash */ op_ash3, /* op_cmpf */ (OPCODE) 0, /* op_cmpi */ (OPCODE) 0, /* op_fix */ (OPCODE) 0, /* op_float */ (OPCODE) 0,#ifdef USE_ALL_OPCODES /* op_idle */ (OPCODE) 0, /* op_lde */ (OPCODE) 0,#endif /* USE_ALL_OPCODES */ /* op_ldf */ (OPCODE) 0, /* op_popldf */ (OPCODE) 0,#ifdef USE_ALL_OPCODES /* op_ldfi */ (OPCODE) 0,#endif /* USE_ALL_OPCODES */ /* op_ldi */ (OPCODE) 0, /* op_popldi */ (OPCODE) 0,#ifdef USE_ALL_OPCODES /* op_ldii */ (OPCODE) 0, /* op_ldm */ (OPCODE) 0,#endif /* USE_ALL_OPCODES */ /* op_lsh */ op_lsh3, /* op_mpyf */ op_mpyf3, /* op_mpyi */ op_mpyi3,#ifdef USE_ALL_OPCODES /* op_negb */ (OPCODE) 0,#endif /* USE_ALL_OPCODES */ /* op_negf */ (OPCODE) 0, /* op_negi */ (OPCODE) 0, /* op_nop */ (OPCODE) 0,#ifdef USE_ALL_OPCODES /* op_norm */ (OPCODE) 0,#endif /* USE_ALL_OPCODES */ /* op_not */ (OPCODE) 0, /* op_pop */ (OPCODE) 0, /* op_popf */ (OPCODE) 0, /* op_push */ (OPCODE) 0, /* op_pushf */ (OPCODE) 0, /* op_pushnopeep */ (OPCODE) 0, /* op_pushfnopeep */ (OPCODE) 0, /* op_or */ op_or3,#ifdef USE_ALL_OPCODES /* op_rnd */ (OPCODE) 0, /* op_rol */ (OPCODE) 0, /* op_rolc */ (OPCODE) 0, /* op_ror */ (OPCODE) 0, /* op_rorc */ (OPCODE) 0,#endif /* USE_ALL_OPCODES */ /* op_rpts */ (OPCODE) 0, /* op_stf */ (OPCODE) 0,#ifdef USE_ALL_OPCODES /* op_stfi */ (OPCODE) 0,#endif /* USE_ALL_OPCODES */ /* op_sti */ (OPCODE) 0,#ifdef USE_ALL_OPCODES /* op_stii */ (OPCODE) 0, /* op_sigi */ (OPCODE) 0, /* op_subb */ op_subb3, /* op_subc */ (OPCODE) 0,#endif /* USE_ALL_OPCODES */ /* op_subf */ op_subf3, /* op_subi */ op_subi3,#ifdef USE_ALL_OPCODES /* op_subrb */ (OPCODE) 0,#endif /* USE_ALL_OPCODES */ /* op_subrf */ (OPCODE) 0, /* op_subri */ (OPCODE) 0, /* op_tstb */ (OPCODE) 0, /* op_xor */ op_xor3,#ifdef USE_ALL_OPCODES /* op_iack */ (OPCODE) 0#endif /* USE_ALL_OPCODES */};static CODE *peep_head = NIL_CODE;static CODE *next_ip;static int changes;#ifdef VERBOSEstatic struct{ int ldi_rx_rx; int ldf_rx_rx; int ldi_rx_ry_ldi_ry_rx; int ldf_rx_ry_ldf_ry_rx; int sti_rx_my_ldi_my_rx; int stf_rx_my_ldf_my_rx; int ldi_mx_ry_sti_ry_mx; int ldf_mx_ry_stf_ry_mx; int redundant_ldi; int redundant_ldf;#ifdef PEEP_REDUNDANT_STI int redundant_sti; int redundant_stf;#endif int commutative_i; int commutative_f; int ldi_opi_opi3; int ldf_opf_opf3; int opi_ldi_opi3; int opf_ldf_opf3; int par_ldf_stf; int par_stf_stf; int par_ldf_ldf; int par_ldi_sti; int par_sti_sti; int par_ldi_ldi; int convert_to_op3; int remap_register_fwd; int remap_register_bwd; int superfluous_load; int superfluous_tst; int superfluous_cmpf; int brd_cycles; int brd_memory; int brd_optimized; int br_to_next_line; int bxx_to_next_line; int bxx_to_ldcond; int bxx_over_br; int br_block_move; int br_branch_move; int br_commoned; int dead_code; int label_before_branch; int label_commoned; int label_removed;} PeepStatistic ={#ifdef PEEP_REDUNDANT_STI 0, 0,#endif /* PEEP_REDUNDANT_STI */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0#ifdef DEBUG}, LastPeepStatistic = {#ifdef PEEP_REDUNDANT_STI 0, 0,#endif /* PEEP_REDUNDANT_STI */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0#endif /* DEBUG */};static clock_t delay_time = 0;static clock_t tstb_time = 0;static clock_t pipe_time = 0;static clock_t paralel_time = 0;static clock_t remap_time = 0;static clock_t ldi_time = 0;static clock_t branch_time = 0;static clock_t cmpi_time = 0;static clock_t flow_time = 0;#endif /* VERBOSE */static int oldtot = 0;static int oldasm = 0;static int oldbranch = 0;static int oldreg = 0;static int newtot = 0;static int newasm = 0;static int newbranch = 0;static int newreg = 0;static PEEP_STAGES SelectedOptimizer = ENABLE_ALL;static int CurrentStage = 0;static unsigned peep_level = 0;/* * The following list is to find out, which sequence in optimizer is best * (Perhaps there isn't 'the best' but different goods, depending * on the code). */static PEEP_STAGES DefaultOptimizerStages[] = { REDUNDANT, REMAPP, COMMUTATIVE, COMBINE_BWD, COMBINE_FWD, DATAFLOW, REDUNDANT, REMAPP, COMMUTATIVE, COMBINE_BWD, COMBINE_FWD, ENABLE_ALL, 0};static PEEP_STAGES *OptimizerStages = &(DefaultOptimizerStages[0]);/* * table with the reverse condition for a given condition * opcodetables must be in same order as this table for correctness */static OPCODE revcond[] = { /* op_blo */ op_bhs, /* op_bls */ op_bhi, /* op_bhi */ op_bls, /* op_bhs */ op_blo, /* op_beq */ op_bne, /* op_bne */ op_beq, /* op_blt */ op_bge, /* op_ble */ op_bgt, /* op_bgt */ op_ble, /* op_bge */ op_blt, /* op_bz */ op_bnz, /* op_bnz */ op_bz, /* op_bp */ op_ble, /* op_bn */ op_bnn, /* op_bnn */ op_bn};static CODE *codeP_ ( (OPCODE, ITYPE, ADDRESS *, ADDRESS *, ADDRESS *, ADDRESS *, ADDRESS *, ADDRESS *));static void add_peep P_ ((CODE *));static void opt3 P_ ((unsigned));static void peep_delete P_ ((const CODE *));static void peep_line P_ ((CODE *));static void peep_label P_ ((CODE *));static void peep_uctran P_ ((const CODE *));static BOOL is_label_used P_ ((const ADDRESS *, LABEL));static BOOL is_restricted_indirect P_ ((const ADDRESS *));static BOOL is_memoryaccess_independent P_ ((const ADDRESS *, const ADDRESS *));#ifdef CHECK_LIST_INTEGRITYstatic void check_peep P_ ((void));#endif /* CHECK_LIST_INTEGRITY *//*****************************************************************************//* * Returns true if the <ea> is suitable for a 3op instruction. */static BOOL is_3op_possible P1 (const ADDRESS *, ap){ if (ap == NIL_ADDRESS) { return (FALSE); } switch (ap->mode) { case am_areg: case am_ireg: case am_dreg: case am_freg: case am_sreg: case am_ind: case am_const_ind: case am_indx2: case am_indxs: return (TRUE); case am_indx: case am_ainc: case am_adec: case am_preinc: case am_predec: if ((ap->u.offset->nodetype == en_icon) && (ap->u.offset->v.i >= -1) && (ap->u.offset->v.i <= 1)) { return (TRUE); } break; case am_immed: case am_direct: case am_const_direct: default: break; } return (FALSE);}#ifdef ASMstatic ADDRESS *mk_branchcomment P0 (void){ ADDRESS *ap; EXPR *ep; ep = mk_node (en_str, NIL_EXPR, NIL_EXPR, tp_void); ep->v.str = (const CHAR *) ";Branch occurs here"; ap = (ADDRESS *) xalloc ((size_t) sizeof (ADDRESS)); ap->mode = am_str; ap->u.offset = ep; return ap;}#endif /* ASM *//* * Find the end of a block of code. */static CODE *block_end P1 (CODE *, ip){ int count = 0; while (ip != NIL_CODE && ip->opcode != op_br && ip->opcode != op_bu && ip->opcode != op_retiu && ip->opcode != op_retsu) { if (count == BRANCH_COUNT) return NIL_CODE; if (branch (ip)) count++; ip = ip->fwd; } return ip;}/* * Find the node which contains the label 'lab'. */CODE *find_label P1 (LABEL, lab){ register CODE *ip; for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) { if (ip->opcode == op_label && ip->src1->u.offset->v.l == lab) return ip; } /* we should have found it */ return NIL_CODE;}/* * Returns false if the <ea> is not a label or else isn't equal to label. */static BOOL is_label_used P2 (const ADDRESS *, ap, LABEL, label){ return (ap != NIL_ADDRESS && ap->mode == am_immed && ap->u.offset->nodetype == en_labcon && ap->u.offset->v.l == label);}/* * Counts the number of times that a label node is referenced. */static int label_references P1 (const CODE *, ip){ CODE *target; struct swtab *sw; LABEL i; LABEL lab = ip->src1->u.offset->v.l; int count = 0; for (target = peep_head; target != NIL_CODE; target = target->fwd) { if ((target != ip) && (is_label_used (target->src1, lab) || is_label_used (target->dst, lab)))/* * src2, src21, src22, dst2 can never contain a label (in this Positions * only indirects and register are allowed) */ count++; } for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) { for (i = 0; i < sw->numlabs; i++) { if (sw->labels[i] == lab) count++; } } if (ip->back != NIL_CODE && ip->back->opcode == op_label) count++; if (ip->fwd != NIL_CODE && ip->fwd->opcode == op_label) count++; return count;}/* * Compare two address nodes and return true if they are equivalent. * a/pre-inc/dec are not treated as same */BOOL is_equal_address P2 (const ADDRESS *, ap1, const ADDRESS *, ap2){ if (ap1 == NIL_ADDRESS || ap2 == NIL_ADDRESS) return FALSE; if (ap1->mode != ap2->mode) return FALSE; switch (ap1->mode) { case am_areg: case am_dreg: case am_freg: case am_ireg: case am_sreg: case am_ind: case am_const_ind: return ap1->preg == ap2->preg; case am_indx: return ap1->preg == ap2->preg && is_equalnode (ap1->u.offset, ap2->u.offset); case am_indx2: case am_indxs: return ap1->preg == ap2->preg && ap1->sreg == ap2->sreg; case am_immed: case am_direct:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?