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