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