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