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