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