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