Example #1
0
File: swt.c Project: 8l/inferno
void
bitstore(Node *b, int n1, int n2, int n3, int result, Node *nn)
{
	long v;
	Node *l;
	Type *t;
	int sh, g, gs;

	/*
	 * n1 has adjusted/masked value
	 * n2 has address of cell
	 * n3 has contents of cell
	 */
	t = tfield;

	l = b->left;
	g = regalloc(t, D_NONE);
	v = ~0 + (1L << b->type->nbits);
	gopcode(OAND, t, D_CONST, nodconst(v), n1, l);
	gmove(t, t, n1, l, g, l);
	if(result != D_NONE)
		gmove(t, nn->type, n1, l, result, nn);
	sh = b->type->shift;
	if(sh > 0) {
		if(sh >= 8) {
			gs = regalloc(t, D_NONE);
			gmove(t, t, D_CONST, nodconst(sh), gs, l);
			gopcode(OASHL, t, gs, l, g, l);
			regfree(gs);
		} else
			gopcode(OASHL, t, D_CONST, nodconst(sh), g, l);
	}
	v <<= sh;
	gopcode(OAND, t, D_CONST, nodconst(~v), n3, l);
	gopcode(OOR, t, n3, l, g, l);
	gmove(t, t, g, l, n2|I_INDIR, l);

	regfree(g);
	regfree(n1);
	regfree(n2);
	regfree(n3);
}
Example #2
0
void
lcgen(Node *n, Node *nn)
{
	Prog *p1;
	Node nod;

	if(debug['g']) {
		prtree(nn, "lcgen lhs");
		prtree(n, "lcgen");
	}
	if(n == Z || n->type == T)
		return;
	if(nn == Z) {
		nn = &nod;
		regalloc(&nod, n, Z);
	}
	switch(n->op) {
	default:
		if(n->addable < INDEXED) {
			diag(n, "unknown op in lcgen: %O", n->op);
			break;
		}
		nod = *n;
		nod.op = OADDR;
		nod.left = n;
		nod.right = Z;
		nod.type = types[TIND];
		gopcode(OAS, &nod, Z, nn);
		break;

	case OCOMMA:
		cgen(n->left, n->left);
		lcgen(n->right, nn);
		break;

	case OIND:
		cgen(n->left, nn);
		break;

	case OCOND:
		bcgen(n->left, 1);
		p1 = p;
		lcgen(n->right->left, nn);
		gbranch(OGOTO);
		patch(p1, pc);
		p1 = p;
		lcgen(n->right->right, nn);
		patch(p1, pc);
		break;
	}
}
Example #3
0
void
bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
{
	int sh;
	int32_t v;
	Node *l;

	/*
	 * n1 gets adjusted/masked value
	 * n2 gets address of cell
	 * n3 gets contents of cell
	 */
	l = b->left;
	if(n2 != Z) {
		regalloc(n1, l, nn);
		reglcgen(n2, l, Z);
		regalloc(n3, l, Z);
		gmove(n2, n3);
		gmove(n3, n1);
	} else {
		regalloc(n1, l, nn);
		cgen(l, n1);
	}
	if(b->type->shift == 0 && typeu[b->type->etype]) {
		v = ~0 + (1L << b->type->nbits);
		gopcode(OAND, tfield, nodconst(v), n1);
	} else {
		sh = 32 - b->type->shift - b->type->nbits;
		if(sh > 0)
			gopcode(OASHL, tfield, nodconst(sh), n1);
		sh += b->type->shift;
		if(sh > 0)
			if(typeu[b->type->etype])
				gopcode(OLSHR, tfield, nodconst(sh), n1);
			else
				gopcode(OASHR, tfield, nodconst(sh), n1);
	}
}
Example #4
0
void
usedset(Node *n, int o)
{
	if(n->op == OLIST) {
		usedset(n->left, o);
		usedset(n->right, o);
		return;
	}
	complex(n);
	switch(n->op) {
	case OADDR:	/* volatile */
		gopcode(OTST, types[TINT], D_TREE, n, D_NONE, Z);
		p->as = ANOP;
		break;
	case ONAME:
		if(o == OSET)
			gopcode(OTST, types[TINT], D_NONE, Z, D_TREE, n);
		else
			gopcode(OTST, types[TINT], D_TREE, n, D_NONE, Z);
		p->as = ANOP;
		break;
	}
}
Example #5
0
void
swit1(C1 *q, int nc, long def, Node *n, Node *tn)
{
	C1 *r;
	int i;
	Prog *sp;

	if(nc < 5) {
		for(i=0; i<nc; i++) {
			if(debug['W'])
				print("case = %.8lux\n", q->val);
			gmove(nodconst(q->val), tn);
			gopcode(OEQ, n, tn, Z);
			patch(p, q->label);
			q++;
		}
		gbranch(OGOTO);
		patch(p, def);
		return;
	}
	i = nc / 2;
	r = q+i;
	if(debug['W'])
		print("case > %.8lux\n", r->val);
	gmove(nodconst(r->val), tn);
	gopcode(OLT, tn, n, Z);
	sp = p;
	gopcode(OEQ, n, tn, Z);
	patch(p, r->label);
	swit1(q, i, def, n, tn);

	if(debug['W'])
		print("case < %.8lux\n", r->val);
	patch(sp, pc);
	swit1(r+1, nc-i-1, def, n, tn);
}
Example #6
0
File: swt.c Project: 8l/inferno
			/* else binary */
void
swit1(C1 *q, int nc, long def, int g, Node *n)
{
	C1 *r;
	int i;
	long v;
	Prog *sp1, *sp2;

	/* note that g and g+1 are not allocated */
	if(nc <= N1)
		goto linear;

	/*
	 * divide and conquer
	 */
	i = nc / 2;
	r = q+i;
	v = r->val;
	/* compare median */
	if(v >= -128 && v < 128) {
		gopcode(OAS, n->type, D_CONST, nodconst(v), g+1, n);
		gopcode(OEQ, n->type, g, n, g+1, n);
	} else
		gopcode(OEQ, n->type, g, n, D_CONST, nodconst(v));
	gbranch(OLT);
	sp1 = p;
	gbranch(OGT);
	sp2 = p;
	gbranch(OGOTO);
	patch(p, r->label);

	patch(sp1, pc);
	swit1(q, i, def, g, n);

	patch(sp2, pc);
	swit1(r+1, nc-i-1, def, g, n);
	return;

linear:
	for(i=0; i<nc; i++) {
		v = q->val;
		if(v >= -128 && v < 128) {
			gopcode(OAS, n->type, D_CONST, nodconst(v), g+1, n);
			gopcode(OEQ, n->type, g+1, n, g, n);
		} else
			gopcode(OEQ, n->type, g, n, D_CONST, nodconst(v));
		gbranch(OEQ);
		patch(p, q->label);
		q++;
	}
	gbranch(OGOTO);
	patch(p, def);
}
Example #7
0
static void
genasop(int o, Node *l, Node *r, Node *nn)
{
	Node nod, nod1, nod2;
	int hardleft;

	hardleft = l->addable < INDEXED || l->complex >= FNX;
	if(l->complex >= r->complex) {
		if(hardleft)
			reglcgen(&nod2, l, Z);
		else
			nod2 = *l;
		regalloc(&nod1, r, Z);
		cgen(r, &nod1);
	} else {
		regalloc(&nod1, r, Z);
		cgen(r, &nod1);
		if(hardleft)
			reglcgen(&nod2, l, Z);
		else
			nod2 = *l;
	}
	if(nod1.type == nod2.type || !typefd[nod1.type->etype])
		regalloc(&nod, &nod2, nn);
	else
		regalloc(&nod, &nod1, Z);
	gmove(&nod2, &nod);
	gopcode(o, &nod1, Z, &nod);
	gmove(&nod, &nod2);
	if(nn != Z)
		gmove(&nod2, nn);
	regfree(&nod);
	regfree(&nod1);
	if(hardleft)
		regfree(&nod2);
}
Example #8
0
void
swit2(C1 *q, int nc, long def, Node *n, Node *tn)
{
	C1 *r;
	int i;
	Prog *sp;

	if(nc < 5) {
		for(i=0; i<nc; i++) {
			if(sval(q->val)) {
				gopcode(OEQ, n, Z, nodconst(q->val));
			} else {
				gopcode(OSUB, nodconst(q->val), n, tn);
				gopcode(OEQ, tn, Z, nodconst(0));
			}
			patch(p, q->label);
			q++;
		}
		gbranch(OGOTO);
		patch(p, def);
		return;
	}
	i = nc / 2;
	r = q+i;
	if(sval(r->val)) {
		gopcode(OGT, n, Z, nodconst(r->val));
		sp = p;
	} else {
		gopcode(OSUB, nodconst(r->val), n, tn);
		gopcode(OGT, tn, Z, nodconst(0));
		sp = p;
	}
	gbranch(OGOTO);
	p->as = ABEQ;
	patch(p, r->label);
	swit2(q, i, def, n, tn);

	patch(sp, pc);
	swit2(r+1, nc-i-1, def, n, tn);
}
Example #9
0
File: cgen.c Project: 8l/inferno
void
cgen(Node *n, int result, Node *nn)
{
	Node *l, *r, nod;
	int lg, rg, xg, yg, g, o;
	long v;
	Prog *p1;

	if(n == Z || n->type == T)
		return;
	if(typesuv[n->type->etype]) {
		sugen(n, result, nn, n->type->width);
		return;
	}
	if(debug['g']) {
		if(result == D_TREE)
			prtree(nn, "result");
		else
			print("result = %R\n", result);
		prtree(n, "cgen");
	}
	l = n->left;
	r = n->right;
	o = n->op;
	if(n->addable >= INDEXED) {
		if(result == D_NONE) {
			if(nn == Z)
				switch(o) {
				default:
					nullwarn(Z, Z);
					break;
				case OINDEX:
					nullwarn(l, r);
					break;
				}
			return;
		}
		gmove(n->type, nn->type, D_TREE, n, result, nn);
		return;
	}

	v = 0; /* set */
	switch(o) {
	default:
		diag(n, "unknown op in cgen: %O", o);
		break;

	case OAS:
		if(l->op == OBIT)
			goto bitas;
		/*
		 * recursive use of result
		 */
		if(result == D_NONE)
		if(l->addable > INDEXED)
		if(l->complex < FNX) {
			cgen(r, D_TREE, l);
			break;
		}

		/*
		 * function calls on both sides
		 */
		if(l->complex >= FNX && r->complex >= FNX) {
			cgen(r, D_TOS, r);
			v = argoff;
			lg = regaddr(result);
			lcgen(l, lg, Z);
			lg |= I_INDIR;
			adjsp(v - argoff);
			gmove(r->type, l->type, D_TOS, r, lg, l);
			if(result != D_NONE)
				gmove(l->type, nn->type, lg, l, result, nn);
			regfree(lg);
			break;
		}

		rg = D_TREE;
		lg = D_TREE;
		if(r->complex >= l->complex) {
			/*
			 * right side before left
			 */
			if(result != D_NONE) {
				rg = regalloc(n->type, result);
				cgen(r, rg, n);
			} else
			if(r->complex >= FNX || r->addable < INDEXED) {
				rg = regalloc(r->type, result);
				cgen(r, rg, r);
			}
			if(l->addable < INDEXED) {
				lg = regaddr(lg);
				lcgen(l, lg, Z);
				lg |= I_INDIR;
			}
		} else {
			/*
			 * left before right
			 */
			if(l->complex >= FNX || l->addable < INDEXED) {
				lg = regaddr(lg);
				lcgen(l, lg, Z);
				lg |= I_INDIR;
			}
			if(result != D_NONE) {
				rg = regalloc(n->type, result);
				cgen(r, rg, n);
			} else
			if(r->addable < INDEXED) {
				rg = regalloc(r->type, result);
				cgen(r, rg, r);
			}
		}
		if(result != D_NONE) {
			gmove(n->type, l->type, rg, r, lg, l);
			gmove(n->type, nn->type, rg, r, result, nn);
		} else
			gmove(r->type, l->type, rg, r, lg, l);
		regfree(lg);
		regfree(rg);
		break;

	bitas:
		n = l->left;
		rg = regalloc(tfield, result);
		if(l->complex >= r->complex) {
			lg = regaddr(D_NONE);
			lcgen(n, lg, Z);
			lg |= I_INDIR;
			cgen(r, rg, r);
		} else {
			cgen(r, rg, r);
			lg = regaddr(D_NONE);
			lcgen(n, lg, Z);
			lg |= I_INDIR;
		}
		g = regalloc(n->type, D_NONE);
		gmove(l->type, l->type, lg, l, g, l);
		bitstore(l, rg, lg, g, result, nn);
		break;

	case OBIT:
		if(result == D_NONE) {
			nullwarn(l, Z);
			break;
		}
		g = bitload(n, D_NONE, D_NONE, result, nn);
		gopcode(OAS, nn->type, g, n, result, nn);
		regfree(g);
		break;

	case ODOT:
		sugen(l, D_TREE, nodrat, l->type->width);
		if(result != D_NONE) {
			warn(n, "non-interruptable temporary");
			nod = *nodrat;
			if(!r || r->op != OCONST) {
				diag(n, "DOT and no offset");
				break;
			}
			nod.xoffset += r->vconst;
			nod.type = n->type;
			cgen(&nod, result, nn);
		}
		break;

	case OASLDIV:
	case OASLMOD:
	case OASDIV:
	case OASMOD:
		if(l->op == OBIT)
			goto asbitop;
		if(typefd[n->type->etype])
			goto asbinop;
		rg = D_TREE;
		if(l->complex >= FNX || r->complex >= FNX) {
			rg = D_TOS;
			cgen(r, rg, r);
			v = argoff;
		} else
		if(r->addable < INDEXED) {
			rg = regalloc(n->type, D_NONE);
			cgen(r, rg, r);
		}
		lg = D_TREE;
		if(!simplv(l)) {
			lg = regaddr(D_NONE);
			lcgen(l, lg, Z);	/* destroys register optimization */
			lg |= I_INDIR;
		}
		g = regpair(result);
		gmove(l->type, n->type, lg, l, g, n);
		if(rg == D_TOS)
			adjsp(v - argoff);
		gopcode(o, n->type, rg, r, g, n);
		if(o == OASLMOD || o == OASMOD)
			gmove(n->type, l->type, g+1, n, lg, l);
		else
			gmove(n->type, l->type, g, n, lg, l);
		if(result != D_NONE)
		if(o == OASLMOD || o == OASMOD)
			gmove(n->type, nn->type, g+1, n, result, nn);
		else
			gmove(n->type, nn->type, g, n, result, nn);
		regfree(g);
		regfree(g+1);
		regfree(lg);
		regfree(rg);
		break;

	case OASXOR:
	case OASAND:
	case OASOR:
		if(l->op == OBIT)
			goto asbitop;
		if(l->complex >= FNX ||
		   l->addable < INDEXED ||
		   result != D_NONE ||
		   typefd[n->type->etype])
			goto asbinop;
		rg = D_TREE;
		if(r->op != OCONST) {
			rg = regalloc(n->type, D_NONE);
			cgen(r, rg, r);
		}
		gopcode(o, l->type, rg, r, D_TREE, l);
		regfree(rg);
		break;

	case OASADD:
	case OASSUB:
		if(l->op == OBIT ||
		   l->complex >= FNX ||
		   l->addable < INDEXED ||
		   result != D_NONE ||
		   typefd[n->type->etype])
			goto asbinop;
		v = vconst(r);
		if(v > 0 && v <= 8) {
			gopcode(o, n->type, D_TREE, r, D_TREE, l);
			break;
		}
		rg = regalloc(n->type, D_NONE);
		cgen(r, rg, r);
		gopcode(o, n->type, rg, r, D_TREE, l);
		regfree(rg);
		break;

	case OASLSHR:
	case OASASHR:
	case OASASHL:
		if(l->op == OBIT ||
		   l->complex >= FNX ||
		   l->addable < INDEXED ||
		   result != D_NONE ||
		   typefd[n->type->etype])
			goto asbinop;
		rg = D_TREE;
		v = vconst(r);
		if(v <= 0 || v > 8) {
			rg = regalloc(n->type, D_NONE);
			cgen(r, rg, r);
		}
		lg = regalloc(n->type, D_NONE);
		cgen(l, lg, l);
		gopcode(o, n->type, rg, r, lg, l);
		gmove(n->type, n->type, lg, l, D_TREE, l);
		regfree(lg);
		regfree(rg);
		break;

	case OASLMUL:
	case OASMUL:
	asbinop:
		if(l->op == OBIT)
			goto asbitop;
		rg = D_TREE;
		if(l->complex >= FNX || r->complex >= FNX) {
			rg = D_TOS;
			cgen(r, rg, r);
			v = argoff;
		} else
		if(r->addable < INDEXED) {
			rg = regalloc(n->type, D_NONE);
			cgen(r, rg, r);
		} else {
			if(o == OASLSHR || o == OASASHR || o == OASASHL) {
				v = vconst(r);
				if(v <= 0 || v > 8) {
					rg = regalloc(n->type, D_NONE);
					cgen(r, rg, r);
				}
			}
		}
		lg = D_TREE;
		if(!simplv(l)) {
			lg = regaddr(D_NONE);
			lcgen(l, lg, Z);	/* destroys register optimization */
			lg |= I_INDIR;
		}
		g = regalloc(n->type, result);
		gmove(l->type, n->type, lg, l, g, n);
		if(rg == D_TOS)
			adjsp(v - argoff);
		if(o == OASXOR)
			if(rg == D_TREE) {
				rg = regalloc(n->type, D_NONE);
				cgen(r, rg, r);
			}
		if(o == OASXOR || o == OASLSHR || o == OASASHR || o == OASASHL)
			if(rg == D_TOS) {
				rg = regalloc(n->type, D_NONE);
				gmove(n->type, n->type, D_TOS, n, rg, n);
			}
		gopcode(o, n->type, rg, r, g, n);
		gmove(n->type, l->type, g, n, lg, l);
		if(result != D_NONE)
			gmove(n->type, nn->type, g, n, result, nn);
		regfree(g);
		regfree(lg);
		regfree(rg);
		break;

	asbitop:
		rg = regaddr(D_NONE);
		lg = regalloc(tfield, D_NONE);
		if(l->complex >= r->complex) {
			g = bitload(l, lg, rg, result, nn);
			xg = regalloc(r->type, D_NONE);
			cgen(r, xg, nn);
		} else {
			xg = regalloc(r->type, D_NONE);
			cgen(r, xg, nn);
			g = bitload(l, lg, rg, result, nn);
		}

		if(!typefd[n->type->etype]) {
			if(o == OASLDIV || o == OASDIV) {
				yg = regpair(result);
				gmove(tfield, n->type, g, l, yg, n);
				gopcode(o, n->type, xg, r, yg, n);
				gmove(n->type, tfield, yg, n, g, l);
				regfree(yg);
				regfree(yg+1);

				regfree(xg);
				bitstore(l, g, rg, lg, D_NONE, nn);
				break;
			}
			if(o == OASLMOD || o == OASMOD) {
				yg = regpair(result);
				gmove(tfield, n->type, g, l, yg, n);
				gopcode(o, n->type, xg, r, yg, n);
				gmove(n->type, tfield, yg+1, n, g, l);
				regfree(yg);
				regfree(yg+1);

				regfree(xg);
				bitstore(l, g, rg, lg, D_NONE, nn);
				break;
			}
		}

		yg = regalloc(n->type, result);
		gmove(tfield, n->type, g, l, yg, n);
		gopcode(o, n->type, xg, r, yg, n);
		gmove(n->type, tfield, yg, n, g, l);
		regfree(yg);

		regfree(xg);
		bitstore(l, g, rg, lg, D_NONE, nn);
		break;

	case OCAST:
		if(result == D_NONE) {
			nullwarn(l, Z);
			break;
		}
		lg = result;
		if(l->complex >= FNX)
			lg = regret(l->type);
		lg = eval(l, lg);
		if(nocast(l->type, n->type)) {
			gmove(n->type, nn->type, lg, l, result, nn);
			regfree(lg);
			break;
		}
		if(nocast(n->type, nn->type)) {
			gmove(l->type, n->type, lg, l, result, nn);
			regfree(lg);
			break;
		}
		rg = regalloc(n->type, result);
		gmove(l->type, n->type, lg, l, rg, n);
		gmove(n->type, nn->type, rg, n, result, nn);
		regfree(rg);
		regfree(lg);
		break;

	case OCOND:
		doinc(l, PRE);
		boolgen(l, 1, D_NONE, Z, l);
		p1 = p;

		inargs++;
		doinc(r->left, PRE);
		cgen(r->left, result, nn);
		doinc(r->left, POST);
		gbranch(OGOTO);
		patch(p1, pc);
		p1 = p;

		doinc(r->right, PRE);
		cgen(r->right, result, nn);
		doinc(r->right, POST);
		patch(p1, pc);
		inargs--;
		break;

	case OIND:
		if(result == D_NONE) {
			nullwarn(l, Z);
			break;
		}
		lg = nodalloc(types[TIND], result, &nod);
		nod.lineno = n->lineno;
		if(l->op == OADD) {
			if(l->left->op == OCONST) {
				nod.xoffset += l->left->vconst;
				l = l->right;
			} else
			if(l->right->op == OCONST) {
				nod.xoffset += l->right->vconst;
				l = l->left;
			}
		}
		cgen(l, lg, l);
		gmove(n->type, nn->type, D_TREE, &nod, result, nn);
		regfree(lg);
		break;

	case OFUNC:
		v = argoff;
		inargs++;
		gargs(r);
		lg = D_TREE;
		if(l->addable < INDEXED) {
			lg = regaddr(result);
			lcgen(l, lg, Z);
			lg |= I_INDIR;
		}
		inargs--;
		doinc(r, POST);
		doinc(l, POST);
		gopcode(OFUNC, types[TCHAR], D_NONE, Z, lg, l);
		regfree(lg);
		if(inargs)
			adjsp(v - argoff);
		if(result != D_NONE) {
			lg = regret(n->type);
			gmove(n->type, nn->type, lg, n, result, nn);
		}
		break;

	case OLDIV:
	case OLMOD:
	case ODIV:
	case OMOD:
		if(result == D_NONE) {
			nullwarn(l, r);
			break;
		}
		if(typefd[n->type->etype])
			goto binop;
		if(r->addable >= INDEXED && r->complex < FNX) {
			lg = regpair(result);
			cgen(l, lg, l);
			rg = D_TREE;
		} else {
			cgen(r, D_TOS, r);
			v = argoff;
			lg = regpair(result);
			cgen(l, lg, l);
			adjsp(v - argoff);
			rg = D_TOS;
		}
		gopcode(o, n->type, rg, r, lg, l);
		if(o == OMOD || o == OLMOD)
			gmove(l->type, nn->type, lg+1, l, result, nn);
		else
			gmove(l->type, nn->type, lg, l, result, nn);
		regfree(lg);
		regfree(lg+1);
		break;

	case OMUL:
	case OLMUL:
		if(l->op == OCONST)
			if(mulcon(r, l, result, nn))
				break;
		if(r->op == OCONST)
			if(mulcon(l, r, result, nn))
				break;
		if(debug['M'])
			print("%L multiply\n", n->lineno);
		goto binop;

	case OAND:
		if(r->op == OCONST)
		if(typeil[n->type->etype])
		if(l->op == OCAST) {
			if(typec[l->left->type->etype])
			if(!(r->vconst & ~0xff)) {
				l = l->left;
				goto binop;
			}
			if(typeh[l->left->type->etype])
			if(!(r->vconst & ~0xffff)) {
				l = l->left;
				goto binop;
			}
		}
		goto binop;

	case OADD:
		if(result == D_TOS)
		if(r->addable >= INDEXED)
		if(l->op == OCONST)
		if(typeil[l->type->etype]) {
			v = l->vconst;
			if(v > -32768 && v < 32768) {
				rg = regaddr(D_NONE);
				gmove(r->type, r->type, D_TREE, r, rg, r);
				gopcode(OADDR, types[TSHORT], D_NONE, Z, rg, r);
				p->to.offset = v;
				p->to.type |= I_INDIR;
				regfree(rg);
				break;
			}
		}

	case OSUB:
		if(result == D_TOS)
		if(l->addable >= INDEXED)
		if(r->op == OCONST)
		if(typeil[r->type->etype]) {
			v = r->vconst;
			if(v > -32768 && v < 32768) {
				if(n->op == OSUB)
					v = -v;
				lg = regaddr(D_NONE);
				gmove(l->type, l->type, D_TREE, l, lg, l);
				gopcode(OADDR, types[TSHORT], D_NONE, Z, lg, l);
				p->to.offset = v;
				p->to.type |= I_INDIR;
				regfree(lg);
				break;
			}
		}
		goto binop;

	case OOR:
	case OXOR:
	binop:
		if(result == D_NONE) {
			nullwarn(l, r);
			break;
		}
		if(l->complex >= FNX && r->complex >= FNX) {
			cgen(r, D_TOS, r);
			v = argoff;
			lg = regalloc(l->type, result);
			cgen(l, lg, l);
			adjsp(v - argoff);
			if(o == OXOR) {
				rg = regalloc(r->type, D_NONE);
				gmove(r->type, r->type, D_TOS, r, rg, r);
				gopcode(o, n->type, rg, r, lg, l);
				regfree(rg);
			} else
				gopcode(o, n->type, D_TOS, r, lg, l);
			gmove(n->type, nn->type, lg, l, result, nn);
			regfree(lg);
			break;
		}
		if(l->complex >= r->complex) {
			if(l->op == OADDR && (o == OADD || o == OSUB))
				lg = regaddr(result);
			else
				lg = regalloc(l->type, result);
			cgen(l, lg, l);
			rg = eval(r, D_NONE);
		} else {
			rg = regalloc(r->type, D_NONE);
			cgen(r, rg, r);
			lg = regalloc(l->type, result);
			cgen(l, lg, l);
		}
		if(o == OXOR) {
			if(rg == D_TREE) {
				rg = regalloc(r->type, D_NONE);
				cgen(r, rg, r);
			}
			if(rg == D_TOS) {
				rg = regalloc(r->type, D_NONE);
				gmove(r->type, r->type, D_TOS, r, rg, r);
			}
		}
		gopcode(o, n->type, rg, r, lg, l);
		gmove(n->type, nn->type, lg, l, result, nn);
		regfree(lg);
		regfree(rg);
		break;

	case OASHL:
		if(r->op == OCONST)
			if(shlcon(l, r, result, nn))
				break;
	case OLSHR:
	case OASHR:
		if(result == D_NONE) {
			nullwarn(l, r);
			break;
		}

		if(l->complex >= FNX && r->complex >= FNX) {
			cgen(r, D_TOS, r);
			v = argoff;
			lg = regalloc(l->type, result);
			cgen(l, lg, l);
			adjsp(v - argoff);
			rg = regalloc(r->type, D_NONE);
			gopcode(OAS, r->type, D_TOS, r, rg, r);
			gopcode(n->op, n->type, rg, r, lg, l);
			gmove(n->type, nn->type, lg, l, result, nn);
			regfree(lg);
			regfree(rg);
			break;
		}
		if(l->complex >= r->complex) {
			lg = regalloc(l->type, result);
			cgen(l, lg, l);
			v = vconst(r);
			if(v <= 0 || v > 8) {
				rg = regalloc(r->type, D_NONE);
				cgen(r, rg, r);
			} else
				rg = eval(r, D_NONE);
		} else {
			rg = regalloc(r->type, D_NONE);
			cgen(r, rg, r);
			lg = regalloc(l->type, result);
			cgen(l, lg, l);
		}
		gopcode(o, n->type, rg, r, lg, l);
		gmove(n->type, nn->type, lg, l, result, nn);
		regfree(lg);
		regfree(rg);
		break;

	case ONEG:
	case OCOM:
		if(result == D_NONE) {
			nullwarn(l, Z);
			break;
		}
		lg = regalloc(l->type, result);
		cgen(l, lg, l);
		gopcode(o, l->type, D_NONE, Z, lg, l);
		gmove(n->type, nn->type, lg, l, result, nn);
		regfree(lg);
		break;

	case OADDR:
		if(result == D_NONE) {
			nullwarn(l, Z);
			break;
		}
		lcgen(l, result, nn);
		break;

	case OEQ:
	case ONE:
	case OLE:
	case OLT:
	case OGE:
	case OGT:
	case OLO:
	case OLS:
	case OHI:
	case OHS:
		if(result == D_NONE) {
			nullwarn(l, r);
			break;
		}
		boolgen(n, 1, result, nn, Z);
		break;

	case OANDAND:
	case OOROR:
		boolgen(n, 1, result, nn, Z);
		if(result == D_NONE)
			patch(p, pc);
		break;

	case OCOMMA:
		cgen(l, D_NONE, l);
		doinc(l, POST);
		doinc(r, PRE);
		cgen(r, result, nn);
		break;

	case ONOT:
		if(result == D_NONE) {
			nullwarn(l, Z);
			break;
		}
		boolgen(n, 1, result, nn, Z);
		break;

	case OPOSTINC:
	case OPOSTDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPOSTDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;
		if(nn == Z)
			goto pre;

		lg = D_TREE;
		if(l->addable < INDEXED) {
			lg = regaddr(D_NONE);
			lcgen(l, lg, Z);
			lg |= I_INDIR;
		}
		if(result != D_NONE)
			gmove(l->type, nn->type, lg, l, result, nn);
		if(typefd[n->type->etype]) {
			rg = regalloc(n->type, D_NONE);
			gmove(l->type, l->type, lg, l, rg, l);
			gopcode(o, n->type, D_CONST, nodconst(1), rg, l);
			gmove(l->type, l->type, rg, l, lg, l);
			regfree(rg);
		} else {
			if(v < 0)
				gopcode(o, n->type, D_CONST, nodconst(-v), lg, l);
			else
				gopcode(o, n->type, D_CONST, nodconst(v), lg, l);
		}
		regfree(lg);
		break;

	case OPREINC:
	case OPREDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPREDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;

	pre:
		lg = D_TREE;
		if(l->addable < INDEXED) {
			lg = regaddr(D_NONE);
			lcgen(l, lg, Z);
			lg |= I_INDIR;
		}
		if(typefd[n->type->etype]) {
			rg = regalloc(n->type, D_NONE);
			gmove(l->type, l->type, lg, l, rg, l);
			gopcode(o, n->type, D_CONST, nodconst(1), rg, l);
			gmove(l->type, l->type, rg, l, lg, l);
			regfree(rg);
		} else {
			if(v < 0)
				gopcode(o, n->type, D_CONST, nodconst(-v), lg, l);
			else
				gopcode(o, n->type, D_CONST, nodconst(v), lg, l);
		}
		if(result != D_NONE)
			gmove(l->type, nn->type, lg, l, result, nn);
		regfree(lg);
		break;

	bitinc:
		rg = regaddr(D_NONE);
		lg = regalloc(tfield, D_NONE);
		if(result != D_NONE && (o == OPOSTINC || o == OPOSTDEC)) {
			g = bitload(l, lg, rg, D_NONE, nn);
			if(nn != Z)
				gmove(l->type, nn->type, g, l, result, nn);
			if(v < 0)
				gopcode(o, n->type, D_CONST, nodconst(-v), g, n);
			else
				gopcode(o, n->type, D_CONST, nodconst(v), g, n);
			bitstore(l, g, rg, lg, D_NONE, nn);
			break;
		}
		g = bitload(l, lg, rg, result, nn);
		if(v < 0)
			gopcode(o, n->type, D_CONST, nodconst(-v), g, n);
		else
			gopcode(o, n->type, D_CONST, nodconst(v), g, n);
		if(result != D_NONE)
			gmove(l->type, nn->type, g, l, result, nn);
		bitstore(l, g, rg, lg, D_NONE, nn);
		break;
	}
}
Example #10
0
void
cgenrel(Node *n, Node *nn, int inrel)
{
	Node *l, *r;
	Prog *p1;
	Node nod, nod1, nod2, nod3, nod4;
	int o, t;
	long v, curs;

	if(debug['g']) {
		prtree(nn, "cgen lhs");
		prtree(n, "cgen");
	}
	if(n == Z || n->type == T)
		return;
	if(typesu[n->type->etype]) {
		sugen(n, nn, n->type->width);
		return;
	}
	l = n->left;
	r = n->right;
	o = n->op;
	if(n->addable >= INDEXED) {
		if(nn == Z) {
			switch(o) {
			default:
				nullwarn(Z, Z);
				break;
			case OINDEX:
				nullwarn(l, r);
				break;
			}
			return;
		}
		gmove(n, nn);
		return;
	}
	curs = cursafe;

	if(n->complex >= FNX)
	if(l->complex >= FNX)
	if(r != Z && r->complex >= FNX)
	switch(o) {
	default:
		if(cond(o) && typesu[l->type->etype])
			break;

		regret(&nod, r);
		cgen(r, &nod);

		regsalloc(&nod1, r);
		gopcode(OAS, &nod, Z, &nod1);

		regfree(&nod);
		nod = *n;
		nod.right = &nod1;
		cgen(&nod, nn);
		return;

	case OFUNC:
	case OCOMMA:
	case OANDAND:
	case OOROR:
	case OCOND:
	case ODOT:
		break;
	}

	switch(o) {
	default:
		diag(n, "unknown op in cgen: %O", o);
		break;

	case ONEG:
	case OCOM:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		regalloc(&nod, l, nn);
		cgen(l, &nod);
		gopcode(o, &nod, Z, &nod);
		gmove(&nod, nn);
		regfree(&nod);
		break;

	case OAS:
		if(l->op == OBIT)
			goto bitas;
		if(l->addable >= INDEXED && l->complex < FNX) {
			if(nn != Z || r->addable < INDEXED) {	/* || hardconst(r) */
				if(r->complex >= FNX && nn == Z)
					regret(&nod, r);
				else
					regalloc(&nod, r, nn);
				cgen(r, &nod);
				gmove(&nod, l);
				if(nn != Z)
					gmove(&nod, nn);
				regfree(&nod);
			} else
				gmove(r, l);
			break;
		}
		if(l->complex >= r->complex) {
			/* TO DO: see 6c for OINDEX && immconst(r) */
			reglcgen(&nod1, l, Z);
			if(r->addable >= INDEXED) {	/* && !hardconst(r) */
				gmove(r, &nod1);
				if(nn != Z)
					gmove(r, nn);
				regfree(&nod1);
				break;
			}
			regalloc(&nod, r, nn);
			cgen(r, &nod);
		} else {
			regalloc(&nod, r, nn);
			cgen(r, &nod);
			reglcgen(&nod1, l, Z);
		}
		gmove(&nod, &nod1);
		regfree(&nod);
		regfree(&nod1);
		break;

	bitas:
		n = l->left;
		regalloc(&nod, r, nn);
		if(l->complex >= r->complex) {
			reglcgen(&nod1, n, Z);
			cgen(r, &nod);
		} else {
			cgen(r, &nod);
			reglcgen(&nod1, n, Z);
		}
		regalloc(&nod2, n, Z);
		gopcode(OAS, &nod1, Z, &nod2);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;

	case OBIT:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		bitload(n, &nod, Z, Z, nn);
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		break;

	case ODIV:
	case OMOD:
		if(nn != Z)
		if((t = vlog(r)) >= 0) {
			/* signed div/mod by constant power of 2 */
			cgen(l, nn);
			gopcode(OGE, nodconst(0), nn, Z);
			p1 = p;
			if(o == ODIV) {
				gopcode(OADD, nodconst((1<<t)-1), Z, nn);
				patch(p1, pc);
				gopcode(OASHR, nodconst(t), Z, nn);
			} else {
				gopcode(ONEG, nn, Z, nn);
				gopcode(OAND, nodconst((1<<t)-1), Z, nn);
				gopcode(ONEG, nn, Z, nn);
				gbranch(OGOTO);
				patch(p1, pc);
				p1 = p;
				gopcode(OAND, nodconst((1<<t)-1), Z, nn);
				patch(p1, pc);
			}
			break;
		}
		goto muldiv;

	case OXOR:
#ifdef NOTYET
		if(nn != Z)
		if(r->op == OCONST && r->vconst == -1){
			cgen(l, nn);
			gopcode(OCOM, nn, Z, nn);
			break;
		}
#endif

	case OSUB:
	case OADD:
	case OAND:
	case OOR:
	case OLSHR:
	case OASHL:
	case OASHR:
		/*
		 * immediate operands
		 */
		if(nn != Z)
		if(r->op == OCONST)
		if(!typefd[n->type->etype]) {
			cgen(l, nn);
			if(r->vconst == 0)
			if(o != OAND)
				break;
			if(nn != Z)
				gopcode(o, r, Z, nn);
			break;
		}

	case OLMUL:
	case OLDIV:
	case OLMOD:
	case OMUL:
	muldiv:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		if(o == OMUL || o == OLMUL) {
			if(mulcon(n, nn))
				break;
		}
		if(l->complex >= r->complex) {
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			regalloc(&nod1, l, Z);		/* note: l used for type, so shifts work! */
			cgen(r, &nod1);
			gopcode(o, &nod1, Z, &nod);
		} else {
			regalloc(&nod, l, nn);		/* note: l used for type, so shifts work! */
			cgen(r, &nod);
			regalloc(&nod1, l, Z);
			cgen(l, &nod1);
			gopcode(o, &nod, &nod1, &nod);
		}
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		regfree(&nod1);
		break;

	case OASLSHR:
	case OASASHL:
	case OASASHR:
	case OASAND:
	case OASADD:
	case OASSUB:
	case OASXOR:
	case OASOR:
		if(l->op == OBIT)
			goto asbitop;
		if(r->op == OCONST)
		if(!typefd[r->type->etype])
		if(!typefd[n->type->etype]) {
			if(l->addable < INDEXED)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			regalloc(&nod, l, nn);		/* note: l used for type, so shifts work! */
			gopcode(OAS, &nod2, Z, &nod);
			gopcode(o, r, Z, &nod);
			gopcode(OAS, &nod, Z, &nod2);
	
			regfree(&nod);
			if(l->addable < INDEXED)
				regfree(&nod2);
			break;
		}

	case OASLMUL:
	case OASLDIV:
	case OASLMOD:
	case OASMUL:
	case OASDIV:
	case OASMOD:
		if(l->op == OBIT)
			goto asbitop;
		if(l->complex >= r->complex) {
			if(l->addable < INDEXED)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			regalloc(&nod, n, nn);
			cgen(r, &nod);
		} else {
			regalloc(&nod, n, nn);
			cgen(r, &nod);
			if(l->addable < INDEXED)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
		}
		regalloc(&nod1, n, Z);
		gopcode(OAS, &nod2, Z, &nod1);
		if(nod1.type->etype != nod.type->etype){
			regalloc(&nod3, &nod, Z);
			gmove(&nod1, &nod3);
			regfree(&nod1);
			nod1 = nod3;
		}
		gopcode(o, &nod, &nod1, &nod);
		gmove(&nod, &nod2);
		if(nn != Z)
			gmove(&nod, nn);
		regfree(&nod);
		regfree(&nod1);
		if(l->addable < INDEXED)
			regfree(&nod2);
		break;

	asbitop:
		regalloc(&nod4, n, nn);
		regalloc(&nod3, r, Z);
		if(l->complex >= r->complex) {
			bitload(l, &nod, &nod1, &nod2, &nod4);
			cgen(r, &nod3);
		} else {
			cgen(r, &nod3);
			bitload(l, &nod, &nod1, &nod2, &nod4);
		}
		gmove(&nod, &nod4);
		gopcode(o, &nod3, Z, &nod4);
		regfree(&nod3);
		gmove(&nod4, &nod);
		regfree(&nod4);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;

	case OADDR:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		lcgen(l, nn);
		break;

	case OFUNC:
		l = uncomma(l);
		if(l->complex >= FNX) {
			if(l->op != OIND)
				diag(n, "bad function call");

			regret(&nod, l->left);
			cgen(l->left, &nod);
			regsalloc(&nod1, l->left);
			gopcode(OAS, &nod, Z, &nod1);
			regfree(&nod);

			nod = *n;
			nod.left = &nod2;
			nod2 = *l;
			nod2.left = &nod1;
			nod2.complex = 1;
			cgen(&nod, nn);

			return;
		}
		if(REGARG >= 0)
			o = reg[REGARG];
		gargs(r, &nod, &nod1);
		if(l->addable < INDEXED) {
			reglcgen(&nod, l, Z);
			gopcode(OFUNC, Z, Z, &nod);
			regfree(&nod);
		} else
			gopcode(OFUNC, Z, Z, l);
		if(REGARG >= 0)
			if(o != reg[REGARG])
				reg[REGARG]--;
		if(nn != Z) {
			regret(&nod, n);
			gopcode(OAS, &nod, Z, nn);
			regfree(&nod);
		}
		break;

	case OIND:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		regialloc(&nod, n, nn);
		r = l;
		while(r->op == OADD)
			r = r->right;
		if(sconst(r) && (v = r->vconst+nod.xoffset) >= -4096 && v < 4096) {
			v = r->vconst;
			r->vconst = 0;
			cgen(l, &nod);
			nod.xoffset += v;
			r->vconst = v;
		} else
			cgen(l, &nod);
		regind(&nod, n);
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		break;

	case OEQ:
	case ONE:
	case OLE:
	case OLT:
	case OGE:
	case OGT:
	case OLO:
	case OLS:
	case OHI:
	case OHS:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		boolgen(n, 1, nn);
		break;

	case OANDAND:
	case OOROR:
		boolgen(n, 1, nn);
		if(nn == Z)
			patch(p, pc);
		break;

	case ONOT:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		boolgen(n, 1, nn);
		break;

	case OCOMMA:
		cgen(l, Z);
		cgen(r, nn);
		break;

	case OCAST:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		/*
		 * convert from types l->n->nn
		 */
		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
			/* both null, gen l->nn */
			cgen(l, nn);
			break;
		}
		if(ewidth[n->type->etype] < ewidth[l->type->etype]){
			if(l->type->etype == TIND && typechlp[n->type->etype])
				warn(n, "conversion of pointer to shorter integer");
		}else if(0){
			if(nocast(n->type, nn->type) || castup(n->type, nn->type)){
				if(typefd[l->type->etype] != typefd[nn->type->etype])
					regalloc(&nod, l, nn);
				else
					regalloc(&nod, nn, nn);
				cgen(l, &nod);
				gmove(&nod, nn);
				regfree(&nod);
				break;
			}
		}
		regalloc(&nod, l, nn);
		cgen(l, &nod);
		regalloc(&nod1, n, &nod);
		if(inrel)
			gmover(&nod, &nod1);
		else
			gopcode(OAS, &nod, Z, &nod1);
		gopcode(OAS, &nod1, Z, nn);
		regfree(&nod1);
		regfree(&nod);
		break;

	case ODOT:
		sugen(l, nodrat, l->type->width);
		if(nn != Z) {
			warn(n, "non-interruptable temporary");
			nod = *nodrat;
			if(!r || r->op != OCONST) {
				diag(n, "DOT and no offset");
				break;
			}
			nod.xoffset += (long)r->vconst;
			nod.type = n->type;
			cgen(&nod, nn);
		}
		break;

	case OCOND:
		bcgen(l, 1);
		p1 = p;
		cgen(r->left, nn);
		gbranch(OGOTO);
		patch(p1, pc);
		p1 = p;
		cgen(r->right, nn);
		patch(p1, pc);
		break;

	case OPOSTINC:
	case OPOSTDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPOSTDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;
		if(nn == Z)
			goto pre;

		if(l->addable < INDEXED)
			reglcgen(&nod2, l, Z);
		else
			nod2 = *l;

		regalloc(&nod, l, nn);
		gopcode(OAS, &nod2, Z, &nod);
		regalloc(&nod1, l, Z);
		if(typefd[l->type->etype]) {
			regalloc(&nod3, l, Z);
			if(v < 0) {
				gopcode(OAS, nodfconst(-v), Z, &nod3);
				gopcode(OSUB, &nod3, &nod, &nod1);
			} else {
				gopcode(OAS, nodfconst(v), Z, &nod3);
				gopcode(OADD, &nod3, &nod, &nod1);
			}
			regfree(&nod3);
		} else
			gopcode(OADD, nodconst(v), &nod, &nod1);
		gopcode(OAS, &nod1, Z, &nod2);

		regfree(&nod);
		regfree(&nod1);
		if(l->addable < INDEXED)
			regfree(&nod2);
		break;

	case OPREINC:
	case OPREDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPREDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;

	pre:
		if(l->addable < INDEXED)
			reglcgen(&nod2, l, Z);
		else
			nod2 = *l;

		regalloc(&nod, l, nn);
		gopcode(OAS, &nod2, Z, &nod);
		if(typefd[l->type->etype]) {
			regalloc(&nod3, l, Z);
			if(v < 0) {
				gopcode(OAS, nodfconst(-v), Z, &nod3);
				gopcode(OSUB, &nod3, Z, &nod);
			} else {
				gopcode(OAS, nodfconst(v), Z, &nod3);
				gopcode(OADD, &nod3, Z, &nod);
			}
			regfree(&nod3);
		} else
			gopcode(OADD, nodconst(v), Z, &nod);
		gopcode(OAS, &nod, Z, &nod2);
		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
			gins(ANOP, l, Z);

		regfree(&nod);
		if(l->addable < INDEXED)
			regfree(&nod2);
		break;

	bitinc:
		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
			bitload(l, &nod, &nod1, &nod2, Z);
			gopcode(OAS, &nod, Z, nn);
			gopcode(OADD, nodconst(v), Z, &nod);
			bitstore(l, &nod, &nod1, &nod2, Z);
			break;
		}
		bitload(l, &nod, &nod1, &nod2, nn);
		gopcode(OADD, nodconst(v), Z, &nod);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;
	}
	cursafe = curs;
	return;
}
Example #11
0
void
cgen(Node *n, Node *nn)
{
	Node *l, *r;
	Prog *p1;
	Node nod, nod1, nod2, nod3, nod4;
	int o;
	long v, curs;

	if(debug['g']) {
		prtree(nn, "cgen lhs");
		prtree(n, "cgen");
	}
	if(n == Z || n->type == T)
		return;
	if(typesuv[n->type->etype]) {
		sugen(n, nn, n->type->width);
		return;
	}
	l = n->left;
	r = n->right;
	o = n->op;
	if(n->addable >= INDEXED) {
		if(nn == Z) {
			switch(o) {
			default:
				nullwarn(Z, Z);
				break;
			case OINDEX:
				nullwarn(l, r);
				break;
			}
			return;
		}
		gmove(n, nn);
		return;
	}
	curs = cursafe;

	if(n->complex >= FNX)
	if(l->complex >= FNX)
	if(r != Z && r->complex >= FNX)
	switch(o) {
	default:
		regret(&nod, r);
		cgen(r, &nod);

		regsalloc(&nod1, r);
		gopcode(OAS, &nod, Z, &nod1);

		regfree(&nod);
		nod = *n;
		nod.right = &nod1;
		cgen(&nod, nn);
		return;

	case OFUNC:
	case OCOMMA:
	case OANDAND:
	case OOROR:
	case OCOND:
	case ODOT:
		break;
	}

	switch(o) {
	default:
		diag(n, "unknown op in cgen: %O", o);
		break;

	case OAS:
		if(l->op == OBIT)
			goto bitas;
		if(l->addable >= INDEXED && l->complex < FNX) {
			if(nn != Z || r->addable < INDEXED) {
				if(r->complex >= FNX && nn == Z)
					regret(&nod, r);
				else
					regalloc(&nod, r, nn);
				cgen(r, &nod);
				gmove(&nod, l);
				if(nn != Z)
					gmove(&nod, nn);
				regfree(&nod);
			} else
				gmove(r, l);
			break;
		}
		if(l->complex >= r->complex) {
			reglcgen(&nod1, l, Z);
			if(r->addable >= INDEXED) {
				gmove(r, &nod1);
				if(nn != Z)
					gmove(r, nn);
				regfree(&nod1);
				break;
			}
			regalloc(&nod, r, nn);
			cgen(r, &nod);
		} else {
			regalloc(&nod, r, nn);
			cgen(r, &nod);
			reglcgen(&nod1, l, Z);
		}
		gmove(&nod, &nod1);
		regfree(&nod);
		regfree(&nod1);
		break;

	bitas:
		n = l->left;
		regalloc(&nod, r, nn);
		if(l->complex >= r->complex) {
			reglcgen(&nod1, n, Z);
			cgen(r, &nod);
		} else {
			cgen(r, &nod);
			reglcgen(&nod1, n, Z);
		}
		regalloc(&nod2, n, Z);
		gopcode(OAS, &nod1, Z, &nod2);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;

	case OBIT:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		bitload(n, &nod, Z, Z, nn);
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		break;

	case OADD:
	case OSUB:
	case OAND:
	case OOR:
	case OXOR:
	case OLSHR:
	case OASHL:
	case OASHR:
		/*
		 * immediate operands
		 */
		if(nn != Z)
		if(r->op == OCONST)
		if(!typefd[n->type->etype]) {
			cgen(l, nn);
			if(r->vconst == 0)
			if(o != OAND)
				break;
			if(nn != Z)
				gopcode(o, r, Z, nn);
			break;
		}

	case OLMUL:
	case OLDIV:
	case OLMOD:
	case OMUL:
	case ODIV:
	case OMOD:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		if(o == OMUL || o == OLMUL) {
			if(mulcon(n, nn))
				break;
		}
		if(l->complex >= r->complex) {
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			regalloc(&nod1, r, Z);
			cgen(r, &nod1);
			gopcode(o, &nod1, Z, &nod);
		} else {
			regalloc(&nod, r, nn);
			cgen(r, &nod);
			regalloc(&nod1, l, Z);
			cgen(l, &nod1);
			gopcode(o, &nod, &nod1, &nod);
		}
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		regfree(&nod1);
		break;

	case OASLSHR:
	case OASASHL:
	case OASASHR:
	case OASAND:
	case OASADD:
	case OASSUB:
	case OASXOR:
	case OASOR:
		if(l->op == OBIT)
			goto asbitop;
		if(r->op == OCONST)
		if(!typefd[r->type->etype])
		if(!typefd[n->type->etype]) {
			if(l->addable < INDEXED)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			regalloc(&nod, r, nn);
			gopcode(OAS, &nod2, Z, &nod);
			gopcode(o, r, Z, &nod);
			gopcode(OAS, &nod, Z, &nod2);
	
			regfree(&nod);
			if(l->addable < INDEXED)
				regfree(&nod2);
			break;
		}

	case OASLMUL:
	case OASLDIV:
	case OASLMOD:
	case OASMUL:
	case OASDIV:
	case OASMOD:
		if(l->op == OBIT)
			goto asbitop;
		if(l->complex >= r->complex) {
			if(l->addable < INDEXED)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			regalloc(&nod1, r, Z);
			cgen(r, &nod1);
		} else {
			regalloc(&nod1, r, Z);
			cgen(r, &nod1);
			if(l->addable < INDEXED)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
		}

		regalloc(&nod, n, nn);
		gmove(&nod2, &nod);
		gopcode(o, &nod1, Z, &nod);
		gmove(&nod, &nod2);
		if(nn != Z)
			gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		regfree(&nod1);
		if(l->addable < INDEXED)
			regfree(&nod2);
		break;

	asbitop:
		regalloc(&nod4, n, nn);
		if(l->complex >= r->complex) {
			bitload(l, &nod, &nod1, &nod2, &nod4);
			regalloc(&nod3, r, Z);
			cgen(r, &nod3);
		} else {
			regalloc(&nod3, r, Z);
			cgen(r, &nod3);
			bitload(l, &nod, &nod1, &nod2, &nod4);
		}
		gmove(&nod, &nod4);
		gopcode(o, &nod3, Z, &nod4);
		regfree(&nod3);
		gmove(&nod4, &nod);
		regfree(&nod4);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;

	case OADDR:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		lcgen(l, nn);
		break;

	case OFUNC:
		if(l->complex >= FNX) {
			if(l->op != OIND)
				diag(n, "bad function call");

			regret(&nod, l->left);
			cgen(l->left, &nod);
			regsalloc(&nod1, l->left);
			gopcode(OAS, &nod, Z, &nod1);
			regfree(&nod);

			nod = *n;
			nod.left = &nod2;
			nod2 = *l;
			nod2.left = &nod1;
			nod2.complex = 1;
			cgen(&nod, nn);

			return;
		}
		o = reg[REGARG];
		gargs(r, &nod, &nod1);
		if(l->addable < INDEXED) {
			reglcgen(&nod, l, Z);
			gopcode(OFUNC, Z, Z, &nod);
			regfree(&nod);
		} else
			gopcode(OFUNC, Z, Z, l);
		if(REGARG)
			if(o != reg[REGARG])
				reg[REGARG]--;
		if(nn != Z) {
			regret(&nod, n);
			gopcode(OAS, &nod, Z, nn);
			regfree(&nod);
		}
		break;

	case OIND:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		regialloc(&nod, n, nn);
		r = l;
		while(r->op == OADD)
			r = r->right;
		if(sconst(r)) {
			v = r->vconst;
			r->vconst = 0;
			cgen(l, &nod);
			nod.xoffset += v;
			r->vconst = v;
		} else
			cgen(l, &nod);
		regind(&nod, n);
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		break;

	case OEQ:
	case ONE:
	case OLE:
	case OLT:
	case OGE:
	case OGT:
	case OLO:
	case OLS:
	case OHI:
	case OHS:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		boolgen(n, 1, nn);
		break;

	case OANDAND:
	case OOROR:
		boolgen(n, 1, nn);
		if(nn == Z)
			patch(p, pc);
		break;

	case ONOT:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		boolgen(n, 1, nn);
		break;

	case OCOMMA:
		cgen(l, Z);
		cgen(r, nn);
		break;

	case OCAST:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		/*
		 * convert from types l->n->nn
		 */
		if(nocast(l->type, n->type)) {
			if(nocast(n->type, nn->type)) {
				cgen(l, nn);
				break;
			}
		}
		regalloc(&nod, l, nn);
		cgen(l, &nod);
		regalloc(&nod1, n, &nod);
		gopcode(OAS, &nod, Z, &nod1);
		gopcode(OAS, &nod1, Z, nn);
		regfree(&nod1);
		regfree(&nod);
		break;

	case ODOT:
		sugen(l, nodrat, l->type->width);
		if(nn != Z) {
			warn(n, "non-interruptable temporary");
			nod = *nodrat;
			if(!r || r->op != OCONST) {
				diag(n, "DOT and no offset");
				break;
			}
			nod.xoffset += (long)r->vconst;
			nod.type = n->type;
			cgen(&nod, nn);
		}
		break;

	case OCOND:
		bcgen(l, 1);
		p1 = p;
		cgen(r->left, nn);
		gbranch(OGOTO);
		patch(p1, pc);
		p1 = p;
		cgen(r->right, nn);
		patch(p1, pc);
		break;

	case OPOSTINC:
	case OPOSTDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPOSTDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;
		if(nn == Z)
			goto pre;

		if(l->addable < INDEXED)
			reglcgen(&nod2, l, Z);
		else
			nod2 = *l;

		regalloc(&nod, l, nn);
		gopcode(OAS, &nod2, Z, &nod);
		regalloc(&nod1, l, Z);
		if(typefd[l->type->etype]) {
			regalloc(&nod3, l, Z);
			if(v < 0) {
				gopcode(OAS, nodfconst(-v), Z, &nod3);
				gopcode(OSUB, &nod3, &nod, &nod1);
			} else {
				gopcode(OAS, nodfconst(v), Z, &nod3);
				gopcode(OADD, &nod3, &nod, &nod1);
			}
			regfree(&nod3);
		} else
			gopcode(OADD, nodconst(v), &nod, &nod1);
		gopcode(OAS, &nod1, Z, &nod2);

		regfree(&nod);
		regfree(&nod1);
		if(l->addable < INDEXED)
			regfree(&nod2);
		break;

	case OPREINC:
	case OPREDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPREDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;

	pre:
		if(l->addable < INDEXED)
			reglcgen(&nod2, l, Z);
		else
			nod2 = *l;

		regalloc(&nod, l, nn);
		gopcode(OAS, &nod2, Z, &nod);
		if(typefd[l->type->etype]) {
			regalloc(&nod3, l, Z);
			if(v < 0) {
				gopcode(OAS, nodfconst(-v), Z, &nod3);
				gopcode(OSUB, &nod3, Z, &nod);
			} else {
				gopcode(OAS, nodfconst(v), Z, &nod3);
				gopcode(OADD, &nod3, Z, &nod);
			}
			regfree(&nod3);
		} else
			gopcode(OADD, nodconst(v), Z, &nod);
		gopcode(OAS, &nod, Z, &nod2);
		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
			gins(ANOP, l, Z);

		regfree(&nod);
		if(l->addable < INDEXED)
			regfree(&nod2);
		break;

	bitinc:
		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
			bitload(l, &nod, &nod1, &nod2, Z);
			gopcode(OAS, &nod, Z, nn);
			gopcode(OADD, nodconst(v), Z, &nod);
			bitstore(l, &nod, &nod1, &nod2, Z);
			break;
		}
		bitload(l, &nod, &nod1, &nod2, nn);
		gopcode(OADD, nodconst(v), Z, &nod);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;
	}
	cursafe = curs;
}
Example #12
0
void
cgen(Node *n, Node *nn)
{
	Node *l, *r, *t;
	Prog *p1;
	Node nod, nod1, nod2, nod3, nod4;
	int o, hardleft;
	int32 v, curs;
	vlong c;

	if(debug['g']) {
		prtree(nn, "cgen lhs");
		prtree(n, "cgen");
	}
	if(n == Z || n->type == T)
		return;
	if(typesu[n->type->etype]) {
		sugen(n, nn, n->type->width);
		return;
	}
	l = n->left;
	r = n->right;
	o = n->op;
	
	if(n->op == OEXREG || (nn != Z && nn->op == OEXREG)) {
		gmove(n, nn);
		return;
	}

	if(n->addable >= INDEXED) {
		if(nn == Z) {
			switch(o) {
			default:
				nullwarn(Z, Z);
				break;
			case OINDEX:
				nullwarn(l, r);
				break;
			}
			return;
		}
		gmove(n, nn);
		return;
	}
	curs = cursafe;

	if(l->complex >= FNX)
	if(r != Z && r->complex >= FNX)
	switch(o) {
	default:
		if(cond(o) && typesu[l->type->etype])
			break;

		regret(&nod, r);
		cgen(r, &nod);

		regsalloc(&nod1, r);
		gmove(&nod, &nod1);

		regfree(&nod);
		nod = *n;
		nod.right = &nod1;

		cgen(&nod, nn);
		return;

	case OFUNC:
	case OCOMMA:
	case OANDAND:
	case OOROR:
	case OCOND:
	case ODOT:
		break;
	}

	hardleft = l->addable < INDEXED || l->complex >= FNX;
	switch(o) {
	default:
		diag(n, "unknown op in cgen: %O", o);
		break;

	case ONEG:
	case OCOM:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		regalloc(&nod, l, nn);
		cgen(l, &nod);
		gopcode(o, n->type, Z, &nod);
		gmove(&nod, nn);
		regfree(&nod);
		break;

	case OAS:
		if(l->op == OBIT)
			goto bitas;
		if(!hardleft) {
			if(nn != Z || r->addable < INDEXED || hardconst(r)) {
				if(r->complex >= FNX && nn == Z)
					regret(&nod, r);
				else
					regalloc(&nod, r, nn);
				cgen(r, &nod);
				gmove(&nod, l);
				if(nn != Z)
					gmove(&nod, nn);
				regfree(&nod);
			} else
				gmove(r, l);
			break;
		}
		if(l->complex >= r->complex) {
			if(l->op == OINDEX && immconst(r)) {
				gmove(r, l);
				break;
			}
			reglcgen(&nod1, l, Z);
			if(r->addable >= INDEXED && !hardconst(r)) {
				gmove(r, &nod1);
				if(nn != Z)
					gmove(r, nn);
				regfree(&nod1);
				break;
			}
			regalloc(&nod, r, nn);
			cgen(r, &nod);
		} else {
			regalloc(&nod, r, nn);
			cgen(r, &nod);
			reglcgen(&nod1, l, Z);
		}
		gmove(&nod, &nod1);
		regfree(&nod);
		regfree(&nod1);
		break;

	bitas:
		n = l->left;
		regalloc(&nod, r, nn);
		if(l->complex >= r->complex) {
			reglcgen(&nod1, n, Z);
			cgen(r, &nod);
		} else {
			cgen(r, &nod);
			reglcgen(&nod1, n, Z);
		}
		regalloc(&nod2, n, Z);
		gmove(&nod1, &nod2);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;

	case OBIT:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		bitload(n, &nod, Z, Z, nn);
		gmove(&nod, nn);
		regfree(&nod);
		break;

	case OLSHR:
	case OASHL:
	case OASHR:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		if(r->op == OCONST) {
			if(r->vconst == 0) {
				cgen(l, nn);
				break;
			}
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			if(o == OASHL && r->vconst == 1)
				gopcode(OADD, n->type, &nod, &nod);
			else
				gopcode(o, n->type, r, &nod);
			gmove(&nod, nn);
			regfree(&nod);
			break;
		}

		/*
		 * get nod to be D_CX
		 */
		if(nodreg(&nod, nn, D_CX)) {
			regsalloc(&nod1, n);
			gmove(&nod, &nod1);
			cgen(n, &nod);		/* probably a bug */
			gmove(&nod, nn);
			gmove(&nod1, &nod);
			break;
		}
		reg[D_CX]++;
		if(nn->op == OREGISTER && nn->reg == D_CX)
			regalloc(&nod1, l, Z);
		else
			regalloc(&nod1, l, nn);
		if(r->complex >= l->complex) {
			cgen(r, &nod);
			cgen(l, &nod1);
		} else {
			cgen(l, &nod1);
			cgen(r, &nod);
		}
		gopcode(o, n->type, &nod, &nod1);
		gmove(&nod1, nn);
		regfree(&nod);
		regfree(&nod1);
		break;

	case OADD:
	case OSUB:
	case OOR:
	case OXOR:
	case OAND:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		if(typefd[n->type->etype])
			goto fop;
		if(r->op == OCONST) {
			if(r->vconst == 0 && o != OAND) {
				cgen(l, nn);
				break;
			}
		}
		if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
		&& (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
			c = l->right->vconst;
			if(c > 0 && c <= 3) {
				if(l->left->complex >= r->complex) {
					regalloc(&nod, l->left, nn);
					cgen(l->left, &nod);
					if(r->addable < INDEXED) {
						regalloc(&nod1, r, Z);
						cgen(r, &nod1);
						genmuladd(&nod, &nod, 1 << c, &nod1);
						regfree(&nod1);
					}
					else
						genmuladd(&nod, &nod, 1 << c, r);
				}
				else {
					regalloc(&nod, r, nn);
					cgen(r, &nod);
					regalloc(&nod1, l->left, Z);
					cgen(l->left, &nod1);
					genmuladd(&nod, &nod1, 1 << c, &nod);
					regfree(&nod1);
				}
				gmove(&nod, nn);
				regfree(&nod);
				break;
			}
		}
		if(r->addable >= INDEXED && !hardconst(r)) {
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			gopcode(o, n->type, r, &nod);
			gmove(&nod, nn);
			regfree(&nod);
			break;
		}
		if(l->complex >= r->complex) {
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			regalloc(&nod1, r, Z);
			cgen(r, &nod1);
			gopcode(o, n->type, &nod1, &nod);
		} else {
			regalloc(&nod1, r, nn);
			cgen(r, &nod1);
			regalloc(&nod, l, Z);
			cgen(l, &nod);
			gopcode(o, n->type, &nod1, &nod);
		}
		gmove(&nod, nn);
		regfree(&nod);
		regfree(&nod1);
		break;

	case OLMOD:
	case OMOD:
	case OLMUL:
	case OLDIV:
	case OMUL:
	case ODIV:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		if(typefd[n->type->etype])
			goto fop;
		if(r->op == OCONST && typechl[n->type->etype]) {	/* TO DO */
			SET(v);
			switch(o) {
			case ODIV:
			case OMOD:
				c = r->vconst;
				if(c < 0)
					c = -c;
				v = xlog2(c);
				if(v < 0)
					break;
				/* fall thru */
			case OMUL:
			case OLMUL:
				regalloc(&nod, l, nn);
				cgen(l, &nod);
				switch(o) {
				case OMUL:
				case OLMUL:
					mulgen(n->type, r, &nod);
					break;
				case ODIV:
					sdiv2(r->vconst, v, l, &nod);
					break;
				case OMOD:
					smod2(r->vconst, v, l, &nod);
					break;
				}
				gmove(&nod, nn);
				regfree(&nod);
				goto done;
			case OLDIV:
				c = r->vconst;
				if((c & 0x80000000) == 0)
					break;
				regalloc(&nod1, l, Z);
				cgen(l, &nod1);
				regalloc(&nod, l, nn);
				zeroregm(&nod);
				gins(ACMPL, &nod1, nodconst(c));
				gins(ASBBL, nodconst(-1), &nod);
				regfree(&nod1);
				gmove(&nod, nn);
				regfree(&nod);
				goto done;
			}
		}

		if(o == OMUL) {
			if(l->addable >= INDEXED) {
				t = l;
				l = r;
				r = t;
			}
			/* should favour AX */
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			if(r->addable < INDEXED || hardconst(r)) {
				regalloc(&nod1, r, Z);
				cgen(r, &nod1);
				gopcode(OMUL, n->type, &nod1, &nod);
				regfree(&nod1);
			}else
				gopcode(OMUL, n->type, r, &nod);	/* addressible */
			gmove(&nod, nn);
			regfree(&nod);
			break;
		}

		/*
		 * get nod to be D_AX
		 * get nod1 to be D_DX
		 */
		if(nodreg(&nod, nn, D_AX)) {
			regsalloc(&nod2, n);
			gmove(&nod, &nod2);
			v = reg[D_AX];
			reg[D_AX] = 0;

			if(isreg(l, D_AX)) {
				nod3 = *n;
				nod3.left = &nod2;
				cgen(&nod3, nn);
			} else
			if(isreg(r, D_AX)) {
				nod3 = *n;
				nod3.right = &nod2;
				cgen(&nod3, nn);
			} else
				cgen(n, nn);

			gmove(&nod2, &nod);
			reg[D_AX] = v;
			break;
		}
		if(nodreg(&nod1, nn, D_DX)) {
			regsalloc(&nod2, n);
			gmove(&nod1, &nod2);
			v = reg[D_DX];
			reg[D_DX] = 0;

			if(isreg(l, D_DX)) {
				nod3 = *n;
				nod3.left = &nod2;
				cgen(&nod3, nn);
			} else
			if(isreg(r, D_DX)) {
				nod3 = *n;
				nod3.right = &nod2;
				cgen(&nod3, nn);
			} else
				cgen(n, nn);

			gmove(&nod2, &nod1);
			reg[D_DX] = v;
			break;
		}
		reg[D_AX]++;

		if(r->op == OCONST && (o == ODIV || o == OLDIV) && immconst(r) && typechl[r->type->etype]) {
			reg[D_DX]++;
			if(l->addable < INDEXED) {
				regalloc(&nod2, l, Z);
				cgen(l, &nod2);
				l = &nod2;
			}
			if(o == ODIV)
				sdivgen(l, r, &nod, &nod1);
			else
				udivgen(l, r, &nod, &nod1);
			gmove(&nod1, nn);
			if(l == &nod2)
				regfree(l);
			goto freeaxdx;
		}

		if(l->complex >= r->complex) {
			cgen(l, &nod);
			reg[D_DX]++;
			if(o == ODIV || o == OMOD)
				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
			if(o == OLDIV || o == OLMOD)
				zeroregm(&nod1);
			if(r->addable < INDEXED || r->op == OCONST) {
				regsalloc(&nod3, r);
				cgen(r, &nod3);
				gopcode(o, n->type, &nod3, Z);
			} else
				gopcode(o, n->type, r, Z);
		} else {
			regsalloc(&nod3, r);
			cgen(r, &nod3);
			cgen(l, &nod);
			reg[D_DX]++;
			if(o == ODIV || o == OMOD)
				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
			if(o == OLDIV || o == OLMOD)
				zeroregm(&nod1);
			gopcode(o, n->type, &nod3, Z);
		}
		if(o == OMOD || o == OLMOD)
			gmove(&nod1, nn);
		else
			gmove(&nod, nn);
	freeaxdx:
		regfree(&nod);
		regfree(&nod1);
		break;

	case OASLSHR:
	case OASASHL:
	case OASASHR:
		if(r->op == OCONST)
			goto asand;
		if(l->op == OBIT)
			goto asbitop;
		if(typefd[n->type->etype])
			goto asand;	/* can this happen? */

		/*
		 * get nod to be D_CX
		 */
		if(nodreg(&nod, nn, D_CX)) {
			regsalloc(&nod1, n);
			gmove(&nod, &nod1);
			cgen(n, &nod);
			if(nn != Z)
				gmove(&nod, nn);
			gmove(&nod1, &nod);
			break;
		}
		reg[D_CX]++;

		if(r->complex >= l->complex) {
			cgen(r, &nod);
			if(hardleft)
				reglcgen(&nod1, l, Z);
			else
				nod1 = *l;
		} else {
			if(hardleft)
				reglcgen(&nod1, l, Z);
			else
				nod1 = *l;
			cgen(r, &nod);
		}

		gopcode(o, l->type, &nod, &nod1);
		regfree(&nod);
		if(nn != Z)
			gmove(&nod1, nn);
		if(hardleft)
			regfree(&nod1);
		break;

	case OASAND:
	case OASADD:
	case OASSUB:
	case OASXOR:
	case OASOR:
	asand:
		if(l->op == OBIT)
			goto asbitop;
		if(typefd[l->type->etype] || typefd[r->type->etype])
			goto asfop;
		if(l->complex >= r->complex) {
			if(hardleft)
				reglcgen(&nod, l, Z);
			else
				nod = *l;
			if(!immconst(r)) {
				regalloc(&nod1, r, nn);
				cgen(r, &nod1);
				gopcode(o, l->type, &nod1, &nod);
				regfree(&nod1);
			} else
				gopcode(o, l->type, r, &nod);
		} else {
			regalloc(&nod1, r, nn);
			cgen(r, &nod1);
			if(hardleft)
				reglcgen(&nod, l, Z);
			else
				nod = *l;
			gopcode(o, l->type, &nod1, &nod);
			regfree(&nod1);
		}
		if(nn != Z)
			gmove(&nod, nn);
		if(hardleft)
			regfree(&nod);
		break;

	asfop:
		if(l->complex >= r->complex) {
			if(hardleft)
				reglcgen(&nod, l, Z);
			else
				nod = *l;
			if(r->addable < INDEXED){
				regalloc(&nod1, r, nn);
				cgen(r, &nod1);
			}else
				nod1 = *r;
			regalloc(&nod2, r, Z);
			gmove(&nod, &nod2);
			gopcode(o, r->type, &nod1, &nod2);
			gmove(&nod2, &nod);
			regfree(&nod2);
			if(r->addable < INDEXED)
				regfree(&nod1);
		} else {
			regalloc(&nod1, r, nn);
			cgen(r, &nod1);
			if(hardleft)
				reglcgen(&nod, l, Z);
			else
				nod = *l;
			if(o != OASMUL && o != OASADD) {
				regalloc(&nod2, r, Z);
				gmove(&nod, &nod2);
				gopcode(o, r->type, &nod1, &nod2);
				regfree(&nod1);
				gmove(&nod2, &nod);
				regfree(&nod2);
			} else {
				gopcode(o, r->type, &nod, &nod1);
				gmove(&nod1, &nod);
				regfree(&nod1);
			}
		}
		if(nn != Z)
			gmove(&nod, nn);
		if(hardleft)
			regfree(&nod);
		break;

	case OASLMUL:
	case OASLDIV:
	case OASLMOD:
	case OASMUL:
	case OASDIV:
	case OASMOD:
		if(l->op == OBIT)
			goto asbitop;
		if(typefd[n->type->etype] || typefd[r->type->etype])
			goto asfop;
		if(r->op == OCONST && typechl[n->type->etype]) {
			SET(v);
			switch(o) {
			case OASDIV:
			case OASMOD:
				c = r->vconst;
				if(c < 0)
					c = -c;
				v = xlog2(c);
				if(v < 0)
					break;
				/* fall thru */
			case OASMUL:
			case OASLMUL:
				if(hardleft)
					reglcgen(&nod2, l, Z);
				else
					nod2 = *l;
				regalloc(&nod, l, nn);
				cgen(&nod2, &nod);
				switch(o) {
				case OASMUL:
				case OASLMUL:
					mulgen(n->type, r, &nod);
					break;
				case OASDIV:
					sdiv2(r->vconst, v, l, &nod);
					break;
				case OASMOD:
					smod2(r->vconst, v, l, &nod);
					break;
				}
			havev:
				gmove(&nod, &nod2);
				if(nn != Z)
					gmove(&nod, nn);
				if(hardleft)
					regfree(&nod2);
				regfree(&nod);
				goto done;
			case OASLDIV:
				c = r->vconst;
				if((c & 0x80000000) == 0)
					break;
				if(hardleft)
					reglcgen(&nod2, l, Z);
				else
					nod2 = *l;
				regalloc(&nod1, l, nn);
				cgen(&nod2, &nod1);
				regalloc(&nod, l, nn);
				zeroregm(&nod);
				gins(ACMPL, &nod1, nodconst(c));
				gins(ASBBL, nodconst(-1), &nod);
				regfree(&nod1);
				goto havev;
			}
		}

		if(o == OASMUL) {
			/* should favour AX */
			regalloc(&nod, l, nn);
			if(r->complex >= FNX) {
				regalloc(&nod1, r, Z);
				cgen(r, &nod1);
				r = &nod1;
			}
			if(hardleft)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			cgen(&nod2, &nod);
			if(r->addable < INDEXED || hardconst(r)) {
				if(r->complex < FNX) {
					regalloc(&nod1, r, Z);
					cgen(r, &nod1);
				}
				gopcode(OASMUL, n->type, &nod1, &nod);
				regfree(&nod1);
			}
			else
				gopcode(OASMUL, n->type, r, &nod);
			if(r == &nod1)
				regfree(r);
			gmove(&nod, &nod2);
			if(nn != Z)
				gmove(&nod, nn);
			regfree(&nod);
			if(hardleft)
				regfree(&nod2);
			break;
		}

		/*
		 * get nod to be D_AX
		 * get nod1 to be D_DX
		 */
		if(nodreg(&nod, nn, D_AX)) {
			regsalloc(&nod2, n);
			gmove(&nod, &nod2);
			v = reg[D_AX];
			reg[D_AX] = 0;

			if(isreg(l, D_AX)) {
				nod3 = *n;
				nod3.left = &nod2;
				cgen(&nod3, nn);
			} else
			if(isreg(r, D_AX)) {
				nod3 = *n;
				nod3.right = &nod2;
				cgen(&nod3, nn);
			} else
				cgen(n, nn);

			gmove(&nod2, &nod);
			reg[D_AX] = v;
			break;
		}
		if(nodreg(&nod1, nn, D_DX)) {
			regsalloc(&nod2, n);
			gmove(&nod1, &nod2);
			v = reg[D_DX];
			reg[D_DX] = 0;

			if(isreg(l, D_DX)) {
				nod3 = *n;
				nod3.left = &nod2;
				cgen(&nod3, nn);
			} else
			if(isreg(r, D_DX)) {
				nod3 = *n;
				nod3.right = &nod2;
				cgen(&nod3, nn);
			} else
				cgen(n, nn);

			gmove(&nod2, &nod1);
			reg[D_DX] = v;
			break;
		}
		reg[D_AX]++;
		reg[D_DX]++;

		if(l->complex >= r->complex) {
			if(hardleft)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			cgen(&nod2, &nod);
			if(r->op == OCONST && typechl[r->type->etype]) {
				switch(o) {
				case OASDIV:
					sdivgen(&nod2, r, &nod, &nod1);
					goto divdone;
				case OASLDIV:
					udivgen(&nod2, r, &nod, &nod1);
				divdone:
					gmove(&nod1, &nod2);
					if(nn != Z)
						gmove(&nod1, nn);
					goto freelxaxdx;
				}
			}
			if(o == OASDIV || o == OASMOD)
				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
			if(o == OASLDIV || o == OASLMOD)
				zeroregm(&nod1);
			if(r->addable < INDEXED || r->op == OCONST ||
			   !typeil[r->type->etype]) {
				regalloc(&nod3, r, Z);
				cgen(r, &nod3);
				gopcode(o, l->type, &nod3, Z);
				regfree(&nod3);
			} else
				gopcode(o, n->type, r, Z);
		} else {
			regalloc(&nod3, r, Z);
			cgen(r, &nod3);
			if(hardleft)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			cgen(&nod2, &nod);
			if(o == OASDIV || o == OASMOD)
				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
			if(o == OASLDIV || o == OASLMOD)
				zeroregm(&nod1);
			gopcode(o, l->type, &nod3, Z);
			regfree(&nod3);
		}
		if(o == OASMOD || o == OASLMOD) {
			gmove(&nod1, &nod2);
			if(nn != Z)
				gmove(&nod1, nn);
		} else {
			gmove(&nod, &nod2);
			if(nn != Z)
				gmove(&nod, nn);
		}
	freelxaxdx:
		if(hardleft)
			regfree(&nod2);
		regfree(&nod);
		regfree(&nod1);
		break;

	fop:
		if(l->complex >= r->complex) {
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			if(r->addable < INDEXED) {
				regalloc(&nod1, r, Z);
				cgen(r, &nod1);
				gopcode(o, n->type, &nod1, &nod);
				regfree(&nod1);
			} else
				gopcode(o, n->type, r, &nod);
		} else {
			/* TO DO: could do better with r->addable >= INDEXED */
			regalloc(&nod1, r, Z);
			cgen(r, &nod1);
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			gopcode(o, n->type, &nod1, &nod);
			regfree(&nod1);
		}
		gmove(&nod, nn);
		regfree(&nod);
		break;

	asbitop:
		regalloc(&nod4, n, nn);
		if(l->complex >= r->complex) {
			bitload(l, &nod, &nod1, &nod2, &nod4);
			regalloc(&nod3, r, Z);
			cgen(r, &nod3);
		} else {
			regalloc(&nod3, r, Z);
			cgen(r, &nod3);
			bitload(l, &nod, &nod1, &nod2, &nod4);
		}
		gmove(&nod, &nod4);

		{	/* TO DO: check floating point source */
			Node onod;

			/* incredible grot ... */
			onod = nod3;
			onod.op = o;
			onod.complex = 2;
			onod.addable = 0;
			onod.type = tfield;
			onod.left = &nod4;
			onod.right = &nod3;
			cgen(&onod, Z);
		}
		regfree(&nod3);
		gmove(&nod4, &nod);
		regfree(&nod4);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;

	case OADDR:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		lcgen(l, nn);
		break;

	case OFUNC:
		if(l->complex >= FNX) {
			if(l->op != OIND)
				diag(n, "bad function call");

			regret(&nod, l->left);
			cgen(l->left, &nod);
			regsalloc(&nod1, l->left);
			gmove(&nod, &nod1);
			regfree(&nod);

			nod = *n;
			nod.left = &nod2;
			nod2 = *l;
			nod2.left = &nod1;
			nod2.complex = 1;
			cgen(&nod, nn);

			return;
		}
		o = 0;
		if(REGARG >= 0)
			o = reg[REGARG];
		gargs(r, &nod, &nod1);
		if(l->addable < INDEXED) {
			reglcgen(&nod, l, nn);
			nod.op = OREGISTER;
			gopcode(OFUNC, n->type, Z, &nod);
			regfree(&nod);
		} else
			gopcode(OFUNC, n->type, Z, l);
		if(REGARG >= 0)
			if(o != reg[REGARG])
				reg[REGARG]--;
		if(nn != Z) {
			regret(&nod, n);
			gmove(&nod, nn);
			regfree(&nod);
		}
		break;

	case OIND:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		regialloc(&nod, n, nn);
		r = l;
		while(r->op == OADD)
			r = r->right;
		if(sconst(r)) {
			v = r->vconst;
			r->vconst = 0;
			cgen(l, &nod);
			nod.xoffset += v;
			r->vconst = v;
		} else
			cgen(l, &nod);
		regind(&nod, n);
		gmove(&nod, nn);
		regfree(&nod);
		break;

	case OEQ:
	case ONE:
	case OLE:
	case OLT:
	case OGE:
	case OGT:
	case OLO:
	case OLS:
	case OHI:
	case OHS:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		boolgen(n, 1, nn);
		break;

	case OANDAND:
	case OOROR:
		boolgen(n, 1, nn);
		if(nn == Z)
			patch(p, pc);
		break;

	case ONOT:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		boolgen(n, 1, nn);
		break;

	case OCOMMA:
		cgen(l, Z);
		cgen(r, nn);
		break;

	case OCAST:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		/*
		 * convert from types l->n->nn
		 */
		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
			/* both null, gen l->nn */
			cgen(l, nn);
			break;
		}
		if(ewidth[n->type->etype] < ewidth[l->type->etype]){
			if(l->type->etype == TIND && typechlp[n->type->etype])
				warn(n, "conversion of pointer to shorter integer");
		}else if(0){
			if(nocast(n->type, nn->type) || castup(n->type, nn->type)){
				if(typefd[l->type->etype] != typefd[nn->type->etype])
					regalloc(&nod, l, nn);
				else
					regalloc(&nod, nn, nn);
				cgen(l, &nod);
				gmove(&nod, nn);
				regfree(&nod);
				break;
			}
		}
		regalloc(&nod, l, nn);
		cgen(l, &nod);
		regalloc(&nod1, n, &nod);
		gmove(&nod, &nod1);
		gmove(&nod1, nn);
		regfree(&nod1);
		regfree(&nod);
		break;

	case ODOT:
		sugen(l, nodrat, l->type->width);
		if(nn == Z)
			break;
		warn(n, "non-interruptable temporary");
		nod = *nodrat;
		if(!r || r->op != OCONST) {
			diag(n, "DOT and no offset");
			break;
		}
		nod.xoffset += (int32)r->vconst;
		nod.type = n->type;
		cgen(&nod, nn);
		break;

	case OCOND:
		bcgen(l, 1);
		p1 = p;
		cgen(r->left, nn);
		gbranch(OGOTO);
		patch(p1, pc);
		p1 = p;
		cgen(r->right, nn);
		patch(p1, pc);
		break;

	case OPOSTINC:
	case OPOSTDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPOSTDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;
		if(nn == Z)
			goto pre;

		if(hardleft)
			reglcgen(&nod, l, Z);
		else
			nod = *l;

		gmove(&nod, nn);
		if(typefd[n->type->etype]) {
			regalloc(&nod1, l, Z);
			gmove(&nod, &nod1);
			if(v < 0)
				gopcode(OSUB, n->type, nodfconst(-v), &nod1);
			else
				gopcode(OADD, n->type, nodfconst(v), &nod1);
			gmove(&nod1, &nod);
			regfree(&nod1);
		} else
			gopcode(OADD, n->type, nodconst(v), &nod);
		if(hardleft)
			regfree(&nod);
		break;

	case OPREINC:
	case OPREDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPREDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;

	pre:
		if(hardleft)
			reglcgen(&nod, l, Z);
		else
			nod = *l;
		if(typefd[n->type->etype]) {
			regalloc(&nod1, l, Z);
			gmove(&nod, &nod1);
			if(v < 0)
				gopcode(OSUB, n->type, nodfconst(-v), &nod1);
			else
				gopcode(OADD, n->type, nodfconst(v), &nod1);
			gmove(&nod1, &nod);
			regfree(&nod1);
		} else
			gopcode(OADD, n->type, nodconst(v), &nod);
		if(nn != Z)
			gmove(&nod, nn);
		if(hardleft)
			regfree(&nod);
		break;

	bitinc:
		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
			bitload(l, &nod, &nod1, &nod2, Z);
			gmove(&nod, nn);
			gopcode(OADD, tfield, nodconst(v), &nod);
			bitstore(l, &nod, &nod1, &nod2, Z);
			break;
		}
		bitload(l, &nod, &nod1, &nod2, nn);
		gopcode(OADD, tfield, nodconst(v), &nod);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;
	}
done:
	cursafe = curs;
}
Example #13
0
File: swt.c Project: 8l/inferno
			/* else binary */
void
swit1(C1 *q, int nc, long def, int g, Node *n)
{
	C1 *r, *s;
	int i, l, m, y;
	long v, range;
	Prog *sp1, *sp2;

	/* note that g and g+1 are not allocated */
	if(nc <= N1)
		goto linear;
	y = 23*nc/100 + 5;	/* number of cases needed to make */
	if(y < N2)		/* direct switch worthwile */
		y = N2;				/* try to do better than n**2 here */
	for(m=nc; m>=y; m--) {			/* m is number of cases */
		s = q+nc;
		r = s-m;
		for(l=nc-m; l>=0; l--) {	/* l is base of contig cases */
			s--;
			range = s->val - r->val;
			if(range > 0 && range <= N3*m)
				goto direct;
			r--;
		}
	}

	/*
	 * divide and conquer
	 */
	i = nc / 2;
	r = q+i;
	v = r->val;
	/* compare median */
	if(v >= -128 && v < 128) {
		gopcode(OAS, n->type, D_CONST, nodconst(v), g+1, n);
		gopcode(OEQ, n->type, g, n, g+1, n);
	} else
		gopcode(OEQ, n->type, g, n, D_CONST, nodconst(v));
	gbranch(OLT);
	sp1 = p;
	gbranch(OGT);
	sp2 = p;
	gbranch(OGOTO);
	patch(p, r->label);

	patch(sp1, pc);
	swit1(q, i, def, g, n);

	patch(sp2, pc);
	swit1(r+1, nc-i-1, def, g, n);
	return;

direct:
	/* compare low bound */
	v = r->val;
	if(v >= -128 && v < 128) {
		gopcode(OAS, n->type, D_CONST, nodconst(v), g+1, n);
		gopcode(OEQ, n->type, g, n, g+1, n);
	} else
		gopcode(OEQ, n->type, g, n, D_CONST, nodconst(v));
	gbranch(OLT);
	sp1 = p;

	/* compare high bound */
	v = s->val;
	if(v >= -128 && v < 128) {
		gopcode(OAS, n->type, D_CONST, nodconst(v), g+1, n);
		gopcode(OEQ, n->type, g, n, g+1, n);
	} else
		gopcode(OEQ, n->type, g, n, D_CONST, nodconst(v));
	gbranch(OGT);
	sp2 = p;

	/* switch */
	v = r->val;
	gpseudo(AMOVW, symstatic, D_R0, 0L);
	p->from.offset = nstatic - v*2;
	p->from.index = g|I_INDEX1;
	p->from.scale = 5;
	nextpc();
	p->as = ACASEW;

	/* table */
	for(i=0; i<=range; i++) {
		gbranch(OCASE);
		if(v == r->val) {
			patch(p, r->label);
			r++;
		} else
			patch(p, def);
		p->from.type = D_STATIC;
		p->from.sym = symstatic;
		p->from.offset = nstatic;
		nstatic += types[TSHORT]->width;
		v++;
	}
	gbranch(OGOTO);
	patch(p, def);
	if(r != s+1)
		print("smelly direct switch\n");

	if(l > 0) {
		patch(sp1, pc);
		swit1(q, l, def, g, n);
	} else
		patch(sp1, def);

	m += l;
	if(m < nc) {
		patch(sp2, pc);
		swit1(q+m, nc-m, def, g, n);
	} else
		patch(sp2, def);
	return;


linear:
	for(i=0; i<nc; i++) {
		v = q->val;
		if(v >= -128 && v < 128) {
			gopcode(OAS, n->type, D_CONST, nodconst(v), g+1, n);
			gopcode(OEQ, n->type, g+1, n, g, n);
		} else
			gopcode(OEQ, n->type, g, n, D_CONST, nodconst(v));
		gbranch(OEQ);
		patch(p, q->label);
		q++;
	}
	gbranch(OGOTO);
	patch(p, def);
}
Example #14
0
File: swt.c Project: 8l/inferno
int
bitload(Node *b, int n1, int n2, int n3, Node *nn)
{
	int sh, g, gs;
	long v;
	Node *l;
	Type *t;

	/*
	 * n1 gets adjusted/masked value
	 * n2 gets address of cell
	 * n3 gets contents of cell
	 */
	gs = 0;
	t = tfield;

	l = b->left;
	g = regalloc(t, n3);
	if(n2 != D_NONE) {
		lcgen(l, n2, Z);
		n2 |= I_INDIR;
		gmove(t, t, n2, l, g, l);
		gmove(t, t, g, l, n1, l);
	} else
		cgen(l, g, nn);
	if(b->type->shift == 0 && typeu[b->type->etype]) {
		v = ~0 + (1L << b->type->nbits);
		gopcode(OAND, t, D_CONST, nodconst(v), g, l);
	} else {
		sh = 32 - b->type->shift - b->type->nbits;
		if(sh > 0)
			if(sh >= 8) {
				gs = regalloc(t, D_NONE);
				gmove(t, t, D_CONST, nodconst(sh), gs, l);
				gopcode(OASHL, t, gs, l, g, l);
				if(b->type->shift)
					regfree(gs);
			} else
				gopcode(OASHL, t, D_CONST, nodconst(sh), g, l);
		sh += b->type->shift;
		if(sh > 0) {
			if(sh >= 8) {
				if(b->type->shift) {
					gs = regalloc(t, D_NONE);
					gmove(t, t, D_CONST, nodconst(sh), gs, l);
				}
				if(typeu[b->type->etype])
					gopcode(OLSHR, t, gs, l, g, l);
				else
					gopcode(OASHR, t, gs, l, g, l);
				regfree(gs);
			} else {
				if(typeu[b->type->etype])
					gopcode(OLSHR, t, D_CONST, nodconst(sh), g, l);
				else
					gopcode(OASHR, t, D_CONST, nodconst(sh), g, l);
			}
		}
	}
	return g;
}
Example #15
0
inttoktype yylex()
{
	register	ptrall	bufptr;	
	register	inttoktype		val;	
	register	struct	exp	*locxp;
	/*
	 *	No local variables to be allocated; this saves
	 *	one piddling instruction..
	 */
	static	int	Lastjxxx;

	bufptr = tokptr;		/*copy in the global value*/
   top:
	if (bufptr < tokub){
		gtoken(val, bufptr);
		switch(yylval = val){
		case	PARSEEOF:
				yylval = val = PARSEEOF;
				break;
		case	BFINT:
		case	INT:
				if (xp >= &explist[NEXP])
				     yyerror("Too many expressions; try simplyfing");
				else
				    locxp = xp++;
				locxp->e_number = Znumber;
				locxp->e_number.num_tag = TYPL;
				glong(locxp->e_xvalue, bufptr);
			  makevalue:
				locxp->e_xtype = XABS;
				locxp->e_xloc = 0;
				locxp->e_xname = NULL;
				yylval = (int)locxp;
				break;
		case	BIGNUM:	
				if (xp >= &explist[NEXP])
				     yyerror("Too many expressions; try simplyfing");
				else
				    locxp = xp++;
				gnumber(locxp->e_number, bufptr);
				goto makevalue;
		case	NAME:
				gptr(yylval, bufptr);
				lastnam = (struct symtab *)yylval;
				break;
		case	SIZESPEC:
		case 	REG:
				gchar(yylval, bufptr);
				break;
		case	INSTn:
		case	INST0:
				gopcode(yyopcode, bufptr);
				break;
		case	IJXXX:
				gopcode(yyopcode, bufptr);
				/* We can't cast Lastjxxx into (int *) here.. */
				gptr(Lastjxxx, bufptr);
				lastjxxx = (struct symtab *)Lastjxxx;
				break;
		case	ILINESKIP:
				gint(yylval, bufptr);
				lineno += yylval;
				goto top;
		case	SKIP:	
				eatskiplg(bufptr);
				goto top;
		case	VOID:	
				goto top;
		case 	STRING:
		case 	ISTAB:
		case	ISTABSTR:
		case	ISTABNONE:
		case	ISTABDOT:
		case	IALIGN:
				gptr(yylval, bufptr);
				break;
		} 
#ifdef DEBUG
		if (toktrace){
		char	*tok_to_name();
		printf("P: %d T#: %4d, %s ",
			passno, bufptr -  firsttoken, tok_to_name(val));
		switch(val){
		case 	INT:	printf("val %d",
					((struct exp *)yylval)->e_xvalue);
				break;
		case	BFINT:	printf("val %d",
					((struct exp *)yylval)->e_xvalue);
				break;
		case 	BIGNUM: bignumprint(((struct exp*)yylval)->e_number);
				break;
		case	NAME:	printf("\"%.8s\"",
					FETCHNAME((struct symtab *)yylval));
				break;
		case	REG:	printf(" r%d",
					yylval);
				break;
		case	IJXXX:
		case	INST0:	
		case	INSTn:	printf("%.8s",
						FETCHNAME(ITABFETCH(yyopcode)));
				break;
		case	STRING:
			printf("length %d, seekoffset %d, place 0%o ",
				((struct strdesc *)yylval)->sd_strlen,
				((struct strdesc *)yylval)->sd_stroff,
				((struct strdesc *)yylval)->sd_place
				);
			if (((struct strdesc *)yylval)->sd_place & STR_CORE)
				printf("value\"%*s\"",
					((struct strdesc *)yylval)->sd_strlen,
					((struct strdesc *)yylval)->sd_string);
			break;
		}  		/*end of the debug switch*/
		printf("\n");
		}
#endif DEBUG

	} else {	/* start a new buffer */
	    if (useVM){
		if (passno == 2){
			tok_temp = emptybuf->tok_next;
			emptybuf->tok_next = tok_free;
			tok_free = emptybuf;
			emptybuf = tok_temp;
		} else {
			emptybuf = emptybuf->tok_next;
		}
		bufno += 1;
		if (emptybuf == 0){
			struct	tokbufdesc *newdallop;
			int	i;
			if (passno == 2)
				goto badread;
			emptybuf = newdallop = (struct tokbufdesc *)
			  Calloc(TOKDALLOP, sizeof (struct tokbufdesc));
			for (i=0; i < TOKDALLOP; i++){
				buftail->tok_next = newdallop;
				buftail = newdallop;
				newdallop += 1;
			}
			buftail->tok_next = 0;
		}	/*end of need to get more buffers*/
		(bytetoktype *)bufptr = &(emptybuf->toks[0]);
		if (passno == 1)
			scan_dot_s(emptybuf);
	    } else {	/*don't use VM*/
		bufno ^= 1;
		emptybuf = &tokbuf[bufno];
		((bytetoktype *)bufptr) = &(emptybuf->toks[0]);
		if (passno == 1){
			/*
			 *	First check if there are things to write
			 *	out at all
			 */
			if (emptybuf->tok_count >= 0){
			    if (writeTEST((char *)emptybuf, sizeof *emptybuf, 1, tokfile)){
				yyerror("Unexpected end of file writing the interpass tmp file");
				exit(2);
			    }
			}
			scan_dot_s(emptybuf);
		} else {	/*pass 2*/
		    if (readTEST((char *)emptybuf, sizeof *emptybuf, 1, tokfile)){
			 badread:
			     yyerror("Unexpected end of file while reading the interpass tmp file");
			     exit(1);
		    }
		}
	    }	/*end of using a real live file*/
	    (char *)tokub = (char *)bufptr + emptybuf->tok_count;
#ifdef DEBUG
	    firsttoken = bufptr;
	    if (debug)
		printf("created buffernumber %d with %d tokens\n",
			bufno, emptybuf->tok_count);
#endif DEBUG
	    goto top;
	}	/*end of reading/creating a new buffer*/
	tokptr = bufptr;		/*copy back the global value*/
	return(val);
}	/*end of yylex*/
Example #16
0
int
mulcon(Node *n, Node *nn)
{
	Node *l, *r, nod1, nod2;
	Multab *m;
	long v;
	int o;
	char code[sizeof(m->code)+2], *p;

	if(typefd[n->type->etype])
		return 0;
	l = n->left;
	r = n->right;
	if(l->op == OCONST) {
		l = r;
		r = n->left;
	}
	if(r->op != OCONST)
		return 0;
	v = convvtox(r->vconst, n->type->etype);
	if(v != r->vconst) {
		if(debug['M'])
			print("%L multiply conv: %lld\n", n->lineno, r->vconst);
		return 0;
	}
	m = mulcon0(n, v);
	if(!m) {
		if(debug['M'])
			print("%L multiply table: %lld\n", n->lineno, r->vconst);
		return 0;
	}

	memmove(code, m->code, sizeof(m->code));
	code[sizeof(m->code)] = 0;

	p = code;
	if(p[1] == 'i')
		p += 2;
	regalloc(&nod1, n, nn);
	cgen(l, &nod1);
	if(v < 0)
		gopcode(ONEG, &nod1, Z, &nod1);
	regalloc(&nod2, n, Z);

loop:
	switch(*p) {
	case 0:
		regfree(&nod2);
		gopcode(OAS, &nod1, Z, nn);
		regfree(&nod1);
		return 1;
	case '+':
		o = OADD;
		goto addsub;
	case '-':
		o = OSUB;
	addsub:	/* number is r,n,l */
		v = p[1] - '0';
		r = &nod1;
		if(v&4)
			r = &nod2;
		n = &nod1;
		if(v&2)
			n = &nod2;
		l = &nod1;
		if(v&1)
			l = &nod2;
		gopcode(o, l, n, r);
		break;
	default: /* op is shiftcount, number is r,l */
		v = p[1] - '0';
		r = &nod1;
		if(v&2)
			r = &nod2;
		l = &nod1;
		if(v&1)
			l = &nod2;
		v = *p - 'a';
		if(v < 0 || v >= 32) {
			diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
			break;
		}
		gopcode(OASHL, nodconst(v), l, r);
		break;
	}
	p += 2;
	goto loop;
}
Example #17
0
File: cgen.c Project: 8l/inferno
void
lcgen(Node *n, int result, Node *nn)
{
	Node rn;
	Prog *p1;
	int lg;

	if(n == Z || n->type == T)
		return;
	if(debug['g']) {
		if(result == D_TREE)
			prtree(nn, "result");
		else
			print("result = %R\n", result);
		prtree(n, "lcgen");
	}
	if(nn == Z) {
		nn = &rn;
		nn->type = types[TIND];
	}
	switch(n->op) {
	case OCOMMA:
		cgen(n->left, D_NONE, n->left);
		doinc(n->left, POST);
		doinc(n->right, PRE);
		lcgen(n->right, result, nn);
		break;

	case OCOND:
		doinc(n->left, PRE);
		boolgen(n->left, 1, D_NONE, Z, n->left);
		p1 = p;

		inargs++;
		doinc(n->right->left, PRE);
		lcgen(n->right->left, result, nn);
		doinc(n->right->left, POST);
		gbranch(OGOTO);
		patch(p1, pc);
		p1 = p;

		doinc(n->right->right, PRE);
		lcgen(n->right->right, result, nn);
		doinc(n->right->right, POST);
		patch(p1, pc);
		inargs--;
		break;

	case OIND:
		if(n->addable >= INDEXED) {
			if(result >= D_A0 && result < D_A0+NREG) {
				gopcode(OADDR, types[TLONG], D_TREE, n, result, nn);
				break;
			}
			if(result == D_TOS) {
				gopcode(OADDR, types[TSHORT], D_NONE, nn, D_TREE, n);
				break;
			}
		}
		cgen(n->left, result, nn);
		break;

	default:
		if(n->addable < INDEXED) {
			diag(n, "unknown op in lcgen: %O", n->op);
			break;
		}
		if(result >= D_A0 && result < D_A0+NREG) {
			gopcode(OADDR, types[TLONG], D_TREE, n, result, nn);
			break;
		}
		if(result == D_TOS) {
			gopcode(OADDR, types[TSHORT], D_NONE, nn, D_TREE, n);
			break;
		}
		lg = regaddr(result);
		gopcode(OADDR, types[TLONG], D_TREE, n, lg, nn);
		gopcode(OAS, nn->type, lg, nn, result, nn);
		regfree(lg);
		break;
	}
}
Example #18
0
void
swit2(C1 *q, int nc, int32 def, Node *n)
{
	C1 *r;
	int i;
	int32 v;
	Prog *sp;

	if(nc >= 3) {
		i = (q+nc-1)->val - (q+0)->val;
		if(i > 0 && i < nc*2)
			goto direct;
	}
	if(nc < 5) {
		for(i=0; i<nc; i++) {
			if(debug['W'])
				print("case = %.8ux\n", q->val);
			gopcode(OEQ, nodconst(q->val), n, Z);
			patch(p, q->label);
			q++;
		}
		gbranch(OGOTO);
		patch(p, def);
		return;
	}

	i = nc / 2;
	r = q+i;
	if(debug['W'])
		print("case > %.8ux\n", r->val);
	gopcode(OGT, nodconst(r->val), n, Z);
	sp = p;
	gopcode(OEQ, nodconst(r->val), n, Z);	/* just gen the B.EQ */
	patch(p, r->label);
	swit2(q, i, def, n);

	if(debug['W'])
		print("case < %.8ux\n", r->val);
	patch(sp, pc);
	swit2(r+1, nc-i-1, def, n);
	return;

direct:
	v = q->val;
	if(v != 0)
		gopcode(OSUB, nodconst(v), Z, n);
	gopcode(OCASE, nodconst((q+nc-1)->val - v), n, Z);
	patch(p, def);
	for(i=0; i<nc; i++) {
		if(debug['W'])
			print("case = %.8ux\n", q->val);
		while(q->val != v) {
			nextpc();
			p->as = ABCASE;
			patch(p, def);
			v++;
		}
		nextpc();
		p->as = ABCASE;
		patch(p, q->label);
		q++;
		v++;
	}
	gbranch(OGOTO);		/* so that regopt() won't be confused */
	patch(p, def);
}