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

📄 ccout.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
	case P_TRZ:
	case P_TRO:
	case P_CAI:
	    if (typ != PTA_RCONST || (p->Pvalue &~ 0777777L) == 0)
		break;
	    if ((p->Pvalue & 0777777L) == 0)
		{
		switch (p->Pop & POF_OPCODE)
		    {
		    case P_TRN:
			i = P_TRN ^ P_TLN;
			break;
		    case P_TRO:
			i = P_TRO ^ P_TLO;
			break;
		    case P_TRZ:
			i = P_TRZ ^ P_TLZ;
			break;
		    case P_TRC:
			i = P_TRC ^ P_TLC;
			break;
		    default:
			i = 0;
			break;
		    }
		if (i)
		    {
		    p->Pop ^= i;			/* Flip from RH to LH */
		    p->Pvalue = ((unsigned INT) p->Pvalue) >> 18;
		    break;
		    }
		}
	    if (! (p->Pvalue &~ 0777777L))
		break; /* still too big? */
	    p->Pop = directop (p->Pop);	/* Turn into memory version */
	    typ |= PTF_IMM;		/* Make PTV_IMMED so outinstr hacks bigness */
	    break;

    /* Optimization for non-test bitwise operations (IOR, AND, XOR).
    ** We try turning these into tests to avoid referencing memory
    ** for a literal constant.
    */
	case P_IOR:
	    if (!optobj || typ != PTV_IMMED || (p->Pvalue &~ 0777777L) == 0)
		break;			/* Can't or don't optimize */
	    if ((p->Pvalue & 0777777L) == 0) /* x,,0 */
		{
		p->Pop = P_TLO;
		typ = PTA_RCONST;
		p->Pvalue = ((unsigned INT) p->Pvalue) >> 18;
		}
	    else if (( (unsigned INT) p->Pvalue >> 18) == 0777777L) /* 777777,,x */
		{
		p->Pop = P_ORCM;
		p->Pvalue = (~p->Pvalue) & 0777777L;
		}
	    break;

	case P_XOR:
	    if (!optobj || typ != PTV_IMMED || (p->Pvalue &~ 0777777L) == 0)
		break;			/* Can't or don't optimize */
	    if ((p->Pvalue & 0777777L) == 0) /* x,,0 */
		{
		p->Pop = P_TLC;
		typ = PTA_RCONST;
		p->Pvalue = ((unsigned INT) p->Pvalue) >> 18;
		}
	    else if (( (unsigned INT) p->Pvalue >> 18) == 0777777L) /* 777777,,x */
		{
		p->Pop = P_EQV;
		p->Pvalue = (~p->Pvalue) & 0777777L;
		}
	    break;

	case P_AND:
	    if (!optobj || typ != PTV_IMMED || (p->Pvalue &~ 0777777L) == 0)
		break;			/* Can't or don't optimize */
	    if ((p->Pvalue & 0777777L) == 0777777L) /* x,,777777 */
		{
		p->Pop = P_TLZ;
		typ = PTA_RCONST;
		p->Pvalue = (unsigned INT) (~p->Pvalue) >> 18;
		}
	    else if (( (unsigned INT)p->Pvalue >> 18) == 0777777L) /* 777777,,x */
		{
		p->Pop = P_TRZ;
		typ = PTA_RCONST;
		p->Pvalue = (~p->Pvalue) & 0777777L;
		}
	    break;
	    
    /*
    ** Signed integer multiplication by a power of two is better done as an ASH
    ** (arithmetic shift - not the same as LSH).  Don't try this
    ** for division, as the result is incorrect for negative numbers!
    ** Note that unsigned multiplication will use P_MUL, not P_IMUL.
    ** Note the subtle test for power-of-two-ness which relies on
    ** twos-complement arithmetic.
    **
    ** Similarly, floating multiply by two becomes FSC (floating scale).
    ** Division is OK, unlike the integer case.
    ** This can only work for single-precision floats (not doubles).
    ** Otherwise we fall through to the other floating code.
    */
	case P_IMUL:
	    if (optobj && typ == PTV_IMMED && (p->Pvalue & (p->Pvalue - 1)) == 0)
		{
		p->Pvalue = binexp (p->Pvalue);	/* get # of bits to shift */
		p->Pop = P_ASH;			/* and opcode */
		typ = PTA_RCONST;			/* and code type */
		}
	    break;

	case P_FMPR:		/* If doing single-precision mult or div */
	case P_FDVR:
	    if (optobj
	      && typ == PTA_FCONST		/* If operand is a float constant */
	      && (i = fltpow2 (p->Pfloat)) != 0)	/* and is a power of 2 */
		{
		p->Pvalue = (p->Pop == P_FDVR) ? -i : i;
		p->Pop = P_FSC;
		typ = PTA_RCONST;
		break;
		}

    /*
    ** Optimize moves of constants to use immediate form if possible.
    ** A check for "float" constants, which can be
    ** MOVSI'd into the LH if their RH is zero, is made in outinstr ().
    ** "double" constants
    ** normally do not come here as they use DMOVx, but it is possible
    ** as part of a code sequence that zeros the second AC separately.
    */
	case P_MOVN:
	    if (!optobj || typ != PTV_IMMED || (p->Pvalue &~ 0777777L) == 0)
		break;
	    p->Pop = P_MOVE;		/* re-invert P_MOVN */
	    p->Pvalue = - p->Pvalue;	/* for fixup into P_MOVSI */
	case P_MOVE:
	    if (!optobj || typ != PTV_IMMED)
		break;
	    if (p->Pvalue && (p->Pvalue & 0777777L) == 0)
		{
		p->Pop = P_MOVS;	/* MOVEI of left half quantity */
		p->Pvalue = ((unsigned INT) p->Pvalue) >> 18;	/* becomes MOVSI */
		}
	    break;
	default:
	    ;	/* do nothing */
	}
    /* End of moby switch on instruction opcode! */

    typ |= p->Ptype & PTF_SKIPPED;
    p->Ptype = typ;	/* Put back type in case it was changed. */
    outinstr (p);	/* Output the instruction! */
}

/* OUTINSTR (p) - Output instruction.
**
** We give a skipped-over op an extra space of indentation, to make it look
** more like human code (big deal) and to make debugging KCC easier.
*/
static void
outinstr (PCODE *p)
{

    int big, i, opr;

    outtab ();				/* Start instruction output w/ tab */
    if (p->Ptype & PTF_SKIPPED)		/* Indent skipped-over instr */
	outc (' ');

    switch (p->Ptype & PTF_ADRMODE)
	{

	case PTA_ONEREG:
	    if (p->Pop == P_MUUO)
		{
		outstr (p->p_im.mnemonic);
		if (p->p_im.p_chnl != -1)	/* KAR-6/91, chgd sentinal to -1 */
		    {
		    outtab ();	/* KAR-2/92, chgd outreg () to outnum () call */
		    outnum (p->p_im.p_chnl);
		    outc (',');
		    }
		else
		    outreg (p->Preg);
		}
	    else
		{
		outop (p->Pop);
		outreg (p->Preg);
		}

	    break;

	case PTA_REGIS:
	    outop (p->Pop);
	    outreg (p->Preg);

	    if (mlist && Register_Preserve (p->Pr2))
		outid (Reg_Id[p->Pr2 -
		      (r_maxnopreserve + 1)]->Sname); /* FW 2A (47) */
	    else if (mlist && p->Pr2 == R_SP)
		outid ("SP");
	    else
		outnum (p->Pr2);
	    break;

    /* PTA_MINDEXED operands require special hackery when the operand is
    ** being used in an immediate fashion, i.e. the address value itself
    ** is needed.  This can happen either if the operand is marked
    ** immediate (PTF_IMM set) or if the opcode is one that treats E as
    ** an immediate operand (only CAIx and TRx are checked).
    */
	case PTA_MINDEXED:
	    if (p->Pop == P_NULPTR)
		{
		outnpd (p);
		break;
		}

	    if (! (p->Ptype & PTF_IMM))
		{
	    /* Not using immediate address, only need to check for
	    ** instrs that are always immediate.
	    */
		if ((i = directop (p->Pop)) != 0) /* Convert CAIx to CAMx? */
		    {
		    p->Pop = i;		/* Ugh, convert to direct form */
		/* Fall past to do MOVEI */
		    }
		else
		    {
		/* Normal operand, easy! */

		    if (p->Pop == P_MUUO)
			{
			outstr (p->p_im.mnemonic);
		    /* KAR-6/91, changed sentinal value to -1 from 0 */
			if (p->p_im.p_chnl != -1)
			    outreg (p->p_im.p_chnl);
			else
			    outreg (p->Preg);
			}
		    else
			{
			outop (p->Pop);
			outreg (p->Preg);
			}

		    outaddress (p);		/* and address */
		    break;			/* Done! */
		    }
		}

	/* Instruction is using an immediate address.
	*/
	    if (p->Pop == P_MOVE || p->Pop == P_MOVEI)
		{
		outop (P_MOVEI);
		outreg (p->Preg);	/* Use given reg */
		outaddress (p);	/* and address */
		break;
		}
	/* Instruction needs an MOVEI preceding it.  Barf if we
	** generated a skip over this instr in the mistaken belief it
	** only occupied 1 word, which means that oneinstr () was either
	** wrong or wasn't called.  In particular, this should never happen
	** for the second of a cascaded skip.
	*/
	    if (p->Ptype & PTF_SKIPPED)
		int_error ("outinstr: MOVEI skipped");
	    outop (P_MOVEI);
	    outreg (R_SCRREG);	/* simulate by MOVEI into scratch */
	    outaddress (p);		/* of desired address */
	    outnl ();
	    outtab ();
	    outop (p->Pop);		/* followed by real instruction */
	    outreg (p->Preg);	/* into desired reg */
	    outnum (R_SCRREG);	/* from scratch reg */
	    break;

    /* PTA_PCONST requires some special checks for immediate pointer
    ** operands, which are distinguished by the lack of a word address
    ** symbol (Pptr is NULL).
    ** These should only be seen for TDZ, TDO, and IOR.
    ** TDZ uses them to mask out the P+S fields of a ptr (converting to wd ptr)
    ** IOR uses them to generate a byte ptr from a word ptr.
    ** TDOx is sometimes seen due to conversion from an IOR.
    ** Not clear if anything else can ever have a null word address.
    */
	case PTA_PCONST:
	    i = 0;
	    if (p->Pptr == NULL)
		switch (p->Pop & POF_OPCODE)
		    {
		    case P_TDZ:
			i = P_TDZ ^ P_TLZ;
			break;	/* Change TDZ to TLZ */
		    case P_TDO:
			i = P_TDO ^ P_TLO;
			break;	/* Change TDO to TLO */
#if 0
		    case P_IOR:
			i = P_IOR ^ P_TLO;
			break;	/* Change IOR to TLO */
#else
		    case P_IOR:
			i = P_IOR ^ P_HRLI;
			break;	/* Change IOR to HRLI */
#endif
		    default:
			;	/* do nothing */
		    }
	    if (i)			/* If can use immediate form, */
		{
		outop (p->Pop ^ i);		/* change opcode and output it! */
		outreg (p->Preg);
		outpti ((int) p->Pbsize, p->Poffset); /* Output immediate P+S sym */
		}
	    else
		{
		outop (p->Pop);		/* Normal full-word pointer constant */
		outreg (p->Preg);
		outc ('[');
		outptr (p->Pptr, (int) p->Pbsize, p->Poffset);
		outc (']');
		}
	    break;

	case PTA_BYTEPOINT:
	    outop (p->Pop);
	    outreg (p->Preg);
	    outc ('[');
	    outnum (p->Pbsize);	/* Output P+S field */
	    outstr (",,");
	    outaddress (p);		/* Now add right half addr+offset (index) */
	    outc (']');
	    break;

	case PTA_RCONST:
	    outop (opr = p->Pop);
	    big = 1;		/* Assume full-word operand */
	    if ((popflg[opr&POF_OPCODE]&PF_EIMM)	/* If op takes E as immed op */
	      || ! (p->Ptype & PTF_IMM))		/* or optype not marked "imm"*/
		big = 0;				/* then just output OP R,val */
	    else
		{
	    /* Op is not an E-immediate type, but is marked as "immediate".
	    ** So either we generate an opI form,
	    ** or make the operand into a memory literal as in OP R,[val].
	    */
		if ((popflg[opr&POF_OPCODE] & PF_OPI)	/* If op can be opI,*/
		  && (p->Pvalue &~ 0777777L) == 0)	/* and operand has zero LH, */
		    {
		    outc ('I');			/* make immediate op! */
		    big = 0;			/* and say small operand */
		    }
		}
	    outreg (p->Preg);		/* Output reg and comma */
	    if (big)
		{
		outc ('[');
		outnum (p->Pvalue);
		outc (']');
		}
	    else
		outnum (p->Pvalue);
	    break;


	case PTA_FCONST:
	    switch (p->Pop & POF_OPCODE)
		{
		case P_FADR:
		case P_FSBR:	/* Single-precision operations */
		case P_FMPR:
		case P_FDVR:	/* can be optimized sometimes */
		case P_MOVS:
		    big = bigfloat (p);	/* Set flag 0 if small */
		    break;
		case P_MOVE:		/* Check for quick setup of float */
		    if ((big = bigfloat (p)) == 0)
			p->Pop = P_MOVS;	/* MOVE R,[flt] into MOVSI R, (flt) */
		    break;
		default:			/* Always big otherwise */
		    big = 1;
		    break;
		}
	    outop (p->Pop);
	    if (!big)
		outc ('I');
	    outreg (p->Preg);
	    outc (big ? '[' : ' (');
#ifdef  __COMPILER_KCC__		/* native mode */
	    outnum (* (INT *) (&p->Pfloat));	/* Pass float as INT val */
#else					/* host may not be PDP-10! */
	    if (big)
		outmpdbl ((INT *) &p->Pdouble, 3);
	    else
		outmpdbl ((INT *) &p->Pfloat, 1);
#endif
	    outc (big ? ']' : ')');

	/* Add a readable comment so humans can understand what the floating
	 * constant is.  However, because this is slow, only do it when
	 * we know the assembler output is going to stay around.
	 */
	    if (!delete)			/* If keeping asm file around, */
		fprintf (out,"\t; %.20g",p->Pfloat);	/* add comment for humans */
	    break;

	case PTA_DCONST1:		/* Double-word floating constant */
	case PTA_DCONST2:
	    i = ((p->Ptype)&PTF_ADRMODE) == PTA_DCONST1 ? 1 : 2;
	    outop (p->Pop);
	    outreg (p->Preg);
	    outc ('[');
	    if (tgmachuse.mapdbl)		/* If target mach fmt is different */
		outmpdbl ((INT *)&p->Pdouble, i);/* Output part of mapped double */
	    else
		outnum (i == 1 ? p->Pdouble1 : p->Pdouble2);
	    outc (']');

	    if (!delete)			/* If keeping asm file around, */
		fprintf (out,"\t; %.20g", p->Pdouble); /* add comment for humans */
	    break;

	case PTA_DCONST:		/* Double-word floating constant */
	    outop (p->Pop);
	    outreg (p->Preg);
	    if (p->Pdouble == 0)		/* Hack: if a double zero, */
		{
		outstr (crtsnam[CRT_ZERO]);	/* Use universal constant location. */
		crtref[CRT_ZERO]++;
		}
	    else if (tgmachuse.mapdbl)	/* If target mach fmt is different */
		{
		outc ('[');
		outmpdbl ((INT *) &p->Pdouble, 3);	/* Output mapped double */
		outc (']');
		}
	    else
		{
		outc ('[');
		outnum (p->Pdouble1);
		outnl ();

⌨️ 快捷键说明

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