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