1 #include "gc.h"
2
3 void
ginit(void)4 ginit(void)
5 {
6 int i;
7 Type *t;
8
9 thechar = 'k';
10 thestring = "sparc";
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 = 0;
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 memset(reg, 0, sizeof(reg));
83 reg[REGZERO] = 1;
84 reg[REGLINK] = 1;
85 reg[REGTMP] = 1;
86 for(i=NREG; i<NREG+NREG; i+=2)
87 reg[i+1] = 1;
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 && i != REGTMP && i != REGLINK)
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*
nod32const(vlong v)219 nod32const(vlong v)
220 {
221 constnode.vconst = v & MASK(32);
222 return &constnode;
223 }
224
225 Node*
nodconst(long v)226 nodconst(long v)
227 {
228 constnode.vconst = v;
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 void
regalloc(Node * n,Node * tn,Node * o)261 regalloc(Node *n, Node *tn, Node *o)
262 {
263 int i, j;
264 static int lasti;
265
266 switch(tn->type->etype) {
267 case TCHAR:
268 case TUCHAR:
269 case TSHORT:
270 case TUSHORT:
271 case TINT:
272 case TUINT:
273 case TLONG:
274 case TULONG:
275 case TIND:
276 if(o != Z && o->op == OREGISTER) {
277 i = o->reg;
278 if(i > 0 && i < NREG)
279 goto out;
280 }
281 j = lasti + REGRET+1;
282 for(i=REGRET+1; i<NREG; i++) {
283 if(j >= NREG)
284 j = REGRET+1;
285 if(reg[j] == 0) {
286 i = j;
287 goto out;
288 }
289 j++;
290 }
291 diag(tn, "out of fixed registers");
292 goto err;
293
294 case TFLOAT:
295 case TDOUBLE:
296 case TVLONG:
297 if(o != Z && o->op == OREGISTER) {
298 i = o->reg;
299 if(i >= NREG && i < NREG+NREG)
300 goto out;
301 }
302 j = lasti*2 + NREG;
303 for(i=NREG; i<NREG+NREG; i+=2) {
304 if(j >= NREG+NREG)
305 j = NREG;
306 if(reg[j] == 0) {
307 i = j;
308 goto out;
309 }
310 j += 2;
311 }
312 diag(tn, "out of float registers");
313 goto err;
314 }
315 diag(tn, "unknown type in regalloc: %T", tn->type);
316 err:
317 i = 0;
318 out:
319 if(i)
320 reg[i]++;
321 lasti++;
322 if(lasti >= 5)
323 lasti = 0;
324 nodreg(n, tn, i);
325 }
326
327 void
regialloc(Node * n,Node * tn,Node * o)328 regialloc(Node *n, Node *tn, Node *o)
329 {
330 Node nod;
331
332 nod = *tn;
333 nod.type = types[TIND];
334 regalloc(n, &nod, o);
335 }
336
337 void
regfree(Node * n)338 regfree(Node *n)
339 {
340 int i;
341
342 i = 0;
343 if(n->op != OREGISTER && n->op != OINDREG)
344 goto err;
345 i = n->reg;
346 if(i < 0 || i >= sizeof(reg))
347 goto err;
348 if(reg[i] <= 0)
349 goto err;
350 reg[i]--;
351 return;
352 err:
353 diag(n, "error in regfree: %d", i);
354 }
355
356 void
regsalloc(Node * n,Node * nn)357 regsalloc(Node *n, Node *nn)
358 {
359 cursafe = align(cursafe, nn->type, Aaut3);
360 maxargsafe = maxround(maxargsafe, cursafe+curarg);
361 *n = *nodsafe;
362 n->xoffset = -(stkoff + cursafe);
363 n->type = nn->type;
364 n->etype = nn->type->etype;
365 n->lineno = nn->lineno;
366 }
367
368 void
regaalloc1(Node * n,Node * nn)369 regaalloc1(Node *n, Node *nn)
370 {
371 nodreg(n, nn, REGARG);
372 reg[REGARG]++;
373 curarg = align(curarg, nn->type, Aarg1);
374 curarg = align(curarg, nn->type, Aarg2);
375 maxargsafe = maxround(maxargsafe, cursafe+curarg);
376 }
377
378 void
regaalloc(Node * n,Node * nn)379 regaalloc(Node *n, Node *nn)
380 {
381 curarg = align(curarg, nn->type, Aarg1);
382 *n = *nn;
383 n->op = OINDREG;
384 n->reg = REGSP;
385 n->xoffset = curarg + SZ_LONG;
386 n->complex = 0;
387 n->addable = 20;
388 curarg = align(curarg, nn->type, Aarg2);
389 maxargsafe = maxround(maxargsafe, cursafe+curarg);
390 }
391
392 void
regind(Node * n,Node * nn)393 regind(Node *n, Node *nn)
394 {
395
396 if(n->op != OREGISTER) {
397 diag(n, "regind not OREGISTER");
398 return;
399 }
400 n->op = OINDREG;
401 n->type = nn->type;
402 }
403
404 void
raddr(Node * n,Prog * p)405 raddr(Node *n, Prog *p)
406 {
407 Adr a;
408
409 naddr(n, &a);
410 if(a.type == D_CONST && a.offset == 0) {
411 a.type = D_REG;
412 a.reg = 0;
413 }
414 if(a.type != D_REG && a.type != D_FREG) {
415 if(n)
416 diag(n, "bad in raddr: %O", n->op);
417 else
418 diag(n, "bad in raddr: <null>");
419 p->reg = NREG;
420 } else
421 p->reg = a.reg;
422 }
423
424 void
naddr(Node * n,Adr * a)425 naddr(Node *n, Adr *a)
426 {
427 long v;
428
429 a->type = D_NONE;
430 if(n == Z)
431 return;
432 switch(n->op) {
433 default:
434 bad:
435 diag(n, "bad in naddr: %O", n->op);
436 break;
437
438 case OREGISTER:
439 a->type = D_REG;
440 a->sym = S;
441 a->reg = n->reg;
442 if(a->reg >= NREG) {
443 a->type = D_FREG;
444 a->reg -= NREG;
445 }
446 break;
447
448 case OIND:
449 naddr(n->left, a);
450 if(a->type == D_REG) {
451 a->type = D_OREG;
452 break;
453 }
454 if(a->type == D_CONST) {
455 a->type = D_OREG;
456 break;
457 }
458 goto bad;
459
460 case OINDREG:
461 a->type = D_OREG;
462 a->sym = S;
463 a->offset = n->xoffset;
464 a->reg = n->reg;
465 break;
466
467 case ONAME:
468 a->etype = n->etype;
469 a->type = D_OREG;
470 a->name = D_STATIC;
471 a->sym = n->sym;
472 a->offset = n->xoffset;
473 if(n->class == CSTATIC)
474 break;
475 if(n->class == CEXTERN || n->class == CGLOBL) {
476 a->name = D_EXTERN;
477 break;
478 }
479 if(n->class == CAUTO) {
480 a->name = D_AUTO;
481 break;
482 }
483 if(n->class == CPARAM) {
484 a->name = D_PARAM;
485 break;
486 }
487 goto bad;
488
489 case OCONST:
490 a->sym = S;
491 a->reg = NREG;
492 if(typefd[n->type->etype]) {
493 a->type = D_FCONST;
494 a->dval = n->fconst;
495 } else {
496 a->type = D_CONST;
497 a->offset = n->vconst;
498 }
499 break;
500
501 case OADDR:
502 naddr(n->left, a);
503 if(a->type == D_OREG) {
504 a->type = D_CONST;
505 break;
506 }
507 goto bad;
508
509 case OADD:
510 if(n->left->op == OCONST) {
511 naddr(n->left, a);
512 v = a->offset;
513 naddr(n->right, a);
514 } else {
515 naddr(n->right, a);
516 v = a->offset;
517 naddr(n->left, a);
518 }
519 a->offset += v;
520 break;
521
522 }
523 }
524
525 void
fop(int as,int f1,int f2,Node * t)526 fop(int as, int f1, int f2, Node *t)
527 {
528 Node nod1, nod2, nod3;
529
530 nodreg(&nod1, t, NREG+f1);
531 nodreg(&nod2, t, NREG+f2);
532 regalloc(&nod3, t, t);
533 gopcode(as, &nod1, &nod2, &nod3);
534 gmove(&nod3, t);
535 regfree(&nod3);
536 }
537
538 void
gmove(Node * f,Node * t)539 gmove(Node *f, Node *t)
540 {
541 int ft, tt, a;
542 Node nod;
543 Prog *p1;
544 double d;
545
546 ft = f->type->etype;
547 tt = t->type->etype;
548
549 if(ft == TDOUBLE && f->op == OCONST) {
550 d = f->fconst;
551 if(d == 0.0) {
552 a = FREGZERO;
553 goto ffreg;
554 }
555 if(d == 0.5) {
556 a = FREGHALF;
557 goto ffreg;
558 }
559 if(d == 1.0) {
560 a = FREGONE;
561 goto ffreg;
562 }
563 if(d == 2.0) {
564 a = FREGTWO;
565 goto ffreg;
566 }
567 if(d == -.5) {
568 fop(OSUB, FREGHALF, FREGZERO, t);
569 return;
570 }
571 if(d == -1.0) {
572 fop(OSUB, FREGONE, FREGZERO, t);
573 return;
574 }
575 if(d == -2.0) {
576 fop(OSUB, FREGTWO, FREGZERO, t);
577 return;
578 }
579 if(d == 1.5) {
580 fop(OADD, FREGONE, FREGHALF, t);
581 return;
582 }
583 if(d == 2.5) {
584 fop(OADD, FREGTWO, FREGHALF, t);
585 return;
586 }
587 if(d == 3.0) {
588 fop(OADD, FREGTWO, FREGONE, t);
589 return;
590 }
591 }
592 if(ft == TFLOAT && f->op == OCONST) {
593 d = f->fconst;
594 if(d == 0) {
595 a = FREGZERO;
596 ffreg:
597 nodreg(&nod, f, NREG+a);
598 gmove(&nod, t);
599 return;
600 }
601 }
602 /*
603 * a load --
604 * put it into a register then
605 * worry what to do with it.
606 */
607 if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
608 switch(ft) {
609 default:
610 if(typefd[tt]) {
611 /* special case can load mem to Freg */
612 regalloc(&nod, t, t);
613 gins(AMOVW, f, &nod);
614 a = AFMOVWD;
615 if(tt == TFLOAT)
616 a = AFMOVWF;
617 gins(a, &nod, &nod);
618 gmove(&nod, t);
619 regfree(&nod);
620 return;
621 }
622 a = AMOVW;
623 break;
624 case TFLOAT:
625 a = AFMOVF;
626 break;
627 case TDOUBLE:
628 a = AFMOVD;
629 break;
630 case TCHAR:
631 a = AMOVB;
632 break;
633 case TUCHAR:
634 a = AMOVBU;
635 break;
636 case TSHORT:
637 a = AMOVH;
638 break;
639 case TUSHORT:
640 a = AMOVHU;
641 break;
642 }
643 regalloc(&nod, f, t);
644 gins(a, f, &nod);
645 gmove(&nod, t);
646 regfree(&nod);
647 return;
648 }
649
650 /*
651 * a store --
652 * put it into a register then
653 * store it.
654 */
655 if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
656 switch(tt) {
657 default:
658 if(typefd[ft]) {
659 /* special case can store mem from Freg */
660 regalloc(&nod, f, Z);
661 a = AFMOVDW;
662 if(ft == TFLOAT)
663 a = AFMOVFW;
664 gins(a, f, &nod);
665 gins(AMOVW, &nod, t);
666 regfree(&nod);
667 return;
668 }
669 a = AMOVW;
670 break;
671 case TUCHAR:
672 a = AMOVBU;
673 break;
674 case TCHAR:
675 a = AMOVB;
676 break;
677 case TUSHORT:
678 a = AMOVHU;
679 break;
680 case TSHORT:
681 a = AMOVH;
682 break;
683 case TFLOAT:
684 a = AFMOVF;
685 break;
686 case TVLONG:
687 case TDOUBLE:
688 a = AFMOVD;
689 break;
690 }
691 if(!typefd[ft] && vconst(f) == 0) {
692 gins(a, f, t);
693 return;
694 }
695 if(ft == tt)
696 regalloc(&nod, t, f);
697 else
698 regalloc(&nod, t, Z);
699 gmove(f, &nod);
700 gins(a, &nod, t);
701 regfree(&nod);
702 return;
703 }
704
705 /*
706 * type x type cross table
707 */
708 a = AGOK;
709 switch(ft) {
710 case TDOUBLE:
711 case TVLONG:
712 case TFLOAT:
713 switch(tt) {
714 case TDOUBLE:
715 case TVLONG:
716 a = AFMOVD;
717 if(ft == TFLOAT)
718 a = AFMOVFD;
719 break;
720 case TFLOAT:
721 a = AFMOVDF;
722 if(ft == TFLOAT)
723 a = AFMOVF;
724 break;
725 case TLONG:
726 case TULONG:
727 case TIND:
728 case TINT:
729 case TUINT:
730 case TSHORT:
731 case TUSHORT:
732 case TCHAR:
733 case TUCHAR:
734 regalloc(&nod, f, Z); /* should be type float */
735 a = AFMOVDW;
736 if(ft == TFLOAT)
737 a = AFMOVFW;
738 gins(a, f, &nod);
739 gins(AFMOVF, &nod, nodrat);
740 regfree(&nod);
741 gins(AMOVW, nodrat, t);
742 gmove(t, t);
743 if(nrathole < SZ_LONG)
744 nrathole = SZ_LONG;
745 return;
746 }
747 break;
748 case TINT:
749 case TUINT:
750 case TLONG:
751 case TULONG:
752 case TIND:
753 switch(tt) {
754 case TDOUBLE:
755 case TVLONG:
756 case TFLOAT:
757 goto fxtofl;
758 case TLONG:
759 case TULONG:
760 case TINT:
761 case TUINT:
762 case TIND:
763 case TSHORT:
764 case TUSHORT:
765 case TCHAR:
766 case TUCHAR:
767 a = AMOVW;
768 break;
769 }
770 break;
771 case TSHORT:
772 switch(tt) {
773 case TDOUBLE:
774 case TVLONG:
775 case TFLOAT:
776 goto fxtofl;
777 case TUINT:
778 case TINT:
779 case TULONG:
780 case TLONG:
781 case TIND:
782 a = AMOVH;
783 break;
784 case TSHORT:
785 case TUSHORT:
786 case TCHAR:
787 case TUCHAR:
788 a = AMOVW;
789 break;
790 }
791 break;
792 case TUSHORT:
793 switch(tt) {
794 case TDOUBLE:
795 case TVLONG:
796 case TFLOAT:
797 goto fxtofl;
798 case TINT:
799 case TUINT:
800 case TLONG:
801 case TULONG:
802 case TIND:
803 a = AMOVHU;
804 break;
805 case TSHORT:
806 case TUSHORT:
807 case TCHAR:
808 case TUCHAR:
809 a = AMOVW;
810 break;
811 }
812 break;
813 case TCHAR:
814 switch(tt) {
815 case TDOUBLE:
816 case TVLONG:
817 case TFLOAT:
818 goto fxtofl;
819 case TINT:
820 case TUINT:
821 case TLONG:
822 case TULONG:
823 case TIND:
824 case TSHORT:
825 case TUSHORT:
826 a = AMOVB;
827 break;
828 case TCHAR:
829 case TUCHAR:
830 a = AMOVW;
831 break;
832 }
833 break;
834 case TUCHAR:
835 switch(tt) {
836 case TDOUBLE:
837 case TVLONG:
838 case TFLOAT:
839 fxtofl:
840 regalloc(&nod, t, t); /* should be type float */
841 gins(AMOVW, f, nodrat);
842 gins(AFMOVF, nodrat, &nod);
843 a = AFMOVWD;
844 if(tt == TFLOAT)
845 a = AFMOVWF;
846 gins(a, &nod, t);
847 regfree(&nod);
848 if(nrathole < SZ_LONG)
849 nrathole = SZ_LONG;
850 if(ft == TULONG) {
851 regalloc(&nod, t, Z);
852 if(tt == TFLOAT) {
853 gins(AFCMPF, t, Z);
854 p->to.type = D_FREG;
855 p->to.reg = FREGZERO;
856 gins(AFBGE, Z, Z);
857 p1 = p;
858 gins(AFMOVF, nodfconst(4294967296.), &nod);
859 gins(AFADDF, &nod, t);
860 } else {
861 gins(AFCMPD, t, Z);
862 p->to.type = D_FREG;
863 p->to.reg = FREGZERO;
864 gins(AFBGE, Z, Z);
865 p1 = p;
866 gins(AFMOVD, nodfconst(4294967296.), &nod);
867 gins(AFADDD, &nod, t);
868 }
869 patch(p1, pc);
870 regfree(&nod);
871 }
872 return;
873 case TINT:
874 case TUINT:
875 case TLONG:
876 case TULONG:
877 case TIND:
878 case TSHORT:
879 case TUSHORT:
880 a = AMOVBU;
881 break;
882 case TCHAR:
883 case TUCHAR:
884 a = AMOVW;
885 break;
886 }
887 break;
888 }
889 if(a == AGOK)
890 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
891 if(a == AMOVW || a == AFMOVF || a == AFMOVD)
892 if(samaddr(f, t))
893 return;
894 gins(a, f, t);
895 }
896
897 void
gins(int a,Node * f,Node * t)898 gins(int a, Node *f, Node *t)
899 {
900
901 nextpc();
902 p->as = a;
903 if(f != Z)
904 naddr(f, &p->from);
905 if(t != Z)
906 naddr(t, &p->to);
907 if(debug['g'])
908 print("%P\n", p);
909 }
910
911 void
gopcode(int o,Node * f1,Node * f2,Node * t)912 gopcode(int o, Node *f1, Node *f2, Node *t)
913 {
914 int a, et;
915 Adr ta;
916
917 et = TLONG;
918 if(f1 != Z && f1->type != T)
919 et = f1->type->etype;
920 a = AGOK;
921 switch(o) {
922 case OAS:
923 gmove(f1, t);
924 return;
925
926 case OASADD:
927 case OADD:
928 a = AADD;
929 if(et == TFLOAT)
930 a = AFADDF;
931 else
932 if(et == TDOUBLE || et == TVLONG)
933 a = AFADDD;
934 break;
935
936 case OASSUB:
937 case OSUB:
938 a = ASUB;
939 if(et == TFLOAT)
940 a = AFSUBF;
941 else
942 if(et == TDOUBLE || et == TVLONG)
943 a = AFSUBD;
944 break;
945
946 case OASOR:
947 case OOR:
948 a = AOR;
949 break;
950
951 case OASAND:
952 case OAND:
953 a = AAND;
954 break;
955
956 case OASXOR:
957 case OXOR:
958 a = AXOR;
959 break;
960
961 case OASLSHR:
962 case OLSHR:
963 a = ASRL;
964 break;
965
966 case OASASHR:
967 case OASHR:
968 a = ASRA;
969 break;
970
971 case OASASHL:
972 case OASHL:
973 a = ASLL;
974 break;
975
976 case OFUNC:
977 a = AJMPL;
978 break;
979
980 case OASLMUL:
981 case OLMUL:
982 case OASMUL:
983 case OMUL:
984 if(et == TFLOAT) {
985 a = AFMULF;
986 break;
987 } else
988 if(et == TDOUBLE || et == TVLONG) {
989 a = AFMULD;
990 break;
991 }
992 a = AMUL;
993 break;
994
995 case OASDIV:
996 case ODIV:
997 if(et == TFLOAT) {
998 a = AFDIVF;
999 break;
1000 } else
1001 if(et == TDOUBLE || et == TVLONG) {
1002 a = AFDIVD;
1003 break;
1004 }
1005 a = ADIV;
1006 break;
1007
1008 case OASMOD:
1009 case OMOD:
1010 a = AMOD;
1011 break;
1012
1013 case OASLMOD:
1014 case OLMOD:
1015 a = AMODL;
1016 break;
1017
1018 case OASLDIV:
1019 case OLDIV:
1020 a = ADIVL;
1021 break;
1022
1023 case OEQ:
1024 a = ABE;
1025 if(typefd[et])
1026 a = AFBE;
1027 goto cmp;
1028
1029 case ONE:
1030 a = ABNE;
1031 if(typefd[et])
1032 a = AFBLG;
1033 goto cmp;
1034
1035 case OLT:
1036 a = ABL;
1037 if(typefd[et])
1038 a = AFBL;
1039 goto cmp;
1040
1041 case OLE:
1042 a = ABLE;
1043 if(typefd[et])
1044 a = AFBLE;
1045 goto cmp;
1046
1047 case OGE:
1048 a = ABGE;
1049 if(typefd[et])
1050 a = AFBGE;
1051 goto cmp;
1052
1053 case OGT:
1054 a = ABG;
1055 if(typefd[et])
1056 a = AFBG;
1057 goto cmp;
1058
1059 case OLO:
1060 a = ABCS;
1061 goto cmp;
1062
1063 case OLS:
1064 a = ABLEU;
1065 goto cmp;
1066
1067 case OHS:
1068 a = ABCC;
1069 goto cmp;
1070
1071 case OHI:
1072 a = ABGU;
1073 goto cmp;
1074
1075 cmp:
1076 nextpc();
1077 p->as = ACMP;
1078 if(et == TFLOAT)
1079 p->as = AFCMPF;
1080 else
1081 if(et == TDOUBLE || et == TVLONG)
1082 p->as = AFCMPD;
1083 if(f1 != Z)
1084 naddr(f1, &p->from);
1085 if(t != Z)
1086 naddr(t, &p->to);
1087 if(f1 == Z || t == Z || f2 != Z)
1088 diag(Z, "bad cmp in gopcode %O", o);
1089 if(debug['g'])
1090 print("%P\n", p);
1091 f1 = Z;
1092 f2 = Z;
1093 t = Z;
1094 break;
1095 }
1096 if(a == AGOK)
1097 diag(Z, "bad in gopcode %O", o);
1098 nextpc();
1099 p->as = a;
1100 if(f1 != Z)
1101 naddr(f1, &p->from);
1102 if(f2 != Z) {
1103 naddr(f2, &ta);
1104 p->reg = ta.reg;
1105 if(ta.type == D_CONST && ta.offset == 0)
1106 p->reg = REGZERO;
1107 }
1108 if(t != Z)
1109 naddr(t, &p->to);
1110 if(debug['g'])
1111 print("%P\n", p);
1112 }
1113
samaddr(Node * f,Node * t)1114 samaddr(Node *f, Node *t)
1115 {
1116
1117 if(f->op != t->op)
1118 return 0;
1119 switch(f->op) {
1120
1121 case OREGISTER:
1122 if(f->reg != t->reg)
1123 break;
1124 return 1;
1125 }
1126 return 0;
1127 }
1128
1129 void
gbranch(int o)1130 gbranch(int o)
1131 {
1132 int a;
1133
1134 a = AGOK;
1135 switch(o) {
1136 case ORETURN:
1137 a = ARETURN;
1138 break;
1139 case OGOTO:
1140 a = AJMP;
1141 break;
1142 }
1143 nextpc();
1144 if(a == AGOK) {
1145 diag(Z, "bad in gbranch %O", o);
1146 nextpc();
1147 }
1148 p->as = a;
1149 }
1150
1151 void
patch(Prog * op,long pc)1152 patch(Prog *op, long pc)
1153 {
1154
1155 op->to.offset = pc;
1156 op->to.type = D_BRANCH;
1157 }
1158
1159 void
gpseudo(int a,Sym * s,Node * n)1160 gpseudo(int a, Sym *s, Node *n)
1161 {
1162
1163 nextpc();
1164 p->as = a;
1165 p->from.type = D_OREG;
1166 p->from.sym = s;
1167 if(a == ATEXT)
1168 p->reg = (profileflg ? 0 : NOPROF);
1169 p->from.name = D_EXTERN;
1170 if(s->class == CSTATIC)
1171 p->from.name = D_STATIC;
1172 naddr(n, &p->to);
1173 if(a == ADATA || a == AGLOBL)
1174 pc--;
1175 }
1176
1177 int
sval(long v)1178 sval(long v)
1179 {
1180
1181 if(v >= -(1<<12) && v < (1<<12))
1182 return 1;
1183 return 0;
1184 }
1185
1186 int
sconst(Node * n)1187 sconst(Node *n)
1188 {
1189 vlong vv;
1190
1191 if(n->op == OCONST) {
1192 if(!typefd[n->type->etype]) {
1193 vv = n->vconst;
1194 if(vv >= -(vlong)(1<<12) && vv < (vlong)(1<<12))
1195 return 1;
1196 }
1197 }
1198 return 0;
1199 }
1200
1201 long
exreg(Type * t)1202 exreg(Type *t)
1203 {
1204 long o;
1205
1206 if(typechlp[t->etype]) {
1207 if(exregoffset <= 3)
1208 return 0;
1209 o = exregoffset;
1210 exregoffset--;
1211 return o;
1212 }
1213 if(typefd[t->etype]) {
1214 if(exfregoffset <= 16)
1215 return 0;
1216 o = exfregoffset + NREG;
1217 exfregoffset--;
1218 return o;
1219 }
1220 return 0;
1221 }
1222
1223 schar ewidth[NTYPE] =
1224 {
1225 -1, /* [TXXX] */
1226 SZ_CHAR, /* [TCHAR] */
1227 SZ_CHAR, /* [TUCHAR] */
1228 SZ_SHORT, /* [TSHORT] */
1229 SZ_SHORT, /* [TUSHORT] */
1230 SZ_INT, /* [TINT] */
1231 SZ_INT, /* [TUINT] */
1232 SZ_LONG, /* [TLONG] */
1233 SZ_LONG, /* [TULONG] */
1234 SZ_VLONG, /* [TVLONG] */
1235 SZ_VLONG, /* [TUVLONG] */
1236 SZ_FLOAT, /* [TFLOAT] */
1237 SZ_DOUBLE, /* [TDOUBLE] */
1238 SZ_IND, /* [TIND] */
1239 0, /* [TFUNC] */
1240 -1, /* [TARRAY] */
1241 0, /* [TVOID] */
1242 -1, /* [TSTRUCT] */
1243 -1, /* [TUNION] */
1244 SZ_INT, /* [TENUM] */
1245 };
1246
1247 long ncast[NTYPE] =
1248 {
1249 0, /* [TXXX] */
1250 BCHAR|BUCHAR, /* [TCHAR] */
1251 BCHAR|BUCHAR, /* [TUCHAR] */
1252 BSHORT|BUSHORT, /* [TSHORT] */
1253 BSHORT|BUSHORT, /* [TUSHORT] */
1254 BINT|BUINT|BLONG|BULONG|BIND, /* [TINT] */
1255 BINT|BUINT|BLONG|BULONG|BIND, /* [TUINT] */
1256 BINT|BUINT|BLONG|BULONG|BIND, /* [TLONG] */
1257 BINT|BUINT|BLONG|BULONG|BIND, /* [TULONG] */
1258 BVLONG|BUVLONG, /* [TVLONG] */
1259 BVLONG|BUVLONG, /* [TUVLONG] */
1260 BFLOAT, /* [TFLOAT] */
1261 BDOUBLE, /* [TDOUBLE] */
1262 BLONG|BULONG|BIND, /* [TIND] */
1263 0, /* [TFUNC] */
1264 0, /* [TARRAY] */
1265 0, /* [TVOID] */
1266 BSTRUCT, /* [TSTRUCT] */
1267 BUNION, /* [TUNION] */
1268 0, /* [TENUM] */
1269 };
1270