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