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