]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/kc/txt.c
merge
[plan9front.git] / sys / src / cmd / kc / txt.c
1 #include "gc.h"
2
3 void
4 ginit(void)
5 {
6         int i;
7         Type *t;
8
9         thechar = 'k';
10         thestring = "sparc";
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 = 0;
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         memset(reg, 0, sizeof(reg));
83         reg[REGZERO] = 1;
84         reg[REGLINK] = 1;
85         reg[REGTMP] = 1;
86         for(i=NREG; i<NREG+NREG; i+=2)
87                 reg[i+1] = 1;
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 && i != REGTMP && i != REGLINK)
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 nod32const(vlong v)
220 {
221         constnode.vconst = v & MASK(32);
222         return &constnode;
223 }
224
225 Node*
226 nodconst(long v)
227 {
228         constnode.vconst = v;
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 void
261 regalloc(Node *n, Node *tn, Node *o)
262 {
263         int i, j;
264         static int lasti;
265
266         switch(tn->type->etype) {
267         case TCHAR:
268         case TUCHAR:
269         case TSHORT:
270         case TUSHORT:
271         case TINT:
272         case TUINT:
273         case TLONG:
274         case TULONG:
275         case TIND:
276                 if(o != Z && o->op == OREGISTER) {
277                         i = o->reg;
278                         if(i > 0 && i < NREG)
279                                 goto out;
280                 }
281                 j = lasti + REGRET+1;
282                 for(i=REGRET+1; i<NREG; i++) {
283                         if(j >= NREG)
284                                 j = REGRET+1;
285                         if(reg[j] == 0) {
286                                 i = j;
287                                 goto out;
288                         }
289                         j++;
290                 }
291                 diag(tn, "out of fixed registers");
292                 goto err;
293
294         case TFLOAT:
295         case TDOUBLE:
296         case TVLONG:
297                 if(o != Z && o->op == OREGISTER) {
298                         i = o->reg;
299                         if(i >= NREG && i < NREG+NREG)
300                                 goto out;
301                 }
302                 j = lasti*2 + NREG;
303                 for(i=NREG; i<NREG+NREG; i+=2) {
304                         if(j >= NREG+NREG)
305                                 j = NREG;
306                         if(reg[j] == 0) {
307                                 i = j;
308                                 goto out;
309                         }
310                         j += 2;
311                 }
312                 diag(tn, "out of float registers");
313                 goto err;
314         }
315         diag(tn, "unknown type in regalloc: %T", tn->type);
316 err:
317         i = 0;
318 out:
319         if(i)
320                 reg[i]++;
321         lasti++;
322         if(lasti >= 5)
323                 lasti = 0;
324         nodreg(n, tn, i);
325 }
326
327 void
328 regialloc(Node *n, Node *tn, Node *o)
329 {
330         Node nod;
331
332         nod = *tn;
333         nod.type = types[TIND];
334         regalloc(n, &nod, o);
335 }
336
337 void
338 regfree(Node *n)
339 {
340         int i;
341
342         i = 0;
343         if(n->op != OREGISTER && n->op != OINDREG)
344                 goto err;
345         i = n->reg;
346         if(i < 0 || i >= sizeof(reg))
347                 goto err;
348         if(reg[i] <= 0)
349                 goto err;
350         reg[i]--;
351         return;
352 err:
353         diag(n, "error in regfree: %d", i);
354 }
355
356 void
357 regsalloc(Node *n, Node *nn)
358 {
359         cursafe = align(cursafe, nn->type, Aaut3);
360         maxargsafe = maxround(maxargsafe, cursafe+curarg);
361         *n = *nodsafe;
362         n->xoffset = -(stkoff + cursafe);
363         n->type = nn->type;
364         n->etype = nn->type->etype;
365         n->lineno = nn->lineno;
366 }
367
368 void
369 regaalloc1(Node *n, Node *nn)
370 {
371         nodreg(n, nn, REGARG);
372         reg[REGARG]++;
373         curarg = align(curarg, nn->type, Aarg1);
374         curarg = align(curarg, nn->type, Aarg2);
375         maxargsafe = maxround(maxargsafe, cursafe+curarg);
376 }
377
378 void
379 regaalloc(Node *n, Node *nn)
380 {
381         curarg = align(curarg, nn->type, Aarg1);
382         *n = *nn;
383         n->op = OINDREG;
384         n->reg = REGSP;
385         n->xoffset = curarg + SZ_LONG;
386         n->complex = 0;
387         n->addable = 20;
388         curarg = align(curarg, nn->type, Aarg2);
389         maxargsafe = maxround(maxargsafe, cursafe+curarg);
390 }
391
392 void
393 regind(Node *n, Node *nn)
394 {
395
396         if(n->op != OREGISTER) {
397                 diag(n, "regind not OREGISTER");
398                 return;
399         }
400         n->op = OINDREG;
401         n->type = nn->type;
402 }
403
404 void
405 raddr(Node *n, Prog *p)
406 {
407         Adr a;
408
409         naddr(n, &a);
410         if(a.type == D_CONST && a.offset == 0) {
411                 a.type = D_REG;
412                 a.reg = 0;
413         }
414         if(a.type != D_REG && a.type != D_FREG) {
415                 if(n)
416                         diag(n, "bad in raddr: %O", n->op);
417                 else
418                         diag(n, "bad in raddr: <null>");
419                 p->reg = NREG;
420         } else
421                 p->reg = a.reg;
422 }
423
424 void
425 naddr(Node *n, Adr *a)
426 {
427         long v;
428
429         a->type = D_NONE;
430         if(n == Z)
431                 return;
432         switch(n->op) {
433         default:
434         bad:
435                 diag(n, "bad in naddr: %O", n->op);
436                 break;
437
438         case OREGISTER:
439                 a->type = D_REG;
440                 a->sym = S;
441                 a->reg = n->reg;
442                 if(a->reg >= NREG) {
443                         a->type = D_FREG;
444                         a->reg -= NREG;
445                 }
446                 break;
447
448         case OIND:
449                 naddr(n->left, a);
450                 if(a->type == D_REG) {
451                         a->type = D_OREG;
452                         break;
453                 }
454                 if(a->type == D_CONST) {
455                         a->type = D_OREG;
456                         break;
457                 }
458                 goto bad;
459
460         case OINDREG:
461                 a->type = D_OREG;
462                 a->sym = S;
463                 a->offset = n->xoffset;
464                 a->reg = n->reg;
465                 break;
466
467         case ONAME:
468                 a->etype = n->etype;
469                 a->type = D_OREG;
470                 a->name = D_STATIC;
471                 a->sym = n->sym;
472                 a->offset = n->xoffset;
473                 if(n->class == CSTATIC)
474                         break;
475                 if(n->class == CEXTERN || n->class == CGLOBL) {
476                         a->name = D_EXTERN;
477                         break;
478                 }
479                 if(n->class == CAUTO) {
480                         a->name = D_AUTO;
481                         break;
482                 }
483                 if(n->class == CPARAM) {
484                         a->name = D_PARAM;
485                         break;
486                 }
487                 goto bad;
488
489         case OCONST:
490                 a->sym = S;
491                 a->reg = NREG;
492                 if(typefd[n->type->etype]) {
493                         a->type = D_FCONST;
494                         a->dval = n->fconst;
495                 } else {
496                         a->type = D_CONST;
497                         a->offset = n->vconst;
498                 }
499                 break;
500
501         case OADDR:
502                 naddr(n->left, a);
503                 if(a->type == D_OREG) {
504                         a->type = D_CONST;
505                         break;
506                 }
507                 goto bad;
508
509         case OADD:
510                 if(n->left->op == OCONST) {
511                         naddr(n->left, a);
512                         v = a->offset;
513                         naddr(n->right, a);
514                 } else {
515                         naddr(n->right, a);
516                         v = a->offset;
517                         naddr(n->left, a);
518                 }
519                 a->offset += v;
520                 break;
521
522         }
523 }
524
525 void
526 fop(int as, int f1, int f2, Node *t)
527 {
528         Node nod1, nod2, nod3;
529
530         nodreg(&nod1, t, NREG+f1);
531         nodreg(&nod2, t, NREG+f2);
532         regalloc(&nod3, t, t);
533         gopcode(as, &nod1, &nod2, &nod3);
534         gmove(&nod3, t);
535         regfree(&nod3);
536 }
537
538 void
539 gmove(Node *f, Node *t)
540 {
541         int ft, tt, a;
542         Node nod;
543         Prog *p1;
544         double d;
545
546         ft = f->type->etype;
547         tt = t->type->etype;
548
549         if(ft == TDOUBLE && f->op == OCONST) {
550                 d = f->fconst;
551                 if(d == 0.0) {
552                         a = FREGZERO;
553                         goto ffreg;
554                 }
555                 if(d == 0.5) {
556                         a = FREGHALF;
557                         goto ffreg;
558                 }
559                 if(d == 1.0) {
560                         a = FREGONE;
561                         goto ffreg;
562                 }
563                 if(d == 2.0) {
564                         a = FREGTWO;
565                         goto ffreg;
566                 }
567                 if(d == -.5) {
568                         fop(OSUB, FREGHALF, FREGZERO, t);
569                         return;
570                 }
571                 if(d == -1.0) {
572                         fop(OSUB, FREGONE, FREGZERO, t);
573                         return;
574                 }
575                 if(d == -2.0) {
576                         fop(OSUB, FREGTWO, FREGZERO, t);
577                         return;
578                 }
579                 if(d == 1.5) {
580                         fop(OADD, FREGONE, FREGHALF, t);
581                         return;
582                 }
583                 if(d == 2.5) {
584                         fop(OADD, FREGTWO, FREGHALF, t);
585                         return;
586                 }
587                 if(d == 3.0) {
588                         fop(OADD, FREGTWO, FREGONE, t);
589                         return;
590                 }
591         }
592         if(ft == TFLOAT && f->op == OCONST) {
593                 d = f->fconst;
594                 if(d == 0) {
595                         a = FREGZERO;
596                 ffreg:
597                         nodreg(&nod, f, NREG+a);
598                         gmove(&nod, t);
599                         return;
600                 }
601         }
602         /*
603          * a load --
604          * put it into a register then
605          * worry what to do with it.
606          */
607         if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
608                 switch(ft) {
609                 default:
610                         if(typefd[tt]) {
611                                 /* special case can load mem to Freg */
612                                 regalloc(&nod, t, t);
613                                 gins(AMOVW, f, &nod);
614                                 a = AFMOVWD;
615                                 if(tt == TFLOAT)
616                                         a = AFMOVWF;
617                                 gins(a, &nod, &nod);
618                                 gmove(&nod, t);
619                                 regfree(&nod);
620                                 return;
621                         }
622                         a = AMOVW;
623                         break;
624                 case TFLOAT:
625                         a = AFMOVF;
626                         break;
627                 case TDOUBLE:
628                         a = AFMOVD;
629                         break;
630                 case TCHAR:
631                         a = AMOVB;
632                         break;
633                 case TUCHAR:
634                         a = AMOVBU;
635                         break;
636                 case TSHORT:
637                         a = AMOVH;
638                         break;
639                 case TUSHORT:
640                         a = AMOVHU;
641                         break;
642                 }
643                 regalloc(&nod, f, t);
644                 gins(a, f, &nod);
645                 gmove(&nod, t);
646                 regfree(&nod);
647                 return;
648         }
649
650         /*
651          * a store --
652          * put it into a register then
653          * store it.
654          */
655         if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
656                 switch(tt) {
657                 default:
658                         if(typefd[ft]) {
659                                 /* special case can store mem from Freg */
660                                 regalloc(&nod, f, Z);
661                                 a = AFMOVDW;
662                                 if(ft == TFLOAT)
663                                         a = AFMOVFW;
664                                 gins(a, f, &nod);
665                                 gins(AMOVW, &nod, t);
666                                 regfree(&nod);
667                                 return;
668                         }
669                         a = AMOVW;
670                         break;
671                 case TUCHAR:
672                         a = AMOVBU;
673                         break;
674                 case TCHAR:
675                         a = AMOVB;
676                         break;
677                 case TUSHORT:
678                         a = AMOVHU;
679                         break;
680                 case TSHORT:
681                         a = AMOVH;
682                         break;
683                 case TFLOAT:
684                         a = AFMOVF;
685                         break;
686                 case TVLONG:
687                 case TDOUBLE:
688                         a = AFMOVD;
689                         break;
690                 }
691                 if(!typefd[ft] && vconst(f) == 0) {
692                         gins(a, f, t);
693                         return;
694                 }
695                 if(ft == tt)
696                         regalloc(&nod, t, f);
697                 else
698                         regalloc(&nod, t, Z);
699                 gmove(f, &nod);
700                 gins(a, &nod, t);
701                 regfree(&nod);
702                 return;
703         }
704
705         /*
706          * type x type cross table
707          */
708         a = AGOK;
709         switch(ft) {
710         case TDOUBLE:
711         case TVLONG:
712         case TFLOAT:
713                 switch(tt) {
714                 case TDOUBLE:
715                 case TVLONG:
716                         a = AFMOVD;
717                         if(ft == TFLOAT)
718                                 a = AFMOVFD;
719                         break;
720                 case TFLOAT:
721                         a = AFMOVDF;
722                         if(ft == TFLOAT)
723                                 a = AFMOVF;
724                         break;
725                 case TLONG:
726                 case TULONG:
727                 case TIND:
728                 case TINT:
729                 case TUINT:
730                 case TSHORT:
731                 case TUSHORT:
732                 case TCHAR:
733                 case TUCHAR:
734                         regalloc(&nod, f, Z);   /* should be type float */
735                         a = AFMOVDW;
736                         if(ft == TFLOAT)
737                                 a = AFMOVFW;
738                         gins(a, f, &nod);
739                         gins(AFMOVF, &nod, nodrat);
740                         regfree(&nod);
741                         gins(AMOVW, nodrat, t);
742                         gmove(t, t);
743                         if(nrathole < SZ_LONG)
744                                 nrathole = SZ_LONG;
745                         return;
746                 }
747                 break;
748         case TINT:
749         case TUINT:
750         case TLONG:
751         case TULONG:
752         case TIND:
753                 switch(tt) {
754                 case TDOUBLE:
755                 case TVLONG:
756                 case TFLOAT:
757                         goto fxtofl;
758                 case TLONG:
759                 case TULONG:
760                 case TINT:
761                 case TUINT:
762                 case TIND:
763                 case TSHORT:
764                 case TUSHORT:
765                 case TCHAR:
766                 case TUCHAR:
767                         a = AMOVW;
768                         break;
769                 }
770                 break;
771         case TSHORT:
772                 switch(tt) {
773                 case TDOUBLE:
774                 case TVLONG:
775                 case TFLOAT:
776                         goto fxtofl;
777                 case TUINT:
778                 case TINT:
779                 case TULONG:
780                 case TLONG:
781                 case TIND:
782                         a = AMOVH;
783                         break;
784                 case TSHORT:
785                 case TUSHORT:
786                 case TCHAR:
787                 case TUCHAR:
788                         a = AMOVW;
789                         break;
790                 }
791                 break;
792         case TUSHORT:
793                 switch(tt) {
794                 case TDOUBLE:
795                 case TVLONG:
796                 case TFLOAT:
797                         goto fxtofl;
798                 case TINT:
799                 case TUINT:
800                 case TLONG:
801                 case TULONG:
802                 case TIND:
803                         a = AMOVHU;
804                         break;
805                 case TSHORT:
806                 case TUSHORT:
807                 case TCHAR:
808                 case TUCHAR:
809                         a = AMOVW;
810                         break;
811                 }
812                 break;
813         case TCHAR:
814                 switch(tt) {
815                 case TDOUBLE:
816                 case TVLONG:
817                 case TFLOAT:
818                         goto fxtofl;
819                 case TINT:
820                 case TUINT:
821                 case TLONG:
822                 case TULONG:
823                 case TIND:
824                 case TSHORT:
825                 case TUSHORT:
826                         a = AMOVB;
827                         break;
828                 case TCHAR:
829                 case TUCHAR:
830                         a = AMOVW;
831                         break;
832                 }
833                 break;
834         case TUCHAR:
835                 switch(tt) {
836                 case TDOUBLE:
837                 case TVLONG:
838                 case TFLOAT:
839                 fxtofl:
840                         regalloc(&nod, t, t);   /* should be type float */
841                         gins(AMOVW, f, nodrat);
842                         gins(AFMOVF, nodrat, &nod);
843                         a = AFMOVWD;
844                         if(tt == TFLOAT)
845                                 a = AFMOVWF;
846                         gins(a, &nod, t);
847                         regfree(&nod);
848                         if(nrathole < SZ_LONG)
849                                 nrathole = SZ_LONG;
850                         if(ft == TULONG) {
851                                 regalloc(&nod, t, Z);
852                                 if(tt == TFLOAT) {
853                                         gins(AFCMPF, t, Z);
854                                         p->to.type = D_FREG;
855                                         p->to.reg = FREGZERO;
856                                         gins(AFBGE, Z, Z);
857                                         p1 = p;
858                                         gins(AFMOVF, nodfconst(4294967296.), &nod);
859                                         gins(AFADDF, &nod, t);
860                                 } else {
861                                         gins(AFCMPD, t, Z);
862                                         p->to.type = D_FREG;
863                                         p->to.reg = FREGZERO;
864                                         gins(AFBGE, Z, Z);
865                                         p1 = p;
866                                         gins(AFMOVD, nodfconst(4294967296.), &nod);
867                                         gins(AFADDD, &nod, t);
868                                 }
869                                 patch(p1, pc);
870                                 regfree(&nod);
871                         }
872                         return;
873                 case TINT:
874                 case TUINT:
875                 case TLONG:
876                 case TULONG:
877                 case TIND:
878                 case TSHORT:
879                 case TUSHORT:
880                         a = AMOVBU;
881                         break;
882                 case TCHAR:
883                 case TUCHAR:
884                         a = AMOVW;
885                         break;
886                 }
887                 break;
888         }
889         if(a == AGOK)
890                 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
891         if(a == AMOVW || a == AFMOVF || a == AFMOVD)
892         if(samaddr(f, t))
893                 return;
894         gins(a, f, t);
895 }
896
897 void
898 gins(int a, Node *f, Node *t)
899 {
900
901         nextpc();
902         p->as = a;
903         if(f != Z)
904                 naddr(f, &p->from);
905         if(t != Z)
906                 naddr(t, &p->to);
907         if(debug['g'])
908                 print("%P\n", p);
909 }
910
911 void
912 gopcode(int o, Node *f1, Node *f2, Node *t)
913 {
914         int a, et;
915         Adr ta;
916
917         et = TLONG;
918         if(f1 != Z && f1->type != T)
919                 et = f1->type->etype;
920         a = AGOK;
921         switch(o) {
922         case OAS:
923                 gmove(f1, t);
924                 return;
925
926         case OASADD:
927         case OADD:
928                 a = AADD;
929                 if(et == TFLOAT)
930                         a = AFADDF;
931                 else
932                 if(et == TDOUBLE || et == TVLONG)
933                         a = AFADDD;
934                 break;
935
936         case OASSUB:
937         case OSUB:
938                 a = ASUB;
939                 if(et == TFLOAT)
940                         a = AFSUBF;
941                 else
942                 if(et == TDOUBLE || et == TVLONG)
943                         a = AFSUBD;
944                 break;
945
946         case OASOR:
947         case OOR:
948                 a = AOR;
949                 break;
950
951         case OASAND:
952         case OAND:
953                 a = AAND;
954                 break;
955
956         case OASXOR:
957         case OXOR:
958                 a = AXOR;
959                 break;
960
961         case OASLSHR:
962         case OLSHR:
963                 a = ASRL;
964                 break;
965
966         case OASASHR:
967         case OASHR:
968                 a = ASRA;
969                 break;
970
971         case OASASHL:
972         case OASHL:
973                 a = ASLL;
974                 break;
975
976         case OFUNC:
977                 a = AJMPL;
978                 break;
979
980         case OASLMUL:
981         case OLMUL:
982         case OASMUL:
983         case OMUL:
984                 if(et == TFLOAT) {
985                         a = AFMULF;
986                         break;
987                 } else
988                 if(et == TDOUBLE || et == TVLONG) {
989                         a = AFMULD;
990                         break;
991                 }
992                 a = AMUL;
993                 break;
994
995         case OASDIV:
996         case ODIV:
997                 if(et == TFLOAT) {
998                         a = AFDIVF;
999                         break;
1000                 } else
1001                 if(et == TDOUBLE || et == TVLONG) {
1002                         a = AFDIVD;
1003                         break;
1004                 }
1005                 a = ADIV;
1006                 break;
1007
1008         case OASMOD:
1009         case OMOD:
1010                 a = AMOD;
1011                 break;
1012
1013         case OASLMOD:
1014         case OLMOD:
1015                 a = AMODL;
1016                 break;
1017
1018         case OASLDIV:
1019         case OLDIV:
1020                 a = ADIVL;
1021                 break;
1022
1023         case OEQ:
1024                 a = ABE;
1025                 if(typefd[et])
1026                         a = AFBE;
1027                 goto cmp;
1028
1029         case ONE:
1030                 a = ABNE;
1031                 if(typefd[et])
1032                         a = AFBLG;
1033                 goto cmp;
1034
1035         case OLT:
1036                 a = ABL;
1037                 if(typefd[et])
1038                         a = AFBL;
1039                 goto cmp;
1040
1041         case OLE:
1042                 a = ABLE;
1043                 if(typefd[et])
1044                         a = AFBLE;
1045                 goto cmp;
1046
1047         case OGE:
1048                 a = ABGE;
1049                 if(typefd[et])
1050                         a = AFBGE;
1051                 goto cmp;
1052
1053         case OGT:
1054                 a = ABG;
1055                 if(typefd[et])
1056                         a = AFBG;
1057                 goto cmp;
1058
1059         case OLO:
1060                 a = ABCS;
1061                 goto cmp;
1062
1063         case OLS:
1064                 a = ABLEU;
1065                 goto cmp;
1066
1067         case OHS:
1068                 a = ABCC;
1069                 goto cmp;
1070
1071         case OHI:
1072                 a = ABGU;
1073                 goto cmp;
1074
1075         cmp:
1076                 nextpc();
1077                 p->as = ACMP;
1078                 if(et == TFLOAT)
1079                         p->as = AFCMPF;
1080                 else
1081                 if(et == TDOUBLE || et == TVLONG)
1082                         p->as = AFCMPD;
1083                 if(f1 != Z)
1084                         naddr(f1, &p->from);
1085                 if(t != Z)
1086                         naddr(t, &p->to);
1087                 if(f1 == Z || t == Z || f2 != Z)
1088                         diag(Z, "bad cmp in gopcode %O", o);
1089                 if(debug['g'])
1090                         print("%P\n", p);
1091                 f1 = Z;
1092                 f2 = Z;
1093                 t = Z;
1094                 break;
1095         }
1096         if(a == AGOK)
1097                 diag(Z, "bad in gopcode %O", o);
1098         nextpc();
1099         p->as = a;
1100         if(f1 != Z)
1101                 naddr(f1, &p->from);
1102         if(f2 != Z) {
1103                 naddr(f2, &ta);
1104                 p->reg = ta.reg;
1105                 if(ta.type == D_CONST && ta.offset == 0)
1106                         p->reg = REGZERO;
1107         }
1108         if(t != Z)
1109                 naddr(t, &p->to);
1110         if(debug['g'])
1111                 print("%P\n", p);
1112 }
1113
1114 samaddr(Node *f, Node *t)
1115 {
1116
1117         if(f->op != t->op)
1118                 return 0;
1119         switch(f->op) {
1120
1121         case OREGISTER:
1122                 if(f->reg != t->reg)
1123                         break;
1124                 return 1;
1125         }
1126         return 0;
1127 }
1128
1129 void
1130 gbranch(int o)
1131 {
1132         int a;
1133
1134         a = AGOK;
1135         switch(o) {
1136         case ORETURN:
1137                 a = ARETURN;
1138                 break;
1139         case OGOTO:
1140                 a = AJMP;
1141                 break;
1142         }
1143         nextpc();
1144         if(a == AGOK) {
1145                 diag(Z, "bad in gbranch %O",  o);
1146                 nextpc();
1147         }
1148         p->as = a;
1149 }
1150
1151 void
1152 patch(Prog *op, long pc)
1153 {
1154
1155         op->to.offset = pc;
1156         op->to.type = D_BRANCH;
1157 }
1158
1159 void
1160 gpseudo(int a, Sym *s, Node *n)
1161 {
1162
1163         nextpc();
1164         p->as = a;
1165         p->from.type = D_OREG;
1166         p->from.sym = s;
1167         if(a == ATEXT)
1168                 p->reg = (profileflg ? 0 : NOPROF);
1169         p->from.name = D_EXTERN;
1170         if(s->class == CSTATIC)
1171                 p->from.name = D_STATIC;
1172         naddr(n, &p->to);
1173         if(a == ADATA || a == AGLOBL)
1174                 pc--;
1175 }
1176
1177 int
1178 sval(long v)
1179 {
1180
1181         if(v >= -(1<<12) && v < (1<<12))
1182                 return 1;
1183         return 0;
1184 }
1185
1186 int
1187 sconst(Node *n)
1188 {
1189         vlong vv;
1190
1191         if(n->op == OCONST) {
1192                 if(!typefd[n->type->etype]) {
1193                         vv = n->vconst;
1194                         if(vv >= -(vlong)(1<<12) && vv < (vlong)(1<<12))
1195                                 return 1;
1196                 }
1197         }
1198         return 0;
1199 }
1200
1201 long
1202 exreg(Type *t)
1203 {
1204         long o;
1205
1206         if(typechlp[t->etype]) {
1207                 if(exregoffset <= 3)
1208                         return 0;
1209                 o = exregoffset;
1210                 exregoffset--;
1211                 return o;
1212         }
1213         if(typefd[t->etype]) {
1214                 if(exfregoffset <= 16)
1215                         return 0;
1216                 o = exfregoffset + NREG;
1217                 exfregoffset--;
1218                 return o;
1219         }
1220         return 0;
1221 }
1222
1223 schar   ewidth[NTYPE] =
1224 {
1225         -1,             /* [TXXX] */
1226         SZ_CHAR,        /* [TCHAR] */
1227         SZ_CHAR,        /* [TUCHAR] */
1228         SZ_SHORT,       /* [TSHORT] */
1229         SZ_SHORT,       /* [TUSHORT] */
1230         SZ_INT,         /* [TINT] */
1231         SZ_INT,         /* [TUINT] */
1232         SZ_LONG,        /* [TLONG] */
1233         SZ_LONG,        /* [TULONG] */
1234         SZ_VLONG,       /* [TVLONG] */
1235         SZ_VLONG,       /* [TUVLONG] */
1236         SZ_FLOAT,       /* [TFLOAT] */
1237         SZ_DOUBLE,      /* [TDOUBLE] */
1238         SZ_IND,         /* [TIND] */
1239         0,              /* [TFUNC] */
1240         -1,             /* [TARRAY] */
1241         0,              /* [TVOID] */
1242         -1,             /* [TSTRUCT] */
1243         -1,             /* [TUNION] */
1244         SZ_INT,         /* [TENUM] */
1245 };
1246
1247 long    ncast[NTYPE] =
1248 {
1249         0,                              /* [TXXX] */
1250         BCHAR|BUCHAR,                   /* [TCHAR] */
1251         BCHAR|BUCHAR,                   /* [TUCHAR] */
1252         BSHORT|BUSHORT,                 /* [TSHORT] */
1253         BSHORT|BUSHORT,                 /* [TUSHORT] */
1254         BINT|BUINT|BLONG|BULONG|BIND,   /* [TINT] */
1255         BINT|BUINT|BLONG|BULONG|BIND,   /* [TUINT] */
1256         BINT|BUINT|BLONG|BULONG|BIND,   /* [TLONG] */
1257         BINT|BUINT|BLONG|BULONG|BIND,   /* [TULONG] */
1258         BVLONG|BUVLONG,                 /* [TVLONG] */
1259         BVLONG|BUVLONG,                 /* [TUVLONG] */
1260         BFLOAT,                         /* [TFLOAT] */
1261         BDOUBLE,                        /* [TDOUBLE] */
1262         BLONG|BULONG|BIND,              /* [TIND] */
1263         0,                              /* [TFUNC] */
1264         0,                              /* [TARRAY] */
1265         0,                              /* [TVOID] */
1266         BSTRUCT,                        /* [TSTRUCT] */
1267         BUNION,                         /* [TUNION] */
1268         0,                              /* [TENUM] */
1269 };