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

📄 flowc30.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
static int attach_regusage_to_label P3 (CODE *, ip, FLOWLISTENTRY **,					RegUsage, int, level){    LABEL   label;    CODE   *target;    unsigned i;    int     count;    SWITCH *sw;    SWITCH *table;    if (ip->opcode != op_bu) {	if (ip->src1->mode != am_immed) {	    return 0;	}	label = ip->src1->u.offset->v.l;	target = find_label (label);	if (target == NULL) {	    FATAL (		   (__FILE__, "attach_regusage_to_label",		    "target not found"));	}	if (target->src21 == NULL) {	    target->src21 = (ADDRESS *) copy_regusage (RegUsage);	    return 1;	} else {	    return merge_regusage ((FLOWLISTENTRY **) target->src21,				   RegUsage);	}    } else {	if (!is_peep_phase (level, PEEP_SWITCH)) {	    return 0;	}	/* look for the switchtable belonging to that op_bu */	table = NIL_SWITCH;	for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) {	    /* genc30 adds the labelname into the offsetfield of src1 */	    if (ip->src1->u.offset->v.l == sw->tablab) {		table = sw;		break;	    }	}	if (table != NIL_SWITCH) {	    count = 0;	    /* attach flowinfo to all labels */	    for (i = 0; i < table->numlabs; i++) {		label = table->labels[i];		target = find_label (label);		if (target == NULL) {		    FATAL (			   (__FILE__, "attach_regusage_to_label",			    "switch_target not found"));		}		if (target->src21 == NULL) {		    target->src21 = (ADDRESS *) copy_regusage (RegUsage);		    count++;		} else {		    count +=			merge_regusage ((FLOWLISTENTRY **) target->src21,					RegUsage);		}	    }	    return count;	} else {	    FATAL (		   (__FILE__, "attach_regusage_to_label",		    "switchtable for bu not found"));	    return 1;	}    }}/*  * Merges the Regusagelist from the Label ip (ip must be a label) * and the Regusage-List (result is the biggest common set of both * lists.) * Both Lists are overwritten with the newly generated common List  * If the label is Referenced in an switch-table, an empty-list * is provided, since we dont know anything about registerusage * after a switch.  * * Returns the amount of changes which have been done. * Is needed for the multipass, we are looping through the code * until no more changes have been done */static int merge_regusage_from_label P3 (CODE *, ip, FLOWLISTENTRY **,					 RegUsage, int, level){    LABEL   label;    SWITCH *sw;    int     found;    label = ip->src1->u.offset->v.l;    found = 0;    if (!is_peep_phase (level, PEEP_SWITCH)) {	for (sw = swtables; sw != (SWITCH *) NULL; sw = sw->next) {	    LABEL   i;	    for (i = 0; i < sw->numlabs; i++) {		if (sw->labels[i] == label) {		    found++;		}	    }	}    }    if (found != 0) {	clear_regusage (RegUsage);	if (ip->src21 == NULL) {	    ip->src21 = (ADDRESS *) copy_regusage (RegUsage);	    return 1;	} else {	    clear_regusage (RegUsage);	    return merge_regusage ((FLOWLISTENTRY **) ip->src21, RegUsage);	}    } else {	if (ip->src21 == NULL) {	    ip->src21 = (ADDRESS *) copy_regusage (RegUsage);	    return 1;	} else {	    found = merge_regusage ((FLOWLISTENTRY **) ip->src21, RegUsage);	    VOIDCAST merge_regusage (RegUsage, (FLOWLISTENTRY **) ip->src21);	    return found;	}    }}/*  * Copies the Regusagelist from the Label ip (ip must be a label) * to the Regusage-List (old contents are overwritten) * If the label is Refrenced in an switch-table, an empty-list * is provided, since we dont know anything about registerusage * after an switch.  */static void copy_regusage_from_label P3 (CODE *, ip, FLOWLISTENTRY **,					 RegUsage, int, level){    LABEL   label;    SWITCH *sw;    int     found;    FLOWLISTENTRY **p;    FLOWLISTENTRY **src;    label = ip->src1->u.offset->v.l;    found = 0;    if (!is_peep_phase (level, PEEP_SWITCH)) {	for (sw = swtables; sw != (SWITCH *) NULL; sw = sw->next) {	    LABEL   i;	    for (i = 0; i < sw->numlabs; i++) {		if (sw->labels[i] == label) {		    found++;		}	    }	}    }    if (found != 0) {	clear_regusage (RegUsage);	if (ip->src21 == NULL) {	    ip->src21 = (ADDRESS *) copy_regusage (RegUsage);	    return;	} else {	    clear_regusage ((FLOWLISTENTRY **) ip->src21);	    return;	}    } else {	if (ip->src21 == NULL) {	    clear_regusage (RegUsage);	    return;	} else {	    REG     r;	    src = (FLOWLISTENTRY **) ip->src21;	    for (r = REG_R0, p = RegUsage; r <= MAX_REG; r++, p++) {		*p = copy_flow_list (src[r]);	    }	}    }}/* * Invalidates (throws out) all references in registers and * to registers, which are changed by the instruction ip,  * including memory references */static void validate_regusage P2 (CODE *, ip, FLOWLISTENTRY **, RegUsage){#ifdef SAVE_PEEP_MEMORY    PEEPINFO StaticMemory;#endif /* SAVE_PEEP_MEMORY */    PEEPINFO *map;    REGBITMAP changed;    REGBITMAP current = 1;    REG     r;    map = GET_PEEP_INFO (ip, StaticMemory);    changed = map->write | map->modified | map->updated;    for (r = REG_R0; r <= MAX_REG; r++) {	if ((changed & current) != 0) {	    remove_from_regusage (RegUsage, r);	}	current <<= 1;    }    if ((changed & (1UL << REG_MEMORY)) != 0) {	remove_from_regusage (RegUsage, REG_MEMORY);    }}/* * Invalidates (throws out) all references in registers and * to registers, which are updated during addressgeneration of  * the instruction ip */#ifdef ENHANCED_FLOWstatic void validate_addressregusage P2 (CODE *, ip, FLOWLISTENTRY **,					 RegUsage){#ifdef SAVE_PEEP_MEMORY    PEEPINFO StaticMemory;#endif /* SAVE_PEEP_MEMORY */    PEEPINFO *map;    REGBITMAP changed;    REGBITMAP current = 1;    REG     r;    map = GET_PEEP_INFO (ip, StaticMemory);    changed = map->updated;    for (r = REG_R0; r <= MAX_REG; r++) {	if ((changed & current) != 0) {	    remove_from_regusage (RegUsage, r);	}	current <<= 1;    }}#endif/* Is called if an amode could be exchanged with register reg  * that is if both contain the same value *  * We do the replace only if we think it useful * We replace following cases * Old               New * Temporary D-Reg   D-Reg * Temporary A-Reg   Not A-Reg  Reduces Pipelincconflicts * Memory            Any Reg    Avoids Memory-access *                              frees busbandwith *  */static BOOL is_exchangable P2 (ADDRESS **, apptr, REG, reg){    ADDRESS *ap = *apptr;    switch (ap->mode) {    case am_dreg:    case am_freg:	if ((ap->preg <= MAX_DATA) && (is_data_register (reg))	    /* 	     * to avoid endless exchanges do replaces only higher 	     * registernumbers with lower registernumbers	     */	    && (reg < ap->preg)) {	    /*	     * replace only if temporary	     */	    *apptr = mk_reg (reg);	    (*apptr)->mode = ap->mode;	    DPRINTF ((DEBUG_FLOW, " and replaced\n"));	    return TRUE;	}	break;    case am_ireg:    case am_sreg:	break;    case am_areg:	if (((!is_address_register (reg)) || (ap->preg <= MAX_ADDR))	    /* 	     * to avoid endless exchanges do replaces only higher 	     * registernumbers with lower registernumbers	     */	    && ((reg < ap->preg) || (is_index_register (reg)))) {	    *apptr = mk_reg (reg);	    DPRINTF ((DEBUG_FLOW, " and replaced\n"));	    return TRUE;	}	break;    default:	*apptr = mk_reg (reg);	DPRINTF ((DEBUG_FLOW, " and replaced\n"));	return TRUE;    }    DPRINTF ((DEBUG_FLOW, " but not changed\n"));    return FALSE;}/* *  Examines dataflow and checks if data is already in a register *  when read-accesses to external ram occurs *  needs multiple-passes to work */int flow_dataflow P2 (CODE *, peep_head, int, level){    FLOWLISTENTRY *RegUsage[MAX_REG + 1];    int     LabelChanges;    BOOL    headless;		/* is true when currently no entrypoint for code was found 				 * (after a jump before the first label is found 				 */    REG     reg;    register CODE *ip;    int     replacecount = 0;    static int totreplace = 0;#ifdef DEBUG    int     Round = 1;#endif /* DEBUG */    do {	DPRINTF ((DEBUG_FLOW, "Dataflow, round %d...", Round++));	LabelChanges = 0;	/* currently no entrypoint found */	headless = FALSE;	/* clear all lists to start analysis */	clear_regusage (&(RegUsage[0]));	for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) {	    /*	     * invalidate all entries with references to registers	     * modified in this instruction	     */	    validate_regusage (ip, &(RegUsage[0]));	    switch (ip->opcode) {	    case op_ldi_ldi:	    case op_ldf_ldf:		/* destination now references to source */		new_flow_list (&(RegUsage[ip->dst2->preg]), ip->dst2->preg,			       ip->src21, ip->type);		if (is_am_register (ip->src21)) {		    /* dest references now to the same list of values as source */		    add_list_to_flow_list (&(RegUsage[ip->dst2->preg]),					   RegUsage[ip->src21->preg]);		    /* source refers now also to destination */		    add_flow_list (&(RegUsage[ip->src21->preg]),				   ip->src21->preg, ip->dst2, ip->type);		}		/*FALLTHRU */	    case op_ldi:	    case op_ldf:	    case op_ldiu:	    case op_ldfu:		/* destination now references to source */		new_flow_list (&(RegUsage[ip->dst->preg]), ip->dst->preg,			       ip->src1, ip->type);		if (is_am_register (ip->src1)) {		    /* dest references now to the same list of values as source */		    add_list_to_flow_list (&(RegUsage[ip->dst->preg]),					   RegUsage[ip->src1->preg]);		    /* source refers now also to destination */		    add_flow_list (&(RegUsage[ip->src1->preg]),				   ip->src1->preg, ip->dst, ip->type);		}		break;	    case op_ldi_sti:	    case op_ldf_stf:		/* destination now references to source */		new_flow_list (&(RegUsage[ip->dst->preg]), ip->dst->preg,			       ip->src1, ip->type);		if (is_am_register (ip->src1)) {		    /* dest references now to the same list of values as source */		    add_list_to_flow_list (&(RegUsage[ip->dst->preg]),					   RegUsage[ip->src1->preg]);		    /* source refers now also to destination */		    add_flow_list (&(RegUsage[ip->src1->preg]),				   ip->src1->preg, ip->dst, ip->type);		}		/* source of sti refers now also to destination */		add_flow_list (&(RegUsage[ip->src21->preg]), ip->src21->preg,			       ip->dst2, ip->type);		break;	    case op_sti_sti:	    case op_stf_stf:		/* source refers now also to destination */		add_flow_list (&(RegUsage[ip->src2->preg]), ip->src2->preg,			       ip->dst2, ip->type);		/*FALLTHRU */	    case op_sti:	    case op_stf:		/* source refers now also to destination */		add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg,			       ip->dst, ip->type);		break;	    case op_absf_stf:	    case op_absi_sti:	    case op_addf3_stf:	    case op_addi3_sti:	    case op_and3_sti:	    case op_ash3_sti:	    case op_fix_sti:	    case op_float_stf:	    case op_lsh3_sti:	    case op_mpyf3_stf:	    case op_mpyi3_sti:	    case op_negf_stf:	    case op_negi_sti:	    case op_not_sti:	    case op_or3_sti:	    case op_subf3_stf:	    case op_subi3_sti:	    case op_xor3_sti:		/* source of sti refers now also to destination */		add_flow_list (&(RegUsage[ip->src2->preg]), ip->src2->preg,			       ip->dst2, ip->type);		if ((ip->dst != NULL) && (is_am_register (ip->dst))) {		    /* destination of operation does not reference to anywhere now */		    RegUsage[ip->dst->preg] = NULL;		}		break;	    case op_blo:	    case op_bls:	    case op_bhi:	    case op_bhs:	    case op_beq:	    case op_bne:	    case op_blt:	    case op_ble:	    case op_bgt:	    case op_bge:	    case op_bz:	    case op_bnz:	    case op_bp:	    case op_bn:	    case op_bnn:		/* attach aktual registerusageinfo to label of jumpdestination */		LabelChanges +=		    attach_regusage_to_label (ip, &(RegUsage[0]), level);		break;	    case op_label:		if (headless == TRUE) {		    /* first entrypoint of this piece of code, so use whole information from label */		    copy_regusage_from_label (ip, &(RegUsage[0]), level);		    headless = FALSE;		} else {		    /* not first entrypoint, so merge information from label */		    LabelChanges +=			merge_regusage_from_label (ip, &(RegUsage[0]), level);		}		break;	    case op_bu:	    case op_br:		/* attach aktual registerusageinfo to label of jumpdestination */		LabelChanges +=		    attach_regusage_to_label (ip, &(RegUsage[0]), level);		/* FALLTHRU */	    case op_retsu:	    case op_retiu:		/* no information abaout registers availlable now */		clear_regusage (&(RegUsage[0]));		/* since no entrypoint found now (unconditional controltransfer) */		headless = TRUE;		break;	    case op_asm:		/* clear whole list, asm can do anything to registers and memory */		clear_regusage (&(RegUsage[0]));		break;	    case op_rpts:	    case op_rptb:		/* remove all references to and from blockrepeatregisters */		RegUsage[REG_RC] = NULL;		RegUsage[REG_RS] = NULL;		RegUsage[REG_RE] = NULL;		remove_from_regusage (RegUsage, REG_RC);		remove_from_regusage (RegUsage, REG_RS);		remove_from_regusage (RegUsage, REG_RE);		break;	    case op_call:	    case op_trapu:	    case op_xcall:	    case op_callu:		/* remove all references to and from temporary registers */		clear_tempreg_usage (&(RegUsage[0]));		/*		 * we do not know what called routine does

⌨️ 快捷键说明

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