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