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