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 + -
显示快捷键?