peep68k.c

来自「一款拥有一定历史的C语言编译器」· C语言 代码 · 共 2,521 行 · 第 1/4 页

C
2,521
字号
    SWITCH *sw;
    if (ip == NIL_CODE)
	return FALSE;
    if (ip2 == NIL_CODE)
	return FALSE;
    for (ip2 = ip2->back; ip2 != NIL_CODE; ip2 = ip2->back) {	switch (ip2->opcode) {	case op_label:	    label = ip2->oper1->u.offset->v.l;	    /* first check code before the label */	    if (!was_move_redundant (ip, ip2, memory)) {		return FALSE;	    }	    /* ... and then check all branches to this label */	    for (ip2 = peep_head; ip2 != NIL_CODE; ip2 = ip2->fwd) {		switch (ip2->opcode) {		case op_beq:		case op_bne:		case op_bgt:		case op_bge:		case op_blt:		case op_ble:		case op_bls:		case op_blo:		case op_bhi:		case op_bhs:		case op_bra:		    if (is_label_used (ip2->oper1, label)) {			OPCODE  op = ip2->opcode;			ip2->opcode = op_nop;			if (!was_move_redundant (ip, ip2, memory)) {			    ip2->opcode = op;			    return FALSE;			}			ip2->opcode = op;		    }		    break;		default:		    break;		}	    }	    /* but if it is via a jump table we cannot determine it */	    for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) {		LABEL   lab;		for (lab = (LABEL) 0; lab < sw->numlabs; lab++) {		    if (sw->labels[lab] == label) {			return FALSE;		    }		}	    }	    return TRUE;	case op_rts:	case op_rte:	case op_jmp:	case op_bra:	    /* should have at least hit a label before here! */	case op_nop:	    return TRUE;	case op_jsr:	case op_bsr:	    return FALSE;#ifdef ASM	case op_asm:	    return FALSE;#endif /* ASM */	case op_line:	    break;	default:	    if (is_same_instruction (ip, ip2)) {		return TRUE;	    }	    altered = is_altered (ip2->opcode);	    overwritten = is_overwrite (ip2->opcode);	    if (ip2->oper2) {		/* two operand instruction */		if (is_equal_address (ip->oper1, ip2->oper2)) {		    if (overwritten && (ip->length <= ip2->length) &&			is_equal_address (ip->oper2, ip2->oper1))			return TRUE;		    if (altered) {			return FALSE;		    }		}		if (altered) {		    if (is_address_used (ip2->oper2, ip->oper1)) {			return FALSE;		    }		    if (is_address_used (ip2->oper2, ip->oper2)) {			return FALSE;		    }		}		if (is_address_changed (ip->oper1, ip2->oper2) ||		    is_address_changed (ip->oper2, ip2->oper2)) {		    return FALSE;		}		switch (ip2->oper2->mode) {		case am_dreg:		case am_areg:		case am_freg:		case am_mreg:		case am_direct:		case am_immed:		    if (altered && (is_equal_address (ip->oper2, ip2->oper2)				    || is_equal_address (ip->oper1,							 ip2->oper2))) {			return FALSE;		    }		    break;		case am_ainc:		case am_adec:		    if (is_equal_address (ip->oper2, ip2->oper2)) {			return FALSE;		    }		    /*lint -fallthrough */		case am_ind:		case am_indx:		    if (altered && memory) {			return FALSE;		    }		    break;		default:		    break;		}	    }	    if (ip2->oper1) {		if (is_address_changed (ip->oper1, ip2->oper1) ||		    is_address_changed (ip->oper2, ip2->oper1)) {		    return FALSE;		}		switch (ip2->oper1->mode) {		case am_dreg:		case am_areg:		case am_freg:		case am_mreg:		case am_direct:		case am_immed:		    if (ip2->oper2 != NIL_ADDRESS) {			break;		    }		    /* one operand instruction */		    if (altered && (is_equal_address (ip->oper2, ip2->oper1)				    || is_equal_address (ip->oper1,							 ip2->oper1))) return			    FALSE;		    break;		case am_ainc:		case am_adec:		    if (is_equal_address (ip->oper2, ip2->oper1)) {			return FALSE;		    }		    /*lint -fallthrough */		case am_ind:		case am_indx:		    if (ip2->oper2 != NIL_ADDRESS) {			break;		    }		    /* one operand instruction */		    if (altered && memory) {			return FALSE;		    }		    break;		default:		    break;		}	    }	    break;	}    }    return FALSE;}/* * Determine whether a move is redundant ... this is done by looking forward * along the code list (following all branches) to determine * whether the destination is required before being overwritten. */static BOOL is_move_redundant P3 (CODE *, ip, CODE *, ip2, BOOL, memory){    (void) ip;			/* KEE COMPILEr HAPPY UNTIL CODE READY */    (void) ip2;    (void) memory;#if 0				/* currently not fully working */    BOOL    result, altered, overwritten;    OPCODE  op;    for (ip2 = ip2->fwd; ip2 != NIL_CODE; ip2 = ip2->fwd) {	switch (ip2->opcode) {	case op_rts:	case op_rte:	case op_jmp:	    return FALSE;	case op_nop:	    return TRUE;	case op_bra:	    ip2->opcode = op_nop;	/* to prevent looping */	    result =		is_move_redundant (ip, find_label (ip2->oper1->u.offset->v.l),				   memory);	    ip2->opcode = op_bra;	    return result;	case op_beq:	case op_bne:	case op_bgt:	case op_bge:	case op_blt:	case op_ble:	case op_bls:	case op_blo:	case op_bhi:	case op_bhs:	    op = ip2->opcode;	    ip2->opcode = op_nop;	/* to prevent looping */	    result = is_move_redundant (ip, ip2, memory) &&		is_move_redundant (ip, find_label (ip2->oper1->u.offset->v.l),				   memory);	    ip2->opcode = op;	    return result;	case op_jsr:	case op_bsr:	    return FALSE;#ifdef ASM	case op_asm:	    return FALSE;#endif /* ASM */	case op_line:	    break;	default:	    if (is_same_instruction (ip, ip2)) {		return TRUE;	    }	    altered = is_altered (ip2->opcode);	    overwritten = is_overwrite (ip2->opcode);	    if (ip2->oper2) {		/* two operand instruction */		if (is_address_used (ip->oper2, ip2->oper1)) {		    return FALSE;		}		if (overwritten &&		    (ip->length <= ip2->length) &&		    is_equal_address (ip->oper2, ip2->oper2)) {		    return TRUE;		}		if (is_address_used (ip->oper2, ip2->oper2)) {		    return FALSE;		}		break;	    } else if (ip2->oper1) {		/* one operand instruction */		if (overwritten &&		    (ip->length <= ip2->length) &&		    is_equal_address (ip->oper2, ip2->oper1)) {		    return TRUE;		}		if (is_address_used (ip->oper2, ip2->oper1)) {		    return FALSE;		}	    }	    break;	}    }#endif    return FALSE;}/* *	  Look forward from the instruction 'ip' and see if the flags are *	  used before being reset. */static BOOL is_flag_used P1 (CODE *, ip){    BOOL    result;    if (ip == NIL_CODE) {	return FALSE;    }    for (ip = ip->fwd; ip; ip = ip->fwd) {	switch (ip->opcode) {	case op_bra:	    ip->opcode = op_nop;	/* to prevent looping */	    result = is_flag_used (find_label (ip->oper1->u.offset->v.l));	    ip->opcode = op_bra;	    return result;	case op_jsr:	case op_bsr:	case op_jmp:	case op_rts:	case op_rte:	case op_nop:	    return FALSE;	default:	    if (is_use_flags (ip->opcode)) {		return TRUE;	    }	    if (is_noset_flags (ip->opcode)) {		if (ip->oper2) {		    if (ip->oper2->mode == am_areg) {			break;		    }		} else if (ip->oper1) {		    if (ip->oper1->mode == am_areg) {			break;		    }		}	    }	    if (is_set_flags (ip->opcode)) {		return FALSE;	    }	    break;	}    }    return FALSE;}/* insert an instruction after the specified position in the code list */static void insert_code P5 (CODE *, target, OPCODE, op, ILEN, len, ADDRESS *,			    ap1, ADDRESS *, ap2){    CODE   *p;    p = code (op, len, ap1, ap2);    p->fwd = target->fwd;    p->back = target;    target->fwd = p->fwd->back = p;}/* ensure we have a label to branch to (create if needed) */static void check_label P2 (const CODE *, ip, CODE *, target){    if (target->fwd->opcode == op_label) {	ip->oper1->u.offset->v.l = target->fwd->oper1->u.offset->v.l;    } else {	insert_code (target, op_label, IL0, mk_label (nextlabel),		     NIL_ADDRESS);	ip->oper1->u.offset->v.l = nextlabel++;    }}static CODE *code P4 (OPCODE, op, ILEN, len, ADDRESS *, ap1, ADDRESS *, ap2){    CODE   *ip;    ip = (CODE *) xalloc (sizeof (CODE));    ip->opcode = op;    ip->length = len;    ip->oper1 = ap1;    ip->oper2 = ap2;#ifdef PEEPFLOW    ip->regmap = 0;#endif /* PEEPFLOW */    return ip;}/* * generate a code sequence into the peep list. */void g_code P4 (OPCODE, op, ILEN, len, ADDRESS *, ap1, ADDRESS *, ap2){    add_peep (code (op, len, ap1, ap2));}#ifdef FLOAT_IEEE/* * generate a floating point code sequence into the peep list. */void g_fcode P4 (OPCODE, op, ILEN, len, ADDRESS *, ap1, ADDRESS *, ap2){    if (ap1 != NIL_ADDRESS && ap1->mode == am_freg &&	(ap2 == NIL_ADDRESS || ap2->mode == am_freg)) {	len = IL12;    }    add_peep (code (op, (ILEN) (len + 1), ap1, ap2));}#endif /* FLOAT_IEEE *//* * add the instruction pointed to by new to the peep list. */static void add_peep P1 (CODE *, ip){    static CODE *peep_tail;    if (peep_head == NIL_CODE) {	peep_head = peep_tail = ip;	ip->fwd = NIL_CODE;	ip->back = NIL_CODE;    } else {	ip->fwd = NIL_CODE;	ip->back = peep_tail;	peep_tail->fwd = ip;	peep_tail = ip;    }}/* * output all code and labels in the peep list. */void flush_peep P1 (unsigned, level){    register CODE *ip;    SWITCH *sw;    EXPR   *ep2;    LABEL   i;    opt3 (level);		/* do the peephole optimizations */    for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) {	if (ip->opcode == op_label) {	    put_label (ip->oper1->u.offset->v.l);	} else {	    put_code (ip);	}    }    peep_head = NIL_CODE;    for (sw = swtables; sw; sw = sw->next) {	put_kseg (alignment_of_type (tp_pointer));	put_label (sw->tablab);	ep2 = mk_lcon (UNDEF_LABEL);#ifdef RELOC_BUG	/* generate the switch jump table as a series of 4-byte addresses */	for (i = 0; i < sw->numlabs; i++) {	    ep2->v.l = sw->labels[i];	    put_pointer (ep2);	}#else	/* generate the switch jump table as a series of 2-byte offsets	 * This limits the amount of code that can be generated in a	 * function to less then 32K.  I believe that this is a reasonable	 * restriction.	 */	{	    EXPR   *ep, *ep1;	    ep1 = mk_lcon (sw->beglab);	    ep = mk_node (en_sub, ep2, ep1, tp_void);	    for (i = (LABEL) 0; i < sw->numlabs; i++) {		ep2->v.l = sw->labels[i];		put_short (ep);	    }	}#endif /* RELOC_BUG */    }    swtables = NIL_SWITCH;}/* * delete an instruction referenced by ip */static void peep_delete P1 (const CODE *, ip){    if (ip == NIL_CODE) {	FATAL ((__FILE__, "peep_delete", ""));
	/* NOTREACHED */    }    if (ip->back == NIL_CODE) {	peep_head = ip->fwd;	if (ip->fwd) {	    ip->fwd->back = NIL_CODE;	}	next_ip = ip->fwd;    } else {	if ((ip->back->fwd = ip->fwd) != NIL_CODE) {	    ip->fwd->back = ip->back;	}	next_ip = ip->back;    }    changes++;}/* * changes LEA <ea>,An				  =>	   PEA <ea> *		   PEA (An) *	The value of An is not needed (An is scratch register) * CAVEAT code generator modifier! */static void peep_pea P1 (const CODE *, ip){    CODE   *prev;    if (ip->oper1->mode != am_ind) {	return;    }    if ((prev = ip->back) == NIL_CODE) {	return;    }    if (prev->opcode == op_lea && prev->oper2->preg == ip->oper1->preg	&& is_temporary_address_register (ip->oper1->preg)) {	prev->opcode = op_pea;	prev->oper2 = NIL_ADDRESS;	peep_delete (ip);    }}/* * peephole optimization for LEA instructions. */static void peep_lea P1 (CODE *, ip){    CODE   *next;    if (ip->oper1->mode == am_ind && ip->oper1->preg == ip->oper2->preg) {	/*	 *       LEA (An), An    deleted	 */	peep_delete (ip);	return;    }    if ((next = ip->fwd) == NIL_CODE) {	return;    }    if (next->opcode == op_movea &&	is_equal_address (ip->oper2, next->oper1) &&	next->oper2->mode == am_areg &&	is_temporary_register (next->oper1->preg)) {	/*	 *       LEA <ea>, An    =>      LEA <ea>, Am	 *       MOVEA.L An, Am	 */	ip->oper2 = next->oper2;	peep_delete (ip->fwd);    }    if (ip->oper2->preg == STACKPTR && is_dest_overwritten (ip->oper2, ip)) {	peep_delete (ip);	return;    }}/* * peephole optimization for MOVE instructions. */static void peep_move P1 (CODE *, ip){    CODE   *ip2;    EXPR   *ep;    /*     * move.w An,An changes the contents of An through sign extension     */    if (is_equal_address (ip->oper1, ip->oper2) &&	(ip->oper1->mode != am_areg || ip->length != IL2)) {	peep_delete (ip);	return;    }    switch (ip->oper1->mode) {    case am_immed:	ep = ip->oper1->u.offset;	if (ip->length == IL4) {	    /*	     * changes MOVE #n, -(A7) =>      PEA n	     *	     * unless n == 0	     */	    if (ip->oper2->mode == am_adec && ip->oper2->preg == STACKPTR &&		(ep->nodetype != en_icon || ep->v.i != 0L)) {		ip->opcode = op_pea;		ip->oper2 = NIL_ADDRESS;		ip->oper1 = copy_addr (ip->oper1, am_direct);		ip->length = IL0;		changes++;		return;	    }	    /*	     * changes MOVE #n, An    =>      LEA n, An	     */	    if (ip->oper2->mode == am_areg) {		ip->opcode = op_lea;		ip->oper1 = copy_addr (ip->oper1, am_direct);		ip->length = IL0;		changes++;		return;	    }	}	if (is_icon (ep)) {	    /*	     *      Replace move immediate An for the following cases	     *                      MOVE #0, An	     *                      MOVE #shortval, An	     *      by the sequences	     *                      SUB.L An,An	     *      and     MOVE.W #shortval, An	     */	    if (ip->oper2->mode == am_areg) {		if (ep->v.i == 0L) {		    ip->length = IL4;		    ip->opcode = op_sub;		    ip->oper1 = ip->oper2;		    changes++;		} else if ((IVAL) -32768L <= ep->v.i			   && ep->v.i <= (IVAL) 32767L) {		    ip->length = IL2;		}		return;	    }	    /*	     *                Replace moving small constants into a data register by	     *                      MOVEQ   #value,Dn	     */	    if (ip->oper2->mode == am_dreg) {		if ((IVAL) -128 <= ep->v.i && ep->v.i <= (IVAL) 127) {		    ip->opcode = op_moveq;		    ip->length = IL0;		    changes++;		    return;		}	    }	    /*	     *      Replace the sequence	     *                      MOVE.W #X, -(An)	     *                      MOVE.W #Y, -(An)	     *      by the sequence	     *                      MOVE.L #(X<<16|Y), -(An)	     */	    ip2 = ip->fwd;	    if (ip->length == IL2 &&		ip->oper2->mode == am_adec &&		ip2->length == IL2 &&		ip2->opcode == op_move &&		ip2->oper1->mode == am_immed &&		is_icon (ip2->oper1->u.offset) &&		ip2->oper2->mode == am_adec &&		ip2->oper2->preg == ip->oper2->preg) {		ip->length = IL4;		ep->v.u = (ep->v.u & (UVAL) 0xffffL) |

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?