Example #1
0
/*
 * Write out the upper address, like the upper register of a 2-register
 * reference, or the next memory location.
 */
void
upput(NODE * p, int size)
{

	size /= SZCHAR;
	switch (p->n_op) {
	case REG:
		if (GCLASS(p->n_rval) == CLASSB || GCLASS(p->n_rval) == CLASSC)
			print_reg64name(stdout, p->n_rval, 1);
		else
			printf("%s", rnames[p->n_rval]);
		break;

	case NAME:
	case OREG:
		setlval(p, getlval(p) + size);
		adrput(stdout, p);
		setlval(p, getlval(p) - size);
		break;
	case ICON:
		printf(CONFMT, getlval(p) >> 32);
		break;
	default:
		comperr("upput bad op %d size %d", p->n_op, size);
	}
}
Example #2
0
/*
 * Compare two trees; return 1 if equal and 0 if not.
 */
int
treecmp(NODE *p1, NODE *p2)
{
	if (p1->n_op != p2->n_op)
		return 0;

	switch (p1->n_op) {
	case SCONV:
	case UMUL:
		return treecmp(p1->n_left, p2->n_left);

	case OREG:
		if (getlval(p1) != getlval(p2) || p1->n_rval != p2->n_rval)
			return 0;
		break;

	case NAME:
	case ICON:
		if (strcmp(p1->n_name, p2->n_name))
			return 0;
		/* FALLTHROUGH */
		if (getlval(p1) != getlval(p2))
			return 0;
		break;

	case TEMP:
#ifdef notyet
		/* SSA will put assignment in separate register */
		/* Help out by accepting different regs here */
		if (xssa)
			break;
#endif
	case REG:
		if (p1->n_rval != p2->n_rval)
			return 0;
		break;
	case LS:
	case RS:
	case PLUS:
	case MINUS:
	case MUL:
	case DIV:
		if (treecmp(p1->n_left, p2->n_left) == 0 ||
		    treecmp(p1->n_right, p2->n_right) == 0)
			return 0;
		break;

	default:
		return 0;
	}
	return 1;
}
Example #3
0
/*
 * Turn a UMUL-referenced node into OREG.
 * Be careful about register classes, this is a place where classes change.
 */
void
offstar(NODE *p, int shape)
{
	NODE *r;

	if (x2debug)
		printf("offstar(%p)\n", p);

	if (isreg(p))
		return; /* Is already OREG */

	r = p->n_right;
	if( p->n_op == PLUS || p->n_op == MINUS ){
		if( r->n_op == ICON ){
			if (isreg(p->n_left) == 0)
				(void)geninsn(p->n_left, INAREG);
			/* Converted in ormake() */
			return;
		}
		if (r->n_op == LS && r->n_right->n_op == ICON &&
		    getlval(r->n_right) == 2 && p->n_op == PLUS) {
			if (isreg(p->n_left) == 0)
				(void)geninsn(p->n_left, INAREG);
			if (isreg(r->n_left) == 0)
				(void)geninsn(r->n_left, INAREG);
			return;
		}
	}
	(void)geninsn(p, INAREG);
}
Example #4
0
void
conput(FILE *fp, NODE *p)
{
	int val = getlval(p);

	switch (p->n_op) {
	case ICON:
		if (p->n_name[0] != '\0') {
			fprintf(fp, "%s", p->n_name);
			if (getlval(p))
				fprintf(fp, "+%d", val);
		} else
			fprintf(fp, "%d", val);
		return;

	default:
		comperr("illegal conput");
	}
}
Example #5
0
void
adrput(FILE *io, NODE *p)
{
	int r;

	/* output an address, with offsets, from p */
	switch (p->n_op) {
	case NAME:
		if (getlval(p))
			fprintf(io, CONFMT "%s", getlval(p),
			    *p->n_name ? "+" : "");
		if (p->n_name[0])
			printf("%s", p->n_name);
		else
			comperr("adrput");
		return;

	case OREG:
		r = p->n_rval;
		
		if (getlval(p))
			fprintf(io, CONFMT "%s", getlval(p),
			    *p->n_name ? "+" : "");
		if (p->n_name[0])
			printf("%s", p->n_name);
		if (R2TEST(r)) {
			int r1 = R2UPK1(r);
			int r2 = R2UPK2(r);
			int sh = R2UPK3(r);

			fprintf(io, "(%s,%s,%d)", 
			    r1 == MAXREGS ? "" : rnames[r1],
			    r2 == MAXREGS ? "" : rnames[r2], sh);
		} else
			fprintf(io, "(%s)", rnames[p->n_rval]);
		return;
	case ICON:
		/* addressable value of the constant */
		if (p->n_type == LONGLONG || p->n_type == ULONGLONG) {
			fprintf(io, "#" CONFMT, getlval(p) >> 32);
		} else {
Example #6
0
void
adrput(FILE * io, NODE * p)
{
	/* output an address, with offsets, from p */

	if (p->n_op == FLD)
		p = p->n_left;

	switch (p->n_op) {

	case NAME:
		if (p->n_name[0] != '\0')
			fputs(p->n_name, io);
		if (getlval(p) != 0)
			fprintf(io, "+" CONFMT, getlval(p));
		return;

	case OREG:
		if (getlval(p))
			fprintf(io, "%d", (int) getlval(p));
		fprintf(io, "(%s)", rnames[p->n_rval]);
		return;

	case ICON:
		/* addressable value of the constant */
		conput(io, p);
		return;

	case REG:
		if (GCLASS(p->n_rval) == CLASSB || GCLASS(p->n_rval) == CLASSC)
			print_reg64name(io, p->n_rval, 0);
		else
			fputs(rnames[p->n_rval], io);
		return;

	default:
		comperr("illegal address, op %d, node %p", p->n_op, p);
		return;

	}
}
Example #7
0
/*
 * Write out the upper address, like the upper register of a 2-register
 * reference, or the next memory location.
 */
void
upput(NODE *p, int size)
{
	switch (p->n_op) {
	case REG:
		printf("%%%s", &rnames[p->n_rval][2]);
		break;
	case NAME:
	case OREG:
		setlval(p, getlval(p) + 4);
		adrput(stdout, p);
		setlval(p, getlval(p) - 4);
		break;

	case ICON:
		printf("#%d", (int)getlval(p));
		break;

	default:
		comperr("upput bad op %d size %d", p->n_op, size);
	}
}
Example #8
0
/*
 * Take integer absolute value.
 * Simply does: ((((x)>>(8*sizeof(x)-1))^(x))-((x)>>(8*sizeof(x)-1)))
 */
static NODE *
builtin_abs(const struct bitable *bt, NODE *a)
{
	NODE *p, *q, *r, *t, *t2, *t3;
	int tmp1, tmp2, shift;

	if (a->n_type != INT)
		a = cast(a, INT, 0);

	if (a->n_op == ICON) {
		if (getlval(a) < 0)
			setlval(a, -getlval(a));
		p = a;
	} else {
		t = tempnode(0, a->n_type, a->n_df, a->n_ap);
		tmp1 = regno(t);
		p = buildtree(ASSIGN, t, a);

		t = tempnode(tmp1, a->n_type, a->n_df, a->n_ap);
		shift = (int)tsize(a->n_type, a->n_df, a->n_ap) - 1;
		q = buildtree(RS, t, bcon(shift));

		t2 = tempnode(0, a->n_type, a->n_df, a->n_ap);
		tmp2 = regno(t2);
		q = buildtree(ASSIGN, t2, q);

		t = tempnode(tmp1, a->n_type, a->n_df, a->n_ap);
		t2 = tempnode(tmp2, a->n_type, a->n_df, a->n_ap);
		t3 = tempnode(tmp2, a->n_type, a->n_df, a->n_ap);
		r = buildtree(MINUS, buildtree(ER, t, t2), t3);

		p = buildtree(COMOP, p, buildtree(COMOP, q, r));
	}

	return p;
}
Example #9
0
static void
shiftop(NODE *p)
{
	NODE *r = p->n_right;
	TWORD ty = p->n_type;

	if (p->n_op == LS && r->n_op == ICON && getlval(r) < 32) {
		expand(p, INBREG, "\tsrl A1,AL,");
		printf(CONFMT "\t# 64-bit left-shift\n", 32 - getlval(r));
		expand(p, INBREG, "\tsll U1,UL,AR\n");
		expand(p, INBREG, "\tor U1,U1,A1\n");
		expand(p, INBREG, "\tsll A1,AL,AR\n");
	} else if (p->n_op == LS && r->n_op == ICON && getlval(r) < 64) {
		expand(p, INBREG, "\tli A1,0\t# 64-bit left-shift\n");
		expand(p, INBREG, "\tsll U1,AL,");
		printf(CONFMT "\n", getlval(r) - 32);
	} else if (p->n_op == LS && r->n_op == ICON) {
		expand(p, INBREG, "\tli A1,0\t# 64-bit left-shift\n");
		expand(p, INBREG, "\tli U1,0\n");
	} else if (p->n_op == RS && r->n_op == ICON && getlval(r) < 32) {
		expand(p, INBREG, "\tsll U1,UL,");
		printf(CONFMT "\t# 64-bit right-shift\n", 32 - getlval(r));
		expand(p, INBREG, "\tsrl A1,AL,AR\n");
		expand(p, INBREG, "\tor A1,A1,U1\n");
		if (ty == LONGLONG)
			expand(p, INBREG, "\tsra U1,UL,AR\n");
		else
			expand(p, INBREG, "\tsrl U1,UL,AR\n");
	} else if (p->n_op == RS && r->n_op == ICON && getlval(r) < 64) {
		if (ty == LONGLONG) {
			expand(p, INBREG, "\tsra U1,UL,31\t# 64-bit right-shift\n");
			expand(p, INBREG, "\tsra A1,UL,");
		}else {
			expand(p, INBREG, "\tli U1,0\t# 64-bit right-shift\n");
			expand(p, INBREG, "\tsrl A1,UL,");
		}
		printf(CONFMT "\n", getlval(r) - 32);
	} else if (p->n_op == LS && r->n_op == ICON) {
		expand(p, INBREG, "\tli A1,0\t# 64-bit right-shift\n");
		expand(p, INBREG, "\tli U1,0\n");
	} else {
		comperr("shiftop");
	}
}
Example #10
0
/*
 * Special shapes.
 */
int
special(NODE *p, int shape)
{
	int o = p->n_op;

	if (o != ICON || p->n_name[0] != 0)
		return SRNOPE;

	switch(shape) {
	case SPCON:
		if ((getlval(p) & ~0xffff) == 0)
			return SRDIR;
		break;
	}

	return SRNOPE;
}
Example #11
0
/*
 * Do the actual conversion of offstar-found OREGs into real OREGs.
 */
void
myormake(NODE *q)
{
	NODE *p, *r;

	if (x2debug)
		printf("myormake(%p)\n", q);

	p = q->n_left;
	if (p->n_op == PLUS && (r = p->n_right)->n_op == LS &&
	    r->n_right->n_op == ICON && getlval(r->n_right) == 2 &&
	    p->n_left->n_op == REG && r->n_left->n_op == REG) {
		q->n_op = OREG;
		setlval(q, 0);
		q->n_rval = R2PACK(p->n_left->n_rval, r->n_left->n_rval, 0);
		tfree(p);
	}
}
Example #12
0
void
conput(FILE *fp, NODE *p)
{
	long val = getlval(p);

	if (p->n_type <= UCHAR)
		val &= 255;
	else if (p->n_type <= USHORT)
		val &= 65535;

	switch (p->n_op) {
	case ICON:
		fprintf(fp, "%ld", val);
		if (p->n_name[0])
			printf("+%s", p->n_name);
		break;

	default:
		comperr("illegal conput, p %p", p);
	}
}
Example #13
0
/*
 * Structure assignment.
 */
static void
stasg(NODE *p)
{
	assert(p->n_right->n_rval == A1);
	/* A0 = dest, A1 = src, A2 = len */
	printf("\tli %s,%d\t# structure size\n", rnames[A2],
	    attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0));
	if (p->n_left->n_op == OREG) {
		printf("\taddiu %s,%s," CONFMT "\t# dest address\n",
		    rnames[A0], rnames[p->n_left->n_rval],
		    getlval(p->n_left));
	} else if (p->n_left->n_op == NAME) {
		printf("\tla %s,", rnames[A0]);
		adrput(stdout, p->n_left);
		printf("\n");
	}
	printf("\tsubu %s,%s,16\n", rnames[SP], rnames[SP]);
	printf("\tjal %s\t# structure copy\n", exname("memcpy"));
	printf("\tnop\n");
	printf("\taddiu %s,%s,16\n", rnames[SP], rnames[SP]);
}
Example #14
0
/*
 * If we're big endian, then all OREG loads of a type
 * larger than the destination, must have the
 * offset changed to point to the correct bytes in memory.
 */
static void
offchg(NODE *p, void *arg)
{
	NODE *l;

	if (p->n_op != SCONV)
		return;

	l = p->n_left;

	if (l->n_op != OREG)
		return;

	switch (l->n_type) {
	case SHORT:
	case USHORT:
		if (DEUNSIGN(p->n_type) == CHAR)
			setlval(l, getlval(l) + 1);
		break;
	case LONG:
	case ULONG:
	case INT:
	case UNSIGNED:
		if (DEUNSIGN(p->n_type) == CHAR)
			setlval(l, getlval(l + 3));
		else if (DEUNSIGN(p->n_type) == SHORT)
			setlval(l, getlval(l + 2));
		break;
	case LONGLONG:
	case ULONGLONG:
		if (DEUNSIGN(p->n_type) == CHAR)
			setlval(l, getlval(l + 7));
		else if (DEUNSIGN(p->n_type) == SHORT)
			setlval(l, getlval(l + 6));
		else if (DEUNSIGN(p->n_type) == INT ||
		    DEUNSIGN(p->n_type) == LONG)
			setlval(l, getlval(l + 4));
		break;
	default:
		comperr("offchg: unknown type");
		break;
	}
}
Example #15
0
/*
 * return true if shape is appropriate for the node p
 *
 * Return values:
 * SRNOPE  Cannot match this shape.
 * SRDIR   Direct match, may or may not traverse down.
 * SRREG   Will match if put in a regster XXX - kill this?
 */
int
tshape(NODE *p, int shape)
{
	int o, mask;

	o = p->n_op;

#ifdef PCC_DEBUG
	if (s2debug)
		printf("tshape(%p, %s) op = %s\n", p, prcook(shape), opst[o]);
#endif

	if (shape & SPECIAL) {

		switch (shape) {
		case SZERO:
		case SONE:
		case SMONE:
		case SSCON:
		case SCCON:
			if (o != ICON || p->n_name[0])
				return SRNOPE;
			if (getlval(p)== 0 && shape == SZERO)
				return SRDIR;
			if (getlval(p) == 1 && shape == SONE)
				return SRDIR;
			if (getlval(p) == -1 && shape == SMONE)
				return SRDIR;
			if (getlval(p) > -257 && getlval(p) < 256 &&
			    shape == SCCON)
				return SRDIR;
			if (getlval(p) > -32769 && getlval(p) < 32768 &&
			    shape == SSCON)
				return SRDIR;
			return SRNOPE;

		case SSOREG:	/* non-indexed OREG */
			if (o == OREG && !R2TEST(p->n_rval))
				return SRDIR;
			return SRNOPE;

		default:
			return (special(p, shape));
		}
	}

	if (shape & SANY)
		return SRDIR;

	if ((shape&INTEMP) && shtemp(p)) /* XXX remove? */
		return SRDIR;

	if ((shape&SWADD) && (o==NAME||o==OREG))
		if (BYTEOFF(getlval(p)))
			return SRNOPE;

	switch (o) {

	case NAME:
		if (shape & SNAME)
			return SRDIR;
		break;

	case ICON:
	case FCON:
		if (shape & SCON)
			return SRDIR;
		break;

	case FLD:
		if (shape & SFLD)
			return flshape(p->n_left);
		break;

	case CCODES:
		if (shape & SCC)
			return SRDIR;
		break;

	case REG:
	case TEMP:
		mask = PCLASS(p);
		if (shape & mask)
			return SRDIR;
		break;

	case OREG:
		if (shape & SOREG)
			return SRDIR;
		break;

	case UMUL:
#if 0
		if (shumul(p->n_left) & shape)
			return SROREG;	/* Calls offstar to traverse down */
		break;
#else
		return shumul(p->n_left, shape);
#endif

	}
	return SRNOPE;
}
Example #16
0
/*
 * generate code by interpreting table entry
 */
void
expand(NODE *p, int cookie, char *cp)
{
	CONSZ val;

#if 0
	printf("expand\n");
	fwalk(p, e2print, 0);
#endif

	for( ; *cp; ++cp ){
		switch( *cp ){

		default:
			putchar(*cp);
			continue;  /* this is the usual case... */

		case 'Z':  /* special machine dependent operations */
			zzzcode( p, *++cp );
			continue;

		case 'F':  /* this line deleted if FOREFF is active */
			if (cookie & FOREFF) {
				while (*cp && *cp != '\n')
					cp++;
				if (*cp == 0)
					return;
			}
			continue;

		case 'S':  /* field size */
			if (fldexpand(p, cookie, &cp))
				continue;
			printf("%d", FLDSZ(p->n_rval));
			continue;

		case 'H':  /* field shift */
			if (fldexpand(p, cookie, &cp))
				continue;
			printf("%d", FLDSHF(p->n_rval));
			continue;

		case 'M':  /* field mask */
		case 'N':  /* complement of field mask */
			if (fldexpand(p, cookie, &cp))
				continue;
			val = 1;
			val <<= FLDSZ(p->n_rval);
			--val;
			val <<= FLDSHF(p->n_rval);
			adrcon( *cp=='M' ? val : ~val );
			continue;

		case 'L':  /* output special label field */
			if (*++cp == 'C')
				printf(LABFMT, p->n_label);
			else
				printf(LABFMT, (int)getlval(getlr(p,*cp)));
			continue;

		case 'O':  /* opcode string */
#ifdef FINDMOPS
			if (p->n_op == ASSIGN)
				hopcode(*++cp, p->n_right->n_op);
			else
#endif
			hopcode( *++cp, p->n_op );
			continue;

		case 'B':  /* byte offset in word */
			val = getlval(getlr(p,*++cp));
			val = BYTEOFF(val);
			printf( CONFMT, val );
			continue;

		case 'C': /* for constant value only */
			conput(stdout, getlr( p, *++cp ) );
			continue;

		case 'I': /* in instruction */
			insput( getlr( p, *++cp ) );
			continue;

		case 'A': /* address of */
			adrput(stdout, getlr( p, *++cp ) );
			continue;

		case 'U': /* for upper half of address, only */
			upput(getlr(p, *++cp), SZLONG);
			continue;

			}

		}

	}