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

📄 cccode.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:

	    if (op == P_SUB)		/* If new instr is SUB, */
		p->Pop ^= (P_ADD ^ P_SUB);	/* invert sense of old instr */

	    p->Preg = r;		/* Make ADD/SUB S,x be ADD/SUB R,x */
	    codrrx(before(p), np);	/* Continue optimization if can */
	    return 1;


	case P_SETZ+POF_BOTH:
	case P_SETO+POF_BOTH:
	    if (p->Ptype == PTA_REGIS
	      && (op == P_DMOVE || op == P_DMOVN)
	      && p->Preg == s && p->Pr2 == s + 1)
		{

	    /*
	    ** fold:  SETZB/SETOB S,S+1
	    **		...
	    **        DMOVE R,S
	    **
	    ** into:  SETZB R,R+1
	    */
		np->Pop = p->Pop;		/* Copy the SETZB/SETOB */
		np->Pr2 = np->Preg + 1;
		dropinstr(p);			/* Flush the SETZB/SETOB */
		return 1;
		}
	    break;
	}		/* end switch (p->Pop&(POF_OPCODE|POF_BOTH)) */

    return 0;		/* No optimization done, let caller handle it. */
}

/* RRPRE3 - (yet another) Auxiliary for RRPRE2 (auxiliary for CODE00).
**	Handles case where previous instruction was a "data fetch"
** into register and new instruction operates on that register.
**	 Turn:	p->   MOVE/MOVEI/DMOVE/HRRZ/HLRZ S,x
**		      ...
**		np->  OPN R,S
**	 into:
**		      OP    R,x
**
** If there are instructions in between (i.e. "..." contains something) then
** we need to be careful that:
**	(1) S is NOT otherwise referenced between the MOVE and the OP.
**		This rule has already been satisfied by findrset().
**	(2) OP is not a skip, and R is NOT referenced in "..."
**		If so, then OK to fold: the MOVE to OP R,X.
**	Otherwise, (3) X doesn't use anything that "..." changes.
**		If so, we can flush the MOVE and add the OP R,X.
**	Otherwise give up.
**
** Note that the OP of a munged instruction may differ from the OPN
** originally pointed to by "np".  This is so the halfword code can
** provide the correct op.  For most calls, the "op" arg will just be
** "np->Pop".
*/
static void
rrpre3(p, np, op)
PCODE *p, *np;
int op;			/* Actual OP to use if a change is made */
{
    PCODE *q;
    INT stkoff;


    /* don't make an XPUSHI - foldstack works better without it */
    if (p->Ptype == PTV_IINDEXED && op == P_PUSH)
	{
	rrpop2(np);		/* Just do simple post-ops */
	return;
	}

    /* Ensure the two instructions are handling the same registers.
    ** If one is a doubleword op and the other isn't then they might not.
    ** e.g. the sequence MOVE S,x / SETZ S+1, / DFAD R,S
    */
    if (rbinreg(p) != rbinaddr(np))	/* Verify p's S == np's S */
	{
	rrpop2(np);			/* Oops, just do simple post-ops */
	return;
	}

    /* If there's nothing in between, then no need to worry about rules.
    ** Otherwise, check for rule (2).
    */
    q = before(np);

    if (Register_Preserve (p->Preg) || Register_Preserve(np->Pr2))
	return;			/* avoid faulty opt */

    if ( p == q			/* Always OK if no "..." in between */
      || (!isskip(np->Pop)		/* Otherwise must not be skip */
	 && !chkref(p, q, np->Preg)))	/* and "..." must not reference R. */
	{
	p->Pop = op;			/* Win!!  fold: MOVE S,X */
	p->Preg = np->Preg;		/* to OP R,X */
	dropinstr(np);			/* Flush new instr */
	rrpopt(p);			/* Do more checks on result! */
	return;
	}

    /* Checking for R usage didn't work out.
    ** Now apply painful check of X by going forwards from
    ** the MOVE, checking each instr to make sure it cannot reference
    ** X or use a register that X does.
    */
    if (chkmref(p, np, (INT *) &stkoff) == NULL)
	{
	/* WON!  Zap the MOVE and turn new op into OP R,X */
	int r = np->Preg;	/* Save R */
	*np = *p;		/* Copy MOVE into added instr */
	p->Pop = P_NOP;		/* Then zap the MOVE */
	np->Pop = op;		/* fold: MOVE S,X */
	np->Preg = r;		/* to OP R,X */
	if (stkoff)		/* If stack indexed through and it changed, */
	    np->Poffset -= stkoff;	/* adjust offset of instruction. */
	rrpopt(np);		/* Do post-optimization checks now! */
	return;
	}
    rrpop2(np);			/* Failed, apply standard post-opts. */
}

/* CHKREF(p, q, reg) - Checks series of instrs to see if any reference
**	the specified register.
**	Searches backwards from q (INCLUSIVE) to p (EXCLUSIVE).
**	Returns non-NULL pointer to most recent reference found.
**	Returns NULL if no reference seen.
*/
static PCODE *
chkref(begp, q, r)
PCODE *begp, *q;
int r;
{
    for (; q && begp != q; q = before(q))
	{
#if 0
	if (rincode(q, r))
#else
	    /*
	     * FW, 22-Mar-93 (SPR 41)
	     *
	     * This function needs to interpret transfers of control
	     * as "references" to the register, because we must
	     * assume that the code jumped to may use the register's
	     * contents.  Therefore, we will break on any of PUSHJ,
	     * POPJ, JUMPn, or JRST.
	     */

	int	    opcode = q->Pop & POF_OPCODE;

	if (rincode (q, r) || opcode == P_PUSHJ || opcode == P_POPJ
		|| opcode == P_JUMP || opcode == P_JRST)
#endif
	    return q;		/* Quit loop if find a reference */
	}
    return NULL;
}

/* CHKMREF - Check an instr sequence for anything affecting a mem ref.
**	BEGP points to start (INCLUSIVE), the instr here defines X.
**	ENDP points to end (EXCLUSIVE)
** Returns pointer to offending instr if any ref found.
**
**	Applies painful check of X (for OP R,X) by going forwards from
** the begp (inclusive), checking each instr to make sure it cannot reference
** X or use a register that X does, since we want to move the X reference
** from the instr at begp to the instr at endp.
**	This involves three distinct checks:
**	(1) If the original instr at begp modifies memory, then this
**		is considered a conflicting reference and we fail, since
**		the instr at endp probably depends on the new value.
**	(2) If X uses a register, that register must not be changed
**		by an intervening instruction!
**	(3) If an intervening instruction references the same place
**		as X (or even threatens to do so), then it must not change
**		memory.
 *
 *	(4) FW, 22-Mar-93: If an intervening instruction jumps, we
 *		must assume that the code jumped to depends on the
 *		value.
 * 
** Must track stack offset both in order to properly check for sameaddr(),
** and to correct the X if it uses the stack (and something in "..."
** changed stack ptr).
**
**	If X depends on stack pointer value, the returned
** offset will be nonzero and X needs it added to its Poffset if it is
** to be used in the instruction at ENDP.
**	If at any point the stack offset changes in a way that means X
** would become non-existent (not on the stack, i.e. a positive stack
** offset) then the routine fails immediately.
*/

PCODE *
chkmref (PCODE *begp, PCODE *endp, INT *aoff)
    {
    PCODE *q;
    INT ioff;
    INT stkoff = 0;
    int xreg = -1;		/* Default assumes X uses no reg */

    *aoff = 0;

    if ((begp->Pop & POF_BOTH) || (popflg[begp->Pop & POF_OPCODE] & PF_MEMCHG))
	return begp;		/* Start instr changes mem! Fail. */

    switch (begp->Ptype & PTF_ADRMODE)
	{
	case PTA_BYTEPOINT:
	case PTA_MINDEXED:
	    if (begp->Pindex)		/* If nonzero index reg, remember it */
		xreg = begp->Pindex;

	    if (xreg != R_SP)		/* Unless stack ptr, forget offset */
		aoff = NULL;
	    break;

	case PTA_REGIS:
	    xreg = begp->Pr2;		/* Then drop thru to ignore offset */

	default:
	    aoff = NULL;
	    break;
	}

    for (q = after (begp); q; q = after (q))
	{
	if (q == endp)
	    {
	    if (aoff)
		*aoff = stkoff;

	    return NULL;		/* Won, return 0 (no reference) */
	    }

	/* Not yet done with loop, check out this instr */

	if (sameaddr (begp, q, stkoff) || alias (begp, q, stkoff))
	    {
	    if ((q->Pop & POF_BOTH) || (popflg[q->Pop & POF_OPCODE] & PF_MEMCHG))
		break;	/* P and Q may refer to same place, and the instr */
	    }		/* changes memory, so must fail. */

	/* Account for stack changes.
	**  A PUSH, POP, or ADJSP of the stack can be understood and the
	** rrchg test skipped if we are using the stack ptr as index reg
	** (otherwise rrchg would flunk the instr).
	*/

	ioff = 0;

	switch (q->Pop & POF_OPCODE)
	    {
	    case P_PUSH:
		if (q->Preg == R_SP)
		    ioff = 1;
		break;

	    case P_POP:
		if (q->Preg == R_SP)
		    ioff = -1;
		break;

	    case P_ADJSP:
		if (q->Preg == R_SP)
		    ioff = q->Pvalue;
		break;

	    /*
	     * FW, 22-Mar-93 (SPR 41) : any transfer of control
	     * should be construed as a reference to the register.
	     */

	    case P_PUSHJ :
	    case P_POPJ :
	    case P_JUMP :
	    case P_JRST :
		return q;
	    }

	stkoff += ioff;

	if (ioff && aoff)	/* Stack change, and using ptr as index reg */
	    {
	    if ((begp->Poffset - stkoff) > 0)
		break;		/* Cell no longer protected by stack ptr */

	    continue;		/* OK, can skip rrchg test */
	    }
	else if (xreg >= 0 && rrchg (q, xreg))
	    break;		/* Modifies register that X needs */
	}

    if (aoff)
	*aoff = stkoff;

    return q;
    }

/* RRPOPT - Post-optimization after adding reg-reg instruction.
**	We've just turned the sequence
**	fold:	MOVE S,x   into:  OP R,x
**		OP R,S
** and want to do further optimization on the new op/address combination
** resulting from that fold.
**	P points to the OP R,x instruction.
*/
static void
rrpopt(p)
PCODE *p;
{
    PCODE *q;
    int op;

    if (Register_Preserve(p->Pr2))    /* Avoids faulty optimizations  */
	return;

    /* P_CAML for an immediate type needs to become P_CAIL... */
    if ((op = immedop(p->Pop)) != 0 && (p->Ptype & PTF_IMM))
	{
	p->Pop = op;		/* fold: op to immediate type, and make */
	p->Ptype &= ~ PTF_IMM;	/* operand PTA_RCONST instead of PTV_IMMED */
	foldskip(p, 1);		/* Fix up P_CAI */
	return;
	}

    q = before(p);	/* look back before munged move.  May be NULL! */

    /* Big post-optimization switch: see what the added op was.
    ** Breaking out just returns, since instr has already been added.
    */
    switch (p->Pop & POF_OPCODE)
	{
	case P_PUSH:
	    code8(P_ADJSP, VR_SP, 0);	/* try adjustment */
	    break;			/* return */

	case P_SKIP:
	    if (p->Pop == P_SKIP+POF_ISSKIP+POS_SKPE
	      && p->Ptype == PTV_IINDEXED)
		/* Fold:	P_SKIPEI R,addr
		** Into:	MOVEI R,addr
		**	assuming that the SKIP is part of a (char *) cast
		** conversion of an immediate address value.
		*/
		p->Pop = P_MOVE;
	    break;			/* return */

	case P_FLTR:
	    if (p->Ptype != PTV_IMMED)
		break;			/* Return, not immediate operand */
	    p->Pop = P_MOVE;		/* fold: FLTRI R,x */
	    p->Ptype = PTA_FCONST;	/* into: MOVSI R,(xE0) */
	    /* This only works if target machine is same as source machine! */
	    p->Pfloat = (float) p->Pvalue;
	    break;			/* return */

	case P_IMUL:
	    if (p->Ptype != PTV_IMMED)
		return;
	    if (p->Pvalue == 1)
		{
		dropinstr(p);	/* drop IMULI R,1 */
		break;		/* then return */
		}

	    if (q && q->Ptype == PTV_IMMED /* !prevskips */
	      && q->Preg == p->Preg)
		switch(q->Pop)
		    {
		    case P_SUB:
		    case P_ADD:
			/*
			** fold:  ADDI/SUBI   R,n
			**        IMULI  R,m
			**
			** into:  IMULI  R,m
			**        ADDI/SUBI   R,m*n
			*/
			q->Pvalue *= p->Pvalue;	/* premultiply constant */
			swappseudo (p, q);	/* put add after multiply */
			p = q;		/* look at multiply for below */
			q = before(p);	/* and before in case another mult */
			if (q == NULL	 /* Check whether safe to drop in */
			  || q->Pop != P_IMUL
			  || q->Ptype != PTV_IMMED
			  || q->Preg != p->Preg)
			    break;		/* No, return now. */
			/* Drop through to next case */

		    case P_IMUL:
			/*
			** fold:  IMULI  R,n
			**        IMULI  R,m
			**
			** into:  IMULI  R,n*m
			*/
			q->Pvalue *= p->Pvalue;	/* multiply both together */
			dropinstr(p);		/* Flush later one */
			break;			/* Then return */

		    case P_MOVN:
		    case P_MOVE:
			/*
			** fold:  MOVEI/MOVNI  R,n
			**        IMULI  R,m
			**
			** into:  MOVEI/MOVNI  R,m*n
			*/
			q->Pvalue *= p->Pvalue;	/* mult const by factor */
			dropinstr(p);		/* flush folded multiply */
			break;			/* then return */
		    }
	    break;

	case P_LDB:
	case P_DPB:
	    foldbyte(p);	/* Attempt some simple opts */
	    break;		/* Done, return */

	case P_ADJBP:
	    foldadjbp(p);	/* fix up ADJBP instruction */
	    break;		/* return */

	case P_SUB:
	    if (p->Ptype == PTV_IMMED
	      && q != NULL
	      && q->Preg == p->Preg
	      && (q->Ptype == PTV_IMMED || q->Ptype == PTV_IINDEXED))
		switch (q->Pop)	/* check safe then switch */
		    {
		    case P_MOVE:
		    case P_ADD:
			q->Poffset -= p->Poffset;
			dropinstr(p);		/* fold:  ADDI/MOVEI R,n */
			foldplus(q);	/*	  SUBI R,m */
			return;		/* into:  ADDI R,n-m */

		    case P_SUB:
			q->Poffset += p->Poffset;
			dropinstr(p);		/* fold:  SUBI R,n */
					/*	  SUBI R,m */
			return;		/* into:  SUBI R,n+m */
		    }
	    /* fall through to foldplus() */

	case P_ADD:
	    foldplus(p);		/* do general optimization on add */
	    if (p != previous)		/* Take care of possible ADDI+ADDI */
		foldplus(previous);	/* that sometimes results */
	    break;			/* return */

	case P_CAM:
	    if (q != NULL
	      && q->Ptype == PTA_REGIS /* !prevskips */
	      && q->Pop == P_MOVE
	      && q->Preg == p->Preg)
		{

		/*
		** fold:  P_MOVE  R,S
		**        P_CAMx  R,x
		**
		** into:  P_CAMx  S,x
		*/
		p->Preg = (char) (q->Pr2);	/* flatten tested register */ // FW KCC-NT
		q->Pop = P_NOP;		/* flush useless move */
		}
	    break;			/* Return */

	default:
	    rrpop2(p);		/* Apply usual opts */
	    return;
	}	/* End of huge switch on newly-added op code */
}

/* RRPOP2 - Auxiliary for CODE0, does some optimizations on OP R,S.
*/
static void
rrpop2(p)
PCODE *p;
{
    if (Register_Preserve(p->Pr2))    /* Avoids faulty optimizations  */
	return;

    switch (p->Pop & POF_OPCODE)
	{
	case P_PUSH:
	    code8(P_ADJSP, VR_SP, 0);	/* Hack stack */
	    break;

	case P_AND:
	case P_IOR:
	case P_XOR:
	    if (!findconst(p))
		inskip(p);		/* turn SKIPA/MOVE/IOR into TLOA/IOR */
	    break;

	case P_CAM:
	    findconst(p);		/* See if can turn CAM into CAI *

⌨️ 快捷键说明

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