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