changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > plan9front / sys/src/cmd/8c/cgen.c

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