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