]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/5c/swt.c
abaco: cleanup, handle image/x-icon, don't use backspace as a hotkey, and remove...
[plan9front.git] / sys / src / cmd / 5c / swt.c
1 #include "gc.h"
2
3 void
4 swit1(C1 *q, int nc, long def, Node *n)
5 {
6         Node tn;
7         
8         regalloc(&tn, &regnode, Z);
9         swit2(q, nc, def, n, &tn);
10         regfree(&tn);
11 }
12
13 void
14 swit2(C1 *q, int nc, long def, Node *n, Node *tn)
15 {
16         C1 *r;
17         int i;
18         long v;
19         Prog *sp;
20
21         if(nc >= 3) {
22                 i = (q+nc-1)->val - (q+0)->val;
23                 if(i > 0 && i < nc*2)
24                         goto direct;
25         }
26         if(nc < 5) {
27                 for(i=0; i<nc; i++) {
28                         if(debug['W'])
29                                 print("case = %.8llux\n", q->val);
30                         gopcode(OEQ, nodconst(q->val), n, Z);
31                         patch(p, q->label);
32                         q++;
33                 }
34                 gbranch(OGOTO);
35                 patch(p, def);
36                 return;
37         }
38
39         i = nc / 2;
40         r = q+i;
41         if(debug['W'])
42                 print("case > %.8llux\n", r->val);
43         gopcode(OGT, nodconst(r->val), n, Z);
44         sp = p;
45         gopcode(OEQ, nodconst(r->val), n, Z);   /* just gen the B.EQ */
46         patch(p, r->label);
47         swit2(q, i, def, n, tn);
48
49         if(debug['W'])
50                 print("case < %.8llux\n", r->val);
51         patch(sp, pc);
52         swit2(r+1, nc-i-1, def, n, tn);
53         return;
54
55 direct:
56         v = q->val;
57         if(v != 0)
58                 gopcode(OSUB, nodconst(v), Z, n);
59         gopcode(OCASE, nodconst((q+nc-1)->val - v), n, Z);
60         patch(p, def);
61         for(i=0; i<nc; i++) {
62                 if(debug['W'])
63                         print("case = %.8llux\n", q->val);
64                 while(q->val != v) {
65                         nextpc();
66                         p->as = ABCASE;
67                         patch(p, def);
68                         v++;
69                 }
70                 nextpc();
71                 p->as = ABCASE;
72                 patch(p, q->label);
73                 q++;
74                 v++;
75         }
76         gbranch(OGOTO);         /* so that regopt() won't be confused */
77         patch(p, def);
78 }
79
80 void
81 bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
82 {
83         int sh;
84         long v;
85         Node *l;
86
87         /*
88          * n1 gets adjusted/masked value
89          * n2 gets address of cell
90          * n3 gets contents of cell
91          */
92         l = b->left;
93         if(n2 != Z) {
94                 regalloc(n1, l, nn);
95                 reglcgen(n2, l, Z);
96                 regalloc(n3, l, Z);
97                 gopcode(OAS, n2, Z, n3);
98                 gopcode(OAS, n3, Z, n1);
99         } else {
100                 regalloc(n1, l, nn);
101                 cgen(l, n1);
102         }
103         if(b->type->shift == 0 && typeu[b->type->etype]) {
104                 v = ~0 + (1L << b->type->nbits);
105                 gopcode(OAND, nodconst(v), Z, n1);
106         } else {
107                 sh = 32 - b->type->shift - b->type->nbits;
108                 if(sh > 0)
109                         gopcode(OASHL, nodconst(sh), Z, n1);
110                 sh += b->type->shift;
111                 if(sh > 0)
112                         if(typeu[b->type->etype])
113                                 gopcode(OLSHR, nodconst(sh), Z, n1);
114                         else
115                                 gopcode(OASHR, nodconst(sh), Z, n1);
116         }
117 }
118
119 void
120 bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
121 {
122         long v;
123         Node nod, *l;
124         int sh;
125
126         /*
127          * n1 has adjusted/masked value
128          * n2 has address of cell
129          * n3 has contents of cell
130          */
131         l = b->left;
132         regalloc(&nod, l, Z);
133         v = ~0 + (1L << b->type->nbits);
134         gopcode(OAND, nodconst(v), Z, n1);
135         gopcode(OAS, n1, Z, &nod);
136         if(nn != Z)
137                 gopcode(OAS, n1, Z, nn);
138         sh = b->type->shift;
139         if(sh > 0)
140                 gopcode(OASHL, nodconst(sh), Z, &nod);
141         v <<= sh;
142         gopcode(OAND, nodconst(~v), Z, n3);
143         gopcode(OOR, n3, Z, &nod);
144         gopcode(OAS, &nod, Z, n2);
145
146         regfree(&nod);
147         regfree(n1);
148         regfree(n2);
149         regfree(n3);
150 }
151
152 long
153 outstring(char *s, long n)
154 {
155         long r;
156
157         if(suppress)
158                 return nstring;
159         r = nstring;
160         while(n) {
161                 string[mnstring] = *s++;
162                 mnstring++;
163                 nstring++;
164                 if(mnstring >= NSNAME) {
165                         gpseudo(ADATA, symstring, nodconst(0L));
166                         p->from.offset += nstring - NSNAME;
167                         p->reg = NSNAME;
168                         p->to.type = D_SCONST;
169                         memmove(p->to.sval, string, NSNAME);
170                         mnstring = 0;
171                 }
172                 n--;
173         }
174         return r;
175 }
176
177 int
178 mulcon(Node *n, Node *nn)
179 {
180         Node *l, *r, nod1, nod2;
181         Multab *m;
182         long v, vs;
183         int o;
184         char code[sizeof(m->code)+2], *p;
185
186         if(typefd[n->type->etype])
187                 return 0;
188         l = n->left;
189         r = n->right;
190         if(l->op == OCONST) {
191                 l = r;
192                 r = n->left;
193         }
194         if(r->op != OCONST)
195                 return 0;
196         v = convvtox(r->vconst, n->type->etype);
197         if(v != r->vconst) {
198                 if(debug['M'])
199                         print("%L multiply conv: %lld\n", n->lineno, r->vconst);
200                 return 0;
201         }
202         m = mulcon0(v);
203         if(!m) {
204                 if(debug['M'])
205                         print("%L multiply table: %lld\n", n->lineno, r->vconst);
206                 return 0;
207         }
208         if(debug['M'] && debug['v'])
209                 print("%L multiply: %ld\n", n->lineno, v);
210
211         memmove(code, m->code, sizeof(m->code));
212         code[sizeof(m->code)] = 0;
213
214         p = code;
215         if(p[1] == 'i')
216                 p += 2;
217         regalloc(&nod1, n, nn);
218         cgen(l, &nod1);
219         vs = v;
220         regalloc(&nod2, n, Z);
221
222 loop:
223         switch(*p) {
224         case 0:
225                 regfree(&nod2);
226                 if(vs < 0) {
227                         gopcode(OAS, &nod1, Z, &nod1);
228                         gopcode(OSUB, &nod1, nodconst(0), nn);
229                 } else 
230                         gopcode(OAS, &nod1, Z, nn);
231                 regfree(&nod1);
232                 return 1;
233         case '+':
234                 o = OADD;
235                 goto addsub;
236         case '-':
237                 o = OSUB;
238         addsub: /* number is r,n,l */
239                 v = p[1] - '0';
240                 r = &nod1;
241                 if(v&4)
242                         r = &nod2;
243                 n = &nod1;
244                 if(v&2)
245                         n = &nod2;
246                 l = &nod1;
247                 if(v&1)
248                         l = &nod2;
249                 gopcode(o, l, n, r);
250                 break;
251         default: /* op is shiftcount, number is r,l */
252                 v = p[1] - '0';
253                 r = &nod1;
254                 if(v&2)
255                         r = &nod2;
256                 l = &nod1;
257                 if(v&1)
258                         l = &nod2;
259                 v = *p - 'a';
260                 if(v < 0 || v >= 32) {
261                         diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
262                         break;
263                 }
264                 gopcode(OASHL, nodconst(v), l, r);
265                 break;
266         }
267         p += 2;
268         goto loop;
269 }
270
271 void
272 sextern(Sym *s, Node *a, long o, long w)
273 {
274         long e, lw;
275
276         for(e=0; e<w; e+=NSNAME) {
277                 lw = NSNAME;
278                 if(w-e < lw)
279                         lw = w-e;
280                 gpseudo(ADATA, s, nodconst(0));
281                 p->from.offset += o+e;
282                 p->reg = lw;
283                 p->to.type = D_SCONST;
284                 memmove(p->to.sval, a->cstring+e, lw);
285         }
286 }
287
288 void
289 gextern(Sym *s, Node *a, long o, long w)
290 {
291
292         if(a->op == OCONST && typev[a->type->etype]) {
293                 if(align(0, types[TCHAR], Aarg1))       /* isbigendian */
294                         gpseudo(ADATA, s, nod32const(a->vconst>>32));
295                 else
296                         gpseudo(ADATA, s, nod32const(a->vconst));
297                 p->from.offset += o;
298                 p->reg = 4;
299                 if(align(0, types[TCHAR], Aarg1))       /* isbigendian */
300                         gpseudo(ADATA, s, nod32const(a->vconst));
301                 else
302                         gpseudo(ADATA, s, nod32const(a->vconst>>32));
303                 p->from.offset += o + 4;
304                 p->reg = 4;
305                 return;
306         }
307         gpseudo(ADATA, s, a);
308         p->from.offset += o;
309         p->reg = w;
310         if(p->to.type == D_OREG)
311                 p->to.type = D_CONST;
312 }
313
314 void    zname(Biobuf*, Sym*, int);
315 char*   zaddr(char*, Adr*, int);
316 void    zwrite(Biobuf*, Prog*, int, int);
317 void    outhist(Biobuf*);
318
319 void
320 zwrite(Biobuf *b, Prog *p, int sf, int st)
321 {
322         char bf[100], *bp;
323
324         bf[0] = p->as;
325         bf[1] = p->scond;
326         bf[2] = p->reg;
327         bf[3] = p->lineno;
328         bf[4] = p->lineno>>8;
329         bf[5] = p->lineno>>16;
330         bf[6] = p->lineno>>24;
331         bp = zaddr(bf+7, &p->from, sf);
332         bp = zaddr(bp, &p->to, st);
333         Bwrite(b, bf, bp-bf);
334 }
335
336 void
337 outcode(void)
338 {
339         struct { Sym *sym; short type; } h[NSYM];
340         Prog *p;
341         Sym *s;
342         int sf, st, t, sym;
343
344         if(debug['S']) {
345                 for(p = firstp; p != P; p = p->link)
346                         if(p->as != ADATA && p->as != AGLOBL)
347                                 pc--;
348                 for(p = firstp; p != P; p = p->link) {
349                         print("%P\n", p);
350                         if(p->as != ADATA && p->as != AGLOBL)
351                                 pc++;
352                 }
353         }
354         outhist(&outbuf);
355         for(sym=0; sym<NSYM; sym++) {
356                 h[sym].sym = S;
357                 h[sym].type = 0;
358         }
359         sym = 1;
360         for(p = firstp; p != P; p = p->link) {
361         jackpot:
362                 sf = 0;
363                 s = p->from.sym;
364                 while(s != S) {
365                         sf = s->sym;
366                         if(sf < 0 || sf >= NSYM)
367                                 sf = 0;
368                         t = p->from.name;
369                         if(h[sf].type == t)
370                         if(h[sf].sym == s)
371                                 break;
372                         s->sym = sym;
373                         zname(&outbuf, s, t);
374                         h[sym].sym = s;
375                         h[sym].type = t;
376                         sf = sym;
377                         sym++;
378                         if(sym >= NSYM)
379                                 sym = 1;
380                         break;
381                 }
382                 st = 0;
383                 s = p->to.sym;
384                 while(s != S) {
385                         st = s->sym;
386                         if(st < 0 || st >= NSYM)
387                                 st = 0;
388                         t = p->to.name;
389                         if(h[st].type == t)
390                         if(h[st].sym == s)
391                                 break;
392                         s->sym = sym;
393                         zname(&outbuf, s, t);
394                         h[sym].sym = s;
395                         h[sym].type = t;
396                         st = sym;
397                         sym++;
398                         if(sym >= NSYM)
399                                 sym = 1;
400                         if(st == sf)
401                                 goto jackpot;
402                         break;
403                 }
404                 zwrite(&outbuf, p, sf, st);
405         }
406         firstp = P;
407         lastp = P;
408 }
409
410 void
411 outhist(Biobuf *b)
412 {
413         Hist *h;
414         char *p, *q, *op, c;
415         Prog pg;
416         int n;
417
418         pg = zprog;
419         pg.as = AHISTORY;
420         c = pathchar();
421         for(h = hist; h != H; h = h->link) {
422                 p = h->name;
423                 op = 0;
424                 /* on windows skip drive specifier in pathname */
425                 if(systemtype(Windows) && p && p[1] == ':'){
426                         p += 2;
427                         c = *p;
428                 }
429                 if(p && p[0] != c && h->offset == 0 && pathname){
430                         /* on windows skip drive specifier in pathname */
431                         if(systemtype(Windows) && pathname[1] == ':') {
432                                 op = p;
433                                 p = pathname+2;
434                                 c = *p;
435                         } else if(pathname[0] == c){
436                                 op = p;
437                                 p = pathname;
438                         }
439                 }
440                 while(p) {
441                         q = utfrune(p, c);
442                         if(q) {
443                                 n = q-p;
444                                 if(n == 0){
445                                         n = 1;  /* leading "/" */
446                                         *p = '/';       /* don't emit "\" on windows */
447                                 }
448                                 q++;
449                         } else {
450                                 n = strlen(p);
451                                 q = 0;
452                         }
453                         if(n) {
454                                 Bputc(b, ANAME);
455                                 Bputc(b, D_FILE);
456                                 Bputc(b, 1);
457                                 Bputc(b, '<');
458                                 Bwrite(b, p, n);
459                                 Bputc(b, 0);
460                         }
461                         p = q;
462                         if(p == 0 && op) {
463                                 p = op;
464                                 op = 0;
465                         }
466                 }
467                 pg.lineno = h->line;
468                 pg.to.type = zprog.to.type;
469                 pg.to.offset = h->offset;
470                 if(h->offset)
471                         pg.to.type = D_CONST;
472
473                 zwrite(b, &pg, 0, 0);
474         }
475 }
476
477 void
478 zname(Biobuf *b, Sym *s, int t)
479 {
480         char *n, bf[7];
481         ulong sig;
482
483         n = s->name;
484         if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
485                 sig = sign(s);
486                 bf[0] = ASIGNAME;
487                 bf[1] = sig;
488                 bf[2] = sig>>8;
489                 bf[3] = sig>>16;
490                 bf[4] = sig>>24;
491                 bf[5] = t;
492                 bf[6] = s->sym;
493                 Bwrite(b, bf, 7);
494                 s->sig = SIGDONE;
495         }
496         else{
497                 bf[0] = ANAME;
498                 bf[1] = t;      /* type */
499                 bf[2] = s->sym; /* sym */
500                 Bwrite(b, bf, 3);
501         }
502         Bwrite(b, n, strlen(n)+1);
503 }
504
505 char*
506 zaddr(char *bp, Adr *a, int s)
507 {
508         long l;
509         Ieee e;
510
511         bp[0] = a->type;
512         bp[1] = a->reg;
513         bp[2] = s;
514         bp[3] = a->name;
515         bp += 4;
516         switch(a->type) {
517         default:
518                 diag(Z, "unknown type %d in zaddr", a->type);
519
520         case D_NONE:
521         case D_REG:
522         case D_FREG:
523         case D_PSR:
524                 break;
525
526         case D_OREG:
527         case D_CONST:
528         case D_BRANCH:
529         case D_SHIFT:
530                 l = a->offset;
531                 bp[0] = l;
532                 bp[1] = l>>8;
533                 bp[2] = l>>16;
534                 bp[3] = l>>24;
535                 bp += 4;
536                 break;
537
538         case D_SCONST:
539                 memmove(bp, a->sval, NSNAME);
540                 bp += NSNAME;
541                 break;
542
543         case D_FCONST:
544                 ieeedtod(&e, a->dval);
545                 l = e.l;
546                 bp[0] = l;
547                 bp[1] = l>>8;
548                 bp[2] = l>>16;
549                 bp[3] = l>>24;
550                 bp += 4;
551                 l = e.h;
552                 bp[0] = l;
553                 bp[1] = l>>8;
554                 bp[2] = l>>16;
555                 bp[3] = l>>24;
556                 bp += 4;
557                 break;
558         }
559         return bp;
560 }
561
562 long
563 align(long i, Type *t, int op)
564 {
565         long o;
566         Type *v;
567         int w;
568
569         o = i;
570         w = 1;
571         switch(op) {
572         default:
573                 diag(Z, "unknown align opcode %d", op);
574                 break;
575
576         case Asu2:      /* padding at end of a struct */
577                 w = SZ_LONG;
578                 if(packflg)
579                         w = packflg;
580                 break;
581
582         case Ael1:      /* initial align of struct element */
583                 for(v=t; v->etype==TARRAY; v=v->link)
584                         ;
585                 w = ewidth[v->etype];
586                 if(w <= 0 || w >= SZ_LONG)
587                         w = SZ_LONG;
588                 if(packflg)
589                         w = packflg;
590                 break;
591
592         case Ael2:      /* width of a struct element */
593                 o += t->width;
594                 break;
595
596         case Aarg0:     /* initial passbyptr argument in arg list */
597                 if(typesuv[t->etype]) {
598                         o = align(o, types[TIND], Aarg1);
599                         o = align(o, types[TIND], Aarg2);
600                 }
601                 break;
602
603         case Aarg1:     /* initial align of parameter */
604                 w = ewidth[t->etype];
605                 if(w <= 0 || w >= SZ_LONG) {
606                         w = SZ_LONG;
607                         break;
608                 }
609                 w = 1;          /* little endian no adjustment */
610                 break;
611
612         case Aarg2:     /* width of a parameter */
613                 o += t->width;
614                 w = SZ_LONG;
615                 break;
616
617         case Aaut3:     /* total align of automatic */
618                 o = align(o, t, Ael2);
619                 o = align(o, t, Ael1);
620                 w = SZ_LONG;    /* because of a pun in cc/dcl.c:contig() */
621                 break;
622         }
623         o = round(o, w);
624         if(debug['A'])
625                 print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
626         return o;
627 }
628
629 long
630 maxround(long max, long v)
631 {
632         v = round(v, SZ_LONG);
633         if(v > max)
634                 return v;
635         return max;
636 }