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