changelog shortlog tags branches changeset files revisions annotate raw help

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