Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - c/kcc5/parith.c
There are no other files named parith.c in the archive.
/* Program to check various pointer arithmetic algorithms for
** all sizes of byte pointers.
*/
#if 0
	Currently the best candidate is:

	Known format/size	Unknown format/size
				SKIPL 16,A
				 LSH 16,6
				LSH 16,-30.	; Get size or PS
	SUB A,B			SUB A,B
	MULI A,bpw<<bits	MUL A,$BPMUL(16)	; 64-wd table
	LSH A+1,-bits		LSH A+1,@$BPLSH(16)	; 64-wd table
				ADD A,$BPADD(16)	; 64-wd table
	ADD A+1,<table>(A)	ADD A+1,(A)

Unknown format/Known size	Known format/unknown size
				LDB 16,[$$BPSZ,,A]	; get PS from A
	SUB A,B			SUB A,B
	MULI A,$$BPMn		MUL A,$BPMUL(16)
	LSH A+1,$$BSHF		LSH A+1,$$BSHF
				ADD A,$BPTAB(16)
	ADD A+1,$BPTBn(A)	ADD A+1,(A)
#endif
#include <stdio.h>

struct bptr {
	int badrsiz;	/* # bits in a word address */
	int bsize;	/* Byte size */
	int bpw;	/* Bytes per word */
	int blh;	/* Initial LH for byte pointer */
	int bmul;	/* Multiplier for MULI (if 0 uses bpw) */
	int bshf;	/* Shift value for LSH/ASH */
			/* If zero, uses CAIGE test instead */
			/* If non-zero, multiplier is bpw*(1<<bshf) */
	int bcases;	/* # cases stored below */
	struct cresult {	/* Result of each test case */
		int cdif;	/* Desired difference (must == cadd+cval) */
		int cidx;	/* Index obtained in R */
		int cval;	/* Value obtained in R+1 */
		int cadd;	/* Bits to add to produce desired diff */
	} bcase[4*6];	/* Enough room for handling 6 bytes/word */
};

/* Local pointers */
struct bptr b6  = { 18, 6, 6, 0360600, 0, 1};
struct bptr b7  = { 18, 7, 5, 0350700, 0, 1};
struct bptr b8  = { 18, 8, 4, 0341000, 0, 1};	/* Use shift */
struct bptr b9  = { 18, 9, 4, 0331100, 0, 1};
struct bptr b18 = { 18,18, 2, 0222200, 0, 1};

/* Extended pointers */
struct bptr xb6  = { 23, 6, 6, 0460000,  0, 5, };
struct bptr xb7  = { 23, 7, 5, 0620000,  0, 5, };
struct bptr xb8  = { 23, 8, 4, 0550000,  0, 5, };
struct bptr xb9  = { 23, 9, 4, 0700000,  0, 5, };
struct bptr xb18 = { 23,18, 2, 0750000,  0, 5, };

struct bptr *alltab[] = {
	&b6, &b7, &b8, &b9, &b18,
	&xb6, &xb7, &xb8, &xb9, &xb18,
	0
};

#define TABSIZ 256
int junk[TABSIZ];		/* Handle negative indices */
int asmtab[TABSIZ];	/* Table for outputting assembler stuff */
int junk2[TABSIZ];
int usetab[TABSIZ];	/* Another table to count usages */

struct dint {int hi; int lo;};	/* For hacking double-word int stuff */
struct dint mult();

int ashflag = 1;	/* True to use ASH instead of LSH */
int dmpflag = 1;	/* True to dump results in assembler table form */
int nerrs = 0;		/* # errors seen */
main()
{
	struct bptr **pp;

	for (pp = alltab; *pp; ++pp)
		dotest(*pp);

	if (dmpflag)
		for (pp = alltab; *pp; ++pp)
			dodmp(*pp);
}
dotest(p)
struct bptr *p;
{
	int i, j;
	int saverrs = nerrs;

	p->bcases = 0;
	if (p->bmul == 0) p->bmul = p->bpw;
	if (p->bshf != 0) p->bmul <<= p->bshf;

	printf("Checking %d-bit BP, LH=0%o, MULI r,0%o, ",
			p->bsize, p->blh, p->bmul);
	if (p->bshf) printf("%s r+1,%d.\n",
			ashflag ? "ASH" : "LSH", -p->bshf);
	else printf("CAIGE/ADDI of index\n");

	/* Check case of +B,+W */
	for (i=0; i < p->bpw; ++i)
		pcase(p, 1, 0, i);
	printf("\t------\n");

	/* Check case of +B,-W */
	for (i=0; i < p->bpw; ++i)
		pcase(p, 1, 0, p->bpw+i);
	printf("\t------\n");

	/* Check case of -B,+W */
	for (i=0; i < p->bpw; ++i)
		pcase(p, 1, p->bpw-1, (p->bpw-1)-i);
	printf("\t------\n");

	/* Check case of -B,-W */
	for (i=0; i < p->bpw; ++i)
		pcase(p, 1, p->bpw-1, p->bpw+(p->bpw-1)-i);

	if (nerrs != saverrs)
	  {	printf("BAD params, %d index conflicts!\n\n", nerrs-saverrs);
		return;
	  }
	printf("Looks good, no conflicting indices!  Testing...\n");

	/* Now apply some more exhaustive testing to the created table. */
	for (i = 0; i < 20; ++i) for (j = 0; j < 20; ++j)
		pcase(p, 0, i, j);

	/* Finally check out the maximum values */
	i = (1 << p->badrsiz) * p->bpw;	/* # of bytes in address space */
	pcase(p, 0, i-1, 0);
	pcase(p, 0, 0, i-1);

	if (nerrs != saverrs)
		printf("BAD params, %d test blunders!\n\n", nerrs-saverrs);
	else printf("CORRECT - all tests passed!\n\n");
}
pcase(p, pflag, inc1, inc2)
struct bptr *p;
int pflag;		/* True if printing results (else verifying) */
{
	int i;
	char *bp1, *bp2;
	unsigned int reg;
	struct dint dreg;
	unsigned int shfres, adres;
	int tabdif, tabidx, tabent;
	struct cresult *pres0 = &p->bcase[0];	/* Start of cases thus far */
	struct cresult *pres;			/* Current test case */
	int rcase = p->bcases;			/* idx of this case */

	pres = pres0 + rcase;

	/* Make the BPs to subtract */
	bp1 = bp2 = (char *)(p->blh<<18);	/* Get BP to word 0 */
	bp1 += inc1;				/* Use ADJBP on it */
	bp2 += inc2;				/* ditto */
	tabdif = inc1 - inc2;			/* This is desired result */

	reg = (int)bp1 - (int)bp2;	/* Now get subtraction result */
	dreg = mult(reg, p->bmul);	/* And result of MUL on that */

	if (pflag) printf(" %2d-%-2d = %6o,,%6o *%-2o=>%3d.",
		inc1, inc2, reg>>18, reg&0777777, p->bmul, dreg.hi);
	if (p->bshf)
	  {
		shfres = ashflag ?
			  (dreg.lo) >> p->bshf		/* ASH */
			: ((unsigned)dreg.lo) >> p->bshf;	/* LSH */
		tabidx = dreg.hi;
	  }
	else {
		shfres = dreg.lo;
		tabidx = (dreg.lo < 0 ? dreg.hi+1 : dreg.hi);
		if (pflag) printf("(%2d)", tabidx);
	  }
	tabent = tabdif - shfres;		/* Get # to add up */
	if (pflag)
	  {	printf(" ? %6o,,%6o + ", shfres>>18, shfres&0777777);
		if (tabent & 0777000000)	/* Would neg look better? */
			printf("-%6o,,%6o",
				((unsigned)-tabent)>>18, (-tabent)&0777777);
		else printf(" %6o,,%6o",
				((unsigned)tabent)>>18, tabent&0777777);

		printf(" = %d", shfres+tabent);
		if ((shfres+tabent) != tabdif)
			printf(" BAD! (%d)", inc1-inc2);
		printf("\n");
	  }

	/* Now store results of this case, and compare against all previous
	** cases to see whether we have an unique combination of index and
	** tabel-entry.
	*/
	if (pflag)
	  {	pres->cdif = tabdif;
		pres->cidx = tabidx;
		pres->cval = shfres;
		pres->cadd = tabent;
		p->bcases++;		/* Bump up count of cases */
	  }
	for (pres = pres0, i = 0; i < rcase; ++i, ++pres)
	  {	if (pres->cidx == tabidx	/* If prev case w/same idx*/
		  && pres->cadd != tabent)	/* should have same entry! */
		  {
			adres = shfres + pres->cadd;
			if (pflag)
				printf("\t\tWARNING - index conflicts with case %d\n",
					pres - pres0);
			else printf("\
\tBAD TEST: %d-%d = %d is actually: %d ? %o,,%o + %o,,%o = %o,,%o (%d)\n",
				inc1, inc2, tabdif, tabidx,
				shfres>>18, shfres&0777777,
				(unsigned)(pres->cadd)>>18, pres->cadd&0777777,
				adres >> 18, adres&0777777, adres);
			nerrs++;
		  }
	  }
}


struct dint
mult(rval, size)
{
asm("	MOVE 1,-1(17)	; Get 1st arg \n\
	MUL 1,-2(17)	; do a MUL by 2nd arg and return the doublewd val.\n");
}
dodmp(p)
struct bptr *p;
{
	int minidx = 0, maxidx = 0;
	int i, x;

	/* Clear table and start installing values */
	for (i = -(TABSIZ-1); i < TABSIZ; ++i)
		usetab[i] = asmtab[i] = 0;
	
	for (i = 0; i < p->bcases; ++i) {
		x = p->bcase[i].cidx;
		if (x >= TABSIZ || x <= -TABSIZ) {
			printf("Error, index of %d too big!\n", x);
			continue;
		}
		if (x > maxidx) maxidx = x;
		if (x < minidx) minidx = x;
		asmtab[x] = p->bcase[i].cadd;
		usetab[x]++;
	}

	/* OK, now print out table! */
	printf("\t/* %2d-bit %s-format P_SUBBP fixup table */\n\n",
		p->bsize, (p->blh&07700 ? "local" : "OWGBP"));
	for (i = minidx; i <= maxidx; ++i)
	  {	if((x = asmtab[i])&0777000000)
		    printf("\t-<%o,,%o>", ((unsigned)-x)>>18, (-x)&0777777);
		else if (x)
		    printf("\t<%o,,%o>", ((unsigned) x)>>18,   x &0777777);
		else printf("\t0 ;unused");
		printf("\t; %d.\n", i);
	  }
	printf("\n\n");
}