⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 peeparm.c

📁 一款拥有一定历史的C语言编译器
💻 C
字号:
/* * C compiler * ========== * * Copyright 1989, 1990, 1991 Christoph van Wuellen. * Credits to Matthew Brandt. * All commercial rights reserved. * * This compiler may be redistributed as long there is no * commercial interest. The compiler must not be redistributed * without its full sources. This notice must stay intact. * * History: * * 1989   starting an 68000 C compiler, starting with material *		  originally by M. Brandt * 1990   68000 C compiler further bug fixes *		  started i386 port (December) * 1991   i386 port finished (January) *		  further corrections in the front end and in the 68000 *		  code generator. *		  The next port will be a SPARC port *//*****************************************************************************/#include "config.h"#ifdef ARM#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "genarm.h"#include "outproto.h"/*********************************************** Static Function Definitions */static CODE *find_label P_ ((LABEL));static BOOL uses_label P_ ((ADDRESS *, LABEL));static int label_references P_ ((CODE *));static void add_peep P_ ((CODE *));static void peep_uctran P_ ((CODE *));static void opt3 P_ ((unsigned));/********************************************************** Static Variables */static CODE *peep_head = NIL_CODE;static CODE *next_ip;static int changes;#if 0static CONDITION reverse_cc[] = {    cc_nv,			/* cc_al */    cc_cs,			/* cc_cc */    cc_cc,			/* cc_cs */    cc_ne,			/* cc_eq */    cc_lt,			/* cc_ge */    cc_le,			/* cc_gt */    cc_ls,			/* cc_hi */    cc_gt,			/* cc_le */    cc_hi,			/* cc_ls */    cc_ge,			/* cc_lt */    cc_pl,			/* cc_mi */    cc_eq,			/* cc_ne */    cc_al,			/* cc_nv */    cc_mi,			/* cc_pl */    cc_vs,			/* cc_vc */    cc_vc			/* cc_vs */};#endif/*****************************************************************************//* * generate a code sequence into the peep list. */void g_code P5 (OPCODE, op, CONDITION, cc, ADDRESS *, ap1, ADDRESS *, ap2,		ADDRESS *, ap3){    CODE   *ip;    ip = (CODE *) xalloc (sizeof (CODE));    ip->opcode = op;    ip->cc = cc;    ip->oper1 = ap1;    ip->oper2 = ap2;    ip->oper3 = ap3;    add_peep (ip);}/* * 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->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 the 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 (CODE *, ip){    if (ip == NIL_CODE) {	FATAL ((__FILE__, "peep_delete", ""));    }    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++;}/* * Returns false if the <ea> does is not a label or else isn't equal to label */static BOOL uses_label P2 (ADDRESS *, ap, LABEL, label){    return (ap != NIL_ADDRESS &&	    ap->mode == am_direct &&	    ap->offset->nodetype == en_labcon && ap->offset->v.l == label);}/* * find the node which contains the label 'lab' */static 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->oper1->offset->v.l == lab) {	    return ip;	}    }    /* we should have found it */    return NIL_CODE;}/* * counts the number of times that a label node is referenced */static int label_references P1 (CODE *, ip){    CODE   *target;    SWITCH *sw;    int     count = 0;    LABEL   i, lab = ip->oper1->offset->v.l;    for (target = peep_head; target != NIL_CODE; target = target->fwd) {	if ((target != ip) &&	    (uses_label (target->oper1, lab) ||	     uses_label (target->oper2, lab) ||	     uses_label (target->oper3, lab))) count++;    }    for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) {	for (i = (LABEL) 0; i < sw->numlabs; i++) {	    if (sw->labels[i] == lab) {		count++;	    }	}    }    return count;}/* * peephole optimization for unconditional transfers. deletes instructions * which have no path. applies to bra, jmp, and rts instructions. */static void peep_uctran P1 (CODE *, ip){    while (ip->fwd != NIL_CODE && ip->fwd->opcode != op_label)	peep_delete (ip->fwd);}/* * 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->offset->v.l;    switch (next->opcode) {    case op_label:	/* if a label is followed by a label then common them up */	label = next->oper1->offset->v.l;	for (target = peep_head; target != NIL_CODE; target = target->fwd) {	    if (uses_label (target->oper1, label)) {		target->oper1->offset->v.l = lab;	    }	    if (uses_label (target->oper2, label)) {		target->oper2->offset->v.l = lab;	    }	    if (uses_label (target->oper3, label)) {		target->oper3->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_b:	if (next->cc == cc_al) {	    prev = ip->back;	    /*	     * To make this fast, assume that the label number is really	     * next->oper1->offset->v.l	     */	    label = next->oper1->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) {		if (prev->opcode == op_b && prev->cc == cc_al) {		    peep_uctran (prev);		}	    }	    break;	}	/*FALLTHRU */    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;    LABEL   label = ip->oper1->offset->v.l;    /* delete branches to the following statement */    for (p = ip->fwd; p != NIL_CODE && p->opcode == op_label; p = p->fwd) {	if (p->oper1->offset->v.l == label) {	    peep_delete (ip);	    return;	}    }#if 0    p = ip->fwd;    if (ip->cc == reverse_cc[p->cc]) {	if (p->opcode == op_b) {	    p->cc = cc_al;	} else {	    /*	     * switch the branch with the following instruction	     */	    ip->back->fwd = p;	    p->fwd->back = ip;	    ip->fwd = p->fwd;	    p->back = ip->back;	    p->fwd = ip;	    ip->back = p;	    changes++;	}    }#endif}static void peep_mov P1 (CODE *, ip){    if (ip->oper1->mode == am_reg &&	ip->oper1->preg == R14 &&	ip->oper2->mode == am_reg && ip->oper2->preg == R15) {	peep_uctran (ip);    }}#if 0/* * The ARM allows instructions to be executed conditionally.  If the * distance between a branch and label is short enough then remove the * branch and make the intervening instruction to be executed conditionally. */static void peep_condition P1 (CODE *, ip){    CODE   *next;    for (next = ip->fwd; next != NIL_CODE; next = next->fwd) {	if (next->opcode == op_label) {	    break;	}	if (next->cc == reverse_cc[ip->cc]) {	    continue;	}	if (next->cc == cc_al) {	    next->cc = reverse_cc[ip->cc];	    continue;	}	break;    }}#endif/* * 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;    if (level == PEEP_NONE) {	return;    }    do {	changes = 0;	next_ip = peep_head;	while (next_ip != NIL_CODE) {	    ip = next_ip;	    next_ip = ip->fwd;	    switch (ip->opcode) {	    case op_label:		peep_label (ip);		break;	    case op_b:#if 0		peep_condition (ip);#endif		peep_bra (ip);		break;	    case op_mov:		peep_mov (ip);		break;	    default:		break;	    }	}#ifdef VERBOSE	if (verbose_option && changes) {	    message (MSG_PEEPCHANGES, changes);	}#endif /* VERBOSE */    } while (changes);}#endif /* ARM */

⌨️ 快捷键说明

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