📄 cccode.c
字号:
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 + -