xref: /inferno-os/utils/ic/cgen.c (revision 6e84dc968bc4eaf047fbefcba2f670940718dda8)
1 #include "gc.h"
2 
3 void
4 cgen(Node *n, Node *nn)
5 {
6 	Node *l, *r;
7 	Prog *p1;
8 	Node nod, nod1, nod2, nod3, nod4;
9 	int o;
10 	long v, curs;
11 
12 	if(debug['g']) {
13 		prtree(nn, "cgen lhs");
14 		prtree(n, "cgen");
15 	}
16 	if(n == Z || n->type == T)
17 		return;
18 	if(typecmplx[n->type->etype]) {
19 		sugen(n, nn, n->type->width);
20 		return;
21 	}
22 	l = n->left;
23 	r = n->right;
24 	o = n->op;
25 	if(n->addable >= INDEXED) {
26 		if(nn == Z) {
27 			switch(o) {
28 			default:
29 				nullwarn(Z, Z);
30 				break;
31 			case OINDEX:
32 				nullwarn(l, r);
33 				break;
34 			}
35 			return;
36 		}
37 		gmove(n, nn);
38 		return;
39 	}
40 	curs = cursafe;
41 
42 	if(n->complex >= FNX)
43 	if(l->complex >= FNX)
44 	if(r != Z && r->complex >= FNX)
45 	switch(o) {
46 	default:
47 		regret(&nod, r);
48 		cgen(r, &nod);
49 
50 		regsalloc(&nod1, r);
51 		gopcode(OAS, &nod, Z, &nod1);
52 
53 		regfree(&nod);
54 		nod = *n;
55 		nod.right = &nod1;
56 		cgen(&nod, nn);
57 		return;
58 
59 	case OFUNC:
60 	case OCOMMA:
61 	case OANDAND:
62 	case OOROR:
63 	case OCOND:
64 	case ODOT:
65 		break;
66 	}
67 
68 	switch(o) {
69 	default:
70 		diag(n, "unknown op in cgen: %O", o);
71 		break;
72 
73 	case OAS:
74 		if(l->op == OBIT)
75 			goto bitas;
76 		if(l->addable >= INDEXED && l->complex < FNX) {
77 			if(nn != Z || r->addable < INDEXED) {
78 				if(r->complex >= FNX && nn == Z)
79 					regret(&nod, r);
80 				else
81 					regalloc(&nod, r, nn);
82 				cgen(r, &nod);
83 				gmove(&nod, l);
84 				if(nn != Z)
85 					gmove(&nod, nn);
86 				regfree(&nod);
87 			} else
88 				gmove(r, l);
89 			break;
90 		}
91 		if(l->complex >= r->complex) {
92 			reglcgen(&nod1, l, Z);
93 			if(r->addable >= INDEXED) {
94 				gmove(r, &nod1);
95 				if(nn != Z)
96 					gmove(r, nn);
97 				regfree(&nod1);
98 				break;
99 			}
100 			regalloc(&nod, r, nn);
101 			cgen(r, &nod);
102 		} else {
103 			regalloc(&nod, r, nn);
104 			cgen(r, &nod);
105 			reglcgen(&nod1, l, Z);
106 		}
107 		gmove(&nod, &nod1);
108 		regfree(&nod);
109 		regfree(&nod1);
110 		break;
111 
112 	bitas:
113 		n = l->left;
114 		regalloc(&nod, r, nn);
115 		if(l->complex >= r->complex) {
116 			reglcgen(&nod1, n, Z);
117 			cgen(r, &nod);
118 		} else {
119 			cgen(r, &nod);
120 			reglcgen(&nod1, n, Z);
121 		}
122 		regalloc(&nod2, n, Z);
123 		gopcode(OAS, &nod1, Z, &nod2);
124 		bitstore(l, &nod, &nod1, &nod2, nn);
125 		break;
126 
127 	case OBIT:
128 		if(nn == Z) {
129 			nullwarn(l, Z);
130 			break;
131 		}
132 		bitload(n, &nod, Z, Z, nn);
133 		gopcode(OAS, &nod, Z, nn);
134 		regfree(&nod);
135 		break;
136 
137 	case OADD:
138 	case OSUB:
139 	case OAND:
140 	case OOR:
141 	case OXOR:
142 	case OLSHR:
143 	case OASHL:
144 	case OASHR:
145 		/*
146 		 * immediate operands
147 		 */
148 		if(nn != Z)
149 		if(sconst(r))
150 		if(!typefd[n->type->etype])
151 		if(r->vconst >= -2048 && r->vconst < 2048) {
152 			cgen(l, nn);
153 			if(r->vconst == 0)
154 			if(o != OAND)
155 				break;
156 			if(nn != Z)
157 				gopcode(o, r, Z, nn);
158 			break;
159 		}
160 
161 	case OLMUL:
162 	case OLDIV:
163 	case OLMOD:
164 	case OMUL:
165 	case ODIV:
166 	case OMOD:
167 		if(nn == Z) {
168 			nullwarn(l, r);
169 			break;
170 		}
171 		if(o == OMUL || o == OLMUL) {
172 			if(mulcon(n, nn))
173 				break;
174 		}
175 		if(l->complex >= r->complex) {
176 			regalloc(&nod, l, nn);
177 			cgen(l, &nod);
178 			regalloc(&nod1, r, Z);
179 			cgen(r, &nod1);
180 			gopcode(o, &nod1, Z, &nod);
181 		} else {
182 			regalloc(&nod, r, nn);
183 			cgen(r, &nod);
184 			regalloc(&nod1, l, Z);
185 			cgen(l, &nod1);
186 			gopcode(o, &nod, &nod1, &nod);
187 		}
188 		gopcode(OAS, &nod, Z, nn);
189 		regfree(&nod);
190 		regfree(&nod1);
191 		break;
192 
193 	case OASLSHR:
194 	case OASASHL:
195 	case OASASHR:
196 	case OASAND:
197 	case OASADD:
198 	case OASSUB:
199 	case OASXOR:
200 	case OASOR:
201 		if(l->op == OBIT)
202 			goto asbitop;
203 		if(sconst(r))
204 		if(!typefd[n->type->etype]) {
205 			if(l->addable < INDEXED)
206 				reglcgen(&nod2, l, Z);
207 			else
208 				nod2 = *l;
209 			regalloc(&nod, r, nn);
210 			gopcode(OAS, &nod2, Z, &nod);
211 			gopcode(o, r, Z, &nod);
212 			gopcode(OAS, &nod, Z, &nod2);
213 
214 			regfree(&nod);
215 			if(l->addable < INDEXED)
216 				regfree(&nod2);
217 			break;
218 		}
219 
220 	case OASLMUL:
221 	case OASLDIV:
222 	case OASLMOD:
223 	case OASMUL:
224 	case OASDIV:
225 	case OASMOD:
226 		if(l->op == OBIT)
227 			goto asbitop;
228 		if(l->complex >= r->complex) {
229 			if(l->addable < INDEXED)
230 				reglcgen(&nod2, l, Z);
231 			else
232 				nod2 = *l;
233 			regalloc(&nod1, r, Z);
234 			cgen(r, &nod1);
235 		} else {
236 			regalloc(&nod1, r, Z);
237 			cgen(r, &nod1);
238 			if(l->addable < INDEXED)
239 				reglcgen(&nod2, l, Z);
240 			else
241 				nod2 = *l;
242 		}
243 
244 		regalloc(&nod, n, nn);
245 		gmove(&nod2, &nod);
246 		gopcode(o, &nod1, Z, &nod);
247 		gmove(&nod, &nod2);
248 		if(nn != Z)
249 			gopcode(OAS, &nod, Z, nn);
250 		regfree(&nod);
251 		regfree(&nod1);
252 		if(l->addable < INDEXED)
253 			regfree(&nod2);
254 		break;
255 
256 	asbitop:
257 		regalloc(&nod4, n, nn);
258 		if(l->complex >= r->complex) {
259 			bitload(l, &nod, &nod1, &nod2, &nod4);
260 			regalloc(&nod3, r, Z);
261 			cgen(r, &nod3);
262 		} else {
263 			regalloc(&nod3, r, Z);
264 			cgen(r, &nod3);
265 			bitload(l, &nod, &nod1, &nod2, &nod4);
266 		}
267 		gmove(&nod, &nod4);
268 		gopcode(o, &nod3, Z, &nod4);
269 		regfree(&nod3);
270 		gmove(&nod4, &nod);
271 		regfree(&nod4);
272 		bitstore(l, &nod, &nod1, &nod2, nn);
273 		break;
274 
275 	case OADDR:
276 		if(nn == Z) {
277 			nullwarn(l, Z);
278 			break;
279 		}
280 		lcgen(l, nn);
281 		break;
282 
283 	case OFUNC:
284 		if(l->complex >= FNX) {
285 			if(l->op != OIND)
286 				diag(n, "bad function call");
287 
288 			regret(&nod, l->left);
289 			cgen(l->left, &nod);
290 			regsalloc(&nod1, l->left);
291 			gopcode(OAS, &nod, Z, &nod1);
292 			regfree(&nod);
293 
294 			nod = *n;
295 			nod.left = &nod2;
296 			nod2 = *l;
297 			nod2.left = &nod1;
298 			nod2.complex = 1;
299 			cgen(&nod, nn);
300 
301 			return;
302 		}
303 		o = reg[REGARG];
304 		gargs(r, &nod, &nod1);
305 		if(l->addable < INDEXED) {
306 			reglcgen(&nod, l, Z);
307 			gopcode(OFUNC, Z, Z, &nod);
308 			regfree(&nod);
309 		} else
310 			gopcode(OFUNC, Z, Z, l);
311 		if(REGARG)
312 			if(o != reg[REGARG])
313 				reg[REGARG]--;
314 		if(nn != Z) {
315 			regret(&nod, n);
316 			gopcode(OAS, &nod, Z, nn);
317 			regfree(&nod);
318 		}
319 		break;
320 
321 	case OIND:
322 		if(nn == Z) {
323 			nullwarn(l, Z);
324 			break;
325 		}
326 		regialloc(&nod, n, nn);
327 		r = l;
328 		while(r->op == OADD)
329 			r = r->right;
330 		if(sconst(r)) {
331 			v = r->vconst;
332 			r->vconst = 0;
333 			cgen(l, &nod);
334 			nod.xoffset += v;
335 			r->vconst = v;
336 		} else
337 			cgen(l, &nod);
338 		regind(&nod, n);
339 		gopcode(OAS, &nod, Z, nn);
340 		regfree(&nod);
341 		break;
342 
343 	case OEQ:
344 	case ONE:
345 	case OLE:
346 	case OLT:
347 	case OGE:
348 	case OGT:
349 	case OLO:
350 	case OLS:
351 	case OHI:
352 	case OHS:
353 		if(nn == Z) {
354 			nullwarn(l, r);
355 			break;
356 		}
357 		boolgen(n, 1, nn);
358 		break;
359 
360 	case OANDAND:
361 	case OOROR:
362 		boolgen(n, 1, nn);
363 		if(nn == Z)
364 			patch(p, pc);
365 		break;
366 
367 	case ONOT:
368 		if(nn == Z) {
369 			nullwarn(l, Z);
370 			break;
371 		}
372 		boolgen(n, 1, nn);
373 		break;
374 
375 	case OCOMMA:
376 		cgen(l, Z);
377 		cgen(r, nn);
378 		break;
379 
380 	case OCAST:
381 		if(nn == Z) {
382 			nullwarn(l, Z);
383 			break;
384 		}
385 		/*
386 		 * convert from types l->n->nn
387 		 */
388 		if(nocast(l->type, n->type)) {
389 			if(nocast(n->type, nn->type)) {
390 				cgen(l, nn);
391 				break;
392 			}
393 		}
394 		regalloc(&nod, l, nn);
395 		cgen(l, &nod);
396 #ifdef maybe
397 		if(l->op == ONAME || l->op == OINDREG || l->op == OIND)
398 			if(typechlp[l->type->etype] && typeilp[nn->type->etype]){
399 				/* load effectively does the cast */
400 				nod.type = types[TLONG];
401 				gopcode(OAS, &nod, Z, nn);
402 				regfree(&nod);
403 				break;
404 			}
405 #endif
406 		regalloc(&nod1, n, &nod);
407 		gopcode(OAS, &nod, Z, &nod1);
408 		gopcode(OAS, &nod1, Z, nn);
409 		regfree(&nod1);
410 		regfree(&nod);
411 		break;
412 
413 	case ODOT:
414 		sugen(l, nodrat, l->type->width);
415 		if(nn != Z) {
416 			warn(n, "non-interruptable temporary");
417 			nod = *nodrat;
418 			if(!r || r->op != OCONST) {
419 				diag(n, "DOT and no offset");
420 				break;
421 			}
422 			nod.xoffset += (long)r->vconst;
423 			nod.type = n->type;
424 			cgen(&nod, nn);
425 		}
426 		break;
427 
428 	case OCOND:
429 		bcgen(l, 1);
430 		p1 = p;
431 		cgen(r->left, nn);
432 		gbranch(OGOTO);
433 		patch(p1, pc);
434 		p1 = p;
435 		cgen(r->right, nn);
436 		patch(p1, pc);
437 		break;
438 
439 	case OPOSTINC:
440 	case OPOSTDEC:
441 		v = 1;
442 		if(l->type->etype == TIND)
443 			v = l->type->link->width;
444 		if(o == OPOSTDEC)
445 			v = -v;
446 		if(l->op == OBIT)
447 			goto bitinc;
448 		if(nn == Z)
449 			goto pre;
450 
451 		if(l->addable < INDEXED)
452 			reglcgen(&nod2, l, Z);
453 		else
454 			nod2 = *l;
455 
456 		regalloc(&nod, l, nn);
457 		gopcode(OAS, &nod2, Z, &nod);
458 		regalloc(&nod1, l, Z);
459 		if(typefd[l->type->etype]) {
460 			regalloc(&nod3, l, Z);
461 			if(v < 0) {
462 				gopcode(OAS, nodfconst(-v), Z, &nod3);
463 				gopcode(OSUB, &nod3, &nod, &nod1);
464 			} else {
465 				gopcode(OAS, nodfconst(v), Z, &nod3);
466 				gopcode(OADD, &nod3, &nod, &nod1);
467 			}
468 			regfree(&nod3);
469 		} else
470 			gopcode(OADD, nodconst(v), &nod, &nod1);
471 		gopcode(OAS, &nod1, Z, &nod2);
472 
473 		regfree(&nod);
474 		regfree(&nod1);
475 		if(l->addable < INDEXED)
476 			regfree(&nod2);
477 		break;
478 
479 	case OPREINC:
480 	case OPREDEC:
481 		v = 1;
482 		if(l->type->etype == TIND)
483 			v = l->type->link->width;
484 		if(o == OPREDEC)
485 			v = -v;
486 		if(l->op == OBIT)
487 			goto bitinc;
488 
489 	pre:
490 		if(l->addable < INDEXED)
491 			reglcgen(&nod2, l, Z);
492 		else
493 			nod2 = *l;
494 
495 		regalloc(&nod, l, nn);
496 		gopcode(OAS, &nod2, Z, &nod);
497 		if(typefd[l->type->etype]) {
498 			regalloc(&nod3, l, Z);
499 			if(v < 0) {
500 				gopcode(OAS, nodfconst(-v), Z, &nod3);
501 				gopcode(OSUB, &nod3, Z, &nod);
502 			} else {
503 				gopcode(OAS, nodfconst(v), Z, &nod3);
504 				gopcode(OADD, &nod3, Z, &nod);
505 			}
506 			regfree(&nod3);
507 		} else
508 			gopcode(OADD, nodconst(v), Z, &nod);
509 		gopcode(OAS, &nod, Z, &nod2);
510 		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
511 			gins(ANOP, l, Z);
512 
513 		regfree(&nod);
514 		if(l->addable < INDEXED)
515 			regfree(&nod2);
516 		break;
517 
518 	bitinc:
519 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
520 			bitload(l, &nod, &nod1, &nod2, Z);
521 			gopcode(OAS, &nod, Z, nn);
522 			gopcode(OADD, nodconst(v), Z, &nod);
523 			bitstore(l, &nod, &nod1, &nod2, Z);
524 			break;
525 		}
526 		bitload(l, &nod, &nod1, &nod2, nn);
527 		gopcode(OADD, nodconst(v), Z, &nod);
528 		bitstore(l, &nod, &nod1, &nod2, nn);
529 		break;
530 	}
531 	cursafe = curs;
532 }
533 
534 void
535 reglcgen(Node *t, Node *n, Node *nn)
536 {
537 	Node *r;
538 	long v;
539 
540 	regialloc(t, n, nn);
541 	if(n->op == OIND) {
542 		r = n->left;
543 		while(r->op == OADD)
544 			r = r->right;
545 		if(sconst(r)) {
546 			v = r->vconst;
547 			r->vconst = 0;
548 			lcgen(n, t);
549 			t->xoffset += v;
550 			r->vconst = v;
551 			regind(t, n);
552 			return;
553 		}
554 	}
555 	lcgen(n, t);
556 	regind(t, n);
557 }
558 
559 void
560 lcgen(Node *n, Node *nn)
561 {
562 	Prog *p1;
563 	Node nod;
564 
565 	if(debug['g']) {
566 		prtree(nn, "lcgen lhs");
567 		prtree(n, "lcgen");
568 	}
569 	if(n == Z || n->type == T)
570 		return;
571 	if(nn == Z) {
572 		nn = &nod;
573 		regalloc(&nod, n, Z);
574 	}
575 	switch(n->op) {
576 	default:
577 		if(n->addable < INDEXED) {
578 			diag(n, "unknown op in lcgen: %O", n->op);
579 			break;
580 		}
581 		nod = *n;
582 		nod.op = OADDR;
583 		nod.left = n;
584 		nod.right = Z;
585 		nod.type = types[TIND];
586 		gopcode(OAS, &nod, Z, nn);
587 		break;
588 
589 	case OCOMMA:
590 		cgen(n->left, n->left);
591 		lcgen(n->right, nn);
592 		break;
593 
594 	case OIND:
595 		cgen(n->left, nn);
596 		break;
597 
598 	case OCOND:
599 		bcgen(n->left, 1);
600 		p1 = p;
601 		lcgen(n->right->left, nn);
602 		gbranch(OGOTO);
603 		patch(p1, pc);
604 		p1 = p;
605 		lcgen(n->right->right, nn);
606 		patch(p1, pc);
607 		break;
608 	}
609 }
610 
611 /*
612  * Conditional branch if bool(n) != true
613  */
614 void
615 bcgen(Node *n, int true)
616 {
617 
618 	if(n->type == T)
619 		gbranch(OGOTO);
620 	else
621 		boolgen(n, true, Z);
622 }
623 
624 /*
625  * If nn == Z, conditional branch if bool(n) != true
626  * If nn != Z, assign n = (bool(n) == true)
627  */
628 void
629 boolgen(Node *n, int true, Node *nn)
630 {
631 	int o;
632 	Prog *p1, *p2;
633 	Node *l, *r, nod, nod1, nod2;
634 	long curs;
635 
636 	if(debug['g']) {
637 		prtree(nn, "boolgen lhs");
638 		prtree(n, true? "boolgen true" : "boolgen false");
639 	}
640 	curs = cursafe;
641 	l = n->left;
642 	r = n->right;
643 	switch(n->op) {
644 
645 	default:
646 		regalloc(&nod, n, nn);
647 		cgen(n, &nod);
648 		if(nn == Z) {
649 			o = true? OEQ : ONE;
650 			if(typefd[n->type->etype]) {
651 				nodreg(&nod1, n, NREG+FREGZERO);
652 				gopcode(o, &nod, &nod1, Z);
653 			} else
654 				gopcode(o, &nod, Z, Z);
655 			regfree(&nod);
656 			break;
657 		}
658 		if(typefd[n->type->etype]) {
659 			regalloc(&nod2, nn, nn);
660 			o = true? ONE : OEQ;
661 			nodreg(&nod1, n, NREG+FREGZERO);
662 			gopcode(o, &nod, &nod1, &nod2);
663 			gopcode(OAS, &nod2, Z, nn);
664 			regfree(&nod2);
665 			regfree(&nod);
666 			break;
667 		}
668 		if(true)
669 			gopcode(OCOND, &nod, nodconst(0), &nod);
670 		else
671 			gopcode(OCOND, nodconst(1), &nod, &nod);
672 		gopcode(OAS, &nod, Z, nn);
673 		regfree(&nod);
674 		break;
675 
676 	case OCONST:
677 		o = vconst(n);
678 		if(!true)
679 			o = !o;
680 		gbranch(OGOTO);
681 		if(o) {
682 			p1 = p;
683 			gbranch(OGOTO);
684 			patch(p1, pc);
685 		}
686 		goto com;
687 
688 	case OCOMMA:
689 		cgen(l, Z);
690 		boolgen(r, true, nn);
691 		break;
692 
693 	case ONOT:
694 		boolgen(l, !true, nn);
695 		break;
696 
697 	case OCOND:
698 		bcgen(l, 1);
699 		p1 = p;
700 		bcgen(r->left, true);
701 		p2 = p;
702 		gbranch(OGOTO);
703 		patch(p1, pc);
704 		p1 = p;
705 		bcgen(r->right, !true);
706 		patch(p2, pc);
707 		p2 = p;
708 		gbranch(OGOTO);
709 		patch(p1, pc);
710 		patch(p2, pc);
711 		goto com;
712 
713 	case OANDAND:
714 		if(!true)
715 			goto caseor;
716 
717 	caseand:
718 		bcgen(l, true);
719 		p1 = p;
720 		bcgen(r, !true);
721 		p2 = p;
722 		patch(p1, pc);
723 		gbranch(OGOTO);
724 		patch(p2, pc);
725 		goto com;
726 
727 	case OOROR:
728 		if(!true)
729 			goto caseand;
730 
731 	caseor:
732 		bcgen(l, !true);
733 		p1 = p;
734 		bcgen(r, !true);
735 		p2 = p;
736 		gbranch(OGOTO);
737 		patch(p1, pc);
738 		patch(p2, pc);
739 		goto com;
740 
741 	case OEQ:
742 	case ONE:
743 	case OLE:
744 	case OLT:
745 	case OGE:
746 	case OGT:
747 	case OHI:
748 	case OHS:
749 	case OLO:
750 	case OLS:
751 		o = n->op;
752 		if(l->complex >= FNX && r->complex >= FNX) {
753 			regret(&nod, r);
754 			cgen(r, &nod);
755 			regsalloc(&nod1, r);
756 			gopcode(OAS, &nod, Z, &nod1);
757 			regfree(&nod);
758 			nod = *n;
759 			nod.right = &nod1;
760 			boolgen(&nod, true, nn);
761 			break;
762 		}
763 		if(true)
764 			o = comrel[relindex(o)];
765 		if(nn != Z || typefd[l->type->etype]) {
766 			if(l->complex >= r->complex) {
767 				regalloc(&nod1, l, nn);
768 				cgen(l, &nod1);
769 				regalloc(&nod, r, Z);
770 				cgen(r, &nod);
771 			} else {
772 				regalloc(&nod, r, nn);
773 				cgen(r, &nod);
774 				regalloc(&nod1, l, Z);
775 				cgen(l, &nod1);
776 			}
777 			if(typefd[l->type->etype]) {
778 				if(nn != Z) {
779 					/* fp compare for assignment */
780 					regalloc(&nod2, nn, nn);
781 					gopcode(o, &nod, &nod1, &nod2);
782 					regfree(&nod2);
783 				} else
784 					/* fp compare for branch */
785 					gopcode(o, &nod, &nod1, Z);
786 				regfree(&nod);
787 				regfree(&nod1);
788 				break;
789 			}
790 			/* int compare for assignment */
791 			switch(o) {
792 			case OEQ:
793 				gopcode(OSUB, &nod1, &nod, &nod);
794 				gopcode(OCOND, &nod, nodconst(0), &nod);
795 				break;
796 			case ONE:
797 				gopcode(OSUB, &nod1, &nod, &nod);
798 				gopcode(OCOND, nodconst(1), &nod, &nod);
799 				break;
800 			case OLE:
801 				gopcode(OCOMMA, &nod1, &nod, &nod);
802 				break;
803 			case OGT:
804 				gopcode(OCOMMA, &nod1, &nod, &nod);
805 				gopcode(OXOR, nodconst(1), &nod, &nod);
806 				break;
807 			case OLT:
808 				gopcode(OCOMMA, &nod, &nod1, &nod);
809 				gopcode(OXOR, nodconst(1), &nod, &nod);
810 				break;
811 			case OGE:
812 				gopcode(OCOMMA, &nod, &nod1, &nod);
813 				break;
814 			case OLS:
815 				gopcode(OCOND, &nod1, &nod, &nod);
816 				break;
817 			case OHI:
818 				gopcode(OCOND, &nod1, &nod, &nod);
819 				gopcode(OXOR, nodconst(1), &nod, &nod);
820 				break;
821 			case OLO:
822 				gopcode(OCOND, &nod, &nod1, &nod);
823 				gopcode(OXOR, nodconst(1), &nod, &nod);
824 				break;
825 			case OHS:
826 				gopcode(OCOND, &nod, &nod1, &nod);
827 				break;
828 			}
829 			gopcode(OAS, &nod, Z, nn);
830 			regfree(&nod);
831 			regfree(&nod1);
832 			break;
833 		}
834 		/* int compare for branch */
835 		if(0 && sconst(l)) {
836 			if(l->vconst == 0) {
837 				regalloc(&nod, r, nn);
838 				cgen(r, &nod);
839 				gopcode(o, l, &nod, Z);
840 				regfree(&nod);
841 				goto com;
842 			}
843 		}
844 		if(0 && sconst(r)) {
845 			if(r->vconst == 0) {
846 				regalloc(&nod, l, nn);
847 				cgen(l, &nod);
848 				gopcode(o, &nod, r, Z);
849 				regfree(&nod);
850 				goto com;
851 			}
852 		}
853 		if(l->complex >= r->complex) {
854 			regalloc(&nod1, l, nn);
855 			cgen(l, &nod1);
856 			regalloc(&nod, r, Z);
857 			cgen(r, &nod);
858 		} else {
859 			regalloc(&nod, r, nn);
860 			cgen(r, &nod);
861 			regalloc(&nod1, l, Z);
862 			cgen(l, &nod1);
863 		}
864 
865 		gopcode(o, &nod, &nod1, Z);
866 		regfree(&nod);
867 		regfree(&nod1);
868 
869 	com:
870 		if(nn != Z) {
871 			p1 = p;
872 			gopcode(OAS, nodconst(1), Z, nn);
873 			gbranch(OGOTO);
874 			p2 = p;
875 			patch(p1, pc);
876 			gopcode(OAS, nodconst(0), Z, nn);
877 			patch(p2, pc);
878 		}
879 		break;
880 	}
881 	cursafe = curs;
882 }
883 
884 void
885 sugen(Node *n, Node *nn, long w)
886 {
887 	Prog *p1;
888 	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
889 	Type *t;
890 	long pc1;
891 	int i, m, c;
892 
893 	if(n == Z || n->type == T)
894 		return;
895 	if(debug['g']) {
896 		prtree(nn, "sugen lhs");
897 		prtree(n, "sugen");
898 	}
899 	if(nn == nodrat)
900 		if(w > nrathole)
901 			nrathole = w;
902 	switch(n->op) {
903 	case OIND:
904 		if(nn == Z) {
905 			nullwarn(n->left, Z);
906 			break;
907 		}
908 
909 	default:
910 		goto copy;
911 
912 	case OCONST:
913 		if(n->type && typev[n->type->etype]) {
914 			if(nn == Z) {
915 				nullwarn(n->left, Z);
916 				break;
917 			}
918 
919 			t = nn->type;
920 			nn->type = types[TLONG];
921 			reglcgen(&nod1, nn, Z);
922 			nn->type = t;
923 
924 			gopcode(OAS, nod32const(n->vconst), Z, &nod1);
925 			nod1.xoffset += SZ_LONG;
926 			gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
927 
928 			regfree(&nod1);
929 			break;
930 		}
931 		goto copy;
932 
933 	case ODOT:
934 		l = n->left;
935 		sugen(l, nodrat, l->type->width);
936 		if(nn != Z) {
937 			warn(n, "non-interruptable temporary");
938 			nod1 = *nodrat;
939 			r = n->right;
940 			if(!r || r->op != OCONST) {
941 				diag(n, "DOT and no offset");
942 				break;
943 			}
944 			nod1.xoffset += (long)r->vconst;
945 			nod1.type = n->type;
946 			sugen(&nod1, nn, w);
947 		}
948 		break;
949 
950 	case OSTRUCT:
951 		/*
952 		 * rewrite so lhs has no fn call
953 		 */
954 		if(nn != Z && nn->complex >= FNX) {
955 			nod1 = *n;
956 			nod1.type = typ(TIND, n->type);
957 			regret(&nod2, &nod1);
958 			lcgen(nn, &nod2);
959 			regsalloc(&nod0, &nod1);
960 			gopcode(OAS, &nod2, Z, &nod0);
961 			regfree(&nod2);
962 
963 			nod1 = *n;
964 			nod1.op = OIND;
965 			nod1.left = &nod0;
966 			nod1.right = Z;
967 			nod1.complex = 1;
968 
969 			sugen(n, &nod1, w);
970 			return;
971 		}
972 
973 		r = n->left;
974 		for(t = n->type->link; t != T; t = t->down) {
975 			l = r;
976 			if(r->op == OLIST) {
977 				l = r->left;
978 				r = r->right;
979 			}
980 			if(nn == Z) {
981 				cgen(l, nn);
982 				continue;
983 			}
984 			/*
985 			 * hand craft *(&nn + o) = l
986 			 */
987 			nod0 = znode;
988 			nod0.op = OAS;
989 			nod0.type = t;
990 			nod0.left = &nod1;
991 			nod0.right = l;
992 
993 			nod1 = znode;
994 			nod1.op = OIND;
995 			nod1.type = t;
996 			nod1.left = &nod2;
997 
998 			nod2 = znode;
999 			nod2.op = OADD;
1000 			nod2.type = typ(TIND, t);
1001 			nod2.left = &nod3;
1002 			nod2.right = &nod4;
1003 
1004 			nod3 = znode;
1005 			nod3.op = OADDR;
1006 			nod3.type = nod2.type;
1007 			nod3.left = nn;
1008 
1009 			nod4 = znode;
1010 			nod4.op = OCONST;
1011 			nod4.type = nod2.type;
1012 			nod4.vconst = t->offset;
1013 
1014 			ccom(&nod0);
1015 			acom(&nod0);
1016 			xcom(&nod0);
1017 			nod0.addable = 0;
1018 
1019 			cgen(&nod0, Z);
1020 		}
1021 		break;
1022 
1023 	case OAS:
1024 		if(nn == Z) {
1025 			if(n->addable < INDEXED)
1026 				sugen(n->right, n->left, w);
1027 			break;
1028 		}
1029 		sugen(n->right, nodrat, w);
1030 		warn(n, "non-interruptable temporary");
1031 		sugen(nodrat, n->left, w);
1032 		sugen(nodrat, nn, w);
1033 		break;
1034 
1035 	case OFUNC:
1036 		if(nn == Z) {
1037 			sugen(n, nodrat, w);
1038 			break;
1039 		}
1040 		if(nn->op != OIND) {
1041 			nn = new1(OADDR, nn, Z);
1042 			nn->type = types[TIND];
1043 			nn->addable = 0;
1044 		} else
1045 			nn = nn->left;
1046 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
1047 		n->type = types[TVOID];
1048 		n->left->type = types[TVOID];
1049 		cgen(n, Z);
1050 		break;
1051 
1052 	case OCOND:
1053 		bcgen(n->left, 1);
1054 		p1 = p;
1055 		sugen(n->right->left, nn, w);
1056 		gbranch(OGOTO);
1057 		patch(p1, pc);
1058 		p1 = p;
1059 		sugen(n->right->right, nn, w);
1060 		patch(p1, pc);
1061 		break;
1062 
1063 	case OCOMMA:
1064 		cgen(n->left, Z);
1065 		sugen(n->right, nn, w);
1066 		break;
1067 	}
1068 	return;
1069 
1070 copy:
1071 	if(nn == Z)
1072 		return;
1073 	if(n->complex >= FNX && nn->complex >= FNX) {
1074 		t = nn->type;
1075 		nn->type = types[TLONG];
1076 		regialloc(&nod1, nn, Z);
1077 		lcgen(nn, &nod1);
1078 		regsalloc(&nod2, nn);
1079 		nn->type = t;
1080 
1081 		gopcode(OAS, &nod1, Z, &nod2);
1082 		regfree(&nod1);
1083 
1084 		nod2.type = typ(TIND, t);
1085 
1086 		nod1 = nod2;
1087 		nod1.op = OIND;
1088 		nod1.left = &nod2;
1089 		nod1.right = Z;
1090 		nod1.complex = 1;
1091 		nod1.type = t;
1092 
1093 		sugen(n, &nod1, w);
1094 		return;
1095 	}
1096 
1097 	if(n->complex > nn->complex) {
1098 		t = n->type;
1099 		n->type = types[TLONG];
1100 		reglcgen(&nod1, n, Z);
1101 		n->type = t;
1102 
1103 		t = nn->type;
1104 		nn->type = types[TLONG];
1105 		reglcgen(&nod2, nn, Z);
1106 		nn->type = t;
1107 	} else {
1108 		t = nn->type;
1109 		nn->type = types[TLONG];
1110 		reglcgen(&nod2, nn, Z);
1111 		nn->type = t;
1112 
1113 		t = n->type;
1114 		n->type = types[TLONG];
1115 		reglcgen(&nod1, n, Z);
1116 		n->type = t;
1117 	}
1118 
1119 	w /= SZ_LONG;
1120 	if(w <= 5) {
1121 		layout(&nod1, &nod2, w, 0, Z);
1122 		goto out;
1123 	}
1124 
1125 	/*
1126 	 * minimize space for unrolling loop
1127 	 * 3,4,5 times. (6 or more is never minimum)
1128 	 * if small structure, try 2 also.
1129 	 */
1130 	c = 0; /* set */
1131 	m = 100;
1132 	i = 3;
1133 	if(w <= 15)
1134 		i = 2;
1135 	for(; i<=5; i++)
1136 		if(i + w%i <= m) {
1137 			c = i;
1138 			m = c + w%c;
1139 		}
1140 
1141 	regalloc(&nod3, &regnode, Z);
1142 	layout(&nod1, &nod2, w%c, w/c, &nod3);
1143 
1144 	pc1 = pc;
1145 	layout(&nod1, &nod2, c, 0, Z);
1146 
1147 	gopcode(OSUB, nodconst(1), Z, &nod3);
1148 	nod1.op = OREGISTER;
1149 	nod1.type = types[TIND];
1150 	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
1151 	nod2.op = OREGISTER;
1152 	nod2.type = types[TIND];
1153 	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
1154 
1155 	gopcode(OEQ, &nod3, Z, Z);
1156 	p->as = ABGT;
1157 	patch(p, pc1);
1158 
1159 	regfree(&nod3);
1160 out:
1161 	regfree(&nod1);
1162 	regfree(&nod2);
1163 }
1164 
1165 void
1166 layout(Node *f, Node *t, int c, int cv, Node *cn)
1167 {
1168 	Node t1, t2;
1169 
1170 	while(c > 3) {
1171 		layout(f, t, 2, 0, Z);
1172 		c -= 2;
1173 	}
1174 
1175 	regalloc(&t1, &regnode, Z);
1176 	regalloc(&t2, &regnode, Z);
1177 	t1.type = types[TLONG];
1178 	t2.type = types[TLONG];
1179 	if(c > 0) {
1180 		gopcode(OAS, f, Z, &t1);
1181 		f->xoffset += SZ_LONG;
1182 	}
1183 	if(cn != Z)
1184 		gopcode(OAS, nodconst(cv), Z, cn);
1185 	if(c > 1) {
1186 		gopcode(OAS, f, Z, &t2);
1187 		f->xoffset += SZ_LONG;
1188 	}
1189 	if(c > 0) {
1190 		gopcode(OAS, &t1, Z, t);
1191 		t->xoffset += SZ_LONG;
1192 	}
1193 	if(c > 2) {
1194 		gopcode(OAS, f, Z, &t1);
1195 		f->xoffset += SZ_LONG;
1196 	}
1197 	if(c > 1) {
1198 		gopcode(OAS, &t2, Z, t);
1199 		t->xoffset += SZ_LONG;
1200 	}
1201 	if(c > 2) {
1202 		gopcode(OAS, &t1, Z, t);
1203 		t->xoffset += SZ_LONG;
1204 	}
1205 	regfree(&t1);
1206 	regfree(&t2);
1207 }
1208