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

📄 flow68k.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 * *  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 MC680X0#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "gen68k.h"#include "outproto.h"/********************************************************* Macro Definitions *//*****************************************************************************/#ifdef DEBUG/* * generate a register name from a tempref number. */static void putreg P1 (REG, r){    switch (r) {    case D0:    case D1:    case D2:    case D3:    case D4:    case D5:    case D6:    case D7:	dprintf (DEBUG_FLOW, "d%d", (int) r);	break;    case A0:    case A1:    case A2:    case A3:    case A4:    case A5:    case A6:    case A7:	dprintf (DEBUG_FLOW, "a%d", (int) r - (int) A0);	break;    case FP0:    case FP1:    case FP2:    case FP3:    case FP4:    case FP5:    case FP6:    case FP7:	dprintf (DEBUG_FLOW, "fp%d", (int) r - (int) FP0);	break;    default:	CANNOT_REACH_HERE ();    }}/* * generate a register mask. */static void put_mask P1 (REGMASK, mask){    REG     reg;    BOOL    pending = FALSE;    for (reg = D0; reg <= FP7; reg++) {	if (mask & (REGMASK) 1) {	    if (pending) {		dprintf (DEBUG_FLOW, "/");	    }	    putreg (reg);	    pending = TRUE;	}	mask >>= 1;    }}/* * generate a register mask for save. */static void put_smask P1 (REGMASK, mask){    put_mask (mask);}/* * generate a register mask for restore. */static void put_rmask P1 (REGMASK, mask){    put_mask (mask);}/* * put a constant to the output file. */static void putconst P1 (const EXPR *, ep){    switch (ep->nodetype) {    case en_autocon:    case en_icon:	dprintf (DEBUG_FLOW, "%ld", ep->v.i);	break;#ifndef FLOAT_BOOTSTRAP#ifdef FLOAT_MFFP    case en_fcon:	dprintf (DEBUG_FLOW, "0x%lx", genffp (ep->v.f));	break;#endif /* FLOAT_MFFP */#endif /* FLOAT_BOOTSTRAP */    case en_labcon:	dprintf (DEBUG_FLOW, "I%u", (unsigned) ep->v.l);	break;    case en_nacon:	dprintf (DEBUG_FLOW, "%s", ep->v.str);	break;    case en_sym:	dprintf (DEBUG_FLOW, "%s", nameof (ep->v.sp));	break;    case en_add:	putconst (ep->v.p[0]);	dprintf (DEBUG_FLOW, "+");	putconst (ep->v.p[1]);	break;    case en_sub:	putconst (ep->v.p[0]);	dprintf (DEBUG_FLOW, "-");	putconst (ep->v.p[1]);	break;    case en_uminus:	dprintf (DEBUG_FLOW, "-");	/*FALLTHRU */    case en_cast:	putconst (ep->v.p[0]);	break;    case en_str:	dprintf (DEBUG_FLOW, "%s", ep->v.str);	break;    default:	FATAL (	       (__FILE__, "putconst", "illegal constant node %d",		ep->nodetype));	break;    }}/* * output a general addressing mode. */static void putamode P1 (const ADDRESS *, ap){    switch (ap->mode) {    case am_immed:	dprintf (DEBUG_FLOW, "#");	if (is_icon (ap->u.offset)) {	    dprintf (DEBUG_FLOW, "%ld", ap->u.offset->v.i);	    break;	}	/*FALLTHRU */    case am_direct:	putconst (ap->u.offset);	break;    case am_areg:	dprintf (DEBUG_FLOW, "a%d", (int) ap->preg - (int) A0);	break;    case am_dreg:	dprintf (DEBUG_FLOW, "d%d", (int) ap->preg);	break;    case am_ind:	dprintf (DEBUG_FLOW, "(a%d)", (int) ap->preg - (int) A0);	break;    case am_ainc:	dprintf (DEBUG_FLOW, "(a%d)+", (int) ap->preg - (int) A0);	break;    case am_adec:	dprintf (DEBUG_FLOW, "-(a%d)", (int) ap->preg - (int) A0);	break;    case am_indx:	/* allow 32-bit offsets */	putconst (ap->u.offset);	dprintf (DEBUG_FLOW, "(a%d)", (int) ap->preg - (int) A0);	break;    case am_indx2:	/* allow 32-bit offsets */	putconst (ap->u.offset);	dprintf (DEBUG_FLOW, "(a%d,d%d.%c)", (int) ap->preg - (int) A0,		 (int) ap->sreg, 'l');	break;    case am_indx3:	/* allow 32-bit offsets */	putconst (ap->u.offset);	dprintf (DEBUG_FLOW, "(a%d,a%d.l)", (int) ap->preg - (int) A0,		 (int) ap->sreg - (int) A0);	break;    case am_indx4:	/* allow 32-bit offsets */	putconst (ap->u.offset);	dprintf (DEBUG_FLOW, "(a%d,d%d.%c)", (int) ap->preg - (int) A0,		 (int) ap->sreg, 'w');	break;    case am_indxpc:	putconst (ap->u.offset);	dprintf (DEBUG_FLOW, "(pc)");	break;    case am_indx2pc:	putconst (ap->u.offset);	dprintf (DEBUG_FLOW, "(a%d,pc)", (int) ap->preg - (int) A0);	break;    case am_rmask:	put_rmask (ap->u.mask);	break;    case am_smask:	put_smask (ap->u.mask);	break;    case am_freg:	dprintf (DEBUG_FLOW, "fp%d", (int) ap->preg - (int) FP0);	break;    case am_line:    case am_str:	putconst (ap->u.offset);	break;    default:	CANNOT_REACH_HERE ();    }}/* *  To print out the regentry list into assembler-output *  Just to check if everything works as I thought */static void print_regentry P1 (REGENTRY *, rp){    int     seperator = ' ';    for (; rp != NIL_REGENTRY; rp = rp->next) {	dprintf (DEBUG_FLOW, "%c", seperator);	putamode (rp->ap);	seperator = ',';    }}/* * Print a single regusage */static void print_regusage P2 (REG, reg, REGENTRY **, regusage){    if (regusage[reg] != NIL_REGENTRY) {	putreg (reg);	dprintf (DEBUG_FLOW, ": ");	print_regentry (regusage[reg]);	dprintf (DEBUG_FLOW, "\n");    }}/* *  To print out the Regusages into assembler-output *  Just to check if everything works as I thought */static void print_regusages P1 (REGENTRY **, regusage){    REG     reg;    for (reg = D0; reg <= MAX_REG; reg++) {	print_regusage (reg, regusage);    }}#endif /* DEBUG *//*****************************************************************************//* * Create a REGENTRY and insert it before 'rp'. */static REGENTRY *mk_regentry P2 (ADDRESS *, ap, REGENTRY *, rp){    REGENTRY *new_rp;    new_rp = (REGENTRY *) xalloc (sizeof (REGENTRY));    new_rp->ap = ap;    new_rp->next = rp;    return new_rp;}/* * Searchs for the address 'ap' in the regentry 'rp' and * returns a pointer to it (or NIL_REGENTRY if not found) */static REGENTRY *search_regentry P2 (REGENTRY *, rp, ADDRESS *, ap){    for (; rp != NIL_REGENTRY; rp = rp->next) {	if (is_equal_address (rp->ap, ap)) {	    return rp;	}    }    return NIL_REGENTRY;}/* * Adds an entry for 'ap' in the list 'rp' if it is not already in * the list. */static REGENTRY *add_regentry P2 (REGENTRY *, rp, ADDRESS *, ap){    switch (ap->mode) {    case am_ainc:    case am_adec:	return rp;    default:	/*	 * check if equivalent entry is already in list	 */	if (search_regentry (rp, ap) == NIL_REGENTRY) {	    rp = mk_regentry (ap, rp);	}	break;    }    return rp;}/* * adds the regentry list 'rp2' to the regentry list 'rp1' and * returns the combined list. */static REGENTRY *add_regentries P2 (REGENTRY *, rp1, REGENTRY *, rp2){    for (; rp2 != NIL_REGENTRY; rp2 = rp2->next) {	rp1 = add_regentry (rp1, rp2->ap);    }    return rp1;}/* * Clears the ap-list of the register ap2->preg and adds the entry ap * if it is suitable (not if it refers to our own register) * * autoincrements are also not suitable as they never point * to the same value the next time */static void new_regentry P3 (REGENTRY **, regusage, ADDRESS *, ap2, ADDRESS *,			     ap){    REG     reg;    switch (ap2->mode) {    case am_dreg:    case am_areg:    case am_freg:	reg = ap2->preg;	break;    default:	return;    }    switch (ap->mode) {    case am_indx2:	if (ap->sreg == reg) {	    regusage[reg] = NIL_REGENTRY;	    return;	}	/*FALLTHRU */    case am_ind:    case am_indx:	if (ap->preg == reg) {	    regusage[reg] = NIL_REGENTRY;	    return;	}	break;    case am_ainc:    case am_adec:	regusage[reg] = NIL_REGENTRY;	return;    default:	break;    }    regusage[reg] = mk_regentry (ap, NIL_REGENTRY);}/*  * Generates a duplicate of the delivered regentry * and returns a pointer to it */static REGENTRY *copy_regentry P1 (REGENTRY *, rp){    REGENTRY *new_rp;    for (new_rp = NIL_REGENTRY; rp != NIL_REGENTRY; rp = rp->next) {	new_rp = mk_regentry (rp->ap, new_rp);    }    return new_rp;}/* * 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_regentry P2 (REGENTRY **, dest, REGENTRY *, src){    REGENTRY *last = NIL_REGENTRY;    REGENTRY *p;    int     changes = 0;    for (p = *dest; p != NIL_REGENTRY; p = p->next) {	if (search_regentry (src, p->ap) == NIL_REGENTRY) {	    changes++;	    if (last == NIL_REGENTRY) {		*dest = p->next;	    } else {		last->next = p->next;	    }	}	last = p;    }    return changes;}/* * removes all entries from dest-regentry which references * register reg in any way * REG_MEMORY is a pseudo-reg and means any memory-access */static void remove_regentry P2 (REGENTRY **, dest, REG, reg){    REGENTRY *last = NIL_REGENTRY;    REGENTRY *p;    if (reg == REG_MEMORY) {	for (p = *dest; p != NIL_REGENTRY; p = p->next) {	    if ((p->ap->mode == am_indx)		|| (p->ap->mode == am_ind)		|| (p->ap->mode == am_direct)		|| (p->ap->mode == am_ainc)		|| (p->ap->mode == am_adec)		|| (p->ap->mode == am_indx2)) {		if (last == NIL_REGENTRY) {		    *dest = p->next;		} else {		    last->next = p->next;		}	    }	    last = p;	}    } else {	for (p = *dest; p != NIL_REGENTRY; p = p->next) {	    if (is_register_used (reg, p->ap)) {		if (last == NIL_REGENTRY) {		    *dest = p->next;		} else {		    last->next = p->next;		}	    }	    last = p;	}    }}/*****************************************************************************//* * clears the whole regusage-list */static void clear_regusage P1 (REGENTRY **, regusage){    REG     reg;    for (reg = D0; reg <= MAX_REG; reg++) {	regusage[reg] = NIL_REGENTRY;    }}/* * Searches for any register already containing the value corresponding * to ap.  If a register is found it is returned, otherwise * NO_REG is returned */static REG search_regusage P2 (REGENTRY **, regusage, ADDRESS *, ap){    REG     reg;    for (reg = D0; reg <= MAX_REG; reg++) {	if (search_regentry (regusage[reg], ap) != NIL_REGENTRY) {

⌨️ 快捷键说明

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