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