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