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