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