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