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

📄 cccreg.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 2 页
字号:
** This is the other helper routine for changereg().  It takes the
** same args as creg(), but it merely makes sure the register change
** will not change the given instruction before calling changereg()
** on the instruction before that one.
**
** This is mutually recursive with creg().
*/

static int
cregbefore(to, from, p, dguard, dstart)
PCODE *p, *dguard, *dstart;
{
    if (to == from) return 1;		/* already right */
#if 1
    if (uptolab && uptolab == jumplab(p))	/* Moving past boundary? */
	return crossfence(to, from, p,dguard,dstart);	/* Yeah, stop. */
#endif
    if ((from == R_RETVAL) && dropsout(p))	/* return uses AC1 */
	return 0;

    switch (p->Ptype & PTF_ADRMODE) {
    case PTA_REGIS:				/* careful of dblwords */
	if (p->Pop == P_POP) {		/* only mem change used as PTA_REGIS */
	    if (p->Pr2 == to) return 0;	/* conflict, lose */
	    else if (p->Pr2 == from) {	/* set of reg to change from */
		if (dguard != NULL) return 0; /* wrong reg val */
		p->Pr2 = to;		/* make it what we want */
		return 1;		/* win */
	    }
	}
	switch (rchange (p->Pop)) {
	case PRC_RSAME:	    case PRC_RSET:	case PRC_RCHG:
	case PRC_DSET_RSAME:   case PRC_DCHG_RSAME:
	    break;			/* mem is single word, normal case */

	case PRC_RCHG_DSAME:	case PRC_DSAME:
	case PRC_DSET:	    case PRC_DCHG: /* can't deal with doublewords */
	    if (p->Pr2 != from && p->Pr2 != from - 1 &&
		p->Pr2 != to && p->Pr2 != to - 1) break; /* safe, go on */
	default:			/* else fall through to loserville */
	    return 0;
	}				/* break falls into standard reg chk */

	if (p->Pr2 == to) return 0;	/* conflict, lose */
	if (p->Pr2 == from) {		/* need to change index */
	    if (!creg(to, from, before(p), dguard, dstart)) return 0;
	    p->Pr2 = to;		/* Change it */
	    return 1;			/* and return success */
	}
	break;				/* otherwise check prev instr */

    case PTA_MINDEXED:
    case PTA_BYTEPOINT:
	if (p->Pindex == to) return 0;	/* conflict, lose */
	if (p->Pindex == from) {	/* need to change index */
	    if (!creg(to, from, before(p), dguard, dstart)) return 0;
	    p->Pindex = to;		/* Change it */
	    return 1;			/* and return success */
	}
	break;				/* otherwise check prev instr */

    case PTA_RCONST:			/* no cared-about regs used */
    case PTA_ONEREG:
    case PTA_PCONST:
    case PTA_FCONST:
    case PTA_DCONST:
    case PTA_DCONST1:
    case PTA_DCONST2:
	break;			/* Don't need addr, just back up */

    default:
	int_error("cregbefore: bad Ptype");
	return 0;
    }
    p = before (p);			/* back up */
    return creg (to, from, p, dguard, dstart);	/* tail-recurse */
}

/*
** Change register for P_ADDI R,1
** Called by changereg() for PRC_RCHG when recursive change fails.
**
** We know that p->Preg == from, but little else.
*/

static int
craddhack(to, from, p)
PCODE *p;
{
    if (p->Ptype != PTV_IMMED || p->Pvalue != 1) return 0; /* pretest failed */
    switch (p->Pop) {			/* is opI R,1; see if P_ADDI or P_SUBI */
    case P_ADD:
	p->Pop = P_AOS;			/* P_ADDI R,1 */
	break;				/* becomes P_AOS S,R */

    case P_SUB:
	p->Pop = P_SOS;			/* similarly for P_SUBI */
	break;

    default:				/* something else */
	return 0;			/* we can't handle it */
    }

    /* Here if was P_ADDI R,1 or P_SUBI R,1.  Finish the transformation. */
    p->Ptype = PTA_REGIS;			/* make a reg-reg P_AOS */
    p->Preg = to;			/* into new register */
    p->Pr2 = from;			/* from old register */
    return 1;				/* return success */
}

/* Register information routines.
**	An instruction may do only ONE of these things to a specific register:
**	Name	R/W	Test	Action
**	-	0/0	~(R|W)	Nothing -- not used in any way
**	REF:	1/0	R & ~W	Reg value is used, but remains same.
**	SET:	0/1	~R & W	Reg is set; any old value is ignored.
**	MOD:	1/1	R & W	Reg value is used and modified.
**
** The following combined cases can be checked for:
**	USE: (REF+MOD)	R	Reg value is used; MAY be changed.
**	CHG: (SET+MOD)	W	Reg value is changed; old value MAY be used.
**	IN:  (all)	R | W	Reg is used or changed by instr.
**	-    (REF+SET)	R ^ W	Reg is read, or set, but not both.
*/
static int rvread, rvwrit;	/* Static for speed */

#if 0	/* 5/91 KCC size */
/*
** RBREF, RBSET, RBMOD, RBUSE, RBCHG
** RREF, RSET, RMOD, RUSE, RCHG
*/
int rbref(p) PCODE *p; { rvsset(p); return rvread & ~rvwrit; }
int rbset(p) PCODE *p; { rvsset(p); return rvwrit & ~rvread; }
int rbmod(p) PCODE *p; { rvsset(p); return rvread & rvwrit; }
int rbuse(p) PCODE *p; { rvsset(p); return rvread; }
int rbchg(p) PCODE *p; { rvsset(p); return rvwrit; }
int rbin (p) PCODE *p; { rvsset(p); return rvread | rvwrit; }
#endif

static void
rvsset(p)
PCODE *p;
{
    static int r;		/* Avoid stack fiddling, for speed */
    rvread = rvwrit = 0;

    /* First see how op deals with the Preg */
    switch (rchange(p->Pop)) {
	/* Single register */
	case PRC_RSAME:	rvread = rbits[p->Preg];	break;	/* Refed */
	case PRC_RSET_DSAME:
	case PRC_RSET:	rvwrit = rbits[p->Preg];	break;	/* Set */
	case PRC_RCHG_DSAME:
	case PRC_RCHG:	rvread = rvwrit = rbits[p->Preg];break;	/* Modified */

	/* Double register */
	case PRC_DSAME:	rvread = drbits[p->Preg]; break;	/* Refed */
	case PRC_DSET_RSAME:
	case PRC_DSET:	rvwrit = drbits[p->Preg]; break;	/* Set */
	case PRC_DCHG_RSAME:
	case PRC_DCHG:	rvread = rvwrit = drbits[p->Preg];break; /* Modified */

	case PRC_UNKNOWN:
	    if (p->Pop == P_PUSHJ) {		/* If PUSHJ, can do a little */
		rvread = rbits[p->Preg];	/* Refs the stack register */
		rvwrit = ~rvread;		/* Sets all but stack reg */
	    } else				/* If completely unknown, */
		rvread = rvwrit = ~0;		/* must assume everything! */
	    break;

	default:
	    int_error("rbitset: bad rchange");
    }

    /* Now see if reg is used in address or as memory operand. */
    switch (p->Ptype & PTF_ADRMODE) {
    case PTA_REGIS:			/* register to register */
	r = p->Pr2;			/* R used as E */
	if (p->Pop == P_DPB) {		/* Check special case of DPB x,R */
	    rvread |= rbits[r];		/* which doesn't change R */
	    return;
	}
	break;				/* Drop out to check for mem change */

    case PTA_MINDEXED:			/* addr+offset(index) */
    case PTA_BYTEPOINT:			/* [bsize,,addr+offset(index)] */
	if (p->Pindex)			/* R used as index reg? */
	    rvread |= rbits[p->Pindex];
	else if (!p->Pptr		/* No index, is R in E? */
	  && p->Poffset >= 0		/* Check for R used as E */
	  && p->Poffset < NREGS) {	/* (see rbinaddr() for more comment) */
	    r = (int) p->Poffset;
	    break;			/* Drop out to check for mem change */
	}
	return;

    default:
	int_error("rbitset: bad adrmode");
    case PTA_RCONST:		/* Simple integer in pvalue */
    case PTA_ONEREG:		/* no address, just register */
    case PTA_PCONST:		/* [<pointer of addr+offset+bsize>] */
    case PTA_FCONST:		/* [float] */
    case PTA_DCONST:		/* [double] */
    case PTA_DCONST1:
    case PTA_DCONST2:
	return;
    }

    /* If we come here, the instruction's memory operand was a register,
    ** identified by "r".
    ** Check further to see if this memory operand is changed or not.
    ** Currently we can't distinguish between setting and modifying.
    **
    ** Note that the only instr we use which can change two words in memory
    ** is DMOVEM (DMOVNM is not used).  We shouldn't ever see a DMOVEM r,E
    ** where E is a register address, but just in case, we check anyway.
    **
    ** One special case exists (DPB x,R) where the flag testing here is
    ** too general; this is caught by the PTA_REGIS check in previous switch.
    */
    switch (rchange(p->Pop)) {
	case PRC_RSET_DSAME:
	case PRC_RCHG_DSAME:
	case PRC_DSET:
	case PRC_DCHG:
	    rvread |= drbits[r];	/* Double-word mem read operand */
	    break;
	default:
	    rvread |= rbits[r];		/* Single-word mem read operand */
    }

    if ((popflg[p->Pop & POF_OPCODE] & PF_MEMCHG)	/* If op changes mem */
      || (p->Pop & POF_BOTH)) {				/* or BOTH flag set, */
	/* Register is munged as memory operand. */
	rvwrit |= ((p->Pop & POF_OPCODE) == P_DMOVEM) ? drbits[r] : rbits[r];
    }
}

/* Slightly faster versions of RBIN when not everything is needed
**
** RBINCODE(p)	Mask of registers used by this pcode instruction.
** RBINREG(p)	Mask of registers used as reg.
** RBINADDR(p)	Mask of registers used in addr.
*/
int
rbincode(p)
PCODE *p;
{	return rbinreg(p) | rbinaddr(p);
}

int
rbinreg(p)
PCODE *p;
{
    switch (rchange(p->Pop)) {
	case PRC_RSAME:	/* nice single word op? */
	case PRC_RSET:
	case PRC_RCHG:
	case PRC_RCHG_DSAME:
	    return rbits[p->Preg];

	case PRC_DSAME:	/* nasty double word op? */
	case PRC_DSET:
	case PRC_DCHG:
	case PRC_DSET_RSAME:
	case PRC_DCHG_RSAME:
	    return drbits[p->Preg];

	default:
	    int_error("rbinreg: bad rchange");
	    /* Drop thru */

	case PRC_UNKNOWN:		/* PUSHJ */
	    return -1;			/* Assume all regs affected! */
    }
}

/* RBINMEM - Internal rtn to get reg mask when R is used as E.
**	 See whether instruction uses double-word mem operand
*/
static int
rbinmem(p, r)
PCODE *p;
int r;
{
    switch (rchange(p->Pop)) {
	case PRC_RSAME:	/* nice single word op? */
	case PRC_RSET:
	case PRC_RCHG:
	case PRC_DSET_RSAME:
	case PRC_DCHG_RSAME:
	    return rbits[r];

	case PRC_RCHG_DSAME:
	case PRC_DSAME:
	case PRC_DSET:
	case PRC_DCHG:
	    return drbits[r];

	default:
	    int_error("rbinmem: bad rchange");
	    /* Drop thru */

	case PRC_UNKNOWN:		/* PUSHJ */
	    return -1;			/* Assume all regs affected! */
    }
}

int
rbinaddr(p)
register PCODE *p;
{
    switch (p->Ptype & PTF_ADRMODE) {
    case PTA_REGIS:			/* register to register */
	return rbinmem(p, p->Pr2);	/* R used as E */

    case PTA_MINDEXED:		/* addr+offset(index) */
    case PTA_BYTEPOINT:		/* [bsize,,addr+offset(index)] */
	if (p->Pindex)		/* R used as index reg? */
	    return rbits[p->Pindex];

	/* No index, check for R used as E.  This is illegal for PTA_MINDEXED
	** and should almost never be seen for PTA_BYTEPOINT.  The only
	** exception is when extracting a bitfield from a function-returned
	** structure -- see the code for Q_DOT in CCGEN2's gprimary().
	*/
	if (!p->Pptr		/* No index, is R in E? */
	  && p->Poffset >= 0	/* Check for R used as E (semi-illegal) */
	  && p->Poffset < NREGS)
	    return rbinmem(p, (int) p->Poffset);
	/* Drop thru to return 0 */

    case PTA_RCONST:		/* Simple integer in pvalue */
    case PTA_ONEREG:		/* no address, just register */
    case PTA_PCONST:		/* [<pointer of addr+offset+bsize>] */
    case PTA_FCONST:		/* [float] */
    case PTA_DCONST:		/* [double] */
    case PTA_DCONST1:
    case PTA_DCONST2:
	return 0;

    default:
	int_error("rbinaddr: bad adrmode");
	return -1;
    }
}

/* RRxxx(p, r) routines - same as RBxxx(p) but take a
**	register number in "r" and return TRUE if that register matches
**	one in the mask that RBxxx(p) would return.
*/
int rruse(p,r) PCODE *p; { rvsset(p); return (rvread) & rbits[r]; }
int rrchg(p,r) PCODE *p; { rvsset(p); return (rvwrit) & rbits[r]; }

#if 0	/* 5/91 KCC size */
int rrref(p,r) PCODE *p; { rvsset(p); return (rvread & ~rvwrit) & rbits[r]; }
int rrset(p,r) PCODE *p; { rvsset(p); return (rvwrit & ~rvread) & rbits[r]; }
int rrmod(p,r) PCODE *p; { rvsset(p); return (rvread & rvwrit) & rbits[r]; }
int rrin (p,r) PCODE *p; { rvsset(p); return (rvread | rvwrit) & rbits[r]; }
#endif

/* RINCODE(p, reg) - returns TRUE if register "reg" is used in any way
**	by the specified pseudo-op.
*/
rincode(p, reg)
PCODE *p;
int reg;
{
    return rinreg(p, reg) || rinaddr(p, reg);
}

/* RINADDR(p, reg) - returns TRUE if register "reg" is used in
**	the address of the specified pseudo-op.
*/
int
rinaddr(p, reg)
PCODE *p;
int reg;
{
    return rbinaddr(p) & rbits[reg];
}

/* RINREG(p, reg) - returns non-zero value if register "reg" is used as
**		a register by the specified pseudo-op.
** This value is:
**	0 - known not to be used.
**	1 - known used, single-word op.
**	2 - known used, double-word op.
**	3 - known used, as 2nd register of double-reg op.
**	4 - Assumed used, but not sure how.
**
**	Note that the default if the code can't figure something out
** is to assume the register WAS used.  Anything that calls rinreg must
** double-check the instruction before assuming that it is a simple thing
** like OP R,x.
*/
int
rinreg(p, reg)
PCODE *p;
int reg;
{
	switch (rchange(p->Pop)) {
	    case PRC_RSAME:	/* nice single word op? */
	    case PRC_RSET:
	    case PRC_RCHG:
	    case PRC_RCHG_DSAME:
		if (p->Preg == reg)		/* The one we want? */
		    return 1;			/* Say single-word op */
		break;

	    case PRC_DSAME:	/* nasty double word op? */
	    case PRC_DSET:
	    case PRC_DCHG:
	    case PRC_DSET_RSAME:
	    case PRC_DCHG_RSAME:
		if (p->Preg == reg)
		    return 2;		/* DOP R,x */
		if (p->Preg+1 == reg)
		    return 3;		/* DOP R-1, x */
		break;

	    default:
		int_error("rinreg: bad rchange");
	    case PRC_UNKNOWN:		/* PUSHJ */
		return 4;		/* Assume it was used, somehow. */
	}
    return 0;		/* Not used at all */
}

⌨️ 快捷键说明

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