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