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