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