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