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 static void
floattofix(Node * f,Node * t)626 floattofix(Node *f, Node *t)
627 {
628 Node nod, fxrat;
629
630 regalloc(&nod, f, Z);
631 regsalloc(&fxrat, &fconstnode);
632 gins(AFCTIWZ, f, &nod);
633 gins(AFMOVD, &nod, &fxrat);
634 regfree(&nod);
635 fxrat.type = nodrat->type;
636 fxrat.etype = nodrat->etype;
637 fxrat.xoffset += 4;
638 gins(AMOVW, &fxrat, t);
639 gmove(t, t);
640 }
641
642 static void
fixtofloat(Node * f,Node * t)643 fixtofloat(Node *f, Node *t)
644 {
645 int a, ft, tt;
646 Prog *p1;
647 Node nod, fxc0, fxc1, fxc2, fxrat;
648
649 ft = f->type->etype;
650 tt = t->type->etype;
651
652 /*
653 * rat[0] = 0x43300000; rat[1] = f^0x80000000;
654 * t = *(double*)rat - FREGCVI;
655 * is-unsigned(t) => if(t<0) t += 2^32;
656 * could be streamlined for int-to-float
657 */
658 regalloc(&fxc0, f, Z);
659 regalloc(&fxc2, f, Z);
660 regsalloc(&fxrat, &fconstnode); /* should be type float */
661 gins(AMOVW, nodconst(0x43300000L), &fxc0);
662 gins(AMOVW, f, &fxc2);
663 gins(AMOVW, &fxc0, &fxrat);
664 gins(AXOR, nodconst(0x80000000L), &fxc2);
665 fxc1 = fxrat;
666 fxc1.type = nodrat->type;
667 fxc1.etype = nodrat->etype;
668 fxc1.xoffset += SZ_LONG;
669 gins(AMOVW, &fxc2, &fxc1);
670 regfree(&fxc2);
671 regfree(&fxc0);
672 regalloc(&nod, t, t); /* should be type float */
673 gins(AFMOVD, &fxrat, &nod);
674 nodreg(&fxc1, t, NREG+FREGCVI);
675 gins(AFSUB, &fxc1, &nod);
676 a = AFMOVD;
677 if(tt == TFLOAT)
678 a = AFRSP;
679 gins(a, &nod, t);
680 regfree(&nod);
681 if(ft == TULONG) {
682 regalloc(&nod, t, Z);
683 gins(AFCMPU, t, Z);
684 p->to.type = D_FREG;
685 p->to.reg = FREGZERO;
686 gins(ABGE, Z, Z);
687 p1 = p;
688 if(tt == TFLOAT) {
689 gins(AFMOVS, nodfconst(4294967296.), &nod);
690 gins(AFADDS, &nod, t);
691 } else {
692 gins(AFMOVD, nodfconst(4294967296.), &nod);
693 gins(AFADD, &nod, t);
694 }
695 patch(p1, pc);
696 regfree(&nod);
697 }
698 }
699
700 void
gmove(Node * f,Node * t)701 gmove(Node *f, Node *t)
702 {
703 int ft, tt, a;
704 Node nod;
705 double d;
706
707 ft = f->type->etype;
708 tt = t->type->etype;
709
710 if(ft == TDOUBLE && f->op == OCONST) {
711 d = f->fconst;
712 if(d == 0.0) {
713 a = FREGZERO;
714 goto ffreg;
715 }
716 if(d == 0.5) {
717 a = FREGHALF;
718 goto ffreg;
719 }
720 if(d == 1.0) {
721 a = FREGONE;
722 goto ffreg;
723 }
724 if(d == 2.0) {
725 a = FREGTWO;
726 goto ffreg;
727 }
728 if(d == -.5) {
729 fop(OSUB, FREGHALF, FREGZERO, t);
730 return;
731 }
732 if(d == -1.0) {
733 fop(OSUB, FREGONE, FREGZERO, t);
734 return;
735 }
736 if(d == -2.0) {
737 fop(OSUB, FREGTWO, FREGZERO, t);
738 return;
739 }
740 if(d == 1.5) {
741 fop(OADD, FREGONE, FREGHALF, t);
742 return;
743 }
744 if(d == 2.5) {
745 fop(OADD, FREGTWO, FREGHALF, t);
746 return;
747 }
748 if(d == 3.0) {
749 fop(OADD, FREGTWO, FREGONE, t);
750 return;
751 }
752 }
753 if(ft == TFLOAT && f->op == OCONST) {
754 d = f->fconst;
755 if(d == 0) {
756 a = FREGZERO;
757 ffreg:
758 nodreg(&nod, f, NREG+a);
759 gmove(&nod, t);
760 return;
761 }
762 }
763 if((ft == TVLONG || ft == TUVLONG) && f->op == OCONST && t->op == OREGPAIR) {
764 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
765 gmove(nod32const(f->vconst>>32), t->left);
766 else
767 gmove(nod32const(f->vconst), t->left);
768 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
769 gmove(nod32const(f->vconst), t->right);
770 else
771 gmove(nod32const(f->vconst>>32), t->right);
772 return;
773 }
774 /*
775 * a load --
776 * put it into a register then
777 * worry what to do with it.
778 */
779 if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
780 switch(ft) {
781 default:
782 a = AMOVW;
783 break;
784 case TFLOAT:
785 a = AFMOVS;
786 break;
787 case TDOUBLE:
788 a = AFMOVD;
789 break;
790 case TCHAR:
791 a = AMOVB;
792 break;
793 case TUCHAR:
794 a = AMOVBZ;
795 break;
796 case TSHORT:
797 a = AMOVH;
798 break;
799 case TUSHORT:
800 a = AMOVHZ;
801 break;
802 }
803 if(typev[ft]) {
804 if(typev[tt] || typefd[tt]) {
805 regalloc(&nod, f, t);
806 /* low order first, because its value will be used first */
807 f->xoffset += SZ_LONG;
808 gins(AMOVW, f, nod.right);
809 f->xoffset -= SZ_LONG;
810 gins(AMOVW, f, nod.left);
811 } else {
812 /* assumed not float or double */
813 regalloc(&nod, ®node, t);
814 f->xoffset += SZ_LONG;
815 gins(AMOVW, f, &nod);
816 f->xoffset -= SZ_LONG;
817 }
818 } else {
819 regalloc(&nod, f, t);
820 gins(a, f, &nod);
821 }
822 gmove(&nod, t);
823 regfree(&nod);
824 return;
825 }
826
827 /*
828 * a store --
829 * put it into a register then
830 * store it.
831 */
832 if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
833 switch(tt) {
834 default:
835 a = AMOVW;
836 break;
837 case TUCHAR:
838 a = AMOVBZ;
839 break;
840 case TCHAR:
841 a = AMOVB;
842 break;
843 case TUSHORT:
844 a = AMOVHZ;
845 break;
846 case TSHORT:
847 a = AMOVH;
848 break;
849 case TFLOAT:
850 a = AFMOVS;
851 break;
852 case TDOUBLE:
853 a = AFMOVD;
854 break;
855 }
856 if(R0ISZERO && !typefd[ft] && vconst(f) == 0) {
857 gins(a, f, t);
858 if(typev[tt]) {
859 t->xoffset += SZ_LONG;
860 gins(a, f, t);
861 t->xoffset -= SZ_LONG;
862 }
863 return;
864 }
865 if(ft == tt)
866 regalloc(&nod, t, f);
867 else
868 regalloc(&nod, t, Z);
869 gmove(f, &nod);
870 if(typev[tt]) {
871 t->xoffset += SZ_LONG;
872 gins(a, nod.right, t);
873 t->xoffset -= SZ_LONG;
874 gins(a, nod.left, t);
875 } else
876 gins(a, &nod, t);
877 regfree(&nod);
878 return;
879 }
880
881 /*
882 * type x type cross table
883 */
884 a = AGOK;
885 switch(ft) {
886 case TDOUBLE:
887 case TFLOAT:
888 switch(tt) {
889 case TDOUBLE:
890 a = AFMOVD;
891 if(ft == TFLOAT)
892 a = AFMOVS; /* AFMOVSD */
893 break;
894 case TFLOAT:
895 a = AFRSP;
896 if(ft == TFLOAT)
897 a = AFMOVS;
898 break;
899 case TINT:
900 case TUINT:
901 case TLONG:
902 case TULONG:
903 case TIND:
904 case TSHORT:
905 case TUSHORT:
906 case TCHAR:
907 case TUCHAR:
908 /* BUG: not right for unsigned long */
909 floattofix(f, t);
910 return;
911 case TVLONG:
912 case TUVLONG:
913 diag(f, "unimplemented double->vlong");
914 return;
915 }
916 break;
917 case TINT:
918 case TUINT:
919 case TLONG:
920 case TULONG:
921 case TIND:
922 switch(tt) {
923 case TDOUBLE:
924 case TFLOAT:
925 fixtofloat(f, t);
926 return;
927 case TINT:
928 case TUINT:
929 case TLONG:
930 case TULONG:
931 case TIND:
932 case TSHORT:
933 case TUSHORT:
934 case TCHAR:
935 case TUCHAR:
936 a = AMOVW;
937 break;
938 }
939 break;
940 case TSHORT:
941 switch(tt) {
942 case TDOUBLE:
943 case TFLOAT:
944 fixtofloat(f, t);
945 return;
946 case TINT:
947 case TUINT:
948 case TLONG:
949 case TULONG:
950 case TIND:
951 a = AMOVH;
952 break;
953 case TSHORT:
954 case TUSHORT:
955 case TCHAR:
956 case TUCHAR:
957 a = AMOVW;
958 break;
959 }
960 break;
961 case TUSHORT:
962 switch(tt) {
963 case TDOUBLE:
964 case TFLOAT:
965 fixtofloat(f, t);
966 return;
967 case TINT:
968 case TUINT:
969 case TLONG:
970 case TULONG:
971 case TIND:
972 a = AMOVHZ;
973 break;
974 case TSHORT:
975 case TUSHORT:
976 case TCHAR:
977 case TUCHAR:
978 a = AMOVW;
979 break;
980 }
981 break;
982 case TCHAR:
983 switch(tt) {
984 case TDOUBLE:
985 case TFLOAT:
986 fixtofloat(f, t);
987 return;
988 case TINT:
989 case TUINT:
990 case TLONG:
991 case TULONG:
992 case TIND:
993 case TSHORT:
994 case TUSHORT:
995 a = AMOVB;
996 break;
997 case TCHAR:
998 case TUCHAR:
999 a = AMOVW;
1000 break;
1001 }
1002 break;
1003 case TUCHAR:
1004 switch(tt) {
1005 case TDOUBLE:
1006 case TFLOAT:
1007 fixtofloat(f, t);
1008 return;
1009 case TINT:
1010 case TUINT:
1011 case TLONG:
1012 case TULONG:
1013 case TIND:
1014 case TSHORT:
1015 case TUSHORT:
1016 a = AMOVBZ;
1017 break;
1018 case TCHAR:
1019 case TUCHAR:
1020 a = AMOVW;
1021 break;
1022 }
1023 break;
1024 case TVLONG:
1025 case TUVLONG:
1026 switch(tt) {
1027 case TVLONG:
1028 case TUVLONG:
1029 a = AMOVW;
1030 break;
1031 }
1032 break;
1033 }
1034 if(a == AGOK)
1035 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
1036 if(a == AMOVW || a == AFMOVS || a == AFMOVD)
1037 if(samaddr(f, t))
1038 return;
1039 if(typev[ft]) {
1040 if(f->op != OREGPAIR || t->op != OREGPAIR)
1041 diag(Z, "bad vlong in gmove (%O->%O)", f->op, t->op);
1042 gins(a, f->left, t->left);
1043 gins(a, f->right, t->right);
1044 } else
1045 gins(a, f, t);
1046 }
1047
1048 void
gins(int a,Node * f,Node * t)1049 gins(int a, Node *f, Node *t)
1050 {
1051
1052 nextpc();
1053 p->as = a;
1054 if(f != Z)
1055 naddr(f, &p->from);
1056 if(t != Z)
1057 naddr(t, &p->to);
1058 if(debug['g'])
1059 print("%P\n", p);
1060 }
1061
1062 void
gins3(int a,Node * f1,Node * f2,Node * t)1063 gins3(int a, Node *f1, Node *f2, Node *t)
1064 {
1065 Adr ta;
1066
1067 nextpc();
1068 p->as = a;
1069 if(f1 != Z)
1070 naddr(f1, &p->from);
1071 if(f2 != Z && (f2->op != OREGISTER || !samaddr(f2, t))) {
1072 ta = zprog.from; /* TO DO */
1073 naddr(f2, &ta);
1074 p->reg = ta.reg;
1075 if(ta.type == D_CONST && ta.offset == 0) {
1076 if(R0ISZERO)
1077 p->reg = REGZERO;
1078 else
1079 diag(Z, "REGZERO in gins3 %A", a);
1080 }else if(ta.type == D_CONST)
1081 p->from3 = ta;
1082 }
1083 if(t != Z)
1084 naddr(t, &p->to);
1085 if(debug['g'])
1086 print("%P\n", p);
1087 }
1088
1089 void
gins4(int a,Node * f1,Node * f2,Node * f3,Node * t)1090 gins4(int a, Node *f1, Node *f2, Node *f3, Node *t)
1091 {
1092 Adr ta;
1093
1094 nextpc();
1095 p->as = a;
1096 naddr(f1, &p->from);
1097 if(f2->op != OREGISTER && (f2->op != OCONST || vconst(f2) != 0))
1098 diag(f2, "invalid gins4");
1099 naddr(f2, &ta);
1100 p->reg = ta.reg;
1101 if(ta.type == D_CONST && ta.offset == 0)
1102 p->reg = REGZERO;
1103 naddr(f3, &p->from3);
1104 naddr(t, &p->to);
1105 if(debug['g'])
1106 print("%P\n", p);
1107 }
1108
1109 void
gopcode(int o,Node * f1,Node * f2,Node * t)1110 gopcode(int o, Node *f1, Node *f2, Node *t)
1111 {
1112 int a, et, uns;
1113
1114 if(o == OAS) {
1115 gmove(f1, t);
1116 return;
1117 }
1118 et = TLONG;
1119 if(f1 != Z && f1->type != T) {
1120 if(f1->op == OCONST && t != Z && t->type != T)
1121 et = t->type->etype;
1122 else
1123 et = f1->type->etype;
1124 }
1125 if((typev[et] || t->type != T && typev[t->type->etype]) && o != OFUNC) {
1126 gopcode64(o, f1, f2, t);
1127 return;
1128 }
1129 uns = 0;
1130 a = AGOK;
1131 switch(o) {
1132
1133 case OASADD:
1134 case OADD:
1135 a = AADD;
1136 if(et == TFLOAT)
1137 a = AFADDS;
1138 else
1139 if(et == TDOUBLE)
1140 a = AFADD;
1141 break;
1142
1143 case OASSUB:
1144 case OSUB:
1145 a = ASUB;
1146 if(et == TFLOAT)
1147 a = AFSUBS;
1148 else
1149 if(et == TDOUBLE)
1150 a = AFSUB;
1151 break;
1152
1153 case OASOR:
1154 case OOR:
1155 a = AOR;
1156 break;
1157
1158 case OASAND:
1159 case OAND:
1160 a = AAND;
1161 if(f1->op == OCONST)
1162 a = AANDCC;
1163 break;
1164
1165 case OASXOR:
1166 case OXOR:
1167 a = AXOR;
1168 break;
1169
1170 case OASLSHR:
1171 case OLSHR:
1172 a = ASRW;
1173 break;
1174
1175 case OASASHR:
1176 case OASHR:
1177 a = ASRAW;
1178 break;
1179
1180 case OASASHL:
1181 case OASHL:
1182 a = ASLW;
1183 break;
1184
1185 case OFUNC:
1186 a = ABL;
1187 break;
1188
1189 case OASLMUL:
1190 case OLMUL:
1191 case OASMUL:
1192 case OMUL:
1193 if(et == TFLOAT) {
1194 a = AFMULS;
1195 break;
1196 } else
1197 if(et == TDOUBLE) {
1198 a = AFMUL;
1199 break;
1200 }
1201 a = AMULLW;
1202 break;
1203
1204 case OASDIV:
1205 case ODIV:
1206 if(et == TFLOAT) {
1207 a = AFDIVS;
1208 break;
1209 } else
1210 if(et == TDOUBLE) {
1211 a = AFDIV;
1212 break;
1213 }
1214 a = ADIVW;
1215 break;
1216
1217 case OASMOD:
1218 case OMOD:
1219 a = AREM;
1220 break;
1221
1222 case OASLMOD:
1223 case OLMOD:
1224 a = AREMU;
1225 break;
1226
1227 case OASLDIV:
1228 case OLDIV:
1229 a = ADIVWU;
1230 break;
1231
1232 case OCOM:
1233 a = ANOR;
1234 break;
1235
1236 case ONEG:
1237 a = ANEG;
1238 if(et == TFLOAT || et == TDOUBLE)
1239 a = AFNEG;
1240 break;
1241
1242 case OEQ:
1243 a = ABEQ;
1244 if(t->op == OCONST && t->vconst >= (1<<15))
1245 goto cmpu;
1246 goto cmp;
1247
1248 case ONE:
1249 a = ABNE;
1250 if(t->op == OCONST && t->vconst >= (1<<15))
1251 goto cmpu;
1252 goto cmp;
1253
1254 case OLT:
1255 a = ABLT;
1256 goto cmp;
1257
1258 case OLE:
1259 a = ABLE;
1260 goto cmp;
1261
1262 case OGE:
1263 a = ABGE;
1264 goto cmp;
1265
1266 case OGT:
1267 a = ABGT;
1268 goto cmp;
1269
1270 case OLO:
1271 a = ABLT;
1272 goto cmpu;
1273
1274 case OLS:
1275 a = ABLE;
1276 goto cmpu;
1277
1278 case OHS:
1279 a = ABGE;
1280 goto cmpu;
1281
1282 case OHI:
1283 a = ABGT;
1284 goto cmpu;
1285
1286 cmpu:
1287 uns = 1;
1288 cmp:
1289 nextpc();
1290 p->as = uns? ACMPU: ACMP;
1291 if(et == TFLOAT)
1292 p->as = AFCMPU;
1293 else
1294 if(et == TDOUBLE)
1295 p->as = AFCMPU;
1296 if(f1 != Z)
1297 naddr(f1, &p->from);
1298 if(t != Z)
1299 naddr(t, &p->to);
1300 if(f1 == Z || t == Z || f2 != Z)
1301 diag(Z, "bad cmp in gopcode %O", o);
1302 if(debug['g'])
1303 print("%P\n", p);
1304 f1 = Z;
1305 f2 = Z;
1306 t = Z;
1307 break;
1308 }
1309 if(a == AGOK)
1310 diag(Z, "bad in gopcode %O", o);
1311 gins3(a, f1, f2, t);
1312 }
1313
1314 static void
gopcode64(int o,Node * f1,Node * f2,Node * t)1315 gopcode64(int o, Node *f1, Node *f2, Node *t)
1316 {
1317 int a1, a2;
1318 Node nod, nod1, nod2, sh;
1319 ulong m;
1320 Prog *p1;
1321
1322 if(t->op != OREGPAIR || f2 != Z && f2->op != OREGPAIR) {
1323 diag(Z, "bad f2/dest in gopcode64 %O", o);
1324 return;
1325 }
1326 if(f1->op != OCONST &&
1327 (typev[f1->type->etype] && f1->op != OREGPAIR || !typev[f1->type->etype] && f1->op != OREGISTER)) {
1328 diag(Z, "bad f1[%O] in gopcode64 %O", f1->op, o);
1329 return;
1330 }
1331 /* a1 for low-order, a2 for high-order */
1332 a1 = AGOK;
1333 a2 = AGOK;
1334 switch(o) {
1335 case OASADD:
1336 case OADD:
1337 if(f1->op == OCONST && sconst(f1)) {
1338 if(f2 == Z)
1339 f2 = t;
1340 gins3(AADDC, f1, f2->right, t->right);
1341 if((f1->vconst>>32) == 0)
1342 gins(AADDZE, f2->left, t->left);
1343 else if((f1->vconst>>32) == -1)
1344 gins(AADDME, f2->left, t->left);
1345 else
1346 diag(t, "odd vlong ADD: %lld", f1->vconst);
1347 return;
1348 }
1349 a1 = AADDC;
1350 a2 = AADDE;
1351 break;
1352
1353 case OASSUB:
1354 case OSUB:
1355 a1 = ASUBC;
1356 a2 = ASUBE;
1357 break;
1358
1359 case OASOR:
1360 case OOR:
1361 if(f1->op == OCONST) {
1362 gori64(AOR, f1, f2, t);
1363 return;
1364 }
1365 a1 = a2 = AOR;
1366 break;
1367
1368 case OASAND:
1369 case OAND:
1370 if(f1->op == OCONST) {
1371 gandi64(AANDCC, f1, f2, t);
1372 return;
1373 }
1374 a1 = a2 = AAND;
1375 break;
1376
1377 case OASXOR:
1378 case OXOR:
1379 if(f1->op == OCONST) {
1380 gori64(AXOR, f1, f2, t);
1381 return;
1382 }
1383 a1 = a2 = AXOR;
1384 break;
1385
1386 case OASLSHR:
1387 case OLSHR:
1388 if(f2 == Z)
1389 f2 = t;
1390 if(f1->op == OCONST) {
1391 if(f1->vconst >= 32) {
1392 if(f1->vconst == 32)
1393 gmove(f2->left, t->right);
1394 else if(f1->vconst < 64)
1395 gins3(ASRW, nodconst(f1->vconst-32), f2->left, t->right);
1396 else
1397 gmove(nodconst(0), t->right);
1398 gmove(nodconst(0), t->left);
1399 return;
1400 }
1401 if(f1->vconst <= 0) {
1402 if(f2 != t)
1403 gmove(f2, t);
1404 return;
1405 }
1406 sh = *nodconst(32 - f1->vconst);
1407 m = 0xFFFFFFFFUL >> f1->vconst;
1408 gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
1409 gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
1410 gins4(ARLWNM, &sh, f2->left, nodconst(m), t->left);
1411 return;
1412 }
1413 regalloc(&nod, ®node, Z);
1414 gins3(ASUBC, f1, nodconst(32), &nod);
1415 gins3(ASRW, f1, f2->right, t->right);
1416 regalloc(&nod1, ®node, Z);
1417 gins3(ASLW, &nod, f2->left, &nod1);
1418 gins(AOR, &nod1, t->right);
1419 gins3(AADD, nodconst(-32), f1, &nod);
1420 gins3(ASRW, &nod, f2->left, &nod1);
1421 gins(AOR, &nod1, t->right);
1422 gins3(ASRW, f1, f2->left, t->left);
1423 regfree(&nod);
1424 regfree(&nod1);
1425 return;
1426
1427 case OASASHR:
1428 case OASHR:
1429 if(f2 == Z)
1430 f2 = t;
1431 if(f1->op == OCONST) {
1432 if(f1->vconst >= 32) {
1433 if(f1->vconst == 32)
1434 gmove(f2->left, t->right);
1435 else if(f1->vconst < 64)
1436 gins3(ASRAW, nodconst(f1->vconst-32), f2->left, t->right);
1437 gins3(ASRAW, nodconst(31), f2->left, t->left);
1438 if(f1->vconst >= 64) {
1439 gmove(t->left, t->right);
1440 return;
1441 }
1442 return;
1443 }
1444 if(f1->vconst <= 0) {
1445 if(f2 != t)
1446 gmove(f2, t);
1447 return;
1448 }
1449 sh = *nodconst(32 - f1->vconst);
1450 m = 0xFFFFFFFFUL >> f1->vconst;
1451 gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
1452 gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
1453 gins3(ASRAW, &sh, f2->left, t->left);
1454 return;
1455 }
1456 regalloc(&nod, ®node, Z);
1457 gins3(ASUBC, f1, nodconst(32), &nod);
1458 gins3(ASRW, f1, f2->right, t->right);
1459 regalloc(&nod1, ®node, Z);
1460 gins3(ASLW, &nod, f2->left, &nod1);
1461 gins(AOR, &nod1, t->right);
1462 gins3(AADDCCC, nodconst(-32), f1, &nod);
1463 gins3(ASRAW, &nod, f2->left, &nod1);
1464 gins(ABLE, Z, Z);
1465 p1 = p;
1466 gins(AMOVW, &nod1, t->right);
1467 patch(p1, pc);
1468 gins3(ASRAW, f1, f2->left, t->left);
1469 regfree(&nod);
1470 regfree(&nod1);
1471 return;
1472
1473 case OASASHL:
1474 case OASHL:
1475 if(f2 == Z)
1476 f2 = t;
1477 if(f1->op == OCONST) {
1478 if(f1->vconst >= 32) {
1479 if(f1->vconst == 32)
1480 gmove(f2->right, t->left);
1481 else if(f1->vconst >= 64)
1482 gmove(nodconst(0), t->left);
1483 else
1484 gins3(ASLW, nodconst(f1->vconst-32), f2->right, t->left);
1485 gmove(nodconst(0), t->right);
1486 return;
1487 }
1488 if(f1->vconst <= 0) {
1489 if(f2 != t)
1490 gmove(f2, t);
1491 return;
1492 }
1493 m = 0xFFFFFFFFUL << f1->vconst;
1494 gins4(ARLWNM, f1, f2->left, nodconst(m), t->left);
1495 gins4(ARLWMI, f1, f2->right, nodconst(~m), t->left);
1496 gins4(ARLWNM, f1, f2->right, nodconst(m), t->right);
1497 return;
1498 }
1499 regalloc(&nod, ®node, Z);
1500 gins3(ASUBC, f1, nodconst(32), &nod);
1501 gins3(ASLW, f1, f2->left, t->left);
1502 regalloc(&nod1, ®node, Z);
1503 gins3(ASRW, &nod, f2->right, &nod1);
1504 gins(AOR, &nod1, t->left);
1505 gins3(AADD, nodconst(-32), f1, &nod);
1506 gins3(ASLW, &nod, f2->right, &nod1);
1507 gins(AOR, &nod1, t->left);
1508 gins3(ASLW, f1, f2->right, t->right);
1509 regfree(&nod);
1510 regfree(&nod1);
1511 return;
1512
1513 case OASLMUL:
1514 case OLMUL:
1515 case OASMUL:
1516 case OMUL:
1517 if(f2 == Z)
1518 f2 = t;
1519 regalloc(&nod, ®node, Z);
1520 gins3(AMULLW, f1->right, f2->right, &nod); /* lo(f2.low*f1.low) */
1521 regalloc(&nod1, ®node, Z);
1522 gins3(AMULHWU, f1->right, f2->right, &nod1); /* hi(f2.low*f1.low) */
1523 regalloc(&nod2, ®node, Z);
1524 gins3(AMULLW, f2->right, f1->left, &nod2); /* lo(f2.low*f1.high) */
1525 gins(AADD, &nod2, &nod1);
1526 gins3(AMULLW, f1->right, f2->left, &nod2); /* lo(f2.high*f1.low) */
1527 gins(AADD, &nod2, &nod1);
1528 regfree(&nod2);
1529 gmove(&nod, t->right);
1530 gmove(&nod1, t->left);
1531 regfree(&nod);
1532 regfree(&nod1);
1533 return;
1534
1535 case OCOM:
1536 a1 = a2 = ANOR;
1537 break;
1538
1539 case ONEG:
1540 gins3(ASUBC, t->right, nodconst(0), t->right);
1541 gins(ASUBZE, t->left, t->left);
1542 return;
1543 }
1544 if(a1 == AGOK || a2 == AGOK)
1545 diag(Z, "bad in gopcode64 %O", o);
1546 if(f1->op == OCONST) {
1547 if(f2 != Z & f2 != t)
1548 diag(Z, "bad const in gopcode64 %O", o);
1549 gins(a1, nod32const(f1->vconst), t->right);
1550 gins(a2, nod32const(f1->vconst>>32), t->left);
1551 } else {
1552 if(f2 != Z && f2 != t) {
1553 gins3(a1, f1->right, f2->right, t->right);
1554 gins3(a2, f1->left, f2->left, t->left);
1555 } else {
1556 gins(a1, f1->right, t->right);
1557 gins(a2, f1->left, t->left);
1558 }
1559 }
1560 }
1561
samaddr(Node * f,Node * t)1562 samaddr(Node *f, Node *t)
1563 {
1564
1565 if(f->op != t->op)
1566 return 0;
1567 switch(f->op) {
1568
1569 case OREGISTER:
1570 if(f->reg != t->reg)
1571 break;
1572 return 1;
1573
1574 case OREGPAIR:
1575 return samaddr(f->left, t->left) && samaddr(f->right, t->right);
1576 }
1577 return 0;
1578 }
1579
1580 static void
gori64(int a,Node * f1,Node * f2,Node * t)1581 gori64(int a, Node *f1, Node *f2, Node *t)
1582 {
1583 ulong lo, hi;
1584
1585 if(f2 == Z)
1586 f2 = t;
1587 lo = f1->vconst & MASK(32);
1588 hi = (f1->vconst >> 32) & MASK(32);
1589 if(lo & 0xFFFF)
1590 gins3(a, nodconst(lo & 0xFFFF), f2->right, t->right);
1591 if((lo >> 16) != 0)
1592 gins3(a, nodconst(lo & 0xFFFF0000UL), f2->right, t->right);
1593 if(hi & 0xFFFF)
1594 gins3(a, nodconst(hi & 0xFFFF), f2->left, t->left);
1595 if((hi >> 16) != 0)
1596 gins3(a, nodconst(hi & 0xFFFF0000UL), f2->left, t->left);
1597 }
1598
1599 static void
gandi64(int a,Node * f1,Node * f2,Node * t)1600 gandi64(int a, Node *f1, Node *f2, Node *t)
1601 {
1602 ulong lo, hi;
1603
1604 if(f2 == Z)
1605 f2 = t;
1606 lo = f1->vconst & MASK(32);
1607 hi = (f1->vconst >> 32) & MASK(32);
1608 if(lo == 0)
1609 gins(AMOVW, nodconst(0), t->right);
1610 else
1611 gins3(a, nodconst(lo), f2->right, t->right);
1612 if(hi == 0)
1613 gins(AMOVW, nodconst(0), t->left);
1614 else
1615 gins3(a, nodconst(hi), f2->left, t->left);
1616 }
1617
1618 void
gbranch(int o)1619 gbranch(int o)
1620 {
1621 int a;
1622
1623 a = AGOK;
1624 switch(o) {
1625 case ORETURN:
1626 a = ARETURN;
1627 break;
1628 case OGOTO:
1629 a = ABR;
1630 break;
1631 }
1632 nextpc();
1633 if(a == AGOK) {
1634 diag(Z, "bad in gbranch %O", o);
1635 nextpc();
1636 }
1637 p->as = a;
1638 }
1639
1640 void
patch(Prog * op,long pc)1641 patch(Prog *op, long pc)
1642 {
1643
1644 op->to.offset = pc;
1645 op->to.type = D_BRANCH;
1646 }
1647
1648 void
gpseudo(int a,Sym * s,Node * n)1649 gpseudo(int a, Sym *s, Node *n)
1650 {
1651
1652 nextpc();
1653 p->as = a;
1654 p->from.type = D_OREG;
1655 p->from.sym = s;
1656 if(a == ATEXT)
1657 p->reg = (profileflg ? 0 : NOPROF);
1658 p->from.name = D_EXTERN;
1659 if(s->class == CSTATIC)
1660 p->from.name = D_STATIC;
1661 naddr(n, &p->to);
1662 if(a == ADATA || a == AGLOBL)
1663 pc--;
1664 }
1665
1666 int
sval(long v)1667 sval(long v)
1668 {
1669
1670 if(v >= -(1<<15) && v < (1<<15))
1671 return 1;
1672 return 0;
1673 }
1674
1675 int
sconst(Node * n)1676 sconst(Node *n)
1677 {
1678 vlong vv;
1679
1680 if(n->op == OCONST) {
1681 if(!typefd[n->type->etype]) {
1682 vv = n->vconst;
1683 if(vv >= -(((vlong)1)<<15) && vv < (((vlong)1)<<15))
1684 return 1;
1685 }
1686 }
1687 return 0;
1688 }
1689
1690 int
uconst(Node * n)1691 uconst(Node *n)
1692 {
1693 vlong vv;
1694
1695 if(n->op == OCONST) {
1696 if(!typefd[n->type->etype]) {
1697 vv = n->vconst;
1698 if(vv >= 0 && vv < (((vlong)1)<<16))
1699 return 1;
1700 }
1701 }
1702 return 0;
1703 }
1704
1705 long
exreg(Type * t)1706 exreg(Type *t)
1707 {
1708 long o;
1709
1710 if(typechlp[t->etype]) {
1711 if(exregoffset <= 3)
1712 return 0;
1713 o = exregoffset;
1714 exregoffset--;
1715 return o;
1716 }
1717 if(typefd[t->etype]) {
1718 if(exfregoffset <= 16)
1719 return 0;
1720 o = exfregoffset + NREG;
1721 exfregoffset--;
1722 return o;
1723 }
1724 return 0;
1725 }
1726
1727 schar ewidth[NTYPE] =
1728 {
1729 -1, /* [TXXX] */
1730 SZ_CHAR, /* [TCHAR] */
1731 SZ_CHAR, /* [TUCHAR] */
1732 SZ_SHORT, /* [TSHORT] */
1733 SZ_SHORT, /* [TUSHORT] */
1734 SZ_INT, /* [TINT] */
1735 SZ_INT, /* [TUINT] */
1736 SZ_LONG, /* [TLONG] */
1737 SZ_LONG, /* [TULONG] */
1738 SZ_VLONG, /* [TVLONG] */
1739 SZ_VLONG, /* [TUVLONG] */
1740 SZ_FLOAT, /* [TFLOAT] */
1741 SZ_DOUBLE, /* [TDOUBLE] */
1742 SZ_IND, /* [TIND] */
1743 0, /* [TFUNC] */
1744 -1, /* [TARRAY] */
1745 0, /* [TVOID] */
1746 -1, /* [TSTRUCT] */
1747 -1, /* [TUNION] */
1748 SZ_INT, /* [TENUM] */
1749 };
1750 long ncast[NTYPE] =
1751 {
1752 0, /* [TXXX] */
1753 BCHAR|BUCHAR, /* [TCHAR] */
1754 BCHAR|BUCHAR, /* [TUCHAR] */
1755 BSHORT|BUSHORT, /* [TSHORT] */
1756 BSHORT|BUSHORT, /* [TUSHORT] */
1757 BINT|BUINT|BLONG|BULONG|BIND, /* [TINT] */
1758 BINT|BUINT|BLONG|BULONG|BIND, /* [TUINT] */
1759 BINT|BUINT|BLONG|BULONG|BIND, /* [TLONG] */
1760 BINT|BUINT|BLONG|BULONG|BIND, /* [TULONG] */
1761 BVLONG|BUVLONG, /* [TVLONG] */
1762 BVLONG|BUVLONG, /* [TUVLONG] */
1763 BFLOAT, /* [TFLOAT] */
1764 BDOUBLE, /* [TDOUBLE] */
1765 BLONG|BULONG|BIND, /* [TIND] */
1766 0, /* [TFUNC] */
1767 0, /* [TARRAY] */
1768 0, /* [TVOID] */
1769 BSTRUCT, /* [TSTRUCT] */
1770 BUNION, /* [TUNION] */
1771 0, /* [TENUM] */
1772 };
1773