1 #include "gc.h"
2
3 void
cgen(Node * n,Node * nn)4 cgen(Node *n, Node *nn)
5 {
6 cgenrel(n, nn, 0);
7 }
8
9 void
cgenrel(Node * n,Node * nn,int inrel)10 cgenrel(Node *n, Node *nn, int inrel)
11 {
12 Node *l, *r;
13 Prog *p1;
14 Node nod, nod1, nod2, nod3, nod4;
15 int o, t;
16 long v, curs;
17
18 if(debug['g']) {
19 prtree(nn, "cgen lhs");
20 prtree(n, "cgen");
21 }
22 if(n == Z || n->type == T)
23 return;
24 if(typesuv[n->type->etype]) {
25 sugen(n, nn, n->type->width);
26 return;
27 }
28 l = n->left;
29 r = n->right;
30 o = n->op;
31 if(n->addable >= INDEXED) {
32 if(nn == Z) {
33 switch(o) {
34 default:
35 nullwarn(Z, Z);
36 break;
37 case OINDEX:
38 nullwarn(l, r);
39 break;
40 }
41 return;
42 }
43 gmove(n, nn);
44 return;
45 }
46 curs = cursafe;
47
48 if(n->complex >= FNX)
49 if(l->complex >= FNX)
50 if(r != Z && r->complex >= FNX)
51 switch(o) {
52 default:
53 regret(&nod, r);
54 cgen(r, &nod);
55
56 regsalloc(&nod1, r);
57 gopcode(OAS, &nod, Z, &nod1);
58
59 regfree(&nod);
60 nod = *n;
61 nod.right = &nod1;
62 cgen(&nod, nn);
63 return;
64
65 case OFUNC:
66 case OCOMMA:
67 case OANDAND:
68 case OOROR:
69 case OCOND:
70 case ODOT:
71 break;
72 }
73
74 switch(o) {
75 default:
76 diag(n, "unknown op in cgen: %O", o);
77 break;
78
79 case OAS:
80 if(l->op == OBIT)
81 goto bitas;
82 if(l->addable >= INDEXED && l->complex < FNX) {
83 if(nn != Z || r->addable < INDEXED) {
84 if(r->complex >= FNX && nn == Z)
85 regret(&nod, r);
86 else
87 regalloc(&nod, r, nn);
88 cgen(r, &nod);
89 gmove(&nod, l);
90 if(nn != Z)
91 gmove(&nod, nn);
92 regfree(&nod);
93 } else
94 gmove(r, l);
95 break;
96 }
97 if(l->complex >= r->complex) {
98 reglcgen(&nod1, l, Z);
99 if(r->addable >= INDEXED) {
100 gmove(r, &nod1);
101 if(nn != Z)
102 gmove(r, nn);
103 regfree(&nod1);
104 break;
105 }
106 regalloc(&nod, r, nn);
107 cgen(r, &nod);
108 } else {
109 regalloc(&nod, r, nn);
110 cgen(r, &nod);
111 reglcgen(&nod1, l, Z);
112 }
113 gmove(&nod, &nod1);
114 regfree(&nod);
115 regfree(&nod1);
116 break;
117
118 bitas:
119 n = l->left;
120 regalloc(&nod, r, nn);
121 if(l->complex >= r->complex) {
122 reglcgen(&nod1, n, Z);
123 cgen(r, &nod);
124 } else {
125 cgen(r, &nod);
126 reglcgen(&nod1, n, Z);
127 }
128 regalloc(&nod2, n, Z);
129 gopcode(OAS, &nod1, Z, &nod2);
130 bitstore(l, &nod, &nod1, &nod2, nn);
131 break;
132
133 case OBIT:
134 if(nn == Z) {
135 nullwarn(l, Z);
136 break;
137 }
138 bitload(n, &nod, Z, Z, nn);
139 gopcode(OAS, &nod, Z, nn);
140 regfree(&nod);
141 break;
142
143 case ODIV:
144 case OMOD:
145 if(nn != Z)
146 if((t = vlog(r)) >= 0) {
147 /* signed div/mod by constant power of 2 */
148 cgen(l, nn);
149 gopcode(OGE, nodconst(0), nn, Z);
150 p1 = p;
151 if(o == ODIV) {
152 gopcode(OADD, nodconst((1<<t)-1), Z, nn);
153 patch(p1, pc);
154 gopcode(OASHR, nodconst(t), Z, nn);
155 } else {
156 gopcode(OSUB, nn, nodconst(0), nn);
157 gopcode(OAND, nodconst((1<<t)-1), Z, nn);
158 gopcode(OSUB, nn, nodconst(0), nn);
159 gbranch(OGOTO);
160 patch(p1, pc);
161 p1 = p;
162 gopcode(OAND, nodconst((1<<t)-1), Z, nn);
163 patch(p1, pc);
164 }
165 break;
166 }
167 goto muldiv;
168
169 case OSUB:
170 if(nn != Z)
171 if(l->op == OCONST)
172 if(!typefd[n->type->etype]) {
173 cgen(r, nn);
174 gopcode(o, Z, l, nn);
175 break;
176 }
177 case OADD:
178 case OAND:
179 case OOR:
180 case OXOR:
181 case OLSHR:
182 case OASHL:
183 case OASHR:
184 /*
185 * immediate operands
186 */
187 if(nn != Z)
188 if(r->op == OCONST)
189 if(!typefd[n->type->etype]) {
190 cgen(l, nn);
191 if(r->vconst == 0)
192 if(o != OAND)
193 break;
194 if(nn != Z)
195 gopcode(o, r, Z, nn);
196 break;
197 }
198
199 case OLMUL:
200 case OLDIV:
201 case OLMOD:
202 case OMUL:
203 muldiv:
204 if(nn == Z) {
205 nullwarn(l, r);
206 break;
207 }
208 if(o == OMUL || o == OLMUL) {
209 if(mulcon(n, nn))
210 break;
211 }
212 if(l->complex >= r->complex) {
213 regalloc(&nod, l, nn);
214 cgen(l, &nod);
215 regalloc(&nod1, r, Z);
216 cgen(r, &nod1);
217 gopcode(o, &nod1, Z, &nod);
218 } else {
219 regalloc(&nod, r, nn);
220 cgen(r, &nod);
221 regalloc(&nod1, l, Z);
222 cgen(l, &nod1);
223 gopcode(o, &nod, &nod1, &nod);
224 }
225 gopcode(OAS, &nod, Z, nn);
226 regfree(&nod);
227 regfree(&nod1);
228 break;
229
230 case OASLSHR:
231 case OASASHL:
232 case OASASHR:
233 case OASAND:
234 case OASADD:
235 case OASSUB:
236 case OASXOR:
237 case OASOR:
238 if(l->op == OBIT)
239 goto asbitop;
240 if(r->op == OCONST)
241 if(!typefd[r->type->etype])
242 if(!typefd[n->type->etype]) {
243 if(l->addable < INDEXED)
244 reglcgen(&nod2, l, Z);
245 else
246 nod2 = *l;
247 regalloc(&nod, r, nn);
248 gopcode(OAS, &nod2, Z, &nod);
249 gopcode(o, r, Z, &nod);
250 gopcode(OAS, &nod, Z, &nod2);
251
252 regfree(&nod);
253 if(l->addable < INDEXED)
254 regfree(&nod2);
255 break;
256 }
257
258 case OASLMUL:
259 case OASLDIV:
260 case OASLMOD:
261 case OASMUL:
262 case OASDIV:
263 case OASMOD:
264 if(l->op == OBIT)
265 goto asbitop;
266 if(l->complex >= r->complex) {
267 if(l->addable < INDEXED)
268 reglcgen(&nod2, l, Z);
269 else
270 nod2 = *l;
271 regalloc(&nod1, r, Z);
272 cgen(r, &nod1);
273 } else {
274 regalloc(&nod1, r, Z);
275 cgen(r, &nod1);
276 if(l->addable < INDEXED)
277 reglcgen(&nod2, l, Z);
278 else
279 nod2 = *l;
280 }
281
282 regalloc(&nod, n, nn);
283 gmove(&nod2, &nod);
284 gopcode(o, &nod1, Z, &nod);
285 gmove(&nod, &nod2);
286 if(nn != Z)
287 gopcode(OAS, &nod, Z, nn);
288 regfree(&nod);
289 regfree(&nod1);
290 if(l->addable < INDEXED)
291 regfree(&nod2);
292 break;
293
294 asbitop:
295 regalloc(&nod4, n, nn);
296 if(l->complex >= r->complex) {
297 bitload(l, &nod, &nod1, &nod2, &nod4);
298 regalloc(&nod3, r, Z);
299 cgen(r, &nod3);
300 } else {
301 regalloc(&nod3, r, Z);
302 cgen(r, &nod3);
303 bitload(l, &nod, &nod1, &nod2, &nod4);
304 }
305 gmove(&nod, &nod4);
306 gopcode(o, &nod3, Z, &nod4);
307 regfree(&nod3);
308 gmove(&nod4, &nod);
309 regfree(&nod4);
310 bitstore(l, &nod, &nod1, &nod2, nn);
311 break;
312
313 case OADDR:
314 if(nn == Z) {
315 nullwarn(l, Z);
316 break;
317 }
318 lcgen(l, nn);
319 break;
320
321 case OFUNC:
322 if(l->complex >= FNX) {
323 if(l->op != OIND)
324 diag(n, "bad function call");
325
326 regret(&nod, l->left);
327 cgen(l->left, &nod);
328 regsalloc(&nod1, l->left);
329 gopcode(OAS, &nod, Z, &nod1);
330 regfree(&nod);
331
332 nod = *n;
333 nod.left = &nod2;
334 nod2 = *l;
335 nod2.left = &nod1;
336 nod2.complex = 1;
337 cgen(&nod, nn);
338
339 return;
340 }
341 if(REGARG >= 0)
342 o = reg[REGARG];
343 gargs(r, &nod, &nod1);
344 if(l->addable < INDEXED) {
345 reglcgen(&nod, l, Z);
346 gopcode(OFUNC, Z, Z, &nod);
347 regfree(&nod);
348 } else
349 gopcode(OFUNC, Z, Z, l);
350 if(REGARG >= 0)
351 if(o != reg[REGARG])
352 reg[REGARG]--;
353 if(nn != Z) {
354 regret(&nod, n);
355 gopcode(OAS, &nod, Z, nn);
356 regfree(&nod);
357 }
358 break;
359
360 case OIND:
361 if(nn == Z) {
362 nullwarn(l, Z);
363 break;
364 }
365 regialloc(&nod, n, nn);
366 r = l;
367 while(r->op == OADD)
368 r = r->right;
369 if(sconst(r) && (v = r->vconst+nod.xoffset) > -4096 && v < 4096) {
370 v = r->vconst;
371 r->vconst = 0;
372 cgen(l, &nod);
373 nod.xoffset += v;
374 r->vconst = v;
375 } else
376 cgen(l, &nod);
377 regind(&nod, n);
378 gopcode(OAS, &nod, Z, nn);
379 regfree(&nod);
380 break;
381
382 case OEQ:
383 case ONE:
384 case OLE:
385 case OLT:
386 case OGE:
387 case OGT:
388 case OLO:
389 case OLS:
390 case OHI:
391 case OHS:
392 if(nn == Z) {
393 nullwarn(l, r);
394 break;
395 }
396 boolgen(n, 1, nn);
397 break;
398
399 case OANDAND:
400 case OOROR:
401 boolgen(n, 1, nn);
402 if(nn == Z)
403 patch(p, pc);
404 break;
405
406 case ONOT:
407 if(nn == Z) {
408 nullwarn(l, Z);
409 break;
410 }
411 boolgen(n, 1, nn);
412 break;
413
414 case OCOMMA:
415 cgen(l, Z);
416 cgen(r, nn);
417 break;
418
419 case OCAST:
420 if(nn == Z) {
421 nullwarn(l, Z);
422 break;
423 }
424 /*
425 * convert from types l->n->nn
426 */
427 if(nocast(l->type, n->type)) {
428 if(nocast(n->type, nn->type)) {
429 cgen(l, nn);
430 break;
431 }
432 }
433 regalloc(&nod, l, nn);
434 cgen(l, &nod);
435 regalloc(&nod1, n, &nod);
436 if(inrel)
437 gmover(&nod, &nod1);
438 else
439 gopcode(OAS, &nod, Z, &nod1);
440 gopcode(OAS, &nod1, Z, nn);
441 regfree(&nod1);
442 regfree(&nod);
443 break;
444
445 case ODOT:
446 sugen(l, nodrat, l->type->width);
447 if(nn != Z) {
448 warn(n, "non-interruptable temporary");
449 nod = *nodrat;
450 if(!r || r->op != OCONST) {
451 diag(n, "DOT and no offset");
452 break;
453 }
454 nod.xoffset += (long)r->vconst;
455 nod.type = n->type;
456 cgen(&nod, nn);
457 }
458 break;
459
460 case OCOND:
461 bcgen(l, 1);
462 p1 = p;
463 cgen(r->left, nn);
464 gbranch(OGOTO);
465 patch(p1, pc);
466 p1 = p;
467 cgen(r->right, nn);
468 patch(p1, pc);
469 break;
470
471 case OPOSTINC:
472 case OPOSTDEC:
473 v = 1;
474 if(l->type->etype == TIND)
475 v = l->type->link->width;
476 if(o == OPOSTDEC)
477 v = -v;
478 if(l->op == OBIT)
479 goto bitinc;
480 if(nn == Z)
481 goto pre;
482
483 if(l->addable < INDEXED)
484 reglcgen(&nod2, l, Z);
485 else
486 nod2 = *l;
487
488 regalloc(&nod, l, nn);
489 gopcode(OAS, &nod2, Z, &nod);
490 regalloc(&nod1, l, Z);
491 if(typefd[l->type->etype]) {
492 regalloc(&nod3, l, Z);
493 if(v < 0) {
494 gopcode(OAS, nodfconst(-v), Z, &nod3);
495 gopcode(OSUB, &nod3, &nod, &nod1);
496 } else {
497 gopcode(OAS, nodfconst(v), Z, &nod3);
498 gopcode(OADD, &nod3, &nod, &nod1);
499 }
500 regfree(&nod3);
501 } else
502 gopcode(OADD, nodconst(v), &nod, &nod1);
503 gopcode(OAS, &nod1, Z, &nod2);
504
505 regfree(&nod);
506 regfree(&nod1);
507 if(l->addable < INDEXED)
508 regfree(&nod2);
509 break;
510
511 case OPREINC:
512 case OPREDEC:
513 v = 1;
514 if(l->type->etype == TIND)
515 v = l->type->link->width;
516 if(o == OPREDEC)
517 v = -v;
518 if(l->op == OBIT)
519 goto bitinc;
520
521 pre:
522 if(l->addable < INDEXED)
523 reglcgen(&nod2, l, Z);
524 else
525 nod2 = *l;
526
527 regalloc(&nod, l, nn);
528 gopcode(OAS, &nod2, Z, &nod);
529 if(typefd[l->type->etype]) {
530 regalloc(&nod3, l, Z);
531 if(v < 0) {
532 gopcode(OAS, nodfconst(-v), Z, &nod3);
533 gopcode(OSUB, &nod3, Z, &nod);
534 } else {
535 gopcode(OAS, nodfconst(v), Z, &nod3);
536 gopcode(OADD, &nod3, Z, &nod);
537 }
538 regfree(&nod3);
539 } else
540 gopcode(OADD, nodconst(v), Z, &nod);
541 gopcode(OAS, &nod, Z, &nod2);
542 if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */
543 gins(ANOP, l, Z);
544
545 regfree(&nod);
546 if(l->addable < INDEXED)
547 regfree(&nod2);
548 break;
549
550 bitinc:
551 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
552 bitload(l, &nod, &nod1, &nod2, Z);
553 gopcode(OAS, &nod, Z, nn);
554 gopcode(OADD, nodconst(v), Z, &nod);
555 bitstore(l, &nod, &nod1, &nod2, Z);
556 break;
557 }
558 bitload(l, &nod, &nod1, &nod2, nn);
559 gopcode(OADD, nodconst(v), Z, &nod);
560 bitstore(l, &nod, &nod1, &nod2, nn);
561 break;
562 }
563 cursafe = curs;
564 return;
565 }
566
567 void
reglcgen(Node * t,Node * n,Node * nn)568 reglcgen(Node *t, Node *n, Node *nn)
569 {
570 Node *r;
571 long v;
572
573 regialloc(t, n, nn);
574 if(n->op == OIND) {
575 r = n->left;
576 while(r->op == OADD)
577 r = r->right;
578 if(sconst(r) && (v = r->vconst+t->xoffset) > -4096 && v < 4096) {
579 v = r->vconst;
580 r->vconst = 0;
581 lcgen(n, t);
582 t->xoffset += v;
583 r->vconst = v;
584 regind(t, n);
585 return;
586 }
587 } else if(n->op == OINDREG) {
588 if((v = n->xoffset) > -4096 && v < 4096) {
589 n->op = OREGISTER;
590 cgen(n, t);
591 t->xoffset += v;
592 n->op = OINDREG;
593 regind(t, n);
594 return;
595 }
596 }
597 lcgen(n, t);
598 regind(t, n);
599 }
600
601 void
reglpcgen(Node * n,Node * nn,int f)602 reglpcgen(Node *n, Node *nn, int f)
603 {
604 Type *t;
605
606 t = nn->type;
607 nn->type = types[TLONG];
608 if(f)
609 reglcgen(n, nn, Z);
610 else {
611 regialloc(n, nn, Z);
612 lcgen(nn, n);
613 regind(n, nn);
614 }
615 nn->type = t;
616 }
617
618 void
lcgen(Node * n,Node * nn)619 lcgen(Node *n, Node *nn)
620 {
621 Prog *p1;
622 Node nod;
623
624 if(debug['g']) {
625 prtree(nn, "lcgen lhs");
626 prtree(n, "lcgen");
627 }
628 if(n == Z || n->type == T)
629 return;
630 if(nn == Z) {
631 nn = &nod;
632 regalloc(&nod, n, Z);
633 }
634 switch(n->op) {
635 default:
636 if(n->addable < INDEXED) {
637 diag(n, "unknown op in lcgen: %O", n->op);
638 break;
639 }
640 nod = *n;
641 nod.op = OADDR;
642 nod.left = n;
643 nod.right = Z;
644 nod.type = types[TIND];
645 gopcode(OAS, &nod, Z, nn);
646 break;
647
648 case OCOMMA:
649 cgen(n->left, n->left);
650 lcgen(n->right, nn);
651 break;
652
653 case OIND:
654 cgen(n->left, nn);
655 break;
656
657 case OCOND:
658 bcgen(n->left, 1);
659 p1 = p;
660 lcgen(n->right->left, nn);
661 gbranch(OGOTO);
662 patch(p1, pc);
663 p1 = p;
664 lcgen(n->right->right, nn);
665 patch(p1, pc);
666 break;
667 }
668 }
669
670 void
bcgen(Node * n,int true)671 bcgen(Node *n, int true)
672 {
673
674 if(n->type == T)
675 gbranch(OGOTO);
676 else
677 boolgen(n, true, Z);
678 }
679
680 void
boolgen(Node * n,int true,Node * nn)681 boolgen(Node *n, int true, Node *nn)
682 {
683 int o;
684 Prog *p1, *p2;
685 Node *l, *r, nod, nod1;
686 long curs;
687
688 if(debug['g']) {
689 prtree(nn, "boolgen lhs");
690 prtree(n, "boolgen");
691 }
692 curs = cursafe;
693 l = n->left;
694 r = n->right;
695 switch(n->op) {
696
697 default:
698 regalloc(&nod, n, nn);
699 cgen(n, &nod);
700 o = ONE;
701 if(true)
702 o = comrel[relindex(o)];
703 if(typefd[n->type->etype]) {
704 gopcode(true ? o | BTRUE : o, nodfconst(0), &nod, Z);
705 } else
706 gopcode(o, nodconst(0), &nod, Z);
707 regfree(&nod);
708 goto com;
709
710 case OCONST:
711 o = vconst(n);
712 if(!true)
713 o = !o;
714 gbranch(OGOTO);
715 if(o) {
716 p1 = p;
717 gbranch(OGOTO);
718 patch(p1, pc);
719 }
720 goto com;
721
722 case OCOMMA:
723 cgen(l, Z);
724 boolgen(r, true, nn);
725 break;
726
727 case ONOT:
728 boolgen(l, !true, nn);
729 break;
730
731 case OCOND:
732 bcgen(l, 1);
733 p1 = p;
734 bcgen(r->left, true);
735 p2 = p;
736 gbranch(OGOTO);
737 patch(p1, pc);
738 p1 = p;
739 bcgen(r->right, !true);
740 patch(p2, pc);
741 p2 = p;
742 gbranch(OGOTO);
743 patch(p1, pc);
744 patch(p2, pc);
745 goto com;
746
747 case OANDAND:
748 if(!true)
749 goto caseor;
750
751 caseand:
752 bcgen(l, true);
753 p1 = p;
754 bcgen(r, !true);
755 p2 = p;
756 patch(p1, pc);
757 gbranch(OGOTO);
758 patch(p2, pc);
759 goto com;
760
761 case OOROR:
762 if(!true)
763 goto caseand;
764
765 caseor:
766 bcgen(l, !true);
767 p1 = p;
768 bcgen(r, !true);
769 p2 = p;
770 gbranch(OGOTO);
771 patch(p1, pc);
772 patch(p2, pc);
773 goto com;
774
775 case OEQ:
776 case ONE:
777 case OLE:
778 case OLT:
779 case OGE:
780 case OGT:
781 case OHI:
782 case OHS:
783 case OLO:
784 case OLS:
785 o = n->op;
786 if(true)
787 o = comrel[relindex(o)];
788 if(l->complex >= FNX && r->complex >= FNX) {
789 regret(&nod, r);
790 cgenrel(r, &nod, 1);
791 regsalloc(&nod1, r);
792 gopcode(OAS, &nod, Z, &nod1);
793 regfree(&nod);
794 nod = *n;
795 nod.right = &nod1;
796 boolgen(&nod, true, nn);
797 break;
798 }
799 if(sconst(l)) {
800 regalloc(&nod, r, nn);
801 cgenrel(r, &nod, 1);
802 o = invrel[relindex(o)];
803 gopcode(true ? o | BTRUE : o, l, &nod, Z);
804 regfree(&nod);
805 goto com;
806 }
807 if(sconst(r)) {
808 regalloc(&nod, l, nn);
809 cgenrel(l, &nod, 1);
810 gopcode(true ? o | BTRUE : o, r, &nod, Z);
811 regfree(&nod);
812 goto com;
813 }
814 if(l->complex >= r->complex) {
815 regalloc(&nod1, l, nn);
816 cgenrel(l, &nod1, 1);
817 regalloc(&nod, r, Z);
818 cgenrel(r, &nod, 1);
819 } else {
820 regalloc(&nod, r, nn);
821 cgenrel(r, &nod, 1);
822 regalloc(&nod1, l, Z);
823 cgenrel(l, &nod1, 1);
824 }
825 gopcode(true ? o | BTRUE : o, &nod, &nod1, Z);
826 regfree(&nod);
827 regfree(&nod1);
828
829 com:
830 if(nn != Z) {
831 p1 = p;
832 gopcode(OAS, nodconst(1), Z, nn);
833 gbranch(OGOTO);
834 p2 = p;
835 patch(p1, pc);
836 gopcode(OAS, nodconst(0), Z, nn);
837 patch(p2, pc);
838 }
839 break;
840 }
841 cursafe = curs;
842 }
843
844 void
sugen(Node * n,Node * nn,long w)845 sugen(Node *n, Node *nn, long w)
846 {
847 Prog *p1;
848 Node nod0, nod1, nod2, nod3, nod4, *l, *r;
849 Type *t;
850 long pc1;
851 int i, m, c;
852
853 if(n == Z || n->type == T)
854 return;
855 if(debug['g']) {
856 prtree(nn, "sugen lhs");
857 prtree(n, "sugen");
858 }
859 if(nn == nodrat)
860 if(w > nrathole)
861 nrathole = w;
862 switch(n->op) {
863 case OIND:
864 if(nn == Z) {
865 nullwarn(n->left, Z);
866 break;
867 }
868
869 default:
870 goto copy;
871
872 case OCONST:
873 if(n->type && typev[n->type->etype]) {
874 if(nn == Z) {
875 nullwarn(n->left, Z);
876 break;
877 }
878
879 t = nn->type;
880 nn->type = types[TLONG];
881 reglcgen(&nod1, nn, Z);
882 nn->type = t;
883
884 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
885 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
886 else
887 gopcode(OAS, nod32const(n->vconst), Z, &nod1);
888 nod1.xoffset += SZ_LONG;
889 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
890 gopcode(OAS, nod32const(n->vconst), Z, &nod1);
891 else
892 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
893
894 regfree(&nod1);
895 break;
896 }
897 goto copy;
898
899 case ODOT:
900 l = n->left;
901 sugen(l, nodrat, l->type->width);
902 if(nn != Z) {
903 warn(n, "non-interruptable temporary");
904 nod1 = *nodrat;
905 r = n->right;
906 if(!r || r->op != OCONST) {
907 diag(n, "DOT and no offset");
908 break;
909 }
910 nod1.xoffset += (long)r->vconst;
911 nod1.type = n->type;
912 sugen(&nod1, nn, w);
913 }
914 break;
915
916 case OSTRUCT:
917 /*
918 * rewrite so lhs has no fn call
919 */
920 if(nn != Z && nn->complex >= FNX) {
921 nod1 = *n;
922 nod1.type = typ(TIND, n->type);
923 regret(&nod2, &nod1);
924 lcgen(nn, &nod2);
925 regsalloc(&nod0, &nod1);
926 gopcode(OAS, &nod2, Z, &nod0);
927 regfree(&nod2);
928
929 nod1 = *n;
930 nod1.op = OIND;
931 nod1.left = &nod0;
932 nod1.right = Z;
933 nod1.complex = 1;
934
935 sugen(n, &nod1, w);
936 return;
937 }
938
939 r = n->left;
940 for(t = n->type->link; t != T; t = t->down) {
941 l = r;
942 if(r->op == OLIST) {
943 l = r->left;
944 r = r->right;
945 }
946 if(nn == Z) {
947 cgen(l, nn);
948 continue;
949 }
950 /*
951 * hand craft *(&nn + o) = l
952 */
953 nod0 = znode;
954 nod0.op = OAS;
955 nod0.type = t;
956 nod0.left = &nod1;
957 nod0.right = l;
958
959 nod1 = znode;
960 nod1.op = OIND;
961 nod1.type = t;
962 nod1.left = &nod2;
963
964 nod2 = znode;
965 nod2.op = OADD;
966 nod2.type = typ(TIND, t);
967 nod2.left = &nod3;
968 nod2.right = &nod4;
969
970 nod3 = znode;
971 nod3.op = OADDR;
972 nod3.type = nod2.type;
973 nod3.left = nn;
974
975 nod4 = znode;
976 nod4.op = OCONST;
977 nod4.type = nod2.type;
978 nod4.vconst = t->offset;
979
980 ccom(&nod0);
981 acom(&nod0);
982 xcom(&nod0);
983 nod0.addable = 0;
984
985 cgen(&nod0, Z);
986 }
987 break;
988
989 case OAS:
990 if(nn == Z) {
991 if(n->addable < INDEXED)
992 sugen(n->right, n->left, w);
993 break;
994 }
995 sugen(n->right, nodrat, w);
996 warn(n, "non-interruptable temporary");
997 sugen(nodrat, n->left, w);
998 sugen(nodrat, nn, w);
999 break;
1000
1001 case OFUNC:
1002 if(nn == Z) {
1003 sugen(n, nodrat, w);
1004 break;
1005 }
1006 if(nn->op != OIND) {
1007 nn = new1(OADDR, nn, Z);
1008 nn->type = types[TIND];
1009 nn->addable = 0;
1010 } else
1011 nn = nn->left;
1012 n = new(OFUNC, n->left, new(OLIST, nn, n->right));
1013 n->type = types[TVOID];
1014 n->left->type = types[TVOID];
1015 cgen(n, Z);
1016 break;
1017
1018 case OCOND:
1019 bcgen(n->left, 1);
1020 p1 = p;
1021 sugen(n->right->left, nn, w);
1022 gbranch(OGOTO);
1023 patch(p1, pc);
1024 p1 = p;
1025 sugen(n->right->right, nn, w);
1026 patch(p1, pc);
1027 break;
1028
1029 case OCOMMA:
1030 cgen(n->left, Z);
1031 sugen(n->right, nn, w);
1032 break;
1033 }
1034 return;
1035
1036 copy:
1037 if(nn == Z)
1038 return;
1039 if(n->complex >= FNX && nn->complex >= FNX) {
1040 t = nn->type;
1041 nn->type = types[TLONG];
1042 regialloc(&nod1, nn, Z);
1043 lcgen(nn, &nod1);
1044 regsalloc(&nod2, nn);
1045 nn->type = t;
1046
1047 gopcode(OAS, &nod1, Z, &nod2);
1048 regfree(&nod1);
1049
1050 nod2.type = typ(TIND, t);
1051
1052 nod1 = nod2;
1053 nod1.op = OIND;
1054 nod1.left = &nod2;
1055 nod1.right = Z;
1056 nod1.complex = 1;
1057 nod1.type = t;
1058
1059 sugen(n, &nod1, w);
1060 return;
1061 }
1062
1063 w /= SZ_LONG;
1064 if(w <= 2) {
1065 if(n->complex > nn->complex) {
1066 reglpcgen(&nod1, n, 1);
1067 reglpcgen(&nod2, nn, 1);
1068 } else {
1069 reglpcgen(&nod2, nn, 1);
1070 reglpcgen(&nod1, n, 1);
1071 }
1072 regalloc(&nod3, ®node, Z);
1073 regalloc(&nod4, ®node, Z);
1074 if(nod3.reg > nod4.reg){
1075 /* code below assumes nod3 loaded first */
1076 Node t = nod3; nod3 = nod4; nod4 = t;
1077 }
1078 nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg));
1079 if(w == 2 && nod1.xoffset == 0)
1080 gmovm(&nod1, &nod0, 0);
1081 else {
1082 gmove(&nod1, &nod3);
1083 if(w == 2) {
1084 nod1.xoffset += SZ_LONG;
1085 gmove(&nod1, &nod4);
1086 }
1087 }
1088 if(w == 2 && nod2.xoffset == 0)
1089 gmovm(&nod0, &nod2, 0);
1090 else {
1091 gmove(&nod3, &nod2);
1092 if(w == 2) {
1093 nod2.xoffset += SZ_LONG;
1094 gmove(&nod4, &nod2);
1095 }
1096 }
1097 regfree(&nod1);
1098 regfree(&nod2);
1099 regfree(&nod3);
1100 regfree(&nod4);
1101 return;
1102 }
1103
1104 if(n->complex > nn->complex) {
1105 reglpcgen(&nod1, n, 0);
1106 reglpcgen(&nod2, nn, 0);
1107 } else {
1108 reglpcgen(&nod2, nn, 0);
1109 reglpcgen(&nod1, n, 0);
1110 }
1111
1112 m = 0;
1113 for(c = 0; c < w && c < 4; c++) {
1114 i = tmpreg();
1115 if (i == 0)
1116 break;
1117 reg[i]++;
1118 m |= 1<<i;
1119 }
1120 nod4 = *(nodconst(m));
1121 if(w < 3*c) {
1122 for (; w>c; w-=c) {
1123 gmovm(&nod1, &nod4, 1);
1124 gmovm(&nod4, &nod2, 1);
1125 }
1126 goto out;
1127 }
1128
1129 regalloc(&nod3, ®node, Z);
1130 gopcode(OAS, nodconst(w/c), Z, &nod3);
1131 w %= c;
1132
1133 pc1 = pc;
1134 gmovm(&nod1, &nod4, 1);
1135 gmovm(&nod4, &nod2, 1);
1136
1137 gopcode(OSUB, nodconst(1), Z, &nod3);
1138 gopcode(OEQ, nodconst(0), &nod3, Z);
1139 p->as = ABGT;
1140 patch(p, pc1);
1141 regfree(&nod3);
1142
1143 out:
1144 if (w) {
1145 i = 0;
1146 while (c>w) {
1147 while ((m&(1<<i)) == 0)
1148 i++;
1149 m &= ~(1<<i);
1150 reg[i] = 0;
1151 c--;
1152 i++;
1153 }
1154 nod4.vconst = m;
1155 gmovm(&nod1, &nod4, 0);
1156 gmovm(&nod4, &nod2, 0);
1157 }
1158 i = 0;
1159 do {
1160 while ((m&(1<<i)) == 0)
1161 i++;
1162 reg[i] = 0;
1163 c--;
1164 i++;
1165 } while (c>0);
1166 regfree(&nod1);
1167 regfree(&nod2);
1168 }
1169