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

📄 cccode.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
void
code6(op, reg, s)
SYMBOL *s;
VREG *reg;
{
    PCODE *p;
    int r = reg ? vrtoreal(reg) : 0;	/* Handle JRST 0,lab */

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	shohdr("CODE6", op, r);
	if (s)
	    fputs(s->Sname, fpho);
	fputc('\n', fpho);
	}
#endif

    /* Pre-optimization, sigh */
    if (optobj
      && (op & POF_OPCODE) == P_JUMP
      && previous && !isskip(previous->Pop))
	{

	/* Emit: JUMPx R,lab	as:	CAIx  R,0
	**				 JRST  lab
	**
	** So skip optimization can work best.  If it doesn't get folded,
	** then optjrst() will turn it back into JUMPx.
	*/
	r = ufcreg(r);		/* optimization loses w/o this? */
	p = newcode(PTA_RCONST,
		op ^ (P_CAI ^ P_JUMP ^ POF_ISSKIP ^ POSF_INVSKIP),
		r);
	p->Pvalue = 0;
	foldskip(p, 1);
	op = P_JRST;		/* make it a jump */
	r = 0;			/* JRST doesn't take a register */
	}

    /* All set up, drop values into the node */
    p = newcode(PTA_MINDEXED, op, r);
    p->Pptr = s;
    p->Pindex = 0;
    p->Poffset = 0;
    reflabel(s, 1);		/* Increment label reference count */

    /* Now do post-optimization */
    if (op == P_JRST && optobj)
	{
	foldjump(before(p), s);
	optjrst(previous);		/* p may have become nop */
	}

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* CODEMDX - Generates general-purpose PTA_MINDEXED op.
**	OP rreg,pptr+poffset(rindex)
**
** NOTE!!! Because this is only used to duplicate addressing of an
** already-generated op, the register args are REAL register numbers,
** not virtual reg pointers!
*/

void
codemdx(op, rreg, pptr, poffset, rindex)
int op;
SYMBOL *pptr;
int rreg;
INT poffset;
int rindex;		/* Not vregs! */
{
    PCODE *p;
    int nreg;

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	shohdr("CODEMDX", op, rreg);
	fprintf(fpho,"%s+%o(%o)\n", (pptr ? pptr->Sname : ""),poffset,rindex);
	}
#endif

    /* Maybe can do more complicated optimizing code generation */
    if (pptr == NULL && poffset == 0)
	{
	code40(op, rreg, ufcreg(rindex), 0);
#if DEBUG_KCC		/* 5/91 KCC size */
	if (debpho)
	    shocum();
#endif
	return;
	}
    nreg = ufcreg(rreg);		/* undo failed changereg */

    /* too general for optimization, just add the code */
    p = newcode(PTA_MINDEXED, op, nreg);
    p->Pptr = pptr;
    p->Poffset = poffset;
    p->Pindex = rindex;

    if (nreg != rreg)		/* Put result back in right register */
	code00(P_MOVE, rreg, nreg);
#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* CODE8 - Generates instruction with integer constant operand
**	OP r,const
**
** Like code1(), but op doesn't become immediate, making type PTA_RCONST.
** E.g. code8(P_ADJSP, VR_SP, n) where n is some stack offset.
**
** KLH: Note slipshod assumption that because CCGSWI calls code8 heavily
** for P_CAIx, foldskip() shouldn't try to change value of R, in case
** it is needed by later switch tests.
*/

void
code8(op, reg, val)
int op;
VREG *reg;
INT val;
{
    codr8(op, vrtoreal(reg), val);
}

static void
codr8(op, r, val)
int op;
int r;
INT val;
{
    PCODE *p;

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

    /* Pre-optimization when about to add ADJSP */
    if (optobj && op == P_ADJSP)
	{
	val = foldstack(val);
	if (val == 0)			/* If completely folded, can return */
	    {
#if DEBUG_KCC		/* 5/91 KCC size */
	    if (debpho)
		shocum();
#endif
	    return;
	    }
	}

    p = newcode(PTA_RCONST, op, r);
    p->Pvalue = val;

    /* Post-optimization for ADJSP, CAIx, CAMx */
    if (optobj)
	{
	if (op == P_ADJSP)
	    {
	    if ((p = before(p)) != NULL
	       && p->Ptype == PTV_IINDEXED)	/* && !prevskips */
		{
		if (p->Pindex == R_SP)
		    p->Poffset -= val;		/* Adjust stk addr for swap */
		swappseudo(p, previous);	/* Encourage tail recursion */
		}
	    }
	else				/* See if can fold: CAM or CAI */
	    foldskip(p, 0);		/* Could be from switch, be careful */
	}
#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* CODE9 - Generates instruction with floating-point constant operand
**	OP r,[float]
**
** Grave misunderstandings will result if the "twowds" flag
** does not match the op specified!
**	Either that flag or the opcode are valid ways of determining 
** whether we are dealing with a 1 or 2 word constant.
*/

void
code9(int op, VREG *vr, double value, int twowds)
/* twowds is TRUE if 2 wds (double), else 1-wd float */
{
    PCODE *p;
    int r = vrtoreal(vr);

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	shohdr("CODE9", op, r);
	fprintf(fpho,"[%.20g]\n", value);
	}
#endif

    /* Optimize a P_MOVE or P_DMOVE of 0.0 since floating point zero is
     * same as integer zero.
     */
    if (value == 0.0 && optobj)
	switch (op)
	    {
	    case P_DMOVE:	/* Make DMOVE R,[0 ? 0] be SETZB R,R+1 */
		/* Can't use code0 as that would release r+1 */
		p = newcode(PTA_REGIS, P_SETZ+POF_BOTH, r);
		p->Pr2 = r+1;
#if DEBUG_KCC		/* 5/91 KCC size */
		if (debpho)
		    shocum();
#endif
		return;
	    case P_MOVE:
		code5(P_SETZ, vr);
#if DEBUG_KCC		/* 5/91 KCC size */
		if (debpho)
		    shocum();
#endif
		return;
	    }

    p = newcode((twowds ? PTA_DCONST : PTA_FCONST), op, r);
    if (twowds)
	p->Pdouble = value;
    else
	p->Pfloat = (float) value;

    if (optobj)
	foldmove(p);	/* see if already have this one */
#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* CODE10 - Generate op with pointer constant operand (ie a pointer literal)
**	OP r,[pointer]
**
** The pointer is made from an:
**		address (pointer to a symbol)
**		offset (in bytes from address)
**		bytesize (0,6,7,8,9,18)
** Using this information, CCOUT constructs a byte or word pointer using
** symbolic references which are resolved at load time into whatever
** the proper values are, whether local or OWGBP format (non-extended or
** extended).
**	A bytesize of -1 is special and indicates that a MASK is desired
** for the P+S field of a byte-pointer.  This should never be used with
** an address or offset.
**	When used with the P_PTRCNV op (which converts a pointer in
** the register), the offset indicates the byte size of the current pointer,
** and the bsize indicates the desired byte size to convert it to.
** The address must be NULL.
*/

void
code10(op, vr, addr, bsize, offset)
int op;
VREG *vr;
SYMBOL *addr;
INT bsize, offset;
{
    codr10(op, vrtoreal(vr), addr, bsize, offset);
}

void
codr10(op, r, addr, bsize, offset)
int op, r;
SYMBOL *addr;
INT bsize, offset;
{
    PCODE *p;
    int nreg;

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	shohdr("CODE10", op, r);
	fprintf(fpho,"[%s+%o (size %d)]\n",
		(addr ? addr->Sname : ""), offset, bsize);
	}
#endif
    nreg = ufcreg(r);	/* undo failed changereg */
			/* this goes with the code0 call below */

    p = newcode(PTA_PCONST, op, nreg);
    p->Pptr = addr;
    p->Poffset = offset;
    p->Pbsize = bsize;

    if (nreg != r)
	code00(P_MOVE, r, nreg);

    if (optobj && op == P_MOVE)
	foldmove(previous);	/* see if already have this one */
#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* CODRMDX - Auxiliary for following routines, just to share
**	common code that creates a PTA_MINDEXED op and returns without
**	doing any optimization.
**	Note that the registers "reg" and "index" are real regs, not virtual.
*/
static void
codrmdx(type, op, reg, ptr, offset, index)
int type, op, reg;
SYMBOL *ptr;
INT offset;
int index;
{
    PCODE *p;

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	shohdr("CODRMDX", op, reg);
	if (type&PTF_IMM)
	    fputs("+I ", fpho);
	if (type&PTF_IND)
	    fputc('@', fpho);
	if (ptr)
	    fputs(ptr->Sname, fpho);
	if (ptr && offset)
	    fputc('+', fpho);
	if (offset)
	    fprintf(fpho, "%o", offset);
	if (index)
	    fprintf(fpho, "(%o)", index);
	fputc('\n', fpho);
	}
#endif
    p = newcode(type, op, reg);
    p->Pptr = ptr;
    p->Poffset = offset;
    p->Pindex = index;
#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* CODE12 - Generates register despill instruction.
**	OP reg,offset(17)
**
** This is used only by CCREG to despill registers with MOVE or DMOVE.
*/
void
code12(op, vr, offset)
int op;
VREG *vr;
INT offset;
{
    codrmdx(PTA_MINDEXED, op, vrtoreal(vr), (SYMBOL *)NULL, offset, R_SP);
}

/* CODE13 - Generates MOVEI of stack location.
**	opI reg,offset(17)
**
** Used by several things, but op is always MOVE, so this always
** becomes an MOVEI of a stack location.
*/
void
code13(op, vr, offset)
int op;
VREG *vr;
INT offset;
{
    codrmdx(PTA_MINDEXED+PTF_IMM, op, vrtoreal(vr),
					(SYMBOL *)NULL, offset, R_SP);
}

/* CODE15 - Generates op with indirect indexed local label
**	OP @lab+offset(idx)
**
** Only used by CCGSWI with op JRST for switch jump tables.
*/
void
code15(op, lab, off, idx)
SYMBOL *lab;
INT off;
VREG *idx;
{
    codrmdx(PTA_MINDEXED+PTF_IND, op, 0, lab, off, vrtoreal(idx));
}

/* CODE16 - Generates op with indexed local label.
**	OP reg,$lab(idx)
**
** Only used by CCGSWI with op CAM for checking switch hash tables.
*/
void
code16(op, vr, lab, vs)
SYMBOL *lab;
VREG *vr, *vs;
{
    int r = vrstoreal(vr, vs);		/* Ensure both R and S in real regs */
    codrmdx(PTA_MINDEXED, op, r, lab, 0, vrreal(vs));
}

/* CODE17 - Generates a literal value.
**
** Only used by CCGSWI for generating switch hash tables.
*/

void
code17(value)
INT value;
{
    PCODE *p;
#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	fprintf(fpho,"CODE17: literal %o\n", value);
	}
#endif
    p = newcode(PTA_RCONST, P_CVALUE, 0);
    p->Pvalue = value;
#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* CODESTR - Generate "code" consisting of a direct user-specified
**	assembly language string.  This implements the asm() construction.
*/
void
codestr(s, len)
char *s;
int len;
{
    flushcode();		/* Ensure pcode buffer flushed */
    while (--len >= 0)
	outc(*s++);
}

/* CODLABEL, CODGOLAB - Generate "code" consisting of the given label symbol.
**	codlab does more optimization and may not actually emit the label.
**	codgolab always emits its label; it is used for goto labels.
*/
/* CODLABEL - Emit a (forward) label.
**
** Optimizations are performed and if the label still has references
** to it, it is emitted.  Then realfreelabel() is called on it, and
** if we emitted it and thus cleared the peephole buffer we also free
** the list of labels queued by freelabel().
*/
void
codlabel(lab)
SYMBOL *lab;
{
    INT after = 0;

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	fprintf(fpho, "CODLAB: %s\n", lab->Sname);
	}
#endif

    if (optobj)
	{
	after = hackstack(lab);		/* pull ADJSP across POPJ */
	optlab(lab);			/* call peephole optimizer */
	}
    if (lab->Svalue > 0)		/* See if still must emit */
	{
#if DEBUG_KCC		/* 5/91 KCC size */
	if (debpho)
	    shocum();		/* Yes, report changes prior to */
#endif
	flushcode();			/* clearing out previous code. */
	outlab(lab);			/* Now emit label. */
	cleanlabs();			/* Now OK to clean up queued labels */
	}
    if (after)
	code8(P_ADJSP, VR_SP, after);	/* fix up stack */
    freelabel(lab);
#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* CODGOLAB - Emit a GOTO type label.

⌨️ 快捷键说明

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