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