xref: /inferno-os/utils/qc/cgen.c (revision 1981fff245dfce579ef416fa767eb69d462039e9)
1 #include "gc.h"
2 
3 static void cmpv(Node*, int, Node*);
4 static void testv(Node*, int);
5 static void cgen64(Node*, Node*);
6 static int isvconstable(int, vlong);
7 
8 void
9 cgen(Node *n, Node *nn)
10 {
11 	Node *l, *r;
12 	Prog *p1;
13 	Node nod, nod1, nod2, nod3, nod4;
14 	int o;
15 	long v, curs;
16 
17 	if(debug['g']) {
18 		prtree(nn, "cgen lhs");
19 		prtree(n, "cgen");
20 	}
21 	if(n == Z || n->type == T)
22 		return;
23 	if(typesu[n->type->etype]) {
24 		sugen(n, nn, n->type->width);
25 		return;
26 	}
27 	if(typev[n->type->etype]) {
28 		switch(n->op) {
29 		case OCONST:
30 		case OFUNC:
31 			cgen64(n, nn);
32 			return;
33 		}
34 	}
35 	l = n->left;
36 	r = n->right;
37 	o = n->op;
38 	if(n->addable >= INDEXED) {
39 		if(nn == Z) {
40 			switch(o) {
41 			default:
42 				nullwarn(Z, Z);
43 				break;
44 			case OINDEX:
45 				nullwarn(l, r);
46 				break;
47 			}
48 			return;
49 		}
50 		gmove(n, nn);
51 		return;
52 	}
53 	curs = cursafe;
54 
55 	if(n->complex >= FNX)
56 	if(l->complex >= FNX)
57 	if(r != Z && r->complex >= FNX)
58 	switch(o) {
59 	default:
60 		if(!typev[r->type->etype]) {
61 			regret(&nod, r);
62 			cgen(r, &nod);
63 			regsalloc(&nod1, r);
64 			gmove(&nod, &nod1);
65 			regfree(&nod);
66 		} else {
67 			regsalloc(&nod1, r);
68 			cgen(r, &nod1);
69 		}
70 
71 		nod = *n;
72 		nod.right = &nod1;
73 		cgen(&nod, nn);
74 		return;
75 
76 	case OFUNC:
77 	case OCOMMA:
78 	case OANDAND:
79 	case OOROR:
80 	case OCOND:
81 	case ODOT:
82 		break;
83 	}
84 
85 	switch(o) {
86 	default:
87 		diag(n, "unknown op in cgen: %O", o);
88 		break;
89 
90 	case ONEG:
91 	case OCOM:
92 		if(nn == Z) {
93 			nullwarn(l, Z);
94 			break;
95 		}
96 		regalloc(&nod, l, nn);
97 		cgen(l, &nod);
98 		gopcode(o, &nod, Z, &nod);
99 		gmove(&nod, nn);
100 		regfree(&nod);
101 		break;
102 
103 	case OAS:
104 		if(l->op == OBIT)
105 			goto bitas;
106 		if(l->addable >= INDEXED) {
107 			if(nn != Z || r->addable < INDEXED) {
108 				regalloc(&nod, r, nn);
109 				cgen(r, &nod);
110 				gmove(&nod, l);
111 				regfree(&nod);
112 			} else
113 				gmove(r, l);
114 			break;
115 		}
116 		if(l->complex >= r->complex) {
117 			reglcgen(&nod1, l, Z);
118 			if(r->addable >= INDEXED) {
119 				gmove(r, &nod1);
120 				if(nn != Z)
121 					gmove(r, nn);
122 				regfree(&nod1);
123 				break;
124 			}
125 			regalloc(&nod, r, nn);
126 			cgen(r, &nod);
127 		} else {
128 			regalloc(&nod, r, nn);
129 			cgen(r, &nod);
130 			reglcgen(&nod1, l, Z);
131 		}
132 		gmove(&nod, &nod1);
133 		regfree(&nod);
134 		regfree(&nod1);
135 		break;
136 
137 	bitas:
138 		n = l->left;
139 		regalloc(&nod, r, nn);
140 		if(l->complex >= r->complex) {
141 			reglcgen(&nod1, n, Z);
142 			cgen(r, &nod);
143 		} else {
144 			cgen(r, &nod);
145 			reglcgen(&nod1, n, Z);
146 		}
147 		regalloc(&nod2, n, Z);
148 		gopcode(OAS, &nod1, Z, &nod2);
149 		bitstore(l, &nod, &nod1, &nod2, nn);
150 		break;
151 
152 	case OBIT:
153 		if(nn == Z) {
154 			nullwarn(l, Z);
155 			break;
156 		}
157 		bitload(n, &nod, Z, Z, nn);
158 		gopcode(OAS, &nod, Z, nn);
159 		regfree(&nod);
160 		break;
161 
162 	case OXOR:
163 		if(nn != Z)
164 		if(r->op == OCONST && r->vconst == -1){
165 			regalloc(&nod, l, nn);
166 			cgen(l, &nod);
167 			gopcode(OCOM, &nod, Z, &nod);
168 			gmove(&nod, nn);
169 			regfree(&nod);
170 			break;
171 		}
172 
173 	case OADD:
174 	case OSUB:
175 	case OAND:
176 	case OOR:
177 	case OLSHR:
178 	case OASHL:
179 	case OASHR:
180 		/*
181 		 * immediate operands
182 		 */
183 		if(nn != Z && r->op == OCONST && !typefd[n->type->etype] &&
184 		    (!typev[n->type->etype] || isvconstable(o, r->vconst))) {
185 			regalloc(&nod, l, nn);
186 			cgen(l, &nod);
187 			if(o == OAND || r->vconst != 0)
188 				gopcode(o, r, Z, &nod);
189 			gmove(&nod, nn);
190 			regfree(&nod);
191 			break;
192 		}
193 
194 	case OMUL:
195 	case OLMUL:
196 	case OLDIV:
197 	case OLMOD:
198 	case ODIV:
199 	case OMOD:
200 		if(nn == Z) {
201 			nullwarn(l, r);
202 			break;
203 		}
204 		if((o == OMUL || o == OLMUL) && !typev[n->type->etype]) {
205 			if(mulcon(n, nn))
206 				break;
207 			if(debug['M'])
208 				print("%L multiply\n", n->lineno);
209 		}
210 		if(l->complex >= r->complex) {
211 			regalloc(&nod, l, nn);
212 			cgen(l, &nod);
213 			if(o != OMUL || typev[n->type->etype] || !sconst(r)) {
214 				regalloc(&nod1, r, Z);
215 				cgen(r, &nod1);
216 				gopcode(o, &nod1, Z, &nod);
217 				regfree(&nod1);
218 			} else
219 				gopcode(o, r, Z, &nod);
220 		} else {
221 			regalloc(&nod1, r, nn);
222 			cgen(r, &nod1);
223 			regalloc(&nod, l, Z);
224 			cgen(l, &nod);
225 			gopcode(o, &nod1, Z, &nod);
226 			regfree(&nod1);
227 		}
228 		gopcode(OAS, &nod, Z, nn);
229 		regfree(&nod);
230 		break;
231 
232 	case OASLSHR:
233 	case OASASHL:
234 	case OASASHR:
235 	case OASAND:
236 	case OASADD:
237 	case OASSUB:
238 	case OASXOR:
239 	case OASOR:
240 		if(l->op == OBIT)
241 			goto asbitop;
242 		if(r->op == OCONST && !typefd[r->type->etype] && !typefd[n->type->etype] &&
243 		   (!typev[n->type->etype] || isvconstable(o, r->vconst))) {
244 			if(l->addable < INDEXED)
245 				reglcgen(&nod2, l, Z);
246 			else
247 				nod2 = *l;
248 			regalloc(&nod, l, nn);
249 			gopcode(OAS, &nod2, Z, &nod);
250 			gopcode(o, r, Z, &nod);
251 			gopcode(OAS, &nod, Z, &nod2);
252 
253 			regfree(&nod);
254 			if(l->addable < INDEXED)
255 				regfree(&nod2);
256 			break;
257 		}
258 
259 	case OASLMUL:
260 	case OASLDIV:
261 	case OASLMOD:
262 	case OASMUL:
263 	case OASDIV:
264 	case OASMOD:
265 		if(l->op == OBIT)
266 			goto asbitop;
267 		if(l->complex >= r->complex) {
268 			if(l->addable < INDEXED)
269 				reglcgen(&nod2, l, Z);
270 			else
271 				nod2 = *l;
272 			regalloc(&nod, r, Z);
273 			cgen(r, &nod);
274 		} else {
275 			regalloc(&nod, r, Z);
276 			cgen(r, &nod);
277 			if(l->addable < INDEXED)
278 				reglcgen(&nod2, l, Z);
279 			else
280 				nod2 = *l;
281 		}
282 		regalloc(&nod1, n, nn);
283 		gopcode(OAS, &nod2, Z, &nod1);
284 		gopcode(o, &nod, Z, &nod1);
285 		gopcode(OAS, &nod1, Z, &nod2);
286 		if(nn != Z)
287 			gopcode(OAS, &nod1, Z, nn);
288 		regfree(&nod);
289 		regfree(&nod1);
290 		if(l->addable < INDEXED)
291 			regfree(&nod2);
292 		break;
293 
294 	asbitop:
295 		regalloc(&nod4, n, nn);
296 		regalloc(&nod3, r, Z);
297 		if(l->complex >= r->complex) {
298 			bitload(l, &nod, &nod1, &nod2, &nod4);
299 			cgen(r, &nod3);
300 		} else {
301 			cgen(r, &nod3);
302 			bitload(l, &nod, &nod1, &nod2, &nod4);
303 		}
304 		gmove(&nod, &nod4);
305 		gopcode(n->op, &nod3, Z, &nod4);
306 		regfree(&nod3);
307 		gmove(&nod4, &nod);
308 		regfree(&nod4);
309 		bitstore(l, &nod, &nod1, &nod2, nn);
310 		break;
311 
312 	case OADDR:
313 		if(nn == Z) {
314 			nullwarn(l, Z);
315 			break;
316 		}
317 		lcgen(l, nn);
318 		break;
319 
320 	case OFUNC:
321 		if(l->complex >= FNX) {
322 			if(l->op != OIND)
323 				diag(n, "bad function call");
324 
325 			regret(&nod, l->left);
326 			cgen(l->left, &nod);
327 			regsalloc(&nod1, l->left);
328 			gopcode(OAS, &nod, Z, &nod1);
329 			regfree(&nod);
330 
331 			nod = *n;
332 			nod.left = &nod2;
333 			nod2 = *l;
334 			nod2.left = &nod1;
335 			nod2.complex = 1;
336 			cgen(&nod, nn);
337 
338 			return;
339 		}
340 		o = reg[REGARG];
341 		gargs(r, &nod, &nod1);
342 		if(l->addable < INDEXED) {
343 			reglcgen(&nod, l, Z);
344 			gopcode(OFUNC, Z, Z, &nod);
345 			regfree(&nod);
346 		} else
347 			gopcode(OFUNC, Z, Z, l);
348 		if(REGARG)
349 			if(o != reg[REGARG])
350 				reg[REGARG]--;
351 		if(nn != Z) {
352 			regret(&nod, n);
353 			gopcode(OAS, &nod, Z, nn);
354 			regfree(&nod);
355 		}
356 		break;
357 
358 	case OIND:
359 		if(nn == Z) {
360 			cgen(l, nn);
361 			break;
362 		}
363 		regialloc(&nod, n, nn);
364 		r = l;
365 		while(r->op == OADD)
366 			r = r->right;
367 		if(sconst(r)) {
368 			v = r->vconst;
369 			r->vconst = 0;
370 			cgen(l, &nod);
371 			nod.xoffset += v;
372 			r->vconst = v;
373 		} else
374 			cgen(l, &nod);
375 		regind(&nod, n);
376 		gmove(&nod, nn);
377 		regfree(&nod);
378 		break;
379 
380 	case OEQ:
381 	case ONE:
382 	case OLE:
383 	case OLT:
384 	case OGE:
385 	case OGT:
386 	case OLO:
387 	case OLS:
388 	case OHI:
389 	case OHS:
390 		if(nn == Z) {
391 			nullwarn(l, r);
392 			break;
393 		}
394 		boolgen(n, 1, nn);
395 		break;
396 
397 	case OANDAND:
398 	case OOROR:
399 		boolgen(n, 1, nn);
400 		if(nn == Z)
401 			patch(p, pc);
402 		break;
403 
404 	case ONOT:
405 		if(nn == Z) {
406 			nullwarn(l, Z);
407 			break;
408 		}
409 		boolgen(n, 1, nn);
410 		break;
411 
412 	case OCOMMA:
413 		cgen(l, Z);
414 		cgen(r, nn);
415 		break;
416 
417 	case OCAST:
418 		if(nn == Z) {
419 			nullwarn(l, Z);
420 			break;
421 		}
422 		/*
423 		 * convert from types l->n->nn
424 		 */
425 		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
426 			/* both null, gen l->nn */
427 			cgen(l, nn);
428 			break;
429 		}
430 		if(typev[l->type->etype] || typev[n->type->etype]) {
431 			cgen64(n, nn);
432 			break;
433 		}
434 		regalloc(&nod, l, nn);
435 		cgen(l, &nod);
436 		regalloc(&nod1, n, &nod);
437 		gmove(&nod, &nod1);
438 		gmove(&nod1, nn);
439 		regfree(&nod1);
440 		regfree(&nod);
441 		break;
442 
443 	case ODOT:
444 		sugen(l, nodrat, l->type->width);
445 		if(nn != Z) {
446 			warn(n, "non-interruptable temporary");
447 			nod = *nodrat;
448 			if(!r || r->op != OCONST) {
449 				diag(n, "DOT and no offset");
450 				break;
451 			}
452 			nod.xoffset += (long)r->vconst;
453 			nod.type = n->type;
454 			cgen(&nod, nn);
455 		}
456 		break;
457 
458 	case OCOND:
459 		bcgen(l, 1);
460 		p1 = p;
461 		cgen(r->left, nn);
462 		gbranch(OGOTO);
463 		patch(p1, pc);
464 		p1 = p;
465 		cgen(r->right, nn);
466 		patch(p1, pc);
467 		break;
468 
469 	case OPOSTINC:
470 	case OPOSTDEC:
471 		v = 1;
472 		if(l->type->etype == TIND)
473 			v = l->type->link->width;
474 		if(o == OPOSTDEC)
475 			v = -v;
476 		if(l->op == OBIT)
477 			goto bitinc;
478 		if(nn == Z)
479 			goto pre;
480 
481 		if(l->addable < INDEXED)
482 			reglcgen(&nod2, l, Z);
483 		else
484 			nod2 = *l;
485 
486 		regalloc(&nod, l, nn);
487 		gopcode(OAS, &nod2, Z, &nod);
488 		regalloc(&nod1, l, Z);
489 		if(typefd[l->type->etype]) {
490 			regalloc(&nod3, l, Z);
491 			if(v < 0) {
492 				gopcode(OAS, nodfconst(-v), Z, &nod3);
493 				gopcode(OSUB, &nod3, &nod, &nod1);
494 			} else {
495 				gopcode(OAS, nodfconst(v), Z, &nod3);
496 				gopcode(OADD, &nod3, &nod, &nod1);
497 			}
498 			regfree(&nod3);
499 		} else
500 			gopcode(OADD, nodconst(v), &nod, &nod1);
501 		gopcode(OAS, &nod1, Z, &nod2);
502 
503 		regfree(&nod);
504 		regfree(&nod1);
505 		if(l->addable < INDEXED)
506 			regfree(&nod2);
507 		break;
508 
509 	case OPREINC:
510 	case OPREDEC:
511 		v = 1;
512 		if(l->type->etype == TIND)
513 			v = l->type->link->width;
514 		if(o == OPREDEC)
515 			v = -v;
516 		if(l->op == OBIT)
517 			goto bitinc;
518 
519 	pre:
520 		if(l->addable < INDEXED)
521 			reglcgen(&nod2, l, Z);
522 		else
523 			nod2 = *l;
524 
525 		regalloc(&nod, l, nn);
526 		gopcode(OAS, &nod2, Z, &nod);
527 		if(typefd[l->type->etype]) {
528 			regalloc(&nod3, l, Z);
529 			if(v < 0) {
530 				gopcode(OAS, nodfconst(-v), Z, &nod3);
531 				gopcode(OSUB, &nod3, Z, &nod);
532 			} else {
533 				gopcode(OAS, nodfconst(v), Z, &nod3);
534 				gopcode(OADD, &nod3, Z, &nod);
535 			}
536 			regfree(&nod3);
537 		} else
538 			gopcode(OADD, nodconst(v), Z, &nod);
539 		gopcode(OAS, &nod, Z, &nod2);
540 		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
541 			gins(ANOP, l, Z);
542 
543 		regfree(&nod);
544 		if(l->addable < INDEXED)
545 			regfree(&nod2);
546 		break;
547 
548 	bitinc:
549 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
550 			bitload(l, &nod, &nod1, &nod2, Z);
551 			gopcode(OAS, &nod, Z, nn);
552 			gopcode(OADD, nodconst(v), Z, &nod);
553 			bitstore(l, &nod, &nod1, &nod2, Z);
554 			break;
555 		}
556 		bitload(l, &nod, &nod1, &nod2, nn);
557 		gopcode(OADD, nodconst(v), Z, &nod);
558 		bitstore(l, &nod, &nod1, &nod2, nn);
559 		break;
560 	}
561 	cursafe = curs;
562 }
563 
564 void
565 reglcgen(Node *t, Node *n, Node *nn)
566 {
567 	Node *r;
568 	long v;
569 
570 	regialloc(t, n, nn);
571 	if(n->op == OIND) {
572 		r = n->left;
573 		while(r->op == OADD)
574 			r = r->right;
575 		if(sconst(r)) {
576 			v = r->vconst;
577 			r->vconst = 0;
578 			lcgen(n, t);
579 			t->xoffset += v;
580 			r->vconst = v;
581 			regind(t, n);
582 			return;
583 		}
584 	}
585 	lcgen(n, t);
586 	regind(t, n);
587 }
588 
589 void
590 lcgen(Node *n, Node *nn)
591 {
592 	Prog *p1;
593 	Node nod;
594 
595 	if(debug['g']) {
596 		prtree(nn, "lcgen lhs");
597 		prtree(n, "lcgen");
598 	}
599 	if(n == Z || n->type == T)
600 		return;
601 	if(nn == Z) {
602 		nn = &nod;
603 		regalloc(&nod, n, Z);
604 	}
605 	switch(n->op) {
606 	default:
607 		if(n->addable < INDEXED) {
608 			diag(n, "unknown op in lcgen: %O", n->op);
609 			break;
610 		}
611 		nod = *n;
612 		nod.op = OADDR;
613 		nod.left = n;
614 		nod.right = Z;
615 		nod.type = types[TIND];
616 		gopcode(OAS, &nod, Z, nn);
617 		break;
618 
619 	case OCOMMA:
620 		cgen(n->left, n->left);
621 		lcgen(n->right, nn);
622 		break;
623 
624 	case OIND:
625 		cgen(n->left, nn);
626 		break;
627 
628 	case OCOND:
629 		bcgen(n->left, 1);
630 		p1 = p;
631 		lcgen(n->right->left, nn);
632 		gbranch(OGOTO);
633 		patch(p1, pc);
634 		p1 = p;
635 		lcgen(n->right->right, nn);
636 		patch(p1, pc);
637 		break;
638 	}
639 }
640 
641 void
642 bcgen(Node *n, int true)
643 {
644 
645 	if(n->type == T)
646 		gbranch(OGOTO);
647 	else
648 		boolgen(n, true, Z);
649 }
650 
651 void
652 boolgen(Node *n, int true, Node *nn)
653 {
654 	int o, uns;
655 	Prog *p1, *p2;
656 	Node *l, *r, nod, nod1;
657 	long curs;
658 
659 	if(debug['g']) {
660 		prtree(nn, "boolgen lhs");
661 		prtree(n, "boolgen");
662 	}
663 	uns = 0;
664 	curs = cursafe;
665 	l = n->left;
666 	r = n->right;
667 	switch(n->op) {
668 
669 	default:
670 		if(n->op == OCONST) {
671 			o = vconst(n);
672 			if(!true)
673 				o = !o;
674 			gbranch(OGOTO);
675 			if(o) {
676 				p1 = p;
677 				gbranch(OGOTO);
678 				patch(p1, pc);
679 			}
680 			goto com;
681 		}
682 		if(typev[n->type->etype]) {
683 			testv(n, true);
684 			goto com;
685 		}
686 		regalloc(&nod, n, nn);
687 		cgen(n, &nod);
688 		o = ONE;
689 		if(true)
690 			o = comrel[relindex(o)];
691 		if(typefd[n->type->etype]) {
692 			nodreg(&nod1, n, NREG+FREGZERO);
693 			gopcode(o, &nod, Z, &nod1);
694 		} else
695 			gopcode(o, &nod, Z, nodconst(0));
696 		regfree(&nod);
697 		goto com;
698 
699 	case OCOMMA:
700 		cgen(l, Z);
701 		boolgen(r, true, nn);
702 		break;
703 
704 	case ONOT:
705 		boolgen(l, !true, nn);
706 		break;
707 
708 	case OCOND:
709 		bcgen(l, 1);
710 		p1 = p;
711 		bcgen(r->left, true);
712 		p2 = p;
713 		gbranch(OGOTO);
714 		patch(p1, pc);
715 		p1 = p;
716 		bcgen(r->right, !true);
717 		patch(p2, pc);
718 		p2 = p;
719 		gbranch(OGOTO);
720 		patch(p1, pc);
721 		patch(p2, pc);
722 		goto com;
723 
724 	case OANDAND:
725 		if(!true)
726 			goto caseor;
727 
728 	caseand:
729 		bcgen(l, true);
730 		p1 = p;
731 		bcgen(r, !true);
732 		p2 = p;
733 		patch(p1, pc);
734 		gbranch(OGOTO);
735 		patch(p2, pc);
736 		goto com;
737 
738 	case OOROR:
739 		if(!true)
740 			goto caseand;
741 
742 	caseor:
743 		bcgen(l, !true);
744 		p1 = p;
745 		bcgen(r, !true);
746 		p2 = p;
747 		gbranch(OGOTO);
748 		patch(p1, pc);
749 		patch(p2, pc);
750 		goto com;
751 
752 	case OHI:
753 	case OHS:
754 	case OLO:
755 	case OLS:
756 		uns = 1;
757 		/* fall through */
758 	case OEQ:
759 	case ONE:
760 	case OLE:
761 	case OLT:
762 	case OGE:
763 	case OGT:
764 		if(typev[l->type->etype]){
765 			cmpv(n, true, Z);
766 			goto com;
767 		}
768 		o = n->op;
769 		if(true)
770 			o = comrel[relindex(o)];
771 		if(l->complex >= FNX && r->complex >= FNX) {
772 			regret(&nod, r);
773 			cgen(r, &nod);
774 			regsalloc(&nod1, r);
775 			gopcode(OAS, &nod, Z, &nod1);
776 			regfree(&nod);
777 			nod = *n;
778 			nod.right = &nod1;
779 			boolgen(&nod, true, nn);
780 			break;
781 		}
782 		if(!uns && sconst(r) || (uns || o == OEQ || o == ONE) && uconst(r)) {
783 			regalloc(&nod, l, nn);
784 			cgen(l, &nod);
785 			gopcode(o, &nod, Z, r);
786 			regfree(&nod);
787 			goto com;
788 		}
789 		if(l->complex >= r->complex) {
790 			regalloc(&nod1, l, nn);
791 			cgen(l, &nod1);
792 			regalloc(&nod, r, Z);
793 			cgen(r, &nod);
794 		} else {
795 			regalloc(&nod, r, nn);
796 			cgen(r, &nod);
797 			regalloc(&nod1, l, Z);
798 			cgen(l, &nod1);
799 		}
800 		gopcode(o, &nod1, Z, &nod);
801 		regfree(&nod);
802 		regfree(&nod1);
803 
804 	com:
805 		if(nn != Z) {
806 			p1 = p;
807 			gopcode(OAS, nodconst(1L), Z, nn);
808 			gbranch(OGOTO);
809 			p2 = p;
810 			patch(p1, pc);
811 			gopcode(OAS, nodconst(0L), Z, nn);
812 			patch(p2, pc);
813 		}
814 		break;
815 	}
816 	cursafe = curs;
817 }
818 
819 void
820 sugen(Node *n, Node *nn, long w)
821 {
822 	Prog *p1;
823 	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
824 	Type *t;
825 	long pc1;
826 	int i, m, c;
827 
828 	if(n == Z || n->type == T)
829 		return;
830 	if(nn == nodrat)
831 		if(w > nrathole)
832 			nrathole = w;
833 	if(debug['g']) {
834 		prtree(nn, "sugen lhs");
835 		prtree(n, "sugen");
836 	}
837 	if(typev[n->type->etype]) {
838 		diag(n, "old vlong sugen: %O", n->op);
839 		return;
840 	}
841 	switch(n->op) {
842 	case OIND:
843 		if(nn == Z) {
844 			nullwarn(n->left, Z);
845 			break;
846 		}
847 
848 	default:
849 		goto copy;
850 
851 	case ODOT:
852 		l = n->left;
853 		sugen(l, nodrat, l->type->width);
854 		if(nn != Z) {
855 			warn(n, "non-interruptable temporary");
856 			nod1 = *nodrat;
857 			r = n->right;
858 			if(!r || r->op != OCONST) {
859 				diag(n, "DOT and no offset");
860 				break;
861 			}
862 			nod1.xoffset += (long)r->vconst;
863 			nod1.type = n->type;
864 			sugen(&nod1, nn, w);
865 		}
866 		break;
867 
868 	case OSTRUCT:
869 		/*
870 		 * rewrite so lhs has no side effects
871 		 */
872 		if(nn != Z && side(nn)) {
873 			nod1 = *n;
874 			nod1.type = typ(TIND, n->type);
875 			regalloc(&nod2, &nod1, Z);
876 			lcgen(nn, &nod2);
877 			regsalloc(&nod0, &nod1);
878 			gopcode(OAS, &nod2, Z, &nod0);
879 			regfree(&nod2);
880 
881 			nod1 = *n;
882 			nod1.op = OIND;
883 			nod1.left = &nod0;
884 			nod1.right = Z;
885 			nod1.complex = 1;
886 
887 			sugen(n, &nod1, w);
888 			return;
889 		}
890 
891 		r = n->left;
892 		for(t = n->type->link; t != T; t = t->down) {
893 			l = r;
894 			if(r->op == OLIST) {
895 				l = r->left;
896 				r = r->right;
897 			}
898 			if(nn == Z) {
899 				cgen(l, nn);
900 				continue;
901 			}
902 			/*
903 			 * hand craft *(&nn + o) = l
904 			 */
905 			nod0 = znode;
906 			nod0.op = OAS;
907 			nod0.type = t;
908 			nod0.left = &nod1;
909 			nod0.right = l;
910 
911 			nod1 = znode;
912 			nod1.op = OIND;
913 			nod1.type = t;
914 			nod1.left = &nod2;
915 
916 			nod2 = znode;
917 			nod2.op = OADD;
918 			nod2.type = typ(TIND, t);
919 			nod2.left = &nod3;
920 			nod2.right = &nod4;
921 
922 			nod3 = znode;
923 			nod3.op = OADDR;
924 			nod3.type = nod2.type;
925 			nod3.left = nn;
926 
927 			nod4 = znode;
928 			nod4.op = OCONST;
929 			nod4.type = nod2.type;
930 			nod4.vconst = t->offset;
931 
932 			ccom(&nod0);
933 			acom(&nod0);
934 			xcom(&nod0);
935 			nod0.addable = 0;
936 
937 			/* prtree(&nod0, "hand craft"); /* */
938 			cgen(&nod0, Z);
939 		}
940 		break;
941 
942 	case OAS:
943 		if(nn == Z) {
944 			if(n->addable < INDEXED)
945 				sugen(n->right, n->left, w);
946 			break;
947 		}
948 		/* BOTCH -- functions can clobber rathole */
949 		sugen(n->right, nodrat, w);
950 		warn(n, "non-interruptable temporary");
951 		sugen(nodrat, n->left, w);
952 		sugen(nodrat, nn, w);
953 		break;
954 
955 	case OFUNC:
956 		/* this transformation should probably be done earlier */
957 		if(nn == Z) {
958 			sugen(n, nodrat, w);
959 			break;
960 		}
961 		if(nn->op != OIND) {
962 			nn = new1(OADDR, nn, Z);
963 			nn->type = types[TIND];
964 			nn->addable = 0;
965 		} else
966 			nn = nn->left;
967 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
968 		n->complex = FNX;
969 		n->type = types[TVOID];
970 		n->left->type = types[TVOID];
971 		cgen(n, Z);
972 		break;
973 
974 	case OCOND:
975 		bcgen(n->left, 1);
976 		p1 = p;
977 		sugen(n->right->left, nn, w);
978 		gbranch(OGOTO);
979 		patch(p1, pc);
980 		p1 = p;
981 		sugen(n->right->right, nn, w);
982 		patch(p1, pc);
983 		break;
984 
985 	case OCOMMA:
986 		cgen(n->left, Z);
987 		sugen(n->right, nn, w);
988 		break;
989 	}
990 	return;
991 
992 copy:
993 	if(nn == Z)
994 		return;
995 	if(n->complex >= FNX && nn->complex >= FNX) {
996 		t = nn->type;
997 		nn->type = types[TLONG];
998 		regialloc(&nod1, nn, Z);
999 		lcgen(nn, &nod1);
1000 		regsalloc(&nod2, nn);
1001 		nn->type = t;
1002 
1003 		gmove(&nod1, &nod2);
1004 		regfree(&nod1);
1005 
1006 		nod2.type = typ(TIND, t);
1007 
1008 		nod1 = nod2;
1009 		nod1.op = OIND;
1010 		nod1.left = &nod2;
1011 		nod1.right = Z;
1012 		nod1.complex = 1;
1013 		nod1.type = t;
1014 
1015 		sugen(n, &nod1, w);
1016 		return;
1017 	}
1018 
1019 	if(n->complex > nn->complex) {
1020 		t = n->type;
1021 		n->type = types[TLONG];
1022 		reglcgen(&nod1, n, Z);
1023 		n->type = t;
1024 
1025 		t = nn->type;
1026 		nn->type = types[TLONG];
1027 		reglcgen(&nod2, nn, Z);
1028 		nn->type = t;
1029 	} else {
1030 		t = nn->type;
1031 		nn->type = types[TLONG];
1032 		reglcgen(&nod2, nn, Z);
1033 		nn->type = t;
1034 
1035 		t = n->type;
1036 		n->type = types[TLONG];
1037 		reglcgen(&nod1, n, Z);
1038 		n->type = t;
1039 	}
1040 
1041 	w /= SZ_LONG;
1042 	if(w <= 5) {
1043 		layout(&nod1, &nod2, w, 0, Z);
1044 		goto out;
1045 	}
1046 
1047 	/*
1048 	 * minimize space for unrolling loop
1049 	 * 3,4,5 times. (6 or more is never minimum)
1050 	 * if small structure, try 2 also.
1051 	 */
1052 	c = 0; /* set */
1053 	m = 100;
1054 	i = 3;
1055 	if(w <= 15)
1056 		i = 2;
1057 	for(; i<=5; i++)
1058 		if(i + w%i <= m) {
1059 			c = i;
1060 			m = c + w%c;
1061 		}
1062 
1063 	regalloc(&nod3, &regnode, Z);
1064 	layout(&nod1, &nod2, w%c, w/c, &nod3);
1065 
1066 	pc1 = pc;
1067 	layout(&nod1, &nod2, c, 0, Z);
1068 
1069 	gopcode(OSUB, nodconst(1L), Z, &nod3);
1070 	nod1.op = OREGISTER;
1071 	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
1072 	nod2.op = OREGISTER;
1073 	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
1074 
1075 	gopcode(OGT, &nod3, Z, nodconst(0));
1076 	patch(p, pc1);
1077 
1078 	regfree(&nod3);
1079 out:
1080 	regfree(&nod1);
1081 	regfree(&nod2);
1082 }
1083 
1084 void
1085 layout(Node *f, Node *t, int c, int cv, Node *cn)
1086 {
1087 	Node t1, t2;
1088 
1089 	while(c > 3) {
1090 		layout(f, t, 2, 0, Z);
1091 		c -= 2;
1092 	}
1093 
1094 	regalloc(&t1, &regnode, Z);
1095 	regalloc(&t2, &regnode, Z);
1096 	if(c > 0) {
1097 		gopcode(OAS, f, Z, &t1);
1098 		f->xoffset += SZ_LONG;
1099 	}
1100 	if(cn != Z)
1101 		gopcode(OAS, nodconst(cv), Z, cn);
1102 	if(c > 1) {
1103 		gopcode(OAS, f, Z, &t2);
1104 		f->xoffset += SZ_LONG;
1105 	}
1106 	if(c > 0) {
1107 		gopcode(OAS, &t1, Z, t);
1108 		t->xoffset += SZ_LONG;
1109 	}
1110 	if(c > 2) {
1111 		gopcode(OAS, f, Z, &t1);
1112 		f->xoffset += SZ_LONG;
1113 	}
1114 	if(c > 1) {
1115 		gopcode(OAS, &t2, Z, t);
1116 		t->xoffset += SZ_LONG;
1117 	}
1118 	if(c > 2) {
1119 		gopcode(OAS, &t1, Z, t);
1120 		t->xoffset += SZ_LONG;
1121 	}
1122 	regfree(&t1);
1123 	regfree(&t2);
1124 }
1125 
1126 /*
1127  * is the vlong's value directly addressible?
1128  */
1129 int
1130 isvdirect(Node *n)
1131 {
1132 	return n->op == ONAME || n->op == OCONST || n->op == OINDREG;
1133 }
1134 
1135 /*
1136  * can the constant be used with given vlong op?
1137  */
1138 static int
1139 isvconstable(int o, vlong v)
1140 {
1141 	switch(o) {
1142 	case OADD:
1143 	case OASADD:
1144 		/* there isn't an immediate form for ADDE/SUBE, but there are special ADDME/ADDZE etc */
1145 		return v == 0 || v == -1;
1146 	case OAND:
1147 	case OOR:
1148 	case OXOR:
1149 	case OLSHR:
1150 	case OASHL:
1151 	case OASHR:
1152 	case OASLSHR:
1153 	case OASASHL:
1154 	case OASASHR:
1155 		return 1;
1156 	}
1157 	return 0;
1158 }
1159 
1160 /*
1161  * most 64-bit operations: cgen into a register pair, then operate.
1162  * 64-bit comparisons are handled a little differently because the two underlying
1163  * comparisons can be compiled separately, since the calculations don't interact.
1164  */
1165 
1166 static void
1167 vcgen(Node *n, Node *o, int *f)
1168 {
1169 	*f = 0;
1170 	if(!isvdirect(n)) {
1171 		if(n->complex >= FNX) {
1172 			regsalloc(o, n);
1173 			cgen(n, o);
1174 			return;
1175 		}
1176 		*f = 1;
1177 		if(n->addable < INDEXED && n->op != OIND && n->op != OINDEX) {
1178 			regalloc(o, n, Z);
1179 			cgen(n, o);
1180 		} else
1181 			reglcgen(o, n, Z);
1182 	} else
1183 		*o = *n;
1184 }
1185 
1186 static int
1187 isuns(int op)
1188 {
1189 	switch(op){
1190 	case OLO:
1191 	case OLS:
1192 	case OHI:
1193 	case OHS:
1194 		return 1;
1195 	default:
1196 		return 0;
1197 	}
1198 }
1199 
1200 static void
1201 gcmpv(Node *l, Node *r, void (*mov)(Node*, Node*, int), int op)
1202 {
1203 	Node vl, vr;
1204 
1205 	regalloc(&vl, &regnode, Z);
1206 	mov(l, &vl, 0);
1207 	regalloc(&vr, &regnode, Z);
1208 	mov(r, &vr, 1+isuns(op));
1209 	gopcode(op, &vl, Z, &vr);
1210 	if(vl.op == OREGISTER)
1211 		regfree(&vl);
1212 	if(vr.op == OREGISTER)
1213 		regfree(&vr);
1214 }
1215 
1216 static void
1217 brcondv(Node *l, Node *r, int chi, int clo)
1218 {
1219 	Prog *p1, *p2, *p3, *p4;
1220 
1221 	gcmpv(l, r, gloadhi, chi);
1222 	p1 = p;
1223 	gins(ABNE, Z, Z);
1224 	p2 = p;
1225 	gcmpv(l, r, gloadlo, clo);
1226 	p3 = p;
1227 	gbranch(OGOTO);
1228 	p4 = p;
1229 	patch(p1, pc);
1230 	patch(p3, pc);
1231 	gbranch(OGOTO);
1232 	patch(p2, pc);
1233 	patch(p4, pc);
1234 }
1235 
1236 static void
1237 testv(Node *n, int true)
1238 {
1239 	Node nod;
1240 
1241 	nod = znode;
1242 	nod.op = ONE;
1243 	nod.left = n;
1244 	nod.right = new1(0, Z, Z);
1245 	*nod.right = *nodconst(0);
1246 	nod.right->type = n->type;
1247 	nod.type = types[TLONG];
1248 	cmpv(&nod, true, Z);
1249 }
1250 
1251 /*
1252  * comparison for vlong does high and low order parts separately,
1253  * which saves loading the latter if the high order comparison suffices
1254  */
1255 static void
1256 cmpv(Node *n, int true, Node *nn)
1257 {
1258 	Node *l, *r, nod, nod1;
1259 	int o, f1, f2;
1260 	Prog *p1, *p2;
1261 	long curs;
1262 
1263 	if(debug['g']) {
1264 		if(nn != nil)
1265 			prtree(nn, "cmpv lhs");
1266 		prtree(n, "cmpv");
1267 	}
1268 	curs = cursafe;
1269 	l = n->left;
1270 	r = n->right;
1271 	if(l->complex >= FNX && r->complex >= FNX) {
1272 		regsalloc(&nod1, r);
1273 		cgen(r, &nod1);
1274 		nod = *n;
1275 		nod.right = &nod1;
1276 		cmpv(&nod, true, nn);
1277 		cursafe = curs;
1278 		return;
1279 	}
1280 	if(l->complex >= r->complex) {
1281 		vcgen(l, &nod1, &f1);
1282 		vcgen(r, &nod, &f2);
1283 	} else {
1284 		vcgen(r, &nod, &f2);
1285 		vcgen(l, &nod1, &f1);
1286 	}
1287 	nod.type = types[TLONG];
1288 	nod1.type = types[TLONG];
1289 	o = n->op;
1290 	if(true)
1291 		o = comrel[relindex(o)];
1292 	switch(o){
1293 	case OEQ:
1294 		gcmpv(&nod1, &nod, gloadhi, ONE);
1295 		p1 = p;
1296 		gcmpv(&nod1, &nod, gloadlo, ONE);
1297 		p2 = p;
1298 		gbranch(OGOTO);
1299 		patch(p1, pc);
1300 		patch(p2, pc);
1301 		break;
1302 	case ONE:
1303 		gcmpv(&nod1, &nod, gloadhi, ONE);
1304 		p1 = p;
1305 		gcmpv(&nod1, &nod, gloadlo, OEQ);
1306 		p2 = p;
1307 		patch(p1, pc);
1308 		gbranch(OGOTO);
1309 		patch(p2, pc);
1310 		break;
1311 	case OLE:
1312 		brcondv(&nod1, &nod, OLT, OLS);
1313 		break;
1314 	case OGT:
1315 		brcondv(&nod1, &nod, OGT, OHI);
1316 		break;
1317 	case OLS:
1318 		brcondv(&nod1, &nod, OLO, OLS);
1319 		break;
1320 	case OHI:
1321 		brcondv(&nod1, &nod, OHI, OHI);
1322 		break;
1323 	case OLT:
1324 		brcondv(&nod1, &nod, OLT, OLO);
1325 		break;
1326 	case OGE:
1327 		brcondv(&nod1, &nod, OGT, OHS);
1328 		break;
1329 	case OLO:
1330 		brcondv(&nod1, &nod, OLO, OLO);
1331 		break;
1332 	case OHS:
1333 		brcondv(&nod1, &nod, OHI, OHS);
1334 		break;
1335 	default:
1336 		diag(n, "bad cmpv");
1337 		return;
1338 	}
1339 	if(f1)
1340 		regfree(&nod1);
1341 	if(f2)
1342 		regfree(&nod);
1343 	cursafe = curs;
1344 }
1345 
1346 static void
1347 cgen64(Node *n, Node *nn)
1348 {
1349 	Node *l, *r, *d;
1350 	Node nod, nod1;
1351 	long curs;
1352 	Type *t;
1353 	int o, m;
1354 
1355 	curs = cursafe;
1356 	l = n->left;
1357 	r = n->right;
1358 	o = n->op;
1359 	switch(o) {
1360 
1361 	case OCONST:
1362 		if(nn == Z) {
1363 			nullwarn(n->left, Z);
1364 			break;
1365 		}
1366 		if(nn->op != OREGPAIR) {
1367 //prtree(n, "cgen64 const");
1368 			t = nn->type;
1369 			nn->type = types[TLONG];
1370 			reglcgen(&nod1, nn, Z);
1371 			nn->type = t;
1372 
1373 			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
1374 				gmove(nod32const(n->vconst>>32), &nod1);
1375 			else
1376 				gmove(nod32const(n->vconst), &nod1);
1377 			nod1.xoffset += SZ_LONG;
1378 			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
1379 				gmove(nod32const(n->vconst), &nod1);
1380 			else
1381 				gmove(nod32const(n->vconst>>32), &nod1);
1382 
1383 			regfree(&nod1);
1384 		} else
1385 			gmove(n, nn);
1386 		break;
1387 
1388 	case OCAST:
1389 		/*
1390 		 * convert from types l->n->nn
1391 		 */
1392 		if(typev[l->type->etype]){
1393 			/* vlong to non-vlong */
1394 			if(!isvdirect(l)) {
1395 				if(l->addable < INDEXED && l->op != OIND && l->op != OINDEX) {
1396 					regalloc(&nod, l, l);
1397 					cgen(l, &nod);
1398 					regalloc(&nod1, n, nn);
1399 					gmove(nod.right, &nod1);
1400 				} else {
1401 					reglcgen(&nod, l, Z);
1402 					regalloc(&nod1, n, nn);
1403 					gloadlo(&nod, &nod1, 0);	/* TO DO: not correct for typefd */
1404 				}
1405 				regfree(&nod);
1406 			} else {
1407 				regalloc(&nod1, n, nn);
1408 				gloadlo(l, &nod1, 0);	/* TO DO: not correct for typefd */
1409 			}
1410 		}else{
1411 			/* non-vlong to vlong */
1412 			regalloc(&nod, l, Z);
1413 			cgen(l, &nod);
1414 			regalloc(&nod1, n, nn);
1415 			gmove(&nod, nod1.right);
1416 			if(typeu[l->type->etype])
1417 				gmove(nodconst(0), nod1.left);
1418 			else
1419 				gopcode(OASHR, nodconst(31), nod1.right, nod1.left);
1420 			regfree(&nod);
1421 		}
1422 		gmove(&nod1, nn);
1423 		regfree(&nod1);
1424 		break;
1425 
1426 	case OFUNC:
1427 		/* this transformation should probably be done earlier */
1428 		if(nn == Z) {
1429 			regsalloc(&nod1, n);
1430 			nn = &nod1;
1431 		}
1432 		m = 0;
1433 		if(nn->op != OIND) {
1434 			if(nn->op == OREGPAIR) {
1435 				m = 1;
1436 				regsalloc(&nod1, nn);
1437 				d = &nod1;
1438 			}else
1439 				d = nn;
1440 			d = new1(OADDR, d, Z);
1441 			d->type = types[TIND];
1442 			d->addable = 0;
1443 		} else
1444 			d = nn->left;
1445 		n = new(OFUNC, l, new(OLIST, d, r));
1446 		n->complex = FNX;
1447 		n->type = types[TVOID];
1448 		n->left->type = types[TVOID];
1449 		cgen(n, Z);
1450 		if(m)
1451 			gmove(&nod1, nn);
1452 		break;
1453 
1454 	default:
1455 		diag(n, "bad cgen64 %O", o);
1456 		break;
1457 	}
1458 	cursafe = curs;
1459 }
1460