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