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

📄 flow68k.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
	    return reg;	}    }    return NO_REG;}/* * Produces a copy of an registerusage-list and returns a pointer to it */static REGENTRY **copy_regusage P1 (REGENTRY **, regusage){    REGENTRY **new_regusage;    REG     reg;    new_regusage = (REGENTRY **) xalloc (sizeof (REGENTRY *[MAX_REG + 1]));    for (reg = D0; reg <= MAX_REG; reg++) {	new_regusage[reg] = copy_regentry (regusage[reg]);    }    return new_regusage;}/* * Merges the largest common registerusage-set from dst and src  * into src * * Returns the number of changes which have been done. * Is needed for the multipass, we are looping through the code * until no more changes are done */static int merge_regusage P2 (REGENTRY **, dest, REGENTRY **, src){    REG     reg;    int     changes = 0;    for (reg = D0; reg <= MAX_REG; reg++) {	changes += merge_regentry (&(dest[reg]), src[reg]);    }    return changes;}/* * Removes all references to and from register reg */static void remove_regusage P2 (REGENTRY **, regusage, REG, reg){    REG     r;    if (reg != REG_MEMORY) {	regusage[reg] = NIL_REGENTRY;    }    for (r = D0; r <= MAX_REG; r++) {	remove_regentry (&(regusage[r]), reg);    }}/* * Removes all references to and from all temporary registers */static void clear_tempreg_usage P1 (REGENTRY **, regusage){    REG     reg;    for (reg = D0; reg <= MAX_REG; reg++) {	if (is_temporary_register (reg)) {	    regusage[reg] = NIL_REGENTRY;	    remove_regusage (regusage, reg);	}    }}/* * Attachs the Regusagelist to the Label which is the destination of * ip (ip must be jump or branch). * The usagelist of the label is corrected to the biggest common set * of regusage and the old list of the label. *  * Returns the number of changes which have been done. * Is needed for the multipass, we are looping through the code * until no more changes are done */static int attach_regusage_to_label P2 (REGENTRY **, regusage, CODE *, ip){    LABEL   label;    CODE   *target;    assert (ip->oper1->mode == am_direct);    label = ip->oper1->u.offset->v.l;    target = find_label (label);    assert (target != NIL_CODE);    if (target->oper2 == NIL_ADDRESS) {	target->oper2 = (ADDRESS *) copy_regusage (regusage);	return 1;    } else {	return merge_regusage ((REGENTRY **) target->oper2, regusage);    }}/*  * Merges the Regusage list from the Label ip (ip must be a label) * and the Regusage list (result is the largest 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 register usage * after a switch.  * * Returns the number 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 P2 (REGENTRY **, regusage, CODE *, ip){    LABEL   label;    SWITCH *sw;    BOOL    is_found = FALSE;    assert (ip->opcode == op_label);    label = ip->oper1->u.offset->v.l;    for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) {	LABEL   i;	for (i = 0; i < sw->numlabs; i++) {	    if (sw->labels[i] == label) {		is_found = TRUE;;	    }	}    }    if (is_found) {	clear_regusage (regusage);	if (ip->oper2 == NIL_ADDRESS) {	    ip->oper2 = (ADDRESS *) copy_regusage (regusage);	    return 1;	} else {	    clear_regusage (regusage);	    return merge_regusage ((REGENTRY **) ip->oper2, regusage);	}    } else {	if (ip->oper2 == NIL_ADDRESS) {	    ip->oper2 = (ADDRESS *) copy_regusage (regusage);	    return 1;	} else {	    int     count;	    count = merge_regusage ((REGENTRY **) ip->oper2, regusage);	    VOIDCAST merge_regusage (regusage, (REGENTRY **) ip->oper2);	    return count;	}    }}/*  * Copies the Regusage list from the label ip (ip must be a label) * to the Regusage list (old contents are overwritten). * If the label is referenced in an switch-table, an empty-list * is provided, since we dont know anything about register usage * after an switch.  */static void copy_regusage_from_label P2 (REGENTRY **, regusage, CODE *, ip){    LABEL   label;    SWITCH *sw;    BOOL    is_found = FALSE;    assert (ip->opcode == op_label);    label = ip->oper1->u.offset->v.l;    for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) {	LABEL   i;	for (i = 0; i < sw->numlabs; i++) {	    if (sw->labels[i] == label) {		is_found = TRUE;	    }	}    }    if (is_found) {	clear_regusage (regusage);	if (ip->oper2 == NIL_ADDRESS) {	    ip->oper2 = (ADDRESS *) copy_regusage (regusage);	} else {	    clear_regusage ((REGENTRY **) ip->oper2);	}    } else {	if (ip->oper2 == NIL_ADDRESS) {	    clear_regusage (regusage);	} else {	    REG     r;	    REGENTRY **p;	    REGENTRY **src = (REGENTRY **) ip->oper2;	    for (r = D0, p = regusage; r < MAX_REG; r++, p++) {		*p = copy_regentry (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 (REGENTRY **, regusage, CODE *, ip){    REGMAP *map;    REGBITMAP changed;    REGBITMAP current = 1;    REG     reg;    if (ip->opcode == op_label)	return;    map = build_regmap (ip);    changed = map->write | map->modified | map->updated;    for (reg = D0; reg <= MAX_REG; reg++) {	if ((changed & current) != 0) {	    remove_regusage (regusage, reg);	}	current <<= 1;    }    if ((changed & MEMBER (REG_MEMORY)) != 0) {	remove_regusage (regusage, REG_MEMORY);    }}/*****************************************************************************//* Is called if an amode could be exchanged with register reg; * that is if both contain the same value *  * We only do the replace if we think it is useful * * We replace following cases * *   Old               New *   Temporary D-Reg   D-Reg *   Temporary A-Reg   Not A-Reg  Reduces Pipelineconflicts *   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 (is_temporary_data_register (ap->preg) && (is_data_register (reg))) {	    /*	     * replace only if temporary	     */	    *apptr = mk_reg (reg);	    (*apptr)->mode = ap->mode;	    return TRUE;	}	break;    case am_areg:	if (!is_address_register (reg)	    || is_temporary_address_register (ap->preg)) {	    *apptr = mk_reg (reg);	    return TRUE;	}	break;    default:	*apptr = mk_reg (reg);	return TRUE;    }    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 P1 (CODE *, peep_head){    REGENTRY *regusage[MAX_REG + 1];    int     label_changes;    BOOL    is_headless;    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++));	label_changes = 0;	is_headless = FALSE;	clear_regusage (regusage);	for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) {	    validate_regusage (regusage, ip);	    switch (ip->opcode) {	    case op_move:	    case op_movea:	    case op_moveq:		new_regentry (regusage, ip->oper2, ip->oper1);		switch (ip->oper2->mode) {		case am_dreg:		case am_areg:		case am_freg:		    reg = ip->oper2->preg;		    regusage[reg] = add_regentry (regusage[reg], ip->oper1);#ifdef DEBUG		    DPRINTF ((DEBUG_FLOW, "ADD: "));		    if (is_debugging (DEBUG_FLOW)) {			print_regusage (reg, regusage);		    }#endif /* DEBUG */		    switch (ip->oper1->mode) {			REG     reg2;		    case am_dreg:		    case am_areg:		    case am_freg:			reg2 = ip->oper1->preg;			regusage[reg2] =			    add_regentries (regusage[reg], regusage[reg2]);#ifdef DEBUG			DPRINTF ((DEBUG_FLOW, "ADD: "));			if (is_debugging (DEBUG_FLOW)) {			    print_regusage (reg2, regusage);			}#endif /* DEBUG */			break;		    default:			break;		    }		    break;		default:		    break;		}		switch (ip->oper1->mode) {		case am_dreg:		case am_areg:		case am_freg:		    reg = ip->oper1->preg;		    regusage[reg] = add_regentry (regusage[reg], ip->oper2);#ifdef DEBUG		    DPRINTF ((DEBUG_FLOW, "ADD: "));		    if (is_debugging (DEBUG_FLOW)) {			print_regusage (reg, regusage);		    }#endif /* DEBUG */		    break;		default:		    break;		}		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:		label_changes += attach_regusage_to_label (regusage, ip);		break;	    case op_label:		if (is_headless) {		    copy_regusage_from_label (regusage, ip);		    is_headless = FALSE;		} else {		    label_changes += merge_regusage_from_label (regusage, ip);		}#ifdef DEBUG		DPRINTF (			 (DEBUG_FLOW, "LABEL: I_%d\n",			  ip->oper1->u.offset->v.l));		if (is_debugging (DEBUG_FLOW)) {		    print_regusages (regusage);		}#endif /* DEBUG */		break;	    case op_bra:		label_changes += attach_regusage_to_label (regusage, ip);		/* FALLTHRU */	    case op_rts:	    case op_rte:		clear_regusage (regusage);		is_headless = TRUE;		break;#ifdef ASM	    case op_asm:		clear_regusage (regusage);		break;#endif /* ASM */	    case op_jsr:		clear_tempreg_usage (regusage);		/*		 * we do not know what called routine does		 * with memory		 */		remove_regusage (regusage, REG_MEMORY);		/* FALLTHRU */	    default:		break;	    }	}	DPRINTF ((DEBUG_FLOW, " %d changes \n", label_changes));    } while (label_changes > 0);    DPRINTF ((DEBUG_FLOW, "%s\n", "Dataflow, REPLACEMENT ROUND"));    label_changes = 0;    is_headless = FALSE;    clear_regusage (regusage);    for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) {	/*	 * invalidate all entries with references to registers	 * modified in this instruction	 */	validate_regusage (regusage, ip);	switch (ip->opcode) {	case op_label:#ifdef DEBUG	    DPRINTF ((DEBUG_FLOW, "LABEL: I_%d\n", ip->oper1->u.offset->v.l));	    if (is_debugging (DEBUG_FLOW)) {		print_regusages (regusage);	    }#endif /* DEBUG */	    if (is_headless) {#ifdef DEBUG		DPRINTF ((DEBUG_FLOW, "Headless\n"));		if (is_debugging (DEBUG_FLOW) && ip->oper2 != NIL_ADDRESS) {		    print_regusages ((REGENTRY **) ip->oper2);		}#endif /* DEBUG */		copy_regusage_from_label (regusage, ip);		is_headless = FALSE;	    } else {		label_changes += merge_regusage_from_label (regusage, ip);	    }#ifdef DEBUG	    DPRINTF ((DEBUG_FLOW, "-----------\n"));	    if (is_debugging (DEBUG_FLOW)) {		print_regusages (regusage);	    }#endif /* DEBUG */	    break;	case op_bra:	    /* FALLTHRU */	case op_rts:	case op_rte:	    clear_regusage (regusage);	    is_headless = TRUE;	    break;#ifdef ASM	case op_asm:	    clear_regusage (regusage);	    break;#endif /* ASM */	case op_jsr:	    clear_tempreg_usage (regusage);	    /*	     * we do not know what the called routine does with memory	     */	    remove_regusage (regusage, REG_MEMORY);	    regusage[A7] = NIL_REGENTRY;	    /* FALLTHRU */	default:	    if (ip->oper1 != NIL_ADDRESS) {		reg = search_regusage (regusage, ip->oper1);		if (reg != NO_REG) {		    DPRINTF (			     (DEBUG_FLOW, "Found replacement for oper1 %d\n",			      (int) reg));		    if (is_exchangable (&(ip->oper1), reg)) {			replacecount++;			totreplace++;		    }		}	    }	    if ((ip->oper2 != NIL_ADDRESS) && (ip->oper2->mode == am_areg)) {		regusage[ip->oper2->preg] = NIL_REGENTRY;	    }	    break;	}#ifdef DEBUG	if (is_debugging (DEBUG_FLOW)) {	    print_regusages (regusage);	}#endif /* DEBUG */    }    DPRINTF (	     (DEBUG_FLOW, "Replaced %d Total %d\n", replacecount,	      totreplace));    return replacecount;}#endif /* MC680X0 */#endif /* PEEPFLOW */

⌨️ 快捷键说明

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