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