peep68k.c
来自「一款拥有一定历史的C语言编译器」· C语言 代码 · 共 2,521 行 · 第 1/4 页
C
2,521 行
return; } if (next->opcode == op_label && label == next->oper1->u.offset->v.l) { ip->fwd->opcode = revcond[(int) ip->opcode - (int) op_beq]; peep_delete (ip); } }#if 0 /* Space optimisation: * if the code after the branch instruction is the same as the * instruction after the label the branch can be moved forward an * instruction provided it didn't affect the conditions on which the * branch is taken. */ target = find_label (label); /* now skip forward over identical instruction sequences */ while (is_same_instruction (ip->fwd, target->fwd) && is_flags_unchanged (ip, ip->fwd)) { /* switch order of instructions */ p = ip->fwd; ip->fwd = p->fwd; p->fwd->back = ip; p->fwd = ip; p->back = ip->back; p->back->fwd = p; ip->back = p; /* and delete redundant instruction */ peep_delete (target->fwd); } check_label (ip, target->back);#endif
/* delete branches to the following statement */
p = ip->fwd;
while (p != NIL_CODE && p->opcode == op_label) {
if (p->oper1->u.offset->v.l == label) {
peep_delete (ip);
return;
}
p = p->fwd;
}
}static void peep_ext P1 (const CODE *, ip){ CODE *next = ip->fwd; if (next == NIL_CODE) { return; } if (next->oper1 && next->oper1->mode == am_indx2 && next->oper1->sreg == ip->oper1->preg) { /* * convert EXT.L Dn => ??? 0(Am.Dn.W) * ??? 0(Am,Dn.L) */ next->oper1->mode = am_indx4; peep_delete (ip); return; } switch (next->opcode) { case op_movea: case op_adda: case op_suba: if ((ip->length == IL4) && ((next->oper2->mode == am_areg) && is_equal_oper (next->oper1, ip->oper1))) { /* * convert EXT.L Dn => MOVE.W Dn,An * MOVE.L Dn, An */ peep_delete (ip); next->length = IL2; } break; case op_asl: case op_asr: case op_rol: case op_ror: if (next->oper1->mode == am_dreg && is_equal_oper (next->oper1, ip->oper1)) peep_delete (ip); break; case op_clr: if (next->opcode == op_clr && next->fwd != NIL_CODE && next->fwd->opcode == op_tst && is_equal_oper (next->fwd->oper1, ip->oper1) && next->fwd->length == ip->length) { /* * convert EXT.L Dn => CLR.L Dm * CLR.L Dm EXT.L Dn * TST.L Dn */ next->fwd->opcode = op_ext; peep_delete (ip); } break; default: break; }}/* * For small shifts left, it can be more efficient to generate ADD * instructions. Although there is a small speed gain when the shift * is by 2 there is a space penalty ... we go for space not speed. */static void peep_shift P1 (CODE *, ip){ if (ip->oper1->mode != am_immed) { return; } if (ip->oper1->u.offset->v.i == (IVAL) 1) { /* * SHL #1, Dn => ADD Dn, Dn */ ip->opcode = op_add; ip->oper1 = copy_addr (ip->oper2, ip->oper2->mode); changes++; }}/* * if a label is followed by a branch to another label, the * branch statement can be deleted when the label is moved */static void peep_label P1 (CODE *, ip){ CODE *prev, *next, *target; SWITCH *sw; LABEL i, lab, label; if ((next = ip->fwd) == NIL_CODE) { return; } if (!optimize_option) { return; } lab = ip->oper1->u.offset->v.l; switch (next->opcode) { case op_label: /* if a label is followed by a label then common them up */ label = next->oper1->u.offset->v.l; for (target = peep_head; target != NIL_CODE; target = target->fwd) { if (is_label_used (target->oper1, label)) { target->oper1->u.offset->v.l = lab; } if (is_label_used (target->oper2, label)) { target->oper2->u.offset->v.l = lab; } } for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) { if (sw->beglab == label) { sw->beglab = lab; } for (i = (LABEL) 0; i < sw->numlabs; i++) { if (sw->labels[i] == label) { sw->labels[i] = lab; } } } peep_delete (next); break; case op_bra: prev = ip->back; /* * To make this fast, assume that the label number is really * next->oper1->u.offset->v.l */ label = next->oper1->u.offset->v.l; if (label == lab) { return; } target = find_label (label); if (target == NIL_CODE) { message (MSG_PEEPLABEL); return; } /* move label */ if (target->fwd == ip) { return; } peep_delete (ip); ip->fwd = target->fwd; ip->back = target; target->fwd = ip; if (ip->fwd != NIL_CODE) { ip->fwd->back = ip; } /* possibly remove branches */ /* in fact, prev is always != 0 if peep_delete has succeeded */ if (prev != NIL_CODE) { switch (prev->opcode) { case op_bra: case op_jmp: case op_rts: case op_rte: peep_uctran (prev); break; default: break; } } break; default: /* check that there are still references to this label */ if (label_references (ip) == 0) { peep_delete (ip); } break; }}/* delete branches to the following statement */static void peep_bra P1 (CODE *, ip){ CODE *p = ip->fwd; CODE *target; LABEL label = ip->oper1->u.offset->v.l; int count; /* delete branches to the following statement */ while (p != NIL_CODE && p->opcode == op_label) { if (p->oper1->u.offset->v.l == label) { peep_delete (ip); return; } p = p->fwd; } if (!optimize_option) { return; } target = find_label (label); /* we should have found it */ if (target == NIL_CODE) { FATAL ((__FILE__, "peep_bra", "target == 0"));
/* NOTREACHED */ } /* Space optimisation: * if the code before the target of the branch is itself a branch * then we can move the destination block of code to eliminate the branch */ p = target->back; if (p != NIL_CODE && ((p->opcode == op_bra) || (p->opcode == op_jmp) || (p->opcode == op_rts) || (p->opcode == op_rte))) { p = block_end (target); if (p != NIL_CODE && p != ip) { if (ip->fwd) { ip->fwd->back = p; } if (p->fwd) { p->fwd->back = target->back; } target->back->fwd = p->fwd; p->fwd = ip->fwd; target->back = ip; ip->fwd = target; peep_delete (ip); return; } } /* Space optimisation: * if the code before the branch instruction is the same as the * instruction before the label the branch can be moved back an * instruction. */ p = ip->back; previous_instruction (target); if (p == target) { return; } /* now skip back over identical instruction sequences */ while (is_same_instruction (p, target)) { p = p->back; previous_instruction (target); peep_delete (p->fwd); } check_label (ip, target); label = ip->oper1->u.offset->v.l; /* Space optimisation: * Optimise for the situation where two branches to the same * target label have identical instruction sequences * leading up to the branch. We can instead eliminate one * of these instruction sequences by branching to the other one. */ for (target = peep_head; target != NIL_CODE; target = target->fwd) { if ((target != ip) && (target->opcode == op_bra) && (target->oper1->u.offset->v.l == label)) { CODE *t = target; p = ip->back; previous_instruction (t); count = 0; while (is_same_instruction (p, t)) { p = p->back; previous_instruction (t); peep_delete (p->fwd); count++; } if (count != 0) { check_label (ip, t); break; } } } peep_uctran (ip);}static void peep_jmp P1 (CODE *, ip){ CODE *target; if (!optimize_option) { return; } /* * see if we can find a jmp just like this one - if so we shall branch * to it. This allows the tail end of the code for switch jump tables * to be commoned up. This is space optimisation! */ for (target = peep_head; target != NIL_CODE; target = target->fwd) { if ((target != ip) && (is_same_instruction (ip, target))) { ip->opcode = op_bra; ip->oper1 = mk_label ((LABEL) 0); /* label filled in by next line */ check_label (ip, target->back); } } peep_uctran (ip);}/* delete multiple debugging line statements */static void peep_line P1 (CODE *, ip){ CODE *ip2; if (ip->fwd == NIL_CODE) { return; } switch (ip->fwd->opcode) { case op_line: peep_delete (ip); break; case op_label: /* move the line number to after the label */ ip2 = ip->fwd; if (ip->back) { ip->back->fwd = ip2; } else { peep_head = ip2; } if (ip2->fwd) { ip2->fwd->back = ip; } ip2->back = ip->back; ip->fwd = ip2->fwd; ip2->fwd = ip; ip->back = ip2; break; default: break; }}/* * delete unnecessary stack frame creation */static void peep_link P1 (const CODE *, ip){ if (ip->fwd == NIL_CODE) { return; } if (ip->fwd->opcode == op_unlk && is_equal_oper (ip->oper1, ip->fwd->oper1)) { peep_delete (ip->fwd); peep_delete (ip); }}/* * peephole optimizer. This routine calls the instruction specific * optimization routines above for each instruction in the peep list. */static void opt3 P1 (unsigned, level){ CODE *ip; do { changes = 0; if (is_peep_phase (level, PEEP_INSTRUCTION)) { /* * Instruction specific optisations */ for (next_ip = peep_head; (ip = next_ip) != NIL_CODE; next_ip = ip->fwd) { switch (ip->opcode) { case op_move: case op_movea:#ifdef FLOAT_IEEE case op_fmove:#endif /* FLOAT_IEEE */ peep_move (ip); break; case op_movem:#ifdef FLOAT_IEEE case op_fmovem:#endif /* FLOAT_IEEE */ peep_movem (ip); break; case op_moveq: peep_moveq (ip); break; case op_pea: peep_pea (ip); break; case op_lea: peep_lea (ip); break; case op_add: case op_addq: case op_adda: peep_add (ip); break; case op_and: peep_and (ip); break; case op_or: peep_or (ip); break; case op_clr: peep_clr (ip); break; case op_sub: case op_suba: peep_sub (ip); break; case op_cmp: case op_cmpa: peep_cmp (ip); break; case op_tst: peep_tst (ip); break; case op_ext: peep_ext (ip); break; case op_asl: peep_shift (ip); break; case op_line: peep_line (ip); break; case op_link: peep_link (ip); break; default: break; } } } if (is_peep_phase (level, PEEP_JUMPS)) { /* * Flow control optimisations. */ for (next_ip = peep_head; (ip = next_ip) != NIL_CODE; next_ip = ip->fwd) { switch (ip->opcode) { case op_beq: case op_bne: case op_bgt: case op_bge: case op_blt: case op_bls: case op_blo: case op_bhi: case op_bhs: peep_bxx (ip); break; case op_rts: case op_rte: peep_uctran (ip); break; case op_label: peep_label (ip); break; case op_bra: peep_bra (ip); break; case op_jmp: peep_jmp (ip); break; default: break; } } }#ifdef PEEPFLOW if (is_peep_phase (level, PEEP_FLOW)) { changes += flow_dataflow (peep_head); }#endif /* PEEPFLOW */#ifdef VERBOSE if (verbose_option && changes) { message (MSG_PEEPCHANGES, changes); }#endif /* VERBOSE */ } while (changes);}#ifdef PEEPFLOW/* * builds the peepinfo of this instruction. */REGMAP *build_regmap P1 (CODE *, ip){ ADDRESS *src; ADDRESS *dst; REGMAP *map; if (ip->regmap == NULL) { ip->regmap = (REGMAP *) xalloc (sizeof (REGMAP)); } map = ip->regmap; map->write = 0; map->modified = 0; map->read = 0; map->used = 0; map->updated = 0; dst = ip->oper2; if (dst == NIL_ADDRESS) { /* one operand instruction */ dst = ip->oper1; src = NIL_ADDRESS; } else { /* two operand instruction */ src = ip->oper2; } if (src != NIL_ADDRESS) { switch (src->mode) { case am_dreg: case am_areg: case am_freg: map->read |= (1UL << (int) src->preg); break; case am_ainc: case am_adec: map->updated |= (1UL << (int) src->preg); map->read |= (1UL << REG_MEMORY); break; case am_indx2: map->used |= (1UL << (int) src->sreg); /*lint -fallthrough */ case am_ind: case am_indx: map->used |= (1UL << (int) src->preg); /*lint -fallthrough */ case am_direct: /*lint -fallthrough */ map->read |= (1UL << REG_MEMORY); break; default: break; } } if (dst != NIL_ADDRESS) { switch (dst->mode) { case am_dreg: case am_areg: case am_freg: map->modified |= (1UL << (int) dst->preg); break; case am_ainc: case am_adec: map->updated |= (1UL << (int) dst->preg); map->modified |= (1UL << REG_MEMORY); break; case am_indx2: map->used |= (1UL << (int) dst->sreg); /*lint -fallthrough */ case am_ind: case am_indx: map->used |= (1UL << (int) dst->preg); /*lint -fallthrough */ case am_direct: /*lint -fallthrough */ map->modified |= (1UL << REG_MEMORY); break; default: break; } } if (is_modify (ip->opcode)) { map->write = map->modified; map->modified = 0; } if (is_uses_sp (ip->opcode)) { map->updated |= (1UL << A7); } return map;}#endif /* PEEP_FLOW */#endif /* MC680X0 */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?