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