Beispiel #1
0
/*}}}*/
PRIVATE void tbinchop (const int low, const int high)
{
	const int midpoint = (high + low) / 2;
	const int thislabel = newlab ();
	caseentry *thisselection = &(casetable[midpoint]);
	treenode *snode;
	/* Jump if exp <= value */
	const int old = switch_to_temp_workspace ();
	snode = newdopnode (S_GR, NOPOSN, selectorexp, thisselection->selectionexp, selectortype);
	switch_to_prev_workspace (old);
	tguard (snode, TRUE, thislabel);	/*        selectorexp          */
	/*        ldc   selection      */
	/*        gt                   */
	/*        cj    thislabel      */
	/* At this point, we know exp > value */
	tjumptable (midpoint + 1, high, TRUE);	/*        ...  higher cases    */
	setlab (thislabel);	/* thislabel:                  */
	tjumptable (low, midpoint, TRUE);	/*        ...  lower cases     */
}
Beispiel #2
0
static void
assemble()
{
    int v[501];
    int f = 0;
    int i;

    Labv = v;
clear:
    for (i = 0; i <= 500; i++) Labv[i] = 0;
    Cp = 0;
next:
    rch();
sw:
    switch (Ch) {

    default: if (Ch == EOF) return;
        printf("\nBAD CH %c AT P = %d\n", Ch, P);
        goto next;

    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
        setlab(rdn());
        Cp = 0;
        goto sw;

    case '$': case ' ': case '\n': goto next;

    case 'L': f = 0; break;
    case 'S': f = 1; break;
    case 'A': f = 2; break;
    case 'J': f = 3; break;
    case 'T': f = 4; break;
    case 'F': f = 5; break;
    case 'K': f = 6; break;
    case 'X': f = 7; break;

    case 'C': rch(); stc(rdn()); goto sw;

    case 'D': rch();
        if (Ch == 'L') {
            rch();
            stw(0);
            labref(rdn(), P - 1);
        } else
            stw(rdn());
        goto sw;

    case 'G': rch();
        A = rdn() + G;
        if (Ch == 'L') rch();
        else printf("\nBAD CODE AT P = %d\n", P);
        M[A] = 0;
        labref(rdn(), A);
        goto sw;
    case 'Z': for (i = 0; i <= 500; i++)
        if (Labv[i] > 0) printf("L%d UNSET\n", i);
        goto clear;
    }
    W = f << FSHIFT;
    rch();
    if (Ch == 'I') { W = W + IBIT; rch(); }
    if (Ch == 'P') { W = W + PBIT; rch(); }
    if (Ch == 'G') { W = W + GBIT; rch(); }

    if (Ch == 'L') {
        rch();
        stw(W + DBIT);
        stw(0);
        labref(rdn(), P - 1);
    } else {
        int a = rdn();
        if ((a & ABITS) == a)
            stw(W + a);
        else { stw(W + DBIT); stw(a); }
    }
    goto sw;
}
Beispiel #3
0
/*****************************************************************************
 *
 *  tcase generates code for a case process tptr
 *
 *****************************************************************************/
PUBLIC void tcase (treenode * tptr)
{
	/*{{{  save globals */
	caseentry *const oldcasetable = casetable;
	const int olddefaultlab = defaultlab;
	const int olddefaultjumpdest = defaultjumpdest;
	const int oldselectortype = selectortype;
	treenode *const oldselectorexp = selectorexp;
	/*}}} */
	BOOL makedefault = TRUE;
	treenode *selectionlist = RHSOf (tptr);
	const int joinlab = newlab ();
	int maxcase = 0;
	treenode *defaultp = NULL;
	/*{{{  initialise globals */
	defaultlab = NO_LABEL;
	defaultjumpdest = FALSE;
	selectorexp = LHSOf (tptr);
	selectortype = ntypeof (selectorexp);
	/* make sure that we don't call memalloc with zero bytes */
	casetable = (caseentry *) memalloc (sizeof (caseentry) * casesin (selectionlist) + 1);
	/*}}} */
	/*{{{  evaluate the selector, if neccessary */
	tpreexp (selectorexp);
	simplify (P_EXP, selectorexp);
	/*}}} */
	/*{{{  build up table of selections, and generate jumps into case body */
	{
		treenode *slist;
		for (slist = selectionlist; !EndOfList (slist); slist = NextItem (slist)) {
			treenode *thisselection = skipspecifications (ThisItem (slist));
			treenode *v = CondGuardOf (thisselection);
			const int l = newlab ();
			if (TagOf (v) == S_ELSE) {
				defaultlab = l;
				defaultp = ThisItem (slist);
				makedefault = FALSE;
			} else
				/*{{{  set up labels and values */
				for (; !EndOfList (v); v = NextItem (v)) {
					treenode *thisconstant = ThisItem (v);
					caseentry *caseentryptr = &(casetable[maxcase]);
					caseentryptr->label = l;
					caseentryptr->jumpdest = FALSE;
					caseentryptr->lowvalue = LoValOf (thisconstant);
					caseentryptr->highvalue = HiValOf (thisconstant);
					caseentryptr->selectionexp = thisconstant;
					caseentryptr->selectionp = ThisItem (slist);
					maxcase++;
				}
			/*}}} */
		}
		if (makedefault)
			defaultlab = newlab ();
#if 0
		sup_qsort (casetable, maxcase, sizeof (caseentry), fitsinword (selectortype) ? comparecases : doublecomparecases);
#else
		sup_qsort (casetable, maxcase, sizeof (caseentry), (bytesinscalar (selectortype) <= 4) ? comparecases : doublecomparecases);
#endif
		tjumptable (0, maxcase - 1, FALSE);
	}
	/*}}} */
	/*{{{  generate case body */
	{
		int casesdone = 0;
		/*{{{  generate default process */
		setlab (defaultlab);
		if (makedefault) {
			if (NEED_ERRORS)	/* bug TS/2071 29/01/93 */
				tstop (tptr);
		} else {
			if (defaultjumpdest)
				genstartblock ();
			tselection (defaultp, joinlab);
		}
		/*}}} */
		while (casesdone < maxcase) {
			treenode *thisprocess;
			int i;
			BOOL jdest;
			/* Find a process to generate */
			for (i = 0; (i < maxcase) && (casetable[i].selectionp == NULL); i++)
				/* skip */ ;
			thisprocess = casetable[i].selectionp;
			/* Generate thisprocess */
			setlab (casetable[i].label);
			jdest = casetable[i].jumpdest;
			/*{{{  find and delete other entries for this process */
			{
				int j;
				for (j = i + 1; j < maxcase; j++)
					if (casetable[j].selectionp == thisprocess) {
						/* Delete the process, so we only generate it once */
						jdest = jdest | casetable[j].jumpdest;
						casetable[j].selectionp = NULL;
						casesdone++;
					}
			}
			/*}}} */
			if (jdest)
				genstartblock ();
			tselection (thisprocess, joinlab);
			casetable[i].selectionp = NULL;
			casesdone++;
		}
		setlab (joinlab);
		genstartblock ();
	}
	/*}}} */
	/*{{{  restore globals */
	memfree (casetable);
	casetable = oldcasetable;
	defaultlab = olddefaultlab;
	defaultjumpdest = olddefaultjumpdest;
	selectortype = oldselectortype;
	selectorexp = oldselectorexp;
	/*}}} */
}
Beispiel #4
0
/*****************************************************************************
 *
 *  tjumptable generates the code for selecting cases given a sorted array
 *             of case values and labels.  Our case values are
 *             case[low .. high].
 *
 *****************************************************************************/
PRIVATE void tjumptable (const int low, const int high, const BOOL nomorejumptables)
{
	const int numcases = (high - low) + 1;
	const BOOL singlelength = fitsinword (selectortype);
#ifdef DEBUG
	{
		int i;

		DEBUG_MSG (("tjumptable: low: %d, high: %d, numcases: %d, nomorejumptables: %d\n", low, high, numcases, nomorejumptables));
		for (i = low; i <= high; i++) {
			DEBUG_MSG (("tjumptable: casetable[%2d].lowvalue = %8X\n", i, casetable[i].lowvalue));
		}
	}
#endif
	if ((numcases <= DELTA) || isquadlength (selectortype)) {
		/* bug INSdi02177 */
		/*{{{  too few cases - output jumps */
		int i;
		BOOL optimisedlast = FALSE;
		for (i = low; i < low + numcases; i++) {
			/*{{{  output a jump for casetable[i] */
			caseentry *thiscase = &(casetable[i]);
			const int old = switch_to_temp_workspace ();
			treenode *snode = newdopnode (S_EQ, NOPOSN, selectorexp, thiscase->selectionexp, selectortype);
			switch_to_prev_workspace (old);

			if ((i == high) && (thiscase->lowvalue != 0)
			    && (thiscase->lowvalue != MOSTNEG_INT32)
			    && fitsinword (selectortype)
			    && (!isinconstanttable (thiscase->selectionexp))) {
				/*{{{  optimise the last case */
				tguard (snode, TRUE, defaultlab);
				genbranch (I_J, thiscase->label);
				thiscase->jumpdest = TRUE;
				optimisedlast = TRUE;
				/*}}} */
			} else {
				tguard (snode, FALSE, thiscase->label);
			}
			/*}}} */
		}
		if (!optimisedlast) {
			genbranch (I_J, defaultlab);
			defaultjumpdest = TRUE;
		}
		/*}}} */
	} else {
		/*{{{  look for biggest jump table */
		int bestlow = 0;
		int besthigh = 0;
		int bestsize = 0;
		if (!nomorejumptables && (!singlelength || (numcases >= MIN_JTAB_SIZE)))
		{
			/*{{{  look for best jump table */
			int i, j;
			const int minjumps = singlelength ? MIN_JTAB_SIZE - 1 : DELTA;

			for (i = low; i < (low + numcases - DELTA); i++) {
				/*{{{  set j to minimum value possible for better subrange */
				j = i + ((bestsize > minjumps) ? bestsize : minjumps);
				/*}}} */
				/*{{{  test all possible subranges starting at i, ending at or past j */
				{
					const int maxaccept = ((high - i) + 1) * DENSITY;
					if (singlelength) {
						/*{{{  single length */
						while (j <= high) {
							/* bug TS/1589 - 04/11/92 this is a bug in gcc 1.36;
							   changing diff to be a BIT32 seems to fix the problem;
							   and is OK as a permanent work-around.
							 */
							/* bug TS/1575 05/11/92 - cast to BIT32 for unsigned arith */
							/*const INT32 diff = casetable[j].lowvalue - casetable[i].lowvalue); */
							/*const INT32 diff = (INT32)((BIT32)casetable[j].lowvalue - (BIT32)casetable[i].lowvalue); */
							const BIT32 diff = (BIT32) casetable[j].lowvalue - (BIT32) casetable[i].lowvalue;
							/*DEBUG_MSG(("i: %2d, j: %2d, lowvalue: %8X, diff: %8X\n",
							   i, j, casetable[j].lowvalue, diff)); */
/*if ((diff < 0) || (diff > maxaccept)) *//* TS/1589 04/11/92 */
							if (diff > (BIT32) maxaccept) {
								DEBUG_MSG (("tjumptable: bombing: diff: %8X\n", diff));
								j = high;	/* no chance so exit */
							} else {
								const int size = (j - i) + 1;
								DEBUG_MSG (("tjumptable: ok: diff: %8X\n", diff));
								if (diff <= (int) (DENSITY * size)) {	/* better subrange   */
									bestlow = i;
									besthigh = j;
									bestsize = size;
								}
							}
							j = j + 1;
						}
						/*}}} */
					} else {
						/*{{{  double length */
						while (j <= high) {
							BIT32 hdiff, ldiff;
							Int64Minus (&hdiff, &ldiff,
								    casetable[j].highvalue, casetable[j].lowvalue,
								    casetable[i].highvalue, casetable[i].lowvalue);
							if ((hdiff != 0) || (ldiff > maxaccept)) {
								j = high;	/* no chance so exit */
							} else {
								const int size = (j - i) + 1;
								if (ldiff <= (int) (DENSITY * size)) {	/* better subrange   */
									bestlow = i;
									besthigh = j;
									bestsize = size;
								}
							}
							j = j + 1;
						}
						/*}}} */
					}
				}
				/*}}} */
			}
			/*}}} */
		}
		if (bestsize == 0) {
			tbinchop (low, high);
		} else {
			/*{{{  do jump table */
			int lesslab = 0, greaterlab = 0;
			caseentry *lowestcase = &(casetable[bestlow]);
			caseentry *highestcase = &(casetable[besthigh]);

			DEBUG_MSG (("generating jump table: bestsize = %d\n", bestsize));
			/*{{{  test for below boundary */
			{
				treenode *lselnexp = lowestcase->selectionexp;
				if (!is_typed_mostneg (selectortype, LoValOf (lselnexp), HiValOf (lselnexp))) {
					int l;
					const int old = switch_to_temp_workspace ();
					treenode *snode = newdopnode (S_GE, NOPOSN, selectorexp, lselnexp, selectortype);
					switch_to_prev_workspace (old);

					if (bestlow == low)
						l = defaultlab;
					else {
						lesslab = newlab ();
						l = lesslab;
					}
					tguard (snode, TRUE, l);
				}
			}
			/*}}} */
			/*{{{  test for above boundary */
			{
				treenode *hselnexp = highestcase->selectionexp;
				if (!is_typed_mostpos (selectortype, LoValOf (hselnexp), HiValOf (hselnexp))) {
					int l;
					const int old = switch_to_temp_workspace ();
					treenode *snode = newdopnode (S_LE, NOPOSN, selectorexp, hselnexp, selectortype);
					switch_to_prev_workspace (old);

					if (besthigh == high)
						l = defaultlab;
					else {
						greaterlab = newlab ();
						l = greaterlab;
					}

					tguard (snode, TRUE, l);
				}
			}
			/*}}} */
			/*{{{  output jump table */
			{
#if 0
				const int jlab = newlab ();
				const int l = newlab ();
#endif
				treenode *snode;

				if (lowestcase->lowvalue != 0) {
					/*{{{  selectorexp; ldc lowvalue; diff */
					const int old = switch_to_temp_workspace ();
					snode = newdopnode (S_MINUS, NOPOSN,	/*           selectorexp           */
							    selectorexp,	/*           ldc   selection       */
							    lowestcase->selectionexp,	/*           diff                  */
							    S_INT);
					switch_to_prev_workspace (old);
					/*}}} */
				} else {
					/*{{{  selectorexp */
					snode = selectorexp;	/*           selectorexp           */
					/*}}} */
				}
				texp (snode, MANY_REGS);
#if 0
				/* subsumed into genstartjumptable to allow optimisation */
				genloadcasescale ();	/*           ldc   casescale       */
				/*{{{  T9000_gamma_badmul */
				if (T9000_gamma_badmul (&tx_global)) {
					gensecondary (I_NOP);
					gencomment0 ("Workaround a slow multiplier");
				}
				/*}}} */
				gensecondary (I_PROD);	/*           prod                  */
				genlabeldiff (I_LDC, jlab, l);	/*           ldc   jlab - l        */
				gensecondary (I_LDPI);	/*           ldpi                  */
				setlab (l);	/* l:                              */
				gensecondary (I_BSUB);	/*           bsub                  */
				gensecondary (I_GCALL);	/*           gcall                 */
				setlab (jlab);	/* jlab:                           */
#endif
				genstartjumptable ();	/* includes jump into table */
				genjumptableentry (I_J, lowestcase->label);
				lowestcase->jumpdest = TRUE;
				/*           j     lowestcase      */
				/*{{{  other cases                                     j     othercases .. */
				{
					int i;
					for (i = bestlow + 1; i <= besthigh; i++) {
						int j;
						/* bug TS/1575 05/11/92 - cast to BIT32 for unsigned arith */
						const int blanks = (int) ((BIT32) casetable[i].lowvalue - (BIT32) casetable[i - 1].lowvalue) - 1;

						for (j = 0; j < blanks; j++) {
							genjumptableentry (I_J, defaultlab);
							defaultjumpdest = TRUE;
						}
						genjumptableentry (I_J, casetable[i].label);
						casetable[i].jumpdest = TRUE;
					}
				}
				/*}}} */
				genendjumptable ();
				/*}}} */
			}
			if (bestlow > low) {
				/*{{{  case on lower values */
				setlab (lesslab);
				tjumptable (low, bestlow - 1, FALSE);
				/*}}} */
			}
			if (besthigh < high) {
				/*{{{  case on higher values */
				setlab (greaterlab);
				tjumptable (besthigh + 1, high, FALSE);
				/*}}} */
			}
			/*}}} */
		}
		/*}}} */
	}
}