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