]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/qc/txt.c
merge
[plan9front.git] / sys / src / cmd / qc / txt.c
1 #include "gc.h"
2
3 static  int     resvreg[nelem(reg)];
4
5 static  void    gopcode64(int, Node*, Node*, Node*);
6 static  void    gori64(int, Node*, Node*, Node*);
7 static  void    gandi64(int, Node*, Node*, Node*);
8
9 void
10 ginit(void)
11 {
12         Type *t;
13
14         thechar = 'q';
15         thestring = "power";
16         exregoffset = REGEXT;
17         exfregoffset = FREGEXT;
18         newvlongcode = 1;
19         listinit();
20         nstring = 0;
21         mnstring = 0;
22         nrathole = 0;
23         pc = 0;
24         breakpc = -1;
25         continpc = -1;
26         cases = C;
27         firstp = P;
28         lastp = P;
29         tfield = types[TLONG];
30
31         typeswitch = typechlv;
32
33         zprog.link = P;
34         zprog.as = AGOK;
35         zprog.reg = NREG;
36         zprog.from.type = D_NONE;
37         zprog.from.name = D_NONE;
38         zprog.from.reg = NREG;
39         zprog.from3 = zprog.from;
40         zprog.to = zprog.from;
41
42         regnode.op = OREGISTER;
43         regnode.class = CEXREG;
44         regnode.reg = 0;
45         regnode.complex = 0;
46         regnode.addable = 11;
47         regnode.type = types[TLONG];
48
49         constnode.op = OCONST;
50         constnode.class = CXXX;
51         constnode.complex = 0;
52         constnode.addable = 20;
53         constnode.type = types[TLONG];
54
55         fconstnode.op = OCONST;
56         fconstnode.class = CXXX;
57         fconstnode.complex = 0;
58         fconstnode.addable = 20;
59         fconstnode.type = types[TDOUBLE];
60
61         nodsafe = new(ONAME, Z, Z);
62         nodsafe->sym = slookup(".safe");
63         nodsafe->type = types[TINT];
64         nodsafe->etype = types[TINT]->etype;
65         nodsafe->class = CAUTO;
66         complex(nodsafe);
67
68         t = typ(TARRAY, types[TCHAR]);
69         symrathole = slookup(".rathole");
70         symrathole->class = CGLOBL;
71         symrathole->type = t;
72
73         nodrat = new(ONAME, Z, Z);
74         nodrat->sym = symrathole;
75         nodrat->type = types[TIND];
76         nodrat->etype = TVOID;
77         nodrat->class = CGLOBL;
78         complex(nodrat);
79         nodrat->type = t;
80
81         com64init();
82
83         memset(reg, 0, sizeof(reg));
84         reg[REGZERO] = 1;       /* don't use */
85         reg[REGTMP] = 1;
86         reg[FREGCVI+NREG] = 1;
87         reg[FREGZERO+NREG] = 1;
88         reg[FREGHALF+NREG] = 1;
89         reg[FREGONE+NREG] = 1;
90         reg[FREGTWO+NREG] = 1;
91         memmove(resvreg, reg, sizeof(reg));
92 }
93
94 void
95 gclean(void)
96 {
97         int i;
98         Sym *s;
99
100         for(i=0; i<NREG; i++)
101                 if(reg[i] && !resvreg[i])
102                         diag(Z, "reg %d left allocated", i);
103         for(i=NREG; i<NREG+NREG; i++)
104                 if(reg[i] && !resvreg[i])
105                         diag(Z, "freg %d left allocated", i-NREG);
106         while(mnstring)
107                 outstring("", 1L);
108         symstring->type->width = nstring;
109         symrathole->type->width = nrathole;
110         for(i=0; i<NHASH; i++)
111         for(s = hash[i]; s != S; s = s->link) {
112                 if(s->type == T)
113                         continue;
114                 if(s->type->width == 0)
115                         continue;
116                 if(s->class != CGLOBL && s->class != CSTATIC)
117                         continue;
118                 if(s->type == types[TENUM])
119                         continue;
120                 gpseudo(AGLOBL, s, nodconst(s->type->width));
121         }
122         nextpc();
123         p->as = AEND;
124         outcode();
125 }
126
127 void
128 nextpc(void)
129 {
130
131         p = alloc(sizeof(*p));
132         *p = zprog;
133         p->lineno = nearln;
134         pc++;
135         if(firstp == P) {
136                 firstp = p;
137                 lastp = p;
138                 return;
139         }
140         lastp->link = p;
141         lastp = p;
142 }
143
144 void
145 gargs(Node *n, Node *tn1, Node *tn2)
146 {
147         long regs;
148         Node fnxargs[20], *fnxp;
149
150         regs = cursafe;
151
152         fnxp = fnxargs;
153         garg1(n, tn1, tn2, 0, &fnxp);   /* compile fns to temps */
154
155         curarg = 0;
156         fnxp = fnxargs;
157         garg1(n, tn1, tn2, 1, &fnxp);   /* compile normal args and temps */
158
159         cursafe = regs;
160 }
161
162 void
163 garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
164 {
165         Node nod;
166
167         if(n == Z)
168                 return;
169         if(n->op == OLIST) {
170                 garg1(n->left, tn1, tn2, f, fnxp);
171                 garg1(n->right, tn1, tn2, f, fnxp);
172                 return;
173         }
174         if(f == 0) {
175                 if(n->complex >= FNX) {
176                         regsalloc(*fnxp, n);
177                         nod = znode;
178                         nod.op = OAS;
179                         nod.left = *fnxp;
180                         nod.right = n;
181                         nod.type = n->type;
182                         cgen(&nod, Z);
183                         (*fnxp)++;
184                 }
185                 return;
186         }
187         if(typesuv[n->type->etype]) {
188                 regaalloc(tn2, n);
189                 if(n->complex >= FNX) {
190                         cgen(*fnxp, tn2);
191                         (*fnxp)++;
192                 } else
193                         cgen(n, tn2);
194                 return;
195         }
196         if(REGARG && curarg == 0 && typechlp[n->type->etype]) {
197                 regaalloc1(tn1, n);
198                 if(n->complex >= FNX) {
199                         cgen(*fnxp, tn1);
200                         (*fnxp)++;
201                 } else
202                         cgen(n, tn1);
203                 return;
204         }
205         if(vconst(n) == 0) {
206                 regaalloc(tn2, n);
207                 gopcode(OAS, n, Z, tn2);
208                 return;
209         }
210         regalloc(tn1, n, Z);
211         if(n->complex >= FNX) {
212                 cgen(*fnxp, tn1);
213                 (*fnxp)++;
214         } else
215                 cgen(n, tn1);
216         regaalloc(tn2, n);
217         gopcode(OAS, tn1, Z, tn2);
218         regfree(tn1);
219 }
220
221 Node*
222 nod32const(vlong v)
223 {
224         constnode.vconst = v & MASK(32);
225         return &constnode;
226 }
227
228 Node*
229 nodconst(long v)
230 {
231         constnode.vconst = v;
232         return &constnode;
233 }
234
235 Node*
236 nodfconst(double d)
237 {
238         fconstnode.fconst = d;
239         return &fconstnode;
240 }
241
242 void
243 nodreg(Node *n, Node *nn, int reg)
244 {
245         *n = regnode;
246         n->reg = reg;
247         n->type = nn->type;
248         n->lineno = nn->lineno;
249 }
250
251 void
252 regret(Node *n, Node *nn)
253 {
254         int r;
255
256         r = REGRET;
257         if(typefd[nn->type->etype])
258                 r = FREGRET+NREG;
259         nodreg(n, nn, r);
260         reg[r]++;
261 }
262
263 void
264 regalloc(Node *n, Node *tn, Node *o)
265 {
266         int i, j;
267         static int lasti;
268
269         switch(tn->type->etype) {
270         case TCHAR:
271         case TUCHAR:
272         case TSHORT:
273         case TUSHORT:
274         case TINT:
275         case TUINT:
276         case TLONG:
277         case TULONG:
278         case TIND:
279                 if(o != Z && o->op == OREGISTER) {
280                         i = o->reg;
281                         if(i > 0 && i < NREG)
282                                 goto out;
283                 }
284                 j = lasti + REGRET+1;
285                 for(i=REGRET+1; i<NREG; i++) {
286                         if(j >= NREG)
287                                 j = REGRET+1;
288                         if(reg[j] == 0) {
289                                 i = j;
290                                 goto out;
291                         }
292                         j++;
293                 }
294                 diag(tn, "out of fixed registers");
295                 goto err;
296
297         case TFLOAT:
298         case TDOUBLE:
299                 if(o != Z && o->op == OREGISTER) {
300                         i = o->reg;
301                         if(i >= NREG && i < NREG+NREG)
302                                 goto out;
303                 }
304                 j = lasti + NREG;
305                 for(i=NREG; i<NREG+NREG; i++) {
306                         if(j >= NREG+NREG)
307                                 j = NREG;
308                         if(reg[j] == 0) {
309                                 i = j;
310                                 goto out;
311                         }
312                         j++;
313                 }
314                 diag(tn, "out of float registers");
315                 goto err;
316
317         case TVLONG:
318         case TUVLONG:
319                 n->op = OREGPAIR;
320                 n->complex = 0; /* already in registers */
321                 n->addable = 11;
322                 n->type = tn->type;
323                 n->lineno = nearln;
324                 n->left = alloc(sizeof(Node));
325                 n->right = alloc(sizeof(Node));
326                 if(o != Z && o->op == OREGPAIR) {
327                         regalloc(n->left, &regnode, o->left);
328                         regalloc(n->right, &regnode, o->right);
329                 } else {
330                         regalloc(n->left, &regnode, Z);
331                         regalloc(n->right, &regnode, Z);
332                 }
333                 n->right->type = types[TULONG];
334                 if(tn->type->etype == TUVLONG)
335                         n->left->type = types[TULONG];  /* TO DO: is this a bad idea? */
336                 return;
337         }
338         diag(tn, "unknown type in regalloc: %T", tn->type);
339 err:
340         i = 0;
341 out:
342         if(i)
343                 reg[i]++;
344         lasti++;
345         if(lasti >= 5)
346                 lasti = 0;
347         nodreg(n, tn, i);
348 }
349
350 void
351 regialloc(Node *n, Node *tn, Node *o)
352 {
353         Node nod;
354
355         nod = *tn;
356         nod.type = types[TIND];
357         regalloc(n, &nod, o);
358 }
359
360 void
361 regfree(Node *n)
362 {
363         int i;
364
365         if(n->op == OREGPAIR) {
366                 regfree(n->left);
367                 regfree(n->right);
368                 return;
369         }
370         i = 0;
371         if(n->op != OREGISTER && n->op != OINDREG)
372                 goto err;
373         i = n->reg;
374         if(i < 0 || i >= sizeof(reg))
375                 goto err;
376         if(reg[i] <= 0)
377                 goto err;
378         reg[i]--;
379         return;
380 err:
381         diag(n, "error in regfree: %d [%d]", i, reg[i]);
382         prtree(n, "regfree");
383 }
384
385 void
386 regsalloc(Node *n, Node *nn)
387 {
388         cursafe = align(cursafe+stkoff, nn->type, Aaut3)-stkoff;
389         maxargsafe = maxround(maxargsafe, cursafe+curarg);
390 //      if(nn->type->etype == TDOUBLE || nn->type->etype == TVLONG){
391 //              extern int hasdoubled;
392 //              fprint(2, "stkoff=%ld cursafe=%ld curarg=%ld %d\n", stkoff, cursafe, curarg, hasdoubled);
393 //      }
394         *n = *nodsafe;
395         n->xoffset = -(stkoff + cursafe);
396         n->type = nn->type;
397         n->etype = nn->type->etype;
398         n->lineno = nn->lineno;
399 }
400
401 void
402 regaalloc1(Node *n, Node *nn)
403 {
404         nodreg(n, nn, REGARG);
405         reg[REGARG]++;
406         curarg = align(curarg, nn->type, Aarg1);
407         curarg = align(curarg, nn->type, Aarg2);
408         maxargsafe = maxround(maxargsafe, cursafe+curarg);
409 }
410
411 void
412 regaalloc(Node *n, Node *nn)
413 {
414         curarg = align(curarg, nn->type, Aarg1);
415         *n = *nn;
416         n->op = OINDREG;
417         n->reg = REGSP;
418         n->xoffset = curarg + SZ_LONG;
419         n->complex = 0;
420         n->addable = 20;
421         curarg = align(curarg, nn->type, Aarg2);
422         maxargsafe = maxround(maxargsafe, cursafe+curarg);
423 }
424
425 void
426 regind(Node *n, Node *nn)
427 {
428
429         if(n->op != OREGISTER) {
430                 diag(n, "regind not OREGISTER");
431                 return;
432         }
433         n->op = OINDREG;
434         n->type = nn->type;
435 }
436
437 void
438 raddr(Node *n, Prog *p)
439 {
440         Adr a;
441
442         naddr(n, &a);
443         if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
444                 a.type = D_REG;
445                 a.reg = REGZERO;
446         }
447         if(a.type != D_REG && a.type != D_FREG) {
448                 if(n)
449                         diag(n, "bad in raddr: %O", n->op);
450                 else
451                         diag(n, "bad in raddr: <null>");
452                 p->reg = NREG;
453         } else
454                 p->reg = a.reg;
455 }
456
457 void
458 naddr(Node *n, Adr *a)
459 {
460         long v;
461
462         a->type = D_NONE;
463         if(n == Z)
464                 return;
465         switch(n->op) {
466         default:
467         bad:
468                 diag(n, "bad in naddr: %O", n->op);
469                 break;
470
471         case OREGISTER:
472                 a->type = D_REG;
473                 a->sym = S;
474                 a->reg = n->reg;
475                 if(a->reg >= NREG) {
476                         a->type = D_FREG;
477                         a->reg -= NREG;
478                 }
479                 break;
480
481         case OIND:
482                 naddr(n->left, a);
483                 a->offset += n->xoffset;        /* little hack for reglcgenv */
484                 if(a->type == D_REG) {
485                         a->type = D_OREG;
486                         break;
487                 }
488                 if(a->type == D_CONST) {
489                         a->type = D_OREG;
490                         break;
491                 }
492                 goto bad;
493
494         case OINDREG:
495                 a->type = D_OREG;
496                 a->sym = S;
497                 a->offset = n->xoffset;
498                 a->reg = n->reg;
499                 break;
500
501         case ONAME:
502                 a->etype = n->etype;
503                 a->type = D_OREG;
504                 a->name = D_STATIC;
505                 a->sym = n->sym;
506                 a->offset = n->xoffset;
507                 if(n->class == CSTATIC)
508                         break;
509                 if(n->class == CEXTERN || n->class == CGLOBL) {
510                         a->name = D_EXTERN;
511                         break;
512                 }
513                 if(n->class == CAUTO) {
514                         a->name = D_AUTO;
515                         break;
516                 }
517                 if(n->class == CPARAM) {
518                         a->name = D_PARAM;
519                         break;
520                 }
521                 goto bad;
522
523         case OCONST:
524                 a->sym = S;
525                 a->reg = NREG;
526                 if(typefd[n->type->etype]) {
527                         a->type = D_FCONST;
528                         a->dval = n->fconst;
529                 } else {
530                         a->type = D_CONST;
531                         a->offset = n->vconst;
532                 }
533                 break;
534
535         case OADDR:
536                 naddr(n->left, a);
537                 if(a->type == D_OREG) {
538                         a->type = D_CONST;
539                         break;
540                 }
541                 goto bad;
542
543         case OADD:
544                 if(n->left->op == OCONST) {
545                         naddr(n->left, a);
546                         v = a->offset;
547                         naddr(n->right, a);
548                 } else {
549                         naddr(n->right, a);
550                         v = a->offset;
551                         naddr(n->left, a);
552                 }
553                 a->offset += v;
554                 break;
555
556         }
557 }
558
559 void
560 gloadhi(Node *f, Node *t, int c)
561 {
562         Type *ot;
563
564         if(f->op == OCONST){
565                 f = nodconst((long)(f->vconst>>32));
566                 if(c==1 && sconst(f) || c==2 && uconst(f)){
567                         if(t->op == OREGISTER)
568                                 regfree(t);
569                         *t = *f;
570                         return;
571                 }
572         }
573         if(f->op == OREGPAIR) {
574                 gmove(f->left, t);
575                 return;
576         }
577         ot = f->type;
578         f->type = types[TLONG];
579         gmove(f, t);
580         f->type = ot;
581 }
582
583 void
584 gloadlo(Node *f, Node *t, int c)
585 {
586         Type *ot;
587
588         if(f->op == OCONST){
589                 f = nodconst((long)f->vconst);
590                 if(c && uconst(f)){
591                         if(t->op == OREGISTER)
592                                 regfree(t);
593                         *t = *f;
594                         return;
595                 }
596         }
597         if(f->op == OREGPAIR) {
598                 gmove(f->right, t);
599                 return;
600         }
601         ot = f->type;
602         f->type = types[TLONG];
603         f->xoffset += SZ_LONG;
604         if(0){
605                 prtree(f, "gloadlo f"); prtree(t, "gloadlo t");
606         }
607         gmove(f, t);
608         f->xoffset -= SZ_LONG;
609         f->type = ot;
610 }
611
612 void
613 fop(int as, int f1, int f2, Node *t)
614 {
615         Node nod1, nod2, nod3;
616
617         nodreg(&nod1, t, NREG+f1);
618         nodreg(&nod2, t, NREG+f2);
619         regalloc(&nod3, t, t);
620         gopcode(as, &nod1, &nod2, &nod3);
621         gmove(&nod3, t);
622         regfree(&nod3);
623 }
624
625 static void
626 floattofix(Node *f, Node *t)
627 {
628         Node nod, fxrat;
629
630         regalloc(&nod, f, Z);
631         regsalloc(&fxrat, &fconstnode);
632         gins(AFCTIWZ, f, &nod);
633         gins(AFMOVD, &nod, &fxrat);
634         regfree(&nod);
635         fxrat.type = nodrat->type;
636         fxrat.etype = nodrat->etype;
637         fxrat.xoffset += 4;
638         gins(AMOVW, &fxrat, t);
639         gmove(t, t);
640 }
641
642 static void
643 fixtofloat(Node *f, Node *t)
644 {
645         int a, ft, tt;
646         Prog *p1;
647         Node nod, fxc0, fxc1, fxc2, fxrat;
648
649         ft = f->type->etype;
650         tt = t->type->etype;
651
652         /*
653          * rat[0] = 0x43300000; rat[1] = f^0x80000000;
654          * t = *(double*)rat - FREGCVI;
655          * is-unsigned(t) => if(t<0) t += 2^32;
656          * could be streamlined for int-to-float
657          */
658         regalloc(&fxc0, f, Z);
659         regalloc(&fxc2, f, Z);
660         regsalloc(&fxrat, &fconstnode); /* should be type float */
661         gins(AMOVW, nodconst(0x43300000L), &fxc0);
662         gins(AMOVW, f, &fxc2);
663         gins(AMOVW, &fxc0, &fxrat);
664         gins(AXOR, nodconst(0x80000000L), &fxc2);
665         fxc1 = fxrat;
666         fxc1.type = nodrat->type;
667         fxc1.etype = nodrat->etype;
668         fxc1.xoffset += SZ_LONG;
669         gins(AMOVW, &fxc2, &fxc1);
670         regfree(&fxc2);
671         regfree(&fxc0);
672         regalloc(&nod, t, t);   /* should be type float */
673         gins(AFMOVD, &fxrat, &nod);
674         nodreg(&fxc1, t, NREG+FREGCVI);
675         gins(AFSUB, &fxc1, &nod);
676         a = AFMOVD;
677         if(tt == TFLOAT)
678                 a = AFRSP;
679         gins(a, &nod, t);
680         regfree(&nod);
681         if(ft == TULONG) {
682                 regalloc(&nod, t, Z);
683                 gins(AFCMPU, t, Z);
684                 p->to.type = D_FREG;
685                 p->to.reg = FREGZERO;
686                 gins(ABGE, Z, Z);
687                 p1 = p;
688                 if(tt == TFLOAT) {
689                         gins(AFMOVS, nodfconst(4294967296.), &nod);
690                         gins(AFADDS, &nod, t);
691                 } else {
692                         gins(AFMOVD, nodfconst(4294967296.), &nod);
693                         gins(AFADD, &nod, t);
694                 }
695                 patch(p1, pc);
696                 regfree(&nod);
697         }
698 }
699
700 void
701 gmove(Node *f, Node *t)
702 {
703         int ft, tt, a;
704         Node nod;
705         double d;
706
707         ft = f->type->etype;
708         tt = t->type->etype;
709
710         if(ft == TDOUBLE && f->op == OCONST) {
711                 d = f->fconst;
712                 if(d == 0.0) {
713                         a = FREGZERO;
714                         goto ffreg;
715                 }
716                 if(d == 0.5) {
717                         a = FREGHALF;
718                         goto ffreg;
719                 }
720                 if(d == 1.0) {
721                         a = FREGONE;
722                         goto ffreg;
723                 }
724                 if(d == 2.0) {
725                         a = FREGTWO;
726                         goto ffreg;
727                 }
728                 if(d == -.5) {
729                         fop(OSUB, FREGHALF, FREGZERO, t);
730                         return;
731                 }
732                 if(d == -1.0) {
733                         fop(OSUB, FREGONE, FREGZERO, t);
734                         return;
735                 }
736                 if(d == -2.0) {
737                         fop(OSUB, FREGTWO, FREGZERO, t);
738                         return;
739                 }
740                 if(d == 1.5) {
741                         fop(OADD, FREGONE, FREGHALF, t);
742                         return;
743                 }
744                 if(d == 2.5) {
745                         fop(OADD, FREGTWO, FREGHALF, t);
746                         return;
747                 }
748                 if(d == 3.0) {
749                         fop(OADD, FREGTWO, FREGONE, t);
750                         return;
751                 }
752         }
753         if(ft == TFLOAT && f->op == OCONST) {
754                 d = f->fconst;
755                 if(d == 0) {
756                         a = FREGZERO;
757                 ffreg:
758                         nodreg(&nod, f, NREG+a);
759                         gmove(&nod, t);
760                         return;
761                 }
762         }
763         if((ft == TVLONG || ft == TUVLONG) && f->op == OCONST && t->op == OREGPAIR) {
764                 if(align(0, types[TCHAR], Aarg1))       /* isbigendian */
765                         gmove(nod32const(f->vconst>>32), t->left);
766                 else
767                         gmove(nod32const(f->vconst), t->left);
768                 if(align(0, types[TCHAR], Aarg1))       /* isbigendian */
769                         gmove(nod32const(f->vconst), t->right);
770                 else
771                         gmove(nod32const(f->vconst>>32), t->right);
772                 return;
773         }
774         /*
775          * a load --
776          * put it into a register then
777          * worry what to do with it.
778          */
779         if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
780                 switch(ft) {
781                 default:
782                         a = AMOVW;
783                         break;
784                 case TFLOAT:
785                         a = AFMOVS;
786                         break;
787                 case TDOUBLE:
788                         a = AFMOVD;
789                         break;
790                 case TCHAR:
791                         a = AMOVB;
792                         break;
793                 case TUCHAR:
794                         a = AMOVBZ;
795                         break;
796                 case TSHORT:
797                         a = AMOVH;
798                         break;
799                 case TUSHORT:
800                         a = AMOVHZ;
801                         break;
802                 }
803                 if(typev[ft]) {
804                         if(typev[tt] || typefd[tt]) {
805                                 regalloc(&nod, f, t);
806                                 /* low order first, because its value will be used first */
807                                 f->xoffset += SZ_LONG;
808                                 gins(AMOVW, f, nod.right);
809                                 f->xoffset -= SZ_LONG;
810                                 gins(AMOVW, f, nod.left);
811                         } else {
812                                 /* assumed not float or double */
813                                 regalloc(&nod, &regnode, t);
814                                 f->xoffset += SZ_LONG;
815                                 gins(AMOVW, f, &nod);
816                                 f->xoffset -= SZ_LONG;
817                         }
818                 } else {
819                         regalloc(&nod, f, t);
820                         gins(a, f, &nod);
821                 }
822                 gmove(&nod, t);
823                 regfree(&nod);
824                 return;
825         }
826
827         /*
828          * a store --
829          * put it into a register then
830          * store it.
831          */
832         if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
833                 switch(tt) {
834                 default:
835                         a = AMOVW;
836                         break;
837                 case TUCHAR:
838                         a = AMOVBZ;
839                         break;
840                 case TCHAR:
841                         a = AMOVB;
842                         break;
843                 case TUSHORT:
844                         a = AMOVHZ;
845                         break;
846                 case TSHORT:
847                         a = AMOVH;
848                         break;
849                 case TFLOAT:
850                         a = AFMOVS;
851                         break;
852                 case TDOUBLE:
853                         a = AFMOVD;
854                         break;
855                 }
856                 if(R0ISZERO && !typefd[ft] && vconst(f) == 0) {
857                         gins(a, f, t);
858                         if(typev[tt]) {
859                                 t->xoffset += SZ_LONG;
860                                 gins(a, f, t);
861                                 t->xoffset -= SZ_LONG;
862                         }
863                         return;
864                 }
865                 if(ft == tt)
866                         regalloc(&nod, t, f);
867                 else
868                         regalloc(&nod, t, Z);
869                 gmove(f, &nod);
870                 if(typev[tt]) {
871                         t->xoffset += SZ_LONG;
872                         gins(a, nod.right, t);
873                         t->xoffset -= SZ_LONG;
874                         gins(a, nod.left, t);
875                 } else
876                         gins(a, &nod, t);
877                 regfree(&nod);
878                 return;
879         }
880
881         /*
882          * type x type cross table
883          */
884         a = AGOK;
885         switch(ft) {
886         case TDOUBLE:
887         case TFLOAT:
888                 switch(tt) {
889                 case TDOUBLE:
890                         a = AFMOVD;
891                         if(ft == TFLOAT)
892                                 a = AFMOVS;     /* AFMOVSD */
893                         break;
894                 case TFLOAT:
895                         a = AFRSP;
896                         if(ft == TFLOAT)
897                                 a = AFMOVS;
898                         break;
899                 case TINT:
900                 case TUINT:
901                 case TLONG:
902                 case TULONG:
903                 case TIND:
904                 case TSHORT:
905                 case TUSHORT:
906                 case TCHAR:
907                 case TUCHAR:
908                         /* BUG: not right for unsigned long */
909                         floattofix(f, t);
910                         return;
911                 case TVLONG:
912                 case TUVLONG:
913                         diag(f, "unimplemented double->vlong");
914                         return;
915                 }
916                 break;
917         case TINT:
918         case TUINT:
919         case TLONG:
920         case TULONG:
921         case TIND:
922                 switch(tt) {
923                 case TDOUBLE:
924                 case TFLOAT:
925                         fixtofloat(f, t);
926                         return;
927                 case TINT:
928                 case TUINT:
929                 case TLONG:
930                 case TULONG:
931                 case TIND:
932                 case TSHORT:
933                 case TUSHORT:
934                 case TCHAR:
935                 case TUCHAR:
936                         a = AMOVW;
937                         break;
938                 }
939                 break;
940         case TSHORT:
941                 switch(tt) {
942                 case TDOUBLE:
943                 case TFLOAT:
944                         fixtofloat(f, t);
945                         return;
946                 case TINT:
947                 case TUINT:
948                 case TLONG:
949                 case TULONG:
950                 case TIND:
951                         a = AMOVH;
952                         break;
953                 case TSHORT:
954                 case TUSHORT:
955                 case TCHAR:
956                 case TUCHAR:
957                         a = AMOVW;
958                         break;
959                 }
960                 break;
961         case TUSHORT:
962                 switch(tt) {
963                 case TDOUBLE:
964                 case TFLOAT:
965                         fixtofloat(f, t);
966                         return;
967                 case TINT:
968                 case TUINT:
969                 case TLONG:
970                 case TULONG:
971                 case TIND:
972                         a = AMOVHZ;
973                         break;
974                 case TSHORT:
975                 case TUSHORT:
976                 case TCHAR:
977                 case TUCHAR:
978                         a = AMOVW;
979                         break;
980                 }
981                 break;
982         case TCHAR:
983                 switch(tt) {
984                 case TDOUBLE:
985                 case TFLOAT:
986                         fixtofloat(f, t);
987                         return;
988                 case TINT:
989                 case TUINT:
990                 case TLONG:
991                 case TULONG:
992                 case TIND:
993                 case TSHORT:
994                 case TUSHORT:
995                         a = AMOVB;
996                         break;
997                 case TCHAR:
998                 case TUCHAR:
999                         a = AMOVW;
1000                         break;
1001                 }
1002                 break;
1003         case TUCHAR:
1004                 switch(tt) {
1005                 case TDOUBLE:
1006                 case TFLOAT:
1007                         fixtofloat(f, t);
1008                         return;
1009                 case TINT:
1010                 case TUINT:
1011                 case TLONG:
1012                 case TULONG:
1013                 case TIND:
1014                 case TSHORT:
1015                 case TUSHORT:
1016                         a = AMOVBZ;
1017                         break;
1018                 case TCHAR:
1019                 case TUCHAR:
1020                         a = AMOVW;
1021                         break;
1022                 }
1023                 break;
1024         case TVLONG:
1025         case TUVLONG:
1026                 switch(tt) {
1027                 case TVLONG:
1028                 case TUVLONG:
1029                         a = AMOVW;
1030                         break;
1031                 }
1032                 break;
1033         }
1034         if(a == AGOK)
1035                 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
1036         if(a == AMOVW || a == AFMOVS || a == AFMOVD)
1037         if(samaddr(f, t))
1038                 return;
1039         if(typev[ft]) {
1040                 if(f->op != OREGPAIR || t->op != OREGPAIR)
1041                         diag(Z, "bad vlong in gmove (%O->%O)", f->op, t->op);
1042                 gins(a, f->left, t->left);
1043                 gins(a, f->right, t->right);
1044         } else
1045                 gins(a, f, t);
1046 }
1047
1048 void
1049 gins(int a, Node *f, Node *t)
1050 {
1051
1052         nextpc();
1053         p->as = a;
1054         if(f != Z)
1055                 naddr(f, &p->from);
1056         if(t != Z)
1057                 naddr(t, &p->to);
1058         if(debug['g'])
1059                 print("%P\n", p);
1060 }
1061
1062 void
1063 gins3(int a, Node *f1, Node *f2, Node *t)
1064 {
1065         Adr ta;
1066
1067         nextpc();
1068         p->as = a;
1069         if(f1 != Z)
1070                 naddr(f1, &p->from);
1071         if(f2 != Z && (f2->op != OREGISTER || !samaddr(f2, t))) {
1072                 ta = zprog.from;        /* TO DO */
1073                 naddr(f2, &ta);
1074                 p->reg = ta.reg;
1075                 if(ta.type == D_CONST && ta.offset == 0) {
1076                         if(R0ISZERO)
1077                                 p->reg = REGZERO;
1078                         else
1079                                 diag(Z, "REGZERO in gins3 %A", a);
1080                 }else if(ta.type == D_CONST)
1081                         p->from3 = ta;
1082         }
1083         if(t != Z)
1084                 naddr(t, &p->to);
1085         if(debug['g'])
1086                 print("%P\n", p);
1087 }
1088
1089 void
1090 gins4(int a, Node *f1, Node *f2, Node *f3, Node *t)
1091 {
1092         Adr ta;
1093
1094         nextpc();
1095         p->as = a;
1096         naddr(f1, &p->from);
1097         if(f2->op != OREGISTER && (f2->op != OCONST || vconst(f2) != 0))
1098                 diag(f2, "invalid gins4");
1099         naddr(f2, &ta);
1100         p->reg = ta.reg;
1101         if(ta.type == D_CONST && ta.offset == 0)
1102                 p->reg = REGZERO;
1103         naddr(f3, &p->from3);
1104         naddr(t, &p->to);
1105         if(debug['g'])
1106                 print("%P\n", p);
1107 }
1108
1109 void
1110 gopcode(int o, Node *f1, Node *f2, Node *t)
1111 {
1112         int a, et, uns;
1113
1114         if(o == OAS) {
1115                 gmove(f1, t);
1116                 return;
1117         }
1118         et = TLONG;
1119         if(f1 != Z && f1->type != T) {
1120                 if(f1->op == OCONST && t != Z && t->type != T)
1121                         et = t->type->etype;
1122                 else
1123                         et = f1->type->etype;
1124         }
1125         if((typev[et] || t->type != T && typev[t->type->etype]) && o != OFUNC) {
1126                 gopcode64(o, f1, f2, t);
1127                 return;
1128         }
1129         uns = 0;
1130         a = AGOK;
1131         switch(o) {
1132
1133         case OASADD:
1134         case OADD:
1135                 a = AADD;
1136                 if(et == TFLOAT)
1137                         a = AFADDS;
1138                 else
1139                 if(et == TDOUBLE)
1140                         a = AFADD;
1141                 break;
1142
1143         case OASSUB:
1144         case OSUB:
1145                 a = ASUB;
1146                 if(et == TFLOAT)
1147                         a = AFSUBS;
1148                 else
1149                 if(et == TDOUBLE)
1150                         a = AFSUB;
1151                 break;
1152
1153         case OASOR:
1154         case OOR:
1155                 a = AOR;
1156                 break;
1157
1158         case OASAND:
1159         case OAND:
1160                 a = AAND;
1161                 if(f1->op == OCONST)
1162                         a = AANDCC;
1163                 break;
1164
1165         case OASXOR:
1166         case OXOR:
1167                 a = AXOR;
1168                 break;
1169
1170         case OASLSHR:
1171         case OLSHR:
1172                 a = ASRW;
1173                 break;
1174
1175         case OASASHR:
1176         case OASHR:
1177                 a = ASRAW;
1178                 break;
1179
1180         case OASASHL:
1181         case OASHL:
1182                 a = ASLW;
1183                 break;
1184
1185         case OFUNC:
1186                 a = ABL;
1187                 break;
1188
1189         case OASLMUL:
1190         case OLMUL:
1191         case OASMUL:
1192         case OMUL:
1193                 if(et == TFLOAT) {
1194                         a = AFMULS;
1195                         break;
1196                 } else
1197                 if(et == TDOUBLE) {
1198                         a = AFMUL;
1199                         break;
1200                 }
1201                 a = AMULLW;
1202                 break;
1203
1204         case OASDIV:
1205         case ODIV:
1206                 if(et == TFLOAT) {
1207                         a = AFDIVS;
1208                         break;
1209                 } else
1210                 if(et == TDOUBLE) {
1211                         a = AFDIV;
1212                         break;
1213                 }
1214                 a = ADIVW;
1215                 break;
1216
1217         case OASMOD:
1218         case OMOD:
1219                 a = AREM;
1220                 break;
1221
1222         case OASLMOD:
1223         case OLMOD:
1224                 a = AREMU;
1225                 break;
1226
1227         case OASLDIV:
1228         case OLDIV:
1229                 a = ADIVWU;
1230                 break;
1231
1232         case OCOM:
1233                 a = ANOR;
1234                 break;
1235
1236         case ONEG:
1237                 a = ANEG;
1238                 if(et == TFLOAT || et == TDOUBLE)
1239                         a = AFNEG;
1240                 break;
1241
1242         case OEQ:
1243                 a = ABEQ;
1244                 if(t->op == OCONST && t->vconst >= (1<<15))
1245                         goto cmpu;
1246                 goto cmp;
1247
1248         case ONE:
1249                 a = ABNE;
1250                 if(t->op == OCONST && t->vconst >= (1<<15))
1251                         goto cmpu;
1252                 goto cmp;
1253
1254         case OLT:
1255                 a = ABLT;
1256                 goto cmp;
1257
1258         case OLE:
1259                 a = ABLE;
1260                 goto cmp;
1261
1262         case OGE:
1263                 a = ABGE;
1264                 goto cmp;
1265
1266         case OGT:
1267                 a = ABGT;
1268                 goto cmp;
1269
1270         case OLO:
1271                 a = ABLT;
1272                 goto cmpu;
1273
1274         case OLS:
1275                 a = ABLE;
1276                 goto cmpu;
1277
1278         case OHS:
1279                 a = ABGE;
1280                 goto cmpu;
1281
1282         case OHI:
1283                 a = ABGT;
1284                 goto cmpu;
1285
1286         cmpu:
1287                 uns = 1;
1288         cmp:
1289                 nextpc();
1290                 p->as = uns? ACMPU: ACMP;
1291                 if(et == TFLOAT)
1292                         p->as = AFCMPU;
1293                 else
1294                 if(et == TDOUBLE)
1295                         p->as = AFCMPU;
1296                 if(f1 != Z)
1297                         naddr(f1, &p->from);
1298                 if(t != Z)
1299                         naddr(t, &p->to);
1300                 if(f1 == Z || t == Z || f2 != Z)
1301                         diag(Z, "bad cmp in gopcode %O", o);
1302                 if(debug['g'])
1303                         print("%P\n", p);
1304                 f1 = Z;
1305                 f2 = Z;
1306                 t = Z;
1307                 break;
1308         }
1309         if(a == AGOK)
1310                 diag(Z, "bad in gopcode %O", o);
1311         gins3(a, f1, f2, t);
1312 }
1313
1314 static void
1315 gopcode64(int o, Node *f1, Node *f2, Node *t)
1316 {
1317         int a1, a2;
1318         Node nod, nod1, nod2, sh;
1319         ulong m;
1320         Prog *p1;
1321
1322         if(t->op != OREGPAIR || f2 != Z && f2->op != OREGPAIR) {
1323                 diag(Z, "bad f2/dest in gopcode64 %O", o);
1324                 return;
1325         }
1326         if(f1->op != OCONST &&
1327            (typev[f1->type->etype] && f1->op != OREGPAIR || !typev[f1->type->etype] && f1->op != OREGISTER)) {
1328                 diag(Z, "bad f1[%O] in gopcode64 %O", f1->op, o);
1329                 return;
1330         }
1331         /* a1 for low-order, a2 for high-order */
1332         a1 = AGOK;
1333         a2 = AGOK;
1334         switch(o) {
1335         case OASADD:
1336         case OADD:
1337                 if(f1->op == OCONST && sconst(f1)) {
1338                         if(f2 == Z)
1339                                 f2 = t;
1340                         gins3(AADDC, f1, f2->right, t->right);
1341                         if((f1->vconst>>32) == 0)
1342                                 gins(AADDZE, f2->left, t->left);
1343                         else if((f1->vconst>>32) == -1)
1344                                 gins(AADDME, f2->left, t->left);
1345                         else
1346                                 diag(t, "odd vlong ADD: %lld", f1->vconst);
1347                         return;
1348                 }
1349                 a1 = AADDC;
1350                 a2 = AADDE;
1351                 break;
1352
1353         case OASSUB:
1354         case OSUB:
1355                 a1 = ASUBC;
1356                 a2 = ASUBE;
1357                 break;
1358
1359         case OASOR:
1360         case OOR:
1361                 if(f1->op == OCONST) {
1362                         gori64(AOR, f1, f2, t);
1363                         return;
1364                 }
1365                 a1 = a2 = AOR;
1366                 break;
1367
1368         case OASAND:
1369         case OAND:
1370                 if(f1->op == OCONST) {
1371                         gandi64(AANDCC, f1, f2, t);
1372                         return;
1373                 }
1374                 a1 = a2 = AAND;
1375                 break;
1376
1377         case OASXOR:
1378         case OXOR:
1379                 if(f1->op == OCONST) {
1380                         gori64(AXOR, f1, f2, t);
1381                         return;
1382                 }
1383                 a1 = a2 = AXOR;
1384                 break;
1385
1386         case OASLSHR:
1387         case OLSHR:
1388                 if(f2 == Z)
1389                         f2 = t;
1390                 if(f1->op == OCONST) {
1391                         if(f1->vconst >= 32) {
1392                                 if(f1->vconst == 32)
1393                                         gmove(f2->left, t->right);
1394                                 else if(f1->vconst < 64)
1395                                         gins3(ASRW, nodconst(f1->vconst-32), f2->left, t->right);
1396                                 else
1397                                         gmove(nodconst(0), t->right);
1398                                 gmove(nodconst(0), t->left);
1399                                 return;
1400                         }
1401                         if(f1->vconst <= 0) {
1402                                 if(f2 != t)
1403                                         gmove(f2, t);
1404                                 return;
1405                         }
1406                         sh = *nodconst(32 - f1->vconst);
1407                         m = 0xFFFFFFFFUL >> f1->vconst;
1408                         gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
1409                         gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
1410                         gins4(ARLWNM, &sh, f2->left, nodconst(m), t->left);
1411                         return;
1412                 }
1413                 regalloc(&nod, &regnode, Z);
1414                 gins3(ASUBC, f1, nodconst(32), &nod);
1415                 gins3(ASRW, f1, f2->right, t->right);
1416                 regalloc(&nod1, &regnode, Z);
1417                 gins3(ASLW, &nod, f2->left, &nod1);
1418                 gins(AOR, &nod1, t->right);
1419                 gins3(AADD, nodconst(-32), f1, &nod);
1420                 gins3(ASRW, &nod, f2->left, &nod1);
1421                 gins(AOR, &nod1, t->right);
1422                 gins3(ASRW, f1, f2->left, t->left);
1423                 regfree(&nod);
1424                 regfree(&nod1);
1425                 return;
1426
1427         case OASASHR:
1428         case OASHR:
1429                 if(f2 == Z)
1430                         f2 = t;
1431                 if(f1->op == OCONST) {
1432                         if(f1->vconst >= 32) {
1433                                 if(f1->vconst == 32)
1434                                         gmove(f2->left, t->right);
1435                                 else if(f1->vconst < 64)
1436                                         gins3(ASRAW, nodconst(f1->vconst-32), f2->left, t->right);
1437                                 gins3(ASRAW, nodconst(31), f2->left, t->left);
1438                                 if(f1->vconst >= 64) {
1439                                         gmove(t->left, t->right);
1440                                         return;
1441                                 }
1442                                 return;
1443                         }
1444                         if(f1->vconst <= 0) {
1445                                 if(f2 != t)
1446                                         gmove(f2, t);
1447                                 return;
1448                         }
1449                         sh = *nodconst(32 - f1->vconst);
1450                         m = 0xFFFFFFFFUL >> f1->vconst;
1451                         gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
1452                         gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
1453                         gins3(ASRAW, &sh, f2->left, t->left);
1454                         return;
1455                 }
1456                 regalloc(&nod, &regnode, Z);
1457                 gins3(ASUBC, f1, nodconst(32), &nod);
1458                 gins3(ASRW, f1, f2->right, t->right);
1459                 regalloc(&nod1, &regnode, Z);
1460                 gins3(ASLW, &nod, f2->left, &nod1);
1461                 gins(AOR, &nod1, t->right);
1462                 gins3(AADDCCC, nodconst(-32), f1, &nod);
1463                 gins3(ASRAW, &nod, f2->left, &nod1);
1464                 gins(ABLE, Z, Z);
1465                 p1 = p;
1466                 gins(AMOVW, &nod1, t->right);
1467                 patch(p1, pc);
1468                 gins3(ASRAW, f1, f2->left, t->left);
1469                 regfree(&nod);
1470                 regfree(&nod1);
1471                 return;
1472
1473         case OASASHL:
1474         case OASHL:
1475                 if(f2 == Z)
1476                         f2 = t;
1477                 if(f1->op == OCONST) {
1478                         if(f1->vconst >= 32) {
1479                                 if(f1->vconst == 32)
1480                                         gmove(f2->right, t->left);
1481                                 else if(f1->vconst >= 64)
1482                                         gmove(nodconst(0), t->left);
1483                                 else
1484                                         gins3(ASLW, nodconst(f1->vconst-32), f2->right, t->left);
1485                                 gmove(nodconst(0), t->right);
1486                                 return;
1487                         }
1488                         if(f1->vconst <= 0) {
1489                                 if(f2 != t)
1490                                         gmove(f2, t);
1491                                 return;
1492                         }
1493                         m = 0xFFFFFFFFUL << f1->vconst;
1494                         gins4(ARLWNM, f1, f2->left, nodconst(m), t->left);
1495                         gins4(ARLWMI, f1, f2->right, nodconst(~m), t->left);
1496                         gins4(ARLWNM, f1, f2->right, nodconst(m), t->right);
1497                         return;
1498                 }
1499                 regalloc(&nod, &regnode, Z);
1500                 gins3(ASUBC, f1, nodconst(32), &nod);
1501                 gins3(ASLW, f1, f2->left, t->left);
1502                 regalloc(&nod1, &regnode, Z);
1503                 gins3(ASRW, &nod, f2->right, &nod1);
1504                 gins(AOR, &nod1, t->left);
1505                 gins3(AADD, nodconst(-32), f1, &nod);
1506                 gins3(ASLW, &nod, f2->right, &nod1);
1507                 gins(AOR, &nod1, t->left);
1508                 gins3(ASLW, f1, f2->right, t->right);
1509                 regfree(&nod);
1510                 regfree(&nod1);
1511                 return;
1512
1513         case OASLMUL:
1514         case OLMUL:
1515         case OASMUL:
1516         case OMUL:
1517                 if(f2 == Z)
1518                         f2 = t;
1519                 regalloc(&nod, &regnode, Z);
1520                 gins3(AMULLW, f1->right, f2->right, &nod);      /* lo(f2.low*f1.low) */
1521                 regalloc(&nod1, &regnode, Z);
1522                 gins3(AMULHWU, f1->right, f2->right, &nod1);            /* hi(f2.low*f1.low) */
1523                 regalloc(&nod2, &regnode, Z);
1524                 gins3(AMULLW, f2->right, f1->left, &nod2);      /* lo(f2.low*f1.high) */
1525                 gins(AADD, &nod2, &nod1);
1526                 gins3(AMULLW, f1->right, f2->left, &nod2);      /* lo(f2.high*f1.low) */
1527                 gins(AADD, &nod2, &nod1);
1528                 regfree(&nod2);
1529                 gmove(&nod, t->right);
1530                 gmove(&nod1, t->left);
1531                 regfree(&nod);
1532                 regfree(&nod1);
1533                 return;
1534
1535         case OCOM:
1536                 a1 = a2 = ANOR;
1537                 break;
1538
1539         case ONEG:
1540                 gins3(ASUBC, t->right, nodconst(0), t->right);
1541                 gins(ASUBZE, t->left, t->left);
1542                 return;
1543         }
1544         if(a1 == AGOK || a2 == AGOK)
1545                 diag(Z, "bad in gopcode64 %O", o);
1546         if(f1->op == OCONST) {
1547                 if(f2 != Z & f2 != t)
1548                         diag(Z, "bad const in gopcode64 %O", o);
1549                 gins(a1, nod32const(f1->vconst), t->right);
1550                 gins(a2, nod32const(f1->vconst>>32), t->left);
1551         } else {
1552                 if(f2 != Z && f2 != t) {
1553                         gins3(a1, f1->right, f2->right, t->right);
1554                         gins3(a2, f1->left, f2->left, t->left);
1555                 } else {
1556                         gins(a1, f1->right, t->right);
1557                         gins(a2, f1->left, t->left);
1558                 }
1559         }
1560 }
1561
1562 samaddr(Node *f, Node *t)
1563 {
1564
1565         if(f->op != t->op)
1566                 return 0;
1567         switch(f->op) {
1568
1569         case OREGISTER:
1570                 if(f->reg != t->reg)
1571                         break;
1572                 return 1;
1573
1574         case OREGPAIR:
1575                 return samaddr(f->left, t->left) && samaddr(f->right, t->right);
1576         }
1577         return 0;
1578 }
1579
1580 static void
1581 gori64(int a, Node *f1, Node *f2, Node *t)
1582 {
1583         ulong lo, hi;
1584
1585         if(f2 == Z)
1586                 f2 = t;
1587         lo = f1->vconst & MASK(32);
1588         hi = (f1->vconst >> 32) & MASK(32);
1589         if(lo & 0xFFFF)
1590                 gins3(a, nodconst(lo & 0xFFFF), f2->right, t->right);
1591         if((lo >> 16) != 0)
1592                 gins3(a, nodconst(lo & 0xFFFF0000UL), f2->right, t->right);
1593         if(hi & 0xFFFF)
1594                 gins3(a, nodconst(hi & 0xFFFF), f2->left, t->left);
1595         if((hi >> 16) != 0)
1596                 gins3(a, nodconst(hi & 0xFFFF0000UL), f2->left, t->left);
1597 }
1598
1599 static void
1600 gandi64(int a, Node *f1, Node *f2, Node *t)
1601 {
1602         ulong lo, hi;
1603
1604         if(f2 == Z)
1605                 f2 = t;
1606         lo = f1->vconst & MASK(32);
1607         hi = (f1->vconst >> 32) & MASK(32);
1608         if(lo == 0)
1609                 gins(AMOVW, nodconst(0), t->right);
1610         else
1611                 gins3(a, nodconst(lo), f2->right, t->right);
1612         if(hi == 0)
1613                 gins(AMOVW, nodconst(0), t->left);
1614         else
1615                 gins3(a, nodconst(hi), f2->left, t->left);
1616 }
1617
1618 void
1619 gbranch(int o)
1620 {
1621         int a;
1622
1623         a = AGOK;
1624         switch(o) {
1625         case ORETURN:
1626                 a = ARETURN;
1627                 break;
1628         case OGOTO:
1629                 a = ABR;
1630                 break;
1631         }
1632         nextpc();
1633         if(a == AGOK) {
1634                 diag(Z, "bad in gbranch %O",  o);
1635                 nextpc();
1636         }
1637         p->as = a;
1638 }
1639
1640 void
1641 patch(Prog *op, long pc)
1642 {
1643
1644         op->to.offset = pc;
1645         op->to.type = D_BRANCH;
1646 }
1647
1648 void
1649 gpseudo(int a, Sym *s, Node *n)
1650 {
1651
1652         nextpc();
1653         p->as = a;
1654         p->from.type = D_OREG;
1655         p->from.sym = s;
1656         if(a == ATEXT)
1657                 p->reg = (profileflg ? 0 : NOPROF);
1658         p->from.name = D_EXTERN;
1659         if(s->class == CSTATIC)
1660                 p->from.name = D_STATIC;
1661         naddr(n, &p->to);
1662         if(a == ADATA || a == AGLOBL)
1663                 pc--;
1664 }
1665
1666 int
1667 sval(long v)
1668 {
1669
1670         if(v >= -(1<<15) && v < (1<<15))
1671                 return 1;
1672         return 0;
1673 }
1674
1675 int
1676 sconst(Node *n)
1677 {
1678         vlong vv;
1679
1680         if(n->op == OCONST) {
1681                 if(!typefd[n->type->etype]) {
1682                         vv = n->vconst;
1683                         if(vv >= -(((vlong)1)<<15) && vv < (((vlong)1)<<15))
1684                                 return 1;
1685                 }
1686         }
1687         return 0;
1688 }
1689
1690 int
1691 uconst(Node *n)
1692 {
1693         vlong vv;
1694
1695         if(n->op == OCONST) {
1696                 if(!typefd[n->type->etype]) {
1697                         vv = n->vconst;
1698                         if(vv >= 0 && vv < (((vlong)1)<<16))
1699                                 return 1;
1700                 }
1701         }
1702         return 0;
1703 }
1704
1705 long
1706 exreg(Type *t)
1707 {
1708         long o;
1709
1710         if(typechlp[t->etype]) {
1711                 if(exregoffset <= 3)
1712                         return 0;
1713                 o = exregoffset;
1714                 exregoffset--;
1715                 return o;
1716         }
1717         if(typefd[t->etype]) {
1718                 if(exfregoffset <= 16)
1719                         return 0;
1720                 o = exfregoffset + NREG;
1721                 exfregoffset--;
1722                 return o;
1723         }
1724         return 0;
1725 }
1726
1727 schar   ewidth[NTYPE] =
1728 {
1729         -1,             /* [TXXX] */
1730         SZ_CHAR,        /* [TCHAR] */
1731         SZ_CHAR,        /* [TUCHAR] */
1732         SZ_SHORT,       /* [TSHORT] */
1733         SZ_SHORT,       /* [TUSHORT] */
1734         SZ_INT,         /* [TINT] */
1735         SZ_INT,         /* [TUINT] */
1736         SZ_LONG,        /* [TLONG] */
1737         SZ_LONG,        /* [TULONG] */
1738         SZ_VLONG,       /* [TVLONG] */
1739         SZ_VLONG,       /* [TUVLONG] */
1740         SZ_FLOAT,       /* [TFLOAT] */
1741         SZ_DOUBLE,      /* [TDOUBLE] */
1742         SZ_IND,         /* [TIND] */
1743         0,              /* [TFUNC] */
1744         -1,             /* [TARRAY] */
1745         0,              /* [TVOID] */
1746         -1,             /* [TSTRUCT] */
1747         -1,             /* [TUNION] */
1748         SZ_INT,         /* [TENUM] */
1749 };
1750 long    ncast[NTYPE] =
1751 {
1752         0,                              /* [TXXX] */
1753         BCHAR|BUCHAR,                   /* [TCHAR] */
1754         BCHAR|BUCHAR,                   /* [TUCHAR] */
1755         BSHORT|BUSHORT,                 /* [TSHORT] */
1756         BSHORT|BUSHORT,                 /* [TUSHORT] */
1757         BINT|BUINT|BLONG|BULONG|BIND,   /* [TINT] */
1758         BINT|BUINT|BLONG|BULONG|BIND,   /* [TUINT] */
1759         BINT|BUINT|BLONG|BULONG|BIND,   /* [TLONG] */
1760         BINT|BUINT|BLONG|BULONG|BIND,   /* [TULONG] */
1761         BVLONG|BUVLONG,                 /* [TVLONG] */
1762         BVLONG|BUVLONG,                 /* [TUVLONG] */
1763         BFLOAT,                         /* [TFLOAT] */
1764         BDOUBLE,                        /* [TDOUBLE] */
1765         BLONG|BULONG|BIND,              /* [TIND] */
1766         0,                              /* [TFUNC] */
1767         0,                              /* [TARRAY] */
1768         0,                              /* [TVOID] */
1769         BSTRUCT,                        /* [TSTRUCT] */
1770         BUNION,                         /* [TUNION] */
1771         0,                              /* [TENUM] */
1772 };