1 #include "gc.h"
2
3 /* ,x/^(print|prtree)\(/i/\/\/ */
4 int castup(Type*, Type*);
5
6 void
cgen(Node * n,Node * nn)7 cgen(Node *n, Node *nn)
8 {
9 Node *l, *r, *t;
10 Prog *p1;
11 Node nod, nod1, nod2, nod3, nod4;
12 int o, hardleft;
13 long v, curs;
14 vlong c;
15
16 if(debug['g']) {
17 prtree(nn, "cgen lhs");
18 prtree(n, "cgen");
19 }
20 if(n == Z || n->type == T)
21 return;
22 if(typesu[n->type->etype]) {
23 sugen(n, nn, n->type->width);
24 return;
25 }
26 l = n->left;
27 r = n->right;
28 o = n->op;
29 if(n->addable >= INDEXED) {
30 if(nn == Z) {
31 switch(o) {
32 default:
33 nullwarn(Z, Z);
34 break;
35 case OINDEX:
36 nullwarn(l, r);
37 break;
38 }
39 return;
40 }
41 gmove(n, nn);
42 return;
43 }
44 curs = cursafe;
45
46 if(l->complex >= FNX)
47 if(r != Z && r->complex >= FNX)
48 switch(o) {
49 default:
50 if(cond(o) && typesu[l->type->etype])
51 break;
52
53 regret(&nod, r);
54 cgen(r, &nod);
55
56 regsalloc(&nod1, r);
57 gmove(&nod, &nod1);
58
59 regfree(&nod);
60 nod = *n;
61 nod.right = &nod1;
62
63 cgen(&nod, nn);
64 return;
65
66 case OFUNC:
67 case OCOMMA:
68 case OANDAND:
69 case OOROR:
70 case OCOND:
71 case ODOT:
72 break;
73 }
74
75 hardleft = l->addable < INDEXED || l->complex >= FNX;
76 switch(o) {
77 default:
78 diag(n, "unknown op in cgen: %O", o);
79 break;
80
81 case ONEG:
82 case OCOM:
83 if(nn == Z) {
84 nullwarn(l, Z);
85 break;
86 }
87 regalloc(&nod, l, nn);
88 cgen(l, &nod);
89 gopcode(o, n->type, Z, &nod);
90 gmove(&nod, nn);
91 regfree(&nod);
92 break;
93
94 case OAS:
95 if(l->op == OBIT)
96 goto bitas;
97 if(!hardleft) {
98 if(nn != Z || r->addable < INDEXED || hardconst(r)) {
99 if(r->complex >= FNX && nn == Z)
100 regret(&nod, r);
101 else
102 regalloc(&nod, r, nn);
103 cgen(r, &nod);
104 gmove(&nod, l);
105 if(nn != Z)
106 gmove(&nod, nn);
107 regfree(&nod);
108 } else
109 gmove(r, l);
110 break;
111 }
112 if(l->complex >= r->complex) {
113 if(l->op == OINDEX && immconst(r)) {
114 gmove(r, l);
115 break;
116 }
117 reglcgen(&nod1, l, Z);
118 if(r->addable >= INDEXED && !hardconst(r)) {
119 gmove(r, &nod1);
120 if(nn != Z)
121 gmove(r, nn);
122 regfree(&nod1);
123 break;
124 }
125 regalloc(&nod, r, nn);
126 cgen(r, &nod);
127 } else {
128 regalloc(&nod, r, nn);
129 cgen(r, &nod);
130 reglcgen(&nod1, l, Z);
131 }
132 gmove(&nod, &nod1);
133 regfree(&nod);
134 regfree(&nod1);
135 break;
136
137 bitas:
138 n = l->left;
139 regalloc(&nod, r, nn);
140 if(l->complex >= r->complex) {
141 reglcgen(&nod1, n, Z);
142 cgen(r, &nod);
143 } else {
144 cgen(r, &nod);
145 reglcgen(&nod1, n, Z);
146 }
147 regalloc(&nod2, n, Z);
148 gmove(&nod1, &nod2);
149 bitstore(l, &nod, &nod1, &nod2, nn);
150 break;
151
152 case OBIT:
153 if(nn == Z) {
154 nullwarn(l, Z);
155 break;
156 }
157 bitload(n, &nod, Z, Z, nn);
158 gmove(&nod, nn);
159 regfree(&nod);
160 break;
161
162 case OLSHR:
163 case OASHL:
164 case OASHR:
165 if(nn == Z) {
166 nullwarn(l, r);
167 break;
168 }
169 if(r->op == OCONST) {
170 if(r->vconst == 0) {
171 cgen(l, nn);
172 break;
173 }
174 regalloc(&nod, l, nn);
175 cgen(l, &nod);
176 if(o == OASHL && r->vconst == 1)
177 gopcode(OADD, n->type, &nod, &nod);
178 else
179 gopcode(o, n->type, r, &nod);
180 gmove(&nod, nn);
181 regfree(&nod);
182 break;
183 }
184
185 /*
186 * get nod to be D_CX
187 */
188 if(nodreg(&nod, nn, D_CX)) {
189 regsalloc(&nod1, n);
190 gmove(&nod, &nod1);
191 cgen(n, &nod); /* probably a bug */
192 gmove(&nod, nn);
193 gmove(&nod1, &nod);
194 break;
195 }
196 reg[D_CX]++;
197 if(nn->op == OREGISTER && nn->reg == D_CX)
198 regalloc(&nod1, l, Z);
199 else
200 regalloc(&nod1, l, nn);
201 if(r->complex >= l->complex) {
202 cgen(r, &nod);
203 cgen(l, &nod1);
204 } else {
205 cgen(l, &nod1);
206 cgen(r, &nod);
207 }
208 gopcode(o, n->type, &nod, &nod1);
209 gmove(&nod1, nn);
210 regfree(&nod);
211 regfree(&nod1);
212 break;
213
214 case OADD:
215 case OSUB:
216 case OOR:
217 case OXOR:
218 case OAND:
219 if(nn == Z) {
220 nullwarn(l, r);
221 break;
222 }
223 if(typefd[n->type->etype])
224 goto fop;
225 if(r->op == OCONST) {
226 if(r->vconst == 0 && o != OAND) {
227 cgen(l, nn);
228 break;
229 }
230 }
231 if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
232 && (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
233 c = l->right->vconst;
234 if(c > 0 && c <= 3) {
235 if(l->left->complex >= r->complex) {
236 regalloc(&nod, l->left, nn);
237 cgen(l->left, &nod);
238 if(r->addable < INDEXED) {
239 regalloc(&nod1, r, Z);
240 cgen(r, &nod1);
241 genmuladd(&nod, &nod, 1 << c, &nod1);
242 regfree(&nod1);
243 }
244 else
245 genmuladd(&nod, &nod, 1 << c, r);
246 }
247 else {
248 regalloc(&nod, r, nn);
249 cgen(r, &nod);
250 regalloc(&nod1, l->left, Z);
251 cgen(l->left, &nod1);
252 genmuladd(&nod, &nod1, 1 << c, &nod);
253 regfree(&nod1);
254 }
255 gmove(&nod, nn);
256 regfree(&nod);
257 break;
258 }
259 }
260 if(r->addable >= INDEXED && !hardconst(r)) {
261 regalloc(&nod, l, nn);
262 cgen(l, &nod);
263 gopcode(o, n->type, r, &nod);
264 gmove(&nod, nn);
265 regfree(&nod);
266 break;
267 }
268 if(l->complex >= r->complex) {
269 regalloc(&nod, l, nn);
270 cgen(l, &nod);
271 regalloc(&nod1, r, Z);
272 cgen(r, &nod1);
273 gopcode(o, n->type, &nod1, &nod);
274 } else {
275 regalloc(&nod1, r, nn);
276 cgen(r, &nod1);
277 regalloc(&nod, l, Z);
278 cgen(l, &nod);
279 gopcode(o, n->type, &nod1, &nod);
280 }
281 gmove(&nod, nn);
282 regfree(&nod);
283 regfree(&nod1);
284 break;
285
286 case OLMOD:
287 case OMOD:
288 case OLMUL:
289 case OLDIV:
290 case OMUL:
291 case ODIV:
292 if(nn == Z) {
293 nullwarn(l, r);
294 break;
295 }
296 if(typefd[n->type->etype])
297 goto fop;
298 if(r->op == OCONST && typechl[n->type->etype]) { /* TO DO */
299 SET(v);
300 switch(o) {
301 case ODIV:
302 case OMOD:
303 c = r->vconst;
304 if(c < 0)
305 c = -c;
306 v = log2(c);
307 if(v < 0)
308 break;
309 /* fall thru */
310 case OMUL:
311 case OLMUL:
312 regalloc(&nod, l, nn);
313 cgen(l, &nod);
314 switch(o) {
315 case OMUL:
316 case OLMUL:
317 mulgen(n->type, r, &nod);
318 break;
319 case ODIV:
320 sdiv2(r->vconst, v, l, &nod);
321 break;
322 case OMOD:
323 smod2(r->vconst, v, l, &nod);
324 break;
325 }
326 gmove(&nod, nn);
327 regfree(&nod);
328 goto done;
329 case OLDIV:
330 c = r->vconst;
331 if((c & 0x80000000) == 0)
332 break;
333 regalloc(&nod1, l, Z);
334 cgen(l, &nod1);
335 regalloc(&nod, l, nn);
336 zeroregm(&nod);
337 gins(ACMPL, &nod1, nodconst(c));
338 gins(ASBBL, nodconst(-1), &nod);
339 regfree(&nod1);
340 gmove(&nod, nn);
341 regfree(&nod);
342 goto done;
343 }
344 }
345
346 if(o == OMUL) {
347 if(l->addable >= INDEXED) {
348 t = l;
349 l = r;
350 r = t;
351 }
352 /* should favour AX */
353 regalloc(&nod, l, nn);
354 cgen(l, &nod);
355 if(r->addable < INDEXED || hardconst(r)) {
356 regalloc(&nod1, r, Z);
357 cgen(r, &nod1);
358 gopcode(OMUL, n->type, &nod1, &nod);
359 regfree(&nod1);
360 }else
361 gopcode(OMUL, n->type, r, &nod); /* addressible */
362 gmove(&nod, nn);
363 regfree(&nod);
364 break;
365 }
366
367 /*
368 * get nod to be D_AX
369 * get nod1 to be D_DX
370 */
371 if(nodreg(&nod, nn, D_AX)) {
372 regsalloc(&nod2, n);
373 gmove(&nod, &nod2);
374 v = reg[D_AX];
375 reg[D_AX] = 0;
376
377 if(isreg(l, D_AX)) {
378 nod3 = *n;
379 nod3.left = &nod2;
380 cgen(&nod3, nn);
381 } else
382 if(isreg(r, D_AX)) {
383 nod3 = *n;
384 nod3.right = &nod2;
385 cgen(&nod3, nn);
386 } else
387 cgen(n, nn);
388
389 gmove(&nod2, &nod);
390 reg[D_AX] = v;
391 break;
392 }
393 if(nodreg(&nod1, nn, D_DX)) {
394 regsalloc(&nod2, n);
395 gmove(&nod1, &nod2);
396 v = reg[D_DX];
397 reg[D_DX] = 0;
398
399 if(isreg(l, D_DX)) {
400 nod3 = *n;
401 nod3.left = &nod2;
402 cgen(&nod3, nn);
403 } else
404 if(isreg(r, D_DX)) {
405 nod3 = *n;
406 nod3.right = &nod2;
407 cgen(&nod3, nn);
408 } else
409 cgen(n, nn);
410
411 gmove(&nod2, &nod1);
412 reg[D_DX] = v;
413 break;
414 }
415 reg[D_AX]++;
416
417 if(r->op == OCONST && (o == ODIV || o == OLDIV) && immconst(r) && typechl[r->type->etype]) {
418 reg[D_DX]++;
419 if(l->addable < INDEXED) {
420 regalloc(&nod2, l, Z);
421 cgen(l, &nod2);
422 l = &nod2;
423 }
424 if(o == ODIV)
425 sdivgen(l, r, &nod, &nod1);
426 else
427 udivgen(l, r, &nod, &nod1);
428 gmove(&nod1, nn);
429 if(l == &nod2)
430 regfree(l);
431 goto freeaxdx;
432 }
433
434 if(l->complex >= r->complex) {
435 cgen(l, &nod);
436 reg[D_DX]++;
437 if(o == ODIV || o == OMOD)
438 gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
439 if(o == OLDIV || o == OLMOD)
440 zeroregm(&nod1);
441 if(r->addable < INDEXED || r->op == OCONST) {
442 regalloc(&nod3, r, Z);
443 cgen(r, &nod3);
444 gopcode(o, n->type, &nod3, Z);
445 regfree(&nod3);
446 } else
447 gopcode(o, n->type, r, Z);
448 } else {
449 regsalloc(&nod3, r);
450 cgen(r, &nod3);
451 cgen(l, &nod);
452 reg[D_DX]++;
453 if(o == ODIV || o == OMOD)
454 gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
455 if(o == OLDIV || o == OLMOD)
456 zeroregm(&nod1);
457 gopcode(o, n->type, &nod3, Z);
458 }
459 if(o == OMOD || o == OLMOD)
460 gmove(&nod1, nn);
461 else
462 gmove(&nod, nn);
463 freeaxdx:
464 regfree(&nod);
465 regfree(&nod1);
466 break;
467
468 case OASLSHR:
469 case OASASHL:
470 case OASASHR:
471 if(r->op == OCONST)
472 goto asand;
473 if(l->op == OBIT)
474 goto asbitop;
475
476 /*
477 * get nod to be D_CX
478 */
479 if(nodreg(&nod, nn, D_CX)) {
480 regsalloc(&nod1, n);
481 gmove(&nod, &nod1);
482 cgen(n, &nod);
483 if(nn != Z)
484 gmove(&nod, nn);
485 gmove(&nod1, &nod);
486 break;
487 }
488 reg[D_CX]++;
489
490 if(r->complex >= l->complex) {
491 cgen(r, &nod);
492 if(hardleft)
493 reglcgen(&nod1, l, Z);
494 else
495 nod1 = *l;
496 } else {
497 if(hardleft)
498 reglcgen(&nod1, l, Z);
499 else
500 nod1 = *l;
501 cgen(r, &nod);
502 }
503
504 gopcode(o, l->type, &nod, &nod1);
505 regfree(&nod);
506 if(nn != Z)
507 gmove(&nod1, nn);
508 if(hardleft)
509 regfree(&nod1);
510 break;
511
512 case OASAND:
513 case OASADD:
514 case OASSUB:
515 case OASXOR:
516 case OASOR:
517 asand:
518 if(l->op == OBIT)
519 goto asbitop;
520 if(typefd[l->type->etype] || typefd[r->type->etype])
521 goto asfop;
522 if(l->complex >= r->complex) {
523 if(hardleft)
524 reglcgen(&nod, l, Z);
525 else
526 nod = *l;
527 if(!immconst(r)) {
528 regalloc(&nod1, r, nn);
529 cgen(r, &nod1);
530 gopcode(o, l->type, &nod1, &nod);
531 regfree(&nod1);
532 } else
533 gopcode(o, l->type, r, &nod);
534 } else {
535 regalloc(&nod1, r, nn);
536 cgen(r, &nod1);
537 if(hardleft)
538 reglcgen(&nod, l, Z);
539 else
540 nod = *l;
541 gopcode(o, l->type, &nod1, &nod);
542 regfree(&nod1);
543 }
544 if(nn != Z)
545 gmove(&nod, nn);
546 if(hardleft)
547 regfree(&nod);
548 break;
549
550 asfop:
551 if(l->complex >= r->complex) {
552 if(hardleft)
553 reglcgen(&nod, l, Z);
554 else
555 nod = *l;
556 if(r->addable < INDEXED){
557 regalloc(&nod1, r, nn);
558 cgen(r, &nod1);
559 }else
560 nod1 = *r;
561 regalloc(&nod2, r, Z);
562 gmove(&nod, &nod2);
563 gopcode(o, r->type, &nod1, &nod2);
564 gmove(&nod2, &nod);
565 regfree(&nod2);
566 if(r->addable < INDEXED)
567 regfree(&nod1);
568 } else {
569 regalloc(&nod1, r, nn);
570 cgen(r, &nod1);
571 if(hardleft)
572 reglcgen(&nod, l, Z);
573 else
574 nod = *l;
575 if(o != OASMUL && o != OASADD || !typefd[l->type->etype]) {
576 regalloc(&nod2, r, Z);
577 gmove(&nod, &nod2);
578 gopcode(o, r->type, &nod1, &nod2);
579 regfree(&nod1);
580 gmove(&nod2, &nod);
581 regfree(&nod2);
582 } else {
583 gopcode(o, r->type, &nod, &nod1);
584 gmove(&nod1, &nod);
585 regfree(&nod1);
586 }
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
reglcgen(Node * t,Node * n,Node * nn)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
lcgen(Node * n,Node * nn)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
bcgen(Node * n,int true)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
boolgen(Node * n,int true,Node * nn)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
sugen(Node * n,Node * nn,long w)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(AMOVQ, &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[TIND];
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[TIND];
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[TIND];
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[TIND];
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
layout(Node * f,Node * t,int c,int cv,Node * cn)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
immconst(Node * n)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
hardconst(Node * n)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
castup(Type * t1,Type * t2)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
zeroregm(Node * n)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
vaddr(Node * n,int a)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
hi64v(Node * n)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
lo64v(Node * n)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 *
hi64(Node * n)1907 hi64(Node *n)
1908 {
1909 return nodconst(hi64v(n));
1910 }
1911
1912 Node *
lo64(Node * n)1913 lo64(Node *n)
1914 {
1915 return nodconst(lo64v(n));
1916 }
1917
1918 int
cond(int op)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