1 #include "gc.h"
2
3 void
swit1(C1 * q,int nc,long def,Node * n)4 swit1(C1 *q, int nc, long def, Node *n)
5 {
6 Node tn;
7
8 regalloc(&tn, ®node, Z);
9 swit2(q, nc, def, n, &tn);
10 regfree(&tn);
11 }
12
13 void
swit2(C1 * q,int nc,long def,Node * n,Node * tn)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 = ABEQ;
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
bitload(Node * b,Node * n1,Node * n2,Node * n3,Node * nn)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
bitstore(Node * b,Node * n1,Node * n2,Node * n3,Node * nn)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
outstring(char * s,long n)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
mulcon(Node * n,Node * nn)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(ONEG, &nod1, Z, &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
sextern(Sym * s,Node * a,long o,long w)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
gextern(Sym * s,Node * a,long o,long w)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 char* zaddr(char*, Adr*, int);
284 void zwrite(Biobuf*, Prog*, int, int);
285 void outhist(Biobuf*);
286
287 void
outcode(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
zwrite(Biobuf * b,Prog * p,int sf,int st)362 zwrite(Biobuf *b, Prog *p, int sf, int st)
363 {
364 char bf[100], *bp;
365 long l;
366
367 bf[0] = p->as;
368 bf[1] = p->as>>8;
369 bf[2] = p->reg;
370 l = p->lineno;
371 bf[3] = l;
372 bf[4] = l>>8;
373 bf[5] = l>>16;
374 bf[6] = l>>24;
375 bp = zaddr(bf+7, &p->from, sf);
376 bp = zaddr(bp, &p->to, st);
377 Bwrite(b, bf, bp-bf);
378 }
379
380 void
outhist(Biobuf * b)381 outhist(Biobuf *b)
382 {
383 Hist *h;
384 char *p, *q, *op, c;
385 Prog pg;
386 int n;
387
388 pg = zprog;
389 pg.as = AHISTORY;
390 c = pathchar();
391 for(h = hist; h != H; h = h->link) {
392 p = h->name;
393 op = 0;
394 /* on windows skip drive specifier in pathname */
395 if(systemtype(Windows) && p && p[1] == ':'){
396 p += 2;
397 c = *p;
398 }
399 if(p && p[0] != c && h->offset == 0 && pathname){
400 /* on windows skip drive specifier in pathname */
401 if(systemtype(Windows) && pathname[1] == ':') {
402 op = p;
403 p = pathname+2;
404 c = *p;
405 } else if(pathname[0] == c){
406 op = p;
407 p = pathname;
408 }
409 }
410 while(p) {
411 q = utfrune(p, c);
412 if(q) {
413 n = q-p;
414 if(n == 0){
415 n = 1; /* leading "/" */
416 *p = '/'; /* don't emit "\" on windows */
417 }
418 q++;
419 } else {
420 n = strlen(p);
421 q = 0;
422 }
423 if(n) {
424 Bputc(b, ANAME);
425 Bputc(b, ANAME>>8);
426 Bputc(b, D_FILE);
427 Bputc(b, 1);
428 Bputc(b, '<');
429 Bwrite(b, p, n);
430 Bputc(b, 0);
431 }
432 p = q;
433 if(p == 0 && op) {
434 p = op;
435 op = 0;
436 }
437 }
438 pg.lineno = h->line;
439 pg.to.type = zprog.to.type;
440 pg.to.offset = h->offset;
441 if(h->offset)
442 pg.to.type = D_CONST;
443
444 zwrite(b, &pg, 0, 0);
445 }
446 }
447
448 void
zname(Biobuf * b,Sym * s,int t)449 zname(Biobuf *b, Sym *s, int t)
450 {
451 char *n, bf[8];
452 ulong sig;
453
454 n = s->name;
455 if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
456 sig = sign(s);
457 bf[0] = ASIGNAME;
458 bf[1] = ASIGNAME>>8;
459 bf[2] = sig;
460 bf[3] = sig>>8;
461 bf[4] = sig>>16;
462 bf[5] = sig>>24;
463 bf[6] = t;
464 bf[7] = s->sym;
465 Bwrite(b, bf, 8);
466 s->sig = SIGDONE;
467 }
468 else{
469 bf[0] = ANAME;
470 bf[1] = ANAME>>8;
471 bf[2] = t; /* type */
472 bf[3] = s->sym; /* sym */
473 Bwrite(b, bf, 4);
474 }
475 Bwrite(b, n, strlen(n)+1);
476 }
477
478 char*
zaddr(char * bp,Adr * a,int s)479 zaddr(char *bp, Adr *a, int s)
480 {
481 long l;
482 Ieee e;
483
484 if(a->type == D_CONST){
485 l = a->offset;
486 if((vlong)l != a->offset)
487 a->type = D_DCONST;
488 }
489 bp[0] = a->type;
490 bp[1] = a->reg;
491 bp[2] = s;
492 bp[3] = a->name;
493 bp += 4;
494 switch(a->type) {
495 default:
496 diag(Z, "unknown type %d in zaddr", a->type);
497
498 case D_NONE:
499 case D_REG:
500 case D_FREG:
501 case D_CREG:
502 break;
503
504 case D_OREG:
505 case D_CONST:
506 case D_BRANCH:
507 l = a->offset;
508 bp[0] = l;
509 bp[1] = l>>8;
510 bp[2] = l>>16;
511 bp[3] = l>>24;
512 bp += 4;
513 break;
514
515 case D_DCONST:
516 l = a->offset;
517 bp[0] = l;
518 bp[1] = l>>8;
519 bp[2] = l>>16;
520 bp[3] = l>>24;
521 bp += 4;
522 l = a->offset>>32;
523 bp[0] = l;
524 bp[1] = l>>8;
525 bp[2] = l>>16;
526 bp[3] = l>>24;
527 bp += 4;
528 break;
529
530 case D_SCONST:
531 memmove(bp, a->sval, NSNAME);
532 bp += NSNAME;
533 break;
534
535 case D_FCONST:
536 ieeedtod(&e, a->dval);
537 l = e.l;
538 bp[0] = l;
539 bp[1] = l>>8;
540 bp[2] = l>>16;
541 bp[3] = l>>24;
542 bp += 4;
543 l = e.h;
544 bp[0] = l;
545 bp[1] = l>>8;
546 bp[2] = l>>16;
547 bp[3] = l>>24;
548 bp += 4;
549 break;
550 }
551 return bp;
552 }
553
554 long
align(long i,Type * t,int op)555 align(long i, Type *t, int op)
556 {
557 long o;
558 Type *v;
559 int w;
560
561 o = i;
562 w = 1;
563 switch(op) {
564 default:
565 diag(Z, "unknown align opcode %d", op);
566 break;
567
568 case Asu2: /* padding at end of a struct */
569 w = SZ_VLONG;
570 if(packflg)
571 w = packflg;
572 break;
573
574 case Ael1: /* initial allign of struct element */
575 for(v=t; v->etype==TARRAY; v=v->link)
576 ;
577 w = ewidth[v->etype];
578 if(w <= 0 || w >= SZ_VLONG)
579 w = SZ_VLONG;
580 if(packflg)
581 w = packflg;
582 break;
583
584 case Ael2: /* width of a struct element */
585 o += t->width;
586 break;
587
588 case Aarg0: /* initial passbyptr argument in arg list */
589 if(typesu[t->etype]) {
590 o = align(o, types[TIND], Aarg1);
591 o = align(o, types[TIND], Aarg2);
592 }
593 break;
594
595 case Aarg1: /* initial align of parameter */
596 w = ewidth[t->etype];
597 if(w <= 0 || w >= SZ_VLONG) {
598 w = SZ_VLONG;
599 break;
600 }
601 o += SZ_VLONG - w; /* big endian adjustment */
602 w = 1;
603 break;
604
605 case Aarg2: /* width of a parameter */
606 o += t->width;
607 w = SZ_VLONG;
608 break;
609
610 case Aaut3: /* total align of automatic */
611 o = align(o, t, Ael1);
612 o = align(o, t, Ael2);
613 break;
614 }
615 o = round(o, w);
616 if(debug['A'])
617 print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
618 return o;
619 }
620
621 long
maxround(long max,long v)622 maxround(long max, long v)
623 {
624 v = round(v, SZ_VLONG);
625 if(v > max)
626 return v;
627 return max;
628 }
629