1 #include "gc.h"
2
3 static int resvreg[nelem(reg)];
4
5 static void gopcode64(int, Node*, Node*, Node*);
6 static void gori64(int, Node*, Node*, Node*);
7 static void gandi64(int, Node*, Node*, Node*);
8
9 void
ginit(void)10 ginit(void)
11 {
12 Type *t;
13
14 thechar = 'q';
15 thestring = "power";
16 exregoffset = REGEXT;
17 exfregoffset = FREGEXT;
18 newvlongcode = 1;
19 listinit();
20 nstring = 0;
21 mnstring = 0;
22 nrathole = 0;
23 pc = 0;
24 breakpc = -1;
25 continpc = -1;
26 cases = C;
27 firstp = P;
28 lastp = P;
29 tfield = types[TLONG];
30
31 typeswitch = typechlv;
32
33 zprog.link = P;
34 zprog.as = AGOK;
35 zprog.reg = NREG;
36 zprog.from.type = D_NONE;
37 zprog.from.name = D_NONE;
38 zprog.from.reg = NREG;
39 zprog.from3 = zprog.from;
40 zprog.to = zprog.from;
41
42 regnode.op = OREGISTER;
43 regnode.class = CEXREG;
44 regnode.reg = 0;
45 regnode.complex = 0;
46 regnode.addable = 11;
47 regnode.type = types[TLONG];
48
49 constnode.op = OCONST;
50 constnode.class = CXXX;
51 constnode.complex = 0;
52 constnode.addable = 20;
53 constnode.type = types[TLONG];
54
55 fconstnode.op = OCONST;
56 fconstnode.class = CXXX;
57 fconstnode.complex = 0;
58 fconstnode.addable = 20;
59 fconstnode.type = types[TDOUBLE];
60
61 nodsafe = new(ONAME, Z, Z);
62 nodsafe->sym = slookup(".safe");
63 nodsafe->type = types[TINT];
64 nodsafe->etype = types[TINT]->etype;
65 nodsafe->class = CAUTO;
66 complex(nodsafe);
67
68 t = typ(TARRAY, types[TCHAR]);
69 symrathole = slookup(".rathole");
70 symrathole->class = CGLOBL;
71 symrathole->type = t;
72
73 nodrat = new(ONAME, Z, Z);
74 nodrat->sym = symrathole;
75 nodrat->type = types[TIND];
76 nodrat->etype = TVOID;
77 nodrat->class = CGLOBL;
78 complex(nodrat);
79 nodrat->type = t;
80
81 com64init();
82
83 memset(reg, 0, sizeof(reg));
84 reg[REGZERO] = 1; /* don't use */
85 reg[REGTMP] = 1;
86 reg[FREGCVI+NREG] = 1;
87 reg[FREGZERO+NREG] = 1;
88 reg[FREGHALF+NREG] = 1;
89 reg[FREGONE+NREG] = 1;
90 reg[FREGTWO+NREG] = 1;
91 memmove(resvreg, reg, sizeof(reg));
92 }
93
94 void
gclean(void)95 gclean(void)
96 {
97 int i;
98 Sym *s;
99
100 for(i=0; i<NREG; i++)
101 if(reg[i] && !resvreg[i])
102 diag(Z, "reg %d left allocated", i);
103 for(i=NREG; i<NREG+NREG; i++)
104 if(reg[i] && !resvreg[i])
105 diag(Z, "freg %d left allocated", i-NREG);
106 while(mnstring)
107 outstring("", 1L);
108 symstring->type->width = nstring;
109 symrathole->type->width = nrathole;
110 for(i=0; i<NHASH; i++)
111 for(s = hash[i]; s != S; s = s->link) {
112 if(s->type == T)
113 continue;
114 if(s->type->width == 0)
115 continue;
116 if(s->class != CGLOBL && s->class != CSTATIC)
117 continue;
118 if(s->type == types[TENUM])
119 continue;
120 gpseudo(AGLOBL, s, nodconst(s->type->width));
121 }
122 nextpc();
123 p->as = AEND;
124 outcode();
125 }
126
127 void
nextpc(void)128 nextpc(void)
129 {
130
131 p = alloc(sizeof(*p));
132 *p = zprog;
133 p->lineno = nearln;
134 pc++;
135 if(firstp == P) {
136 firstp = p;
137 lastp = p;
138 return;
139 }
140 lastp->link = p;
141 lastp = p;
142 }
143
144 void
gargs(Node * n,Node * tn1,Node * tn2)145 gargs(Node *n, Node *tn1, Node *tn2)
146 {
147 long regs;
148 Node fnxargs[20], *fnxp;
149
150 regs = cursafe;
151
152 fnxp = fnxargs;
153 garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */
154
155 curarg = 0;
156 fnxp = fnxargs;
157 garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */
158
159 cursafe = regs;
160 }
161
162 void
garg1(Node * n,Node * tn1,Node * tn2,int f,Node ** fnxp)163 garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
164 {
165 Node nod;
166
167 if(n == Z)
168 return;
169 if(n->op == OLIST) {
170 garg1(n->left, tn1, tn2, f, fnxp);
171 garg1(n->right, tn1, tn2, f, fnxp);
172 return;
173 }
174 if(f == 0) {
175 if(n->complex >= FNX) {
176 regsalloc(*fnxp, n);
177 nod = znode;
178 nod.op = OAS;
179 nod.left = *fnxp;
180 nod.right = n;
181 nod.type = n->type;
182 cgen(&nod, Z);
183 (*fnxp)++;
184 }
185 return;
186 }
187 if(typesuv[n->type->etype]) {
188 regaalloc(tn2, n);
189 if(n->complex >= FNX) {
190 cgen(*fnxp, tn2);
191 (*fnxp)++;
192 } else
193 cgen(n, tn2);
194 return;
195 }
196 if(REGARG && curarg == 0 && typechlp[n->type->etype]) {
197 regaalloc1(tn1, n);
198 if(n->complex >= FNX) {
199 cgen(*fnxp, tn1);
200 (*fnxp)++;
201 } else
202 cgen(n, tn1);
203 return;
204 }
205 if(vconst(n) == 0) {
206 regaalloc(tn2, n);
207 gopcode(OAS, n, Z, tn2);
208 return;
209 }
210 regalloc(tn1, n, Z);
211 if(n->complex >= FNX) {
212 cgen(*fnxp, tn1);
213 (*fnxp)++;
214 } else
215 cgen(n, tn1);
216 regaalloc(tn2, n);
217 gopcode(OAS, tn1, Z, tn2);
218 regfree(tn1);
219 }
220
221 Node*
nod32const(vlong v)222 nod32const(vlong v)
223 {
224 constnode.vconst = v & MASK(32);
225 return &constnode;
226 }
227
228 Node*
nodconst(long v)229 nodconst(long v)
230 {
231 constnode.vconst = v;
232 return &constnode;
233 }
234
235 Node*
nodfconst(double d)236 nodfconst(double d)
237 {
238 fconstnode.fconst = d;
239 return &fconstnode;
240 }
241
242 void
nodreg(Node * n,Node * nn,int reg)243 nodreg(Node *n, Node *nn, int reg)
244 {
245 *n = regnode;
246 n->reg = reg;
247 n->type = nn->type;
248 n->lineno = nn->lineno;
249 }
250
251 void
regret(Node * n,Node * nn)252 regret(Node *n, Node *nn)
253 {
254 int r;
255
256 r = REGRET;
257 if(typefd[nn->type->etype])
258 r = FREGRET+NREG;
259 nodreg(n, nn, r);
260 reg[r]++;
261 }
262
263 void
regalloc(Node * n,Node * tn,Node * o)264 regalloc(Node *n, Node *tn, Node *o)
265 {
266 int i, j;
267 static int lasti;
268
269 switch(tn->type->etype) {
270 case TCHAR:
271 case TUCHAR:
272 case TSHORT:
273 case TUSHORT:
274 case TINT:
275 case TUINT:
276 case TLONG:
277 case TULONG:
278 case TIND:
279 if(o != Z && o->op == OREGISTER) {
280 i = o->reg;
281 if(i > 0 && i < NREG)
282 goto out;
283 }
284 j = lasti + REGRET+1;
285 for(i=REGRET+1; i<NREG; i++) {
286 if(j >= NREG)
287 j = REGRET+1;
288 if(reg[j] == 0) {
289 i = j;
290 goto out;
291 }
292 j++;
293 }
294 diag(tn, "out of fixed registers");
295 goto err;
296
297 case TFLOAT:
298 case TDOUBLE:
299 if(o != Z && o->op == OREGISTER) {
300 i = o->reg;
301 if(i >= NREG && i < NREG+NREG)
302 goto out;
303 }
304 j = lasti + NREG;
305 for(i=NREG; i<NREG+NREG; i++) {
306 if(j >= NREG+NREG)
307 j = NREG;
308 if(reg[j] == 0) {
309 i = j;
310 goto out;
311 }
312 j++;
313 }
314 diag(tn, "out of float registers");
315 goto err;
316
317 case TVLONG:
318 case TUVLONG:
319 n->op = OREGPAIR;
320 n->complex = 0; /* already in registers */
321 n->addable = 11;
322 n->type = tn->type;
323 n->lineno = nearln;
324 n->left = alloc(sizeof(Node));
325 n->right = alloc(sizeof(Node));
326 if(o != Z && o->op == OREGPAIR) {
327 regalloc(n->left, ®node, o->left);
328 regalloc(n->right, ®node, o->right);
329 } else {
330 regalloc(n->left, ®node, Z);
331 regalloc(n->right, ®node, Z);
332 }
333 n->right->type = types[TULONG];
334 if(tn->type->etype == TUVLONG)
335 n->left->type = types[TULONG]; /* TO DO: is this a bad idea? */
336 return;
337 }
338 diag(tn, "unknown type in regalloc: %T", tn->type);
339 err:
340 i = 0;
341 out:
342 if(i)
343 reg[i]++;
344 lasti++;
345 if(lasti >= 5)
346 lasti = 0;
347 nodreg(n, tn, i);
348 }
349
350 void
regialloc(Node * n,Node * tn,Node * o)351 regialloc(Node *n, Node *tn, Node *o)
352 {
353 Node nod;
354
355 nod = *tn;
356 nod.type = types[TIND];
357 regalloc(n, &nod, o);
358 }
359
360 void
regfree(Node * n)361 regfree(Node *n)
362 {
363 int i;
364
365 if(n->op == OREGPAIR) {
366 regfree(n->left);
367 regfree(n->right);
368 return;
369 }
370 i = 0;
371 if(n->op != OREGISTER && n->op != OINDREG)
372 goto err;
373 i = n->reg;
374 if(i < 0 || i >= sizeof(reg))
375 goto err;
376 if(reg[i] <= 0)
377 goto err;
378 reg[i]--;
379 return;
380 err:
381 diag(n, "error in regfree: %d [%d]", i, reg[i]);
382 prtree(n, "regfree");
383 }
384
385 void
regsalloc(Node * n,Node * nn)386 regsalloc(Node *n, Node *nn)
387 {
388 cursafe = align(cursafe+stkoff, nn->type, Aaut3)-stkoff;
389 maxargsafe = maxround(maxargsafe, cursafe+curarg);
390 // if(nn->type->etype == TDOUBLE || nn->type->etype == TVLONG){
391 // extern int hasdoubled;
392 // fprint(2, "stkoff=%ld cursafe=%ld curarg=%ld %d\n", stkoff, cursafe, curarg, hasdoubled);
393 // }
394 *n = *nodsafe;
395 n->xoffset = -(stkoff + cursafe);
396 n->type = nn->type;
397 n->etype = nn->type->etype;
398 n->lineno = nn->lineno;
399 }
400
401 void
regaalloc1(Node * n,Node * nn)402 regaalloc1(Node *n, Node *nn)
403 {
404 nodreg(n, nn, REGARG);
405 reg[REGARG]++;
406 curarg = align(curarg, nn->type, Aarg1);
407 curarg = align(curarg, nn->type, Aarg2);
408 maxargsafe = maxround(maxargsafe, cursafe+curarg);
409 }
410
411 void
regaalloc(Node * n,Node * nn)412 regaalloc(Node *n, Node *nn)
413 {
414 curarg = align(curarg, nn->type, Aarg1);
415 *n = *nn;
416 n->op = OINDREG;
417 n->reg = REGSP;
418 n->xoffset = curarg + SZ_LONG;
419 n->complex = 0;
420 n->addable = 20;
421 curarg = align(curarg, nn->type, Aarg2);
422 maxargsafe = maxround(maxargsafe, cursafe+curarg);
423 }
424
425 void
regind(Node * n,Node * nn)426 regind(Node *n, Node *nn)
427 {
428
429 if(n->op != OREGISTER) {
430 diag(n, "regind not OREGISTER");
431 return;
432 }
433 n->op = OINDREG;
434 n->type = nn->type;
435 }
436
437 void
raddr(Node * n,Prog * p)438 raddr(Node *n, Prog *p)
439 {
440 Adr a;
441
442 naddr(n, &a);
443 if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
444 a.type = D_REG;
445 a.reg = REGZERO;
446 }
447 if(a.type != D_REG && a.type != D_FREG) {
448 if(n)
449 diag(n, "bad in raddr: %O", n->op);
450 else
451 diag(n, "bad in raddr: <null>");
452 p->reg = NREG;
453 } else
454 p->reg = a.reg;
455 }
456
457 void
naddr(Node * n,Adr * a)458 naddr(Node *n, Adr *a)
459 {
460 long v;
461
462 a->type = D_NONE;
463 if(n == Z)
464 return;
465 switch(n->op) {
466 default:
467 bad:
468 diag(n, "bad in naddr: %O", n->op);
469 break;
470
471 case OREGISTER:
472 a->type = D_REG;
473 a->sym = S;
474 a->reg = n->reg;
475 if(a->reg >= NREG) {
476 a->type = D_FREG;
477 a->reg -= NREG;
478 }
479 break;
480
481 case OIND:
482 naddr(n->left, a);
483 a->offset += n->xoffset; /* little hack for reglcgenv */
484 if(a->type == D_REG) {
485 a->type = D_OREG;
486 break;
487 }
488 if(a->type == D_CONST) {
489 a->type = D_OREG;
490 break;
491 }
492 goto bad;
493
494 case OINDREG:
495 a->type = D_OREG;
496 a->sym = S;
497 a->offset = n->xoffset;
498 a->reg = n->reg;
499 break;
500
501 case ONAME:
502 a->etype = n->etype;
503 a->type = D_OREG;
504 a->name = D_STATIC;
505 a->sym = n->sym;
506 a->offset = n->xoffset;
507 if(n->class == CSTATIC)
508 break;
509 if(n->class == CEXTERN || n->class == CGLOBL) {
510 a->name = D_EXTERN;
511 break;
512 }
513 if(n->class == CAUTO) {
514 a->name = D_AUTO;
515 break;
516 }
517 if(n->class == CPARAM) {
518 a->name = D_PARAM;
519 break;
520 }
521 goto bad;
522
523 case OCONST:
524 a->sym = S;
525 a->reg = NREG;
526 if(typefd[n->type->etype]) {
527 a->type = D_FCONST;
528 a->dval = n->fconst;
529 } else {
530 a->type = D_CONST;
531 a->offset = n->vconst;
532 }
533 break;
534
535 case OADDR:
536 naddr(n->left, a);
537 if(a->type == D_OREG) {
538 a->type = D_CONST;
539 break;
540 }
541 goto bad;
542
543 case OADD:
544 if(n->left->op == OCONST) {
545 naddr(n->left, a);
546 v = a->offset;
547 naddr(n->right, a);
548 } else {
549 naddr(n->right, a);
550 v = a->offset;
551 naddr(n->left, a);
552 }
553 a->offset += v;
554 break;
555
556 }
557 }
558
559 void
gloadhi(Node * f,Node * t,int c)560 gloadhi(Node *f, Node *t, int c)
561 {
562 Type *ot;
563
564 if(f->op == OCONST){
565 f = nodconst((long)(f->vconst>>32));
566 if(c==1 && sconst(f) || c==2 && uconst(f)){
567 if(t->op == OREGISTER)
568 regfree(t);
569 *t = *f;
570 return;
571 }
572 }
573 if(f->op == OREGPAIR) {
574 gmove(f->left, t);
575 return;
576 }
577 ot = f->type;
578 f->type = types[TLONG];
579 gmove(f, t);
580 f->type = ot;
581 }
582
583 void
gloadlo(Node * f,Node * t,int c)584 gloadlo(Node *f, Node *t, int c)
585 {
586 Type *ot;
587
588 if(f->op == OCONST){
589 f = nodconst((long)f->vconst);
590 if(c && uconst(f)){
591 if(t->op == OREGISTER)
592 regfree(t);
593 *t = *f;
594 return;
595 }
596 }
597 if(f->op == OREGPAIR) {
598 gmove(f->right, t);
599 return;
600 }
601 ot = f->type;
602 f->type = types[TLONG];
603 f->xoffset += SZ_LONG;
604 if(0){
605 prtree(f, "gloadlo f"); prtree(t, "gloadlo t");
606 }
607 gmove(f, t);
608 f->xoffset -= SZ_LONG;
609 f->type = ot;
610 }
611
612 void
fop(int as,int f1,int f2,Node * t)613 fop(int as, int f1, int f2, Node *t)
614 {
615 Node nod1, nod2, nod3;
616
617 nodreg(&nod1, t, NREG+f1);
618 nodreg(&nod2, t, NREG+f2);
619 regalloc(&nod3, t, t);
620 gopcode(as, &nod1, &nod2, &nod3);
621 gmove(&nod3, t);
622 regfree(&nod3);
623 }
624
625 void
gmove(Node * f,Node * t)626 gmove(Node *f, Node *t)
627 {
628 int ft, tt, a;
629 Node nod, fxc0, fxc1, fxc2, fxrat;
630 Prog *p1;
631 double d;
632
633 ft = f->type->etype;
634 tt = t->type->etype;
635
636 if(ft == TDOUBLE && f->op == OCONST) {
637 d = f->fconst;
638 if(d == 0.0) {
639 a = FREGZERO;
640 goto ffreg;
641 }
642 if(d == 0.5) {
643 a = FREGHALF;
644 goto ffreg;
645 }
646 if(d == 1.0) {
647 a = FREGONE;
648 goto ffreg;
649 }
650 if(d == 2.0) {
651 a = FREGTWO;
652 goto ffreg;
653 }
654 if(d == -.5) {
655 fop(OSUB, FREGHALF, FREGZERO, t);
656 return;
657 }
658 if(d == -1.0) {
659 fop(OSUB, FREGONE, FREGZERO, t);
660 return;
661 }
662 if(d == -2.0) {
663 fop(OSUB, FREGTWO, FREGZERO, t);
664 return;
665 }
666 if(d == 1.5) {
667 fop(OADD, FREGONE, FREGHALF, t);
668 return;
669 }
670 if(d == 2.5) {
671 fop(OADD, FREGTWO, FREGHALF, t);
672 return;
673 }
674 if(d == 3.0) {
675 fop(OADD, FREGTWO, FREGONE, t);
676 return;
677 }
678 }
679 if(ft == TFLOAT && f->op == OCONST) {
680 d = f->fconst;
681 if(d == 0) {
682 a = FREGZERO;
683 ffreg:
684 nodreg(&nod, f, NREG+a);
685 gmove(&nod, t);
686 return;
687 }
688 }
689 if((ft == TVLONG || ft == TUVLONG) && f->op == OCONST && t->op == OREGPAIR) {
690 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
691 gmove(nod32const(f->vconst>>32), t->left);
692 else
693 gmove(nod32const(f->vconst), t->left);
694 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
695 gmove(nod32const(f->vconst), t->right);
696 else
697 gmove(nod32const(f->vconst>>32), t->right);
698 return;
699 }
700 /*
701 * a load --
702 * put it into a register then
703 * worry what to do with it.
704 */
705 if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
706 switch(ft) {
707 default:
708 a = AMOVW;
709 break;
710 case TFLOAT:
711 a = AFMOVS;
712 break;
713 case TDOUBLE:
714 a = AFMOVD;
715 break;
716 case TCHAR:
717 a = AMOVB;
718 break;
719 case TUCHAR:
720 a = AMOVBZ;
721 break;
722 case TSHORT:
723 a = AMOVH;
724 break;
725 case TUSHORT:
726 a = AMOVHZ;
727 break;
728 }
729 if(typev[ft]) {
730 if(typev[tt]) {
731 regalloc(&nod, f, t);
732 /* low order first, because its value will be used first */
733 f->xoffset += SZ_LONG;
734 gins(AMOVW, f, nod.right);
735 f->xoffset -= SZ_LONG;
736 gins(AMOVW, f, nod.left);
737 } else {
738 /* assumed not float or double */
739 regalloc(&nod, ®node, t);
740 f->xoffset += SZ_LONG;
741 gins(AMOVW, f, &nod);
742 f->xoffset -= SZ_LONG;
743 }
744 } else {
745 regalloc(&nod, f, t);
746 gins(a, f, &nod);
747 }
748 gmove(&nod, t);
749 regfree(&nod);
750 return;
751 }
752
753 /*
754 * a store --
755 * put it into a register then
756 * store it.
757 */
758 if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
759 switch(tt) {
760 default:
761 a = AMOVW;
762 break;
763 case TUCHAR:
764 a = AMOVBZ;
765 break;
766 case TCHAR:
767 a = AMOVB;
768 break;
769 case TUSHORT:
770 a = AMOVHZ;
771 break;
772 case TSHORT:
773 a = AMOVH;
774 break;
775 case TFLOAT:
776 a = AFMOVS;
777 break;
778 case TDOUBLE:
779 a = AFMOVD;
780 break;
781 }
782 if(R0ISZERO && !typefd[ft] && vconst(f) == 0) {
783 gins(a, f, t);
784 if(typev[tt]) {
785 t->xoffset += SZ_LONG;
786 gins(a, f, t);
787 t->xoffset -= SZ_LONG;
788 }
789 return;
790 }
791 if(ft == tt)
792 regalloc(&nod, t, f);
793 else
794 regalloc(&nod, t, Z);
795 gmove(f, &nod);
796 if(typev[tt]) {
797 t->xoffset += SZ_LONG;
798 gins(a, nod.right, t);
799 t->xoffset -= SZ_LONG;
800 gins(a, nod.left, t);
801 } else
802 gins(a, &nod, t);
803 regfree(&nod);
804 return;
805 }
806
807 /*
808 * type x type cross table
809 */
810 a = AGOK;
811 switch(ft) {
812 case TDOUBLE:
813 case TFLOAT:
814 switch(tt) {
815 case TDOUBLE:
816 a = AFMOVD;
817 if(ft == TFLOAT)
818 a = AFMOVS; /* AFMOVSD */
819 break;
820 case TFLOAT:
821 a = AFRSP;
822 if(ft == TFLOAT)
823 a = AFMOVS;
824 break;
825 case TINT:
826 case TUINT:
827 case TLONG:
828 case TULONG:
829 case TIND:
830 case TSHORT:
831 case TUSHORT:
832 case TCHAR:
833 case TUCHAR:
834 /* BUG: not right for unsigned long */
835 regalloc(&nod, f, Z); /* should be type float */
836 regsalloc(&fxrat, &fconstnode);
837 gins(AFCTIWZ, f, &nod);
838 gins(AFMOVD, &nod, &fxrat);
839 regfree(&nod);
840 fxrat.type = nodrat->type;
841 fxrat.etype = nodrat->etype;
842 fxrat.xoffset += 4;
843 gins(AMOVW, &fxrat, t);
844 gmove(t, t);
845 return;
846 }
847 break;
848 case TINT:
849 case TUINT:
850 case TLONG:
851 case TULONG:
852 case TIND:
853 switch(tt) {
854 case TDOUBLE:
855 case TFLOAT:
856 goto fxtofl;
857 case TINT:
858 case TUINT:
859 case TLONG:
860 case TULONG:
861 case TIND:
862 case TSHORT:
863 case TUSHORT:
864 case TCHAR:
865 case TUCHAR:
866 a = AMOVW;
867 break;
868 }
869 break;
870 case TSHORT:
871 switch(tt) {
872 case TDOUBLE:
873 case TFLOAT:
874 goto fxtofl;
875 case TINT:
876 case TUINT:
877 case TLONG:
878 case TULONG:
879 case TIND:
880 a = AMOVH;
881 break;
882 case TSHORT:
883 case TUSHORT:
884 case TCHAR:
885 case TUCHAR:
886 a = AMOVW;
887 break;
888 }
889 break;
890 case TUSHORT:
891 switch(tt) {
892 case TDOUBLE:
893 case TFLOAT:
894 goto fxtofl;
895 case TINT:
896 case TUINT:
897 case TLONG:
898 case TULONG:
899 case TIND:
900 a = AMOVHZ;
901 break;
902 case TSHORT:
903 case TUSHORT:
904 case TCHAR:
905 case TUCHAR:
906 a = AMOVW;
907 break;
908 }
909 break;
910 case TCHAR:
911 switch(tt) {
912 case TDOUBLE:
913 case TFLOAT:
914 goto fxtofl;
915 case TINT:
916 case TUINT:
917 case TLONG:
918 case TULONG:
919 case TIND:
920 case TSHORT:
921 case TUSHORT:
922 a = AMOVB;
923 break;
924 case TCHAR:
925 case TUCHAR:
926 a = AMOVW;
927 break;
928 }
929 break;
930 case TUCHAR:
931 switch(tt) {
932 case TDOUBLE:
933 case TFLOAT:
934 fxtofl:
935 /*
936 * rat[0] = 0x43300000; rat[1] = f^0x80000000;
937 * t = *(double*)rat - FREGCVI;
938 * is-unsigned(t) => if(t<0) t += 2^32;
939 * could be streamlined for int-to-float
940 */
941 regalloc(&fxc0, f, Z);
942 regalloc(&fxc2, f, Z);
943 regsalloc(&fxrat, &fconstnode); /* should be type float */
944 gins(AMOVW, nodconst(0x43300000L), &fxc0);
945 gins(AMOVW, f, &fxc2);
946 gins(AMOVW, &fxc0, &fxrat);
947 gins(AXOR, nodconst(0x80000000L), &fxc2);
948 fxc1 = fxrat;
949 fxc1.type = nodrat->type;
950 fxc1.etype = nodrat->etype;
951 fxc1.xoffset += SZ_LONG;
952 gins(AMOVW, &fxc2, &fxc1);
953 regfree(&fxc2);
954 regfree(&fxc0);
955 regalloc(&nod, t, t); /* should be type float */
956 gins(AFMOVD, &fxrat, &nod);
957 nodreg(&fxc1, t, NREG+FREGCVI);
958 gins(AFSUB, &fxc1, &nod);
959 a = AFMOVD;
960 if(tt == TFLOAT)
961 a = AFRSP;
962 gins(a, &nod, t);
963 regfree(&nod);
964 if(ft == TULONG) {
965 regalloc(&nod, t, Z);
966 if(tt == TFLOAT) {
967 gins(AFCMPU, t, Z);
968 p->to.type = D_FREG;
969 p->to.reg = FREGZERO;
970 gins(ABGE, Z, Z);
971 p1 = p;
972 gins(AFMOVS, nodfconst(4294967296.), &nod);
973 gins(AFADDS, &nod, t);
974 } else {
975 gins(AFCMPU, t, Z);
976 p->to.type = D_FREG;
977 p->to.reg = FREGZERO;
978 gins(ABGE, Z, Z);
979 p1 = p;
980 gins(AFMOVD, nodfconst(4294967296.), &nod);
981 gins(AFADD, &nod, t);
982 }
983 patch(p1, pc);
984 regfree(&nod);
985 }
986 return;
987 case TINT:
988 case TUINT:
989 case TLONG:
990 case TULONG:
991 case TIND:
992 case TSHORT:
993 case TUSHORT:
994 a = AMOVBZ;
995 break;
996 case TCHAR:
997 case TUCHAR:
998 a = AMOVW;
999 break;
1000 }
1001 break;
1002 case TVLONG:
1003 case TUVLONG:
1004 switch(tt) {
1005 case TVLONG:
1006 case TUVLONG:
1007 a = AMOVW;
1008 break;
1009 }
1010 break;
1011 }
1012 if(a == AGOK)
1013 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
1014 if(a == AMOVW || a == AFMOVS || a == AFMOVD)
1015 if(samaddr(f, t))
1016 return;
1017 if(typev[ft]) {
1018 if(f->op != OREGPAIR || t->op != OREGPAIR)
1019 diag(Z, "bad vlong in gmove (%O->%O)", f->op, t->op);
1020 gins(a, f->left, t->left);
1021 gins(a, f->right, t->right);
1022 } else
1023 gins(a, f, t);
1024 }
1025
1026 void
gins(int a,Node * f,Node * t)1027 gins(int a, Node *f, Node *t)
1028 {
1029
1030 nextpc();
1031 p->as = a;
1032 if(f != Z)
1033 naddr(f, &p->from);
1034 if(t != Z)
1035 naddr(t, &p->to);
1036 if(debug['g'])
1037 print("%P\n", p);
1038 }
1039
1040 void
gins3(int a,Node * f1,Node * f2,Node * t)1041 gins3(int a, Node *f1, Node *f2, Node *t)
1042 {
1043 Adr ta;
1044
1045 nextpc();
1046 p->as = a;
1047 if(f1 != Z)
1048 naddr(f1, &p->from);
1049 if(f2 != Z && (f2->op != OREGISTER || !samaddr(f2, t))) {
1050 ta = zprog.from; /* TO DO */
1051 naddr(f2, &ta);
1052 p->reg = ta.reg;
1053 if(ta.type == D_CONST && ta.offset == 0) {
1054 if(R0ISZERO)
1055 p->reg = REGZERO;
1056 else
1057 diag(Z, "REGZERO in gins3 %A", a);
1058 }else if(ta.type == D_CONST)
1059 p->from3 = ta;
1060 }
1061 if(t != Z)
1062 naddr(t, &p->to);
1063 if(debug['g'])
1064 print("%P\n", p);
1065 }
1066
1067 void
gins4(int a,Node * f1,Node * f2,Node * f3,Node * t)1068 gins4(int a, Node *f1, Node *f2, Node *f3, Node *t)
1069 {
1070 Adr ta;
1071
1072 nextpc();
1073 p->as = a;
1074 naddr(f1, &p->from);
1075 if(f2->op != OREGISTER && (f2->op != OCONST || vconst(f2) != 0))
1076 diag(f2, "invalid gins4");
1077 naddr(f2, &ta);
1078 p->reg = ta.reg;
1079 if(ta.type == D_CONST && ta.offset == 0)
1080 p->reg = REGZERO;
1081 naddr(f3, &p->from3);
1082 naddr(t, &p->to);
1083 if(debug['g'])
1084 print("%P\n", p);
1085 }
1086
1087 void
gopcode(int o,Node * f1,Node * f2,Node * t)1088 gopcode(int o, Node *f1, Node *f2, Node *t)
1089 {
1090 int a, et, uns;
1091
1092 if(o == OAS) {
1093 gmove(f1, t);
1094 return;
1095 }
1096 et = TLONG;
1097 if(f1 != Z && f1->type != T) {
1098 if(f1->op == OCONST && t != Z && t->type != T)
1099 et = t->type->etype;
1100 else
1101 et = f1->type->etype;
1102 }
1103 if((typev[et] || t->type != T && typev[t->type->etype]) && o != OFUNC) {
1104 gopcode64(o, f1, f2, t);
1105 return;
1106 }
1107 uns = 0;
1108 a = AGOK;
1109 switch(o) {
1110
1111 case OASADD:
1112 case OADD:
1113 a = AADD;
1114 if(et == TFLOAT)
1115 a = AFADDS;
1116 else
1117 if(et == TDOUBLE)
1118 a = AFADD;
1119 break;
1120
1121 case OASSUB:
1122 case OSUB:
1123 a = ASUB;
1124 if(et == TFLOAT)
1125 a = AFSUBS;
1126 else
1127 if(et == TDOUBLE)
1128 a = AFSUB;
1129 break;
1130
1131 case OASOR:
1132 case OOR:
1133 a = AOR;
1134 break;
1135
1136 case OASAND:
1137 case OAND:
1138 a = AAND;
1139 if(f1->op == OCONST)
1140 a = AANDCC;
1141 break;
1142
1143 case OASXOR:
1144 case OXOR:
1145 a = AXOR;
1146 break;
1147
1148 case OASLSHR:
1149 case OLSHR:
1150 a = ASRW;
1151 break;
1152
1153 case OASASHR:
1154 case OASHR:
1155 a = ASRAW;
1156 break;
1157
1158 case OASASHL:
1159 case OASHL:
1160 a = ASLW;
1161 break;
1162
1163 case OFUNC:
1164 a = ABL;
1165 break;
1166
1167 case OASLMUL:
1168 case OLMUL:
1169 case OASMUL:
1170 case OMUL:
1171 if(et == TFLOAT) {
1172 a = AFMULS;
1173 break;
1174 } else
1175 if(et == TDOUBLE) {
1176 a = AFMUL;
1177 break;
1178 }
1179 a = AMULLW;
1180 break;
1181
1182 case OASDIV:
1183 case ODIV:
1184 if(et == TFLOAT) {
1185 a = AFDIVS;
1186 break;
1187 } else
1188 if(et == TDOUBLE) {
1189 a = AFDIV;
1190 break;
1191 }
1192 a = ADIVW;
1193 break;
1194
1195 case OASMOD:
1196 case OMOD:
1197 a = AREM;
1198 break;
1199
1200 case OASLMOD:
1201 case OLMOD:
1202 a = AREMU;
1203 break;
1204
1205 case OASLDIV:
1206 case OLDIV:
1207 a = ADIVWU;
1208 break;
1209
1210 case OCOM:
1211 a = ANOR;
1212 break;
1213
1214 case ONEG:
1215 a = ANEG;
1216 if(et == TFLOAT || et == TDOUBLE)
1217 a = AFNEG;
1218 break;
1219
1220 case OEQ:
1221 a = ABEQ;
1222 if(t->op == OCONST && t->vconst >= (1<<15))
1223 goto cmpu;
1224 goto cmp;
1225
1226 case ONE:
1227 a = ABNE;
1228 if(t->op == OCONST && t->vconst >= (1<<15))
1229 goto cmpu;
1230 goto cmp;
1231
1232 case OLT:
1233 a = ABLT;
1234 goto cmp;
1235
1236 case OLE:
1237 a = ABLE;
1238 goto cmp;
1239
1240 case OGE:
1241 a = ABGE;
1242 goto cmp;
1243
1244 case OGT:
1245 a = ABGT;
1246 goto cmp;
1247
1248 case OLO:
1249 a = ABLT;
1250 goto cmpu;
1251
1252 case OLS:
1253 a = ABLE;
1254 goto cmpu;
1255
1256 case OHS:
1257 a = ABGE;
1258 goto cmpu;
1259
1260 case OHI:
1261 a = ABGT;
1262 goto cmpu;
1263
1264 cmpu:
1265 uns = 1;
1266 cmp:
1267 nextpc();
1268 p->as = uns? ACMPU: ACMP;
1269 if(et == TFLOAT)
1270 p->as = AFCMPU;
1271 else
1272 if(et == TDOUBLE)
1273 p->as = AFCMPU;
1274 if(f1 != Z)
1275 naddr(f1, &p->from);
1276 if(t != Z)
1277 naddr(t, &p->to);
1278 if(f1 == Z || t == Z || f2 != Z)
1279 diag(Z, "bad cmp in gopcode %O", o);
1280 if(debug['g'])
1281 print("%P\n", p);
1282 f1 = Z;
1283 f2 = Z;
1284 t = Z;
1285 break;
1286 }
1287 if(a == AGOK)
1288 diag(Z, "bad in gopcode %O", o);
1289 gins3(a, f1, f2, t);
1290 }
1291
1292 static void
gopcode64(int o,Node * f1,Node * f2,Node * t)1293 gopcode64(int o, Node *f1, Node *f2, Node *t)
1294 {
1295 int a1, a2;
1296 Node nod, nod1, nod2, sh;
1297 ulong m;
1298 Prog *p1;
1299
1300 if(t->op != OREGPAIR || f2 != Z && f2->op != OREGPAIR) {
1301 diag(Z, "bad f2/dest in gopcode64 %O", o);
1302 return;
1303 }
1304 if(f1->op != OCONST &&
1305 (typev[f1->type->etype] && f1->op != OREGPAIR || !typev[f1->type->etype] && f1->op != OREGISTER)) {
1306 diag(Z, "bad f1[%O] in gopcode64 %O", f1->op, o);
1307 return;
1308 }
1309 /* a1 for low-order, a2 for high-order */
1310 a1 = AGOK;
1311 a2 = AGOK;
1312 switch(o) {
1313 case OASADD:
1314 case OADD:
1315 if(f1->op == OCONST && sconst(f1)) {
1316 if(f2 == Z)
1317 f2 = t;
1318 gins3(AADDC, f1, f2->right, t->right);
1319 if((f1->vconst>>32) == 0)
1320 gins(AADDZE, f2->left, t->left);
1321 else if((f1->vconst>>32) == -1)
1322 gins(AADDME, f2->left, t->left);
1323 else
1324 diag(t, "odd vlong ADD: %lld", f1->vconst);
1325 return;
1326 }
1327 a1 = AADDC;
1328 a2 = AADDE;
1329 break;
1330
1331 case OASSUB:
1332 case OSUB:
1333 a1 = ASUBC;
1334 a2 = ASUBE;
1335 break;
1336
1337 case OASOR:
1338 case OOR:
1339 if(f1->op == OCONST) {
1340 gori64(AOR, f1, f2, t);
1341 return;
1342 }
1343 a1 = a2 = AOR;
1344 break;
1345
1346 case OASAND:
1347 case OAND:
1348 if(f1->op == OCONST) {
1349 gandi64(AANDCC, f1, f2, t);
1350 return;
1351 }
1352 a1 = a2 = AAND;
1353 break;
1354
1355 case OASXOR:
1356 case OXOR:
1357 if(f1->op == OCONST) {
1358 gori64(AXOR, f1, f2, t);
1359 return;
1360 }
1361 a1 = a2 = AXOR;
1362 break;
1363
1364 case OASLSHR:
1365 case OLSHR:
1366 if(f2 == Z)
1367 f2 = t;
1368 if(f1->op == OCONST) {
1369 if(f1->vconst >= 32) {
1370 if(f1->vconst == 32)
1371 gmove(f2->left, t->right);
1372 else if(f1->vconst < 64)
1373 gins3(ASRW, nodconst(f1->vconst-32), f2->left, t->right);
1374 else
1375 gmove(nodconst(0), t->right);
1376 gmove(nodconst(0), t->left);
1377 return;
1378 }
1379 if(f1->vconst <= 0) {
1380 if(f2 != t)
1381 gmove(f2, t);
1382 return;
1383 }
1384 sh = *nodconst(32 - f1->vconst);
1385 m = 0xFFFFFFFFUL >> f1->vconst;
1386 gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
1387 gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
1388 gins4(ARLWNM, &sh, f2->left, nodconst(m), t->left);
1389 return;
1390 }
1391 regalloc(&nod, ®node, Z);
1392 gins3(ASUBC, f1, nodconst(32), &nod);
1393 gins3(ASRW, f1, f2->right, t->right);
1394 regalloc(&nod1, ®node, Z);
1395 gins3(ASLW, &nod, f2->left, &nod1);
1396 gins(AOR, &nod1, t->right);
1397 gins3(AADD, nodconst(-32), f1, &nod);
1398 gins3(ASRW, &nod, f2->left, &nod1);
1399 gins(AOR, &nod1, t->right);
1400 gins3(ASRW, f1, f2->left, t->left);
1401 regfree(&nod);
1402 regfree(&nod1);
1403 return;
1404
1405 case OASASHR:
1406 case OASHR:
1407 if(f2 == Z)
1408 f2 = t;
1409 if(f1->op == OCONST) {
1410 if(f1->vconst >= 32) {
1411 if(f1->vconst == 32)
1412 gmove(f2->left, t->right);
1413 else if(f1->vconst < 64)
1414 gins3(ASRAW, nodconst(f1->vconst-32), f2->left, t->right);
1415 gins3(ASRAW, nodconst(31), f2->left, t->left);
1416 if(f1->vconst >= 64) {
1417 gmove(t->left, t->right);
1418 return;
1419 }
1420 return;
1421 }
1422 if(f1->vconst <= 0) {
1423 if(f2 != t)
1424 gmove(f2, t);
1425 return;
1426 }
1427 sh = *nodconst(32 - f1->vconst);
1428 m = 0xFFFFFFFFUL >> f1->vconst;
1429 gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
1430 gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
1431 gins3(ASRAW, &sh, f2->left, t->left);
1432 return;
1433 }
1434 regalloc(&nod, ®node, Z);
1435 gins3(ASUBC, f1, nodconst(32), &nod);
1436 gins3(ASRW, f1, f2->right, t->right);
1437 regalloc(&nod1, ®node, Z);
1438 gins3(ASLW, &nod, f2->left, &nod1);
1439 gins(AOR, &nod1, t->right);
1440 gins3(AADDCCC, nodconst(-32), f1, &nod);
1441 gins3(ASRAW, &nod, f2->left, &nod1);
1442 gins(ABLE, Z, Z);
1443 p1 = p;
1444 gins(AMOVW, &nod1, t->right);
1445 patch(p1, pc);
1446 gins3(ASRAW, f1, f2->left, t->left);
1447 regfree(&nod);
1448 regfree(&nod1);
1449 return;
1450
1451 case OASASHL:
1452 case OASHL:
1453 if(f2 == Z)
1454 f2 = t;
1455 if(f1->op == OCONST) {
1456 if(f1->vconst >= 32) {
1457 if(f1->vconst == 32)
1458 gmove(f2->right, t->left);
1459 else if(f1->vconst >= 64)
1460 gmove(nodconst(0), t->left);
1461 else
1462 gins3(ASLW, nodconst(f1->vconst-32), f2->right, t->left);
1463 gmove(nodconst(0), t->right);
1464 return;
1465 }
1466 if(f1->vconst <= 0) {
1467 if(f2 != t)
1468 gmove(f2, t);
1469 return;
1470 }
1471 m = 0xFFFFFFFFUL << f1->vconst;
1472 gins4(ARLWNM, f1, f2->left, nodconst(m), t->left);
1473 gins4(ARLWMI, f1, f2->right, nodconst(~m), t->left);
1474 gins4(ARLWNM, f1, f2->right, nodconst(m), t->right);
1475 return;
1476 }
1477 regalloc(&nod, ®node, Z);
1478 gins3(ASUBC, f1, nodconst(32), &nod);
1479 gins3(ASLW, f1, f2->left, t->left);
1480 regalloc(&nod1, ®node, Z);
1481 gins3(ASRW, &nod, f2->right, &nod1);
1482 gins(AOR, &nod1, t->left);
1483 gins3(AADD, nodconst(-32), f1, &nod);
1484 gins3(ASLW, &nod, f2->right, &nod1);
1485 gins(AOR, &nod1, t->left);
1486 gins3(ASLW, f1, f2->right, t->right);
1487 regfree(&nod);
1488 regfree(&nod1);
1489 return;
1490
1491 case OASLMUL:
1492 case OLMUL:
1493 case OASMUL:
1494 case OMUL:
1495 if(f2 == Z)
1496 f2 = t;
1497 regalloc(&nod, ®node, Z);
1498 gins3(AMULLW, f1->right, f2->right, &nod); /* lo(f2.low*f1.low) */
1499 regalloc(&nod1, ®node, Z);
1500 gins3(AMULHWU, f1->right, f2->right, &nod1); /* hi(f2.low*f1.low) */
1501 regalloc(&nod2, ®node, Z);
1502 gins3(AMULLW, f2->right, f1->left, &nod2); /* lo(f2.low*f1.high) */
1503 gins(AADD, &nod2, &nod1);
1504 gins3(AMULLW, f1->right, f2->left, &nod2); /* lo(f2.high*f1.low) */
1505 gins(AADD, &nod2, &nod1);
1506 regfree(&nod2);
1507 gmove(&nod, t->right);
1508 gmove(&nod1, t->left);
1509 regfree(&nod);
1510 regfree(&nod1);
1511 return;
1512
1513 case OCOM:
1514 a1 = a2 = ANOR;
1515 break;
1516
1517 case ONEG:
1518 gins3(ASUBC, t->right, nodconst(0), t->right);
1519 gins(ASUBZE, t->left, t->left);
1520 return;
1521 }
1522 if(a1 == AGOK || a2 == AGOK)
1523 diag(Z, "bad in gopcode64 %O", o);
1524 if(f1->op == OCONST) {
1525 if(f2 != Z & f2 != t)
1526 diag(Z, "bad const in gopcode64 %O", o);
1527 gins(a1, nod32const(f1->vconst), t->right);
1528 gins(a2, nod32const(f1->vconst>>32), t->left);
1529 } else {
1530 if(f2 != Z && f2 != t) {
1531 gins3(a1, f1->right, f2->right, t->right);
1532 gins3(a2, f1->left, f2->left, t->left);
1533 } else {
1534 gins(a1, f1->right, t->right);
1535 gins(a2, f1->left, t->left);
1536 }
1537 }
1538 }
1539
samaddr(Node * f,Node * t)1540 samaddr(Node *f, Node *t)
1541 {
1542
1543 if(f->op != t->op)
1544 return 0;
1545 switch(f->op) {
1546
1547 case OREGISTER:
1548 if(f->reg != t->reg)
1549 break;
1550 return 1;
1551
1552 case OREGPAIR:
1553 return samaddr(f->left, t->left) && samaddr(f->right, t->right);
1554 }
1555 return 0;
1556 }
1557
1558 static void
gori64(int a,Node * f1,Node * f2,Node * t)1559 gori64(int a, Node *f1, Node *f2, Node *t)
1560 {
1561 ulong lo, hi;
1562
1563 if(f2 == Z)
1564 f2 = t;
1565 lo = f1->vconst & MASK(32);
1566 hi = (f1->vconst >> 32) & MASK(32);
1567 if(lo & 0xFFFF)
1568 gins3(a, nodconst(lo & 0xFFFF), f2->right, t->right);
1569 if((lo >> 16) != 0)
1570 gins3(a, nodconst(lo & 0xFFFF0000UL), f2->right, t->right);
1571 if(hi & 0xFFFF)
1572 gins3(a, nodconst(hi & 0xFFFF), f2->left, t->left);
1573 if((hi >> 16) != 0)
1574 gins3(a, nodconst(hi & 0xFFFF0000UL), f2->left, t->left);
1575 }
1576
1577 static void
gandi64(int a,Node * f1,Node * f2,Node * t)1578 gandi64(int a, Node *f1, Node *f2, Node *t)
1579 {
1580 ulong lo, hi;
1581
1582 if(f2 == Z)
1583 f2 = t;
1584 lo = f1->vconst & MASK(32);
1585 hi = (f1->vconst >> 32) & MASK(32);
1586 if(lo == 0)
1587 gins(AMOVW, nodconst(0), t->right);
1588 else
1589 gins3(a, nodconst(lo), f2->right, t->right);
1590 if(hi == 0)
1591 gins(AMOVW, nodconst(0), t->left);
1592 else
1593 gins3(a, nodconst(hi), f2->left, t->left);
1594 }
1595
1596 void
gbranch(int o)1597 gbranch(int o)
1598 {
1599 int a;
1600
1601 a = AGOK;
1602 switch(o) {
1603 case ORETURN:
1604 a = ARETURN;
1605 break;
1606 case OGOTO:
1607 a = ABR;
1608 break;
1609 }
1610 nextpc();
1611 if(a == AGOK) {
1612 diag(Z, "bad in gbranch %O", o);
1613 nextpc();
1614 }
1615 p->as = a;
1616 }
1617
1618 void
patch(Prog * op,long pc)1619 patch(Prog *op, long pc)
1620 {
1621
1622 op->to.offset = pc;
1623 op->to.type = D_BRANCH;
1624 }
1625
1626 void
gpseudo(int a,Sym * s,Node * n)1627 gpseudo(int a, Sym *s, Node *n)
1628 {
1629
1630 nextpc();
1631 p->as = a;
1632 p->from.type = D_OREG;
1633 p->from.sym = s;
1634 if(a == ATEXT)
1635 p->reg = (profileflg ? 0 : NOPROF);
1636 p->from.name = D_EXTERN;
1637 if(s->class == CSTATIC)
1638 p->from.name = D_STATIC;
1639 naddr(n, &p->to);
1640 if(a == ADATA || a == AGLOBL)
1641 pc--;
1642 }
1643
1644 int
sval(long v)1645 sval(long v)
1646 {
1647
1648 if(v >= -(1<<15) && v < (1<<15))
1649 return 1;
1650 return 0;
1651 }
1652
1653 int
sconst(Node * n)1654 sconst(Node *n)
1655 {
1656 vlong vv;
1657
1658 if(n->op == OCONST) {
1659 if(!typefd[n->type->etype]) {
1660 vv = n->vconst;
1661 if(vv >= -(((vlong)1)<<15) && vv < (((vlong)1)<<15))
1662 return 1;
1663 }
1664 }
1665 return 0;
1666 }
1667
1668 int
uconst(Node * n)1669 uconst(Node *n)
1670 {
1671 vlong vv;
1672
1673 if(n->op == OCONST) {
1674 if(!typefd[n->type->etype]) {
1675 vv = n->vconst;
1676 if(vv >= 0 && vv < (((vlong)1)<<16))
1677 return 1;
1678 }
1679 }
1680 return 0;
1681 }
1682
1683 long
exreg(Type * t)1684 exreg(Type *t)
1685 {
1686 long o;
1687
1688 if(typechlp[t->etype]) {
1689 if(exregoffset <= 3)
1690 return 0;
1691 o = exregoffset;
1692 exregoffset--;
1693 return o;
1694 }
1695 if(typefd[t->etype]) {
1696 if(exfregoffset <= 16)
1697 return 0;
1698 o = exfregoffset + NREG;
1699 exfregoffset--;
1700 return o;
1701 }
1702 return 0;
1703 }
1704
1705 schar ewidth[NTYPE] =
1706 {
1707 -1, /* [TXXX] */
1708 SZ_CHAR, /* [TCHAR] */
1709 SZ_CHAR, /* [TUCHAR] */
1710 SZ_SHORT, /* [TSHORT] */
1711 SZ_SHORT, /* [TUSHORT] */
1712 SZ_INT, /* [TINT] */
1713 SZ_INT, /* [TUINT] */
1714 SZ_LONG, /* [TLONG] */
1715 SZ_LONG, /* [TULONG] */
1716 SZ_VLONG, /* [TVLONG] */
1717 SZ_VLONG, /* [TUVLONG] */
1718 SZ_FLOAT, /* [TFLOAT] */
1719 SZ_DOUBLE, /* [TDOUBLE] */
1720 SZ_IND, /* [TIND] */
1721 0, /* [TFUNC] */
1722 -1, /* [TARRAY] */
1723 0, /* [TVOID] */
1724 -1, /* [TSTRUCT] */
1725 -1, /* [TUNION] */
1726 SZ_INT, /* [TENUM] */
1727 };
1728 long ncast[NTYPE] =
1729 {
1730 0, /* [TXXX] */
1731 BCHAR|BUCHAR, /* [TCHAR] */
1732 BCHAR|BUCHAR, /* [TUCHAR] */
1733 BSHORT|BUSHORT, /* [TSHORT] */
1734 BSHORT|BUSHORT, /* [TUSHORT] */
1735 BINT|BUINT|BLONG|BULONG|BIND, /* [TINT] */
1736 BINT|BUINT|BLONG|BULONG|BIND, /* [TUINT] */
1737 BINT|BUINT|BLONG|BULONG|BIND, /* [TLONG] */
1738 BINT|BUINT|BLONG|BULONG|BIND, /* [TULONG] */
1739 BVLONG|BUVLONG, /* [TVLONG] */
1740 BVLONG|BUVLONG, /* [TUVLONG] */
1741 BFLOAT, /* [TFLOAT] */
1742 BDOUBLE, /* [TDOUBLE] */
1743 BLONG|BULONG|BIND, /* [TIND] */
1744 0, /* [TFUNC] */
1745 0, /* [TARRAY] */
1746 0, /* [TVOID] */
1747 BSTRUCT, /* [TSTRUCT] */
1748 BUNION, /* [TUNION] */
1749 0, /* [TENUM] */
1750 };
1751