xref: /inferno-os/utils/8c/cgen.c (revision 5d0c4cf3fc288434c41cba52dd998ab1d7375a7b)
1 #include "gc.h"
2 
3 /* ,x/^(print|prtree)\(/i/\/\/ */
4 
5 void
6 cgen(Node *n, Node *nn)
7 {
8 	Node *l, *r, *t;
9 	Prog *p1;
10 	Node nod, nod1, nod2, nod3, nod4;
11 	int o, hardleft;
12 	long v, curs;
13 	vlong c;
14 
15 	if(debug['g']) {
16 		prtree(nn, "cgen lhs");
17 		prtree(n, "cgen");
18 	}
19 	if(n == Z || n->type == T)
20 		return;
21 	if(typesuv[n->type->etype]) {
22 		sugen(n, nn, n->type->width);
23 		return;
24 	}
25 	l = n->left;
26 	r = n->right;
27 	o = n->op;
28 // Go's version does the following, but it's the wrong place: doesn't allow assignment
29 //	if(o == OEXREG || nn != Z && nn->op == OEXREG) {
30 //		gmove(n, nn);
31 //		return;
32 //	}
33 
34 	if(n->addable >= INDEXED) {
35 		if(nn == Z) {
36 			switch(o) {
37 			default:
38 				nullwarn(Z, Z);
39 				break;
40 			case OINDEX:
41 				nullwarn(l, r);
42 				break;
43 			}
44 			return;
45 		}
46 		gmove(n, nn);
47 		return;
48 	}
49 	curs = cursafe;
50 
51 	if(l->complex >= FNX)
52 	if(r != Z && r->complex >= FNX)
53 	switch(o) {
54 	default:
55 		if(cond(o) && typesuv[l->type->etype])
56 			break;
57 
58 		regret(&nod, r);
59 		cgen(r, &nod);
60 
61 		regsalloc(&nod1, r);
62 		gmove(&nod, &nod1);
63 
64 		regfree(&nod);
65 		nod = *n;
66 		nod.right = &nod1;
67 
68 		cgen(&nod, nn);
69 		return;
70 
71 	case OFUNC:
72 	case OCOMMA:
73 	case OANDAND:
74 	case OOROR:
75 	case OCOND:
76 	case ODOT:
77 		break;
78 	}
79 
80 	hardleft = l->addable < INDEXED || l->complex >= FNX;
81 	switch(o) {
82 	default:
83 		diag(n, "unknown op in cgen: %O", o);
84 		break;
85 
86 	case ONEG:
87 	case OCOM:
88 		if(nn == Z) {
89 			nullwarn(l, Z);
90 			break;
91 		}
92 		regalloc(&nod, l, nn);
93 		cgen(l, &nod);
94 		gopcode(o, n->type, Z, &nod);
95 		gmove(&nod, nn);
96 		regfree(&nod);
97 		break;
98 
99 	case OAS:
100 		if(typefd[n->type->etype]) {
101 			cgen(r, &fregnode0);
102 			if(nn != Z)
103 				gins(AFMOVD, &fregnode0, &fregnode0);
104 			if(l->addable < INDEXED) {
105 				reglcgen(&nod, l, Z);
106 				gmove(&fregnode0, &nod);
107 				regfree(&nod);
108 			} else
109 				gmove(&fregnode0, l);
110 			if(nn != Z)
111 				gmove(&fregnode0, nn);
112 			return;
113 		}
114 		if(l->op == OBIT)
115 			goto bitas;
116 		if(!hardleft) {
117 			if(nn != Z || r->addable < INDEXED) {
118 				if(r->complex >= FNX && nn == Z)
119 					regret(&nod, r);
120 				else
121 					regalloc(&nod, r, nn);
122 				cgen(r, &nod);
123 				gmove(&nod, l);
124 				if(nn != Z)
125 					gmove(&nod, nn);
126 				regfree(&nod);
127 			} else
128 				gmove(r, l);
129 			break;
130 		}
131 		if(l->complex >= r->complex) {
132 			if(l->op == OINDEX && r->op == OCONST) {
133 				gmove(r, l);
134 				break;
135 			}
136 			reglcgen(&nod1, l, Z);
137 			if(r->addable >= INDEXED) {
138 				gmove(r, &nod1);
139 				if(nn != Z)
140 					gmove(r, nn);
141 				regfree(&nod1);
142 				break;
143 			}
144 			regalloc(&nod, r, nn);
145 			cgen(r, &nod);
146 		} else {
147 			regalloc(&nod, r, nn);
148 			cgen(r, &nod);
149 			reglcgen(&nod1, l, Z);
150 		}
151 		gmove(&nod, &nod1);
152 		regfree(&nod);
153 		regfree(&nod1);
154 		break;
155 
156 	bitas:
157 		n = l->left;
158 		regalloc(&nod, r, nn);
159 		if(l->complex >= r->complex) {
160 			reglcgen(&nod1, n, Z);
161 			cgen(r, &nod);
162 		} else {
163 			cgen(r, &nod);
164 			reglcgen(&nod1, n, Z);
165 		}
166 		regalloc(&nod2, n, Z);
167 		gmove(&nod1, &nod2);
168 		bitstore(l, &nod, &nod1, &nod2, nn);
169 		break;
170 
171 	case OBIT:
172 		if(nn == Z) {
173 			nullwarn(l, Z);
174 			break;
175 		}
176 		bitload(n, &nod, Z, Z, nn);
177 		gmove(&nod, nn);
178 		regfree(&nod);
179 		break;
180 
181 	case OLSHR:
182 	case OASHL:
183 	case OASHR:
184 		if(nn == Z) {
185 			nullwarn(l, r);
186 			break;
187 		}
188 		if(r->op == OCONST) {
189 			if(r->vconst == 0) {
190 				cgen(l, nn);
191 				break;
192 			}
193 			regalloc(&nod, l, nn);
194 			cgen(l, &nod);
195 			if(o == OASHL && r->vconst == 1)
196 				gopcode(OADD, n->type, &nod, &nod);
197 			else
198 				gopcode(o, n->type, r, &nod);
199 			gmove(&nod, nn);
200 			regfree(&nod);
201 			break;
202 		}
203 
204 		/*
205 		 * get nod to be D_CX
206 		 */
207 		if(nodreg(&nod, nn, D_CX)) {
208 			regsalloc(&nod1, n);
209 			gmove(&nod, &nod1);
210 			cgen(n, &nod);		/* probably a bug */
211 			gmove(&nod, nn);
212 			gmove(&nod1, &nod);
213 			break;
214 		}
215 		reg[D_CX]++;
216 		if(nn->op == OREGISTER && nn->reg == D_CX)
217 			regalloc(&nod1, l, Z);
218 		else
219 			regalloc(&nod1, l, nn);
220 		if(r->complex >= l->complex) {
221 			cgen(r, &nod);
222 			cgen(l, &nod1);
223 		} else {
224 			cgen(l, &nod1);
225 			cgen(r, &nod);
226 		}
227 		gopcode(o, n->type, &nod, &nod1);
228 		gmove(&nod1, nn);
229 		regfree(&nod);
230 		regfree(&nod1);
231 		break;
232 
233 	case OADD:
234 	case OSUB:
235 	case OOR:
236 	case OXOR:
237 	case OAND:
238 		if(nn == Z) {
239 			nullwarn(l, r);
240 			break;
241 		}
242 		if(typefd[n->type->etype])
243 			goto fop;
244 		if(r->op == OCONST) {
245 			if(r->vconst == 0 && o != OAND) {
246 				cgen(l, nn);
247 				break;
248 			}
249 		}
250 		if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
251 		&& (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
252 			c = l->right->vconst;
253 			if(c > 0 && c <= 3 && nareg(1) >= 4) {
254 				if(l->left->complex >= r->complex) {
255 					regalloc(&nod, l->left, nn);
256 					cgen(l->left, &nod);
257 					if(r->addable < INDEXED) {
258 						regalloc(&nod1, r, Z);
259 						cgen(r, &nod1);
260 						genmuladd(&nod, &nod, 1 << c, &nod1);
261 						regfree(&nod1);
262 					}
263 					else
264 						genmuladd(&nod, &nod, 1 << c, r);
265 				}
266 				else {
267 					regalloc(&nod, r, nn);
268 					cgen(r, &nod);
269 					regalloc(&nod1, l->left, Z);
270 					cgen(l->left, &nod1);
271 					genmuladd(&nod, &nod1, 1 << c, &nod);
272 					regfree(&nod1);
273 				}
274 				gmove(&nod, nn);
275 				regfree(&nod);
276 				break;
277 			}
278 		}
279 		if(r->addable >= INDEXED) {
280 			regalloc(&nod, l, nn);
281 			cgen(l, &nod);
282 			gopcode(o, n->type, r, &nod);
283 			gmove(&nod, nn);
284 			regfree(&nod);
285 			break;
286 		}
287 		if(l->complex >= r->complex) {
288 			regalloc(&nod, l, nn);
289 			cgen(l, &nod);
290 			regalloc(&nod1, r, Z);
291 			cgen(r, &nod1);
292 			gopcode(o, n->type, &nod1, &nod);
293 		} else {
294 			regalloc(&nod1, r, nn);
295 			cgen(r, &nod1);
296 			regalloc(&nod, l, Z);
297 			cgen(l, &nod);
298 			gopcode(o, n->type, &nod1, &nod);
299 		}
300 		gmove(&nod, nn);
301 		regfree(&nod);
302 		regfree(&nod1);
303 		break;
304 
305 	case OLMOD:
306 	case OMOD:
307 	case OLMUL:
308 	case OLDIV:
309 	case OMUL:
310 	case ODIV:
311 		if(nn == Z) {
312 			nullwarn(l, r);
313 			break;
314 		}
315 		if(typefd[n->type->etype])
316 			goto fop;
317 		if(r->op == OCONST) {
318 			v = 0;
319 			switch(o) {
320 			case ODIV:
321 			case OMOD:
322 				c = r->vconst;
323 				if(c < 0)
324 					c = -c;
325 				v = log2(c);
326 				if(v < 0)
327 					break;
328 				/* fall thru */
329 			case OMUL:
330 			case OLMUL:
331 				regalloc(&nod, l, nn);
332 				cgen(l, &nod);
333 				switch(o) {
334 				case OMUL:
335 				case OLMUL:
336 					mulgen(n->type, r, &nod);
337 					break;
338 				case ODIV:
339 					sdiv2(r->vconst, v, l, &nod);
340 					break;
341 				case OMOD:
342 					smod2(r->vconst, v, l, &nod);
343 					break;
344 				}
345 				gmove(&nod, nn);
346 				regfree(&nod);
347 				goto done;
348 			case OLDIV:
349 				c = r->vconst;
350 				if((c & 0x80000000) == 0)
351 					break;
352 				regalloc(&nod1, l, Z);
353 				cgen(l, &nod1);
354 				regalloc(&nod, l, nn);
355 				zeroregm(&nod);
356 				gins(ACMPL, &nod1, nodconst(c));
357 				gins(ASBBL, nodconst(-1), &nod);
358 				regfree(&nod1);
359 				gmove(&nod, nn);
360 				regfree(&nod);
361 				goto done;
362 			}
363 		}
364 
365 		if(o == OMUL) {
366 			if(l->addable >= INDEXED) {
367 				t = l;
368 				l = r;
369 				r = t;
370 				goto imula;
371 			}
372 			else if(r->addable >= INDEXED) {
373 			imula:
374 /* should favour AX */
375 				regalloc(&nod, l, nn);
376 				cgen(l, &nod);
377 				gopcode(OMUL, n->type, r, &nod);
378 			}
379 			else {
380 /* should favour AX */
381 				regalloc(&nod, l, nn);
382 				cgen(l, &nod);
383 				regalloc(&nod1, r, Z);
384 				cgen(r, &nod1);
385 				gopcode(OMUL, n->type, &nod1, &nod);
386 				regfree(&nod1);
387 			}
388 			gmove(&nod, nn);
389 			regfree(&nod);
390 			goto done;
391 		}
392 
393 		/*
394 		 * get nod to be D_AX
395 		 * get nod1 to be D_DX
396 		 */
397 		if(nodreg(&nod, nn, D_AX)) {
398 			regsalloc(&nod2, n);
399 			gmove(&nod, &nod2);
400 			v = reg[D_AX];
401 			reg[D_AX] = 0;
402 
403 			if(isreg(l, D_AX)) {
404 				nod3 = *n;
405 				nod3.left = &nod2;
406 				cgen(&nod3, nn);
407 			} else
408 			if(isreg(r, D_AX)) {
409 				nod3 = *n;
410 				nod3.right = &nod2;
411 				cgen(&nod3, nn);
412 			} else
413 				cgen(n, nn);
414 
415 			gmove(&nod2, &nod);
416 			reg[D_AX] = v;
417 			break;
418 		}
419 		if(nodreg(&nod1, nn, D_DX)) {
420 			regsalloc(&nod2, n);
421 			gmove(&nod1, &nod2);
422 			v = reg[D_DX];
423 			reg[D_DX] = 0;
424 
425 			if(isreg(l, D_DX)) {
426 				nod3 = *n;
427 				nod3.left = &nod2;
428 				cgen(&nod3, nn);
429 			} else
430 			if(isreg(r, D_DX)) {
431 				nod3 = *n;
432 				nod3.right = &nod2;
433 				cgen(&nod3, nn);
434 			} else
435 				cgen(n, nn);
436 
437 			gmove(&nod2, &nod1);
438 			reg[D_DX] = v;
439 			break;
440 		}
441 		reg[D_AX]++;
442 
443 		if(r->op == OCONST) {
444 			switch(o) {
445 			case ODIV:
446 				reg[D_DX]++;
447 				if(l->addable < INDEXED) {
448 					regalloc(&nod2, l, Z);
449 					cgen(l, &nod2);
450 					l = &nod2;
451 				}
452 				sdivgen(l, r, &nod, &nod1);
453 				gmove(&nod1, nn);
454 				if(l == &nod2)
455 					regfree(l);
456 				goto freeaxdx;
457 			case OLDIV:
458 				reg[D_DX]++;
459 				if(l->addable < INDEXED) {
460 					regalloc(&nod2, l, Z);
461 					cgen(l, &nod2);
462 					l = &nod2;
463 				}
464 				udivgen(l, r, &nod, &nod1);
465 				gmove(&nod1, nn);
466 				if(l == &nod2)
467 					regfree(l);
468 				goto freeaxdx;
469 			}
470 		}
471 
472 		if(l->complex >= r->complex) {
473 			cgen(l, &nod);
474 			reg[D_DX]++;
475 			if(o == ODIV || o == OMOD)
476 				gins(ACDQ, Z, Z);
477 			if(o == OLDIV || o == OLMOD)
478 				zeroregm(&nod1);
479 			if(r->addable < INDEXED || r->op == OCONST) {
480 				regsalloc(&nod3, r);
481 				cgen(r, &nod3);
482 				gopcode(o, n->type, &nod3, Z);
483 			} else
484 				gopcode(o, n->type, r, Z);
485 		} else {
486 			regsalloc(&nod3, r);
487 			cgen(r, &nod3);
488 			cgen(l, &nod);
489 			reg[D_DX]++;
490 			if(o == ODIV || o == OMOD)
491 				gins(ACDQ, Z, Z);
492 			if(o == OLDIV || o == OLMOD)
493 				zeroregm(&nod1);
494 			gopcode(o, n->type, &nod3, Z);
495 		}
496 		if(o == OMOD || o == OLMOD)
497 			gmove(&nod1, nn);
498 		else
499 			gmove(&nod, nn);
500 	freeaxdx:
501 		regfree(&nod);
502 		regfree(&nod1);
503 		break;
504 
505 	case OASLSHR:
506 	case OASASHL:
507 	case OASASHR:
508 		if(r->op == OCONST)
509 			goto asand;
510 		if(l->op == OBIT)
511 			goto asbitop;
512 		if(typefd[n->type->etype])
513 			goto asfop;
514 
515 		/*
516 		 * get nod to be D_CX
517 		 */
518 		if(nodreg(&nod, nn, D_CX)) {
519 			regsalloc(&nod1, n);
520 			gmove(&nod, &nod1);
521 			cgen(n, &nod);
522 			if(nn != Z)
523 				gmove(&nod, nn);
524 			gmove(&nod1, &nod);
525 			break;
526 		}
527 		reg[D_CX]++;
528 
529 		if(r->complex >= l->complex) {
530 			cgen(r, &nod);
531 			if(hardleft)
532 				reglcgen(&nod1, l, Z);
533 			else
534 				nod1 = *l;
535 		} else {
536 			if(hardleft)
537 				reglcgen(&nod1, l, Z);
538 			else
539 				nod1 = *l;
540 			cgen(r, &nod);
541 		}
542 
543 		gopcode(o, l->type, &nod, &nod1);
544 		regfree(&nod);
545 		if(nn != Z)
546 			gmove(&nod1, nn);
547 		if(hardleft)
548 			regfree(&nod1);
549 		break;
550 
551 	case OASAND:
552 	case OASADD:
553 	case OASSUB:
554 	case OASXOR:
555 	case OASOR:
556 	asand:
557 		if(l->op == OBIT)
558 			goto asbitop;
559 		if(typefd[n->type->etype]||typefd[r->type->etype])
560 			goto asfop;
561 		if(l->complex >= r->complex) {
562 			if(hardleft)
563 				reglcgen(&nod, l, Z);
564 			else
565 				nod = *l;
566 			if(r->op != OCONST) {
567 				regalloc(&nod1, r, nn);
568 				cgen(r, &nod1);
569 				gopcode(o, l->type, &nod1, &nod);
570 				regfree(&nod1);
571 			} else
572 				gopcode(o, l->type, r, &nod);
573 		} else {
574 			regalloc(&nod1, r, nn);
575 			cgen(r, &nod1);
576 			if(hardleft)
577 				reglcgen(&nod, l, Z);
578 			else
579 				nod = *l;
580 			gopcode(o, l->type, &nod1, &nod);
581 			regfree(&nod1);
582 		}
583 		if(nn != Z)
584 			gmove(&nod, nn);
585 		if(hardleft)
586 			regfree(&nod);
587 		break;
588 
589 	case OASLMUL:
590 	case OASLDIV:
591 	case OASLMOD:
592 	case OASMUL:
593 	case OASDIV:
594 	case OASMOD:
595 		if(l->op == OBIT)
596 			goto asbitop;
597 		if(typefd[n->type->etype]||typefd[r->type->etype])
598 			goto asfop;
599 		if(r->op == OCONST) {
600 			v = 0;
601 			switch(o) {
602 			case OASDIV:
603 			case OASMOD:
604 				c = r->vconst;
605 				if(c < 0)
606 					c = -c;
607 				v = log2(c);
608 				if(v < 0)
609 					break;
610 				/* fall thru */
611 			case OASMUL:
612 			case OASLMUL:
613 				if(hardleft)
614 					reglcgen(&nod2, l, Z);
615 				else
616 					nod2 = *l;
617 				regalloc(&nod, l, nn);
618 				cgen(&nod2, &nod);
619 				switch(o) {
620 				case OASMUL:
621 				case OASLMUL:
622 					mulgen(n->type, r, &nod);
623 					break;
624 				case OASDIV:
625 					sdiv2(r->vconst, v, l, &nod);
626 					break;
627 				case OASMOD:
628 					smod2(r->vconst, v, l, &nod);
629 					break;
630 				}
631 			havev:
632 				gmove(&nod, &nod2);
633 				if(nn != Z)
634 					gmove(&nod, nn);
635 				if(hardleft)
636 					regfree(&nod2);
637 				regfree(&nod);
638 				goto done;
639 			case OASLDIV:
640 				c = r->vconst;
641 				if((c & 0x80000000) == 0)
642 					break;
643 				if(hardleft)
644 					reglcgen(&nod2, l, Z);
645 				else
646 					nod2 = *l;
647 				regalloc(&nod1, l, nn);
648 				cgen(&nod2, &nod1);
649 				regalloc(&nod, l, nn);
650 				zeroregm(&nod);
651 				gins(ACMPL, &nod1, nodconst(c));
652 				gins(ASBBL, nodconst(-1), &nod);
653 				regfree(&nod1);
654 				goto havev;
655 			}
656 		}
657 
658 		if(o == OASMUL) {
659 /* should favour AX */
660 			regalloc(&nod, l, nn);
661 			if(r->complex >= FNX) {
662 				regalloc(&nod1, r, Z);
663 				cgen(r, &nod1);
664 				r = &nod1;
665 			}
666 			if(hardleft)
667 				reglcgen(&nod2, l, Z);
668 			else
669 				nod2 = *l;
670 			cgen(&nod2, &nod);
671 			if(r->addable < INDEXED) {
672 				if(r->complex < FNX) {
673 					regalloc(&nod1, r, Z);
674 					cgen(r, &nod1);
675 				}
676 				gopcode(OASMUL, n->type, &nod1, &nod);
677 				regfree(&nod1);
678 			}
679 			else
680 				gopcode(OASMUL, n->type, r, &nod);
681 			if(r == &nod1)
682 				regfree(r);
683 			gmove(&nod, &nod2);
684 			if(nn != Z)
685 				gmove(&nod, nn);
686 			regfree(&nod);
687 			if(hardleft)
688 				regfree(&nod2);
689 			goto done;
690 		}
691 
692 		/*
693 		 * get nod to be D_AX
694 		 * get nod1 to be D_DX
695 		 */
696 		if(nodreg(&nod, nn, D_AX)) {
697 			regsalloc(&nod2, n);
698 			gmove(&nod, &nod2);
699 			v = reg[D_AX];
700 			reg[D_AX] = 0;
701 
702 			if(isreg(l, D_AX)) {
703 				nod3 = *n;
704 				nod3.left = &nod2;
705 				cgen(&nod3, nn);
706 			} else
707 			if(isreg(r, D_AX)) {
708 				nod3 = *n;
709 				nod3.right = &nod2;
710 				cgen(&nod3, nn);
711 			} else
712 				cgen(n, nn);
713 
714 			gmove(&nod2, &nod);
715 			reg[D_AX] = v;
716 			break;
717 		}
718 		if(nodreg(&nod1, nn, D_DX)) {
719 			regsalloc(&nod2, n);
720 			gmove(&nod1, &nod2);
721 			v = reg[D_DX];
722 			reg[D_DX] = 0;
723 
724 			if(isreg(l, D_DX)) {
725 				nod3 = *n;
726 				nod3.left = &nod2;
727 				cgen(&nod3, nn);
728 			} else
729 			if(isreg(r, D_DX)) {
730 				nod3 = *n;
731 				nod3.right = &nod2;
732 				cgen(&nod3, nn);
733 			} else
734 				cgen(n, nn);
735 
736 			gmove(&nod2, &nod1);
737 			reg[D_DX] = v;
738 			break;
739 		}
740 		reg[D_AX]++;
741 		reg[D_DX]++;
742 
743 		if(l->complex >= r->complex) {
744 			if(hardleft)
745 				reglcgen(&nod2, l, Z);
746 			else
747 				nod2 = *l;
748 			cgen(&nod2, &nod);
749 			if(r->op == OCONST) {
750 				switch(o) {
751 				case OASDIV:
752 					sdivgen(&nod2, r, &nod, &nod1);
753 					goto divdone;
754 				case OASLDIV:
755 					udivgen(&nod2, r, &nod, &nod1);
756 				divdone:
757 					gmove(&nod1, &nod2);
758 					if(nn != Z)
759 						gmove(&nod1, nn);
760 					goto freelxaxdx;
761 				}
762 			}
763 			if(o == OASDIV || o == OASMOD)
764 				gins(ACDQ, Z, Z);
765 			if(o == OASLDIV || o == OASLMOD)
766 				zeroregm(&nod1);
767 			if(r->addable < INDEXED || r->op == OCONST ||
768 			   !typeil[r->type->etype]) {
769 				regalloc(&nod3, r, Z);
770 				cgen(r, &nod3);
771 				gopcode(o, l->type, &nod3, Z);
772 				regfree(&nod3);
773 			} else
774 				gopcode(o, n->type, r, Z);
775 		} else {
776 			regalloc(&nod3, r, Z);
777 			cgen(r, &nod3);
778 			if(hardleft)
779 				reglcgen(&nod2, l, Z);
780 			else
781 				nod2 = *l;
782 			cgen(&nod2, &nod);
783 			if(o == OASDIV || o == OASMOD)
784 				gins(ACDQ, Z, Z);
785 			if(o == OASLDIV || o == OASLMOD)
786 				zeroregm(&nod1);
787 			gopcode(o, l->type, &nod3, Z);
788 			regfree(&nod3);
789 		}
790 		if(o == OASMOD || o == OASLMOD) {
791 			gmove(&nod1, &nod2);
792 			if(nn != Z)
793 				gmove(&nod1, nn);
794 		} else {
795 			gmove(&nod, &nod2);
796 			if(nn != Z)
797 				gmove(&nod, nn);
798 		}
799 	freelxaxdx:
800 		if(hardleft)
801 			regfree(&nod2);
802 		regfree(&nod);
803 		regfree(&nod1);
804 		break;
805 
806 	fop:
807 		if(l->complex >= r->complex) {
808 			cgen(l, &fregnode0);
809 			if(r->addable < INDEXED) {
810 				cgen(r, &fregnode0);
811 				fgopcode(o, &fregnode0, &fregnode1, 1, 0);
812 			} else
813 				fgopcode(o, r, &fregnode0, 0, 0);
814 		} else {
815 			cgen(r, &fregnode0);
816 			if(l->addable < INDEXED) {
817 				cgen(l, &fregnode0);
818 				fgopcode(o, &fregnode0, &fregnode1, 1, 1);
819 			} else
820 				fgopcode(o, l, &fregnode0, 0, 1);
821 		}
822 		gmove(&fregnode0, nn);
823 		break;
824 
825 	asfop:
826 		if(l->complex >= r->complex) {
827 			if(hardleft)
828 				reglcgen(&nod, l, Z);
829 			else
830 				nod = *l;
831 			cgen(r, &fregnode0);
832 		} else {
833 			cgen(r, &fregnode0);
834 			if(hardleft)
835 				reglcgen(&nod, l, Z);
836 			else
837 				nod = *l;
838 		}
839 		if(!typefd[l->type->etype]) {
840 			gmove(&nod, &fregnode0);
841 			fgopcode(o, &fregnode0, &fregnode1, 1, 1);
842 		} else
843 			fgopcode(o, &nod, &fregnode0, 0, 1);
844 		if(nn != Z)
845 			gins(AFMOVD, &fregnode0, &fregnode0);
846 		gmove(&fregnode0, &nod);
847 		if(nn != Z)
848 			gmove(&fregnode0, nn);
849 		if(hardleft)
850 			regfree(&nod);
851 		break;
852 
853 	asbitop:
854 		regalloc(&nod4, n, nn);
855 		if(l->complex >= r->complex) {
856 			bitload(l, &nod, &nod1, &nod2, &nod4);
857 			regalloc(&nod3, r, Z);
858 			cgen(r, &nod3);
859 		} else {
860 			regalloc(&nod3, r, Z);
861 			cgen(r, &nod3);
862 			bitload(l, &nod, &nod1, &nod2, &nod4);
863 		}
864 		gmove(&nod, &nod4);
865 
866 		if(typefd[nod3.type->etype])
867 			fgopcode(o, &fregnode0, &fregnode1, 1, 1);
868 		else {
869 			Node onod;
870 
871 			/* incredible grot ... */
872 			onod = nod3;
873 			onod.op = o;
874 			onod.complex = 2;
875 			onod.addable = 0;
876 			onod.type = tfield;
877 			onod.left = &nod4;
878 			onod.right = &nod3;
879 			cgen(&onod, Z);
880 		}
881 		regfree(&nod3);
882 		gmove(&nod4, &nod);
883 		regfree(&nod4);
884 		bitstore(l, &nod, &nod1, &nod2, nn);
885 		break;
886 
887 	case OADDR:
888 		if(nn == Z) {
889 			nullwarn(l, Z);
890 			break;
891 		}
892 		lcgen(l, nn);
893 		break;
894 
895 	case OFUNC:
896 		l = uncomma(l);
897 		if(l->complex >= FNX) {
898 			if(l->op != OIND)
899 				diag(n, "bad function call");
900 
901 			regret(&nod, l->left);
902 			cgen(l->left, &nod);
903 			regsalloc(&nod1, l->left);
904 			gmove(&nod, &nod1);
905 			regfree(&nod);
906 
907 			nod = *n;
908 			nod.left = &nod2;
909 			nod2 = *l;
910 			nod2.left = &nod1;
911 			nod2.complex = 1;
912 			cgen(&nod, nn);
913 
914 			return;
915 		}
916 		gargs(r, &nod, &nod1);
917 		if(l->addable < INDEXED) {
918 			reglcgen(&nod, l, nn);
919 			nod.op = OREGISTER;
920 			gopcode(OFUNC, n->type, Z, &nod);
921 			regfree(&nod);
922 		} else
923 			gopcode(OFUNC, n->type, Z, l);
924 		if(REGARG>=0 && reg[REGARG])
925 			reg[REGARG]--;
926 		if(nn != Z) {
927 			regret(&nod, n);
928 			gmove(&nod, nn);
929 			regfree(&nod);
930 		} else
931 		if(typefd[n->type->etype])
932 			gins(AFMOVDP, &fregnode0, &fregnode0);
933 		break;
934 
935 	case OIND:
936 		if(nn == Z) {
937 			nullwarn(l, Z);
938 			break;
939 		}
940 		regialloc(&nod, n, nn);
941 		r = l;
942 		while(r->op == OADD)
943 			r = r->right;
944 		if(sconst(r)) {
945 			v = r->vconst;
946 			r->vconst = 0;
947 			cgen(l, &nod);
948 			nod.xoffset += v;
949 			r->vconst = v;
950 		} else
951 			cgen(l, &nod);
952 		regind(&nod, n);
953 		gmove(&nod, nn);
954 		regfree(&nod);
955 		break;
956 
957 	case OEQ:
958 	case ONE:
959 	case OLE:
960 	case OLT:
961 	case OGE:
962 	case OGT:
963 	case OLO:
964 	case OLS:
965 	case OHI:
966 	case OHS:
967 		if(nn == Z) {
968 			nullwarn(l, r);
969 			break;
970 		}
971 		boolgen(n, 1, nn);
972 		break;
973 
974 	case OANDAND:
975 	case OOROR:
976 		boolgen(n, 1, nn);
977 		if(nn == Z)
978 			patch(p, pc);
979 		break;
980 
981 	case ONOT:
982 		if(nn == Z) {
983 			nullwarn(l, Z);
984 			break;
985 		}
986 		boolgen(n, 1, nn);
987 		break;
988 
989 	case OCOMMA:
990 		cgen(l, Z);
991 		cgen(r, nn);
992 		break;
993 
994 	case OCAST:
995 		if(nn == Z) {
996 			nullwarn(l, Z);
997 			break;
998 		}
999 		/*
1000 		 * convert from types l->n->nn
1001 		 */
1002 		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
1003 			/* both null, gen l->nn */
1004 			cgen(l, nn);
1005 			break;
1006 		}
1007 		if(typev[l->type->etype]) {
1008 			cgen64(n, nn);
1009 			break;
1010 		}
1011 		regalloc(&nod, l, nn);
1012 		cgen(l, &nod);
1013 		regalloc(&nod1, n, &nod);
1014 		gmove(&nod, &nod1);
1015 		gmove(&nod1, nn);
1016 		regfree(&nod1);
1017 		regfree(&nod);
1018 		break;
1019 
1020 	case ODOT:
1021 		sugen(l, nodrat, l->type->width);
1022 		if(nn == Z)
1023 			break;
1024 		warn(n, "non-interruptable temporary");
1025 		nod = *nodrat;
1026 		if(!r || r->op != OCONST) {
1027 			diag(n, "DOT and no offset");
1028 			break;
1029 		}
1030 		nod.xoffset += (long)r->vconst;
1031 		nod.type = n->type;
1032 		cgen(&nod, nn);
1033 		break;
1034 
1035 	case OCOND:
1036 		bcgen(l, 1);
1037 		p1 = p;
1038 		cgen(r->left, nn);
1039 		gbranch(OGOTO);
1040 		patch(p1, pc);
1041 		p1 = p;
1042 		cgen(r->right, nn);
1043 		patch(p1, pc);
1044 		break;
1045 
1046 	case OPOSTINC:
1047 	case OPOSTDEC:
1048 		v = 1;
1049 		if(l->type->etype == TIND)
1050 			v = l->type->link->width;
1051 		if(o == OPOSTDEC)
1052 			v = -v;
1053 		if(l->op == OBIT)
1054 			goto bitinc;
1055 		if(nn == Z)
1056 			goto pre;
1057 
1058 		if(hardleft)
1059 			reglcgen(&nod, l, Z);
1060 		else
1061 			nod = *l;
1062 
1063 		if(typefd[n->type->etype])
1064 			goto fltinc;
1065 		gmove(&nod, nn);
1066 		gopcode(OADD, n->type, nodconst(v), &nod);
1067 		if(hardleft)
1068 			regfree(&nod);
1069 		break;
1070 
1071 	case OPREINC:
1072 	case OPREDEC:
1073 		v = 1;
1074 		if(l->type->etype == TIND)
1075 			v = l->type->link->width;
1076 		if(o == OPREDEC)
1077 			v = -v;
1078 		if(l->op == OBIT)
1079 			goto bitinc;
1080 
1081 	pre:
1082 		if(hardleft)
1083 			reglcgen(&nod, l, Z);
1084 		else
1085 			nod = *l;
1086 		if(typefd[n->type->etype])
1087 			goto fltinc;
1088 		gopcode(OADD, n->type, nodconst(v), &nod);
1089 		if(nn != Z)
1090 			gmove(&nod, nn);
1091 		if(hardleft)
1092 			regfree(&nod);
1093 		break;
1094 
1095 	fltinc:
1096 		gmove(&nod, &fregnode0);
1097 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC))
1098 			gins(AFMOVD, &fregnode0, &fregnode0);
1099 		gins(AFLD1, Z, Z);
1100 		if(v < 0)
1101 			fgopcode(OSUB, &fregnode0, &fregnode1, 1, 0);
1102 		else
1103 			fgopcode(OADD, &fregnode0, &fregnode1, 1, 0);
1104 		if(nn != Z && (o == OPREINC || o == OPREDEC))
1105 			gins(AFMOVD, &fregnode0, &fregnode0);
1106 		gmove(&fregnode0, &nod);
1107 		if(hardleft)
1108 			regfree(&nod);
1109 		break;
1110 
1111 	bitinc:
1112 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
1113 			bitload(l, &nod, &nod1, &nod2, Z);
1114 			gmove(&nod, nn);
1115 			gopcode(OADD, tfield, nodconst(v), &nod);
1116 			bitstore(l, &nod, &nod1, &nod2, Z);
1117 			break;
1118 		}
1119 		bitload(l, &nod, &nod1, &nod2, nn);
1120 		gopcode(OADD, tfield, nodconst(v), &nod);
1121 		bitstore(l, &nod, &nod1, &nod2, nn);
1122 		break;
1123 	}
1124 done:
1125 	cursafe = curs;
1126 }
1127 
1128 void
1129 reglcgen(Node *t, Node *n, Node *nn)
1130 {
1131 	Node *r;
1132 	long v;
1133 
1134 	regialloc(t, n, nn);
1135 	if(n->op == OIND) {
1136 		r = n->left;
1137 		while(r->op == OADD)
1138 			r = r->right;
1139 		if(sconst(r)) {
1140 			v = r->vconst;
1141 			r->vconst = 0;
1142 			lcgen(n, t);
1143 			t->xoffset += v;
1144 			r->vconst = v;
1145 			regind(t, n);
1146 			return;
1147 		}
1148 	}
1149 	lcgen(n, t);
1150 	regind(t, n);
1151 }
1152 
1153 void
1154 lcgen(Node *n, Node *nn)
1155 {
1156 	Prog *p1;
1157 	Node nod;
1158 
1159 	if(debug['g']) {
1160 		prtree(nn, "lcgen lhs");
1161 		prtree(n, "lcgen");
1162 	}
1163 	if(n == Z || n->type == T)
1164 		return;
1165 	if(nn == Z) {
1166 		nn = &nod;
1167 		regalloc(&nod, n, Z);
1168 	}
1169 	switch(n->op) {
1170 	default:
1171 		if(n->addable < INDEXED) {
1172 			diag(n, "unknown op in lcgen: %O", n->op);
1173 			break;
1174 		}
1175 		gopcode(OADDR, n->type, n, nn);
1176 		break;
1177 
1178 	case OCOMMA:
1179 		cgen(n->left, n->left);
1180 		lcgen(n->right, nn);
1181 		break;
1182 
1183 	case OIND:
1184 		cgen(n->left, nn);
1185 		break;
1186 
1187 	case OCOND:
1188 		bcgen(n->left, 1);
1189 		p1 = p;
1190 		lcgen(n->right->left, nn);
1191 		gbranch(OGOTO);
1192 		patch(p1, pc);
1193 		p1 = p;
1194 		lcgen(n->right->right, nn);
1195 		patch(p1, pc);
1196 		break;
1197 	}
1198 }
1199 
1200 void
1201 bcgen(Node *n, int true)
1202 {
1203 
1204 	if(n->type == T)
1205 		gbranch(OGOTO);
1206 	else
1207 		boolgen(n, true, Z);
1208 }
1209 
1210 void
1211 boolgen(Node *n, int true, Node *nn)
1212 {
1213 	int o;
1214 	Prog *p1, *p2;
1215 	Node *l, *r, nod, nod1;
1216 	long curs;
1217 
1218 	if(debug['g']) {
1219 		prtree(nn, "boolgen lhs");
1220 		prtree(n, "boolgen");
1221 	}
1222 	curs = cursafe;
1223 	l = n->left;
1224 	r = n->right;
1225 	switch(n->op) {
1226 
1227 	default:
1228 		if(typev[n->type->etype]) {
1229 			testv(n, true);
1230 			goto com;
1231 		}
1232 		o = ONE;
1233 		if(true)
1234 			o = OEQ;
1235 		if(typefd[n->type->etype]) {
1236 			if(n->addable < INDEXED) {
1237 				cgen(n, &fregnode0);
1238 				gins(AFLDZ, Z, Z);
1239 				fgopcode(o, &fregnode0, &fregnode1, 1, 1);
1240 			} else {
1241 				gins(AFLDZ, Z, Z);
1242 				fgopcode(o, n, &fregnode0, 0, 1);
1243 			}
1244 			goto com;
1245 		}
1246 		/* bad, 13 is address of external that becomes constant */
1247 		if(n->addable >= INDEXED && n->addable != 13) {
1248 			gopcode(o, n->type, n, nodconst(0));
1249 			goto com;
1250 		}
1251 		regalloc(&nod, n, nn);
1252 		cgen(n, &nod);
1253 		gopcode(o, n->type, &nod, nodconst(0));
1254 		regfree(&nod);
1255 		goto com;
1256 
1257 	case OCONST:
1258 		o = vconst(n);
1259 		if(!true)
1260 			o = !o;
1261 		gbranch(OGOTO);
1262 		if(o) {
1263 			p1 = p;
1264 			gbranch(OGOTO);
1265 			patch(p1, pc);
1266 		}
1267 		goto com;
1268 
1269 	case OCOMMA:
1270 		cgen(l, Z);
1271 		boolgen(r, true, nn);
1272 		break;
1273 
1274 	case ONOT:
1275 		boolgen(l, !true, nn);
1276 		break;
1277 
1278 	case OCOND:
1279 		bcgen(l, 1);
1280 		p1 = p;
1281 		bcgen(r->left, true);
1282 		p2 = p;
1283 		gbranch(OGOTO);
1284 		patch(p1, pc);
1285 		p1 = p;
1286 		bcgen(r->right, !true);
1287 		patch(p2, pc);
1288 		p2 = p;
1289 		gbranch(OGOTO);
1290 		patch(p1, pc);
1291 		patch(p2, pc);
1292 		goto com;
1293 
1294 	case OANDAND:
1295 		if(!true)
1296 			goto caseor;
1297 
1298 	caseand:
1299 		bcgen(l, true);
1300 		p1 = p;
1301 		bcgen(r, !true);
1302 		p2 = p;
1303 		patch(p1, pc);
1304 		gbranch(OGOTO);
1305 		patch(p2, pc);
1306 		goto com;
1307 
1308 	case OOROR:
1309 		if(!true)
1310 			goto caseand;
1311 
1312 	caseor:
1313 		bcgen(l, !true);
1314 		p1 = p;
1315 		bcgen(r, !true);
1316 		p2 = p;
1317 		gbranch(OGOTO);
1318 		patch(p1, pc);
1319 		patch(p2, pc);
1320 		goto com;
1321 
1322 	case OEQ:
1323 	case ONE:
1324 	case OLE:
1325 	case OLT:
1326 	case OGE:
1327 	case OGT:
1328 	case OHI:
1329 	case OHS:
1330 	case OLO:
1331 	case OLS:
1332 		o = n->op;
1333 		if(typev[l->type->etype]) {
1334 			if(!true)
1335 				n->op = comrel[relindex(o)];
1336 			cgen64(n, Z);
1337 			goto com;
1338 		}
1339 		if(true)
1340 			o = comrel[relindex(o)];
1341 		if(l->complex >= FNX && r->complex >= FNX) {
1342 			regret(&nod, r);
1343 			cgen(r, &nod);
1344 			regsalloc(&nod1, r);
1345 			gmove(&nod, &nod1);
1346 			regfree(&nod);
1347 			nod = *n;
1348 			nod.right = &nod1;
1349 			boolgen(&nod, true, nn);
1350 			break;
1351 		}
1352 		if(typefd[l->type->etype]) {
1353 			if(l->complex >= r->complex) {
1354 				cgen(l, &fregnode0);
1355 				if(r->addable < INDEXED) {
1356 					cgen(r, &fregnode0);
1357 					o = invrel[relindex(o)];
1358 					fgopcode(o, &fregnode0, &fregnode1, 1, 1);
1359 				} else
1360 					fgopcode(o, r, &fregnode0, 0, 1);
1361 			} else {
1362 				o = invrel[relindex(o)];
1363 				cgen(r, &fregnode0);
1364 				if(l->addable < INDEXED) {
1365 					cgen(l, &fregnode0);
1366 					o = invrel[relindex(o)];
1367 					fgopcode(o, &fregnode0, &fregnode1, 1, 1);
1368 				} else
1369 					fgopcode(o, l, &fregnode0, 0, 1);
1370 			}
1371 			goto com;
1372 		}
1373 		if(l->op == OCONST) {
1374 			o = invrel[relindex(o)];
1375 			/* bad, 13 is address of external that becomes constant */
1376 			if(r->addable < INDEXED || r->addable == 13) {
1377 				regalloc(&nod, r, nn);
1378 				cgen(r, &nod);
1379 				gopcode(o, l->type, &nod, l);
1380 				regfree(&nod);
1381 			} else
1382 				gopcode(o, l->type, r, l);
1383 			goto com;
1384 		}
1385 		if(l->complex >= r->complex) {
1386 			regalloc(&nod, l, nn);
1387 			cgen(l, &nod);
1388 			if(r->addable < INDEXED) {
1389 				regalloc(&nod1, r, Z);
1390 				cgen(r, &nod1);
1391 				gopcode(o, l->type, &nod, &nod1);
1392 				regfree(&nod1);
1393 			} else
1394 				gopcode(o, l->type, &nod, r);
1395 			regfree(&nod);
1396 			goto com;
1397 		}
1398 		regalloc(&nod, r, nn);
1399 		cgen(r, &nod);
1400 		if(l->addable < INDEXED || l->addable == 13) {
1401 			regalloc(&nod1, l, Z);
1402 			cgen(l, &nod1);
1403 			if(typechlp[l->type->etype])
1404 				gopcode(o, types[TINT], &nod1, &nod);
1405 			else
1406 				gopcode(o, l->type, &nod1, &nod);
1407 			regfree(&nod1);
1408 		} else
1409 			gopcode(o, l->type, l, &nod);
1410 		regfree(&nod);
1411 
1412 	com:
1413 		if(nn != Z) {
1414 			p1 = p;
1415 			gmove(nodconst(1L), nn);
1416 			gbranch(OGOTO);
1417 			p2 = p;
1418 			patch(p1, pc);
1419 			gmove(nodconst(0L), nn);
1420 			patch(p2, pc);
1421 		}
1422 		break;
1423 	}
1424 	cursafe = curs;
1425 }
1426 
1427 void
1428 sugen(Node *n, Node *nn, long w)
1429 {
1430 	Prog *p1;
1431 	Node nod0, nod1, nod2, nod3, nod4, *h, *l, *r;
1432 	Type *t;
1433 	int c, v, x;
1434 
1435 	if(n == Z || n->type == T)
1436 		return;
1437 	if(debug['g']) {
1438 		prtree(nn, "sugen lhs");
1439 		prtree(n, "sugen");
1440 	}
1441 	if(nn == nodrat)
1442 		if(w > nrathole)
1443 			nrathole = w;
1444 	switch(n->op) {
1445 	case OIND:
1446 		if(nn == Z) {
1447 			nullwarn(n->left, Z);
1448 			break;
1449 		}
1450 
1451 	default:
1452 		goto copy;
1453 
1454 	case OCONST:
1455 		if(n->type && typev[n->type->etype]) {
1456 			if(nn == Z) {
1457 				nullwarn(n->left, Z);
1458 				break;
1459 			}
1460 
1461 			if(nn->op == OREGPAIR) {
1462 				loadpair(n, nn);
1463 				break;
1464 			}
1465 			else if(!vaddr(nn, 0)) {
1466 				t = nn->type;
1467 				nn->type = types[TLONG];
1468 				reglcgen(&nod1, nn, Z);
1469 				nn->type = t;
1470 
1471 				gmove(lo64(n), &nod1);
1472 				nod1.xoffset += SZ_LONG;
1473 				gmove(hi64(n), &nod1);
1474 				regfree(&nod1);
1475 			}
1476 			else {
1477 				gins(AMOVL, lo64(n), nn);
1478 				nn->xoffset += SZ_LONG;
1479 				gins(AMOVL, hi64(n), nn);
1480 				nn->xoffset -= SZ_LONG;
1481 				break;
1482 			}
1483 			break;
1484 		}
1485 		goto copy;
1486 
1487 	case ODOT:
1488 		l = n->left;
1489 		sugen(l, nodrat, l->type->width);
1490 		if(nn == Z)
1491 			break;
1492 		warn(n, "non-interruptable temporary");
1493 		nod1 = *nodrat;
1494 		r = n->right;
1495 		if(!r || r->op != OCONST) {
1496 			diag(n, "DOT and no offset");
1497 			break;
1498 		}
1499 		nod1.xoffset += (long)r->vconst;
1500 		nod1.type = n->type;
1501 		sugen(&nod1, nn, w);
1502 		break;
1503 
1504 	case OSTRUCT:
1505 		/*
1506 		 * rewrite so lhs has no fn call
1507 		 */
1508 		if(nn != Z && side(nn)) {
1509 			nod1 = *n;
1510 			nod1.type = typ(TIND, n->type);
1511 			regret(&nod2, &nod1);
1512 			lcgen(nn, &nod2);
1513 			regsalloc(&nod0, &nod1);
1514 			cgen(&nod2, &nod0);
1515 			regfree(&nod2);
1516 
1517 			nod1 = *n;
1518 			nod1.op = OIND;
1519 			nod1.left = &nod0;
1520 			nod1.right = Z;
1521 			nod1.complex = 1;
1522 
1523 			sugen(n, &nod1, w);
1524 			return;
1525 		}
1526 
1527 		r = n->left;
1528 		for(t = n->type->link; t != T; t = t->down) {
1529 			l = r;
1530 			if(r->op == OLIST) {
1531 				l = r->left;
1532 				r = r->right;
1533 			}
1534 			if(nn == Z) {
1535 				cgen(l, nn);
1536 				continue;
1537 			}
1538 			/*
1539 			 * hand craft *(&nn + o) = l
1540 			 */
1541 			nod0 = znode;
1542 			nod0.op = OAS;
1543 			nod0.type = t;
1544 			nod0.left = &nod1;
1545 			nod0.right = nil;
1546 
1547 			nod1 = znode;
1548 			nod1.op = OIND;
1549 			nod1.type = t;
1550 			nod1.left = &nod2;
1551 
1552 			nod2 = znode;
1553 			nod2.op = OADD;
1554 			nod2.type = typ(TIND, t);
1555 			nod2.left = &nod3;
1556 			nod2.right = &nod4;
1557 
1558 			nod3 = znode;
1559 			nod3.op = OADDR;
1560 			nod3.type = nod2.type;
1561 			nod3.left = nn;
1562 
1563 			nod4 = znode;
1564 			nod4.op = OCONST;
1565 			nod4.type = nod2.type;
1566 			nod4.vconst = t->offset;
1567 
1568 			ccom(&nod0);
1569 			acom(&nod0);
1570 			xcom(&nod0);
1571 			nod0.addable = 0;
1572 			nod0.right = l;
1573 
1574 			/* prtree(&nod0, "hand craft"); /* */
1575 			cgen(&nod0, Z);
1576 		}
1577 		break;
1578 
1579 	case OAS:
1580 		if(nn == Z) {
1581 			if(n->addable < INDEXED)
1582 				sugen(n->right, n->left, w);
1583 			break;
1584 		}
1585 
1586 		sugen(n->right, nodrat, w);
1587 		warn(n, "non-interruptable temporary");
1588 		sugen(nodrat, n->left, w);
1589 		sugen(nodrat, nn, w);
1590 		break;
1591 
1592 	case OFUNC:
1593 		if(nn == Z) {
1594 			sugen(n, nodrat, w);
1595 			break;
1596 		}
1597 		h = nn;
1598 		if(nn->op == OREGPAIR) {
1599 			regsalloc(&nod1, nn);
1600 			nn = &nod1;
1601 		}
1602 		if(nn->op != OIND) {
1603 			nn = new1(OADDR, nn, Z);
1604 			nn->type = types[TIND];
1605 			nn->addable = 0;
1606 		} else
1607 			nn = nn->left;
1608 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
1609 		n->type = types[TVOID];
1610 		n->left->type = types[TVOID];
1611 		cgen(n, Z);
1612 		if(h->op == OREGPAIR)
1613 			loadpair(nn->left, h);
1614 		break;
1615 
1616 	case OCOND:
1617 		bcgen(n->left, 1);
1618 		p1 = p;
1619 		sugen(n->right->left, nn, w);
1620 		gbranch(OGOTO);
1621 		patch(p1, pc);
1622 		p1 = p;
1623 		sugen(n->right->right, nn, w);
1624 		patch(p1, pc);
1625 		break;
1626 
1627 	case OCOMMA:
1628 		cgen(n->left, Z);
1629 		sugen(n->right, nn, w);
1630 		break;
1631 	}
1632 	return;
1633 
1634 copy:
1635 	if(nn == Z) {
1636 		switch(n->op) {
1637 		case OASADD:
1638 		case OASSUB:
1639 		case OASAND:
1640 		case OASOR:
1641 		case OASXOR:
1642 
1643 		case OASMUL:
1644 		case OASLMUL:
1645 
1646 		case OASASHL:
1647 		case OASASHR:
1648 		case OASLSHR:
1649 			break;
1650 
1651 		case OPOSTINC:
1652 		case OPOSTDEC:
1653 		case OPREINC:
1654 		case OPREDEC:
1655 			break;
1656 
1657 		default:
1658 			return;
1659 		}
1660 	}
1661 
1662 	if(n->complex >= FNX && nn != nil && nn->complex >= FNX) {
1663 		t = nn->type;
1664 		nn->type = types[TLONG];
1665 		regialloc(&nod1, nn, Z);
1666 		lcgen(nn, &nod1);
1667 		regsalloc(&nod2, nn);
1668 		nn->type = t;
1669 
1670 		gins(AMOVL, &nod1, &nod2);
1671 		regfree(&nod1);
1672 
1673 		nod2.type = typ(TIND, t);
1674 
1675 		nod1 = nod2;
1676 		nod1.op = OIND;
1677 		nod1.left = &nod2;
1678 		nod1.right = Z;
1679 		nod1.complex = 1;
1680 		nod1.type = t;
1681 
1682 		sugen(n, &nod1, w);
1683 		return;
1684 	}
1685 
1686 	x = 0;
1687 	v = w == 8;
1688 	if(v) {
1689 		c = cursafe;
1690 		if(n->left != Z && n->left->complex >= FNX
1691 		&& n->right != Z && n->right->complex >= FNX) {
1692 //			warn(n, "toughie");
1693 			regsalloc(&nod1, n->right);
1694 			cgen(n->right, &nod1);
1695 			nod2 = *n;
1696 			nod2.right = &nod1;
1697 			cgen(&nod2, nn);
1698 			cursafe = c;
1699 			return;
1700 		}
1701 		if(cgen64(n, nn)) {
1702 			cursafe = c;
1703 			return;
1704 		}
1705 		if(n->op == OCOM) {
1706 			n = n->left;
1707 			x = 1;
1708 		}
1709 	}
1710 
1711 	/* botch, need to save in .safe */
1712 	c = 0;
1713 	if(n->complex > nn->complex) {
1714 		t = n->type;
1715 		n->type = types[TLONG];
1716 		if(v) {
1717 			regalloc(&nod0, n, Z);
1718 			if(!vaddr(n, 0)) {
1719 				reglcgen(&nod1, n, Z);
1720 				n->type = t;
1721 				n = &nod1;
1722 			}
1723 			else
1724 				n->type = t;
1725 		}
1726 		else {
1727 			nodreg(&nod1, n, D_SI);
1728 			if(reg[D_SI]) {
1729 				gins(APUSHL, &nod1, Z);
1730 				c |= 1;
1731 				reg[D_SI]++;
1732 			}
1733 			lcgen(n, &nod1);
1734 			n->type = t;
1735 		}
1736 
1737 		t = nn->type;
1738 		nn->type = types[TLONG];
1739 		if(v) {
1740 			if(!vaddr(nn, 0)) {
1741 				reglcgen(&nod2, nn, Z);
1742 				nn->type = t;
1743 				nn = &nod2;
1744 			}
1745 			else
1746 				nn->type = t;
1747 		}
1748 		else {
1749 			nodreg(&nod2, nn, D_DI);
1750 			if(reg[D_DI]) {
1751 				gins(APUSHL, &nod2, Z);
1752 				c |= 2;
1753 				reg[D_DI]++;
1754 			}
1755 			lcgen(nn, &nod2);
1756 			nn->type = t;
1757 		}
1758 	} else {
1759 		t = nn->type;
1760 		nn->type = types[TLONG];
1761 		if(v) {
1762 			regalloc(&nod0, nn, Z);
1763 			if(!vaddr(nn, 0)) {
1764 				reglcgen(&nod2, nn, Z);
1765 				nn->type = t;
1766 				nn = &nod2;
1767 			}
1768 			else
1769 				nn->type = t;
1770 		}
1771 		else {
1772 			nodreg(&nod2, nn, D_DI);
1773 			if(reg[D_DI]) {
1774 				gins(APUSHL, &nod2, Z);
1775 				c |= 2;
1776 				reg[D_DI]++;
1777 			}
1778 			lcgen(nn, &nod2);
1779 			nn->type = t;
1780 		}
1781 
1782 		t = n->type;
1783 		n->type = types[TLONG];
1784 		if(v) {
1785 			if(!vaddr(n, 0)) {
1786 				reglcgen(&nod1, n, Z);
1787 				n->type = t;
1788 				n = &nod1;
1789 			}
1790 			else
1791 				n->type = t;
1792 		}
1793 		else {
1794 			nodreg(&nod1, n, D_SI);
1795 			if(reg[D_SI]) {
1796 				gins(APUSHL, &nod1, Z);
1797 				c |= 1;
1798 				reg[D_SI]++;
1799 			}
1800 			lcgen(n, &nod1);
1801 			n->type = t;
1802 		}
1803 	}
1804 	if(v) {
1805 		gins(AMOVL, n, &nod0);
1806 		if(x)
1807 			gins(ANOTL, Z, &nod0);
1808 		gins(AMOVL, &nod0, nn);
1809 		n->xoffset += SZ_LONG;
1810 		nn->xoffset += SZ_LONG;
1811 		gins(AMOVL, n, &nod0);
1812 		if(x)
1813 			gins(ANOTL, Z, &nod0);
1814 		gins(AMOVL, &nod0, nn);
1815 		n->xoffset -= SZ_LONG;
1816 		nn->xoffset -= SZ_LONG;
1817 		if(nn == &nod2)
1818 			regfree(&nod2);
1819 		if(n == &nod1)
1820 			regfree(&nod1);
1821 		regfree(&nod0);
1822 		return;
1823 	}
1824 	nodreg(&nod3, n, D_CX);
1825 	if(reg[D_CX]) {
1826 		gins(APUSHL, &nod3, Z);
1827 		c |= 4;
1828 		reg[D_CX]++;
1829 	}
1830 	gins(AMOVL, nodconst(w/SZ_LONG), &nod3);
1831 	gins(ACLD, Z, Z);
1832 	gins(AREP, Z, Z);
1833 	gins(AMOVSL, Z, Z);
1834 	if(w & (SZ_LONG-1)) {
1835 		/* odd length of packed structure */
1836 		gins(AMOVL, nodconst(w & (SZ_LONG-1)), &nod3);
1837 		gins(AREP, Z, Z);
1838 		gins(AMOVSB, Z, Z);
1839 	}
1840 	if(c & 4) {
1841 		gins(APOPL, Z, &nod3);
1842 		reg[D_CX]--;
1843 	}
1844 	if(c & 2) {
1845 		gins(APOPL, Z, &nod2);
1846 		reg[nod2.reg]--;
1847 	}
1848 	if(c & 1) {
1849 		gins(APOPL, Z, &nod1);
1850 		reg[nod1.reg]--;
1851 	}
1852 }
1853