]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/8c/txt.c
python: update python build configuration to new ape capabilities like getaddrinfo...
[plan9front.git] / sys / src / cmd / 8c / txt.c
1 #include "gc.h"
2
3 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
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
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
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
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
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*
237 nodconst(long v)
238 {
239         constnode.vconst = v;
240         return &constnode;
241 }
242
243 Node*
244 nodfconst(double d)
245 {
246         fconstnode.fconst = d;
247         return &fconstnode;
248 }
249
250 int
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
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
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
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, &regnode, o->left);
333                         regalloc(n->right, &regnode, o->right);
334                 } else {
335                         regalloc(n->left, &regnode, Z);
336                         regalloc(n->right, &regnode, 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
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
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
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
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
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
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
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
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, &regnode);
844                         gins(AFMOVLP, f, &nod);
845                         gmove(&nod, t);
846                         return;
847                 }
848                 regsalloc(&nod, &regnode);
849                 regsalloc(&nod1, &regnode);
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, &regnode);
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, &regnode);
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, &regnode);
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
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, &regnode, 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, &regnode, 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
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
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, &regnode, 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
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
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
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
1349 patch(Prog *op, long pc)
1350 {
1351
1352         op->to.offset = pc;
1353         op->to.type = D_BRANCH;
1354 }
1355
1356 void
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
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
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 };