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

📄 flowc30.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 * * 1995   Ivo Oesch, Started to build a codegenerator for the *        signalprocessor TMS320C30 (December) * *  Examines dataflow and checks if data is already in a register *  when read-accesses to external ram occurs *  needs multiple-passes to work *//*****************************************************************************/#include "config.h"#ifdef PEEPFLOW#ifdef TMS320C30#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "genc30.h"#include "outproto.h"/********************************************************* Macro Definitions */#define ENHANCED_FLOW/*****************************************************************************/#ifdef DEBUG/* *  To print out the Regusage into assembler-output *  Just to check if everything works as I thought */static void print_flowlist P1 (FLOWLISTENTRY *, list){    FLOWLISTENTRY *p;    for (p = list; p != NULL; p = p->next) {	putamode_tst (p->ap);#ifdef NO_MIX_WITH_FLOAT	if (p->type == OP_FLOAT) {	    dprintf (DEBUG_FLOW, " [F]; ");	} else {	    dprintf (DEBUG_FLOW, " [I]; ");	}#else	dprintf (DEBUG_FLOW, "; ");#endif    }}/* *  To to print out the Regusage into assembler-output *  Just to check if everything works as I thought */static void print_regusage P1 (FLOWLISTENTRY **, RegUsage){    REG     reg;    for (reg = REG_R0; reg <= MAX_REG; reg++) {	if (RegUsage[reg] != NULL) {	    putreg_tst (reg);	    dprintf (DEBUG_FLOW, ": ");	    print_flowlist (RegUsage[reg]);	    dprintf (DEBUG_FLOW, "\n");	}    }}#endif /* DEBUG *//* * Searchs the address 'ap' in the flowlist 'head' and and  * returns a pointer to it (or NULL if not found) */static FLOWLISTENTRY *search_flowlist_entry P3 (FLOWLISTENTRY *, head,						ADDRESS *, ap, ITYPE, type){    FLOWLISTENTRY *p;#ifdef NO_MIX_WITH_FLOAT    ITYPE   TypeOfThisList;    if (head != NULL) {	TypeOfThisList = head->type;    }#endif    for (p = head; p != NULL; p = p->next) {#ifdef NO_MIX_WITH_FLOAT	if (TypeOfThisList != p->type) {	    FATAL (		   (__FILE__, "search_flowlist_entry",		    "mixed int and float in list"));	}#endif	if (is_equal_address (p->ap, ap)) {#ifdef NO_MIX_WITH_FLOAT	    if (p->type == type) {		return p;	    }#else	    return p;#endif	}    }    return NULL;}/* * Adds the address 'ap' to the flowlist of register 'reg' in regusage * unsuitable 'ap's and double-entries are supressed  */static void add_flow_list P4 (FLOWLISTENTRY **, RegUsage, REG, reg, ADDRESS *,			      ap, ITYPE, type){    FLOWLISTENTRY *Entry;    ADDRESS *ap1;    IVAL    offset;    if ((ap->mode == am_ainc) || (ap->mode == am_adec)) {	/* ainc could be treated as am_indx with offset = -increment	 * in list, sinc addressregister points increment farther than	 * value was written	 * except it was stored with itself (arn, *arn++)	 */	if ((ap->preg == reg)	    || (ap->u.offset->nodetype != en_icon)) {	    return;	}	ap1 = copy_addr (ap, am_indx);	offset =	    (ap->mode == am_ainc) ? -ap->u.offset->v.i : ap->u.offset->v.i;	ap1->u.offset = mk_const ((long) offset);	ap = ap1;    }    if ((ap->mode == am_preinc) || (ap->mode == am_predec)) {	/* preinc could be treated as am_ind in list, sinc	 * addressregister points still to the same location	 * except it was stored with itself (arn, *++arn)	 */	if (ap->preg == reg) {	    return;	}	ap = copy_addr (ap, am_ind);    }    /*     * check if equivalent entry is already in list     */    if (search_flowlist_entry (*RegUsage, ap, type) == NULL) {	Entry = (FLOWLISTENTRY *) xalloc ((size_t) sizeof (FLOWLISTENTRY));	Entry->ap = ap;#ifdef NO_MIX_WITH_FLOAT	Entry->type = type;#endif	Entry->next = *RegUsage;	*RegUsage = Entry;    }}/* * adds the flowlist 'dest' to the flowlist '*regusage', double- * entries are supressed */static void add_list_to_flow_list P2 (FLOWLISTENTRY **, RegUsage,				      FLOWLISTENTRY *, src){    FLOWLISTENTRY *Entry;    FLOWLISTENTRY *p;    for (p = src; p != NULL; p = p->next) {	/*	 * check if equivalent entry is already in list	 */	if (search_flowlist_entry (*RegUsage, p->ap, p->type) == NULL) {	    Entry =		(FLOWLISTENTRY *) xalloc ((size_t) sizeof (FLOWLISTENTRY));	    Entry->ap = p->ap;#ifdef NO_MIX_WITH_FLOAT	    Entry->type = p->type;#endif	    Entry->next = *RegUsage;	    *RegUsage = Entry;	}    }}/* * clears the ap-list of the register reg and adds the entry ap * if it is suitable (not if it refers to our own register) * (ldi *ar2, ar2, ar2 is changed during the operation) * autoincrements are also not suitable, they never point * to the same value the next time */static void new_flow_list P4 (FLOWLISTENTRY **, RegUsage, REG, reg, ADDRESS *,			      ap, ITYPE, type){    FLOWLISTENTRY *Entry;    ADDRESS *ap1;    IVAL    offset;    switch (ap->mode) {    case am_indx2:    case am_indxs:	if (ap->sreg == reg) {	    *RegUsage = NULL;	    return;	}	/*FALLTHRU */    case am_ind:    case am_const_ind:    case am_indx:	if (ap->preg == reg) {	    *RegUsage = NULL;	    return;	}	break;    case am_preinc:    case am_predec:	/*	 * preinc could be treated as am_ind in list, sinc	 * addressregister points still to the same location	 * except it was loaded with itself (*++arn, arn)	 */	if (ap->preg == reg) {	    *RegUsage = NULL;	    return;	}	ap = copy_addr (ap, am_ind);	break;    case am_ainc:    case am_adec:	/*	 * ainc could be treated as am_indx with offset = -increment	 * in list, sinc addressregister points increment farther than	 * value was written	 * except it was loaded with itself (*arn++, arn)	 */	if ((ap->preg == reg)	    || (ap->u.offset->nodetype != en_icon)) {	    *RegUsage = NULL;	    return;	}	ap1 = copy_addr (ap, am_indx);	offset =	    (ap->mode == am_ainc) ? -ap->u.offset->v.i : ap->u.offset->v.i;	ap1->u.offset = mk_const (offset);	ap = ap1;	break;    default:	break;    }    Entry = (FLOWLISTENTRY *) xalloc ((size_t) sizeof (FLOWLISTENTRY));    Entry->ap = ap;#ifdef NO_MIX_WITH_FLOAT    Entry->type = type;#endif    Entry->next = NULL;    *RegUsage = Entry;}/*  * Generates a duplicate of the delivered flowlist * and returns a pointer to it */static FLOWLISTENTRY *copy_flow_list P1 (FLOWLISTENTRY *, List){    FLOWLISTENTRY *NewList = NULL;    FLOWLISTENTRY *Entry = NULL;    FLOWLISTENTRY *p;    for (p = List; p != NULL; p = p->next) {	Entry = (FLOWLISTENTRY *) xalloc ((size_t) sizeof (FLOWLISTENTRY));	Entry->ap = p->ap;#ifdef NO_MIX_WITH_FLOAT	Entry->type = p->type;#endif	Entry->next = NewList;	NewList = Entry;    }    return NewList;}/* * Only entries contained in both lists are delivered back in dest * (the biggest common set is returned in dest) * * Returns the amount 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_flow_list P2 (FLOWLISTENTRY **, dest, FLOWLISTENTRY *, src){    FLOWLISTENTRY *Last = NULL;    FLOWLISTENTRY *p;    int     changes = 0;    for (p = *dest; p != NULL; p = p->next) {	if (search_flowlist_entry (src, p->ap, p->type) == NULL) {	    changes++;	    if (Last == NULL) {		*dest = p->next;	    } else {		Last->next = p->next;	    }	}	Last = p;    }    return changes;}/* * removes all entries from dest-flowlist which references * register reg in any way * REG_MEMORY is a pseudo-reg and means any memory-access */static void remove_from_flowlist P2 (FLOWLISTENTRY **, dest, REG, reg){    FLOWLISTENTRY *Last = NULL;    FLOWLISTENTRY *p;    if (reg == REG_MEMORY) {	for (p = *dest; p != NULL; p = p->next) {	    if ((p->ap->mode == am_indx)		|| (p->ap->mode == am_ind)		/* || (p->ap->mode == am_const_ind) */		|| (p->ap->mode == am_direct)		/* || (p->ap->mode == am_const_direct) */		|| (p->ap->mode == am_ainc)		|| (p->ap->mode == am_adec)		|| (p->ap->mode == am_preinc)		|| (p->ap->mode == am_predec)		|| (p->ap->mode == am_indx2)		|| (p->ap->mode == am_indxs)) {		if (Last == NULL) {		    *dest = p->next;		} else {		    Last->next = p->next;		}	    }	    Last = p;	}    } else {	for (p = *dest; p != NULL; p = p->next) {	    if (is_register_used (reg, p->ap)) {		if (Last == NULL) {		    *dest = p->next;		} else {		    Last->next = p->next;		}	    }	    Last = p;	}    }}/* * clears the whole regusage-list */static void clear_regusage P1 (FLOWLISTENTRY **, RegUsage){    REG     reg;    for (reg = REG_R0; reg <= MAX_REG; reg++) {	RegUsage[reg] = NULL;    }}/* * Searchs if any register already contains the value corresponding * to ap. if a register is found, its number is returned, otherewise * -1 is returnned */static REG search_in_regusage P3 (FLOWLISTENTRY **, RegUsage, ADDRESS *, ap,				  ITYPE, type){    REG     reg;    for (reg = REG_R0; reg <= MAX_REG; reg++) {	if (search_flowlist_entry (RegUsage[reg], ap, type) != NULL) {	    return reg;	}    }    return NO_REG;}/* * Produces a copy of an registerusage-list and returns a pointer to it */static FLOWLISTENTRY **copy_regusage P1 (FLOWLISTENTRY **, RegUsage){    FLOWLISTENTRY **NewRegUsage;    FLOWLISTENTRY **p;    REG     reg;    NewRegUsage = (FLOWLISTENTRY **) xalloc ((size_t)					     sizeof (FLOWLISTENTRY *						     [MAX_REG + 1]));    for (reg = REG_R0, p = NewRegUsage; reg <= MAX_REG; reg++, p++) {	*p = copy_flow_list (RegUsage[reg]);    }    return NewRegUsage;}/* * Merges the biggest common registerusage-set from dst and src  * into src * * Returns the amount 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 (FLOWLISTENTRY **, dest, FLOWLISTENTRY **, src){    REG     reg;    int     changes = 0;    for (reg = REG_R0; reg <= MAX_REG; reg++) {	changes += merge_flow_list (&(dest[reg]), src[reg]);    }    return changes;}/* * Removes all references to and from register reg */static void remove_from_regusage P2 (FLOWLISTENTRY **, RegUsage, REG, reg){    REG     r;    if (reg != REG_MEMORY) {	RegUsage[reg] = NULL;    }    for (r = REG_R0; r <= MAX_REG; r++) {	remove_from_flowlist (&(RegUsage[r]), reg);    }}/* * Removes all references to and from all temporary registers */static void clear_tempreg_usage P1 (FLOWLISTENTRY **, RegUsage){    REG     reg;    for (reg = REG_R0; reg <= MAX_DATA; reg++) {	RegUsage[reg] = NULL;	remove_from_regusage (RegUsage, reg);    }    for (reg = REG_AR0; reg <= MAX_ADDR; reg++) {	RegUsage[reg] = NULL;	remove_from_regusage (RegUsage, reg);    }}/* * Attachs the Regusagelist to the Label which is 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 amount of changes which have been done. * Is needed for the multipass, we are looping through the code * until no more changes are done */

⌨️ 快捷键说明

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