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