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