xref: /inferno-os/utils/8c/cgen.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
174a4d8c2SCharles.Forsyth #include "gc.h"
274a4d8c2SCharles.Forsyth 
374a4d8c2SCharles.Forsyth /* ,x/^(print|prtree)\(/i/\/\/ */
474a4d8c2SCharles.Forsyth 
574a4d8c2SCharles.Forsyth void
cgen(Node * n,Node * nn)674a4d8c2SCharles.Forsyth cgen(Node *n, Node *nn)
774a4d8c2SCharles.Forsyth {
874a4d8c2SCharles.Forsyth 	Node *l, *r, *t;
974a4d8c2SCharles.Forsyth 	Prog *p1;
1074a4d8c2SCharles.Forsyth 	Node nod, nod1, nod2, nod3, nod4;
1174a4d8c2SCharles.Forsyth 	int o, hardleft;
1274a4d8c2SCharles.Forsyth 	long v, curs;
1374a4d8c2SCharles.Forsyth 	vlong c;
1474a4d8c2SCharles.Forsyth 
1574a4d8c2SCharles.Forsyth 	if(debug['g']) {
1674a4d8c2SCharles.Forsyth 		prtree(nn, "cgen lhs");
1774a4d8c2SCharles.Forsyth 		prtree(n, "cgen");
1874a4d8c2SCharles.Forsyth 	}
1974a4d8c2SCharles.Forsyth 	if(n == Z || n->type == T)
2074a4d8c2SCharles.Forsyth 		return;
2174a4d8c2SCharles.Forsyth 	if(typesuv[n->type->etype]) {
2274a4d8c2SCharles.Forsyth 		sugen(n, nn, n->type->width);
2374a4d8c2SCharles.Forsyth 		return;
2474a4d8c2SCharles.Forsyth 	}
2574a4d8c2SCharles.Forsyth 	l = n->left;
2674a4d8c2SCharles.Forsyth 	r = n->right;
2774a4d8c2SCharles.Forsyth 	o = n->op;
28*45a20ab7Sforsyth // Go's version does the following, but it's the wrong place: doesn't allow assignment
29*45a20ab7Sforsyth //	if(o == OEXREG || nn != Z && nn->op == OEXREG) {
30*45a20ab7Sforsyth //		gmove(n, nn);
31*45a20ab7Sforsyth //		return;
32*45a20ab7Sforsyth //	}
33*45a20ab7Sforsyth 
3474a4d8c2SCharles.Forsyth 	if(n->addable >= INDEXED) {
3574a4d8c2SCharles.Forsyth 		if(nn == Z) {
3674a4d8c2SCharles.Forsyth 			switch(o) {
3774a4d8c2SCharles.Forsyth 			default:
3874a4d8c2SCharles.Forsyth 				nullwarn(Z, Z);
3974a4d8c2SCharles.Forsyth 				break;
4074a4d8c2SCharles.Forsyth 			case OINDEX:
4174a4d8c2SCharles.Forsyth 				nullwarn(l, r);
4274a4d8c2SCharles.Forsyth 				break;
4374a4d8c2SCharles.Forsyth 			}
4474a4d8c2SCharles.Forsyth 			return;
4574a4d8c2SCharles.Forsyth 		}
4674a4d8c2SCharles.Forsyth 		gmove(n, nn);
4774a4d8c2SCharles.Forsyth 		return;
4874a4d8c2SCharles.Forsyth 	}
4974a4d8c2SCharles.Forsyth 	curs = cursafe;
5074a4d8c2SCharles.Forsyth 
5174a4d8c2SCharles.Forsyth 	if(l->complex >= FNX)
5274a4d8c2SCharles.Forsyth 	if(r != Z && r->complex >= FNX)
5374a4d8c2SCharles.Forsyth 	switch(o) {
5474a4d8c2SCharles.Forsyth 	default:
5574a4d8c2SCharles.Forsyth 		if(cond(o) && typesuv[l->type->etype])
5674a4d8c2SCharles.Forsyth 			break;
5774a4d8c2SCharles.Forsyth 
5874a4d8c2SCharles.Forsyth 		regret(&nod, r);
5974a4d8c2SCharles.Forsyth 		cgen(r, &nod);
6074a4d8c2SCharles.Forsyth 
6174a4d8c2SCharles.Forsyth 		regsalloc(&nod1, r);
6274a4d8c2SCharles.Forsyth 		gmove(&nod, &nod1);
6374a4d8c2SCharles.Forsyth 
6474a4d8c2SCharles.Forsyth 		regfree(&nod);
6574a4d8c2SCharles.Forsyth 		nod = *n;
6674a4d8c2SCharles.Forsyth 		nod.right = &nod1;
6774a4d8c2SCharles.Forsyth 
6874a4d8c2SCharles.Forsyth 		cgen(&nod, nn);
6974a4d8c2SCharles.Forsyth 		return;
7074a4d8c2SCharles.Forsyth 
7174a4d8c2SCharles.Forsyth 	case OFUNC:
7274a4d8c2SCharles.Forsyth 	case OCOMMA:
7374a4d8c2SCharles.Forsyth 	case OANDAND:
7474a4d8c2SCharles.Forsyth 	case OOROR:
7574a4d8c2SCharles.Forsyth 	case OCOND:
7674a4d8c2SCharles.Forsyth 	case ODOT:
7774a4d8c2SCharles.Forsyth 		break;
7874a4d8c2SCharles.Forsyth 	}
7974a4d8c2SCharles.Forsyth 
8074a4d8c2SCharles.Forsyth 	hardleft = l->addable < INDEXED || l->complex >= FNX;
8174a4d8c2SCharles.Forsyth 	switch(o) {
8274a4d8c2SCharles.Forsyth 	default:
8374a4d8c2SCharles.Forsyth 		diag(n, "unknown op in cgen: %O", o);
8474a4d8c2SCharles.Forsyth 		break;
8574a4d8c2SCharles.Forsyth 
8674a4d8c2SCharles.Forsyth 	case ONEG:
8774a4d8c2SCharles.Forsyth 	case OCOM:
8874a4d8c2SCharles.Forsyth 		if(nn == Z) {
8974a4d8c2SCharles.Forsyth 			nullwarn(l, Z);
9074a4d8c2SCharles.Forsyth 			break;
9174a4d8c2SCharles.Forsyth 		}
9274a4d8c2SCharles.Forsyth 		regalloc(&nod, l, nn);
9374a4d8c2SCharles.Forsyth 		cgen(l, &nod);
9474a4d8c2SCharles.Forsyth 		gopcode(o, n->type, Z, &nod);
9574a4d8c2SCharles.Forsyth 		gmove(&nod, nn);
9674a4d8c2SCharles.Forsyth 		regfree(&nod);
9774a4d8c2SCharles.Forsyth 		break;
9874a4d8c2SCharles.Forsyth 
9974a4d8c2SCharles.Forsyth 	case OAS:
10074a4d8c2SCharles.Forsyth 		if(typefd[n->type->etype]) {
10174a4d8c2SCharles.Forsyth 			cgen(r, &fregnode0);
10274a4d8c2SCharles.Forsyth 			if(nn != Z)
10374a4d8c2SCharles.Forsyth 				gins(AFMOVD, &fregnode0, &fregnode0);
10474a4d8c2SCharles.Forsyth 			if(l->addable < INDEXED) {
10574a4d8c2SCharles.Forsyth 				reglcgen(&nod, l, Z);
10674a4d8c2SCharles.Forsyth 				gmove(&fregnode0, &nod);
10774a4d8c2SCharles.Forsyth 				regfree(&nod);
10874a4d8c2SCharles.Forsyth 			} else
10974a4d8c2SCharles.Forsyth 				gmove(&fregnode0, l);
11074a4d8c2SCharles.Forsyth 			if(nn != Z)
11174a4d8c2SCharles.Forsyth 				gmove(&fregnode0, nn);
11274a4d8c2SCharles.Forsyth 			return;
11374a4d8c2SCharles.Forsyth 		}
11474a4d8c2SCharles.Forsyth 		if(l->op == OBIT)
11574a4d8c2SCharles.Forsyth 			goto bitas;
11674a4d8c2SCharles.Forsyth 		if(!hardleft) {
11774a4d8c2SCharles.Forsyth 			if(nn != Z || r->addable < INDEXED) {
11874a4d8c2SCharles.Forsyth 				if(r->complex >= FNX && nn == Z)
11974a4d8c2SCharles.Forsyth 					regret(&nod, r);
12074a4d8c2SCharles.Forsyth 				else
12174a4d8c2SCharles.Forsyth 					regalloc(&nod, r, nn);
12274a4d8c2SCharles.Forsyth 				cgen(r, &nod);
12374a4d8c2SCharles.Forsyth 				gmove(&nod, l);
12474a4d8c2SCharles.Forsyth 				if(nn != Z)
12574a4d8c2SCharles.Forsyth 					gmove(&nod, nn);
12674a4d8c2SCharles.Forsyth 				regfree(&nod);
12774a4d8c2SCharles.Forsyth 			} else
12874a4d8c2SCharles.Forsyth 				gmove(r, l);
12974a4d8c2SCharles.Forsyth 			break;
13074a4d8c2SCharles.Forsyth 		}
13174a4d8c2SCharles.Forsyth 		if(l->complex >= r->complex) {
13274a4d8c2SCharles.Forsyth 			if(l->op == OINDEX && r->op == OCONST) {
13374a4d8c2SCharles.Forsyth 				gmove(r, l);
13474a4d8c2SCharles.Forsyth 				break;
13574a4d8c2SCharles.Forsyth 			}
13674a4d8c2SCharles.Forsyth 			reglcgen(&nod1, l, Z);
13774a4d8c2SCharles.Forsyth 			if(r->addable >= INDEXED) {
13874a4d8c2SCharles.Forsyth 				gmove(r, &nod1);
13974a4d8c2SCharles.Forsyth 				if(nn != Z)
14074a4d8c2SCharles.Forsyth 					gmove(r, nn);
14174a4d8c2SCharles.Forsyth 				regfree(&nod1);
14274a4d8c2SCharles.Forsyth 				break;
14374a4d8c2SCharles.Forsyth 			}
14474a4d8c2SCharles.Forsyth 			regalloc(&nod, r, nn);
14574a4d8c2SCharles.Forsyth 			cgen(r, &nod);
14674a4d8c2SCharles.Forsyth 		} else {
14774a4d8c2SCharles.Forsyth 			regalloc(&nod, r, nn);
14874a4d8c2SCharles.Forsyth 			cgen(r, &nod);
14974a4d8c2SCharles.Forsyth 			reglcgen(&nod1, l, Z);
15074a4d8c2SCharles.Forsyth 		}
15174a4d8c2SCharles.Forsyth 		gmove(&nod, &nod1);
15274a4d8c2SCharles.Forsyth 		regfree(&nod);
15374a4d8c2SCharles.Forsyth 		regfree(&nod1);
15474a4d8c2SCharles.Forsyth 		break;
15574a4d8c2SCharles.Forsyth 
15674a4d8c2SCharles.Forsyth 	bitas:
15774a4d8c2SCharles.Forsyth 		n = l->left;
15874a4d8c2SCharles.Forsyth 		regalloc(&nod, r, nn);
15974a4d8c2SCharles.Forsyth 		if(l->complex >= r->complex) {
16074a4d8c2SCharles.Forsyth 			reglcgen(&nod1, n, Z);
16174a4d8c2SCharles.Forsyth 			cgen(r, &nod);
16274a4d8c2SCharles.Forsyth 		} else {
16374a4d8c2SCharles.Forsyth 			cgen(r, &nod);
16474a4d8c2SCharles.Forsyth 			reglcgen(&nod1, n, Z);
16574a4d8c2SCharles.Forsyth 		}
16674a4d8c2SCharles.Forsyth 		regalloc(&nod2, n, Z);
16774a4d8c2SCharles.Forsyth 		gmove(&nod1, &nod2);
16874a4d8c2SCharles.Forsyth 		bitstore(l, &nod, &nod1, &nod2, nn);
16974a4d8c2SCharles.Forsyth 		break;
17074a4d8c2SCharles.Forsyth 
17174a4d8c2SCharles.Forsyth 	case OBIT:
17274a4d8c2SCharles.Forsyth 		if(nn == Z) {
17374a4d8c2SCharles.Forsyth 			nullwarn(l, Z);
17474a4d8c2SCharles.Forsyth 			break;
17574a4d8c2SCharles.Forsyth 		}
17674a4d8c2SCharles.Forsyth 		bitload(n, &nod, Z, Z, nn);
17774a4d8c2SCharles.Forsyth 		gmove(&nod, nn);
17874a4d8c2SCharles.Forsyth 		regfree(&nod);
17974a4d8c2SCharles.Forsyth 		break;
18074a4d8c2SCharles.Forsyth 
18174a4d8c2SCharles.Forsyth 	case OLSHR:
18274a4d8c2SCharles.Forsyth 	case OASHL:
18374a4d8c2SCharles.Forsyth 	case OASHR:
18474a4d8c2SCharles.Forsyth 		if(nn == Z) {
18574a4d8c2SCharles.Forsyth 			nullwarn(l, r);
18674a4d8c2SCharles.Forsyth 			break;
18774a4d8c2SCharles.Forsyth 		}
18874a4d8c2SCharles.Forsyth 		if(r->op == OCONST) {
18974a4d8c2SCharles.Forsyth 			if(r->vconst == 0) {
19074a4d8c2SCharles.Forsyth 				cgen(l, nn);
19174a4d8c2SCharles.Forsyth 				break;
19274a4d8c2SCharles.Forsyth 			}
19374a4d8c2SCharles.Forsyth 			regalloc(&nod, l, nn);
19474a4d8c2SCharles.Forsyth 			cgen(l, &nod);
19574a4d8c2SCharles.Forsyth 			if(o == OASHL && r->vconst == 1)
19674a4d8c2SCharles.Forsyth 				gopcode(OADD, n->type, &nod, &nod);
19774a4d8c2SCharles.Forsyth 			else
19874a4d8c2SCharles.Forsyth 				gopcode(o, n->type, r, &nod);
19974a4d8c2SCharles.Forsyth 			gmove(&nod, nn);
20074a4d8c2SCharles.Forsyth 			regfree(&nod);
20174a4d8c2SCharles.Forsyth 			break;
20274a4d8c2SCharles.Forsyth 		}
20374a4d8c2SCharles.Forsyth 
20474a4d8c2SCharles.Forsyth 		/*
20574a4d8c2SCharles.Forsyth 		 * get nod to be D_CX
20674a4d8c2SCharles.Forsyth 		 */
20774a4d8c2SCharles.Forsyth 		if(nodreg(&nod, nn, D_CX)) {
20874a4d8c2SCharles.Forsyth 			regsalloc(&nod1, n);
20974a4d8c2SCharles.Forsyth 			gmove(&nod, &nod1);
21074a4d8c2SCharles.Forsyth 			cgen(n, &nod);		/* probably a bug */
21174a4d8c2SCharles.Forsyth 			gmove(&nod, nn);
21274a4d8c2SCharles.Forsyth 			gmove(&nod1, &nod);
21374a4d8c2SCharles.Forsyth 			break;
21474a4d8c2SCharles.Forsyth 		}
21574a4d8c2SCharles.Forsyth 		reg[D_CX]++;
21674a4d8c2SCharles.Forsyth 		if(nn->op == OREGISTER && nn->reg == D_CX)
21774a4d8c2SCharles.Forsyth 			regalloc(&nod1, l, Z);
21874a4d8c2SCharles.Forsyth 		else
21974a4d8c2SCharles.Forsyth 			regalloc(&nod1, l, nn);
22074a4d8c2SCharles.Forsyth 		if(r->complex >= l->complex) {
22174a4d8c2SCharles.Forsyth 			cgen(r, &nod);
22274a4d8c2SCharles.Forsyth 			cgen(l, &nod1);
22374a4d8c2SCharles.Forsyth 		} else {
22474a4d8c2SCharles.Forsyth 			cgen(l, &nod1);
22574a4d8c2SCharles.Forsyth 			cgen(r, &nod);
22674a4d8c2SCharles.Forsyth 		}
22774a4d8c2SCharles.Forsyth 		gopcode(o, n->type, &nod, &nod1);
22874a4d8c2SCharles.Forsyth 		gmove(&nod1, nn);
22974a4d8c2SCharles.Forsyth 		regfree(&nod);
23074a4d8c2SCharles.Forsyth 		regfree(&nod1);
23174a4d8c2SCharles.Forsyth 		break;
23274a4d8c2SCharles.Forsyth 
23374a4d8c2SCharles.Forsyth 	case OADD:
23474a4d8c2SCharles.Forsyth 	case OSUB:
23574a4d8c2SCharles.Forsyth 	case OOR:
23674a4d8c2SCharles.Forsyth 	case OXOR:
23774a4d8c2SCharles.Forsyth 	case OAND:
23874a4d8c2SCharles.Forsyth 		if(nn == Z) {
23974a4d8c2SCharles.Forsyth 			nullwarn(l, r);
24074a4d8c2SCharles.Forsyth 			break;
24174a4d8c2SCharles.Forsyth 		}
24274a4d8c2SCharles.Forsyth 		if(typefd[n->type->etype])
24374a4d8c2SCharles.Forsyth 			goto fop;
24474a4d8c2SCharles.Forsyth 		if(r->op == OCONST) {
24574a4d8c2SCharles.Forsyth 			if(r->vconst == 0 && o != OAND) {
24674a4d8c2SCharles.Forsyth 				cgen(l, nn);
24774a4d8c2SCharles.Forsyth 				break;
24874a4d8c2SCharles.Forsyth 			}
24974a4d8c2SCharles.Forsyth 		}
25074a4d8c2SCharles.Forsyth 		if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
25174a4d8c2SCharles.Forsyth 		&& (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
25274a4d8c2SCharles.Forsyth 			c = l->right->vconst;
253*45a20ab7Sforsyth 			if(c > 0 && c <= 3 && nareg(1) >= 4) {
25474a4d8c2SCharles.Forsyth 				if(l->left->complex >= r->complex) {
25574a4d8c2SCharles.Forsyth 					regalloc(&nod, l->left, nn);
25674a4d8c2SCharles.Forsyth 					cgen(l->left, &nod);
25774a4d8c2SCharles.Forsyth 					if(r->addable < INDEXED) {
25874a4d8c2SCharles.Forsyth 						regalloc(&nod1, r, Z);
25974a4d8c2SCharles.Forsyth 						cgen(r, &nod1);
26074a4d8c2SCharles.Forsyth 						genmuladd(&nod, &nod, 1 << c, &nod1);
26174a4d8c2SCharles.Forsyth 						regfree(&nod1);
26274a4d8c2SCharles.Forsyth 					}
26374a4d8c2SCharles.Forsyth 					else
26474a4d8c2SCharles.Forsyth 						genmuladd(&nod, &nod, 1 << c, r);
26574a4d8c2SCharles.Forsyth 				}
26674a4d8c2SCharles.Forsyth 				else {
26774a4d8c2SCharles.Forsyth 					regalloc(&nod, r, nn);
26874a4d8c2SCharles.Forsyth 					cgen(r, &nod);
26974a4d8c2SCharles.Forsyth 					regalloc(&nod1, l->left, Z);
27074a4d8c2SCharles.Forsyth 					cgen(l->left, &nod1);
27174a4d8c2SCharles.Forsyth 					genmuladd(&nod, &nod1, 1 << c, &nod);
27274a4d8c2SCharles.Forsyth 					regfree(&nod1);
27374a4d8c2SCharles.Forsyth 				}
27474a4d8c2SCharles.Forsyth 				gmove(&nod, nn);
27574a4d8c2SCharles.Forsyth 				regfree(&nod);
27674a4d8c2SCharles.Forsyth 				break;
27774a4d8c2SCharles.Forsyth 			}
27874a4d8c2SCharles.Forsyth 		}
27974a4d8c2SCharles.Forsyth 		if(r->addable >= INDEXED) {
28074a4d8c2SCharles.Forsyth 			regalloc(&nod, l, nn);
28174a4d8c2SCharles.Forsyth 			cgen(l, &nod);
28274a4d8c2SCharles.Forsyth 			gopcode(o, n->type, r, &nod);
28374a4d8c2SCharles.Forsyth 			gmove(&nod, nn);
28474a4d8c2SCharles.Forsyth 			regfree(&nod);
28574a4d8c2SCharles.Forsyth 			break;
28674a4d8c2SCharles.Forsyth 		}
28774a4d8c2SCharles.Forsyth 		if(l->complex >= r->complex) {
28874a4d8c2SCharles.Forsyth 			regalloc(&nod, l, nn);
28974a4d8c2SCharles.Forsyth 			cgen(l, &nod);
29074a4d8c2SCharles.Forsyth 			regalloc(&nod1, r, Z);
29174a4d8c2SCharles.Forsyth 			cgen(r, &nod1);
29274a4d8c2SCharles.Forsyth 			gopcode(o, n->type, &nod1, &nod);
29374a4d8c2SCharles.Forsyth 		} else {
29474a4d8c2SCharles.Forsyth 			regalloc(&nod1, r, nn);
29574a4d8c2SCharles.Forsyth 			cgen(r, &nod1);
29674a4d8c2SCharles.Forsyth 			regalloc(&nod, l, Z);
29774a4d8c2SCharles.Forsyth 			cgen(l, &nod);
29874a4d8c2SCharles.Forsyth 			gopcode(o, n->type, &nod1, &nod);
29974a4d8c2SCharles.Forsyth 		}
30074a4d8c2SCharles.Forsyth 		gmove(&nod, nn);
30174a4d8c2SCharles.Forsyth 		regfree(&nod);
30274a4d8c2SCharles.Forsyth 		regfree(&nod1);
30374a4d8c2SCharles.Forsyth 		break;
30474a4d8c2SCharles.Forsyth 
30574a4d8c2SCharles.Forsyth 	case OLMOD:
30674a4d8c2SCharles.Forsyth 	case OMOD:
30774a4d8c2SCharles.Forsyth 	case OLMUL:
30874a4d8c2SCharles.Forsyth 	case OLDIV:
30974a4d8c2SCharles.Forsyth 	case OMUL:
31074a4d8c2SCharles.Forsyth 	case ODIV:
31174a4d8c2SCharles.Forsyth 		if(nn == Z) {
31274a4d8c2SCharles.Forsyth 			nullwarn(l, r);
31374a4d8c2SCharles.Forsyth 			break;
31474a4d8c2SCharles.Forsyth 		}
31574a4d8c2SCharles.Forsyth 		if(typefd[n->type->etype])
31674a4d8c2SCharles.Forsyth 			goto fop;
31774a4d8c2SCharles.Forsyth 		if(r->op == OCONST) {
318*45a20ab7Sforsyth 			v = 0;
31974a4d8c2SCharles.Forsyth 			switch(o) {
32074a4d8c2SCharles.Forsyth 			case ODIV:
32174a4d8c2SCharles.Forsyth 			case OMOD:
32274a4d8c2SCharles.Forsyth 				c = r->vconst;
32374a4d8c2SCharles.Forsyth 				if(c < 0)
32474a4d8c2SCharles.Forsyth 					c = -c;
32574a4d8c2SCharles.Forsyth 				v = log2(c);
32674a4d8c2SCharles.Forsyth 				if(v < 0)
32774a4d8c2SCharles.Forsyth 					break;
32874a4d8c2SCharles.Forsyth 				/* fall thru */
32974a4d8c2SCharles.Forsyth 			case OMUL:
33074a4d8c2SCharles.Forsyth 			case OLMUL:
33174a4d8c2SCharles.Forsyth 				regalloc(&nod, l, nn);
33274a4d8c2SCharles.Forsyth 				cgen(l, &nod);
33374a4d8c2SCharles.Forsyth 				switch(o) {
33474a4d8c2SCharles.Forsyth 				case OMUL:
33574a4d8c2SCharles.Forsyth 				case OLMUL:
33674a4d8c2SCharles.Forsyth 					mulgen(n->type, r, &nod);
33774a4d8c2SCharles.Forsyth 					break;
33874a4d8c2SCharles.Forsyth 				case ODIV:
33974a4d8c2SCharles.Forsyth 					sdiv2(r->vconst, v, l, &nod);
34074a4d8c2SCharles.Forsyth 					break;
34174a4d8c2SCharles.Forsyth 				case OMOD:
34274a4d8c2SCharles.Forsyth 					smod2(r->vconst, v, l, &nod);
34374a4d8c2SCharles.Forsyth 					break;
34474a4d8c2SCharles.Forsyth 				}
34574a4d8c2SCharles.Forsyth 				gmove(&nod, nn);
34674a4d8c2SCharles.Forsyth 				regfree(&nod);
34774a4d8c2SCharles.Forsyth 				goto done;
34874a4d8c2SCharles.Forsyth 			case OLDIV:
34974a4d8c2SCharles.Forsyth 				c = r->vconst;
35074a4d8c2SCharles.Forsyth 				if((c & 0x80000000) == 0)
35174a4d8c2SCharles.Forsyth 					break;
35274a4d8c2SCharles.Forsyth 				regalloc(&nod1, l, Z);
35374a4d8c2SCharles.Forsyth 				cgen(l, &nod1);
35474a4d8c2SCharles.Forsyth 				regalloc(&nod, l, nn);
35574a4d8c2SCharles.Forsyth 				zeroregm(&nod);
35674a4d8c2SCharles.Forsyth 				gins(ACMPL, &nod1, nodconst(c));
35774a4d8c2SCharles.Forsyth 				gins(ASBBL, nodconst(-1), &nod);
35874a4d8c2SCharles.Forsyth 				regfree(&nod1);
35974a4d8c2SCharles.Forsyth 				gmove(&nod, nn);
36074a4d8c2SCharles.Forsyth 				regfree(&nod);
36174a4d8c2SCharles.Forsyth 				goto done;
36274a4d8c2SCharles.Forsyth 			}
36374a4d8c2SCharles.Forsyth 		}
36474a4d8c2SCharles.Forsyth 
36574a4d8c2SCharles.Forsyth 		if(o == OMUL) {
36674a4d8c2SCharles.Forsyth 			if(l->addable >= INDEXED) {
36774a4d8c2SCharles.Forsyth 				t = l;
36874a4d8c2SCharles.Forsyth 				l = r;
36974a4d8c2SCharles.Forsyth 				r = t;
370*45a20ab7Sforsyth 				goto imula;
37174a4d8c2SCharles.Forsyth 			}
372*45a20ab7Sforsyth 			else if(r->addable >= INDEXED) {
373*45a20ab7Sforsyth 			imula:
37474a4d8c2SCharles.Forsyth /* should favour AX */
37574a4d8c2SCharles.Forsyth 				regalloc(&nod, l, nn);
37674a4d8c2SCharles.Forsyth 				cgen(l, &nod);
377*45a20ab7Sforsyth 				gopcode(OMUL, n->type, r, &nod);
378*45a20ab7Sforsyth 			}
379*45a20ab7Sforsyth 			else {
380*45a20ab7Sforsyth /* should favour AX */
381*45a20ab7Sforsyth 				regalloc(&nod, l, nn);
382*45a20ab7Sforsyth 				cgen(l, &nod);
38374a4d8c2SCharles.Forsyth 				regalloc(&nod1, r, Z);
38474a4d8c2SCharles.Forsyth 				cgen(r, &nod1);
38574a4d8c2SCharles.Forsyth 				gopcode(OMUL, n->type, &nod1, &nod);
38674a4d8c2SCharles.Forsyth 				regfree(&nod1);
387*45a20ab7Sforsyth 			}
38874a4d8c2SCharles.Forsyth 			gmove(&nod, nn);
38974a4d8c2SCharles.Forsyth 			regfree(&nod);
390*45a20ab7Sforsyth 			goto done;
39174a4d8c2SCharles.Forsyth 		}
39274a4d8c2SCharles.Forsyth 
39374a4d8c2SCharles.Forsyth 		/*
39474a4d8c2SCharles.Forsyth 		 * get nod to be D_AX
39574a4d8c2SCharles.Forsyth 		 * get nod1 to be D_DX
39674a4d8c2SCharles.Forsyth 		 */
39774a4d8c2SCharles.Forsyth 		if(nodreg(&nod, nn, D_AX)) {
39874a4d8c2SCharles.Forsyth 			regsalloc(&nod2, n);
39974a4d8c2SCharles.Forsyth 			gmove(&nod, &nod2);
40074a4d8c2SCharles.Forsyth 			v = reg[D_AX];
40174a4d8c2SCharles.Forsyth 			reg[D_AX] = 0;
40274a4d8c2SCharles.Forsyth 
40374a4d8c2SCharles.Forsyth 			if(isreg(l, D_AX)) {
40474a4d8c2SCharles.Forsyth 				nod3 = *n;
40574a4d8c2SCharles.Forsyth 				nod3.left = &nod2;
40674a4d8c2SCharles.Forsyth 				cgen(&nod3, nn);
40774a4d8c2SCharles.Forsyth 			} else
40874a4d8c2SCharles.Forsyth 			if(isreg(r, D_AX)) {
40974a4d8c2SCharles.Forsyth 				nod3 = *n;
41074a4d8c2SCharles.Forsyth 				nod3.right = &nod2;
41174a4d8c2SCharles.Forsyth 				cgen(&nod3, nn);
41274a4d8c2SCharles.Forsyth 			} else
41374a4d8c2SCharles.Forsyth 				cgen(n, nn);
41474a4d8c2SCharles.Forsyth 
41574a4d8c2SCharles.Forsyth 			gmove(&nod2, &nod);
41674a4d8c2SCharles.Forsyth 			reg[D_AX] = v;
41774a4d8c2SCharles.Forsyth 			break;
41874a4d8c2SCharles.Forsyth 		}
41974a4d8c2SCharles.Forsyth 		if(nodreg(&nod1, nn, D_DX)) {
42074a4d8c2SCharles.Forsyth 			regsalloc(&nod2, n);
42174a4d8c2SCharles.Forsyth 			gmove(&nod1, &nod2);
42274a4d8c2SCharles.Forsyth 			v = reg[D_DX];
42374a4d8c2SCharles.Forsyth 			reg[D_DX] = 0;
42474a4d8c2SCharles.Forsyth 
42574a4d8c2SCharles.Forsyth 			if(isreg(l, D_DX)) {
42674a4d8c2SCharles.Forsyth 				nod3 = *n;
42774a4d8c2SCharles.Forsyth 				nod3.left = &nod2;
42874a4d8c2SCharles.Forsyth 				cgen(&nod3, nn);
42974a4d8c2SCharles.Forsyth 			} else
43074a4d8c2SCharles.Forsyth 			if(isreg(r, D_DX)) {
43174a4d8c2SCharles.Forsyth 				nod3 = *n;
43274a4d8c2SCharles.Forsyth 				nod3.right = &nod2;
43374a4d8c2SCharles.Forsyth 				cgen(&nod3, nn);
43474a4d8c2SCharles.Forsyth 			} else
43574a4d8c2SCharles.Forsyth 				cgen(n, nn);
43674a4d8c2SCharles.Forsyth 
43774a4d8c2SCharles.Forsyth 			gmove(&nod2, &nod1);
43874a4d8c2SCharles.Forsyth 			reg[D_DX] = v;
43974a4d8c2SCharles.Forsyth 			break;
44074a4d8c2SCharles.Forsyth 		}
44174a4d8c2SCharles.Forsyth 		reg[D_AX]++;
44274a4d8c2SCharles.Forsyth 
443*45a20ab7Sforsyth 		if(r->op == OCONST) {
444*45a20ab7Sforsyth 			switch(o) {
445*45a20ab7Sforsyth 			case ODIV:
44674a4d8c2SCharles.Forsyth 				reg[D_DX]++;
44774a4d8c2SCharles.Forsyth 				if(l->addable < INDEXED) {
44874a4d8c2SCharles.Forsyth 					regalloc(&nod2, l, Z);
44974a4d8c2SCharles.Forsyth 					cgen(l, &nod2);
45074a4d8c2SCharles.Forsyth 					l = &nod2;
45174a4d8c2SCharles.Forsyth 				}
45274a4d8c2SCharles.Forsyth 				sdivgen(l, r, &nod, &nod1);
453*45a20ab7Sforsyth 				gmove(&nod1, nn);
454*45a20ab7Sforsyth 				if(l == &nod2)
455*45a20ab7Sforsyth 					regfree(l);
456*45a20ab7Sforsyth 				goto freeaxdx;
457*45a20ab7Sforsyth 			case OLDIV:
458*45a20ab7Sforsyth 				reg[D_DX]++;
459*45a20ab7Sforsyth 				if(l->addable < INDEXED) {
460*45a20ab7Sforsyth 					regalloc(&nod2, l, Z);
461*45a20ab7Sforsyth 					cgen(l, &nod2);
462*45a20ab7Sforsyth 					l = &nod2;
463*45a20ab7Sforsyth 				}
46474a4d8c2SCharles.Forsyth 				udivgen(l, r, &nod, &nod1);
46574a4d8c2SCharles.Forsyth 				gmove(&nod1, nn);
46674a4d8c2SCharles.Forsyth 				if(l == &nod2)
46774a4d8c2SCharles.Forsyth 					regfree(l);
46874a4d8c2SCharles.Forsyth 				goto freeaxdx;
46974a4d8c2SCharles.Forsyth 			}
470*45a20ab7Sforsyth 		}
47174a4d8c2SCharles.Forsyth 
47274a4d8c2SCharles.Forsyth 		if(l->complex >= r->complex) {
47374a4d8c2SCharles.Forsyth 			cgen(l, &nod);
47474a4d8c2SCharles.Forsyth 			reg[D_DX]++;
47574a4d8c2SCharles.Forsyth 			if(o == ODIV || o == OMOD)
47674a4d8c2SCharles.Forsyth 				gins(ACDQ, Z, Z);
47774a4d8c2SCharles.Forsyth 			if(o == OLDIV || o == OLMOD)
47874a4d8c2SCharles.Forsyth 				zeroregm(&nod1);
47974a4d8c2SCharles.Forsyth 			if(r->addable < INDEXED || r->op == OCONST) {
48074a4d8c2SCharles.Forsyth 				regsalloc(&nod3, r);
48174a4d8c2SCharles.Forsyth 				cgen(r, &nod3);
48274a4d8c2SCharles.Forsyth 				gopcode(o, n->type, &nod3, Z);
48374a4d8c2SCharles.Forsyth 			} else
48474a4d8c2SCharles.Forsyth 				gopcode(o, n->type, r, Z);
48574a4d8c2SCharles.Forsyth 		} else {
48674a4d8c2SCharles.Forsyth 			regsalloc(&nod3, r);
48774a4d8c2SCharles.Forsyth 			cgen(r, &nod3);
48874a4d8c2SCharles.Forsyth 			cgen(l, &nod);
48974a4d8c2SCharles.Forsyth 			reg[D_DX]++;
49074a4d8c2SCharles.Forsyth 			if(o == ODIV || o == OMOD)
49174a4d8c2SCharles.Forsyth 				gins(ACDQ, Z, Z);
49274a4d8c2SCharles.Forsyth 			if(o == OLDIV || o == OLMOD)
49374a4d8c2SCharles.Forsyth 				zeroregm(&nod1);
49474a4d8c2SCharles.Forsyth 			gopcode(o, n->type, &nod3, Z);
49574a4d8c2SCharles.Forsyth 		}
49674a4d8c2SCharles.Forsyth 		if(o == OMOD || o == OLMOD)
49774a4d8c2SCharles.Forsyth 			gmove(&nod1, nn);
49874a4d8c2SCharles.Forsyth 		else
49974a4d8c2SCharles.Forsyth 			gmove(&nod, nn);
50074a4d8c2SCharles.Forsyth 	freeaxdx:
50174a4d8c2SCharles.Forsyth 		regfree(&nod);
50274a4d8c2SCharles.Forsyth 		regfree(&nod1);
50374a4d8c2SCharles.Forsyth 		break;
50474a4d8c2SCharles.Forsyth 
50574a4d8c2SCharles.Forsyth 	case OASLSHR:
50674a4d8c2SCharles.Forsyth 	case OASASHL:
50774a4d8c2SCharles.Forsyth 	case OASASHR:
50874a4d8c2SCharles.Forsyth 		if(r->op == OCONST)
50974a4d8c2SCharles.Forsyth 			goto asand;
51074a4d8c2SCharles.Forsyth 		if(l->op == OBIT)
51174a4d8c2SCharles.Forsyth 			goto asbitop;
51274a4d8c2SCharles.Forsyth 		if(typefd[n->type->etype])
51374a4d8c2SCharles.Forsyth 			goto asfop;
51474a4d8c2SCharles.Forsyth 
51574a4d8c2SCharles.Forsyth 		/*
51674a4d8c2SCharles.Forsyth 		 * get nod to be D_CX
51774a4d8c2SCharles.Forsyth 		 */
51874a4d8c2SCharles.Forsyth 		if(nodreg(&nod, nn, D_CX)) {
51974a4d8c2SCharles.Forsyth 			regsalloc(&nod1, n);
52074a4d8c2SCharles.Forsyth 			gmove(&nod, &nod1);
52174a4d8c2SCharles.Forsyth 			cgen(n, &nod);
52274a4d8c2SCharles.Forsyth 			if(nn != Z)
52374a4d8c2SCharles.Forsyth 				gmove(&nod, nn);
52474a4d8c2SCharles.Forsyth 			gmove(&nod1, &nod);
52574a4d8c2SCharles.Forsyth 			break;
52674a4d8c2SCharles.Forsyth 		}
52774a4d8c2SCharles.Forsyth 		reg[D_CX]++;
52874a4d8c2SCharles.Forsyth 
52974a4d8c2SCharles.Forsyth 		if(r->complex >= l->complex) {
53074a4d8c2SCharles.Forsyth 			cgen(r, &nod);
53174a4d8c2SCharles.Forsyth 			if(hardleft)
53274a4d8c2SCharles.Forsyth 				reglcgen(&nod1, l, Z);
53374a4d8c2SCharles.Forsyth 			else
53474a4d8c2SCharles.Forsyth 				nod1 = *l;
53574a4d8c2SCharles.Forsyth 		} else {
53674a4d8c2SCharles.Forsyth 			if(hardleft)
53774a4d8c2SCharles.Forsyth 				reglcgen(&nod1, l, Z);
53874a4d8c2SCharles.Forsyth 			else
53974a4d8c2SCharles.Forsyth 				nod1 = *l;
54074a4d8c2SCharles.Forsyth 			cgen(r, &nod);
54174a4d8c2SCharles.Forsyth 		}
54274a4d8c2SCharles.Forsyth 
54374a4d8c2SCharles.Forsyth 		gopcode(o, l->type, &nod, &nod1);
54474a4d8c2SCharles.Forsyth 		regfree(&nod);
54574a4d8c2SCharles.Forsyth 		if(nn != Z)
54674a4d8c2SCharles.Forsyth 			gmove(&nod1, nn);
54774a4d8c2SCharles.Forsyth 		if(hardleft)
54874a4d8c2SCharles.Forsyth 			regfree(&nod1);
54974a4d8c2SCharles.Forsyth 		break;
55074a4d8c2SCharles.Forsyth 
55174a4d8c2SCharles.Forsyth 	case OASAND:
55274a4d8c2SCharles.Forsyth 	case OASADD:
55374a4d8c2SCharles.Forsyth 	case OASSUB:
55474a4d8c2SCharles.Forsyth 	case OASXOR:
55574a4d8c2SCharles.Forsyth 	case OASOR:
55674a4d8c2SCharles.Forsyth 	asand:
55774a4d8c2SCharles.Forsyth 		if(l->op == OBIT)
55874a4d8c2SCharles.Forsyth 			goto asbitop;
55974a4d8c2SCharles.Forsyth 		if(typefd[n->type->etype]||typefd[r->type->etype])
56074a4d8c2SCharles.Forsyth 			goto asfop;
56174a4d8c2SCharles.Forsyth 		if(l->complex >= r->complex) {
56274a4d8c2SCharles.Forsyth 			if(hardleft)
56374a4d8c2SCharles.Forsyth 				reglcgen(&nod, l, Z);
56474a4d8c2SCharles.Forsyth 			else
56574a4d8c2SCharles.Forsyth 				nod = *l;
56674a4d8c2SCharles.Forsyth 			if(r->op != OCONST) {
56774a4d8c2SCharles.Forsyth 				regalloc(&nod1, r, nn);
56874a4d8c2SCharles.Forsyth 				cgen(r, &nod1);
56974a4d8c2SCharles.Forsyth 				gopcode(o, l->type, &nod1, &nod);
57074a4d8c2SCharles.Forsyth 				regfree(&nod1);
57174a4d8c2SCharles.Forsyth 			} else
57274a4d8c2SCharles.Forsyth 				gopcode(o, l->type, r, &nod);
57374a4d8c2SCharles.Forsyth 		} else {
57474a4d8c2SCharles.Forsyth 			regalloc(&nod1, r, nn);
57574a4d8c2SCharles.Forsyth 			cgen(r, &nod1);
57674a4d8c2SCharles.Forsyth 			if(hardleft)
57774a4d8c2SCharles.Forsyth 				reglcgen(&nod, l, Z);
57874a4d8c2SCharles.Forsyth 			else
57974a4d8c2SCharles.Forsyth 				nod = *l;
58074a4d8c2SCharles.Forsyth 			gopcode(o, l->type, &nod1, &nod);
58174a4d8c2SCharles.Forsyth 			regfree(&nod1);
58274a4d8c2SCharles.Forsyth 		}
58374a4d8c2SCharles.Forsyth 		if(nn != Z)
58474a4d8c2SCharles.Forsyth 			gmove(&nod, nn);
58574a4d8c2SCharles.Forsyth 		if(hardleft)
58674a4d8c2SCharles.Forsyth 			regfree(&nod);
58774a4d8c2SCharles.Forsyth 		break;
58874a4d8c2SCharles.Forsyth 
58974a4d8c2SCharles.Forsyth 	case OASLMUL:
59074a4d8c2SCharles.Forsyth 	case OASLDIV:
59174a4d8c2SCharles.Forsyth 	case OASLMOD:
59274a4d8c2SCharles.Forsyth 	case OASMUL:
59374a4d8c2SCharles.Forsyth 	case OASDIV:
59474a4d8c2SCharles.Forsyth 	case OASMOD:
59574a4d8c2SCharles.Forsyth 		if(l->op == OBIT)
59674a4d8c2SCharles.Forsyth 			goto asbitop;
59774a4d8c2SCharles.Forsyth 		if(typefd[n->type->etype]||typefd[r->type->etype])
59874a4d8c2SCharles.Forsyth 			goto asfop;
59974a4d8c2SCharles.Forsyth 		if(r->op == OCONST) {
600*45a20ab7Sforsyth 			v = 0;
60174a4d8c2SCharles.Forsyth 			switch(o) {
60274a4d8c2SCharles.Forsyth 			case OASDIV:
60374a4d8c2SCharles.Forsyth 			case OASMOD:
60474a4d8c2SCharles.Forsyth 				c = r->vconst;
60574a4d8c2SCharles.Forsyth 				if(c < 0)
60674a4d8c2SCharles.Forsyth 					c = -c;
60774a4d8c2SCharles.Forsyth 				v = log2(c);
60874a4d8c2SCharles.Forsyth 				if(v < 0)
60974a4d8c2SCharles.Forsyth 					break;
61074a4d8c2SCharles.Forsyth 				/* fall thru */
61174a4d8c2SCharles.Forsyth 			case OASMUL:
61274a4d8c2SCharles.Forsyth 			case OASLMUL:
61374a4d8c2SCharles.Forsyth 				if(hardleft)
61474a4d8c2SCharles.Forsyth 					reglcgen(&nod2, l, Z);
61574a4d8c2SCharles.Forsyth 				else
61674a4d8c2SCharles.Forsyth 					nod2 = *l;
61774a4d8c2SCharles.Forsyth 				regalloc(&nod, l, nn);
61874a4d8c2SCharles.Forsyth 				cgen(&nod2, &nod);
61974a4d8c2SCharles.Forsyth 				switch(o) {
62074a4d8c2SCharles.Forsyth 				case OASMUL:
62174a4d8c2SCharles.Forsyth 				case OASLMUL:
62274a4d8c2SCharles.Forsyth 					mulgen(n->type, r, &nod);
62374a4d8c2SCharles.Forsyth 					break;
62474a4d8c2SCharles.Forsyth 				case OASDIV:
62574a4d8c2SCharles.Forsyth 					sdiv2(r->vconst, v, l, &nod);
62674a4d8c2SCharles.Forsyth 					break;
62774a4d8c2SCharles.Forsyth 				case OASMOD:
62874a4d8c2SCharles.Forsyth 					smod2(r->vconst, v, l, &nod);
62974a4d8c2SCharles.Forsyth 					break;
63074a4d8c2SCharles.Forsyth 				}
63174a4d8c2SCharles.Forsyth 			havev:
63274a4d8c2SCharles.Forsyth 				gmove(&nod, &nod2);
63374a4d8c2SCharles.Forsyth 				if(nn != Z)
63474a4d8c2SCharles.Forsyth 					gmove(&nod, nn);
63574a4d8c2SCharles.Forsyth 				if(hardleft)
63674a4d8c2SCharles.Forsyth 					regfree(&nod2);
63774a4d8c2SCharles.Forsyth 				regfree(&nod);
63874a4d8c2SCharles.Forsyth 				goto done;
63974a4d8c2SCharles.Forsyth 			case OASLDIV:
64074a4d8c2SCharles.Forsyth 				c = r->vconst;
64174a4d8c2SCharles.Forsyth 				if((c & 0x80000000) == 0)
64274a4d8c2SCharles.Forsyth 					break;
64374a4d8c2SCharles.Forsyth 				if(hardleft)
64474a4d8c2SCharles.Forsyth 					reglcgen(&nod2, l, Z);
64574a4d8c2SCharles.Forsyth 				else
64674a4d8c2SCharles.Forsyth 					nod2 = *l;
64774a4d8c2SCharles.Forsyth 				regalloc(&nod1, l, nn);
64874a4d8c2SCharles.Forsyth 				cgen(&nod2, &nod1);
64974a4d8c2SCharles.Forsyth 				regalloc(&nod, l, nn);
65074a4d8c2SCharles.Forsyth 				zeroregm(&nod);
65174a4d8c2SCharles.Forsyth 				gins(ACMPL, &nod1, nodconst(c));
65274a4d8c2SCharles.Forsyth 				gins(ASBBL, nodconst(-1), &nod);
65374a4d8c2SCharles.Forsyth 				regfree(&nod1);
65474a4d8c2SCharles.Forsyth 				goto havev;
65574a4d8c2SCharles.Forsyth 			}
65674a4d8c2SCharles.Forsyth 		}
65774a4d8c2SCharles.Forsyth 
65874a4d8c2SCharles.Forsyth 		if(o == OASMUL) {
65974a4d8c2SCharles.Forsyth /* should favour AX */
66074a4d8c2SCharles.Forsyth 			regalloc(&nod, l, nn);
66174a4d8c2SCharles.Forsyth 			if(r->complex >= FNX) {
66274a4d8c2SCharles.Forsyth 				regalloc(&nod1, r, Z);
66374a4d8c2SCharles.Forsyth 				cgen(r, &nod1);
66474a4d8c2SCharles.Forsyth 				r = &nod1;
66574a4d8c2SCharles.Forsyth 			}
66674a4d8c2SCharles.Forsyth 			if(hardleft)
66774a4d8c2SCharles.Forsyth 				reglcgen(&nod2, l, Z);
66874a4d8c2SCharles.Forsyth 			else
66974a4d8c2SCharles.Forsyth 				nod2 = *l;
67074a4d8c2SCharles.Forsyth 			cgen(&nod2, &nod);
67174a4d8c2SCharles.Forsyth 			if(r->addable < INDEXED) {
67274a4d8c2SCharles.Forsyth 				if(r->complex < FNX) {
67374a4d8c2SCharles.Forsyth 					regalloc(&nod1, r, Z);
67474a4d8c2SCharles.Forsyth 					cgen(r, &nod1);
67574a4d8c2SCharles.Forsyth 				}
67674a4d8c2SCharles.Forsyth 				gopcode(OASMUL, n->type, &nod1, &nod);
67774a4d8c2SCharles.Forsyth 				regfree(&nod1);
67874a4d8c2SCharles.Forsyth 			}
67974a4d8c2SCharles.Forsyth 			else
68074a4d8c2SCharles.Forsyth 				gopcode(OASMUL, n->type, r, &nod);
68174a4d8c2SCharles.Forsyth 			if(r == &nod1)
68274a4d8c2SCharles.Forsyth 				regfree(r);
68374a4d8c2SCharles.Forsyth 			gmove(&nod, &nod2);
68474a4d8c2SCharles.Forsyth 			if(nn != Z)
68574a4d8c2SCharles.Forsyth 				gmove(&nod, nn);
68674a4d8c2SCharles.Forsyth 			regfree(&nod);
68774a4d8c2SCharles.Forsyth 			if(hardleft)
68874a4d8c2SCharles.Forsyth 				regfree(&nod2);
689*45a20ab7Sforsyth 			goto done;
69074a4d8c2SCharles.Forsyth 		}
69174a4d8c2SCharles.Forsyth 
69274a4d8c2SCharles.Forsyth 		/*
69374a4d8c2SCharles.Forsyth 		 * get nod to be D_AX
69474a4d8c2SCharles.Forsyth 		 * get nod1 to be D_DX
69574a4d8c2SCharles.Forsyth 		 */
69674a4d8c2SCharles.Forsyth 		if(nodreg(&nod, nn, D_AX)) {
69774a4d8c2SCharles.Forsyth 			regsalloc(&nod2, n);
69874a4d8c2SCharles.Forsyth 			gmove(&nod, &nod2);
69974a4d8c2SCharles.Forsyth 			v = reg[D_AX];
70074a4d8c2SCharles.Forsyth 			reg[D_AX] = 0;
70174a4d8c2SCharles.Forsyth 
70274a4d8c2SCharles.Forsyth 			if(isreg(l, D_AX)) {
70374a4d8c2SCharles.Forsyth 				nod3 = *n;
70474a4d8c2SCharles.Forsyth 				nod3.left = &nod2;
70574a4d8c2SCharles.Forsyth 				cgen(&nod3, nn);
70674a4d8c2SCharles.Forsyth 			} else
70774a4d8c2SCharles.Forsyth 			if(isreg(r, D_AX)) {
70874a4d8c2SCharles.Forsyth 				nod3 = *n;
70974a4d8c2SCharles.Forsyth 				nod3.right = &nod2;
71074a4d8c2SCharles.Forsyth 				cgen(&nod3, nn);
71174a4d8c2SCharles.Forsyth 			} else
71274a4d8c2SCharles.Forsyth 				cgen(n, nn);
71374a4d8c2SCharles.Forsyth 
71474a4d8c2SCharles.Forsyth 			gmove(&nod2, &nod);
71574a4d8c2SCharles.Forsyth 			reg[D_AX] = v;
71674a4d8c2SCharles.Forsyth 			break;
71774a4d8c2SCharles.Forsyth 		}
71874a4d8c2SCharles.Forsyth 		if(nodreg(&nod1, nn, D_DX)) {
71974a4d8c2SCharles.Forsyth 			regsalloc(&nod2, n);
72074a4d8c2SCharles.Forsyth 			gmove(&nod1, &nod2);
72174a4d8c2SCharles.Forsyth 			v = reg[D_DX];
72274a4d8c2SCharles.Forsyth 			reg[D_DX] = 0;
72374a4d8c2SCharles.Forsyth 
72474a4d8c2SCharles.Forsyth 			if(isreg(l, D_DX)) {
72574a4d8c2SCharles.Forsyth 				nod3 = *n;
72674a4d8c2SCharles.Forsyth 				nod3.left = &nod2;
72774a4d8c2SCharles.Forsyth 				cgen(&nod3, nn);
72874a4d8c2SCharles.Forsyth 			} else
72974a4d8c2SCharles.Forsyth 			if(isreg(r, D_DX)) {
73074a4d8c2SCharles.Forsyth 				nod3 = *n;
73174a4d8c2SCharles.Forsyth 				nod3.right = &nod2;
73274a4d8c2SCharles.Forsyth 				cgen(&nod3, nn);
73374a4d8c2SCharles.Forsyth 			} else
73474a4d8c2SCharles.Forsyth 				cgen(n, nn);
73574a4d8c2SCharles.Forsyth 
73674a4d8c2SCharles.Forsyth 			gmove(&nod2, &nod1);
73774a4d8c2SCharles.Forsyth 			reg[D_DX] = v;
73874a4d8c2SCharles.Forsyth 			break;
73974a4d8c2SCharles.Forsyth 		}
74074a4d8c2SCharles.Forsyth 		reg[D_AX]++;
74174a4d8c2SCharles.Forsyth 		reg[D_DX]++;
74274a4d8c2SCharles.Forsyth 
74374a4d8c2SCharles.Forsyth 		if(l->complex >= r->complex) {
74474a4d8c2SCharles.Forsyth 			if(hardleft)
74574a4d8c2SCharles.Forsyth 				reglcgen(&nod2, l, Z);
74674a4d8c2SCharles.Forsyth 			else
74774a4d8c2SCharles.Forsyth 				nod2 = *l;
74874a4d8c2SCharles.Forsyth 			cgen(&nod2, &nod);
74974a4d8c2SCharles.Forsyth 			if(r->op == OCONST) {
75074a4d8c2SCharles.Forsyth 				switch(o) {
75174a4d8c2SCharles.Forsyth 				case OASDIV:
75274a4d8c2SCharles.Forsyth 					sdivgen(&nod2, r, &nod, &nod1);
75374a4d8c2SCharles.Forsyth 					goto divdone;
75474a4d8c2SCharles.Forsyth 				case OASLDIV:
75574a4d8c2SCharles.Forsyth 					udivgen(&nod2, r, &nod, &nod1);
75674a4d8c2SCharles.Forsyth 				divdone:
75774a4d8c2SCharles.Forsyth 					gmove(&nod1, &nod2);
75874a4d8c2SCharles.Forsyth 					if(nn != Z)
75974a4d8c2SCharles.Forsyth 						gmove(&nod1, nn);
76074a4d8c2SCharles.Forsyth 					goto freelxaxdx;
76174a4d8c2SCharles.Forsyth 				}
76274a4d8c2SCharles.Forsyth 			}
76374a4d8c2SCharles.Forsyth 			if(o == OASDIV || o == OASMOD)
76474a4d8c2SCharles.Forsyth 				gins(ACDQ, Z, Z);
76574a4d8c2SCharles.Forsyth 			if(o == OASLDIV || o == OASLMOD)
76674a4d8c2SCharles.Forsyth 				zeroregm(&nod1);
76774a4d8c2SCharles.Forsyth 			if(r->addable < INDEXED || r->op == OCONST ||
76874a4d8c2SCharles.Forsyth 			   !typeil[r->type->etype]) {
76974a4d8c2SCharles.Forsyth 				regalloc(&nod3, r, Z);
77074a4d8c2SCharles.Forsyth 				cgen(r, &nod3);
77174a4d8c2SCharles.Forsyth 				gopcode(o, l->type, &nod3, Z);
77274a4d8c2SCharles.Forsyth 				regfree(&nod3);
77374a4d8c2SCharles.Forsyth 			} else
77474a4d8c2SCharles.Forsyth 				gopcode(o, n->type, r, Z);
77574a4d8c2SCharles.Forsyth 		} else {
77674a4d8c2SCharles.Forsyth 			regalloc(&nod3, r, Z);
77774a4d8c2SCharles.Forsyth 			cgen(r, &nod3);
77874a4d8c2SCharles.Forsyth 			if(hardleft)
77974a4d8c2SCharles.Forsyth 				reglcgen(&nod2, l, Z);
78074a4d8c2SCharles.Forsyth 			else
78174a4d8c2SCharles.Forsyth 				nod2 = *l;
78274a4d8c2SCharles.Forsyth 			cgen(&nod2, &nod);
78374a4d8c2SCharles.Forsyth 			if(o == OASDIV || o == OASMOD)
78474a4d8c2SCharles.Forsyth 				gins(ACDQ, Z, Z);
78574a4d8c2SCharles.Forsyth 			if(o == OASLDIV || o == OASLMOD)
78674a4d8c2SCharles.Forsyth 				zeroregm(&nod1);
78774a4d8c2SCharles.Forsyth 			gopcode(o, l->type, &nod3, Z);
78874a4d8c2SCharles.Forsyth 			regfree(&nod3);
78974a4d8c2SCharles.Forsyth 		}
79074a4d8c2SCharles.Forsyth 		if(o == OASMOD || o == OASLMOD) {
79174a4d8c2SCharles.Forsyth 			gmove(&nod1, &nod2);
79274a4d8c2SCharles.Forsyth 			if(nn != Z)
79374a4d8c2SCharles.Forsyth 				gmove(&nod1, nn);
79474a4d8c2SCharles.Forsyth 		} else {
79574a4d8c2SCharles.Forsyth 			gmove(&nod, &nod2);
79674a4d8c2SCharles.Forsyth 			if(nn != Z)
79774a4d8c2SCharles.Forsyth 				gmove(&nod, nn);
79874a4d8c2SCharles.Forsyth 		}
79974a4d8c2SCharles.Forsyth 	freelxaxdx:
80074a4d8c2SCharles.Forsyth 		if(hardleft)
80174a4d8c2SCharles.Forsyth 			regfree(&nod2);
80274a4d8c2SCharles.Forsyth 		regfree(&nod);
80374a4d8c2SCharles.Forsyth 		regfree(&nod1);
80474a4d8c2SCharles.Forsyth 		break;
80574a4d8c2SCharles.Forsyth 
80674a4d8c2SCharles.Forsyth 	fop:
80774a4d8c2SCharles.Forsyth 		if(l->complex >= r->complex) {
80874a4d8c2SCharles.Forsyth 			cgen(l, &fregnode0);
80974a4d8c2SCharles.Forsyth 			if(r->addable < INDEXED) {
81074a4d8c2SCharles.Forsyth 				cgen(r, &fregnode0);
81174a4d8c2SCharles.Forsyth 				fgopcode(o, &fregnode0, &fregnode1, 1, 0);
81274a4d8c2SCharles.Forsyth 			} else
81374a4d8c2SCharles.Forsyth 				fgopcode(o, r, &fregnode0, 0, 0);
81474a4d8c2SCharles.Forsyth 		} else {
81574a4d8c2SCharles.Forsyth 			cgen(r, &fregnode0);
81674a4d8c2SCharles.Forsyth 			if(l->addable < INDEXED) {
81774a4d8c2SCharles.Forsyth 				cgen(l, &fregnode0);
81874a4d8c2SCharles.Forsyth 				fgopcode(o, &fregnode0, &fregnode1, 1, 1);
81974a4d8c2SCharles.Forsyth 			} else
82074a4d8c2SCharles.Forsyth 				fgopcode(o, l, &fregnode0, 0, 1);
82174a4d8c2SCharles.Forsyth 		}
82274a4d8c2SCharles.Forsyth 		gmove(&fregnode0, nn);
82374a4d8c2SCharles.Forsyth 		break;
82474a4d8c2SCharles.Forsyth 
82574a4d8c2SCharles.Forsyth 	asfop:
82674a4d8c2SCharles.Forsyth 		if(l->complex >= r->complex) {
82774a4d8c2SCharles.Forsyth 			if(hardleft)
82874a4d8c2SCharles.Forsyth 				reglcgen(&nod, l, Z);
82974a4d8c2SCharles.Forsyth 			else
83074a4d8c2SCharles.Forsyth 				nod = *l;
83174a4d8c2SCharles.Forsyth 			cgen(r, &fregnode0);
83274a4d8c2SCharles.Forsyth 		} else {
83374a4d8c2SCharles.Forsyth 			cgen(r, &fregnode0);
83474a4d8c2SCharles.Forsyth 			if(hardleft)
83574a4d8c2SCharles.Forsyth 				reglcgen(&nod, l, Z);
83674a4d8c2SCharles.Forsyth 			else
83774a4d8c2SCharles.Forsyth 				nod = *l;
83874a4d8c2SCharles.Forsyth 		}
83974a4d8c2SCharles.Forsyth 		if(!typefd[l->type->etype]) {
84074a4d8c2SCharles.Forsyth 			gmove(&nod, &fregnode0);
84174a4d8c2SCharles.Forsyth 			fgopcode(o, &fregnode0, &fregnode1, 1, 1);
84274a4d8c2SCharles.Forsyth 		} else
84374a4d8c2SCharles.Forsyth 			fgopcode(o, &nod, &fregnode0, 0, 1);
84474a4d8c2SCharles.Forsyth 		if(nn != Z)
84574a4d8c2SCharles.Forsyth 			gins(AFMOVD, &fregnode0, &fregnode0);
84674a4d8c2SCharles.Forsyth 		gmove(&fregnode0, &nod);
84774a4d8c2SCharles.Forsyth 		if(nn != Z)
84874a4d8c2SCharles.Forsyth 			gmove(&fregnode0, nn);
84974a4d8c2SCharles.Forsyth 		if(hardleft)
85074a4d8c2SCharles.Forsyth 			regfree(&nod);
85174a4d8c2SCharles.Forsyth 		break;
85274a4d8c2SCharles.Forsyth 
85374a4d8c2SCharles.Forsyth 	asbitop:
85474a4d8c2SCharles.Forsyth 		regalloc(&nod4, n, nn);
85574a4d8c2SCharles.Forsyth 		if(l->complex >= r->complex) {
85674a4d8c2SCharles.Forsyth 			bitload(l, &nod, &nod1, &nod2, &nod4);
85774a4d8c2SCharles.Forsyth 			regalloc(&nod3, r, Z);
85874a4d8c2SCharles.Forsyth 			cgen(r, &nod3);
85974a4d8c2SCharles.Forsyth 		} else {
86074a4d8c2SCharles.Forsyth 			regalloc(&nod3, r, Z);
86174a4d8c2SCharles.Forsyth 			cgen(r, &nod3);
86274a4d8c2SCharles.Forsyth 			bitload(l, &nod, &nod1, &nod2, &nod4);
86374a4d8c2SCharles.Forsyth 		}
86474a4d8c2SCharles.Forsyth 		gmove(&nod, &nod4);
86574a4d8c2SCharles.Forsyth 
86674a4d8c2SCharles.Forsyth 		if(typefd[nod3.type->etype])
86774a4d8c2SCharles.Forsyth 			fgopcode(o, &fregnode0, &fregnode1, 1, 1);
86874a4d8c2SCharles.Forsyth 		else {
86974a4d8c2SCharles.Forsyth 			Node onod;
87074a4d8c2SCharles.Forsyth 
87174a4d8c2SCharles.Forsyth 			/* incredible grot ... */
87274a4d8c2SCharles.Forsyth 			onod = nod3;
87374a4d8c2SCharles.Forsyth 			onod.op = o;
87474a4d8c2SCharles.Forsyth 			onod.complex = 2;
87574a4d8c2SCharles.Forsyth 			onod.addable = 0;
87674a4d8c2SCharles.Forsyth 			onod.type = tfield;
87774a4d8c2SCharles.Forsyth 			onod.left = &nod4;
87874a4d8c2SCharles.Forsyth 			onod.right = &nod3;
87974a4d8c2SCharles.Forsyth 			cgen(&onod, Z);
88074a4d8c2SCharles.Forsyth 		}
88174a4d8c2SCharles.Forsyth 		regfree(&nod3);
88274a4d8c2SCharles.Forsyth 		gmove(&nod4, &nod);
88374a4d8c2SCharles.Forsyth 		regfree(&nod4);
88474a4d8c2SCharles.Forsyth 		bitstore(l, &nod, &nod1, &nod2, nn);
88574a4d8c2SCharles.Forsyth 		break;
88674a4d8c2SCharles.Forsyth 
88774a4d8c2SCharles.Forsyth 	case OADDR:
88874a4d8c2SCharles.Forsyth 		if(nn == Z) {
88974a4d8c2SCharles.Forsyth 			nullwarn(l, Z);
89074a4d8c2SCharles.Forsyth 			break;
89174a4d8c2SCharles.Forsyth 		}
89274a4d8c2SCharles.Forsyth 		lcgen(l, nn);
89374a4d8c2SCharles.Forsyth 		break;
89474a4d8c2SCharles.Forsyth 
89574a4d8c2SCharles.Forsyth 	case OFUNC:
896*45a20ab7Sforsyth 		l = uncomma(l);
89774a4d8c2SCharles.Forsyth 		if(l->complex >= FNX) {
89874a4d8c2SCharles.Forsyth 			if(l->op != OIND)
89974a4d8c2SCharles.Forsyth 				diag(n, "bad function call");
90074a4d8c2SCharles.Forsyth 
90174a4d8c2SCharles.Forsyth 			regret(&nod, l->left);
90274a4d8c2SCharles.Forsyth 			cgen(l->left, &nod);
90374a4d8c2SCharles.Forsyth 			regsalloc(&nod1, l->left);
90474a4d8c2SCharles.Forsyth 			gmove(&nod, &nod1);
90574a4d8c2SCharles.Forsyth 			regfree(&nod);
90674a4d8c2SCharles.Forsyth 
90774a4d8c2SCharles.Forsyth 			nod = *n;
90874a4d8c2SCharles.Forsyth 			nod.left = &nod2;
90974a4d8c2SCharles.Forsyth 			nod2 = *l;
91074a4d8c2SCharles.Forsyth 			nod2.left = &nod1;
91174a4d8c2SCharles.Forsyth 			nod2.complex = 1;
91274a4d8c2SCharles.Forsyth 			cgen(&nod, nn);
91374a4d8c2SCharles.Forsyth 
91474a4d8c2SCharles.Forsyth 			return;
91574a4d8c2SCharles.Forsyth 		}
91674a4d8c2SCharles.Forsyth 		gargs(r, &nod, &nod1);
91774a4d8c2SCharles.Forsyth 		if(l->addable < INDEXED) {
91874a4d8c2SCharles.Forsyth 			reglcgen(&nod, l, nn);
91974a4d8c2SCharles.Forsyth 			nod.op = OREGISTER;
92074a4d8c2SCharles.Forsyth 			gopcode(OFUNC, n->type, Z, &nod);
92174a4d8c2SCharles.Forsyth 			regfree(&nod);
92274a4d8c2SCharles.Forsyth 		} else
92374a4d8c2SCharles.Forsyth 			gopcode(OFUNC, n->type, Z, l);
924c0927006Sforsyth 		if(REGARG>=0 && reg[REGARG])
92574a4d8c2SCharles.Forsyth 			reg[REGARG]--;
92674a4d8c2SCharles.Forsyth 		if(nn != Z) {
92774a4d8c2SCharles.Forsyth 			regret(&nod, n);
92874a4d8c2SCharles.Forsyth 			gmove(&nod, nn);
92974a4d8c2SCharles.Forsyth 			regfree(&nod);
93074a4d8c2SCharles.Forsyth 		} else
93174a4d8c2SCharles.Forsyth 		if(typefd[n->type->etype])
93274a4d8c2SCharles.Forsyth 			gins(AFMOVDP, &fregnode0, &fregnode0);
93374a4d8c2SCharles.Forsyth 		break;
93474a4d8c2SCharles.Forsyth 
93574a4d8c2SCharles.Forsyth 	case OIND:
93674a4d8c2SCharles.Forsyth 		if(nn == Z) {
93774a4d8c2SCharles.Forsyth 			nullwarn(l, Z);
93874a4d8c2SCharles.Forsyth 			break;
93974a4d8c2SCharles.Forsyth 		}
94074a4d8c2SCharles.Forsyth 		regialloc(&nod, n, nn);
94174a4d8c2SCharles.Forsyth 		r = l;
94274a4d8c2SCharles.Forsyth 		while(r->op == OADD)
94374a4d8c2SCharles.Forsyth 			r = r->right;
94474a4d8c2SCharles.Forsyth 		if(sconst(r)) {
94574a4d8c2SCharles.Forsyth 			v = r->vconst;
94674a4d8c2SCharles.Forsyth 			r->vconst = 0;
94774a4d8c2SCharles.Forsyth 			cgen(l, &nod);
94874a4d8c2SCharles.Forsyth 			nod.xoffset += v;
94974a4d8c2SCharles.Forsyth 			r->vconst = v;
95074a4d8c2SCharles.Forsyth 		} else
95174a4d8c2SCharles.Forsyth 			cgen(l, &nod);
95274a4d8c2SCharles.Forsyth 		regind(&nod, n);
95374a4d8c2SCharles.Forsyth 		gmove(&nod, nn);
95474a4d8c2SCharles.Forsyth 		regfree(&nod);
95574a4d8c2SCharles.Forsyth 		break;
95674a4d8c2SCharles.Forsyth 
95774a4d8c2SCharles.Forsyth 	case OEQ:
95874a4d8c2SCharles.Forsyth 	case ONE:
95974a4d8c2SCharles.Forsyth 	case OLE:
96074a4d8c2SCharles.Forsyth 	case OLT:
96174a4d8c2SCharles.Forsyth 	case OGE:
96274a4d8c2SCharles.Forsyth 	case OGT:
96374a4d8c2SCharles.Forsyth 	case OLO:
96474a4d8c2SCharles.Forsyth 	case OLS:
96574a4d8c2SCharles.Forsyth 	case OHI:
96674a4d8c2SCharles.Forsyth 	case OHS:
96774a4d8c2SCharles.Forsyth 		if(nn == Z) {
96874a4d8c2SCharles.Forsyth 			nullwarn(l, r);
96974a4d8c2SCharles.Forsyth 			break;
97074a4d8c2SCharles.Forsyth 		}
97174a4d8c2SCharles.Forsyth 		boolgen(n, 1, nn);
97274a4d8c2SCharles.Forsyth 		break;
97374a4d8c2SCharles.Forsyth 
97474a4d8c2SCharles.Forsyth 	case OANDAND:
97574a4d8c2SCharles.Forsyth 	case OOROR:
97674a4d8c2SCharles.Forsyth 		boolgen(n, 1, nn);
97774a4d8c2SCharles.Forsyth 		if(nn == Z)
97874a4d8c2SCharles.Forsyth 			patch(p, pc);
97974a4d8c2SCharles.Forsyth 		break;
98074a4d8c2SCharles.Forsyth 
98174a4d8c2SCharles.Forsyth 	case ONOT:
98274a4d8c2SCharles.Forsyth 		if(nn == Z) {
98374a4d8c2SCharles.Forsyth 			nullwarn(l, Z);
98474a4d8c2SCharles.Forsyth 			break;
98574a4d8c2SCharles.Forsyth 		}
98674a4d8c2SCharles.Forsyth 		boolgen(n, 1, nn);
98774a4d8c2SCharles.Forsyth 		break;
98874a4d8c2SCharles.Forsyth 
98974a4d8c2SCharles.Forsyth 	case OCOMMA:
99074a4d8c2SCharles.Forsyth 		cgen(l, Z);
99174a4d8c2SCharles.Forsyth 		cgen(r, nn);
99274a4d8c2SCharles.Forsyth 		break;
99374a4d8c2SCharles.Forsyth 
99474a4d8c2SCharles.Forsyth 	case OCAST:
99574a4d8c2SCharles.Forsyth 		if(nn == Z) {
99674a4d8c2SCharles.Forsyth 			nullwarn(l, Z);
99774a4d8c2SCharles.Forsyth 			break;
99874a4d8c2SCharles.Forsyth 		}
99974a4d8c2SCharles.Forsyth 		/*
100074a4d8c2SCharles.Forsyth 		 * convert from types l->n->nn
100174a4d8c2SCharles.Forsyth 		 */
100274a4d8c2SCharles.Forsyth 		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
100374a4d8c2SCharles.Forsyth 			/* both null, gen l->nn */
100474a4d8c2SCharles.Forsyth 			cgen(l, nn);
100574a4d8c2SCharles.Forsyth 			break;
100674a4d8c2SCharles.Forsyth 		}
100774a4d8c2SCharles.Forsyth 		if(typev[l->type->etype]) {
100874a4d8c2SCharles.Forsyth 			cgen64(n, nn);
100974a4d8c2SCharles.Forsyth 			break;
101074a4d8c2SCharles.Forsyth 		}
101174a4d8c2SCharles.Forsyth 		regalloc(&nod, l, nn);
101274a4d8c2SCharles.Forsyth 		cgen(l, &nod);
101374a4d8c2SCharles.Forsyth 		regalloc(&nod1, n, &nod);
101474a4d8c2SCharles.Forsyth 		gmove(&nod, &nod1);
101574a4d8c2SCharles.Forsyth 		gmove(&nod1, nn);
101674a4d8c2SCharles.Forsyth 		regfree(&nod1);
101774a4d8c2SCharles.Forsyth 		regfree(&nod);
101874a4d8c2SCharles.Forsyth 		break;
101974a4d8c2SCharles.Forsyth 
102074a4d8c2SCharles.Forsyth 	case ODOT:
102174a4d8c2SCharles.Forsyth 		sugen(l, nodrat, l->type->width);
102274a4d8c2SCharles.Forsyth 		if(nn == Z)
102374a4d8c2SCharles.Forsyth 			break;
102474a4d8c2SCharles.Forsyth 		warn(n, "non-interruptable temporary");
102574a4d8c2SCharles.Forsyth 		nod = *nodrat;
102674a4d8c2SCharles.Forsyth 		if(!r || r->op != OCONST) {
102774a4d8c2SCharles.Forsyth 			diag(n, "DOT and no offset");
102874a4d8c2SCharles.Forsyth 			break;
102974a4d8c2SCharles.Forsyth 		}
103074a4d8c2SCharles.Forsyth 		nod.xoffset += (long)r->vconst;
103174a4d8c2SCharles.Forsyth 		nod.type = n->type;
103274a4d8c2SCharles.Forsyth 		cgen(&nod, nn);
103374a4d8c2SCharles.Forsyth 		break;
103474a4d8c2SCharles.Forsyth 
103574a4d8c2SCharles.Forsyth 	case OCOND:
103674a4d8c2SCharles.Forsyth 		bcgen(l, 1);
103774a4d8c2SCharles.Forsyth 		p1 = p;
103874a4d8c2SCharles.Forsyth 		cgen(r->left, nn);
103974a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
104074a4d8c2SCharles.Forsyth 		patch(p1, pc);
104174a4d8c2SCharles.Forsyth 		p1 = p;
104274a4d8c2SCharles.Forsyth 		cgen(r->right, nn);
104374a4d8c2SCharles.Forsyth 		patch(p1, pc);
104474a4d8c2SCharles.Forsyth 		break;
104574a4d8c2SCharles.Forsyth 
104674a4d8c2SCharles.Forsyth 	case OPOSTINC:
104774a4d8c2SCharles.Forsyth 	case OPOSTDEC:
104874a4d8c2SCharles.Forsyth 		v = 1;
104974a4d8c2SCharles.Forsyth 		if(l->type->etype == TIND)
105074a4d8c2SCharles.Forsyth 			v = l->type->link->width;
105174a4d8c2SCharles.Forsyth 		if(o == OPOSTDEC)
105274a4d8c2SCharles.Forsyth 			v = -v;
105374a4d8c2SCharles.Forsyth 		if(l->op == OBIT)
105474a4d8c2SCharles.Forsyth 			goto bitinc;
105574a4d8c2SCharles.Forsyth 		if(nn == Z)
105674a4d8c2SCharles.Forsyth 			goto pre;
105774a4d8c2SCharles.Forsyth 
105874a4d8c2SCharles.Forsyth 		if(hardleft)
105974a4d8c2SCharles.Forsyth 			reglcgen(&nod, l, Z);
106074a4d8c2SCharles.Forsyth 		else
106174a4d8c2SCharles.Forsyth 			nod = *l;
106274a4d8c2SCharles.Forsyth 
106374a4d8c2SCharles.Forsyth 		if(typefd[n->type->etype])
106474a4d8c2SCharles.Forsyth 			goto fltinc;
106574a4d8c2SCharles.Forsyth 		gmove(&nod, nn);
106674a4d8c2SCharles.Forsyth 		gopcode(OADD, n->type, nodconst(v), &nod);
106774a4d8c2SCharles.Forsyth 		if(hardleft)
106874a4d8c2SCharles.Forsyth 			regfree(&nod);
106974a4d8c2SCharles.Forsyth 		break;
107074a4d8c2SCharles.Forsyth 
107174a4d8c2SCharles.Forsyth 	case OPREINC:
107274a4d8c2SCharles.Forsyth 	case OPREDEC:
107374a4d8c2SCharles.Forsyth 		v = 1;
107474a4d8c2SCharles.Forsyth 		if(l->type->etype == TIND)
107574a4d8c2SCharles.Forsyth 			v = l->type->link->width;
107674a4d8c2SCharles.Forsyth 		if(o == OPREDEC)
107774a4d8c2SCharles.Forsyth 			v = -v;
107874a4d8c2SCharles.Forsyth 		if(l->op == OBIT)
107974a4d8c2SCharles.Forsyth 			goto bitinc;
108074a4d8c2SCharles.Forsyth 
108174a4d8c2SCharles.Forsyth 	pre:
108274a4d8c2SCharles.Forsyth 		if(hardleft)
108374a4d8c2SCharles.Forsyth 			reglcgen(&nod, l, Z);
108474a4d8c2SCharles.Forsyth 		else
108574a4d8c2SCharles.Forsyth 			nod = *l;
108674a4d8c2SCharles.Forsyth 		if(typefd[n->type->etype])
108774a4d8c2SCharles.Forsyth 			goto fltinc;
108874a4d8c2SCharles.Forsyth 		gopcode(OADD, n->type, nodconst(v), &nod);
108974a4d8c2SCharles.Forsyth 		if(nn != Z)
109074a4d8c2SCharles.Forsyth 			gmove(&nod, nn);
109174a4d8c2SCharles.Forsyth 		if(hardleft)
109274a4d8c2SCharles.Forsyth 			regfree(&nod);
109374a4d8c2SCharles.Forsyth 		break;
109474a4d8c2SCharles.Forsyth 
109574a4d8c2SCharles.Forsyth 	fltinc:
109674a4d8c2SCharles.Forsyth 		gmove(&nod, &fregnode0);
109774a4d8c2SCharles.Forsyth 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC))
109874a4d8c2SCharles.Forsyth 			gins(AFMOVD, &fregnode0, &fregnode0);
109974a4d8c2SCharles.Forsyth 		gins(AFLD1, Z, Z);
110074a4d8c2SCharles.Forsyth 		if(v < 0)
110174a4d8c2SCharles.Forsyth 			fgopcode(OSUB, &fregnode0, &fregnode1, 1, 0);
110274a4d8c2SCharles.Forsyth 		else
110374a4d8c2SCharles.Forsyth 			fgopcode(OADD, &fregnode0, &fregnode1, 1, 0);
110474a4d8c2SCharles.Forsyth 		if(nn != Z && (o == OPREINC || o == OPREDEC))
110574a4d8c2SCharles.Forsyth 			gins(AFMOVD, &fregnode0, &fregnode0);
110674a4d8c2SCharles.Forsyth 		gmove(&fregnode0, &nod);
110774a4d8c2SCharles.Forsyth 		if(hardleft)
110874a4d8c2SCharles.Forsyth 			regfree(&nod);
110974a4d8c2SCharles.Forsyth 		break;
111074a4d8c2SCharles.Forsyth 
111174a4d8c2SCharles.Forsyth 	bitinc:
111274a4d8c2SCharles.Forsyth 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
111374a4d8c2SCharles.Forsyth 			bitload(l, &nod, &nod1, &nod2, Z);
111474a4d8c2SCharles.Forsyth 			gmove(&nod, nn);
111574a4d8c2SCharles.Forsyth 			gopcode(OADD, tfield, nodconst(v), &nod);
111674a4d8c2SCharles.Forsyth 			bitstore(l, &nod, &nod1, &nod2, Z);
111774a4d8c2SCharles.Forsyth 			break;
111874a4d8c2SCharles.Forsyth 		}
111974a4d8c2SCharles.Forsyth 		bitload(l, &nod, &nod1, &nod2, nn);
112074a4d8c2SCharles.Forsyth 		gopcode(OADD, tfield, nodconst(v), &nod);
112174a4d8c2SCharles.Forsyth 		bitstore(l, &nod, &nod1, &nod2, nn);
112274a4d8c2SCharles.Forsyth 		break;
112374a4d8c2SCharles.Forsyth 	}
112474a4d8c2SCharles.Forsyth done:
112574a4d8c2SCharles.Forsyth 	cursafe = curs;
112674a4d8c2SCharles.Forsyth }
112774a4d8c2SCharles.Forsyth 
112874a4d8c2SCharles.Forsyth void
reglcgen(Node * t,Node * n,Node * nn)112974a4d8c2SCharles.Forsyth reglcgen(Node *t, Node *n, Node *nn)
113074a4d8c2SCharles.Forsyth {
113174a4d8c2SCharles.Forsyth 	Node *r;
113274a4d8c2SCharles.Forsyth 	long v;
113374a4d8c2SCharles.Forsyth 
113474a4d8c2SCharles.Forsyth 	regialloc(t, n, nn);
113574a4d8c2SCharles.Forsyth 	if(n->op == OIND) {
113674a4d8c2SCharles.Forsyth 		r = n->left;
113774a4d8c2SCharles.Forsyth 		while(r->op == OADD)
113874a4d8c2SCharles.Forsyth 			r = r->right;
113974a4d8c2SCharles.Forsyth 		if(sconst(r)) {
114074a4d8c2SCharles.Forsyth 			v = r->vconst;
114174a4d8c2SCharles.Forsyth 			r->vconst = 0;
114274a4d8c2SCharles.Forsyth 			lcgen(n, t);
114374a4d8c2SCharles.Forsyth 			t->xoffset += v;
114474a4d8c2SCharles.Forsyth 			r->vconst = v;
114574a4d8c2SCharles.Forsyth 			regind(t, n);
114674a4d8c2SCharles.Forsyth 			return;
114774a4d8c2SCharles.Forsyth 		}
114874a4d8c2SCharles.Forsyth 	}
114974a4d8c2SCharles.Forsyth 	lcgen(n, t);
115074a4d8c2SCharles.Forsyth 	regind(t, n);
115174a4d8c2SCharles.Forsyth }
115274a4d8c2SCharles.Forsyth 
115374a4d8c2SCharles.Forsyth void
lcgen(Node * n,Node * nn)115474a4d8c2SCharles.Forsyth lcgen(Node *n, Node *nn)
115574a4d8c2SCharles.Forsyth {
115674a4d8c2SCharles.Forsyth 	Prog *p1;
115774a4d8c2SCharles.Forsyth 	Node nod;
115874a4d8c2SCharles.Forsyth 
115974a4d8c2SCharles.Forsyth 	if(debug['g']) {
116074a4d8c2SCharles.Forsyth 		prtree(nn, "lcgen lhs");
116174a4d8c2SCharles.Forsyth 		prtree(n, "lcgen");
116274a4d8c2SCharles.Forsyth 	}
116374a4d8c2SCharles.Forsyth 	if(n == Z || n->type == T)
116474a4d8c2SCharles.Forsyth 		return;
116574a4d8c2SCharles.Forsyth 	if(nn == Z) {
116674a4d8c2SCharles.Forsyth 		nn = &nod;
116774a4d8c2SCharles.Forsyth 		regalloc(&nod, n, Z);
116874a4d8c2SCharles.Forsyth 	}
116974a4d8c2SCharles.Forsyth 	switch(n->op) {
117074a4d8c2SCharles.Forsyth 	default:
117174a4d8c2SCharles.Forsyth 		if(n->addable < INDEXED) {
117274a4d8c2SCharles.Forsyth 			diag(n, "unknown op in lcgen: %O", n->op);
117374a4d8c2SCharles.Forsyth 			break;
117474a4d8c2SCharles.Forsyth 		}
117574a4d8c2SCharles.Forsyth 		gopcode(OADDR, n->type, n, nn);
117674a4d8c2SCharles.Forsyth 		break;
117774a4d8c2SCharles.Forsyth 
117874a4d8c2SCharles.Forsyth 	case OCOMMA:
117974a4d8c2SCharles.Forsyth 		cgen(n->left, n->left);
118074a4d8c2SCharles.Forsyth 		lcgen(n->right, nn);
118174a4d8c2SCharles.Forsyth 		break;
118274a4d8c2SCharles.Forsyth 
118374a4d8c2SCharles.Forsyth 	case OIND:
118474a4d8c2SCharles.Forsyth 		cgen(n->left, nn);
118574a4d8c2SCharles.Forsyth 		break;
118674a4d8c2SCharles.Forsyth 
118774a4d8c2SCharles.Forsyth 	case OCOND:
118874a4d8c2SCharles.Forsyth 		bcgen(n->left, 1);
118974a4d8c2SCharles.Forsyth 		p1 = p;
119074a4d8c2SCharles.Forsyth 		lcgen(n->right->left, nn);
119174a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
119274a4d8c2SCharles.Forsyth 		patch(p1, pc);
119374a4d8c2SCharles.Forsyth 		p1 = p;
119474a4d8c2SCharles.Forsyth 		lcgen(n->right->right, nn);
119574a4d8c2SCharles.Forsyth 		patch(p1, pc);
119674a4d8c2SCharles.Forsyth 		break;
119774a4d8c2SCharles.Forsyth 	}
119874a4d8c2SCharles.Forsyth }
119974a4d8c2SCharles.Forsyth 
120074a4d8c2SCharles.Forsyth void
bcgen(Node * n,int true)120174a4d8c2SCharles.Forsyth bcgen(Node *n, int true)
120274a4d8c2SCharles.Forsyth {
120374a4d8c2SCharles.Forsyth 
120474a4d8c2SCharles.Forsyth 	if(n->type == T)
120574a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
120674a4d8c2SCharles.Forsyth 	else
120774a4d8c2SCharles.Forsyth 		boolgen(n, true, Z);
120874a4d8c2SCharles.Forsyth }
120974a4d8c2SCharles.Forsyth 
121074a4d8c2SCharles.Forsyth void
boolgen(Node * n,int true,Node * nn)121174a4d8c2SCharles.Forsyth boolgen(Node *n, int true, Node *nn)
121274a4d8c2SCharles.Forsyth {
121374a4d8c2SCharles.Forsyth 	int o;
121474a4d8c2SCharles.Forsyth 	Prog *p1, *p2;
121574a4d8c2SCharles.Forsyth 	Node *l, *r, nod, nod1;
121674a4d8c2SCharles.Forsyth 	long curs;
121774a4d8c2SCharles.Forsyth 
121874a4d8c2SCharles.Forsyth 	if(debug['g']) {
121974a4d8c2SCharles.Forsyth 		prtree(nn, "boolgen lhs");
122074a4d8c2SCharles.Forsyth 		prtree(n, "boolgen");
122174a4d8c2SCharles.Forsyth 	}
122274a4d8c2SCharles.Forsyth 	curs = cursafe;
122374a4d8c2SCharles.Forsyth 	l = n->left;
122474a4d8c2SCharles.Forsyth 	r = n->right;
122574a4d8c2SCharles.Forsyth 	switch(n->op) {
122674a4d8c2SCharles.Forsyth 
122774a4d8c2SCharles.Forsyth 	default:
122874a4d8c2SCharles.Forsyth 		if(typev[n->type->etype]) {
122974a4d8c2SCharles.Forsyth 			testv(n, true);
123074a4d8c2SCharles.Forsyth 			goto com;
123174a4d8c2SCharles.Forsyth 		}
123274a4d8c2SCharles.Forsyth 		o = ONE;
123374a4d8c2SCharles.Forsyth 		if(true)
123474a4d8c2SCharles.Forsyth 			o = OEQ;
123574a4d8c2SCharles.Forsyth 		if(typefd[n->type->etype]) {
123674a4d8c2SCharles.Forsyth 			if(n->addable < INDEXED) {
123774a4d8c2SCharles.Forsyth 				cgen(n, &fregnode0);
123874a4d8c2SCharles.Forsyth 				gins(AFLDZ, Z, Z);
123974a4d8c2SCharles.Forsyth 				fgopcode(o, &fregnode0, &fregnode1, 1, 1);
124074a4d8c2SCharles.Forsyth 			} else {
124174a4d8c2SCharles.Forsyth 				gins(AFLDZ, Z, Z);
124274a4d8c2SCharles.Forsyth 				fgopcode(o, n, &fregnode0, 0, 1);
124374a4d8c2SCharles.Forsyth 			}
124474a4d8c2SCharles.Forsyth 			goto com;
124574a4d8c2SCharles.Forsyth 		}
124674a4d8c2SCharles.Forsyth 		/* bad, 13 is address of external that becomes constant */
124774a4d8c2SCharles.Forsyth 		if(n->addable >= INDEXED && n->addable != 13) {
124874a4d8c2SCharles.Forsyth 			gopcode(o, n->type, n, nodconst(0));
124974a4d8c2SCharles.Forsyth 			goto com;
125074a4d8c2SCharles.Forsyth 		}
125174a4d8c2SCharles.Forsyth 		regalloc(&nod, n, nn);
125274a4d8c2SCharles.Forsyth 		cgen(n, &nod);
125374a4d8c2SCharles.Forsyth 		gopcode(o, n->type, &nod, nodconst(0));
125474a4d8c2SCharles.Forsyth 		regfree(&nod);
125574a4d8c2SCharles.Forsyth 		goto com;
125674a4d8c2SCharles.Forsyth 
125774a4d8c2SCharles.Forsyth 	case OCONST:
125874a4d8c2SCharles.Forsyth 		o = vconst(n);
125974a4d8c2SCharles.Forsyth 		if(!true)
126074a4d8c2SCharles.Forsyth 			o = !o;
126174a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
126274a4d8c2SCharles.Forsyth 		if(o) {
126374a4d8c2SCharles.Forsyth 			p1 = p;
126474a4d8c2SCharles.Forsyth 			gbranch(OGOTO);
126574a4d8c2SCharles.Forsyth 			patch(p1, pc);
126674a4d8c2SCharles.Forsyth 		}
126774a4d8c2SCharles.Forsyth 		goto com;
126874a4d8c2SCharles.Forsyth 
126974a4d8c2SCharles.Forsyth 	case OCOMMA:
127074a4d8c2SCharles.Forsyth 		cgen(l, Z);
127174a4d8c2SCharles.Forsyth 		boolgen(r, true, nn);
127274a4d8c2SCharles.Forsyth 		break;
127374a4d8c2SCharles.Forsyth 
127474a4d8c2SCharles.Forsyth 	case ONOT:
127574a4d8c2SCharles.Forsyth 		boolgen(l, !true, nn);
127674a4d8c2SCharles.Forsyth 		break;
127774a4d8c2SCharles.Forsyth 
127874a4d8c2SCharles.Forsyth 	case OCOND:
127974a4d8c2SCharles.Forsyth 		bcgen(l, 1);
128074a4d8c2SCharles.Forsyth 		p1 = p;
128174a4d8c2SCharles.Forsyth 		bcgen(r->left, true);
128274a4d8c2SCharles.Forsyth 		p2 = p;
128374a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
128474a4d8c2SCharles.Forsyth 		patch(p1, pc);
128574a4d8c2SCharles.Forsyth 		p1 = p;
128674a4d8c2SCharles.Forsyth 		bcgen(r->right, !true);
128774a4d8c2SCharles.Forsyth 		patch(p2, pc);
128874a4d8c2SCharles.Forsyth 		p2 = p;
128974a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
129074a4d8c2SCharles.Forsyth 		patch(p1, pc);
129174a4d8c2SCharles.Forsyth 		patch(p2, pc);
129274a4d8c2SCharles.Forsyth 		goto com;
129374a4d8c2SCharles.Forsyth 
129474a4d8c2SCharles.Forsyth 	case OANDAND:
129574a4d8c2SCharles.Forsyth 		if(!true)
129674a4d8c2SCharles.Forsyth 			goto caseor;
129774a4d8c2SCharles.Forsyth 
129874a4d8c2SCharles.Forsyth 	caseand:
129974a4d8c2SCharles.Forsyth 		bcgen(l, true);
130074a4d8c2SCharles.Forsyth 		p1 = p;
130174a4d8c2SCharles.Forsyth 		bcgen(r, !true);
130274a4d8c2SCharles.Forsyth 		p2 = p;
130374a4d8c2SCharles.Forsyth 		patch(p1, pc);
130474a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
130574a4d8c2SCharles.Forsyth 		patch(p2, pc);
130674a4d8c2SCharles.Forsyth 		goto com;
130774a4d8c2SCharles.Forsyth 
130874a4d8c2SCharles.Forsyth 	case OOROR:
130974a4d8c2SCharles.Forsyth 		if(!true)
131074a4d8c2SCharles.Forsyth 			goto caseand;
131174a4d8c2SCharles.Forsyth 
131274a4d8c2SCharles.Forsyth 	caseor:
131374a4d8c2SCharles.Forsyth 		bcgen(l, !true);
131474a4d8c2SCharles.Forsyth 		p1 = p;
131574a4d8c2SCharles.Forsyth 		bcgen(r, !true);
131674a4d8c2SCharles.Forsyth 		p2 = p;
131774a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
131874a4d8c2SCharles.Forsyth 		patch(p1, pc);
131974a4d8c2SCharles.Forsyth 		patch(p2, pc);
132074a4d8c2SCharles.Forsyth 		goto com;
132174a4d8c2SCharles.Forsyth 
132274a4d8c2SCharles.Forsyth 	case OEQ:
132374a4d8c2SCharles.Forsyth 	case ONE:
132474a4d8c2SCharles.Forsyth 	case OLE:
132574a4d8c2SCharles.Forsyth 	case OLT:
132674a4d8c2SCharles.Forsyth 	case OGE:
132774a4d8c2SCharles.Forsyth 	case OGT:
132874a4d8c2SCharles.Forsyth 	case OHI:
132974a4d8c2SCharles.Forsyth 	case OHS:
133074a4d8c2SCharles.Forsyth 	case OLO:
133174a4d8c2SCharles.Forsyth 	case OLS:
133274a4d8c2SCharles.Forsyth 		o = n->op;
133374a4d8c2SCharles.Forsyth 		if(typev[l->type->etype]) {
133474a4d8c2SCharles.Forsyth 			if(!true)
133574a4d8c2SCharles.Forsyth 				n->op = comrel[relindex(o)];
133674a4d8c2SCharles.Forsyth 			cgen64(n, Z);
133774a4d8c2SCharles.Forsyth 			goto com;
133874a4d8c2SCharles.Forsyth 		}
133974a4d8c2SCharles.Forsyth 		if(true)
134074a4d8c2SCharles.Forsyth 			o = comrel[relindex(o)];
134174a4d8c2SCharles.Forsyth 		if(l->complex >= FNX && r->complex >= FNX) {
134274a4d8c2SCharles.Forsyth 			regret(&nod, r);
134374a4d8c2SCharles.Forsyth 			cgen(r, &nod);
134474a4d8c2SCharles.Forsyth 			regsalloc(&nod1, r);
134574a4d8c2SCharles.Forsyth 			gmove(&nod, &nod1);
134674a4d8c2SCharles.Forsyth 			regfree(&nod);
134774a4d8c2SCharles.Forsyth 			nod = *n;
134874a4d8c2SCharles.Forsyth 			nod.right = &nod1;
134974a4d8c2SCharles.Forsyth 			boolgen(&nod, true, nn);
135074a4d8c2SCharles.Forsyth 			break;
135174a4d8c2SCharles.Forsyth 		}
135274a4d8c2SCharles.Forsyth 		if(typefd[l->type->etype]) {
135374a4d8c2SCharles.Forsyth 			if(l->complex >= r->complex) {
135474a4d8c2SCharles.Forsyth 				cgen(l, &fregnode0);
135574a4d8c2SCharles.Forsyth 				if(r->addable < INDEXED) {
135674a4d8c2SCharles.Forsyth 					cgen(r, &fregnode0);
135774a4d8c2SCharles.Forsyth 					o = invrel[relindex(o)];
135874a4d8c2SCharles.Forsyth 					fgopcode(o, &fregnode0, &fregnode1, 1, 1);
135974a4d8c2SCharles.Forsyth 				} else
136074a4d8c2SCharles.Forsyth 					fgopcode(o, r, &fregnode0, 0, 1);
136174a4d8c2SCharles.Forsyth 			} else {
136274a4d8c2SCharles.Forsyth 				o = invrel[relindex(o)];
136374a4d8c2SCharles.Forsyth 				cgen(r, &fregnode0);
136474a4d8c2SCharles.Forsyth 				if(l->addable < INDEXED) {
136574a4d8c2SCharles.Forsyth 					cgen(l, &fregnode0);
136674a4d8c2SCharles.Forsyth 					o = invrel[relindex(o)];
136774a4d8c2SCharles.Forsyth 					fgopcode(o, &fregnode0, &fregnode1, 1, 1);
136874a4d8c2SCharles.Forsyth 				} else
136974a4d8c2SCharles.Forsyth 					fgopcode(o, l, &fregnode0, 0, 1);
137074a4d8c2SCharles.Forsyth 			}
137174a4d8c2SCharles.Forsyth 			goto com;
137274a4d8c2SCharles.Forsyth 		}
137374a4d8c2SCharles.Forsyth 		if(l->op == OCONST) {
137474a4d8c2SCharles.Forsyth 			o = invrel[relindex(o)];
137574a4d8c2SCharles.Forsyth 			/* bad, 13 is address of external that becomes constant */
137674a4d8c2SCharles.Forsyth 			if(r->addable < INDEXED || r->addable == 13) {
137774a4d8c2SCharles.Forsyth 				regalloc(&nod, r, nn);
137874a4d8c2SCharles.Forsyth 				cgen(r, &nod);
137974a4d8c2SCharles.Forsyth 				gopcode(o, l->type, &nod, l);
138074a4d8c2SCharles.Forsyth 				regfree(&nod);
138174a4d8c2SCharles.Forsyth 			} else
138274a4d8c2SCharles.Forsyth 				gopcode(o, l->type, r, l);
138374a4d8c2SCharles.Forsyth 			goto com;
138474a4d8c2SCharles.Forsyth 		}
138574a4d8c2SCharles.Forsyth 		if(l->complex >= r->complex) {
138674a4d8c2SCharles.Forsyth 			regalloc(&nod, l, nn);
138774a4d8c2SCharles.Forsyth 			cgen(l, &nod);
138874a4d8c2SCharles.Forsyth 			if(r->addable < INDEXED) {
138974a4d8c2SCharles.Forsyth 				regalloc(&nod1, r, Z);
139074a4d8c2SCharles.Forsyth 				cgen(r, &nod1);
139174a4d8c2SCharles.Forsyth 				gopcode(o, l->type, &nod, &nod1);
139274a4d8c2SCharles.Forsyth 				regfree(&nod1);
139374a4d8c2SCharles.Forsyth 			} else
139474a4d8c2SCharles.Forsyth 				gopcode(o, l->type, &nod, r);
139574a4d8c2SCharles.Forsyth 			regfree(&nod);
139674a4d8c2SCharles.Forsyth 			goto com;
139774a4d8c2SCharles.Forsyth 		}
139874a4d8c2SCharles.Forsyth 		regalloc(&nod, r, nn);
139974a4d8c2SCharles.Forsyth 		cgen(r, &nod);
140074a4d8c2SCharles.Forsyth 		if(l->addable < INDEXED || l->addable == 13) {
140174a4d8c2SCharles.Forsyth 			regalloc(&nod1, l, Z);
140274a4d8c2SCharles.Forsyth 			cgen(l, &nod1);
140374a4d8c2SCharles.Forsyth 			if(typechlp[l->type->etype])
140474a4d8c2SCharles.Forsyth 				gopcode(o, types[TINT], &nod1, &nod);
140574a4d8c2SCharles.Forsyth 			else
140674a4d8c2SCharles.Forsyth 				gopcode(o, l->type, &nod1, &nod);
140774a4d8c2SCharles.Forsyth 			regfree(&nod1);
140874a4d8c2SCharles.Forsyth 		} else
140974a4d8c2SCharles.Forsyth 			gopcode(o, l->type, l, &nod);
141074a4d8c2SCharles.Forsyth 		regfree(&nod);
141174a4d8c2SCharles.Forsyth 
141274a4d8c2SCharles.Forsyth 	com:
141374a4d8c2SCharles.Forsyth 		if(nn != Z) {
141474a4d8c2SCharles.Forsyth 			p1 = p;
141574a4d8c2SCharles.Forsyth 			gmove(nodconst(1L), nn);
141674a4d8c2SCharles.Forsyth 			gbranch(OGOTO);
141774a4d8c2SCharles.Forsyth 			p2 = p;
141874a4d8c2SCharles.Forsyth 			patch(p1, pc);
141974a4d8c2SCharles.Forsyth 			gmove(nodconst(0L), nn);
142074a4d8c2SCharles.Forsyth 			patch(p2, pc);
142174a4d8c2SCharles.Forsyth 		}
142274a4d8c2SCharles.Forsyth 		break;
142374a4d8c2SCharles.Forsyth 	}
142474a4d8c2SCharles.Forsyth 	cursafe = curs;
142574a4d8c2SCharles.Forsyth }
142674a4d8c2SCharles.Forsyth 
142774a4d8c2SCharles.Forsyth void
sugen(Node * n,Node * nn,long w)142874a4d8c2SCharles.Forsyth sugen(Node *n, Node *nn, long w)
142974a4d8c2SCharles.Forsyth {
143074a4d8c2SCharles.Forsyth 	Prog *p1;
143174a4d8c2SCharles.Forsyth 	Node nod0, nod1, nod2, nod3, nod4, *h, *l, *r;
143274a4d8c2SCharles.Forsyth 	Type *t;
143374a4d8c2SCharles.Forsyth 	int c, v, x;
143474a4d8c2SCharles.Forsyth 
143574a4d8c2SCharles.Forsyth 	if(n == Z || n->type == T)
143674a4d8c2SCharles.Forsyth 		return;
143774a4d8c2SCharles.Forsyth 	if(debug['g']) {
143874a4d8c2SCharles.Forsyth 		prtree(nn, "sugen lhs");
143974a4d8c2SCharles.Forsyth 		prtree(n, "sugen");
144074a4d8c2SCharles.Forsyth 	}
144174a4d8c2SCharles.Forsyth 	if(nn == nodrat)
144274a4d8c2SCharles.Forsyth 		if(w > nrathole)
144374a4d8c2SCharles.Forsyth 			nrathole = w;
144474a4d8c2SCharles.Forsyth 	switch(n->op) {
144574a4d8c2SCharles.Forsyth 	case OIND:
144674a4d8c2SCharles.Forsyth 		if(nn == Z) {
144774a4d8c2SCharles.Forsyth 			nullwarn(n->left, Z);
144874a4d8c2SCharles.Forsyth 			break;
144974a4d8c2SCharles.Forsyth 		}
145074a4d8c2SCharles.Forsyth 
145174a4d8c2SCharles.Forsyth 	default:
145274a4d8c2SCharles.Forsyth 		goto copy;
145374a4d8c2SCharles.Forsyth 
145474a4d8c2SCharles.Forsyth 	case OCONST:
145574a4d8c2SCharles.Forsyth 		if(n->type && typev[n->type->etype]) {
145674a4d8c2SCharles.Forsyth 			if(nn == Z) {
145774a4d8c2SCharles.Forsyth 				nullwarn(n->left, Z);
145874a4d8c2SCharles.Forsyth 				break;
145974a4d8c2SCharles.Forsyth 			}
146074a4d8c2SCharles.Forsyth 
146174a4d8c2SCharles.Forsyth 			if(nn->op == OREGPAIR) {
146274a4d8c2SCharles.Forsyth 				loadpair(n, nn);
146374a4d8c2SCharles.Forsyth 				break;
146474a4d8c2SCharles.Forsyth 			}
146574a4d8c2SCharles.Forsyth 			else if(!vaddr(nn, 0)) {
146674a4d8c2SCharles.Forsyth 				t = nn->type;
146774a4d8c2SCharles.Forsyth 				nn->type = types[TLONG];
146874a4d8c2SCharles.Forsyth 				reglcgen(&nod1, nn, Z);
146974a4d8c2SCharles.Forsyth 				nn->type = t;
147074a4d8c2SCharles.Forsyth 
147174a4d8c2SCharles.Forsyth 				gmove(lo64(n), &nod1);
147274a4d8c2SCharles.Forsyth 				nod1.xoffset += SZ_LONG;
147374a4d8c2SCharles.Forsyth 				gmove(hi64(n), &nod1);
147474a4d8c2SCharles.Forsyth 				regfree(&nod1);
147574a4d8c2SCharles.Forsyth 			}
147674a4d8c2SCharles.Forsyth 			else {
147774a4d8c2SCharles.Forsyth 				gins(AMOVL, lo64(n), nn);
147874a4d8c2SCharles.Forsyth 				nn->xoffset += SZ_LONG;
147974a4d8c2SCharles.Forsyth 				gins(AMOVL, hi64(n), nn);
148074a4d8c2SCharles.Forsyth 				nn->xoffset -= SZ_LONG;
148174a4d8c2SCharles.Forsyth 				break;
148274a4d8c2SCharles.Forsyth 			}
148374a4d8c2SCharles.Forsyth 			break;
148474a4d8c2SCharles.Forsyth 		}
148574a4d8c2SCharles.Forsyth 		goto copy;
148674a4d8c2SCharles.Forsyth 
148774a4d8c2SCharles.Forsyth 	case ODOT:
148874a4d8c2SCharles.Forsyth 		l = n->left;
148974a4d8c2SCharles.Forsyth 		sugen(l, nodrat, l->type->width);
149074a4d8c2SCharles.Forsyth 		if(nn == Z)
149174a4d8c2SCharles.Forsyth 			break;
149274a4d8c2SCharles.Forsyth 		warn(n, "non-interruptable temporary");
149374a4d8c2SCharles.Forsyth 		nod1 = *nodrat;
149474a4d8c2SCharles.Forsyth 		r = n->right;
149574a4d8c2SCharles.Forsyth 		if(!r || r->op != OCONST) {
149674a4d8c2SCharles.Forsyth 			diag(n, "DOT and no offset");
149774a4d8c2SCharles.Forsyth 			break;
149874a4d8c2SCharles.Forsyth 		}
149974a4d8c2SCharles.Forsyth 		nod1.xoffset += (long)r->vconst;
150074a4d8c2SCharles.Forsyth 		nod1.type = n->type;
150174a4d8c2SCharles.Forsyth 		sugen(&nod1, nn, w);
150274a4d8c2SCharles.Forsyth 		break;
150374a4d8c2SCharles.Forsyth 
150474a4d8c2SCharles.Forsyth 	case OSTRUCT:
150574a4d8c2SCharles.Forsyth 		/*
150674a4d8c2SCharles.Forsyth 		 * rewrite so lhs has no fn call
150774a4d8c2SCharles.Forsyth 		 */
150874a4d8c2SCharles.Forsyth 		if(nn != Z && side(nn)) {
150974a4d8c2SCharles.Forsyth 			nod1 = *n;
151074a4d8c2SCharles.Forsyth 			nod1.type = typ(TIND, n->type);
151174a4d8c2SCharles.Forsyth 			regret(&nod2, &nod1);
151274a4d8c2SCharles.Forsyth 			lcgen(nn, &nod2);
151374a4d8c2SCharles.Forsyth 			regsalloc(&nod0, &nod1);
151474a4d8c2SCharles.Forsyth 			cgen(&nod2, &nod0);
151574a4d8c2SCharles.Forsyth 			regfree(&nod2);
151674a4d8c2SCharles.Forsyth 
151774a4d8c2SCharles.Forsyth 			nod1 = *n;
151874a4d8c2SCharles.Forsyth 			nod1.op = OIND;
151974a4d8c2SCharles.Forsyth 			nod1.left = &nod0;
152074a4d8c2SCharles.Forsyth 			nod1.right = Z;
152174a4d8c2SCharles.Forsyth 			nod1.complex = 1;
152274a4d8c2SCharles.Forsyth 
152374a4d8c2SCharles.Forsyth 			sugen(n, &nod1, w);
152474a4d8c2SCharles.Forsyth 			return;
152574a4d8c2SCharles.Forsyth 		}
152674a4d8c2SCharles.Forsyth 
152774a4d8c2SCharles.Forsyth 		r = n->left;
152874a4d8c2SCharles.Forsyth 		for(t = n->type->link; t != T; t = t->down) {
152974a4d8c2SCharles.Forsyth 			l = r;
153074a4d8c2SCharles.Forsyth 			if(r->op == OLIST) {
153174a4d8c2SCharles.Forsyth 				l = r->left;
153274a4d8c2SCharles.Forsyth 				r = r->right;
153374a4d8c2SCharles.Forsyth 			}
153474a4d8c2SCharles.Forsyth 			if(nn == Z) {
153574a4d8c2SCharles.Forsyth 				cgen(l, nn);
153674a4d8c2SCharles.Forsyth 				continue;
153774a4d8c2SCharles.Forsyth 			}
153874a4d8c2SCharles.Forsyth 			/*
153974a4d8c2SCharles.Forsyth 			 * hand craft *(&nn + o) = l
154074a4d8c2SCharles.Forsyth 			 */
154174a4d8c2SCharles.Forsyth 			nod0 = znode;
154274a4d8c2SCharles.Forsyth 			nod0.op = OAS;
154374a4d8c2SCharles.Forsyth 			nod0.type = t;
154474a4d8c2SCharles.Forsyth 			nod0.left = &nod1;
154574a4d8c2SCharles.Forsyth 			nod0.right = nil;
154674a4d8c2SCharles.Forsyth 
154774a4d8c2SCharles.Forsyth 			nod1 = znode;
154874a4d8c2SCharles.Forsyth 			nod1.op = OIND;
154974a4d8c2SCharles.Forsyth 			nod1.type = t;
155074a4d8c2SCharles.Forsyth 			nod1.left = &nod2;
155174a4d8c2SCharles.Forsyth 
155274a4d8c2SCharles.Forsyth 			nod2 = znode;
155374a4d8c2SCharles.Forsyth 			nod2.op = OADD;
155474a4d8c2SCharles.Forsyth 			nod2.type = typ(TIND, t);
155574a4d8c2SCharles.Forsyth 			nod2.left = &nod3;
155674a4d8c2SCharles.Forsyth 			nod2.right = &nod4;
155774a4d8c2SCharles.Forsyth 
155874a4d8c2SCharles.Forsyth 			nod3 = znode;
155974a4d8c2SCharles.Forsyth 			nod3.op = OADDR;
156074a4d8c2SCharles.Forsyth 			nod3.type = nod2.type;
156174a4d8c2SCharles.Forsyth 			nod3.left = nn;
156274a4d8c2SCharles.Forsyth 
156374a4d8c2SCharles.Forsyth 			nod4 = znode;
156474a4d8c2SCharles.Forsyth 			nod4.op = OCONST;
156574a4d8c2SCharles.Forsyth 			nod4.type = nod2.type;
156674a4d8c2SCharles.Forsyth 			nod4.vconst = t->offset;
156774a4d8c2SCharles.Forsyth 
156874a4d8c2SCharles.Forsyth 			ccom(&nod0);
156974a4d8c2SCharles.Forsyth 			acom(&nod0);
157074a4d8c2SCharles.Forsyth 			xcom(&nod0);
157174a4d8c2SCharles.Forsyth 			nod0.addable = 0;
157274a4d8c2SCharles.Forsyth 			nod0.right = l;
157374a4d8c2SCharles.Forsyth 
157474a4d8c2SCharles.Forsyth 			/* prtree(&nod0, "hand craft"); /* */
157574a4d8c2SCharles.Forsyth 			cgen(&nod0, Z);
157674a4d8c2SCharles.Forsyth 		}
157774a4d8c2SCharles.Forsyth 		break;
157874a4d8c2SCharles.Forsyth 
157974a4d8c2SCharles.Forsyth 	case OAS:
158074a4d8c2SCharles.Forsyth 		if(nn == Z) {
158174a4d8c2SCharles.Forsyth 			if(n->addable < INDEXED)
158274a4d8c2SCharles.Forsyth 				sugen(n->right, n->left, w);
158374a4d8c2SCharles.Forsyth 			break;
158474a4d8c2SCharles.Forsyth 		}
158574a4d8c2SCharles.Forsyth 
158674a4d8c2SCharles.Forsyth 		sugen(n->right, nodrat, w);
158774a4d8c2SCharles.Forsyth 		warn(n, "non-interruptable temporary");
158874a4d8c2SCharles.Forsyth 		sugen(nodrat, n->left, w);
158974a4d8c2SCharles.Forsyth 		sugen(nodrat, nn, w);
159074a4d8c2SCharles.Forsyth 		break;
159174a4d8c2SCharles.Forsyth 
159274a4d8c2SCharles.Forsyth 	case OFUNC:
159374a4d8c2SCharles.Forsyth 		if(nn == Z) {
159474a4d8c2SCharles.Forsyth 			sugen(n, nodrat, w);
159574a4d8c2SCharles.Forsyth 			break;
159674a4d8c2SCharles.Forsyth 		}
159774a4d8c2SCharles.Forsyth 		h = nn;
159874a4d8c2SCharles.Forsyth 		if(nn->op == OREGPAIR) {
159974a4d8c2SCharles.Forsyth 			regsalloc(&nod1, nn);
160074a4d8c2SCharles.Forsyth 			nn = &nod1;
160174a4d8c2SCharles.Forsyth 		}
160274a4d8c2SCharles.Forsyth 		if(nn->op != OIND) {
160374a4d8c2SCharles.Forsyth 			nn = new1(OADDR, nn, Z);
160474a4d8c2SCharles.Forsyth 			nn->type = types[TIND];
160574a4d8c2SCharles.Forsyth 			nn->addable = 0;
160674a4d8c2SCharles.Forsyth 		} else
160774a4d8c2SCharles.Forsyth 			nn = nn->left;
160874a4d8c2SCharles.Forsyth 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
160974a4d8c2SCharles.Forsyth 		n->type = types[TVOID];
161074a4d8c2SCharles.Forsyth 		n->left->type = types[TVOID];
161174a4d8c2SCharles.Forsyth 		cgen(n, Z);
161274a4d8c2SCharles.Forsyth 		if(h->op == OREGPAIR)
161374a4d8c2SCharles.Forsyth 			loadpair(nn->left, h);
161474a4d8c2SCharles.Forsyth 		break;
161574a4d8c2SCharles.Forsyth 
161674a4d8c2SCharles.Forsyth 	case OCOND:
161774a4d8c2SCharles.Forsyth 		bcgen(n->left, 1);
161874a4d8c2SCharles.Forsyth 		p1 = p;
161974a4d8c2SCharles.Forsyth 		sugen(n->right->left, nn, w);
162074a4d8c2SCharles.Forsyth 		gbranch(OGOTO);
162174a4d8c2SCharles.Forsyth 		patch(p1, pc);
162274a4d8c2SCharles.Forsyth 		p1 = p;
162374a4d8c2SCharles.Forsyth 		sugen(n->right->right, nn, w);
162474a4d8c2SCharles.Forsyth 		patch(p1, pc);
162574a4d8c2SCharles.Forsyth 		break;
162674a4d8c2SCharles.Forsyth 
162774a4d8c2SCharles.Forsyth 	case OCOMMA:
162874a4d8c2SCharles.Forsyth 		cgen(n->left, Z);
162974a4d8c2SCharles.Forsyth 		sugen(n->right, nn, w);
163074a4d8c2SCharles.Forsyth 		break;
163174a4d8c2SCharles.Forsyth 	}
163274a4d8c2SCharles.Forsyth 	return;
163374a4d8c2SCharles.Forsyth 
163474a4d8c2SCharles.Forsyth copy:
163574a4d8c2SCharles.Forsyth 	if(nn == Z) {
163674a4d8c2SCharles.Forsyth 		switch(n->op) {
163774a4d8c2SCharles.Forsyth 		case OASADD:
163874a4d8c2SCharles.Forsyth 		case OASSUB:
163974a4d8c2SCharles.Forsyth 		case OASAND:
164074a4d8c2SCharles.Forsyth 		case OASOR:
164174a4d8c2SCharles.Forsyth 		case OASXOR:
164274a4d8c2SCharles.Forsyth 
164374a4d8c2SCharles.Forsyth 		case OASMUL:
164474a4d8c2SCharles.Forsyth 		case OASLMUL:
164574a4d8c2SCharles.Forsyth 
164674a4d8c2SCharles.Forsyth 		case OASASHL:
164774a4d8c2SCharles.Forsyth 		case OASASHR:
164874a4d8c2SCharles.Forsyth 		case OASLSHR:
164974a4d8c2SCharles.Forsyth 			break;
165074a4d8c2SCharles.Forsyth 
165174a4d8c2SCharles.Forsyth 		case OPOSTINC:
165274a4d8c2SCharles.Forsyth 		case OPOSTDEC:
165374a4d8c2SCharles.Forsyth 		case OPREINC:
165474a4d8c2SCharles.Forsyth 		case OPREDEC:
165574a4d8c2SCharles.Forsyth 			break;
165674a4d8c2SCharles.Forsyth 
165774a4d8c2SCharles.Forsyth 		default:
165874a4d8c2SCharles.Forsyth 			return;
165974a4d8c2SCharles.Forsyth 		}
166074a4d8c2SCharles.Forsyth 	}
166174a4d8c2SCharles.Forsyth 
166274a4d8c2SCharles.Forsyth 	if(n->complex >= FNX && nn != nil && nn->complex >= FNX) {
166374a4d8c2SCharles.Forsyth 		t = nn->type;
166474a4d8c2SCharles.Forsyth 		nn->type = types[TLONG];
166574a4d8c2SCharles.Forsyth 		regialloc(&nod1, nn, Z);
166674a4d8c2SCharles.Forsyth 		lcgen(nn, &nod1);
166774a4d8c2SCharles.Forsyth 		regsalloc(&nod2, nn);
166874a4d8c2SCharles.Forsyth 		nn->type = t;
166974a4d8c2SCharles.Forsyth 
167074a4d8c2SCharles.Forsyth 		gins(AMOVL, &nod1, &nod2);
167174a4d8c2SCharles.Forsyth 		regfree(&nod1);
167274a4d8c2SCharles.Forsyth 
167374a4d8c2SCharles.Forsyth 		nod2.type = typ(TIND, t);
167474a4d8c2SCharles.Forsyth 
167574a4d8c2SCharles.Forsyth 		nod1 = nod2;
167674a4d8c2SCharles.Forsyth 		nod1.op = OIND;
167774a4d8c2SCharles.Forsyth 		nod1.left = &nod2;
167874a4d8c2SCharles.Forsyth 		nod1.right = Z;
167974a4d8c2SCharles.Forsyth 		nod1.complex = 1;
168074a4d8c2SCharles.Forsyth 		nod1.type = t;
168174a4d8c2SCharles.Forsyth 
168274a4d8c2SCharles.Forsyth 		sugen(n, &nod1, w);
168374a4d8c2SCharles.Forsyth 		return;
168474a4d8c2SCharles.Forsyth 	}
168574a4d8c2SCharles.Forsyth 
168674a4d8c2SCharles.Forsyth 	x = 0;
168774a4d8c2SCharles.Forsyth 	v = w == 8;
168874a4d8c2SCharles.Forsyth 	if(v) {
168974a4d8c2SCharles.Forsyth 		c = cursafe;
169074a4d8c2SCharles.Forsyth 		if(n->left != Z && n->left->complex >= FNX
169174a4d8c2SCharles.Forsyth 		&& n->right != Z && n->right->complex >= FNX) {
169274a4d8c2SCharles.Forsyth //			warn(n, "toughie");
169374a4d8c2SCharles.Forsyth 			regsalloc(&nod1, n->right);
169474a4d8c2SCharles.Forsyth 			cgen(n->right, &nod1);
169574a4d8c2SCharles.Forsyth 			nod2 = *n;
169674a4d8c2SCharles.Forsyth 			nod2.right = &nod1;
169774a4d8c2SCharles.Forsyth 			cgen(&nod2, nn);
169874a4d8c2SCharles.Forsyth 			cursafe = c;
169974a4d8c2SCharles.Forsyth 			return;
170074a4d8c2SCharles.Forsyth 		}
170174a4d8c2SCharles.Forsyth 		if(cgen64(n, nn)) {
170274a4d8c2SCharles.Forsyth 			cursafe = c;
170374a4d8c2SCharles.Forsyth 			return;
170474a4d8c2SCharles.Forsyth 		}
170574a4d8c2SCharles.Forsyth 		if(n->op == OCOM) {
170674a4d8c2SCharles.Forsyth 			n = n->left;
170774a4d8c2SCharles.Forsyth 			x = 1;
170874a4d8c2SCharles.Forsyth 		}
170974a4d8c2SCharles.Forsyth 	}
171074a4d8c2SCharles.Forsyth 
171174a4d8c2SCharles.Forsyth 	/* botch, need to save in .safe */
171274a4d8c2SCharles.Forsyth 	c = 0;
171374a4d8c2SCharles.Forsyth 	if(n->complex > nn->complex) {
171474a4d8c2SCharles.Forsyth 		t = n->type;
171574a4d8c2SCharles.Forsyth 		n->type = types[TLONG];
171674a4d8c2SCharles.Forsyth 		if(v) {
171774a4d8c2SCharles.Forsyth 			regalloc(&nod0, n, Z);
171874a4d8c2SCharles.Forsyth 			if(!vaddr(n, 0)) {
171974a4d8c2SCharles.Forsyth 				reglcgen(&nod1, n, Z);
172074a4d8c2SCharles.Forsyth 				n->type = t;
172174a4d8c2SCharles.Forsyth 				n = &nod1;
172274a4d8c2SCharles.Forsyth 			}
172374a4d8c2SCharles.Forsyth 			else
172474a4d8c2SCharles.Forsyth 				n->type = t;
172574a4d8c2SCharles.Forsyth 		}
172674a4d8c2SCharles.Forsyth 		else {
172774a4d8c2SCharles.Forsyth 			nodreg(&nod1, n, D_SI);
172874a4d8c2SCharles.Forsyth 			if(reg[D_SI]) {
172974a4d8c2SCharles.Forsyth 				gins(APUSHL, &nod1, Z);
173074a4d8c2SCharles.Forsyth 				c |= 1;
173174a4d8c2SCharles.Forsyth 				reg[D_SI]++;
173274a4d8c2SCharles.Forsyth 			}
173374a4d8c2SCharles.Forsyth 			lcgen(n, &nod1);
173474a4d8c2SCharles.Forsyth 			n->type = t;
173574a4d8c2SCharles.Forsyth 		}
173674a4d8c2SCharles.Forsyth 
173774a4d8c2SCharles.Forsyth 		t = nn->type;
173874a4d8c2SCharles.Forsyth 		nn->type = types[TLONG];
173974a4d8c2SCharles.Forsyth 		if(v) {
174074a4d8c2SCharles.Forsyth 			if(!vaddr(nn, 0)) {
174174a4d8c2SCharles.Forsyth 				reglcgen(&nod2, nn, Z);
174274a4d8c2SCharles.Forsyth 				nn->type = t;
174374a4d8c2SCharles.Forsyth 				nn = &nod2;
174474a4d8c2SCharles.Forsyth 			}
174574a4d8c2SCharles.Forsyth 			else
174674a4d8c2SCharles.Forsyth 				nn->type = t;
174774a4d8c2SCharles.Forsyth 		}
174874a4d8c2SCharles.Forsyth 		else {
174974a4d8c2SCharles.Forsyth 			nodreg(&nod2, nn, D_DI);
175074a4d8c2SCharles.Forsyth 			if(reg[D_DI]) {
175174a4d8c2SCharles.Forsyth 				gins(APUSHL, &nod2, Z);
175274a4d8c2SCharles.Forsyth 				c |= 2;
175374a4d8c2SCharles.Forsyth 				reg[D_DI]++;
175474a4d8c2SCharles.Forsyth 			}
175574a4d8c2SCharles.Forsyth 			lcgen(nn, &nod2);
175674a4d8c2SCharles.Forsyth 			nn->type = t;
175774a4d8c2SCharles.Forsyth 		}
175874a4d8c2SCharles.Forsyth 	} else {
175974a4d8c2SCharles.Forsyth 		t = nn->type;
176074a4d8c2SCharles.Forsyth 		nn->type = types[TLONG];
176174a4d8c2SCharles.Forsyth 		if(v) {
176274a4d8c2SCharles.Forsyth 			regalloc(&nod0, nn, Z);
176374a4d8c2SCharles.Forsyth 			if(!vaddr(nn, 0)) {
176474a4d8c2SCharles.Forsyth 				reglcgen(&nod2, nn, Z);
176574a4d8c2SCharles.Forsyth 				nn->type = t;
176674a4d8c2SCharles.Forsyth 				nn = &nod2;
176774a4d8c2SCharles.Forsyth 			}
176874a4d8c2SCharles.Forsyth 			else
176974a4d8c2SCharles.Forsyth 				nn->type = t;
177074a4d8c2SCharles.Forsyth 		}
177174a4d8c2SCharles.Forsyth 		else {
177274a4d8c2SCharles.Forsyth 			nodreg(&nod2, nn, D_DI);
177374a4d8c2SCharles.Forsyth 			if(reg[D_DI]) {
177474a4d8c2SCharles.Forsyth 				gins(APUSHL, &nod2, Z);
177574a4d8c2SCharles.Forsyth 				c |= 2;
177674a4d8c2SCharles.Forsyth 				reg[D_DI]++;
177774a4d8c2SCharles.Forsyth 			}
177874a4d8c2SCharles.Forsyth 			lcgen(nn, &nod2);
177974a4d8c2SCharles.Forsyth 			nn->type = t;
178074a4d8c2SCharles.Forsyth 		}
178174a4d8c2SCharles.Forsyth 
178274a4d8c2SCharles.Forsyth 		t = n->type;
178374a4d8c2SCharles.Forsyth 		n->type = types[TLONG];
178474a4d8c2SCharles.Forsyth 		if(v) {
178574a4d8c2SCharles.Forsyth 			if(!vaddr(n, 0)) {
178674a4d8c2SCharles.Forsyth 				reglcgen(&nod1, n, Z);
178774a4d8c2SCharles.Forsyth 				n->type = t;
178874a4d8c2SCharles.Forsyth 				n = &nod1;
178974a4d8c2SCharles.Forsyth 			}
179074a4d8c2SCharles.Forsyth 			else
179174a4d8c2SCharles.Forsyth 				n->type = t;
179274a4d8c2SCharles.Forsyth 		}
179374a4d8c2SCharles.Forsyth 		else {
179474a4d8c2SCharles.Forsyth 			nodreg(&nod1, n, D_SI);
179574a4d8c2SCharles.Forsyth 			if(reg[D_SI]) {
179674a4d8c2SCharles.Forsyth 				gins(APUSHL, &nod1, Z);
179774a4d8c2SCharles.Forsyth 				c |= 1;
179874a4d8c2SCharles.Forsyth 				reg[D_SI]++;
179974a4d8c2SCharles.Forsyth 			}
180074a4d8c2SCharles.Forsyth 			lcgen(n, &nod1);
180174a4d8c2SCharles.Forsyth 			n->type = t;
180274a4d8c2SCharles.Forsyth 		}
180374a4d8c2SCharles.Forsyth 	}
180474a4d8c2SCharles.Forsyth 	if(v) {
180574a4d8c2SCharles.Forsyth 		gins(AMOVL, n, &nod0);
180674a4d8c2SCharles.Forsyth 		if(x)
180774a4d8c2SCharles.Forsyth 			gins(ANOTL, Z, &nod0);
180874a4d8c2SCharles.Forsyth 		gins(AMOVL, &nod0, nn);
180974a4d8c2SCharles.Forsyth 		n->xoffset += SZ_LONG;
181074a4d8c2SCharles.Forsyth 		nn->xoffset += SZ_LONG;
181174a4d8c2SCharles.Forsyth 		gins(AMOVL, n, &nod0);
181274a4d8c2SCharles.Forsyth 		if(x)
181374a4d8c2SCharles.Forsyth 			gins(ANOTL, Z, &nod0);
181474a4d8c2SCharles.Forsyth 		gins(AMOVL, &nod0, nn);
181574a4d8c2SCharles.Forsyth 		n->xoffset -= SZ_LONG;
181674a4d8c2SCharles.Forsyth 		nn->xoffset -= SZ_LONG;
181774a4d8c2SCharles.Forsyth 		if(nn == &nod2)
181874a4d8c2SCharles.Forsyth 			regfree(&nod2);
181974a4d8c2SCharles.Forsyth 		if(n == &nod1)
182074a4d8c2SCharles.Forsyth 			regfree(&nod1);
182174a4d8c2SCharles.Forsyth 		regfree(&nod0);
182274a4d8c2SCharles.Forsyth 		return;
182374a4d8c2SCharles.Forsyth 	}
182474a4d8c2SCharles.Forsyth 	nodreg(&nod3, n, D_CX);
182574a4d8c2SCharles.Forsyth 	if(reg[D_CX]) {
182674a4d8c2SCharles.Forsyth 		gins(APUSHL, &nod3, Z);
182774a4d8c2SCharles.Forsyth 		c |= 4;
182874a4d8c2SCharles.Forsyth 		reg[D_CX]++;
182974a4d8c2SCharles.Forsyth 	}
183074a4d8c2SCharles.Forsyth 	gins(AMOVL, nodconst(w/SZ_LONG), &nod3);
183174a4d8c2SCharles.Forsyth 	gins(ACLD, Z, Z);
183274a4d8c2SCharles.Forsyth 	gins(AREP, Z, Z);
183374a4d8c2SCharles.Forsyth 	gins(AMOVSL, Z, Z);
1834*45a20ab7Sforsyth 	if(w & (SZ_LONG-1)) {
1835*45a20ab7Sforsyth 		/* odd length of packed structure */
1836*45a20ab7Sforsyth 		gins(AMOVL, nodconst(w & (SZ_LONG-1)), &nod3);
1837*45a20ab7Sforsyth 		gins(AREP, Z, Z);
1838*45a20ab7Sforsyth 		gins(AMOVSB, Z, Z);
1839*45a20ab7Sforsyth 	}
184074a4d8c2SCharles.Forsyth 	if(c & 4) {
184174a4d8c2SCharles.Forsyth 		gins(APOPL, Z, &nod3);
184274a4d8c2SCharles.Forsyth 		reg[D_CX]--;
184374a4d8c2SCharles.Forsyth 	}
184474a4d8c2SCharles.Forsyth 	if(c & 2) {
184574a4d8c2SCharles.Forsyth 		gins(APOPL, Z, &nod2);
184674a4d8c2SCharles.Forsyth 		reg[nod2.reg]--;
184774a4d8c2SCharles.Forsyth 	}
184874a4d8c2SCharles.Forsyth 	if(c & 1) {
184974a4d8c2SCharles.Forsyth 		gins(APOPL, Z, &nod1);
185074a4d8c2SCharles.Forsyth 		reg[nod1.reg]--;
185174a4d8c2SCharles.Forsyth 	}
185274a4d8c2SCharles.Forsyth }
1853