]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/8c/txt.c
8c, 6c: native ROL (cyclic shift) instruction support, improve peephole optimizers
[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                 goto err;
315
316         case TFLOAT:
317         case TDOUBLE:
318                 i = D_F0;
319                 goto out;
320
321         case TVLONG:
322         case TUVLONG:
323                 n->op = OREGPAIR;
324                 n->complex = 0; /* already in registers */
325                 n->addable = 11;
326                 n->type = tn->type;
327                 n->lineno = nearln;
328                 n->left = alloc(sizeof(Node));
329                 n->right = alloc(sizeof(Node));
330                 if(o != Z && o->op == OREGPAIR) {
331                         regalloc(n->left, &regnode, o->left);
332                         regalloc(n->right, &regnode, o->right);
333                 } else {
334                         regalloc(n->left, &regnode, Z);
335                         regalloc(n->right, &regnode, Z);
336                 }
337                 n->right->type = types[TULONG];
338                 if(tn->type->etype == TUVLONG)
339                         n->left->type = types[TULONG];
340                 return;
341         }
342         diag(tn, "unknown type in regalloc: %T", tn->type);
343 err:
344         i = 0;
345 out:
346         if(i)
347                 reg[i]++;
348         nodreg(n, tn, i);
349 //print("+ %R %d\n", i, reg[i]);
350 }
351
352 void
353 regialloc(Node *n, Node *tn, Node *o)
354 {
355         Node nod;
356
357         nod = *tn;
358         nod.type = types[TIND];
359         regalloc(n, &nod, o);
360 }
361
362 void
363 regfree(Node *n)
364 {
365         int i;
366
367         if(n->op == OREGPAIR) {
368                 regfree(n->left);
369                 regfree(n->right);
370                 return;
371         }
372
373         i = 0;
374         if(n->op != OREGISTER && n->op != OINDREG)
375                 goto err;
376         i = n->reg;
377         if(i < 0 || i >= sizeof(reg))
378                 goto err;
379         if(reg[i] <= 0)
380                 goto err;
381         reg[i]--;
382 //print("- %R %d\n", i, reg[i]);
383         return;
384 err:
385         diag(n, "error in regfree: %R", i);
386 }
387
388 void
389 regsalloc(Node *n, Node *nn)
390 {
391         cursafe = align(cursafe, nn->type, Aaut3);
392         maxargsafe = maxround(maxargsafe, cursafe+curarg);
393         *n = *nodsafe;
394         n->xoffset = -(stkoff + cursafe);
395         n->type = nn->type;
396         n->etype = nn->type->etype;
397         n->lineno = nn->lineno;
398 }
399
400 void
401 regaalloc1(Node *n, Node *nn)
402 {
403         USED(nn);
404
405         if(REGARG < 0) {
406                 diag(n, "regaalloc1");
407                 return;
408         }
409 /* not reached 
410         nodreg(n, nn, REGARG);
411         reg[REGARG]++;
412         curarg = align(curarg, nn->type, Aarg1);
413         curarg = align(curarg, nn->type, Aarg2);
414         maxargsafe = maxround(maxargsafe, cursafe+curarg);
415 */
416 }
417
418 void
419 regaalloc(Node *n, Node *nn)
420 {
421         curarg = align(curarg, nn->type, Aarg1);
422         *n = *nn;
423         n->op = OINDREG;
424         n->reg = REGSP;
425         n->xoffset = curarg;
426         n->complex = 0;
427         n->addable = 20;
428         curarg = align(curarg, nn->type, Aarg2);
429         maxargsafe = maxround(maxargsafe, cursafe+curarg);
430 }
431
432 void
433 regind(Node *n, Node *nn)
434 {
435
436         if(n->op != OREGISTER) {
437                 diag(n, "regind not OREGISTER");
438                 return;
439         }
440         n->op = OINDREG;
441         n->type = nn->type;
442 }
443
444 void
445 naddr(Node *n, Adr *a)
446 {
447         long v;
448
449         a->type = D_NONE;
450         if(n == Z)
451                 return;
452         switch(n->op) {
453         default:
454         bad:
455                 diag(n, "bad in naddr: %O %D", n->op, a);
456 //prtree(n, "naddr");
457                 break;
458
459         case OREGISTER:
460                 a->type = n->reg;
461                 a->sym = S;
462                 break;
463
464         case OEXREG:
465                 a->type = D_INDIR + D_GS;
466                 a->offset = n->reg - 1;
467                 a->etype = n->etype;
468                 break;
469
470         case OIND:
471                 naddr(n->left, a);
472                 if(a->type >= D_AX && a->type <= D_DI)
473                         a->type += D_INDIR;
474                 else
475                 if(a->type == D_CONST)
476                         a->type = D_NONE+D_INDIR;
477                 else
478                 if(a->type == D_ADDR) {
479                         a->type = a->index;
480                         a->index = D_NONE;
481                 } else
482                         goto bad;
483                 break;
484
485         case OINDEX:
486                 a->type = idx.ptr;
487                 if(n->left->op == OADDR || n->left->op == OCONST)
488                         naddr(n->left, a);
489                 if(a->type >= D_AX && a->type <= D_DI)
490                         a->type += D_INDIR;
491                 else
492                 if(a->type == D_CONST)
493                         a->type = D_NONE+D_INDIR;
494                 else
495                 if(a->type == D_ADDR) {
496                         a->type = a->index;
497                         a->index = D_NONE;
498                 } else
499                         goto bad;
500                 a->index = idx.reg;
501                 a->scale = n->scale;
502                 a->offset += n->xoffset;
503                 break;
504
505         case OINDREG:
506                 a->type = n->reg+D_INDIR;
507                 a->sym = S;
508                 a->offset = n->xoffset;
509                 break;
510
511         case ONAME:
512                 a->etype = n->etype;
513                 a->type = D_STATIC;
514                 a->sym = n->sym;
515                 a->offset = n->xoffset;
516                 if(n->class == CSTATIC)
517                         break;
518                 if(n->class == CEXTERN || n->class == CGLOBL) {
519                         a->type = D_EXTERN;
520                         break;
521                 }
522                 if(n->class == CAUTO) {
523                         a->type = D_AUTO;
524                         break;
525                 }
526                 if(n->class == CPARAM) {
527                         a->type = D_PARAM;
528                         break;
529                 }
530                 goto bad;
531
532         case OCONST:
533                 if(typefd[n->type->etype]) {
534                         a->type = D_FCONST;
535                         a->dval = n->fconst;
536                         break;
537                 }
538                 a->sym = S;
539                 a->type = D_CONST;
540                 a->offset = n->vconst;
541                 break;
542
543         case OADDR:
544                 naddr(n->left, a);
545                 if(a->type >= D_INDIR) {
546                         a->type -= D_INDIR;
547                         break;
548                 }
549                 if(a->type == D_EXTERN || a->type == D_STATIC ||
550                    a->type == D_AUTO || a->type == D_PARAM)
551                         if(a->index == D_NONE) {
552                                 a->index = a->type;
553                                 a->type = D_ADDR;
554                                 break;
555                         }
556                 goto bad;
557
558         case OADD:
559                 if(n->right->op == OCONST) {
560                         v = n->right->vconst;
561                         naddr(n->left, a);
562                 } else
563                 if(n->left->op == OCONST) {
564                         v = n->left->vconst;
565                         naddr(n->right, a);
566                 } else
567                         goto bad;
568                 a->offset += v;
569                 break;
570
571         }
572 }
573
574 #define CASE(a,b)       ((a<<8)|(b<<0))
575
576 void
577 gmove(Node *f, Node *t)
578 {
579         int ft, tt, a;
580         Node nod, nod1;
581         Prog *p1;
582
583         ft = f->type->etype;
584         tt = t->type->etype;
585         if(debug['M'])
586                 print("gop: %O %O[%s],%O[%s]\n", OAS,
587                         f->op, tnames[ft], t->op, tnames[tt]);
588         if(typefd[ft] && f->op == OCONST) {
589                 if(f->fconst == 0)
590                         gins(AFLDZ, Z, Z);
591                 else
592                 if(f->fconst == 1)
593                         gins(AFLD1, Z, Z);
594                 else
595                         gins(AFMOVD, f, &fregnode0);
596                 gmove(&fregnode0, t);
597                 return;
598         }
599 /*
600  * load
601  */
602         if(f->op == ONAME || f->op == OINDREG ||
603            f->op == OIND || f->op == OINDEX)
604         switch(ft) {
605         case TCHAR:
606                 a = AMOVBLSX;
607                 goto ld;
608         case TUCHAR:
609                 a = AMOVBLZX;
610                 goto ld;
611         case TSHORT:
612                 if(typefd[tt]) {
613                         gins(AFMOVW, f, &fregnode0);
614                         gmove(&fregnode0, t);
615                         return;
616                 }
617                 a = AMOVWLSX;
618                 goto ld;
619         case TUSHORT:
620                 a = AMOVWLZX;
621                 goto ld;
622         case TINT:
623         case TLONG:
624                 if(typefd[tt]) {
625                         gins(AFMOVL, f, &fregnode0);
626                         gmove(&fregnode0, t);
627                         return;
628                 }
629         case TUINT:
630         case TULONG:
631         case TIND:
632                 a = AMOVL;
633         ld:
634                 regalloc(&nod, f, t);
635                 gins(a, f, &nod);
636                 gmove(&nod, t);
637                 regfree(&nod);
638                 return;
639
640         case TFLOAT:
641                 gins(AFMOVF, f, t);
642                 return;
643         case TDOUBLE:
644                 gins(AFMOVD, f, t);
645                 return;
646         }
647
648 /*
649  * store
650  */
651         if(t->op == ONAME || t->op == OINDREG ||
652            t->op == OIND || t->op == OINDEX)
653         switch(tt) {
654         case TCHAR:
655         case TUCHAR:
656                 a = AMOVB;      goto st;
657         case TSHORT:
658         case TUSHORT:
659                 a = AMOVW;      goto st;
660         case TINT:
661         case TUINT:
662         case TLONG:
663         case TULONG:
664         case TIND:
665                 a = AMOVL;      goto st;
666
667         st:
668                 if(f->op == OCONST) {
669                         gins(a, f, t);
670                         return;
671                 }
672                 regalloc(&nod, t, f);
673                 gmove(f, &nod);
674                 gins(a, &nod, t);
675                 regfree(&nod);
676                 return;
677
678         case TFLOAT:
679                 gins(AFMOVFP, f, t);
680                 return;
681         case TDOUBLE:
682                 gins(AFMOVDP, f, t);
683                 return;
684         }
685
686 /*
687  * convert
688  */
689         switch(CASE(ft,tt)) {
690         default:
691 /*
692  * integer to integer
693  ********
694                 a = AGOK;       break;
695
696         case CASE(      TCHAR,  TCHAR):
697         case CASE(      TUCHAR, TCHAR):
698         case CASE(      TSHORT, TCHAR):
699         case CASE(      TUSHORT,TCHAR):
700         case CASE(      TINT,   TCHAR):
701         case CASE(      TUINT,  TCHAR):
702         case CASE(      TLONG,  TCHAR):
703         case CASE(      TULONG, TCHAR):
704         case CASE(      TIND,   TCHAR):
705
706         case CASE(      TCHAR,  TUCHAR):
707         case CASE(      TUCHAR, TUCHAR):
708         case CASE(      TSHORT, TUCHAR):
709         case CASE(      TUSHORT,TUCHAR):
710         case CASE(      TINT,   TUCHAR):
711         case CASE(      TUINT,  TUCHAR):
712         case CASE(      TLONG,  TUCHAR):
713         case CASE(      TULONG, TUCHAR):
714         case CASE(      TIND,   TUCHAR):
715
716         case CASE(      TSHORT, TSHORT):
717         case CASE(      TUSHORT,TSHORT):
718         case CASE(      TINT,   TSHORT):
719         case CASE(      TUINT,  TSHORT):
720         case CASE(      TLONG,  TSHORT):
721         case CASE(      TULONG, TSHORT):
722         case CASE(      TIND,   TSHORT):
723
724         case CASE(      TSHORT, TUSHORT):
725         case CASE(      TUSHORT,TUSHORT):
726         case CASE(      TINT,   TUSHORT):
727         case CASE(      TUINT,  TUSHORT):
728         case CASE(      TLONG,  TUSHORT):
729         case CASE(      TULONG, TUSHORT):
730         case CASE(      TIND,   TUSHORT):
731
732         case CASE(      TINT,   TINT):
733         case CASE(      TUINT,  TINT):
734         case CASE(      TLONG,  TINT):
735         case CASE(      TULONG, TINT):
736         case CASE(      TIND,   TINT):
737
738         case CASE(      TINT,   TUINT):
739         case CASE(      TUINT,  TUINT):
740         case CASE(      TLONG,  TUINT):
741         case CASE(      TULONG, TUINT):
742         case CASE(      TIND,   TUINT):
743
744         case CASE(      TINT,   TLONG):
745         case CASE(      TUINT,  TLONG):
746         case CASE(      TLONG,  TLONG):
747         case CASE(      TULONG, TLONG):
748         case CASE(      TIND,   TLONG):
749
750         case CASE(      TINT,   TULONG):
751         case CASE(      TUINT,  TULONG):
752         case CASE(      TLONG,  TULONG):
753         case CASE(      TULONG, TULONG):
754         case CASE(      TIND,   TULONG):
755
756         case CASE(      TINT,   TIND):
757         case CASE(      TUINT,  TIND):
758         case CASE(      TLONG,  TIND):
759         case CASE(      TULONG, TIND):
760         case CASE(      TIND,   TIND):
761  *****/
762                 a = AMOVL;
763                 break;
764
765         case CASE(      TSHORT, TINT):
766         case CASE(      TSHORT, TUINT):
767         case CASE(      TSHORT, TLONG):
768         case CASE(      TSHORT, TULONG):
769         case CASE(      TSHORT, TIND):
770                 a = AMOVWLSX;
771                 if(f->op == OCONST) {
772                         f->vconst &= 0xffff;
773                         if(f->vconst & 0x8000)
774                                 f->vconst |= 0xffff0000;
775                         a = AMOVL;
776                 }
777                 break;
778
779         case CASE(      TUSHORT,TINT):
780         case CASE(      TUSHORT,TUINT):
781         case CASE(      TUSHORT,TLONG):
782         case CASE(      TUSHORT,TULONG):
783         case CASE(      TUSHORT,TIND):
784                 a = AMOVWLZX;
785                 if(f->op == OCONST) {
786                         f->vconst &= 0xffff;
787                         a = AMOVL;
788                 }
789                 break;
790
791         case CASE(      TCHAR,  TSHORT):
792         case CASE(      TCHAR,  TUSHORT):
793         case CASE(      TCHAR,  TINT):
794         case CASE(      TCHAR,  TUINT):
795         case CASE(      TCHAR,  TLONG):
796         case CASE(      TCHAR,  TULONG):
797         case CASE(      TCHAR,  TIND):
798                 a = AMOVBLSX;
799                 if(f->op == OCONST) {
800                         f->vconst &= 0xff;
801                         if(f->vconst & 0x80)
802                                 f->vconst |= 0xffffff00;
803                         a = AMOVL;
804                 }
805                 break;
806
807         case CASE(      TUCHAR, TSHORT):
808         case CASE(      TUCHAR, TUSHORT):
809         case CASE(      TUCHAR, TINT):
810         case CASE(      TUCHAR, TUINT):
811         case CASE(      TUCHAR, TLONG):
812         case CASE(      TUCHAR, TULONG):
813         case CASE(      TUCHAR, TIND):
814                 a = AMOVBLZX;
815                 if(f->op == OCONST) {
816                         f->vconst &= 0xff;
817                         a = AMOVL;
818                 }
819                 break;
820
821 /*
822  * float to fix
823  */
824         case CASE(      TFLOAT, TCHAR):
825         case CASE(      TFLOAT, TUCHAR):
826         case CASE(      TFLOAT, TSHORT):
827         case CASE(      TFLOAT, TUSHORT):
828         case CASE(      TFLOAT, TINT):
829         case CASE(      TFLOAT, TLONG):
830         case CASE(      TFLOAT, TIND):
831
832         case CASE(      TDOUBLE,TCHAR):
833         case CASE(      TDOUBLE,TUCHAR):
834         case CASE(      TDOUBLE,TSHORT):
835         case CASE(      TDOUBLE,TUSHORT):
836         case CASE(      TDOUBLE,TINT):
837         case CASE(      TDOUBLE,TLONG):
838         case CASE(      TDOUBLE,TIND):
839                 if(fproundflg) {
840                         regsalloc(&nod, &regnode);
841                         gins(AFMOVLP, f, &nod);
842                         gmove(&nod, t);
843                         return;
844                 }
845                 regsalloc(&nod, &regnode);
846                 regsalloc(&nod1, &regnode);
847                 gins(AFSTCW, Z, &nod1);
848                 nod1.xoffset += 2;
849                 gins(AMOVW, nodconst(0xf7f), &nod1);
850                 gins(AFLDCW, &nod1, Z);
851                 gins(AFMOVLP, f, &nod);
852                 nod1.xoffset -= 2;
853                 gins(AFLDCW, &nod1, Z);
854                 gmove(&nod, t);
855                 return;
856
857 /*
858  * float to ulong
859  */
860         case CASE(      TDOUBLE,        TULONG):
861         case CASE(      TFLOAT, TULONG):
862         case CASE(      TDOUBLE,        TUINT):
863         case CASE(      TFLOAT, TUINT):
864                 regsalloc(&nod, &regnode);
865                 gmove(f, &fregnode0);
866                 gins(AFADDD, nodfconst(-2147483648.), &fregnode0);
867                 gins(AFMOVLP, f, &nod);
868                 gins(ASUBL, nodconst(-2147483648), &nod);
869                 gmove(&nod, t);
870                 return;
871
872 /*
873  * ulong to float
874  */
875         case CASE(      TULONG, TDOUBLE):
876         case CASE(      TULONG, TFLOAT):
877         case CASE(      TUINT,  TDOUBLE):
878         case CASE(      TUINT,  TFLOAT):
879                 regalloc(&nod, f, f);
880                 gmove(f, &nod);
881                 regsalloc(&nod1, &regnode);
882                 gmove(&nod, &nod1);
883                 gins(AFMOVL, &nod1, &fregnode0);
884                 gins(ACMPL, &nod, nodconst(0));
885                 gins(AJGE, Z, Z);
886                 p1 = p;
887                 gins(AFADDD, nodfconst(4294967296.), &fregnode0);
888                 patch(p1, pc);
889                 regfree(&nod);
890                 return;
891
892 /*
893  * fix to float
894  */
895         case CASE(      TCHAR,  TFLOAT):
896         case CASE(      TUCHAR, TFLOAT):
897         case CASE(      TSHORT, TFLOAT):
898         case CASE(      TUSHORT,TFLOAT):
899         case CASE(      TINT,   TFLOAT):
900         case CASE(      TLONG,  TFLOAT):
901         case CASE(      TIND,   TFLOAT):
902
903         case CASE(      TCHAR,  TDOUBLE):
904         case CASE(      TUCHAR, TDOUBLE):
905         case CASE(      TSHORT, TDOUBLE):
906         case CASE(      TUSHORT,TDOUBLE):
907         case CASE(      TINT,   TDOUBLE):
908         case CASE(      TLONG,  TDOUBLE):
909         case CASE(      TIND,   TDOUBLE):
910                 regsalloc(&nod, &regnode);
911                 gmove(f, &nod);
912                 gins(AFMOVL, &nod, &fregnode0);
913                 return;
914
915 /*
916  * float to float
917  */
918         case CASE(      TFLOAT, TFLOAT):
919         case CASE(      TDOUBLE,TFLOAT):
920
921         case CASE(      TFLOAT, TDOUBLE):
922         case CASE(      TDOUBLE,TDOUBLE):
923                 a = AFMOVD;     break;
924         }
925         if(a == AMOVL || a == AFMOVD)
926         if(samaddr(f, t))
927                 return;
928         gins(a, f, t);
929 }
930
931 void
932 doindex(Node *n)
933 {
934         Node nod, nod1;
935         long v;
936
937 if(debug['Y'])
938 prtree(n, "index");
939
940 if(n->left->complex >= FNX)
941 print("botch in doindex\n");
942
943         regalloc(&nod, &regnode, Z);
944         v = constnode.vconst;
945         cgen(n->right, &nod);
946         idx.ptr = D_NONE;
947         if(n->left->op == OCONST)
948                 idx.ptr = D_CONST;
949         else if(n->left->op == OREGISTER)
950 //      else if(n->left->op == OREGISTER && typeil[n->left->type->etype])
951                 idx.ptr = n->left->reg;
952         else if(n->left->op != OADDR) {
953                 reg[D_BP]++;    // cant be used as a base
954                 regalloc(&nod1, &regnode, Z);
955                 cgen(n->left, &nod1);
956                 idx.ptr = nod1.reg;
957                 regfree(&nod1);
958                 reg[D_BP]--;
959         }
960         idx.reg = nod.reg;
961         regfree(&nod);
962         constnode.vconst = v;
963 }
964
965 void
966 gins(int a, Node *f, Node *t)
967 {
968
969         if(f != Z && f->op == OINDEX)
970                 doindex(f);
971         if(t != Z && t->op == OINDEX)
972                 doindex(t);
973         nextpc();
974         p->as = a;
975         if(f != Z)
976                 naddr(f, &p->from);
977         if(t != Z)
978                 naddr(t, &p->to);
979         if(debug['g'])
980                 print("%P\n", p);
981 }
982
983 void
984 fgopcode(int o, Node *f, Node *t, int pop, int rev)
985 {
986         int a, et;
987         Node nod;
988
989         et = TLONG;
990         if(f != Z && f->type != T)
991                 et = f->type->etype;
992         if(!typefd[et]) {
993                 diag(f, "fop: integer %O", o);
994                 return;
995         }
996         if(debug['M']) {
997                 if(t != Z && t->type != T)
998                         print("gop: %O %O-%s Z\n", o, f->op, tnames[et]);
999                 else
1000                         print("gop: %O %O-%s %O-%s\n", o,
1001                                 f->op, tnames[et], t->op, tnames[t->type->etype]);
1002         }
1003         a = AGOK;
1004         switch(o) {
1005
1006         case OASADD:
1007         case OADD:
1008                 if(et == TFLOAT)
1009                         a = AFADDF;
1010                 else
1011                 if(et == TDOUBLE) {
1012                         a = AFADDD;
1013                         if(pop)
1014                                 a = AFADDDP;
1015                 }
1016                 break;
1017
1018         case OASSUB:
1019         case OSUB:
1020                 if(et == TFLOAT) {
1021                         a = AFSUBF;
1022                         if(rev)
1023                                 a = AFSUBRF;
1024                 } else
1025                 if(et == TDOUBLE) {
1026                         a = AFSUBD;
1027                         if(pop)
1028                                 a = AFSUBDP;
1029                         if(rev) {
1030                                 a = AFSUBRD;
1031                                 if(pop)
1032                                         a = AFSUBRDP;
1033                         }
1034                 }
1035                 break;
1036
1037         case OASMUL:
1038         case OMUL:
1039                 if(et == TFLOAT)
1040                         a = AFMULF;
1041                 else
1042                 if(et == TDOUBLE) {
1043                         a = AFMULD;
1044                         if(pop)
1045                                 a = AFMULDP;
1046                 }
1047                 break;
1048
1049         case OASMOD:
1050         case OMOD:
1051         case OASDIV:
1052         case ODIV:
1053                 if(et == TFLOAT) {
1054                         a = AFDIVF;
1055                         if(rev)
1056                                 a = AFDIVRF;
1057                 } else
1058                 if(et == TDOUBLE) {
1059                         a = AFDIVD;
1060                         if(pop)
1061                                 a = AFDIVDP;
1062                         if(rev) {
1063                                 a = AFDIVRD;
1064                                 if(pop)
1065                                         a = AFDIVRDP;
1066                         }
1067                 }
1068                 break;
1069
1070         case OEQ:
1071         case ONE:
1072         case OLT:
1073         case OLE:
1074         case OGE:
1075         case OGT:
1076                 pop += rev;
1077                 if(et == TFLOAT) {
1078                         a = AFCOMF;
1079                         if(pop) {
1080                                 a = AFCOMFP;
1081                                 if(pop > 1)
1082                                         a = AGOK;
1083                         }
1084                 } else
1085                 if(et == TDOUBLE) {
1086                         a = AFCOMF;
1087                         if(pop) {
1088                                 a = AFCOMDP;
1089                                 if(pop > 1)
1090                                         a = AFCOMDPP;
1091                         }
1092                 }
1093                 gins(a, f, t);
1094                 regalloc(&nod, &regnode, Z);
1095                 if(nod.reg != D_AX) {
1096                         regfree(&nod);
1097                         nod.reg = D_AX;
1098                         gins(APUSHL, &nod, Z);
1099                         gins(AWAIT, Z, Z);
1100                         gins(AFSTSW, Z, &nod);
1101                         gins(ASAHF, Z, Z);
1102                         gins(APOPL, Z, &nod);
1103                 } else {
1104                         gins(AWAIT, Z, Z);
1105                         gins(AFSTSW, Z, &nod);
1106                         gins(ASAHF, Z, Z);
1107                         regfree(&nod);
1108                 }
1109                 switch(o) {
1110                 case OEQ:       a = AJEQ; break;
1111                 case ONE:       a = AJNE; break;
1112                 case OLT:       a = AJCS; break;
1113                 case OLE:       a = AJLS; break;
1114                 case OGE:       a = AJCC; break;
1115                 case OGT:       a = AJHI; break;
1116                 }
1117                 gins(a, Z, Z);
1118                 return;
1119         }
1120         if(a == AGOK)
1121                 diag(Z, "bad in gopcode %O", o);
1122         gins(a, f, t);
1123 }
1124
1125 void
1126 gopcode(int o, Type *ty, Node *f, Node *t)
1127 {
1128         int a, et;
1129
1130         et = TLONG;
1131         if(ty != T)
1132                 et = ty->etype;
1133         if(typefd[et] && o != OADDR && o != OFUNC) {
1134                 diag(f, "gop: float %O", o);
1135                 return;
1136         }
1137         if(debug['M']) {
1138                 if(f != Z && f->type != T)
1139                         print("gop: %O %O[%s],", o, f->op, tnames[et]);
1140                 else
1141                         print("gop: %O Z,", o);
1142                 if(t != Z && t->type != T)
1143                         print("%O[%s]\n", t->op, tnames[t->type->etype]);
1144                 else
1145                         print("Z\n");
1146         }
1147         a = AGOK;
1148         switch(o) {
1149         case OCOM:
1150                 a = ANOTL;
1151                 if(et == TCHAR || et == TUCHAR)
1152                         a = ANOTB;
1153                 if(et == TSHORT || et == TUSHORT)
1154                         a = ANOTW;
1155                 break;
1156
1157         case ONEG:
1158                 a = ANEGL;
1159                 if(et == TCHAR || et == TUCHAR)
1160                         a = ANEGB;
1161                 if(et == TSHORT || et == TUSHORT)
1162                         a = ANEGW;
1163                 break;
1164
1165         case OADDR:
1166                 a = ALEAL;
1167                 break;
1168
1169         case OASADD:
1170         case OADD:
1171                 a = AADDL;
1172                 if(et == TCHAR || et == TUCHAR)
1173                         a = AADDB;
1174                 if(et == TSHORT || et == TUSHORT)
1175                         a = AADDW;
1176                 break;
1177
1178         case OASSUB:
1179         case OSUB:
1180                 a = ASUBL;
1181                 if(et == TCHAR || et == TUCHAR)
1182                         a = ASUBB;
1183                 if(et == TSHORT || et == TUSHORT)
1184                         a = ASUBW;
1185                 break;
1186
1187         case OASOR:
1188         case OOR:
1189                 a = AORL;
1190                 if(et == TCHAR || et == TUCHAR)
1191                         a = AORB;
1192                 if(et == TSHORT || et == TUSHORT)
1193                         a = AORW;
1194                 break;
1195
1196         case OASAND:
1197         case OAND:
1198                 a = AANDL;
1199                 if(et == TCHAR || et == TUCHAR)
1200                         a = AANDB;
1201                 if(et == TSHORT || et == TUSHORT)
1202                         a = AANDW;
1203                 break;
1204
1205         case OASXOR:
1206         case OXOR:
1207                 a = AXORL;
1208                 if(et == TCHAR || et == TUCHAR)
1209                         a = AXORB;
1210                 if(et == TSHORT || et == TUSHORT)
1211                         a = AXORW;
1212                 break;
1213
1214         case OASLSHR:
1215         case OLSHR:
1216                 a = ASHRL;
1217                 if(et == TCHAR || et == TUCHAR)
1218                         a = ASHRB;
1219                 if(et == TSHORT || et == TUSHORT)
1220                         a = ASHRW;
1221                 break;
1222
1223         case OASASHR:
1224         case OASHR:
1225                 a = ASARL;
1226                 if(et == TCHAR || et == TUCHAR)
1227                         a = ASARB;
1228                 if(et == TSHORT || et == TUSHORT)
1229                         a = ASARW;
1230                 break;
1231
1232         case OASASHL:
1233         case OASHL:
1234                 a = ASALL;
1235                 if(et == TCHAR || et == TUCHAR)
1236                         a = ASALB;
1237                 if(et == TSHORT || et == TUSHORT)
1238                         a = ASALW;
1239                 break;
1240
1241         case OROL:
1242                 a = AROLL;
1243                 if(et == TCHAR || et == TUCHAR)
1244                         a = AROLB;
1245                 if(et == TSHORT || et == TUSHORT)
1246                         a = AROLW;
1247                 break;
1248
1249         case OFUNC:
1250                 a = ACALL;
1251                 break;
1252
1253         case OASMUL:
1254         case OMUL:
1255                 if(f->op == OREGISTER && t != Z && isreg(t, D_AX) && reg[D_DX] == 0)
1256                         t = Z;
1257                 a = AIMULL;
1258                 break;
1259
1260         case OASMOD:
1261         case OMOD:
1262         case OASDIV:
1263         case ODIV:
1264                 a = AIDIVL;
1265                 break;
1266
1267         case OASLMUL:
1268         case OLMUL:
1269                 a = AMULL;
1270                 break;
1271
1272         case OASLMOD:
1273         case OLMOD:
1274         case OASLDIV:
1275         case OLDIV:
1276                 a = ADIVL;
1277                 break;
1278
1279         case OEQ:
1280         case ONE:
1281         case OLT:
1282         case OLE:
1283         case OGE:
1284         case OGT:
1285         case OLO:
1286         case OLS:
1287         case OHS:
1288         case OHI:
1289                 a = ACMPL;
1290                 if(et == TCHAR || et == TUCHAR)
1291                         a = ACMPB;
1292                 if(et == TSHORT || et == TUSHORT)
1293                         a = ACMPW;
1294                 gins(a, f, t);
1295                 switch(o) {
1296                 case OEQ:       a = AJEQ; break;
1297                 case ONE:       a = AJNE; break;
1298                 case OLT:       a = AJLT; break;
1299                 case OLE:       a = AJLE; break;
1300                 case OGE:       a = AJGE; break;
1301                 case OGT:       a = AJGT; break;
1302                 case OLO:       a = AJCS; break;
1303                 case OLS:       a = AJLS; break;
1304                 case OHS:       a = AJCC; break;
1305                 case OHI:       a = AJHI; break;
1306                 }
1307                 gins(a, Z, Z);
1308                 return;
1309         }
1310         if(a == AGOK)
1311                 diag(Z, "bad in gopcode %O", o);
1312         gins(a, f, t);
1313 }
1314
1315 int
1316 samaddr(Node *f, Node *t)
1317 {
1318
1319         if(f->op != t->op)
1320                 return 0;
1321         switch(f->op) {
1322
1323         case OREGISTER:
1324                 if(f->reg != t->reg)
1325                         break;
1326                 return 1;
1327         }
1328         return 0;
1329 }
1330
1331 void
1332 gbranch(int o)
1333 {
1334         int a;
1335
1336         a = AGOK;
1337         switch(o) {
1338         case ORETURN:
1339                 a = ARET;
1340                 break;
1341         case OGOTO:
1342                 a = AJMP;
1343                 break;
1344         }
1345         nextpc();
1346         if(a == AGOK) {
1347                 diag(Z, "bad in gbranch %O",  o);
1348                 nextpc();
1349         }
1350         p->as = a;
1351 }
1352
1353 void
1354 patch(Prog *op, long pc)
1355 {
1356
1357         op->to.offset = pc;
1358         op->to.type = D_BRANCH;
1359 }
1360
1361 void
1362 gpseudo(int a, Sym *s, Node *n)
1363 {
1364
1365         nextpc();
1366         p->as = a;
1367         p->from.type = D_EXTERN;
1368         p->from.sym = s;
1369         p->from.scale = (profileflg ? 0 : NOPROF);
1370         if(s->class == CSTATIC)
1371                 p->from.type = D_STATIC;
1372         naddr(n, &p->to);
1373         if(a == ADATA || a == AGLOBL)
1374                 pc--;
1375 }
1376
1377 int
1378 sconst(Node *n)
1379 {
1380         long v;
1381
1382         if(n->op == OCONST && !typefd[n->type->etype]) {
1383                 v = n->vconst;
1384                 if(v >= -32766L && v < 32766L)
1385                         return 1;
1386         }
1387         return 0;
1388 }
1389
1390 long
1391 exreg(Type *t)
1392 {
1393
1394         int o;
1395
1396         if(typechlp[t->etype]){
1397                 if(exregoffset >= 32)
1398                         return 0;
1399                 o = exregoffset;
1400                 exregoffset += 4;
1401                 return o+1;     /* +1 to avoid 0 == failure; naddr case OEXREG will -1. */
1402         }
1403         return 0;
1404 }
1405
1406 schar   ewidth[NTYPE] =
1407 {
1408         -1,             /*[TXXX]*/      
1409         SZ_CHAR,        /*[TCHAR]*/     
1410         SZ_CHAR,        /*[TUCHAR]*/
1411         SZ_SHORT,       /*[TSHORT]*/
1412         SZ_SHORT,       /*[TUSHORT]*/
1413         SZ_INT,         /*[TINT]*/
1414         SZ_INT,         /*[TUINT]*/
1415         SZ_LONG,        /*[TLONG]*/
1416         SZ_LONG,        /*[TULONG]*/
1417         SZ_VLONG,       /*[TVLONG]*/
1418         SZ_VLONG,       /*[TUVLONG]*/
1419         SZ_FLOAT,       /*[TFLOAT]*/
1420         SZ_DOUBLE,      /*[TDOUBLE]*/
1421         SZ_IND,         /*[TIND]*/
1422         0,              /*[TFUNC]*/
1423         -1,             /*[TARRAY]*/
1424         0,              /*[TVOID]*/
1425         -1,             /*[TSTRUCT]*/
1426         -1,             /*[TUNION]*/
1427         SZ_INT,         /*[TENUM]*/
1428 };
1429 long    ncast[NTYPE] =
1430 {
1431         0,                              /*[TXXX]*/
1432         BCHAR|BUCHAR,                   /*[TCHAR]*/
1433         BCHAR|BUCHAR,                   /*[TUCHAR]*/    
1434         BSHORT|BUSHORT,                 /*[TSHORT]*/
1435         BSHORT|BUSHORT,                 /*[TUSHORT]*/
1436         BINT|BUINT|BLONG|BULONG|BIND,   /*[TINT]*/              
1437         BINT|BUINT|BLONG|BULONG|BIND,   /*[TUINT]*/
1438         BINT|BUINT|BLONG|BULONG|BIND,   /*[TLONG]*/
1439         BINT|BUINT|BLONG|BULONG|BIND,   /*[TULONG]*/
1440         BVLONG|BUVLONG,                 /*[TVLONG]*/
1441         BVLONG|BUVLONG,                 /*[TUVLONG]*/
1442         BFLOAT,                         /*[TFLOAT]*/
1443         BDOUBLE,                        /*[TDOUBLE]*/
1444         BLONG|BULONG|BIND,              /*[TIND]*/
1445         0,                              /*[TFUNC]*/
1446         0,                              /*[TARRAY]*/
1447         0,                              /*[TVOID]*/
1448         BSTRUCT,                        /*[TSTRUCT]*/
1449         BUNION,                         /*[TUNION]*/
1450         0,                              /*[TENUM]*/
1451 };