1 #include "gc.h"
2
3 static int resvreg[nelem(reg)];
4
5 #define isv(et) ((et) == TVLONG || (et) == TUVLONG || (et) == TIND)
6
7 void
ginit(void)8 ginit(void)
9 {
10 Type *t;
11
12 thechar = '9';
13 thestring = "power64";
14 exregoffset = REGEXT;
15 exfregoffset = FREGEXT;
16 listinit();
17 nstring = 0;
18 mnstring = 0;
19 nrathole = 0;
20 pc = 0;
21 breakpc = -1;
22 continpc = -1;
23 cases = C;
24 firstp = P;
25 lastp = P;
26 tfield = types[TLONG];
27
28 typeword = typechlvp;
29 typeswitch = typechlv;
30 typecmplx = typesu;
31 /* TO DO */
32 memmove(typechlpv, typechlp, sizeof(typechlpv));
33 typechlpv[TVLONG] = 1;
34 typechlpv[TUVLONG] = 1;
35
36 zprog.link = P;
37 zprog.as = AGOK;
38 zprog.reg = NREG;
39 zprog.from.type = D_NONE;
40 zprog.from.name = D_NONE;
41 zprog.from.reg = NREG;
42 zprog.to = zprog.from;
43
44 regnode.op = OREGISTER;
45 regnode.class = CEXREG;
46 regnode.reg = 0;
47 regnode.complex = 0;
48 regnode.addable = 11;
49 regnode.type = types[TLONG];
50
51 qregnode = regnode;
52 qregnode.type = types[TVLONG];
53
54 constnode.op = OCONST;
55 constnode.class = CXXX;
56 constnode.complex = 0;
57 constnode.addable = 20;
58 constnode.type = types[TLONG];
59
60 vconstnode = constnode;
61 vconstnode.type = types[TVLONG];
62
63 fconstnode.op = OCONST;
64 fconstnode.class = CXXX;
65 fconstnode.complex = 0;
66 fconstnode.addable = 20;
67 fconstnode.type = types[TDOUBLE];
68
69 nodsafe = new(ONAME, Z, Z);
70 nodsafe->sym = slookup(".safe");
71 nodsafe->type = types[TINT];
72 nodsafe->etype = types[TINT]->etype;
73 nodsafe->class = CAUTO;
74 complex(nodsafe);
75
76 t = typ(TARRAY, types[TCHAR]);
77 symrathole = slookup(".rathole");
78 symrathole->class = CGLOBL;
79 symrathole->type = t;
80
81 nodrat = new(ONAME, Z, Z);
82 nodrat->sym = symrathole;
83 nodrat->type = types[TIND];
84 nodrat->etype = TVOID;
85 nodrat->class = CGLOBL;
86 complex(nodrat);
87 nodrat->type = t;
88
89 nodret = new(ONAME, Z, Z);
90 nodret->sym = slookup(".ret");
91 nodret->type = types[TIND];
92 nodret->etype = TIND;
93 nodret->class = CPARAM;
94 nodret = new(OIND, nodret, Z);
95 complex(nodret);
96
97 com64init();
98
99 memset(reg, 0, sizeof(reg));
100 reg[REGZERO] = 1; /* don't use */
101 reg[REGTMP] = 1;
102 reg[FREGCVI+NREG] = 1;
103 reg[FREGZERO+NREG] = 1;
104 reg[FREGHALF+NREG] = 1;
105 reg[FREGONE+NREG] = 1;
106 reg[FREGTWO+NREG] = 1;
107 memmove(resvreg, reg, sizeof(reg));
108 }
109
110 void
gclean(void)111 gclean(void)
112 {
113 int i;
114 Sym *s;
115
116 for(i=0; i<NREG; i++)
117 if(reg[i] && !resvreg[i])
118 diag(Z, "reg %d left allocated", i);
119 for(i=NREG; i<NREG+NREG; i++)
120 if(reg[i] && !resvreg[i])
121 diag(Z, "freg %d left allocated", i-NREG);
122 while(mnstring)
123 outstring("", 1L);
124 symstring->type->width = nstring;
125 symrathole->type->width = nrathole;
126 for(i=0; i<NHASH; i++)
127 for(s = hash[i]; s != S; s = s->link) {
128 if(s->type == T)
129 continue;
130 if(s->type->width == 0)
131 continue;
132 if(s->class != CGLOBL && s->class != CSTATIC)
133 continue;
134 if(s->type == types[TENUM])
135 continue;
136 gpseudo(AGLOBL, s, nodconst(s->type->width));
137 }
138 nextpc();
139 p->as = AEND;
140 outcode();
141 }
142
143 void
nextpc(void)144 nextpc(void)
145 {
146
147 p = alloc(sizeof(*p));
148 *p = zprog;
149 p->lineno = nearln;
150 pc++;
151 if(firstp == P) {
152 firstp = p;
153 lastp = p;
154 return;
155 }
156 lastp->link = p;
157 lastp = p;
158 }
159
160 void
gargs(Node * n,Node * tn1,Node * tn2)161 gargs(Node *n, Node *tn1, Node *tn2)
162 {
163 long regs;
164 Node fnxargs[20], *fnxp;
165
166 regs = cursafe;
167
168 fnxp = fnxargs;
169 garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */
170
171 curarg = 0;
172 fnxp = fnxargs;
173 garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */
174
175 cursafe = regs;
176 }
177
178 void
garg1(Node * n,Node * tn1,Node * tn2,int f,Node ** fnxp)179 garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
180 {
181 Node nod;
182
183 if(n == Z)
184 return;
185 if(n->op == OLIST) {
186 garg1(n->left, tn1, tn2, f, fnxp);
187 garg1(n->right, tn1, tn2, f, fnxp);
188 return;
189 }
190 if(f == 0) {
191 if(n->complex >= FNX) {
192 regsalloc(*fnxp, n);
193 nod = znode;
194 nod.op = OAS;
195 nod.left = *fnxp;
196 nod.right = n;
197 nod.type = n->type;
198 cgen(&nod, Z);
199 (*fnxp)++;
200 }
201 return;
202 }
203 if(typesu[n->type->etype]) {
204 regaalloc(tn2, n);
205 if(n->complex >= FNX) {
206 sugen(*fnxp, tn2, n->type->width);
207 (*fnxp)++;
208 } else
209 sugen(n, tn2, n->type->width);
210 return;
211 }
212 if(REGARG>=0 && curarg == 0 && typechlpv[n->type->etype]) {
213 regaalloc1(tn1, n);
214 if(n->complex >= FNX) {
215 cgen(*fnxp, tn1);
216 (*fnxp)++;
217 } else
218 cgen(n, tn1);
219 return;
220 }
221 if(vconst(n) == 0) {
222 regaalloc(tn2, n);
223 gopcode(OAS, n, Z, tn2);
224 return;
225 }
226 regalloc(tn1, n, Z);
227 if(n->complex >= FNX) {
228 cgen(*fnxp, tn1);
229 (*fnxp)++;
230 } else
231 cgen(n, tn1);
232 regaalloc(tn2, n);
233 gopcode(OAS, tn1, Z, tn2);
234 regfree(tn1);
235 }
236
237 Node*
nod32const(vlong v)238 nod32const(vlong v)
239 {
240 constnode.vconst = v & MASK(32);
241 return &constnode;
242 }
243
244 Node*
nodgconst(vlong v,Type * t)245 nodgconst(vlong v, Type *t)
246 {
247 if(!typev[t->etype])
248 return nodconst((long)v);
249 vconstnode.vconst = v;
250 return &vconstnode;
251 }
252
253 Node*
nodconst(long v)254 nodconst(long v)
255 {
256 constnode.vconst = v;
257 return &constnode;
258 }
259
260 Node*
nodfconst(double d)261 nodfconst(double d)
262 {
263 fconstnode.fconst = d;
264 return &fconstnode;
265 }
266
267 void
nodreg(Node * n,Node * nn,int reg)268 nodreg(Node *n, Node *nn, int reg)
269 {
270 *n = qregnode;
271 n->reg = reg;
272 n->type = nn->type;
273 n->lineno = nn->lineno;
274 }
275
276 void
regret(Node * n,Node * nn)277 regret(Node *n, Node *nn)
278 {
279 int r;
280
281 r = REGRET;
282 if(typefd[nn->type->etype])
283 r = FREGRET+NREG;
284 nodreg(n, nn, r);
285 reg[r]++;
286 }
287
288 void
regalloc(Node * n,Node * tn,Node * o)289 regalloc(Node *n, Node *tn, Node *o)
290 {
291 int i, j;
292 static int lasti;
293
294 switch(tn->type->etype) {
295 case TCHAR:
296 case TUCHAR:
297 case TSHORT:
298 case TUSHORT:
299 case TINT:
300 case TUINT:
301 case TLONG:
302 case TULONG:
303 case TVLONG:
304 case TUVLONG:
305 case TIND:
306 if(o != Z && o->op == OREGISTER) {
307 i = o->reg;
308 if(i > 0 && i < NREG)
309 goto out;
310 }
311 j = lasti + REGRET+1;
312 for(i=REGRET+1; i<NREG; i++) {
313 if(j >= NREG)
314 j = REGRET+1;
315 if(reg[j] == 0) {
316 i = j;
317 goto out;
318 }
319 j++;
320 }
321 diag(tn, "out of fixed registers");
322 goto err;
323
324 case TFLOAT:
325 case TDOUBLE:
326 if(o != Z && o->op == OREGISTER) {
327 i = o->reg;
328 if(i >= NREG && i < NREG+NREG)
329 goto out;
330 }
331 j = lasti + NREG;
332 for(i=NREG; i<NREG+NREG; i++) {
333 if(j >= NREG+NREG)
334 j = NREG;
335 if(reg[j] == 0) {
336 i = j;
337 goto out;
338 }
339 j++;
340 }
341 diag(tn, "out of float registers");
342 goto err;
343 }
344 diag(tn, "unknown type in regalloc: %T", tn->type);
345 err:
346 i = 0;
347 out:
348 if(i)
349 reg[i]++;
350 lasti++;
351 if(lasti >= 5)
352 lasti = 0;
353 nodreg(n, tn, i);
354 }
355
356 void
regialloc(Node * n,Node * tn,Node * o)357 regialloc(Node *n, Node *tn, Node *o)
358 {
359 Node nod;
360
361 nod = *tn;
362 nod.type = types[TIND];
363 regalloc(n, &nod, o);
364 }
365
366 void
regfree(Node * n)367 regfree(Node *n)
368 {
369 int i;
370
371 i = 0;
372 if(n->op != OREGISTER && n->op != OINDREG)
373 goto err;
374 i = n->reg;
375 if(i < 0 || i >= sizeof(reg))
376 goto err;
377 if(reg[i] <= 0)
378 goto err;
379 reg[i]--;
380 return;
381 err:
382 diag(n, "error in regfree: %d", i);
383 }
384
385 void
regsalloc(Node * n,Node * nn)386 regsalloc(Node *n, Node *nn)
387 {
388 cursafe = align(cursafe, nn->type, Aaut3);
389 maxargsafe = maxround(maxargsafe, cursafe+curarg);
390 *n = *nodsafe;
391 n->xoffset = -(stkoff + cursafe);
392 n->type = nn->type;
393 n->etype = nn->type->etype;
394 n->lineno = nn->lineno;
395 }
396
397 void
regaalloc1(Node * n,Node * nn)398 regaalloc1(Node *n, Node *nn)
399 {
400 nodreg(n, nn, REGARG);
401 reg[REGARG]++;
402 curarg = align(curarg, nn->type, Aarg1);
403 curarg = align(curarg, nn->type, Aarg2);
404 maxargsafe = maxround(maxargsafe, cursafe+curarg);
405 }
406
407 void
regaalloc(Node * n,Node * nn)408 regaalloc(Node *n, Node *nn)
409 {
410 curarg = align(curarg, nn->type, Aarg1);
411 *n = *nn;
412 n->op = OINDREG;
413 n->reg = REGSP;
414 n->xoffset = curarg + SZ_VLONG;
415 n->complex = 0;
416 n->addable = 20;
417 curarg = align(curarg, nn->type, Aarg2);
418 maxargsafe = maxround(maxargsafe, cursafe+curarg);
419 }
420
421 void
regind(Node * n,Node * nn)422 regind(Node *n, Node *nn)
423 {
424
425 if(n->op != OREGISTER) {
426 diag(n, "regind not OREGISTER");
427 return;
428 }
429 n->op = OINDREG;
430 n->type = nn->type;
431 }
432
433 void
raddr(Node * n,Prog * p)434 raddr(Node *n, Prog *p)
435 {
436 Adr a;
437
438 naddr(n, &a);
439 if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
440 a.type = D_REG;
441 a.reg = REGZERO;
442 }
443 if(a.type != D_REG && a.type != D_FREG) {
444 if(n)
445 diag(n, "bad in raddr: %O", n->op);
446 else
447 diag(n, "bad in raddr: <null>");
448 p->reg = NREG;
449 } else
450 p->reg = a.reg;
451 }
452
453 void
naddr(Node * n,Adr * a)454 naddr(Node *n, Adr *a)
455 {
456 long v;
457
458 a->type = D_NONE;
459 if(n == Z)
460 return;
461 switch(n->op) {
462 default:
463 bad:
464 diag(n, "bad in naddr: %O", n->op);
465 break;
466
467 case OREGISTER:
468 a->type = D_REG;
469 a->sym = S;
470 a->reg = n->reg;
471 if(a->reg >= NREG) {
472 a->type = D_FREG;
473 a->reg -= NREG;
474 }
475 break;
476
477 case OIND:
478 naddr(n->left, a);
479 if(a->type == D_REG) {
480 a->type = D_OREG;
481 break;
482 }
483 if(a->type == D_CONST) {
484 a->type = D_OREG;
485 break;
486 }
487 goto bad;
488
489 case OINDREG:
490 a->type = D_OREG;
491 a->sym = S;
492 a->offset = n->xoffset;
493 a->reg = n->reg;
494 break;
495
496 case ONAME:
497 a->etype = n->etype;
498 a->type = D_OREG;
499 a->name = D_STATIC;
500 a->sym = n->sym;
501 a->offset = n->xoffset;
502 if(n->class == CSTATIC)
503 break;
504 if(n->class == CEXTERN || n->class == CGLOBL) {
505 a->name = D_EXTERN;
506 break;
507 }
508 if(n->class == CAUTO) {
509 a->name = D_AUTO;
510 break;
511 }
512 if(n->class == CPARAM) {
513 a->name = D_PARAM;
514 break;
515 }
516 goto bad;
517
518 case OCONST:
519 a->sym = S;
520 a->reg = NREG;
521 if(typefd[n->type->etype]) {
522 a->type = D_FCONST;
523 a->dval = n->fconst;
524 } else {
525 a->type = D_CONST;
526 a->offset = n->vconst;
527 }
528 break;
529
530 case OADDR:
531 naddr(n->left, a);
532 if(a->type == D_OREG) {
533 a->type = D_CONST;
534 break;
535 }
536 goto bad;
537
538 case OADD:
539 if(n->left->op == OCONST) {
540 naddr(n->left, a);
541 v = a->offset;
542 naddr(n->right, a);
543 } else {
544 naddr(n->right, a);
545 v = a->offset;
546 naddr(n->left, a);
547 }
548 a->offset += v;
549 break;
550
551 }
552 }
553
554 void
fop(int as,int f1,int f2,Node * t)555 fop(int as, int f1, int f2, Node *t)
556 {
557 Node nod1, nod2, nod3;
558
559 nodreg(&nod1, t, NREG+f1);
560 nodreg(&nod2, t, NREG+f2);
561 regalloc(&nod3, t, t);
562 gopcode(as, &nod1, &nod2, &nod3);
563 gmove(&nod3, t);
564 regfree(&nod3);
565 }
566
567 void
gmove(Node * f,Node * t)568 gmove(Node *f, Node *t)
569 {
570 int ft, tt, a;
571 Node nod, fxc0, fxc1, fxc2, fxrat;
572 Prog *p1;
573 double d;
574
575 ft = f->type->etype;
576 tt = t->type->etype;
577
578 if(ft == TDOUBLE && f->op == OCONST) {
579 d = f->fconst;
580 if(d == 0.0) {
581 a = FREGZERO;
582 goto ffreg;
583 }
584 if(d == 0.5) {
585 a = FREGHALF;
586 goto ffreg;
587 }
588 if(d == 1.0) {
589 a = FREGONE;
590 goto ffreg;
591 }
592 if(d == 2.0) {
593 a = FREGTWO;
594 goto ffreg;
595 }
596 if(d == -.5) {
597 fop(OSUB, FREGHALF, FREGZERO, t);
598 return;
599 }
600 if(d == -1.0) {
601 fop(OSUB, FREGONE, FREGZERO, t);
602 return;
603 }
604 if(d == -2.0) {
605 fop(OSUB, FREGTWO, FREGZERO, t);
606 return;
607 }
608 if(d == 1.5) {
609 fop(OADD, FREGONE, FREGHALF, t);
610 return;
611 }
612 if(d == 2.5) {
613 fop(OADD, FREGTWO, FREGHALF, t);
614 return;
615 }
616 if(d == 3.0) {
617 fop(OADD, FREGTWO, FREGONE, t);
618 return;
619 }
620 }
621 if(ft == TFLOAT && f->op == OCONST) {
622 d = f->fconst;
623 if(d == 0) {
624 a = FREGZERO;
625 ffreg:
626 nodreg(&nod, f, NREG+a);
627 gmove(&nod, t);
628 return;
629 }
630 }
631 /*
632 * a load --
633 * put it into a register then
634 * worry what to do with it.
635 */
636 if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
637 switch(ft) {
638 default:
639 if(ewidth[ft] == 4){
640 if(typeu[ft])
641 a = AMOVWZ;
642 else
643 a = AMOVW;
644 }else
645 a = AMOVD;
646 break;
647 case TINT:
648 a = AMOVW;
649 break;
650 case TUINT:
651 a = AMOVWZ;
652 break;
653 case TFLOAT:
654 a = AFMOVS;
655 break;
656 case TDOUBLE:
657 a = AFMOVD;
658 break;
659 case TCHAR:
660 a = AMOVB;
661 break;
662 case TUCHAR:
663 a = AMOVBZ;
664 break;
665 case TSHORT:
666 a = AMOVH;
667 break;
668 case TUSHORT:
669 a = AMOVHZ;
670 break;
671 }
672 regalloc(&nod, f, t);
673 gins(a, f, &nod);
674 gmove(&nod, t);
675 regfree(&nod);
676 return;
677 }
678
679 /*
680 * a store --
681 * put it into a register then
682 * store it.
683 */
684 if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
685 switch(tt) {
686 default:
687 if(ewidth[tt] == 4)
688 a = AMOVW;
689 else
690 a = AMOVD;
691 break;
692 case TINT:
693 a = AMOVW;
694 break;
695 case TUINT:
696 a = AMOVWZ;
697 break;
698 case TUCHAR:
699 a = AMOVBZ;
700 break;
701 case TCHAR:
702 a = AMOVB;
703 break;
704 case TUSHORT:
705 a = AMOVHZ;
706 break;
707 case TSHORT:
708 a = AMOVH;
709 break;
710 case TFLOAT:
711 a = AFMOVS;
712 break;
713 case TDOUBLE:
714 a = AFMOVD;
715 break;
716 }
717 if(!typefd[ft] && vconst(f) == 0) {
718 gins(a, f, t);
719 return;
720 }
721 if(ft == tt)
722 regalloc(&nod, t, f);
723 else
724 regalloc(&nod, t, Z);
725 gmove(f, &nod);
726 gins(a, &nod, t);
727 regfree(&nod);
728 return;
729 }
730
731 /*
732 * type x type cross table
733 */
734 a = AGOK;
735 switch(ft) {
736 case TDOUBLE:
737 case TFLOAT:
738 switch(tt) {
739 case TDOUBLE:
740 a = AFMOVD;
741 if(ft == TFLOAT)
742 a = AFMOVS; /* AFMOVSD */
743 break;
744 case TFLOAT:
745 a = AFRSP;
746 if(ft == TFLOAT)
747 a = AFMOVS;
748 break;
749 case TINT:
750 case TUINT:
751 case TLONG:
752 case TULONG:
753 case TIND:
754 case TSHORT:
755 case TUSHORT:
756 case TCHAR:
757 case TUCHAR:
758 /* BUG: not right for unsigned long */
759 regalloc(&nod, f, Z); /* should be type float */
760 regsalloc(&fxrat, f);
761 gins(AFCTIWZ, f, &nod);
762 gins(AFMOVD, &nod, &fxrat);
763 regfree(&nod);
764 fxrat.type = nodrat->type;
765 fxrat.etype = nodrat->etype;
766 fxrat.xoffset += 4;
767 gins(AMOVW, &fxrat, t); /* TO DO */
768 gmove(t, t);
769 return;
770 case TVLONG:
771 case TUVLONG:
772 /* BUG: not right for unsigned long */
773 regalloc(&nod, f, Z); /* should be type float */
774 regsalloc(&fxrat, f);
775 gins(AFCTIDZ, f, &nod);
776 gins(AFMOVD, &nod, &fxrat);
777 regfree(&nod);
778 fxrat.type = nodrat->type;
779 fxrat.etype = nodrat->etype;
780 gins(AMOVD, &fxrat, t);
781 gmove(t, t);
782 return;
783 }
784 break;
785 case TINT:
786 case TUINT:
787 case TLONG:
788 case TULONG:
789 switch(tt) {
790 case TDOUBLE:
791 case TFLOAT:
792 goto fxtofl;
793 case TINT:
794 case TUINT:
795 case TLONG:
796 case TULONG:
797 case TSHORT:
798 case TUSHORT:
799 case TCHAR:
800 case TUCHAR:
801 if(typeu[tt])
802 a = AMOVWZ;
803 else
804 a = AMOVW;
805 break;
806 case TVLONG:
807 case TUVLONG:
808 case TIND:
809 a = AMOVD;
810 break;
811 }
812 break;
813 case TVLONG:
814 case TUVLONG:
815 case TIND:
816 switch(tt) {
817 case TDOUBLE:
818 case TFLOAT:
819 goto fxtofl;
820 case TINT:
821 case TUINT:
822 case TLONG:
823 case TULONG:
824 case TVLONG:
825 case TUVLONG:
826 case TIND:
827 case TSHORT:
828 case TUSHORT:
829 case TCHAR:
830 case TUCHAR:
831 a = AMOVD; /* TO DO: conversion done? */
832 break;
833 }
834 break;
835 case TSHORT:
836 switch(tt) {
837 case TDOUBLE:
838 case TFLOAT:
839 goto fxtofl;
840 case TINT:
841 case TUINT:
842 case TLONG:
843 case TULONG:
844 case TVLONG:
845 case TUVLONG:
846 case TIND:
847 a = AMOVH;
848 break;
849 case TSHORT:
850 case TUSHORT:
851 case TCHAR:
852 case TUCHAR:
853 a = AMOVD;
854 break;
855 }
856 break;
857 case TUSHORT:
858 switch(tt) {
859 case TDOUBLE:
860 case TFLOAT:
861 goto fxtofl;
862 case TINT:
863 case TUINT:
864 case TLONG:
865 case TULONG:
866 case TVLONG:
867 case TUVLONG:
868 case TIND:
869 a = AMOVHZ;
870 break;
871 case TSHORT:
872 case TUSHORT:
873 case TCHAR:
874 case TUCHAR:
875 a = AMOVD;
876 break;
877 }
878 break;
879 case TCHAR:
880 switch(tt) {
881 case TDOUBLE:
882 case TFLOAT:
883 goto fxtofl;
884 case TINT:
885 case TUINT:
886 case TLONG:
887 case TULONG:
888 case TVLONG:
889 case TUVLONG:
890 case TIND:
891 case TSHORT:
892 case TUSHORT:
893 a = AMOVB;
894 break;
895 case TCHAR:
896 case TUCHAR:
897 a = AMOVD;
898 break;
899 }
900 break;
901 case TUCHAR:
902 switch(tt) {
903 case TDOUBLE:
904 case TFLOAT:
905 fxtofl:
906 /*
907 * rat[0] = 0x43300000; rat[1] = f^0x80000000;
908 * t = *(double*)rat - FREGCVI;
909 * is-unsigned(t) => if(t<0) t += 2^32;
910 * could be streamlined for int-to-float
911 */
912 regalloc(&fxc0, f, Z);
913 regalloc(&fxc2, f, Z);
914 regsalloc(&fxrat, t); /* should be type float */
915 gins(AMOVW, nodconst(0x43300000L), &fxc0);
916 gins(AMOVW, f, &fxc2);
917 gins(AMOVW, &fxc0, &fxrat);
918 gins(AXOR, nodconst(0x80000000L), &fxc2);
919 fxc1 = fxrat;
920 fxc1.type = nodrat->type;
921 fxc1.etype = nodrat->etype;
922 fxc1.xoffset += SZ_LONG;
923 gins(AMOVW, &fxc2, &fxc1);
924 regfree(&fxc2);
925 regfree(&fxc0);
926 regalloc(&nod, t, t); /* should be type float */
927 gins(AFMOVD, &fxrat, &nod);
928 nodreg(&fxc1, t, NREG+FREGCVI);
929 gins(AFSUB, &fxc1, &nod);
930 a = AFMOVD;
931 if(tt == TFLOAT)
932 a = AFRSP;
933 gins(a, &nod, t);
934 regfree(&nod);
935 if(ft == TULONG) {
936 regalloc(&nod, t, Z);
937 if(tt == TFLOAT) {
938 gins(AFCMPU, t, Z);
939 p->to.type = D_FREG;
940 p->to.reg = FREGZERO;
941 gins(ABGE, Z, Z);
942 p1 = p;
943 gins(AFMOVS, nodfconst(4294967296.), &nod);
944 gins(AFADDS, &nod, t);
945 } else {
946 gins(AFCMPU, t, Z);
947 p->to.type = D_FREG;
948 p->to.reg = FREGZERO;
949 gins(ABGE, Z, Z);
950 p1 = p;
951 gins(AFMOVD, nodfconst(4294967296.), &nod);
952 gins(AFADD, &nod, t);
953 }
954 patch(p1, pc);
955 regfree(&nod);
956 }
957 return;
958 case TINT:
959 case TUINT:
960 case TLONG:
961 case TULONG:
962 case TVLONG:
963 case TUVLONG:
964 case TIND:
965 case TSHORT:
966 case TUSHORT:
967 a = AMOVBZ;
968 break;
969 case TCHAR:
970 case TUCHAR:
971 a = AMOVD;
972 break;
973 }
974 break;
975 }
976 if(a == AGOK)
977 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
978 if(a == AMOVD || (a == AMOVW || a == AMOVWZ) && ewidth[ft] == ewidth[tt] || a == AFMOVS || a == AFMOVD)
979 if(samaddr(f, t))
980 return;
981 gins(a, f, t);
982 }
983
984 void
gins(int a,Node * f,Node * t)985 gins(int a, Node *f, Node *t)
986 {
987
988 nextpc();
989 p->as = a;
990 if(f != Z)
991 naddr(f, &p->from);
992 if(t != Z)
993 naddr(t, &p->to);
994 if(debug['g'])
995 print("%P\n", p);
996 }
997
998 void
gopcode(int o,Node * f1,Node * f2,Node * t)999 gopcode(int o, Node *f1, Node *f2, Node *t)
1000 {
1001 int a, et;
1002 Adr ta;
1003 int uns;
1004
1005 uns = 0;
1006 et = TLONG;
1007 if(f1 != Z && f1->type != T) {
1008 if(f1->op == OCONST && t != Z && t->type != T)
1009 et = t->type->etype;
1010 else
1011 et = f1->type->etype;
1012 }
1013 a = AGOK;
1014 switch(o) {
1015 case OAS:
1016 gmove(f1, t);
1017 return;
1018
1019 case OASADD:
1020 case OADD:
1021 a = AADD;
1022 if(et == TFLOAT)
1023 a = AFADDS;
1024 else
1025 if(et == TDOUBLE)
1026 a = AFADD;
1027 break;
1028
1029 case OASSUB:
1030 case OSUB:
1031 a = ASUB;
1032 if(et == TFLOAT)
1033 a = AFSUBS;
1034 else
1035 if(et == TDOUBLE)
1036 a = AFSUB;
1037 break;
1038
1039 case OASOR:
1040 case OOR:
1041 a = AOR;
1042 break;
1043
1044 case OASAND:
1045 case OAND:
1046 a = AAND;
1047 if(f1->op == OCONST)
1048 a = AANDCC;
1049 break;
1050
1051 case OASXOR:
1052 case OXOR:
1053 a = AXOR;
1054 break;
1055
1056 case OASLSHR:
1057 case OLSHR:
1058 a = ASRW;
1059 if(isv(et))
1060 a = ASRD;
1061 break;
1062
1063 case OASASHR:
1064 case OASHR:
1065 a = ASRAW;
1066 if(isv(et))
1067 a = ASRAD;
1068 break;
1069
1070 case OASASHL:
1071 case OASHL:
1072 a = ASLW;
1073 if(isv(et))
1074 a = ASLD;
1075 break;
1076
1077 case OFUNC:
1078 a = ABL;
1079 break;
1080
1081 case OASLMUL:
1082 case OLMUL:
1083 case OASMUL:
1084 case OMUL:
1085 if(et == TFLOAT) {
1086 a = AFMULS;
1087 break;
1088 } else
1089 if(et == TDOUBLE) {
1090 a = AFMUL;
1091 break;
1092 }
1093 a = AMULLW;
1094 if(isv(et))
1095 a = AMULLD;
1096 break;
1097
1098 case OASDIV:
1099 case ODIV:
1100 if(et == TFLOAT) {
1101 a = AFDIVS;
1102 break;
1103 } else
1104 if(et == TDOUBLE) {
1105 a = AFDIV;
1106 break;
1107 } else
1108 a = ADIVW;
1109 if(isv(et))
1110 a = ADIVD;
1111 break;
1112
1113 case OASMOD:
1114 case OMOD:
1115 a = AREM;
1116 if(isv(et))
1117 a = AREMD;
1118 break;
1119
1120 case OASLMOD:
1121 case OLMOD:
1122 a = AREMU;
1123 if(isv(et))
1124 a = AREMDU;
1125 break;
1126
1127 case OASLDIV:
1128 case OLDIV:
1129 a = ADIVWU;
1130 if(isv(et))
1131 a = ADIVDU;
1132 break;
1133
1134 case OCOM:
1135 a = ANOR;
1136 break;
1137
1138 case ONEG:
1139 a = ANEG;
1140 if(et == TFLOAT || et == TDOUBLE)
1141 a = AFNEG;
1142 break;
1143
1144 case OEQ:
1145 a = ABEQ;
1146 goto cmp;
1147
1148 case ONE:
1149 a = ABNE;
1150 goto cmp;
1151
1152 case OLT:
1153 a = ABLT;
1154 goto cmp;
1155
1156 case OLE:
1157 a = ABLE;
1158 goto cmp;
1159
1160 case OGE:
1161 a = ABGE;
1162 goto cmp;
1163
1164 case OGT:
1165 a = ABGT;
1166 goto cmp;
1167
1168 case OLO:
1169 a = ABLT;
1170 goto cmpu;
1171
1172 case OLS:
1173 a = ABLE;
1174 goto cmpu;
1175
1176 case OHS:
1177 a = ABGE;
1178 goto cmpu;
1179
1180 case OHI:
1181 a = ABGT;
1182 goto cmpu;
1183
1184 cmpu:
1185 uns = 1;
1186 cmp:
1187 nextpc();
1188 switch(et){
1189 case TINT:
1190 case TLONG:
1191 p->as = ACMPW;
1192 break;
1193 case TUINT:
1194 case TULONG:
1195 p->as = ACMPWU;
1196 break;
1197 case TFLOAT:
1198 case TDOUBLE:
1199 p->as = AFCMPU;
1200 break;
1201 default:
1202 p->as = uns? ACMPU: ACMP;
1203 break;
1204 }
1205 if(f1 != Z)
1206 naddr(f1, &p->from);
1207 if(t != Z)
1208 naddr(t, &p->to);
1209 if(f1 == Z || t == Z || f2 != Z)
1210 diag(Z, "bad cmp in gopcode %O", o);
1211 if(debug['g'])
1212 print("%P\n", p);
1213 f1 = Z;
1214 f2 = Z;
1215 t = Z;
1216 break;
1217 }
1218 if(a == AGOK)
1219 diag(Z, "bad in gopcode %O", o);
1220 nextpc();
1221 p->as = a;
1222 if(f1 != Z)
1223 naddr(f1, &p->from);
1224 if(f2 != Z) {
1225 naddr(f2, &ta);
1226 p->reg = ta.reg;
1227 if(ta.type == D_CONST && ta.offset == 0) {
1228 if(R0ISZERO)
1229 p->reg = REGZERO;
1230 else
1231 diag(Z, "REGZERO in gopcode %O", o);
1232 }
1233 }
1234 if(t != Z)
1235 naddr(t, &p->to);
1236 if(debug['g'])
1237 print("%P\n", p);
1238 }
1239
1240 int
samaddr(Node * f,Node * t)1241 samaddr(Node *f, Node *t)
1242 {
1243 return f->op == OREGISTER && t->op == OREGISTER && f->reg == t->reg;
1244 }
1245
1246 void
gbranch(int o)1247 gbranch(int o)
1248 {
1249 int a;
1250
1251 a = AGOK;
1252 switch(o) {
1253 case ORETURN:
1254 a = ARETURN;
1255 break;
1256 case OGOTO:
1257 a = ABR;
1258 break;
1259 }
1260 nextpc();
1261 if(a == AGOK) {
1262 diag(Z, "bad in gbranch %O", o);
1263 nextpc();
1264 }
1265 p->as = a;
1266 }
1267
1268 void
patch(Prog * op,long pc)1269 patch(Prog *op, long pc)
1270 {
1271
1272 op->to.offset = pc;
1273 op->to.type = D_BRANCH;
1274 }
1275
1276 void
gpseudo(int a,Sym * s,Node * n)1277 gpseudo(int a, Sym *s, Node *n)
1278 {
1279
1280 nextpc();
1281 p->as = a;
1282 p->from.type = D_OREG;
1283 p->from.sym = s;
1284 if(a == ATEXT)
1285 p->reg = (profileflg ? 0 : NOPROF);
1286 p->from.name = D_EXTERN;
1287 if(s->class == CSTATIC)
1288 p->from.name = D_STATIC;
1289 naddr(n, &p->to);
1290 if(a == ADATA || a == AGLOBL)
1291 pc--;
1292 }
1293
1294 int
sval(long v)1295 sval(long v)
1296 {
1297
1298 if(v >= -(1<<15) && v < (1<<15))
1299 return 1;
1300 return 0;
1301 }
1302
1303 int
sconst(Node * n)1304 sconst(Node *n)
1305 {
1306 vlong vv;
1307
1308 if(n->op == OCONST) {
1309 if(!typefd[n->type->etype]) {
1310 vv = n->vconst;
1311 if(vv >= -(((vlong)1)<<15) && vv < (((vlong)1)<<15))
1312 return 1;
1313 }
1314 }
1315 return 0;
1316 }
1317
1318 int
uconst(Node * n)1319 uconst(Node *n)
1320 {
1321 vlong vv;
1322
1323 if(n->op == OCONST) {
1324 if(!typefd[n->type->etype]) {
1325 vv = n->vconst;
1326 if(vv >= 0 && vv < (((vlong)1)<<16))
1327 return 1;
1328 }
1329 }
1330 return 0;
1331 }
1332
1333 int
immconst(Node * n)1334 immconst(Node *n)
1335 {
1336 vlong v;
1337
1338 if(n->op != OCONST || typefd[n->type->etype])
1339 return 0;
1340 v = n->vconst;
1341 if((v & 0xFFFF) == 0)
1342 v >>= 16;
1343 if(v >= 0 && v < ((vlong)1<<16))
1344 return 1;
1345 if(v >= -((vlong)1<<15) && v <= ((vlong)1<<15))
1346 return 1;
1347 return 0;
1348 }
1349
1350 long
exreg(Type * t)1351 exreg(Type *t)
1352 {
1353 long o;
1354
1355 if(typechlpv[t->etype]) {
1356 if(exregoffset <= 3)
1357 return 0;
1358 o = exregoffset;
1359 exregoffset--;
1360 return o;
1361 }
1362 if(typefd[t->etype]) {
1363 if(exfregoffset <= 16)
1364 return 0;
1365 o = exfregoffset + NREG;
1366 exfregoffset--;
1367 return o;
1368 }
1369 return 0;
1370 }
1371
1372 schar ewidth[NTYPE] =
1373 {
1374 -1, /* [TXXX] */
1375 SZ_CHAR, /* [TCHAR] */
1376 SZ_CHAR, /* [TUCHAR] */
1377 SZ_SHORT, /* [TSHORT] */
1378 SZ_SHORT, /* [TUSHORT] */
1379 SZ_INT, /* [TINT] */
1380 SZ_INT, /* [TUINT] */
1381 SZ_LONG, /* [TLONG] */
1382 SZ_LONG, /* [TULONG] */
1383 SZ_VLONG, /* [TVLONG] */
1384 SZ_VLONG, /* [TUVLONG] */
1385 SZ_FLOAT, /* [TFLOAT] */
1386 SZ_DOUBLE, /* [TDOUBLE] */
1387 SZ_IND, /* [TIND] */
1388 0, /* [TFUNC] */
1389 -1, /* [TARRAY] */
1390 0, /* [TVOID] */
1391 -1, /* [TSTRUCT] */
1392 -1, /* [TUNION] */
1393 SZ_INT, /* [TENUM] */
1394 };
1395 long ncast[NTYPE] =
1396 {
1397 0, /* [TXXX] */
1398 BCHAR|BUCHAR, /* [TCHAR] */
1399 BCHAR|BUCHAR, /* [TUCHAR] */
1400 BSHORT|BUSHORT, /* [TSHORT] */
1401 BSHORT|BUSHORT, /* [TUSHORT] */
1402 BINT|BUINT|BLONG|BULONG, /* [TINT] */
1403 BINT|BUINT|BLONG|BULONG, /* [TUINT] */
1404 BINT|BUINT|BLONG|BULONG, /* [TLONG] */
1405 BINT|BUINT|BLONG|BULONG, /* [TULONG] */
1406 BVLONG|BUVLONG|BIND, /* [TVLONG] */
1407 BVLONG|BUVLONG|BIND, /* [TUVLONG] */
1408 BFLOAT, /* [TFLOAT] */
1409 BDOUBLE, /* [TDOUBLE] */
1410 BVLONG|BUVLONG|BIND, /* [TIND] */
1411 0, /* [TFUNC] */
1412 0, /* [TARRAY] */
1413 0, /* [TVOID] */
1414 BSTRUCT, /* [TSTRUCT] */
1415 BUNION, /* [TUNION] */
1416 0, /* [TENUM] */
1417 };
1418