]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/8c/txt.c
fix ref822 again: remove uniqarray(), fix case with many entries in 'n'.
[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 static int
932 regused(Node *n, int r)
933 {
934         if(n == nil)
935                 return 0;
936         if(isreg(n, r))
937                 return 1;
938         return regused(n->left, r) || regused(n->right, r);
939 }
940
941 void
942 doindex(Node *n, Node *o)
943 {
944         Node nod, nod1;
945         long v;
946
947 if(debug['Y'])
948 prtree(n, "index");
949
950 if(n->left->complex >= FNX)
951 print("botch in doindex\n");
952
953         if(n->right->op == OREGISTER)
954                 o = n->right;
955         else if(o == Z || o->op != OREGISTER || regused(n, o->reg))
956                 o = Z;
957         regalloc(&nod, &regnode, o);
958         v = constnode.vconst;
959         cgen(n->right, &nod);
960         idx.ptr = D_NONE;
961         if(n->left->op == OCONST)
962                 idx.ptr = D_CONST;
963         else if(n->left->op == OREGISTER)
964 //      else if(n->left->op == OREGISTER && typeil[n->left->type->etype])
965                 idx.ptr = n->left->reg;
966         else if(n->left->op != OADDR) {
967                 reg[D_BP]++;    // cant be used as a base
968                 regalloc(&nod1, &regnode, Z);
969                 cgen(n->left, &nod1);
970                 idx.ptr = nod1.reg;
971                 regfree(&nod1);
972                 reg[D_BP]--;
973         }
974         idx.reg = nod.reg;
975         regfree(&nod);
976         constnode.vconst = v;
977 }
978
979 void
980 gins(int a, Node *f, Node *t)
981 {
982         if(f != Z && f->op == OINDEX)
983                 doindex(f, a == AMOVL || a == ALEAL
984                         || a == AMOVBLSX || a == AMOVBLZX
985                         || a == AMOVWLSX || a == AMOVWLZX ? t : Z);
986         if(t != Z && t->op == OINDEX)
987                 doindex(t, Z);
988         nextpc();
989         p->as = a;
990         if(f != Z)
991                 naddr(f, &p->from);
992         if(t != Z)
993                 naddr(t, &p->to);
994         if(debug['g'])
995                 print("%P\n", p);
996 }
997
998 void
999 fgopcode(int o, Node *f, Node *t, int pop, int rev)
1000 {
1001         int a, et;
1002         Node nod;
1003
1004         et = TLONG;
1005         if(f != Z && f->type != T)
1006                 et = f->type->etype;
1007         if(!typefd[et]) {
1008                 diag(f, "fop: integer %O", o);
1009                 return;
1010         }
1011         if(debug['M']) {
1012                 if(t != Z && t->type != T)
1013                         print("gop: %O %O-%s Z\n", o, f->op, tnames[et]);
1014                 else
1015                         print("gop: %O %O-%s %O-%s\n", o,
1016                                 f->op, tnames[et], t->op, tnames[t->type->etype]);
1017         }
1018         a = AGOK;
1019         switch(o) {
1020
1021         case OASADD:
1022         case OADD:
1023                 if(et == TFLOAT)
1024                         a = AFADDF;
1025                 else
1026                 if(et == TDOUBLE) {
1027                         a = AFADDD;
1028                         if(pop)
1029                                 a = AFADDDP;
1030                 }
1031                 break;
1032
1033         case OASSUB:
1034         case OSUB:
1035                 if(et == TFLOAT) {
1036                         a = AFSUBF;
1037                         if(rev)
1038                                 a = AFSUBRF;
1039                 } else
1040                 if(et == TDOUBLE) {
1041                         a = AFSUBD;
1042                         if(pop)
1043                                 a = AFSUBDP;
1044                         if(rev) {
1045                                 a = AFSUBRD;
1046                                 if(pop)
1047                                         a = AFSUBRDP;
1048                         }
1049                 }
1050                 break;
1051
1052         case OASMUL:
1053         case OMUL:
1054                 if(et == TFLOAT)
1055                         a = AFMULF;
1056                 else
1057                 if(et == TDOUBLE) {
1058                         a = AFMULD;
1059                         if(pop)
1060                                 a = AFMULDP;
1061                 }
1062                 break;
1063
1064         case OASMOD:
1065         case OMOD:
1066         case OASDIV:
1067         case ODIV:
1068                 if(et == TFLOAT) {
1069                         a = AFDIVF;
1070                         if(rev)
1071                                 a = AFDIVRF;
1072                 } else
1073                 if(et == TDOUBLE) {
1074                         a = AFDIVD;
1075                         if(pop)
1076                                 a = AFDIVDP;
1077                         if(rev) {
1078                                 a = AFDIVRD;
1079                                 if(pop)
1080                                         a = AFDIVRDP;
1081                         }
1082                 }
1083                 break;
1084
1085         case OEQ:
1086         case ONE:
1087         case OLT:
1088         case OLE:
1089         case OGE:
1090         case OGT:
1091                 pop += rev;
1092                 if(et == TFLOAT) {
1093                         a = AFCOMF;
1094                         if(pop) {
1095                                 a = AFCOMFP;
1096                                 if(pop > 1)
1097                                         a = AGOK;
1098                         }
1099                 } else
1100                 if(et == TDOUBLE) {
1101                         a = AFCOMF;
1102                         if(pop) {
1103                                 a = AFCOMDP;
1104                                 if(pop > 1)
1105                                         a = AFCOMDPP;
1106                         }
1107                 }
1108                 gins(a, f, t);
1109                 regalloc(&nod, &regnode, Z);
1110                 if(nod.reg != D_AX) {
1111                         regfree(&nod);
1112                         nod.reg = D_AX;
1113                         gins(APUSHL, &nod, Z);
1114                         gins(AWAIT, Z, Z);
1115                         gins(AFSTSW, Z, &nod);
1116                         gins(ASAHF, Z, Z);
1117                         gins(APOPL, Z, &nod);
1118                 } else {
1119                         gins(AWAIT, Z, Z);
1120                         gins(AFSTSW, Z, &nod);
1121                         gins(ASAHF, Z, Z);
1122                         regfree(&nod);
1123                 }
1124                 switch(o) {
1125                 case OEQ:       a = AJEQ; break;
1126                 case ONE:       a = AJNE; break;
1127                 case OLT:       a = AJCS; break;
1128                 case OLE:       a = AJLS; break;
1129                 case OGE:       a = AJCC; break;
1130                 case OGT:       a = AJHI; break;
1131                 }
1132                 gins(a, Z, Z);
1133                 return;
1134         }
1135         if(a == AGOK)
1136                 diag(Z, "bad in gopcode %O", o);
1137         gins(a, f, t);
1138 }
1139
1140 void
1141 gopcode(int o, Type *ty, Node *f, Node *t)
1142 {
1143         int a, et;
1144
1145         et = TLONG;
1146         if(ty != T)
1147                 et = ty->etype;
1148         if(typefd[et] && o != OADDR && o != OFUNC) {
1149                 diag(f, "gop: float %O", o);
1150                 return;
1151         }
1152         if(debug['M']) {
1153                 if(f != Z && f->type != T)
1154                         print("gop: %O %O[%s],", o, f->op, tnames[et]);
1155                 else
1156                         print("gop: %O Z,", o);
1157                 if(t != Z && t->type != T)
1158                         print("%O[%s]\n", t->op, tnames[t->type->etype]);
1159                 else
1160                         print("Z\n");
1161         }
1162         a = AGOK;
1163         switch(o) {
1164         case OCOM:
1165                 a = ANOTL;
1166                 if(et == TCHAR || et == TUCHAR)
1167                         a = ANOTB;
1168                 if(et == TSHORT || et == TUSHORT)
1169                         a = ANOTW;
1170                 break;
1171
1172         case ONEG:
1173                 a = ANEGL;
1174                 if(et == TCHAR || et == TUCHAR)
1175                         a = ANEGB;
1176                 if(et == TSHORT || et == TUSHORT)
1177                         a = ANEGW;
1178                 break;
1179
1180         case OADDR:
1181                 a = ALEAL;
1182                 break;
1183
1184         case OASADD:
1185         case OADD:
1186                 a = AADDL;
1187                 if(et == TCHAR || et == TUCHAR)
1188                         a = AADDB;
1189                 if(et == TSHORT || et == TUSHORT)
1190                         a = AADDW;
1191                 break;
1192
1193         case OASSUB:
1194         case OSUB:
1195                 a = ASUBL;
1196                 if(et == TCHAR || et == TUCHAR)
1197                         a = ASUBB;
1198                 if(et == TSHORT || et == TUSHORT)
1199                         a = ASUBW;
1200                 break;
1201
1202         case OASOR:
1203         case OOR:
1204                 a = AORL;
1205                 if(et == TCHAR || et == TUCHAR)
1206                         a = AORB;
1207                 if(et == TSHORT || et == TUSHORT)
1208                         a = AORW;
1209                 break;
1210
1211         case OASAND:
1212         case OAND:
1213                 a = AANDL;
1214                 if(et == TCHAR || et == TUCHAR)
1215                         a = AANDB;
1216                 if(et == TSHORT || et == TUSHORT)
1217                         a = AANDW;
1218                 break;
1219
1220         case OASXOR:
1221         case OXOR:
1222                 a = AXORL;
1223                 if(et == TCHAR || et == TUCHAR)
1224                         a = AXORB;
1225                 if(et == TSHORT || et == TUSHORT)
1226                         a = AXORW;
1227                 break;
1228
1229         case OASLSHR:
1230         case OLSHR:
1231                 a = ASHRL;
1232                 if(et == TCHAR || et == TUCHAR)
1233                         a = ASHRB;
1234                 if(et == TSHORT || et == TUSHORT)
1235                         a = ASHRW;
1236                 break;
1237
1238         case OASASHR:
1239         case OASHR:
1240                 a = ASARL;
1241                 if(et == TCHAR || et == TUCHAR)
1242                         a = ASARB;
1243                 if(et == TSHORT || et == TUSHORT)
1244                         a = ASARW;
1245                 break;
1246
1247         case OASASHL:
1248         case OASHL:
1249                 a = ASALL;
1250                 if(et == TCHAR || et == TUCHAR)
1251                         a = ASALB;
1252                 if(et == TSHORT || et == TUSHORT)
1253                         a = ASALW;
1254                 break;
1255
1256         case OROL:
1257                 a = AROLL;
1258                 if(et == TCHAR || et == TUCHAR)
1259                         a = AROLB;
1260                 if(et == TSHORT || et == TUSHORT)
1261                         a = AROLW;
1262                 break;
1263
1264         case OFUNC:
1265                 a = ACALL;
1266                 break;
1267
1268         case OASMUL:
1269         case OMUL:
1270                 if(f->op == OREGISTER && t != Z && isreg(t, D_AX) && reg[D_DX] == 0)
1271                         t = Z;
1272                 a = AIMULL;
1273                 break;
1274
1275         case OASMOD:
1276         case OMOD:
1277         case OASDIV:
1278         case ODIV:
1279                 a = AIDIVL;
1280                 break;
1281
1282         case OASLMUL:
1283         case OLMUL:
1284                 a = AMULL;
1285                 break;
1286
1287         case OASLMOD:
1288         case OLMOD:
1289         case OASLDIV:
1290         case OLDIV:
1291                 a = ADIVL;
1292                 break;
1293
1294         case OEQ:
1295         case ONE:
1296         case OLT:
1297         case OLE:
1298         case OGE:
1299         case OGT:
1300         case OLO:
1301         case OLS:
1302         case OHS:
1303         case OHI:
1304                 a = ACMPL;
1305                 if(et == TCHAR || et == TUCHAR)
1306                         a = ACMPB;
1307                 if(et == TSHORT || et == TUSHORT)
1308                         a = ACMPW;
1309                 gins(a, f, t);
1310                 switch(o) {
1311                 case OEQ:       a = AJEQ; break;
1312                 case ONE:       a = AJNE; break;
1313                 case OLT:       a = AJLT; break;
1314                 case OLE:       a = AJLE; break;
1315                 case OGE:       a = AJGE; break;
1316                 case OGT:       a = AJGT; break;
1317                 case OLO:       a = AJCS; break;
1318                 case OLS:       a = AJLS; break;
1319                 case OHS:       a = AJCC; break;
1320                 case OHI:       a = AJHI; break;
1321                 }
1322                 gins(a, Z, Z);
1323                 return;
1324         }
1325         if(a == AGOK)
1326                 diag(Z, "bad in gopcode %O", o);
1327         gins(a, f, t);
1328 }
1329
1330 int
1331 samaddr(Node *f, Node *t)
1332 {
1333
1334         if(f->op != t->op)
1335                 return 0;
1336         switch(f->op) {
1337
1338         case OREGISTER:
1339                 if(f->reg != t->reg)
1340                         break;
1341                 return 1;
1342         }
1343         return 0;
1344 }
1345
1346 void
1347 gbranch(int o)
1348 {
1349         int a;
1350
1351         a = AGOK;
1352         switch(o) {
1353         case ORETURN:
1354                 a = ARET;
1355                 break;
1356         case OGOTO:
1357                 a = AJMP;
1358                 break;
1359         }
1360         nextpc();
1361         if(a == AGOK) {
1362                 diag(Z, "bad in gbranch %O",  o);
1363                 nextpc();
1364         }
1365         p->as = a;
1366 }
1367
1368 void
1369 patch(Prog *op, long pc)
1370 {
1371
1372         op->to.offset = pc;
1373         op->to.type = D_BRANCH;
1374 }
1375
1376 void
1377 gpseudo(int a, Sym *s, Node *n)
1378 {
1379
1380         nextpc();
1381         p->as = a;
1382         p->from.type = D_EXTERN;
1383         p->from.sym = s;
1384         p->from.scale = (profileflg ? 0 : NOPROF);
1385         if(s->class == CSTATIC)
1386                 p->from.type = D_STATIC;
1387         naddr(n, &p->to);
1388         if(a == ADATA || a == AGLOBL)
1389                 pc--;
1390 }
1391
1392 int
1393 sconst(Node *n)
1394 {
1395         long v;
1396
1397         if(n->op == OCONST && !typefd[n->type->etype]) {
1398                 v = n->vconst;
1399                 if(v >= -32766L && v < 32766L)
1400                         return 1;
1401         }
1402         return 0;
1403 }
1404
1405 long
1406 exreg(Type *t)
1407 {
1408
1409         int o;
1410
1411         if(typechlp[t->etype]){
1412                 if(exregoffset >= 32)
1413                         return 0;
1414                 o = exregoffset;
1415                 exregoffset += 4;
1416                 return o+1;     /* +1 to avoid 0 == failure; naddr case OEXREG will -1. */
1417         }
1418         return 0;
1419 }
1420
1421 schar   ewidth[NTYPE] =
1422 {
1423         -1,             /*[TXXX]*/      
1424         SZ_CHAR,        /*[TCHAR]*/     
1425         SZ_CHAR,        /*[TUCHAR]*/
1426         SZ_SHORT,       /*[TSHORT]*/
1427         SZ_SHORT,       /*[TUSHORT]*/
1428         SZ_INT,         /*[TINT]*/
1429         SZ_INT,         /*[TUINT]*/
1430         SZ_LONG,        /*[TLONG]*/
1431         SZ_LONG,        /*[TULONG]*/
1432         SZ_VLONG,       /*[TVLONG]*/
1433         SZ_VLONG,       /*[TUVLONG]*/
1434         SZ_FLOAT,       /*[TFLOAT]*/
1435         SZ_DOUBLE,      /*[TDOUBLE]*/
1436         SZ_IND,         /*[TIND]*/
1437         0,              /*[TFUNC]*/
1438         -1,             /*[TARRAY]*/
1439         0,              /*[TVOID]*/
1440         -1,             /*[TSTRUCT]*/
1441         -1,             /*[TUNION]*/
1442         SZ_INT,         /*[TENUM]*/
1443 };
1444 long    ncast[NTYPE] =
1445 {
1446         0,                              /*[TXXX]*/
1447         BCHAR|BUCHAR,                   /*[TCHAR]*/
1448         BCHAR|BUCHAR,                   /*[TUCHAR]*/    
1449         BSHORT|BUSHORT,                 /*[TSHORT]*/
1450         BSHORT|BUSHORT,                 /*[TUSHORT]*/
1451         BINT|BUINT|BLONG|BULONG|BIND,   /*[TINT]*/              
1452         BINT|BUINT|BLONG|BULONG|BIND,   /*[TUINT]*/
1453         BINT|BUINT|BLONG|BULONG|BIND,   /*[TLONG]*/
1454         BINT|BUINT|BLONG|BULONG|BIND,   /*[TULONG]*/
1455         BVLONG|BUVLONG,                 /*[TVLONG]*/
1456         BVLONG|BUVLONG,                 /*[TUVLONG]*/
1457         BFLOAT,                         /*[TFLOAT]*/
1458         BDOUBLE,                        /*[TDOUBLE]*/
1459         BLONG|BULONG|BIND,              /*[TIND]*/
1460         0,                              /*[TFUNC]*/
1461         0,                              /*[TARRAY]*/
1462         0,                              /*[TVOID]*/
1463         BSTRUCT,                        /*[TSTRUCT]*/
1464         BUNION,                         /*[TUNION]*/
1465         0,                              /*[TENUM]*/
1466 };