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