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