]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vc/txt.c
show line numbers in dtracy type errors
[plan9front.git] / sys / src / cmd / vc / txt.c
1 #include "gc.h"
2
3 void
4 ginit(void)
5 {
6         int i;
7         Type *t;
8
9         thechar = 'v';
10         thestring = "mips";
11         exregoffset = REGEXT;
12         exfregoffset = FREGEXT;
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         zprog.link = P;
26         zprog.as = AGOK;
27         zprog.reg = NREG;
28         zprog.from.type = D_NONE;
29         zprog.from.name = D_NONE;
30         zprog.from.reg = NREG;
31         zprog.to = zprog.from;
32
33         regnode.op = OREGISTER;
34         regnode.class = CEXREG;
35         regnode.reg = REGTMP;
36         regnode.complex = 0;
37         regnode.addable = 11;
38         regnode.type = types[TLONG];
39
40         constnode.op = OCONST;
41         constnode.class = CXXX;
42         constnode.complex = 0;
43         constnode.addable = 20;
44         constnode.type = types[TLONG];
45
46         fconstnode.op = OCONST;
47         fconstnode.class = CXXX;
48         fconstnode.complex = 0;
49         fconstnode.addable = 20;
50         fconstnode.type = types[TDOUBLE];
51
52         nodsafe = new(ONAME, Z, Z);
53         nodsafe->sym = slookup(".safe");
54         nodsafe->type = types[TINT];
55         nodsafe->etype = types[TINT]->etype;
56         nodsafe->class = CAUTO;
57         complex(nodsafe);
58
59         t = typ(TARRAY, types[TCHAR]);
60         symrathole = slookup(".rathole");
61         symrathole->class = CGLOBL;
62         symrathole->type = t;
63
64         nodrat = new(ONAME, Z, Z);
65         nodrat->sym = symrathole;
66         nodrat->type = types[TIND];
67         nodrat->etype = TVOID;
68         nodrat->class = CGLOBL;
69         complex(nodrat);
70         nodrat->type = t;
71
72         nodret = new(ONAME, Z, Z);
73         nodret->sym = slookup(".ret");
74         nodret->type = types[TIND];
75         nodret->etype = TIND;
76         nodret->class = CPARAM;
77         nodret = new(OIND, nodret, Z);
78         complex(nodret);
79
80         com64init();
81
82         for(i=0; i<nelem(reg); i++) {
83                 reg[i] = 0;
84                 if(i == REGZERO ||
85                   (i >= NREG && ((i-NREG)&1)))
86                         reg[i] = 1;
87         }
88 }
89
90 void
91 gclean(void)
92 {
93         int i;
94         Sym *s;
95
96         for(i=0; i<NREG; i++)
97                 if(i != REGZERO)
98                         if(reg[i])
99                                 diag(Z, "reg %d left allocated", i);
100         for(i=NREG; i<NREG+NREG; i+=2)
101                 if(reg[i])
102                         diag(Z, "freg %d left allocated", i-NREG);
103         while(mnstring)
104                 outstring("", 1L);
105         symstring->type->width = nstring;
106         symrathole->type->width = nrathole;
107         for(i=0; i<NHASH; i++)
108         for(s = hash[i]; s != S; s = s->link) {
109                 if(s->type == T)
110                         continue;
111                 if(s->type->width == 0)
112                         continue;
113                 if(s->class != CGLOBL && s->class != CSTATIC)
114                         continue;
115                 if(s->type == types[TENUM])
116                         continue;
117                 gpseudo(AGLOBL, s, nodconst(s->type->width));
118         }
119         nextpc();
120         p->as = AEND;
121         outcode();
122 }
123
124 void
125 nextpc(void)
126 {
127
128         p = alloc(sizeof(*p));
129         *p = zprog;
130         p->lineno = nearln;
131         pc++;
132         if(firstp == P) {
133                 firstp = p;
134                 lastp = p;
135                 return;
136         }
137         lastp->link = p;
138         lastp = p;
139 }
140
141 void
142 gargs(Node *n, Node *tn1, Node *tn2)
143 {
144         long regs;
145         Node fnxargs[20], *fnxp;
146
147         regs = cursafe;
148
149         fnxp = fnxargs;
150         garg1(n, tn1, tn2, 0, &fnxp);   /* compile fns to temps */
151
152         curarg = 0;
153         fnxp = fnxargs;
154         garg1(n, tn1, tn2, 1, &fnxp);   /* compile normal args and temps */
155
156         cursafe = regs;
157 }
158
159 void
160 garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
161 {
162         Node nod;
163
164         if(n == Z)
165                 return;
166         if(n->op == OLIST) {
167                 garg1(n->left, tn1, tn2, f, fnxp);
168                 garg1(n->right, tn1, tn2, f, fnxp);
169                 return;
170         }
171         if(f == 0) {
172                 if(n->complex >= FNX) {
173                         regsalloc(*fnxp, n);
174                         nod = znode;
175                         nod.op = OAS;
176                         nod.left = *fnxp;
177                         nod.right = n;
178                         nod.type = n->type;
179                         cgen(&nod, Z);
180                         (*fnxp)++;
181                 }
182                 return;
183         }
184         if(typesuv[n->type->etype]) {
185                 regaalloc(tn2, n);
186                 if(n->complex >= FNX) {
187                         sugen(*fnxp, tn2, n->type->width);
188                         (*fnxp)++;
189                 } else
190                         sugen(n, tn2, n->type->width);
191                 return;
192         }
193         if(REGARG && curarg == 0 && typechlp[n->type->etype]) {
194                 regaalloc1(tn1, n);
195                 if(n->complex >= FNX) {
196                         cgen(*fnxp, tn1);
197                         (*fnxp)++;
198                 } else
199                         cgen(n, tn1);
200                 return;
201         }
202         if(vconst(n) == 0) {
203                 regaalloc(tn2, n);
204                 gopcode(OAS, n, Z, tn2);
205                 return;
206         }
207         regalloc(tn1, n, Z);
208         if(n->complex >= FNX) {
209                 cgen(*fnxp, tn1);
210                 (*fnxp)++;
211         } else
212                 cgen(n, tn1);
213         regaalloc(tn2, n);
214         gopcode(OAS, tn1, Z, tn2);
215         regfree(tn1);
216 }
217
218 Node*
219 nodconst(long v)
220 {
221         constnode.vconst = v;
222         return &constnode;
223 }
224
225 Node*
226 nod32const(vlong v)
227 {
228         constnode.vconst = v & MASK(32);
229         return &constnode;
230 }
231
232 Node*
233 nodfconst(double d)
234 {
235         fconstnode.fconst = d;
236         return &fconstnode;
237 }
238
239 void
240 nodreg(Node *n, Node *nn, int reg)
241 {
242         *n = regnode;
243         n->reg = reg;
244         n->type = nn->type;
245         n->lineno = nn->lineno;
246 }
247
248 void
249 regret(Node *n, Node *nn)
250 {
251         int r;
252
253         r = REGRET;
254         if(typefd[nn->type->etype])
255                 r = FREGRET+NREG;
256         nodreg(n, nn, r);
257         reg[r]++;
258 }
259
260 int
261 tmpreg(void)
262 {
263         int i;
264
265         for(i=REGRET+1; i<NREG; i++)
266                 if(reg[i] == 0)
267                         return i;
268         diag(Z, "out of fixed registers");
269         return 0;
270 }
271
272 void
273 regalloc(Node *n, Node *tn, Node *o)
274 {
275         int i, j;
276         static int lasti;
277
278         switch(tn->type->etype) {
279         case TCHAR:
280         case TUCHAR:
281         case TSHORT:
282         case TUSHORT:
283         case TINT:
284         case TUINT:
285         case TLONG:
286         case TULONG:
287         case TIND:
288                 if(o != Z && o->op == OREGISTER) {
289                         i = o->reg;
290                         if(i > 0 && i < NREG)
291                                 goto out;
292                 }
293                 j = lasti + REGRET+1;
294                 for(i=REGRET+1; i<NREG; i++) {
295                         if(j >= NREG)
296                                 j = REGRET+1;
297                         if(reg[j] == 0) {
298                                 i = j;
299                                 goto out;
300                         }
301                         j++;
302                 }
303                 diag(tn, "out of fixed registers");
304                 goto err;
305
306         case TFLOAT:
307         case TDOUBLE:
308         case TVLONG:
309                 if(o != Z && o->op == OREGISTER) {
310                         i = o->reg;
311                         if(i >= NREG && i < NREG+NREG)
312                                 goto out;
313                 }
314                 j = 0*2 + NREG;
315                 for(i=NREG; i<NREG+NREG; i+=2) {
316                         if(j >= NREG+NREG)
317                                 j = NREG;
318                         if(reg[j] == 0) {
319                                 i = j;
320                                 goto out;
321                         }
322                         j += 2;
323                 }
324                 diag(tn, "out of float registers");
325                 goto err;
326         }
327         diag(tn, "unknown type in regalloc: %T", tn->type);
328 err:
329         nodreg(n, tn, 0);
330         return;
331 out:
332         reg[i]++;
333         lasti++;
334         if(lasti >= 5)
335                 lasti = 0;
336         nodreg(n, tn, i);
337 }
338
339 void
340 regialloc(Node *n, Node *tn, Node *o)
341 {
342         Node nod;
343
344         nod = *tn;
345         nod.type = types[TIND];
346         regalloc(n, &nod, o);
347 }
348
349 void
350 regfree(Node *n)
351 {
352         int i;
353
354         i = 0;
355         if(n->op != OREGISTER && n->op != OINDREG)
356                 goto err;
357         i = n->reg;
358         if(i < 0 || i >= sizeof(reg))
359                 goto err;
360         if(reg[i] <= 0)
361                 goto err;
362         reg[i]--;
363         return;
364 err:
365         diag(n, "error in regfree: %d", i);
366 }
367
368 void
369 regsalloc(Node *n, Node *nn)
370 {
371         cursafe = align(cursafe, nn->type, Aaut3);
372         maxargsafe = maxround(maxargsafe, cursafe+curarg);
373         *n = *nodsafe;
374         n->xoffset = -(stkoff + cursafe);
375         n->type = nn->type;
376         n->etype = nn->type->etype;
377         n->lineno = nn->lineno;
378 }
379
380 void
381 regaalloc1(Node *n, Node *nn)
382 {
383         nodreg(n, nn, REGARG);
384         reg[REGARG]++;
385         curarg = align(curarg, nn->type, Aarg1);
386         curarg = align(curarg, nn->type, Aarg2);
387         maxargsafe = maxround(maxargsafe, cursafe+curarg);
388 }
389
390 void
391 regaalloc(Node *n, Node *nn)
392 {
393         curarg = align(curarg, nn->type, Aarg1);
394         *n = *nn;
395         n->op = OINDREG;
396         n->reg = REGSP;
397         n->xoffset = curarg + SZ_LONG;
398         n->complex = 0;
399         n->addable = 20;
400         curarg = align(curarg, nn->type, Aarg2);
401         maxargsafe = maxround(maxargsafe, cursafe+curarg);
402 }
403
404 void
405 regind(Node *n, Node *nn)
406 {
407
408         if(n->op != OREGISTER) {
409                 diag(n, "regind not OREGISTER");
410                 return;
411         }
412         n->op = OINDREG;
413         n->type = nn->type;
414 }
415
416 void
417 raddr(Node *n, Prog *p)
418 {
419         Adr a;
420
421         naddr(n, &a);
422         if(a.type == D_CONST && a.offset == 0) {
423                 a.type = D_REG;
424                 a.reg = 0;
425         }
426         if(a.type != D_REG && a.type != D_FREG) {
427                 if(n)
428                         diag(n, "bad in raddr: %O", n->op);
429                 else
430                         diag(n, "bad in raddr: <null>");
431                 p->reg = NREG;
432         } else
433                 p->reg = a.reg;
434 }
435
436 void
437 naddr(Node *n, Adr *a)
438 {
439         long v;
440
441         a->type = D_NONE;
442         if(n == Z)
443                 return;
444         switch(n->op) {
445         default:
446         bad:
447                 diag(n, "bad in naddr: %O", n->op);
448                 break;
449
450         case OREGISTER:
451                 a->type = D_REG;
452                 a->sym = S;
453                 a->reg = n->reg;
454                 if(a->reg >= NREG) {
455                         a->type = D_FREG;
456                         a->reg -= NREG;
457                 }
458                 break;
459
460         case OIND:
461                 naddr(n->left, a);
462                 if(a->type == D_REG) {
463                         a->type = D_OREG;
464                         break;
465                 }
466                 if(a->type == D_CONST) {
467                         a->type = D_OREG;
468                         break;
469                 }
470                 goto bad;
471
472         case OINDREG:
473                 a->type = D_OREG;
474                 a->sym = S;
475                 a->offset = n->xoffset;
476                 a->reg = n->reg;
477                 break;
478
479         case ONAME:
480                 a->etype = n->etype;
481                 a->type = D_OREG;
482                 a->name = D_STATIC;
483                 a->sym = n->sym;
484                 a->offset = n->xoffset;
485                 if(n->class == CSTATIC)
486                         break;
487                 if(n->class == CEXTERN || n->class == CGLOBL) {
488                         a->name = D_EXTERN;
489                         break;
490                 }
491                 if(n->class == CAUTO) {
492                         a->name = D_AUTO;
493                         break;
494                 }
495                 if(n->class == CPARAM) {
496                         a->name = D_PARAM;
497                         break;
498                 }
499                 goto bad;
500
501         case OCONST:
502                 a->sym = S;
503                 a->reg = NREG;
504                 if(typefd[n->type->etype]) {
505                         a->type = D_FCONST;
506                         a->dval = n->fconst;
507                 } else {
508                         a->type = D_CONST;
509                         a->offset = n->vconst;
510                 }
511                 break;
512
513         case OADDR:
514                 naddr(n->left, a);
515                 if(a->type == D_OREG) {
516                         a->type = D_CONST;
517                         break;
518                 }
519                 goto bad;
520
521         case OADD:
522                 if(n->left->op == OCONST) {
523                         naddr(n->left, a);
524                         v = a->offset;
525                         naddr(n->right, a);
526                 } else {
527                         naddr(n->right, a);
528                         v = a->offset;
529                         naddr(n->left, a);
530                 }
531                 a->offset += v;
532                 break;
533
534         }
535 }
536
537 void
538 fop(int as, int f1, int f2, Node *t)
539 {
540         Node nod1, nod2, nod3;
541
542         nodreg(&nod1, t, NREG+f1);
543         nodreg(&nod2, t, NREG+f2);
544         regalloc(&nod3, t, t);
545         gopcode(as, &nod1, &nod2, &nod3);
546         gmove(&nod3, t);
547         regfree(&nod3);
548 }
549
550 void
551 gmove(Node *f, Node *t)
552 {
553         int ft, tt, a;
554         Node nod, nod1, nod2;
555         Prog *p1;
556         double d;
557
558         ft = f->type->etype;
559         tt = t->type->etype;
560         if(debug['M'])
561                 print("gop: %O %O[%s],%O[%s]\n", OAS,
562                         f->op, tnames[ft], t->op, tnames[tt]);
563
564         if(ft == TDOUBLE && f->op == OCONST) {
565                 d = f->fconst;
566                 if(d == 0.0) {
567                         a = FREGZERO;
568                         goto ffreg;
569                 }
570                 if(d == 0.5) {
571                         a = FREGHALF;
572                         goto ffreg;
573                 }
574                 if(d == 1.0) {
575                         a = FREGONE;
576                         goto ffreg;
577                 }
578                 if(d == 2.0) {
579                         a = FREGTWO;
580                         goto ffreg;
581                 }
582                 if(d == -.5) {
583                         fop(OSUB, FREGHALF, FREGZERO, t);
584                         return;
585                 }
586                 if(d == -1.0) {
587                         fop(OSUB, FREGONE, FREGZERO, t);
588                         return;
589                 }
590                 if(d == -2.0) {
591                         fop(OSUB, FREGTWO, FREGZERO, t);
592                         return;
593                 }
594                 if(d == 1.5) {
595                         fop(OADD, FREGONE, FREGHALF, t);
596                         return;
597                 }
598                 if(d == 2.5) {
599                         fop(OADD, FREGTWO, FREGHALF, t);
600                         return;
601                 }
602                 if(d == 3.0) {
603                         fop(OADD, FREGTWO, FREGONE, t);
604                         return;
605                 }
606         }
607         if(ft == TFLOAT && f->op == OCONST) {
608                 d = f->fconst;
609                 if(d == 0) {
610                         a = FREGZERO;
611                 ffreg:
612                         nodreg(&nod, f, NREG+a);
613                         gmove(&nod, t);
614                         return;
615                 }
616         }
617         /*
618          * a load --
619          * put it into a register then
620          * worry what to do with it.
621          */
622         if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
623                 switch(ft) {
624                 default:
625                         if(typefd[tt]) {
626                                 /* special case can load mem to Freg */
627                                 regalloc(&nod, t, t);
628                                 gins(AMOVW, f, &nod);
629                                 a = AMOVWD;
630                                 if(tt == TFLOAT)
631                                         a = AMOVWF;
632                                 gins(a, &nod, &nod);
633                                 gmove(&nod, t);
634                                 regfree(&nod);
635                                 return;
636                         }
637                         a = AMOVW;
638                         break;
639                 case TFLOAT:
640                         a = AMOVF;
641                         break;
642                 case TDOUBLE:
643                         a = AMOVD;
644                         break;
645                 case TCHAR:
646                         a = AMOVB;
647                         break;
648                 case TUCHAR:
649                         a = AMOVBU;
650                         break;
651                 case TSHORT:
652                         a = AMOVH;
653                         break;
654                 case TUSHORT:
655                         a = AMOVHU;
656                         break;
657                 }
658                 if(typechlp[ft] && typeilp[tt])
659                         regalloc(&nod, t, t);
660                 else
661                         regalloc(&nod, f, t);
662                 gins(a, f, &nod);
663                 gmove(&nod, t);
664                 regfree(&nod);
665                 return;
666         }
667
668         /*
669          * a store --
670          * put it into a register then
671          * store it.
672          */
673         if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
674                 switch(tt) {
675                 default:
676                         a = AMOVW;
677                         break;
678                 case TUCHAR:
679                         a = AMOVBU;
680                         break;
681                 case TCHAR:
682                         a = AMOVB;
683                         break;
684                 case TUSHORT:
685                         a = AMOVHU;
686                         break;
687                 case TSHORT:
688                         a = AMOVH;
689                         break;
690                 case TFLOAT:
691                         a = AMOVF;
692                         break;
693                 case TDOUBLE:
694                         a = AMOVD;
695                         break;
696                 }
697                 if(!typefd[ft] && vconst(f) == 0) {
698                         gins(a, f, t);
699                         return;
700                 }
701                 if(ft == tt)
702                         regalloc(&nod, t, f);
703                 else
704                         regalloc(&nod, t, Z);
705                 gmove(f, &nod);
706                 gins(a, &nod, t);
707                 regfree(&nod);
708                 return;
709         }
710
711         /*
712          * type x type cross table
713          */
714         a = AGOK;
715         switch(ft) {
716         case TDOUBLE:
717         case TVLONG:
718         case TFLOAT:
719                 switch(tt) {
720                 case TDOUBLE:
721                 case TVLONG:
722                         a = AMOVD;
723                         if(ft == TFLOAT)
724                                 a = AMOVFD;
725                         break;
726                 case TFLOAT:
727                         a = AMOVDF;
728                         if(ft == TFLOAT)
729                                 a = AMOVF;
730                         break;
731                 case TINT:
732                 case TUINT:
733                 case TLONG:
734                 case TULONG:
735                 case TIND:
736                 case TSHORT:
737                 case TUSHORT:
738                 case TCHAR:
739                 case TUCHAR:
740                         if(fproundflg) {
741                                 /* convert f, t */
742                                 regalloc(&nod, f, Z);
743                                 gins(AMOVDW, f, &nod);
744                                 if(ft == TFLOAT)
745                                         p->as = AMOVFW;
746                                 gins(AMOVW, &nod, t);
747                                 regfree(&nod);
748                                 gins(AMOVW, t, t);
749                                 return;
750                         }
751                         regalloc(&nod1, &regnode, Z);
752                         regalloc(&nod2, &regnode, Z);
753
754                         /* movw fcr, rx */
755                         gins(AMOVW, Z, &nod1);
756                         p->from.type = D_FCREG;
757                         p->from.reg = 31;
758
759                         /* nop */
760                         gins(ANOR, nodconst(0), nodconst(0));
761                         p->to.type = D_REG;
762                         p->to.reg = 0;
763
764                         /* nop */
765                         gins(ANOR, nodconst(0), nodconst(0));
766                         p->to.type = D_REG;
767                         p->to.reg = 0;
768
769                         /* or $3, rx, ry */
770                         gins(AOR, nodconst(3), &nod2);
771                         p->reg = nod1.reg;
772
773                         /* xor $2, ry */
774                         gins(AXOR, nodconst(2), &nod2);
775
776                         /* movw ry, fcr */
777                         gins(AMOVW, &nod2, Z);
778                         p->to.type = D_FCREG;
779                         p->to.reg = 31;
780
781                         /* nop */
782                         gins(ANOR, nodconst(0), nodconst(0));
783                         p->to.type = D_REG;
784                         p->to.reg = 0;
785
786                         /* nop */
787                         gins(ANOR, nodconst(0), nodconst(0));
788                         p->to.type = D_REG;
789                         p->to.reg = 0;
790
791                         /* convert f, t */
792                         regalloc(&nod, f, Z);
793                         gins(AMOVDW, f, &nod);
794                         if(ft == TFLOAT)
795                                 p->as = AMOVFW;
796                         gins(AMOVW, &nod, t);
797                         regfree(&nod);
798                         gins(AMOVW, t, t);
799
800                         /* movw rx, fcr */
801                         gins(AMOVW, &nod1, Z);
802                         p->to.type = D_FCREG;
803                         p->to.reg = 31;
804
805                         /* nop */
806                         gins(ANOR, nodconst(0), nodconst(0));
807                         p->to.type = D_REG;
808                         p->to.reg = 0;
809
810                         /* nop */
811                         gins(ANOR, nodconst(0), nodconst(0));
812                         p->to.type = D_REG;
813                         p->to.reg = 0;
814
815                         regfree(&nod1);
816                         regfree(&nod2);
817                         return;
818                 }
819                 break;
820         case TINT:
821         case TUINT:
822         case TLONG:
823         case TULONG:
824         case TIND:
825                 switch(tt) {
826                 case TDOUBLE:
827                 case TVLONG:
828                         gins(AMOVW, f, t);
829                         gins(AMOVWD, t, t);
830                         if(ft == TULONG || ft == TUINT) {
831                                 regalloc(&nod, t, Z);
832                                 gins(ACMPGED, t, Z);
833                                 p->reg = FREGZERO;
834                                 gins(ABFPT, Z, Z);
835                                 p1 = p;
836                                 gins(AMOVD, nodfconst(4294967296.), &nod);
837                                 gins(AADDD, &nod, t);
838                                 patch(p1, pc);
839                                 regfree(&nod);
840                         }
841                         return;
842                 case TFLOAT:
843                         gins(AMOVW, f, t);
844                         gins(AMOVWF, t, t);
845                         if(ft == TULONG || ft == TUINT) {
846                                 regalloc(&nod, t, Z);
847                                 gins(ACMPGEF, t, Z);
848                                 p->reg = FREGZERO;
849                                 gins(ABFPT, Z, Z);
850                                 p1 = p;
851                                 gins(AMOVF, nodfconst(4294967296.), &nod);
852                                 gins(AADDF, &nod, t);
853                                 patch(p1, pc);
854                                 regfree(&nod);
855                         }
856                         return;
857                 case TINT:
858                 case TUINT:
859                 case TLONG:
860                 case TULONG:
861                 case TIND:
862                 case TSHORT:
863                 case TUSHORT:
864                 case TCHAR:
865                 case TUCHAR:
866                         a = AMOVW;
867                         break;
868                 }
869                 break;
870         case TSHORT:
871                 switch(tt) {
872                 case TDOUBLE:
873                 case TVLONG:
874                         regalloc(&nod, f, Z);
875                         gins(AMOVH, f, &nod);
876                         gins(AMOVW, &nod, t);
877                         gins(AMOVWD, t, t);
878                         regfree(&nod);
879                         return;
880                 case TFLOAT:
881                         regalloc(&nod, f, Z);
882                         gins(AMOVH, f, &nod);
883                         gins(AMOVW, &nod, t);
884                         gins(AMOVWF, t, t);
885                         regfree(&nod);
886                         return;
887                 case TINT:
888                 case TUINT:
889                 case TLONG:
890                 case TULONG:
891                 case TIND:
892                         a = AMOVH;
893                         break;
894                 case TSHORT:
895                 case TUSHORT:
896                 case TCHAR:
897                 case TUCHAR:
898                         a = AMOVW;
899                         break;
900                 }
901                 break;
902         case TUSHORT:
903                 switch(tt) {
904                 case TDOUBLE:
905                 case TVLONG:
906                         regalloc(&nod, f, Z);
907                         gins(AMOVHU, f, &nod);
908                         gins(AMOVW, &nod, t);
909                         gins(AMOVWD, t, t);
910                         regfree(&nod);
911                         return;
912                 case TFLOAT:
913                         regalloc(&nod, f, Z);
914                         gins(AMOVHU, f, &nod);
915                         gins(AMOVW, &nod, t);
916                         gins(AMOVWF, t, t);
917                         regfree(&nod);
918                         return;
919                 case TINT:
920                 case TUINT:
921                 case TLONG:
922                 case TULONG:
923                 case TIND:
924                         a = AMOVHU;
925                         break;
926                 case TSHORT:
927                 case TUSHORT:
928                 case TCHAR:
929                 case TUCHAR:
930                         a = AMOVW;
931                         break;
932                 }
933                 break;
934         case TCHAR:
935                 switch(tt) {
936                 case TDOUBLE:
937                 case TVLONG:
938                         regalloc(&nod, f, Z);
939                         gins(AMOVB, f, &nod);
940                         gins(AMOVW, &nod, t);
941                         gins(AMOVWD, t, t);
942                         regfree(&nod);
943                         return;
944                 case TFLOAT:
945                         regalloc(&nod, f, Z);
946                         gins(AMOVB, f, &nod);
947                         gins(AMOVW, &nod, t);
948                         gins(AMOVWF, t, t);
949                         regfree(&nod);
950                         return;
951                 case TINT:
952                 case TUINT:
953                 case TLONG:
954                 case TULONG:
955                 case TIND:
956                 case TSHORT:
957                 case TUSHORT:
958                         a = AMOVB;
959                         break;
960                 case TCHAR:
961                 case TUCHAR:
962                         a = AMOVW;
963                         break;
964                 }
965                 break;
966         case TUCHAR:
967                 switch(tt) {
968                 case TDOUBLE:
969                 case TVLONG:
970                         regalloc(&nod, f, Z);
971                         gins(AMOVBU, f, &nod);
972                         gins(AMOVW, &nod, t);
973                         gins(AMOVWD, t, t);
974                         regfree(&nod);
975                         return;
976                 case TFLOAT:
977                         regalloc(&nod, f, Z);
978                         gins(AMOVBU, f, &nod);
979                         gins(AMOVW, &nod, t);
980                         gins(AMOVWF, t, t);
981                         regfree(&nod);
982                         return;
983                 case TINT:
984                 case TUINT:
985                 case TLONG:
986                 case TULONG:
987                 case TIND:
988                 case TSHORT:
989                 case TUSHORT:
990                         a = AMOVBU;
991                         break;
992                 case TCHAR:
993                 case TUCHAR:
994                         a = AMOVW;
995                         break;
996                 }
997                 break;
998         }
999         if(a == AGOK)
1000                 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
1001         if(a == AMOVW || a == AMOVF || a == AMOVD)
1002         if(samaddr(f, t))
1003                 return;
1004         gins(a, f, t);
1005 }
1006
1007 void
1008 gins(int a, Node *f, Node *t)
1009 {
1010
1011         nextpc();
1012         p->as = a;
1013         if(f != Z)
1014                 naddr(f, &p->from);
1015         if(t != Z)
1016                 naddr(t, &p->to);
1017         if(debug['g'])
1018                 print("%P\n", p);
1019 }
1020
1021 void
1022 gopcode(int o, Node *f1, Node *f2, Node *t)
1023 {
1024         int a, et;
1025         Adr ta;
1026
1027         et = TLONG;
1028         if(f1 != Z && f1->type != T)
1029                 et = f1->type->etype;
1030         a = AGOK;
1031         switch(o) {
1032         case OAS:
1033                 gmove(f1, t);
1034                 return;
1035
1036         case OASADD:
1037         case OADD:
1038                 a = AADDU;
1039                 if(et == TFLOAT)
1040                         a = AADDF;
1041                 else
1042                 if(et == TDOUBLE || et == TVLONG)
1043                         a = AADDD;
1044                 break;
1045
1046         case OASSUB:
1047         case OSUB:
1048                 a = ASUBU;
1049                 if(et == TFLOAT)
1050                         a = ASUBF;
1051                 else
1052                 if(et == TDOUBLE || et == TVLONG)
1053                         a = ASUBD;
1054                 break;
1055
1056         case OASOR:
1057         case OOR:
1058                 a = AOR;
1059                 break;
1060
1061         case OASAND:
1062         case OAND:
1063                 a = AAND;
1064                 break;
1065
1066         case OASXOR:
1067         case OXOR:
1068                 a = AXOR;
1069                 break;
1070
1071         case OASLSHR:
1072         case OLSHR:
1073                 a = ASRL;
1074                 break;
1075
1076         case OASASHR:
1077         case OASHR:
1078                 a = ASRA;
1079                 break;
1080
1081         case OASASHL:
1082         case OASHL:
1083                 a = ASLL;
1084                 break;
1085
1086         case OFUNC:
1087                 a = AJAL;
1088                 break;
1089
1090         case OCOND:
1091                 a = ASGTU;
1092                 break;
1093
1094         case OCOMMA:
1095                 a = ASGT;
1096                 break;
1097
1098         case OASMUL:
1099         case OMUL:
1100                 if(et == TFLOAT) {
1101                         a = AMULF;
1102                         break;
1103                 } else
1104                 if(et == TDOUBLE || et == TVLONG) {
1105                         a = AMULD;
1106                         break;
1107                 }
1108                 a = AMUL;
1109                 goto muldiv;
1110
1111         case OASDIV:
1112         case ODIV:
1113                 if(et == TFLOAT) {
1114                         a = ADIVF;
1115                         break;
1116                 } else
1117                 if(et == TDOUBLE || et == TVLONG) {
1118                         a = ADIVD;
1119                         break;
1120                 }
1121                 a = ADIV;
1122                 goto muldiv;
1123
1124         case OASMOD:
1125         case OMOD:
1126                 a = ADIV;
1127                 o = OMOD;
1128                 goto muldiv;
1129
1130         case OASLMUL:
1131         case OLMUL:
1132                 a = AMULU;
1133                 goto muldiv;
1134
1135         case OASLMOD:
1136         case OLMOD:
1137                 a = ADIVU;
1138                 o = OMOD;
1139                 goto muldiv;
1140
1141         case OASLDIV:
1142         case OLDIV:
1143                 a = ADIVU;
1144                 goto muldiv;
1145
1146         muldiv:
1147                 nextpc();
1148                 naddr(f1, &p->from);
1149                 if(f2 == Z)
1150                         raddr(t, p);
1151                 else
1152                         raddr(f2, p);
1153                 p->as = a;
1154                 if(debug['g'])
1155                         print("%P\n", p);
1156
1157                 nextpc();
1158                 p->as = AMOVW;
1159                 a = D_LO;
1160                 if(o == OMOD)
1161                         a = D_HI;
1162                 p->from.type = a;
1163                 naddr(t, &p->to);
1164                 if(debug['g'])
1165                         print("%P\n", p);
1166                 return;
1167
1168         case OEQ:
1169                 if(!typefd[et]) {
1170                         a = ABEQ;
1171                         break;
1172                 }
1173
1174         case ONE:
1175                 if(!typefd[et]) {
1176                         a = ABNE;
1177                         break;
1178                 }
1179
1180         case OLT:
1181         case OLE:
1182         case OGE:
1183         case OGT:
1184                 if(typefd[et]) {
1185                         nextpc();
1186                         if(et == TFLOAT) {
1187                                 a = ACMPGTF;
1188                                 if(o == OEQ || o == ONE)
1189                                         a = ACMPEQF;
1190                                 else
1191                                 if(o == OLT || o == OGE)
1192                                         a = ACMPGEF;
1193                         } else {
1194                                 a = ACMPGTD;
1195                                 if(o == OEQ || o == ONE)
1196                                         a = ACMPEQD;
1197                                 else
1198                                 if(o == OLT || o == OGE)
1199                                         a = ACMPGED;
1200                         }
1201                         p->as = a;
1202                         naddr(f1, &p->from);
1203                         raddr(f2, p);
1204                         if(debug['g'])
1205                                 print("%P\n", p);
1206                         nextpc();
1207                         a = ABFPF;
1208                         if(o == OEQ || o == OGE || o == OGT)
1209                                 a = ABFPT;
1210                         p->as = a;
1211                         if(debug['g'])
1212                                 print("%P\n", p);
1213                         return;
1214                 }
1215                 if(vconst(f1) == 0 || vconst(f2) == 0) {
1216                         if(vconst(f1) == 0) {
1217                                 o = invrel[relindex(o)];
1218                                 f1 = f2;
1219                         }
1220                         switch(o) {
1221                         case OLT:
1222                                 a = ABLTZ;
1223                                 break;
1224                         case OLE:
1225                                 a = ABLEZ;
1226                                 break;
1227                         case OGE:
1228                                 a = ABGEZ;
1229                                 break;
1230                         case OGT:
1231                                 a = ABGTZ;
1232                                 break;
1233                         }
1234                         f2 = Z;
1235                         break;
1236                 }
1237
1238         case OLO:
1239         case OLS:
1240         case OHS:
1241         case OHI:
1242                 nextpc();
1243                 if(o == OLE || o == OGT || o == OLS || o == OHI) {
1244                         naddr(f1, &p->from);
1245                         raddr(f2, p);
1246                 } else {
1247                         naddr(f2, &p->from);
1248                         raddr(f1, p);
1249                 }
1250                 naddr(&regnode, &p->to);
1251                 p->to.reg = tmpreg();
1252                 a = ASGT;
1253                 if(o == OLO || o == OLS || o == OHS || o == OHI)
1254                         a = ASGTU;
1255                 p->as = a;
1256                 if(debug['g'])
1257                         print("%P\n", p);
1258
1259                 nextpc();
1260                 naddr(&regnode, &p->from);
1261                 p->from.reg = tmpreg();
1262                 a = ABEQ;
1263                 if(o == OLT || o == OGT || o == OLO || o == OHI)
1264                         a = ABNE;
1265                 p->as = a;
1266                 if(debug['g'])
1267                         print("%P\n", p);
1268                 return;
1269         }
1270         if(a == AGOK)
1271                 diag(Z, "bad in gopcode %O", o);
1272         nextpc();
1273         p->as = a;
1274         if(f1 != Z)
1275                 naddr(f1, &p->from);
1276         if(f2 != Z) {
1277                 naddr(f2, &ta);
1278                 p->reg = ta.reg;
1279                 if(ta.type == D_CONST && ta.offset == 0)
1280                         p->reg = REGZERO;
1281         }
1282         if(t != Z)
1283                 naddr(t, &p->to);
1284         if(debug['g'])
1285                 print("%P\n", p);
1286 }
1287
1288 int
1289 samaddr(Node *f, Node *t)
1290 {
1291
1292         if(f->op != t->op)
1293                 return 0;
1294         switch(f->op) {
1295
1296         case OREGISTER:
1297                 if(f->reg != t->reg)
1298                         break;
1299                 return 1;
1300         }
1301         return 0;
1302 }
1303
1304 void
1305 gbranch(int o)
1306 {
1307         int a;
1308
1309         a = AGOK;
1310         switch(o) {
1311         case ORETURN:
1312                 a = ARET;
1313                 break;
1314         case OGOTO:
1315                 a = AJMP;
1316                 break;
1317         }
1318         nextpc();
1319         if(a == AGOK) {
1320                 diag(Z, "bad in gbranch %O",  o);
1321                 nextpc();
1322         }
1323         p->as = a;
1324 }
1325
1326 void
1327 patch(Prog *op, long pc)
1328 {
1329
1330         op->to.offset = pc;
1331         op->to.type = D_BRANCH;
1332 }
1333
1334 void
1335 gpseudo(int a, Sym *s, Node *n)
1336 {
1337
1338         nextpc();
1339         p->as = a;
1340         p->from.type = D_OREG;
1341         p->from.sym = s;
1342         if(a == ATEXT)
1343                 p->reg = (profileflg ? 0 : NOPROF);
1344         p->from.name = D_EXTERN;
1345         if(s->class == CSTATIC)
1346                 p->from.name = D_STATIC;
1347         naddr(n, &p->to);
1348         if(a == ADATA || a == AGLOBL)
1349                 pc--;
1350 }
1351
1352 int
1353 sconst(Node *n)
1354 {
1355         vlong vv;
1356
1357         if(n->op == OCONST) {
1358                 if(!typefd[n->type->etype]) {
1359                         vv = n->vconst;
1360                         if(vv >= (vlong)(-32766) && vv < (vlong)32766)
1361                                 return 1;
1362                 }
1363         }
1364         return 0;
1365 }
1366
1367 int
1368 sval(long v)
1369 {
1370         if(v >= -32766L && v < 32766L)
1371                 return 1;
1372         return 0;
1373 }
1374
1375 long
1376 exreg(Type *t)
1377 {
1378         long o;
1379
1380         if(typechlp[t->etype]) {
1381                 if(exregoffset <= 16)
1382                         return 0;
1383                 o = exregoffset;
1384                 exregoffset--;
1385                 return o;
1386         }
1387         if(typefd[t->etype]) {
1388                 if(exfregoffset <= 16)
1389                         return 0;
1390                 o = exfregoffset + NREG;
1391                 exfregoffset--;
1392                 return o;
1393         }
1394         return 0;
1395 }
1396
1397 schar   ewidth[NTYPE] =
1398 {
1399         -1,             /* [TXXX] */
1400         SZ_CHAR,        /* [TCHAR] */
1401         SZ_CHAR,        /* [TUCHAR] */
1402         SZ_SHORT,       /* [TSHORT] */
1403         SZ_SHORT,       /* [TUSHORT] */
1404         SZ_INT,         /* [TINT] */
1405         SZ_INT,         /* [TUINT] */
1406         SZ_LONG,        /* [TLONG] */
1407         SZ_LONG,        /* [TULONG] */
1408         SZ_VLONG,       /* [TVLONG] */
1409         SZ_VLONG,       /* [TUVLONG] */
1410         SZ_FLOAT,       /* [TFLOAT] */
1411         SZ_DOUBLE,      /* [TDOUBLE] */
1412         SZ_IND,         /* [TIND] */
1413         0,              /* [TFUNC] */
1414         -1,             /* [TARRAY] */
1415         0,              /* [TVOID] */
1416         -1,             /* [TSTRUCT] */
1417         -1,             /* [TUNION] */
1418         SZ_INT,         /* [TENUM] */
1419 };
1420
1421 long    ncast[NTYPE] =
1422 {
1423         0,                              /* [TXXX] */
1424         BCHAR|BUCHAR,                   /* [TCHAR] */
1425         BCHAR|BUCHAR,                   /* [TUCHAR] */
1426         BSHORT|BUSHORT,                 /* [TSHORT] */
1427         BSHORT|BUSHORT,                 /* [TUSHORT] */
1428         BINT|BUINT|BLONG|BULONG|BIND,   /* [TINT] */
1429         BINT|BUINT|BLONG|BULONG|BIND,   /* [TUINT] */
1430         BINT|BUINT|BLONG|BULONG|BIND,   /* [TLONG] */
1431         BINT|BUINT|BLONG|BULONG|BIND,   /* [TULONG] */
1432         BVLONG|BUVLONG,                 /* [TVLONG] */
1433         BVLONG|BUVLONG,                 /* [TUVLONG] */
1434         BFLOAT,                         /* [TFLOAT] */
1435         BDOUBLE,                        /* [TDOUBLE] */
1436         BLONG|BULONG|BIND,              /* [TIND] */
1437         0,                              /* [TFUNC] */
1438         0,                              /* [TARRAY] */
1439         0,                              /* [TVOID] */
1440         BSTRUCT,                        /* [TSTRUCT] */
1441         BUNION,                         /* [TUNION] */
1442         0,                              /* [TENUM] */
1443 };