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

📄 cccode.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
**	This is a CODxxx routine both for consistency and so that
** PHO debugging information can be output if desired.
** Returns 1 if all relevant instances of the "from" register in the
** peephole buffer were successfully changed to the "to" register.
** Otherwise returns 0 and nothing was changed.
*/
int
codcreg(to, from)
VREG *to, *from;
{
    int ret;

    (void) vrstoreal(from, to);
    ret = changereg(vrreal(to), vrreal(from), previous);
#if DEBUG_KCC		/* 5/91 KCC size */
    if (ret && debpho)
	{
	fprintf(fpho, "CODCREG: to %o from %o\n", vrreal(to), vrreal(from));
	shocum();
	}
#endif
    return ret;
}

/* CODE0 - Generates instruction with register-only operands.
**	OP r1,r2
**
** CODE0 releases register r2 for future reassignment (although later
** peephole optimizations might notice that it hasn't been changed yet
** and re-use whatever value it contained).
**
** CODEK0 does NOT release register r2.  The assignment operators need to
** keep around two registers sometimes.
*/


void
codek0(op, r1, r2)	/* KEEP the second register!! */
int op;
VREG *r1, *r2;
{
    VREG *r3 = vrget();		/* Get another temp reg */
    int s = vrstoreal(r3, r2);		/* Ensure it and both regs real */
    int r = vrstoreal(r1, r2);

    vrfree(r3);
    code00(P_SETM, s, vrreal(r2));	/* Use this to avoid losing r2 */
    code00(op, r, s);
}
void
code0(op, r1, r2)
int op;
VREG *r1, *r2;
{
    int s = vrstoreal(r2, r1);		/* Make regs real ones */
    if (r1 != r2)
	vrfree(r2);		/* flush operand for later */
    code00(op, vrreal(r1), s);
}

void
code00(int op, int r, int s)
{
    PCODE *p, *prev;

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	shohdr("CODE0", op, r);
	fprintf(fpho, "%o\n", s);
	}
#endif


    if (Register_Preserve(s) && op == P_MOVE && r == s)
	return;		/* Don't create useless "MOVE R,R" */

    if (Register_Nopreserve(s))
    /* Simple pre-optimization. */
	s = ufcreg(s);			/* Flush failed changereg for 2nd AC */
    if (Register_Nopreserve(r))
	if ((op & POF_OPCODE) == P_CAM)	/* and other if comparison */
	    r = ufcreg(r);

    /* Now just add the instruction. */
    prev = previous;			/* Remember previous, if any */
    p = newcode(PTA_REGIS, op, r);
    p->Pr2 = s;

    /* Everything else is optimization hacks */

    /* Try to avoid storing a MOVE-type op by going back through
    ** the buffer and changing code so that the operand register (s)
    ** is already the destination (r).
    ** Neither pushneg nor pnegreg creates or kills any instructions,
    ** so pointers remain safe.
    */
    if (Register_Nopreserve(p->Preg) && Register_Nopreserve(p->Pr2) &&
	    Register_Nopreserve(prev->Preg) && Register_Nopreserve(prev->Pr2))
	if (optobj)
	    switch (op)
		{
		case P_SETM:			/* Special code to avoid optimizer! */
		    break;			/* Otherwise S will get re-used. */

		case P_MOVM:			/* If case hash, also do nothing */
		    break;

		case P_MOVN:			/* fold: out P_MOVN */
		    if (r == s && pnegreg(s, prev))	/* Try to use other instrs */
			{
			flsprev();		/* Win, don't need MOVN at all! */
			break;
			}
		    if (!pushneg(s, prev))	/* Try to negate value */
			{
			codrrx(prev, p);	/* Didn't work, try other opts */
			break;
			}
		    p->Pop = P_MOVE;		/* Value negated! Change op to MOVE */
					/* and drop thru to handle MOVE */
		case P_MOVE:
		    if (changereg(r, s, prev))
			flsprev();		/* Won, can flush instr we added */
		    else
			codrrx(prev, p);	/* Nope, just apply other opts. */
		    break;

		case P_DMOVE:
		    if (r == s)			/* Changereg doesn't like doubles, */
			flsprev();		/* so this is the best we can do. */
		    else
			codrrx(prev, p);	/* Nope, try other optimizations. */
		    break;

		default:			/* None of above, just try */
		    codrrx(prev, p);		/* normal post-optimizations */
		    break;
		}

#if DEBUG_KCC		/* 5/91 KCC size */
    /* Done, show updated buffer on debugging output if required */
    if (debpho)
	shocum();
#endif
}

/* CODE1 - Generates instruction with an immediate integer constant operand
**	OP+I r,val
** This becomes type PTA_RCONST+PTF_IMM. 
*/

void
code1(op, vr, s)
int op;
VREG *vr;
INT s;
{
    codr1(op, vrtoreal(vr), s);
}

void
codr1(op, r, s)
int op, r;
INT s;
{
    PCODE *p;

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	shohdr("CODE1", op, r);
	fprintf(fpho,"<imm> %o\n", s);
	}
#endif
    p = newcode(PTA_RCONST+PTF_IMM, op, r);
    p->Poffset = s;

    if (optobj)
	{
	foldplus(p);		/* now do post-optimizations */
	foldmove(previous);	/* "previous" instead of "p", maybe changed */
	}
#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* CODEBP - Generate instr with PTA_BYTEPOINT local byte pointer operand.
**	OP r,[bbbbii,,sym+o]
**
** Used in optimization of string ops, and in generating struct bit fields.
** NOTE!!! The reg and index arguments are REAL register #s, not pointers
** to virtual regs.
*/

void
codebp(op, r, b, i, sym, o)
int op, r;		/* Note real, not vreg */
INT b;
int i;
SYMBOL *sym;
INT o;
{
    PCODE *p;

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	shohdr("CODEBP", op, r);
	fprintf(fpho,"[%o,,%s+%o(%o)]\n",
			b, (sym ? sym->Sname : ""), o, i);
	}
#endif
    p = newcode(PTA_BYTEPOINT, op, r);		/* Add the instruction */
    p->Pindex = i;
    p->Pptr = sym;
    p->Poffset = o;
    p->Pbsize = b;		/* Store P+S field here */

    /* Apply local-format byte-pointer optimizations */
    if (optobj)
	{
	foldbp(p);	/* Try to optimize operand (doesn't change opcode) */
	foldbyte(p);	/* Attempt byte op optimizations */
	}
#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* CODE3 - Generates address for symbol.
**	OPI R,sym
**
** Only used with P_MOVE, so this becomes MOVEI R,SYM.
*/

void
code3(op, vr, s)
SYMBOL *s;
VREG *vr;
{
    codrmdx(PTA_MINDEXED+PTF_IMM, op, vrtoreal(vr), s, 0, 0);
}

/* CODE4 - Generates instruction using indexed register operand.
**	OP r,(idx)
**
** This is used after a gaddress() to get the contents of a variable,
** and also for assignment ops (like Q_ASGN = P_MOVEM).  The index is released.
**
** CODEK4 is the same but doesn't release the index register.
**
** CODE4S takes an extra argument which it stuffs into the Pbsize field
** of the stored op.  This is used as a special hack for P_SMOVE only,
** and the size is associated with the op rather than the operand.
*/

void
code4(op, reg, idx)
VREG *reg, *idx;
{
    int r, s;

    r = reg ? vrstoreal(reg, idx) : 0;	/* Allow IBP/JRST 0, */
    s = ufcreg(vrtoreal(idx));
    if (reg != idx)
	vrfree(idx);	/* will no longer need register */
    code40(op, r, s, 0);
}

static char *tmp_mnem;  /* KAR-2/91, static storage for imuuo mnemonic */
extern int _chnl;	/* KAR-2/91, temporary storage for channel numbers */

void
code4m(op, reg, idx, mnem)
int op;
VREG *reg, *idx;
char *mnem;
{
    int r, s;

    tmp_mnem = (char *) calloc(1, strlen(mnem) + 1);
    if (tmp_mnem == NULL)
	jerr("Out of memory for imuuo mnemonic\n");
    strcpy(tmp_mnem, mnem);

    r = reg ? vrstoreal(reg, idx) : 0;	/* Allow IBP/JRST 0, */
    s = ufcreg(vrtoreal(idx));
    if (reg != idx)
	vrfree(idx);	/* will no longer need register */
    code40(op, r, s, 0);
}

void
codek4(op, reg, idx)
VREG *reg, *idx;
{
    VREG *r3;
    int r, s;

    r = ufcreg(vrtoreal(idx));
    s = vrstoreal(r3 = vrget(), idx);
    code00(P_SETM, s, r);	/* Use this to avoid losing r2 */
    r = vrstoreal(reg, r3);
    s = vrreal(r3);
    vrfree(r3);
    code40(op, r, s, 0);
}

void
code4s(op, reg, idx, keep, bsiz)
int op;
VREG *reg, *idx;
INT bsiz;
{
    VREG *r3;
    int r, s;
    if (keep)
	{
	r = ufcreg(vrtoreal(idx));
	s = vrstoreal(r3 = vrget(), idx);
	code00(P_SETM, s, r);	/* Use this to avoid losing r2 */
	r = vrstoreal(reg, r3);
	vrfree(r3);
	}
    else
	{
	r = vrstoreal(reg, idx);
	s = ufcreg(vrreal(idx));
	if (reg != idx)
	    vrfree(idx);	/* will no longer need register */
	}
    code40(op, r, s, bsiz);
}

void
code40(op, r, s, bsiz)
int op;
int r, s;
INT bsiz;
{
    PCODE *p;

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	shohdr("CODE4", op, r);
	fprintf(fpho,"(%o) siz %lo\n", s, (INT) bsiz);
	}
#endif
    
    /* First just add the instruction */
    p = newcode(PTA_MINDEXED, op, r);
    p->Pptr = NULL;
    p->Poffset = 0;
    p->Pindex = s;
    p->Pbsize = bsiz;

/*
 * KAR-1/92, use channel field for null ptr det. to store line number also
 * need to skip mnemonic copy, so changed "if" to a "switch" below.
 */
    switch (op)
	{
	case P_MUUO:
	    p->p_im.mnemonic = (char *) calloc(1, strlen(tmp_mnem) + 1);
	    if (p->p_im.mnemonic == NULL)
		jerr("Out of memory for null ptr detection mnemonic\n");
	    strcpy(p->p_im.mnemonic, tmp_mnem);
	    free(tmp_mnem);
	    tmp_mnem = NULL;
	case P_NULPTR:
	    p->p_im.p_chnl = _chnl;
	    _chnl = -1;	/* KAR-6/91, Changed empty signal to -1 from 0 */
	    break;
	default:
	    if (optobj)			/* Apply post-optimization */
		foldxref(p);
	    break;
	}

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* CODE5 - Generate op using only a single register operand.
**	OP reg,
**
** Currently only used for SETZ, POPJ, TRNA.
*/

void
code5(op, reg)
VREG *reg;
{
    PCODE *p, *q;
    int r;
    r = reg ? vrtoreal(reg) : 0;	/* Allow for TRNA 0, in gboolop() */

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	shohdr("CODE5", op, r);
	fputc('\n', fpho);
	}
#endif

    p = newcode(PTA_ONEREG, op, r);		/* Add the instruction */

    if (optobj && (op == P_SETZ || op == P_SETO))
	{
	if ((q = before(p)) != NULL	/* Check previous instr */
		&& q->Pop == op
		&& q->Ptype == PTA_ONEREG /* && !prevskips */)
	    {
	    /*
	    ** fold:  SETZ  S, / SETZ R,	(or SETO)
	    ** into:  SETZB S,R			(or SETOB)
	    */
	    p->Ptype = PTA_REGIS;
	    p->Pop |= POF_BOTH;
	    p->Pr2 = r;
	    dropinstr(p);	/* Flush instr we just added */
	    }
	else if (op == P_SETZ)
	    foldmove(p);
	}

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

extern void free();

void
code5m(op, reg, mnem)
VREG *reg;
char *mnem;
{
    PCODE *p, *q;
    int r;

    r = reg ? vrtoreal(reg) : 0;	/* Allow for TRNA 0, in gboolop() */

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	shohdr("CODE5", op, r);
	fputc('\n', fpho);
	}
#endif

    p = newcode(PTA_ONEREG, op, r);		/* Add the instruction */
    
    /* KAR-2/91, Copies mnemonic into PCODE node for imuuo */
    if (op == P_MUUO)
	{
	p->p_im.mnemonic = (char *) calloc(1, strlen(mnem) + 1);
	if (p->p_im.mnemonic == NULL)
	    jerr("Out of memory for null ptr mnemonic\n");
	strcpy(p->p_im.mnemonic, mnem);
	p->p_im.p_chnl = _chnl;
	_chnl = -1;	/* KAR-6/91, Changed sentinal value to -1 from 0 */
	}

    if (optobj && (op == P_SETZ || op == P_SETO))
	{
	if ((q = before(p)) != NULL	/* Check previous instr */
		&& q->Pop == op
		&& q->Ptype == PTA_ONEREG /* && !prevskips */)
	    {
	    /*
	    ** fold:  SETZ  S, / SETZ R,	(or SETO)
	    ** into:  SETZB S,R			(or SETOB)
	    */
	    p->Ptype = PTA_REGIS;
	    p->Pop |= POF_BOTH;
	    p->Pr2 = r;
	    dropinstr(p);	/* Flush instr we just added */
	    }
	else if (op == P_SETZ)
	    foldmove(p);
	}

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* CODE6 - Generate op with a symbolic address operand.
**	OP reg,sym
** This is mostly used for jumps and switch jump tables.
*/


⌨️ 快捷键说明

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