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