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