1 #include "gc.h"
2
3 static int doubleflag;
4
5 void
swit1(C1 * q,int nc,long def,Node * n)6 swit1(C1 *q, int nc, long def, Node *n)
7 {
8 Node tn;
9
10 regalloc(&tn, ®node, Z);
11 swit2(q, nc, def, n, &tn);
12 regfree(&tn);
13 }
14
15 void
swit2(C1 * q,int nc,long def,Node * n,Node * tn)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
bitload(Node * b,Node * n1,Node * n2,Node * n3,Node * nn)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
bitstore(Node * b,Node * n1,Node * n2,Node * n3,Node * nn)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
outstring(char * s,long n)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
mulcon(Node * n,Node * nn)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
gextern(Sym * s,Node * a,long o,long w)243 gextern(Sym *s, Node *a, long o, long w)
244 {
245 if(a->op == OCONST && typev[a->type->etype]) {
246 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
247 gpseudo(ADATA, s, nod32const(a->vconst>>32));
248 else
249 gpseudo(ADATA, s, nod32const(a->vconst));
250 p->from.offset += o;
251 p->reg = 4;
252 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
253 gpseudo(ADATA, s, nod32const(a->vconst));
254 else
255 gpseudo(ADATA, s, nod32const(a->vconst>>32));
256 p->from.offset += o + 4;
257 p->reg = 4;
258 return;
259 }
260 gpseudo(ADATA, s, a);
261 p->from.offset += o;
262 p->reg = w;
263 if(p->to.type == D_OREG)
264 p->to.type = D_CONST;
265 }
266
267 void zname(Biobuf*, Sym*, int);
268 char* zaddr(char*, Adr*, int);
269 void zwrite(Biobuf*, Prog*, int, int);
270 void outhist(Biobuf*);
271
272 void
outcode(void)273 outcode(void)
274 {
275 struct { Sym *sym; short type; } h[NSYM];
276 Prog *p;
277 Sym *s;
278 int sf, st, t, sym;
279
280 if(debug['S']) {
281 for(p = firstp; p != P; p = p->link)
282 if(p->as != ADATA && p->as != AGLOBL)
283 pc--;
284 for(p = firstp; p != P; p = p->link) {
285 print("%P\n", p);
286 if(p->as != ADATA && p->as != AGLOBL)
287 pc++;
288 }
289 }
290 outhist(&outbuf);
291 for(sym=0; sym<NSYM; sym++) {
292 h[sym].sym = S;
293 h[sym].type = 0;
294 }
295 sym = 1;
296 for(p = firstp; p != P; p = p->link) {
297 jackpot:
298 sf = 0;
299 s = p->from.sym;
300 while(s != S) {
301 sf = s->sym;
302 if(sf < 0 || sf >= NSYM)
303 sf = 0;
304 t = p->from.name;
305 if(h[sf].type == t)
306 if(h[sf].sym == s)
307 break;
308 s->sym = sym;
309 zname(&outbuf, s, t);
310 h[sym].sym = s;
311 h[sym].type = t;
312 sf = sym;
313 sym++;
314 if(sym >= NSYM)
315 sym = 1;
316 break;
317 }
318 st = 0;
319 s = p->to.sym;
320 while(s != S) {
321 st = s->sym;
322 if(st < 0 || st >= NSYM)
323 st = 0;
324 t = p->to.name;
325 if(h[st].type == t)
326 if(h[st].sym == s)
327 break;
328 s->sym = sym;
329 zname(&outbuf, s, t);
330 h[sym].sym = s;
331 h[sym].type = t;
332 st = sym;
333 sym++;
334 if(sym >= NSYM)
335 sym = 1;
336 if(st == sf)
337 goto jackpot;
338 break;
339 }
340 zwrite(&outbuf, p, sf, st);
341 }
342 firstp = P;
343 lastp = P;
344 }
345
346 void
zwrite(Biobuf * b,Prog * p,int sf,int st)347 zwrite(Biobuf *b, Prog *p, int sf, int st)
348 {
349 char bf[100], *bp;
350 long l;
351
352 bf[0] = p->as;
353 bf[1] = p->as>>8;
354 bf[2] = p->reg;
355 if(p->from3.type != D_NONE)
356 bf[2] |= 0x40;
357 l = p->lineno;
358 bf[3] = l;
359 bf[4] = l>>8;
360 bf[5] = l>>16;
361 bf[6] = l>>24;
362 bp = zaddr(bf+7, &p->from, sf);
363 if(bf[2] & 0x40)
364 bp = zaddr(bp, &p->from3, 0);
365 bp = zaddr(bp, &p->to, st);
366 Bwrite(b, bf, bp-bf);
367 }
368
369 void
outhist(Biobuf * b)370 outhist(Biobuf *b)
371 {
372 Hist *h;
373 char *p, *q, *op, c;
374 Prog pg;
375 int n;
376
377 pg = zprog;
378 pg.as = AHISTORY;
379 c = pathchar();
380 for(h = hist; h != H; h = h->link) {
381 p = h->name;
382 op = 0;
383 /* on windows skip drive specifier in pathname */
384 if(systemtype(Windows) && p && p[1] == ':'){
385 p += 2;
386 c = *p;
387 }
388 if(p && p[0] != c && h->offset == 0 && pathname){
389 /* on windows skip drive specifier in pathname */
390 if(systemtype(Windows) && pathname[1] == ':') {
391 op = p;
392 p = pathname+2;
393 c = *p;
394 } else if(pathname[0] == c){
395 op = p;
396 p = pathname;
397 }
398 }
399 while(p) {
400 q = utfrune(p, c);
401 if(q) {
402 n = q-p;
403 if(n == 0){
404 n = 1; /* leading "/" */
405 *p = '/'; /* don't emit "\" on windows */
406 }
407 q++;
408 } else {
409 n = strlen(p);
410 q = 0;
411 }
412 if(n) {
413 Bputc(b, ANAME);
414 Bputc(b, ANAME>>8);
415 Bputc(b, D_FILE);
416 Bputc(b, 1);
417 Bputc(b, '<');
418 Bwrite(b, p, n);
419 Bputc(b, 0);
420 }
421 p = q;
422 if(p == 0 && op) {
423 p = op;
424 op = 0;
425 }
426 }
427 pg.lineno = h->line;
428 pg.to.type = zprog.to.type;
429 pg.to.offset = h->offset;
430 if(h->offset)
431 pg.to.type = D_CONST;
432
433 zwrite(b, &pg, 0, 0);
434 }
435 }
436
437 void
zname(Biobuf * b,Sym * s,int t)438 zname(Biobuf *b, Sym *s, int t)
439 {
440 char *n, bf[8];
441 ulong sig;
442
443 n = s->name;
444 if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
445 sig = sign(s);
446 bf[0] = ASIGNAME;
447 bf[1] = ASIGNAME>>8;
448 bf[2] = sig;
449 bf[3] = sig>>8;
450 bf[4] = sig>>16;
451 bf[5] = sig>>24;
452 bf[6] = t;
453 bf[7] = s->sym;
454 Bwrite(b, bf, 8);
455 s->sig = SIGDONE;
456 }
457 else{
458 bf[0] = ANAME;
459 bf[1] = ANAME>>8;
460 bf[2] = t; /* type */
461 bf[3] = s->sym; /* sym */
462 Bwrite(b, bf, 4);
463 }
464 Bwrite(b, n, strlen(n)+1);
465 }
466
467 char*
zaddr(char * bp,Adr * a,int s)468 zaddr(char *bp, Adr *a, int s)
469 {
470 long l;
471 Ieee e;
472
473 bp[0] = a->type;
474 bp[1] = a->reg;
475 bp[2] = s;
476 bp[3] = a->name;
477 bp += 4;
478 switch(a->type) {
479 default:
480 diag(Z, "unknown type %d in zaddr", a->type);
481
482 case D_NONE:
483 case D_REG:
484 case D_FREG:
485 case D_CREG:
486 break;
487
488 case D_OREG:
489 case D_CONST:
490 case D_BRANCH:
491 l = a->offset;
492 bp[0] = l;
493 bp[1] = l>>8;
494 bp[2] = l>>16;
495 bp[3] = l>>24;
496 bp += 4;
497 break;
498
499 case D_SCONST:
500 memmove(bp, a->sval, NSNAME);
501 bp += NSNAME;
502 break;
503
504 case D_FCONST:
505 ieeedtod(&e, a->dval);
506 l = e.l;
507 bp[0] = l;
508 bp[1] = l>>8;
509 bp[2] = l>>16;
510 bp[3] = l>>24;
511 bp += 4;
512 l = e.h;
513 bp[0] = l;
514 bp[1] = l>>8;
515 bp[2] = l>>16;
516 bp[3] = l>>24;
517 bp += 4;
518 break;
519 }
520 return bp;
521 }
522
523 static int
doubled(Type * t)524 doubled(Type *t)
525 {
526 Type *v;
527
528 if(debug['4'])
529 return 0;
530 if(t->nbits != 0)
531 return 0;
532 switch(t->etype){
533 case TDOUBLE:
534 return 1;
535
536 case TARRAY:
537 for(v=t; v->etype==TARRAY; v=v->link)
538 ;
539 return v->etype == TDOUBLE;
540
541 case TSTRUCT:
542 case TUNION:
543 for(v = t->link; v != T; v = v->down)
544 if(doubled(v))
545 return 1;
546 break;
547 }
548 return 0;
549 }
550
551 long
align(long i,Type * t,int op)552 align(long i, Type *t, int op)
553 {
554 long o;
555 Type *v;
556 int w, pc;
557
558 o = i;
559 w = 1;
560 pc = 0;
561 switch(op) {
562 default:
563 diag(Z, "unknown align opcode %d", op);
564 break;
565
566 case Asu2: /* padding at end of a struct */
567 w = doubled(t)? SZ_DOUBLE: SZ_LONG;
568 if(packflg)
569 w = packflg;
570 break;
571
572 case Ael1: /* initial align of struct element (also automatic) */
573 for(v=t; v->etype==TARRAY; v=v->link)
574 ;
575 w = ewidth[v->etype];
576 if(w <= 0 || w >= SZ_LONG){
577 if(doubled(v)){
578 w = SZ_DOUBLE;
579 doubleflag = 1;
580 }else
581 w = SZ_LONG;
582 }
583 if(packflg)
584 w = packflg;
585 break;
586
587 case Ael2: /* width of a struct element */
588 o += t->width;
589 break;
590
591 case Aarg0: /* initial passbyptr argument in arg list */
592 if(typesuv[t->etype]) {
593 o = align(o, types[TIND], Aarg1);
594 o = align(o, types[TIND], Aarg2);
595 }
596 break;
597
598 case Aarg1: /* initial align of parameter */
599 w = ewidth[t->etype];
600 if(w <= 0 || w >= SZ_LONG) {
601 if(doubled(t)){
602 w = SZ_DOUBLE;
603 pc = SZ_LONG; /* alignment must account for pc */
604 hasdoubled = 1;
605 }else
606 w = SZ_LONG;
607 break;
608 }
609 o += SZ_LONG - w; /* big endian adjustment */
610 w = 1;
611 break;
612
613 case Aarg2: /* width of a parameter */
614 o += t->width;
615 w = SZ_LONG;
616 if(doubled(t)){
617 pc = SZ_LONG;
618 hasdoubled = 1;
619 }
620 break;
621
622 case Aaut3: /* total align of automatic */
623 doubleflag = 0;
624 o = align(o, t, Ael1);
625 o = align(o, t, Ael2);
626 hasdoubled |= doubleflag;
627 break;
628 }
629 o = round(o+pc, w)-pc;
630 if(debug['A'])
631 print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
632 return o;
633 }
634
635 long
maxround(long max,long v)636 maxround(long max, long v)
637 {
638 int w;
639
640 w = SZ_LONG;
641 if((debug['8'] || hasdoubled) && !debug['4'])
642 w = SZ_DOUBLE;
643 v = round(v, w);
644 if(v > max)
645 return v;
646 return max;
647 }
648