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