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

📄 ccjskp.c

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

    case P_SUB:
	if (!safechange) return;

	/*
	** fold:  P_SUB R,addr
	**  	  P_CAIN R,0
	**
	** into:  P_CAMN R,addr
	**
	** (only for P_CAMN or P_CAME, not other comparisons)
	*/

	if (p->Pop != P_CAI+POF_ISSKIP+POS_SKPE && p->Pop != P_CAI+POF_ISSKIP+POS_SKPN) return;
	q->Pop = p->Pop;		/* make comparison */
	if (q->Ptype & PTF_IMM) q->Ptype &=~ PTF_IMM; /* immediate uses P_CAI form */
	else q->Pop ^= (P_CAM ^ P_CAI);	/* memory uses P_CAM form */
	break;

    case P_AOS:	case P_SOS:

	/*
	** fold:  P_AOS   R,addr
	**        P_CAIx  R,0
	**
	** into:  P_AOSx  R,addr
	*/

	q->Pop |= (p->Pop &~ POF_OPCODE);
	break;

    default: return;
    }

    /*
    ** All the defaults in the previous switch should be return statements,
    ** so if we made it through we must have made a fold.  We should therefore
    ** flush the P_CAIx so we don't have two skips in a row.
    */

    dropinstr(p);		/* flush it, making sure previous valid */
}

/* JUMPTOSKIP(p) - Turn a jump into an immediate compare against zero.
** 
** Assumes there is one instruction between the jump and its
** label; if only zero the resulting skip should be reversed.
** Doesn't update PTF_SKIPPED in following opcodes.
*/

static void
jumptoskip (p)
PCODE *p;
{
    if ((p->Ptype &~ PTF_SKIPPED) == PTA_MINDEXED) switch (p->Pop & POF_OPCODE) {
    case P_JRST:
	if (invskip(before(p))) {	/* can flip previous skips */
	    dropjump (p);		/* so having done it just drop jump */
	    return;
	}
	reflabel (p->Pptr, -1);		/* fix up reference counts */
	p->Pop = P_TRN+POF_ISSKIP+POS_SKPA;	/* now turn it into a P_TRNA */
	p->Ptype ^= (PTA_MINDEXED ^ PTA_ONEREG); /* no address */
	p->Preg = 0;			/* no register either */
	return;

    case P_JUMP:
	reflabel (p->Pptr, -1);		/* fix up reference counts */
	p->Pop ^= (P_CAI ^ P_JUMP ^ POF_ISSKIP); /* make P_CAIx */
	p->Ptype ^= (PTA_MINDEXED ^ PTA_RCONST); /* immediate compare */
	p->Pvalue = 0;			/* against zero */
	return;

    case P_AOJ:
	reflabel (p->Pptr, -1);		/* fix up reference counts */
	p->Pop ^= (P_AOS ^ P_AOJ ^ POF_ISSKIP);	/* make P_AOSx */
	p->Ptype ^= (PTA_MINDEXED ^ PTA_REGIS);	/* reg to reg */
	p->Pr2 = p->Preg;		/* both same reg */
	return;

    case P_SOJ:
	reflabel (p->Pptr, -1);		/* fix up reference counts */
	p->Pop ^= (P_SOS ^ P_SOJ ^ POF_ISSKIP);	/* make P_SOSx */
	p->Ptype ^= (PTA_MINDEXED ^ PTA_REGIS);	/* reg to reg */
	p->Pr2 = p->Preg;		/* both same reg */
	return;
    }
}

/* CROSSJUMP(p, label) - Pull JUMPx across skips
**
** Sometimes it can improve code to move a P_JUMPx, P_AOJx, or P_SOJx from one
** side of a set of cascaded skips to the other.  We have to be careful
** though in rearranging this sort of thing that we don't get illegal
** memory references or indirection loops.
**	KLH: One problem with this code is that the two code sequences
** are not equivalent.  That is, the registers may end up with different
** values, since the skips may have modified the regs.  The initial sequence
** would not do this modification, whereas the new sequence does.
*/

static void
crossjump(pcur, lab)
PCODE *pcur;
label lab;
{
    PCODE *q, *p;
    int op;

    /*
    ** fold:  JUMPx  R,lab		; JUMPx, AOJx, or SOJx
    **	      (any number of skips)	; for JUMP, cannot change R or any mem
    **					;         also cannot use R in address
    **					; for A/SOJ, ditto + can't use R as reg
    **	pcur-> JRST   L2
    **	      lab: (or JRST lab)
    **
    ** into:  (the same skips)
    **	      JUMPy  R,L2
    **	      lab: (or JRST lab)
    */
    if (pcur->Pop != P_JRST) return;	/* must be a jump here */

    for (q = before(pcur); ; q = before(q)) {
	if (q == NULL) return;
	if (!isskip(q->Pop))		/* Non-skip instr halts loop */
	    break;
	if ((popflg[q->Pop&POF_OPCODE]&PF_MEMCHG)	/* Any mem chg instr */
	  || (q->Ptype & PTF_IND))			/* or indirect ref */
		return;					/* halts the search. */
    }
    switch (op = (q->Pop & POF_OPCODE)) {
	case P_AOJ:
	case P_SOJ:
	case P_JUMP:
	    if (q->Pptr != lab || prevskips(q))
		return;			/* Wrong label or op is skipped */

	    /* Re-scan the skips to ensure they do not use R unsafely.
	    ** For JUMP, just ensure the skip does not modify R, and does not
	    **	use it in an address.
	    ** For AOJ/SOJ, must ensure R is not referenced at all.
	    */
	    for (p = before(pcur); p != q; p = before(p)) {
		if (rinaddr(p, q->Preg) ||	/* R cannot be in addr */
		  ((op == P_JUMP)
		  ? rrchg(p, q->Preg)		/* Cannot modify R */
		  : rinreg(p, q->Preg)))	/* Cannot reference R */
		    return;
	    }
	    /* Won, OK to move and invert the jump. */
	    pcur->Preg = q->Preg;		/* else copy reg to jump on */
	    pcur->Pop = revop(q->Pop);		/* invert jump cond */
	    dropjump(q);			/* drop original JUMPx */
    }
}

/* FOLDJUMP(label) - Common optimizations for labels and jumps
**
** Called either when about to emit a jump to the given label, or when about
** to emit the label itself.  There are some things we can do in optlab()
** that we can't do here, because (for instance) we don't want to turn a
** jump two before another to the same place into a TRNA to the jump.
*/

void
foldjump(PCODE *prev, label lab) 
/* Instr preceding either label or the JRST to label */
{
    PCODE *q, *b;

    if (!prev || !oneinstr(prev) ||
	(q = before(prev)) == NULL || (b = before(q)) == NULL) return;

    if (q->Pop == P_JRST
      && q->Pptr == lab
      && !(q->Ptype & PTF_IND)
      && invskip(b)) {
	/*
	** Fold:  skip		Into:	reverse-skip
	**         JRST lab		--
	**        op			 op
	**        lab: (or JRST lab)	lab: (or JRST lab)
	*/

	dropjump(q);			/* already flipped skip, drop jump */
	setskip(prev);			/* op is now skipped over */
	if (prev->Pop == P_MOVN
	  && b->Preg == prev->Preg
	  && !prevskips(b)
	  && (b->Pop == P_SKIP+POF_ISSKIP+POS_SKPG || b->Pop == P_SKIP+POF_ISSKIP+POS_SKPGE)
	  && (sameaddr(b, prev, 0)
	    || (prev->Ptype == PTF_SKIPPED+PTA_REGIS
	      && prev->Preg == prev->Pr2))) {

	    /*
	    ** fold:  SKIPGE R,x	into: MOVM R,x
	    ** 	       MOVN R,R			--
	    */
	    b->Pop = P_MOVM;		/* make MOVM */
	    dropinstr(prev);		/* drop MOVN and fix prev */
	    prev = b;			/* to point to new previous op */
	}
    } else if (isskip(q->Pop) && oneinstr(q)
		&& b->Pop == P_JRST && b->Pptr == lab
		&& invskip(before(b))) {
	/*
	** fold:  skip1
	**         JRST lab
	**        skip2		(must be skippable)
	**         op
	**    lab:  (or JRST lab)
	**
	** into:  reverse skip1
	**         reverse skip2
	**          JRST lab
	**        op
	**    lab:  (or JRST lab)
	*/

	q->Pop = revop(q->Pop);		/* reverse the second skip */
	setskip(q);			/* skip now will be skipped over */
	swappseudo(b, q);		/* switch the skip and the jump */
	clrskip(prev);			/* op no longer skipped over */
    }

    crossjump(prev, lab);		/* pull JUMPx across skips */
}

/* NEWSKIP(p) - Turn non-skip op into a skip
**
** I.e. P_MOVE becomes P_SKIPA.  Works even if op is skipped over
** (caller must check for that case).  Again, afters are not set PTF_SKIPPED.
*/

static int
newskip (p)
PCODE *p;
{
    PCODE *q;

    if (p != NULL) switch (p->Pop) {
    case P_SUB:
	if ((p->Ptype &~ PTF_SKIPPED) != PTV_IMMED || p->Pvalue != 1) break;
	p->Ptype ^= (PTV_IMMED ^ PTA_REGIS);
	p->Pr2 = p->Preg;
    case P_SOS:
	p->Pop = P_SOS+POF_ISSKIP+POS_SKPA;
	return 1;

    case P_ADD:
	if ((p->Ptype &~ PTF_SKIPPED) != PTV_IMMED || p->Pvalue != 1) break;
	p->Ptype ^= (PTV_IMMED ^ PTA_REGIS);
	p->Pr2 = p->Preg;
    case P_AOS:
	p->Pop = P_AOS+POF_ISSKIP+POS_SKPA;
	return 1;

    case P_IOR:
	if (p->Ptype & PTF_IMM) {
	    p->Pop = P_TRO+POF_ISSKIP+POS_SKPA;
	    p->Ptype &=~ PTF_IMM;
	} else p->Pop = P_TDO+POF_ISSKIP+POS_SKPA;
	return 1;

    case P_XOR:
	if (p->Ptype & PTF_IMM) {
	    p->Pop = P_TRC+POF_ISSKIP+POS_SKPA;
	    p->Ptype &=~ PTF_IMM;
	} else p->Pop = P_TDC+POF_ISSKIP+POS_SKPA;
	return 1;

    case P_SETZ:
	if ((p->Ptype &~ PTF_SKIPPED) != PTA_ONEREG) break;
	p->Pop = P_TDZ+POF_ISSKIP+POS_SKPA;
	p->Ptype ^= (PTA_ONEREG ^ PTA_REGIS);
	p->Pr2 = p->Preg;
	return 1;

    case P_SETO:   case P_MOVN:   case P_MOVE:
	if (!unsetz (p) || p->Ptype == PTV_IINDEXED) break; /* no XP_SKIPAI */
	p->Pop = P_SKIP+POF_ISSKIP+POS_SKPA;
	if ((p->Ptype &~ PTF_SKIPPED) == PTA_REGIS && (q = before (p)) != NULL &&
	    q->Preg == p->Pr2 && !prevskips (q)) switch (q->Pop & POF_OPCODE) {
	case P_SKIP: case P_AOS: case P_SOS:

	    /*
	    ** fold:  P_SKIPx S,x
	    ** 	      P_SKIPA R,S
	    **
	    ** into:  P_SKIPx R,x
	    */

	    q->Pop = revop (q->Pop);	/* invert skip */
	    q->Preg = p->Preg;		/* set reg */
	    dropinstr(p);		/* drop extra skip, fix up previous */
	}
	    
	return 1;
    }
    return 0;
}

/* UNSKIP(p) - Turn skip back into non-skip
** Undoes the actions of newskip(), and turns off conditional skips.
**
** Safe to be called on non-skip ops like P_JRST and P_POPJ.
*/

void
unskip (p)
PCODE *p;
{
    if (!isskip (p->Pop)) return;	/* be safe for P_JUMPx */
    switch (p->Pop &= POF_OPCODE) {
    case P_SOS:
	if ((p->Ptype &~ PTF_SKIPPED) != PTA_REGIS || p->Pr2 != p->Preg) return;
	p->Pop = P_SUB;			/* P_SOSA R,R */
	p->Ptype ^= (PTA_REGIS ^ PTV_IMMED);	/* becomes P_SUBI R,1 */
	p->Pvalue = 1;
	return;

    case P_AOS:
	if ((p->Ptype &~ PTF_SKIPPED) != PTA_REGIS || p->Pr2 != p->Preg) return;
	p->Pop = P_ADD;			/* P_AOSA R,R */
	p->Ptype ^= (PTA_REGIS ^ PTV_IMMED);	/* becomes P_ADDI R,1 */
	p->Pvalue = 1;
	return;

    case P_TRO:
	p->Ptype |= PTF_IMM;
    case P_TDO:
	p->Pop = P_IOR;
	return;

    case P_TRC:
	p->Ptype |= PTF_IMM;
    case P_TDC:
	p->Pop = P_XOR;
	return;

    case P_TDZ:
	if ((p->Ptype &~ PTF_SKIPPED) != PTA_REGIS || p->Pr2 != p->Preg) return;
	p->Pop = P_SETZ;			/* P_TDZA R,R */
	p->Ptype ^= (PTA_REGIS ^ PTA_ONEREG);	/* becomes P_SETZ R, */
	return;

    case P_SKIP:
	p->Pop = P_MOVE;
	if ((p->Ptype &~ PTF_SKIPPED) != PTV_IMMED || p->Pvalue != -1) return;
	p->Pop = P_SETO;
	p->Ptype ^= (PTV_IMMED ^ PTA_ONEREG);
	return;

    case P_TRN: case P_TDN: case P_TLN: case P_CAI: case P_CAM: /* no-ops */
	dropinstr(p);		/* flush it all the way, fix up previous */
	unskip(before(p));	/* make sure no spurious skippage */
    }
    /* default is safe, just op with no skip part */
}

/* OPTLAB(label) - Optimize code in front of label
**
** If we know the label is coming after the next instruction, we can
** make several changes, mostly turning jumps into skips, that improve
** code and may make it possible to avoid emitting the label.
*/

void
optlab(label lab)
{
    PCODE *p, *q, *b, *bb;

    /* Fold useless jumps and preceeding skips into nothing */
    if ((previous->Pop == P_JRST || (previous->Pop & POF_OPCODE) == P_JUMP) &&
	previous->Pptr == lab && !(previous->Ptype & PTF_IND)) {

	dropjump(previous);		/* drop the jump or skip */
	unskip(previous);		/* disable the skip before it */

⌨️ 快捷键说明

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