1 #include "gc.h" 2 3 int 4 swcmp(void *a1, void *a2) 5 { 6 C1 *p1, *p2; 7 8 p1 = a1; 9 p2 = a2; 10 if(p1->val < p2->val) 11 return -1; 12 return p1->val > p2->val; 13 } 14 15 void 16 doswit(Node *n) 17 { 18 Case *c; 19 C1 *q, *iq; 20 long def, nc, i; 21 22 def = 0; 23 nc = 0; 24 for(c = cases; c->link != C; c = c->link) { 25 if(c->def) { 26 if(def) 27 diag(n, "more than one default in switch"); 28 def = c->label; 29 continue; 30 } 31 nc++; 32 } 33 34 i = nc*sizeof(C1); 35 while(nhunk < i) 36 gethunk(); 37 iq = (C1*)hunk; 38 nhunk -= i; 39 hunk += i; 40 41 q = iq; 42 for(c = cases; c->link != C; c = c->link) { 43 if(c->def) 44 continue; 45 q->label = c->label; 46 q->val = c->val; 47 q++; 48 } 49 qsort(iq, nc, sizeof(C1), swcmp); 50 if(debug['W']) 51 for(i=0; i<nc; i++) 52 print("case %2d: = %.8lux\n", i, iq[i].val); 53 if(def == 0) 54 def = breakpc; 55 for(i=0; i<nc-1; i++) 56 if(iq[i].val == iq[i+1].val) 57 diag(n, "duplicate cases in switch %ld", iq[i].val); 58 swit1(iq, nc, def, n); 59 } 60 61 void 62 swit1(C1 *q, int nc, long def, Node *n) 63 { 64 C1 *r; 65 int i; 66 Prog *sp; 67 68 if(nc < 5) { 69 for(i=0; i<nc; i++) { 70 if(debug['W']) 71 print("case = %.8lux\n", q->val); 72 gopcode(OEQ, nodconst(q->val), Z, n); 73 patch(p, q->label); 74 q++; 75 } 76 gbranch(OGOTO); 77 patch(p, def); 78 return; 79 } 80 i = nc / 2; 81 r = q+i; 82 if(debug['W']) 83 print("case > %.8lux\n", r->val); 84 gopcode(OLT, nodconst(r->val), Z, n); 85 86 sp = p; 87 gbranch(OGOTO); 88 p->as = ABE; 89 patch(p, r->label); 90 swit1(q, i, def, n); 91 92 if(debug['W']) 93 print("case < %.8lux\n", r->val); 94 patch(sp, pc); 95 swit1(r+1, nc-i-1, def, n); 96 } 97 98 void 99 cas(void) 100 { 101 Case *c; 102 103 ALLOC(c, Case); 104 c->link = cases; 105 cases = c; 106 } 107 108 void 109 bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 110 { 111 int sh; 112 long v; 113 Node *l; 114 115 /* 116 * n1 gets adjusted/masked value 117 * n2 gets address of cell 118 * n3 gets contents of cell 119 */ 120 l = b->left; 121 if(n2 != Z) { 122 regalloc(n1, l, nn); 123 reglcgen(n2, l, Z); 124 regalloc(n3, l, Z); 125 gopcode(OAS, n2, Z, n3); 126 gopcode(OAS, n3, Z, n1); 127 } else { 128 regalloc(n1, l, nn); 129 cgen(l, n1); 130 } 131 if(b->type->shift == 0 && typeu[b->type->etype]) { 132 v = ~0 + (1L << b->type->nbits); 133 gopcode(OAND, nodconst(v), Z, n1); 134 } else { 135 sh = 32 - b->type->shift - b->type->nbits; 136 if(sh > 0) 137 gopcode(OASHL, nodconst(sh), Z, n1); 138 sh += b->type->shift; 139 if(sh > 0) 140 if(typeu[b->type->etype]) 141 gopcode(OLSHR, nodconst(sh), Z, n1); 142 else 143 gopcode(OASHR, nodconst(sh), Z, n1); 144 } 145 } 146 147 void 148 bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 149 { 150 long v; 151 Node nod, *l; 152 int sh; 153 154 /* 155 * n1 has adjusted/masked value 156 * n2 has address of cell 157 * n3 has contents of cell 158 */ 159 l = b->left; 160 regalloc(&nod, l, Z); 161 v = ~0 + (1L << b->type->nbits); 162 gopcode(OAND, nodconst(v), Z, n1); 163 gopcode(OAS, n1, Z, &nod); 164 if(nn != Z) 165 gopcode(OAS, n1, Z, nn); 166 sh = b->type->shift; 167 if(sh > 0) 168 gopcode(OASHL, nodconst(sh), Z, &nod); 169 v <<= sh; 170 gopcode(OAND, nodconst(~v), Z, n3); 171 gopcode(OOR, n3, Z, &nod); 172 gopcode(OAS, &nod, Z, n2); 173 174 regfree(&nod); 175 regfree(n1); 176 regfree(n2); 177 regfree(n3); 178 } 179 180 long 181 outstring(char *s, long n) 182 { 183 long r; 184 185 r = nstring; 186 while(n > 0) { 187 string[mnstring] = *s++; 188 mnstring++; 189 nstring++; 190 if(mnstring >= NSNAME) { 191 gpseudo(ADATA, symstring, nodconst(0L)); 192 p->from.offset += nstring - NSNAME; 193 p->from.scale = NSNAME; 194 p->to.type = D_SCONST; 195 memmove(p->to.sval, string, NSNAME); 196 mnstring = 0; 197 } 198 n--; 199 } 200 return r; 201 } 202 203 long 204 outlstring(ushort *s, long n) 205 { 206 char buf[2]; 207 int c; 208 long r; 209 210 while(nstring & 1) 211 outstring("", 1); 212 r = nstring; 213 while(n > 0) { 214 c = *s++; 215 if(endian(0)) { 216 buf[0] = c>>8; 217 buf[1] = c; 218 } else { 219 buf[0] = c; 220 buf[1] = c>>8; 221 } 222 outstring(buf, 2); 223 n -= sizeof(ushort); 224 } 225 return r; 226 } 227 228 int 229 vlog(Node *n) 230 { 231 232 int s, i; 233 ulong m, v; 234 235 if(n->op != OCONST) 236 goto bad; 237 if(!typechlp[n->type->etype]) 238 goto bad; 239 240 v = n->vconst; 241 242 s = 0; 243 m = MASK(64); 244 for(i=32; i; i>>=1) { 245 m >>= i; 246 if(!(v & m)) { 247 v >>= i; 248 s += i; 249 } 250 } 251 if(v == 1) 252 return s; 253 254 bad: 255 return -1; 256 } 257 258 void 259 nullwarn(Node *l, Node *r) 260 { 261 warn(Z, "result of operation not used"); 262 if(l != Z) 263 cgen(l, Z); 264 if(r != Z) 265 cgen(r, Z); 266 } 267 268 void 269 sextern(Sym *s, Node *a, long o, long w) 270 { 271 long e, lw; 272 273 for(e=0; e<w; e+=NSNAME) { 274 lw = NSNAME; 275 if(w-e < lw) 276 lw = w-e; 277 gpseudo(ADATA, s, nodconst(0L)); 278 p->from.offset += o+e; 279 p->from.scale = lw; 280 p->to.type = D_SCONST; 281 memmove(p->to.sval, a->cstring+e, lw); 282 } 283 } 284 285 void 286 gextern(Sym *s, Node *a, long o, long w) 287 { 288 gpseudo(ADATA, s, a); 289 p->from.offset += o; 290 p->from.scale = w; 291 switch(p->to.type) { 292 default: 293 p->to.index = p->to.type; 294 p->to.type = D_ADDR; 295 case D_CONST: 296 case D_FCONST: 297 case D_ADDR: 298 break; 299 } 300 } 301 302 void zname(Biobuf*, char*, int, int); 303 void zaddr(Biobuf*, Adr*, int); 304 void outhist(Biobuf*); 305 306 void 307 outcode(void) 308 { 309 struct { Sym *sym; short type; } h[NSYM]; 310 Prog *p; 311 Sym *s; 312 int f, sf, st, t, sym; 313 Biobuf b; 314 315 if(debug['S']) { 316 for(p = firstp; p != P; p = p->link) 317 if(p->as != ADATA && p->as != AGLOBL) 318 pc--; 319 for(p = firstp; p != P; p = p->link) { 320 print("%P\n", p); 321 if(p->as != ADATA && p->as != AGLOBL) 322 pc++; 323 } 324 } 325 f = open(outfile, OWRITE); 326 if(f < 0) { 327 diag(Z, "cannot open %s", outfile); 328 return; 329 } 330 Binit(&b, f, OWRITE); 331 Bseek(&b, 0L, 2); 332 outhist(&b); 333 for(sym=0; sym<NSYM; sym++) { 334 h[sym].sym = S; 335 h[sym].type = 0; 336 } 337 sym = 1; 338 for(p = firstp; p != P; p = p->link) { 339 jackpot: 340 sf = 0; 341 s = p->from.sym; 342 while(s != S) { 343 sf = s->sym; 344 if(sf < 0 || sf >= NSYM) 345 sf = 0; 346 t = p->from.type; 347 if(t == D_ADDR) 348 t = p->from.index; 349 if(h[sf].type == t) 350 if(h[sf].sym == s) 351 break; 352 zname(&b, s->name, t, sym); 353 s->sym = sym; 354 h[sym].sym = s; 355 h[sym].type = t; 356 sf = sym; 357 sym++; 358 if(sym >= NSYM) 359 sym = 1; 360 break; 361 } 362 st = 0; 363 s = p->to.sym; 364 while(s != S) { 365 st = s->sym; 366 if(st < 0 || st >= NSYM) 367 st = 0; 368 t = p->to.type; 369 if(t == D_ADDR) 370 t = p->to.index; 371 if(h[st].type == t) 372 if(h[st].sym == s) 373 break; 374 zname(&b, s->name, t, sym); 375 s->sym = sym; 376 h[sym].sym = s; 377 h[sym].type = t; 378 st = sym; 379 sym++; 380 if(sym >= NSYM) 381 sym = 1; 382 if(st == sf) 383 goto jackpot; 384 break; 385 } 386 Bputc(&b, p->as); 387 Bputc(&b, p->lineno); 388 Bputc(&b, p->lineno>>8); 389 Bputc(&b, p->lineno>>16); 390 Bputc(&b, p->lineno>>24); 391 switch(t = p->type) { 392 case D_NONE: 393 t = 0; /* 0 D_NONE */ 394 break; 395 default: 396 if(t < D_R0 || t >= D_R0+32) { 397 diag(Z, "bad type in outcode"); 398 t = D_R0; 399 } 400 t = (t - D_R0) + 1; /* 1-32 D_R0+ */ 401 break; 402 case D_CONST: 403 t = p->offset; 404 if(t >= 32) { 405 diag(Z, "bad offset in outcode"); 406 t = 0; 407 } 408 t = (t - 0) + 33; /* 33-64 D_CONST+ */ 409 break; 410 } 411 Bputc(&b, t); 412 zaddr(&b, &p->from, sf); 413 zaddr(&b, &p->to, st); 414 } 415 Bflush(&b); 416 close(f); 417 firstp = P; 418 lastp = P; 419 } 420 421 void 422 outhist(Biobuf *b) 423 { 424 Hist *h; 425 char *p, *q, *op; 426 Prog pg; 427 int n; 428 429 pg = zprog; 430 pg.as = AHISTORY; 431 for(h = hist; h != H; h = h->link) { 432 p = h->name; 433 op = 0; 434 if(p && p[0] != '/' && h->offset == 0 && pathname && pathname[0] == '/') { 435 op = p; 436 p = pathname; 437 } 438 while(p) { 439 q = utfrune(p, '/'); 440 if(q) { 441 n = q-p; 442 if(n == 0) 443 n = 1; /* leading "/" */ 444 q++; 445 } else { 446 n = strlen(p); 447 q = 0; 448 } 449 if(n) { 450 Bputc(b, ANAME); 451 Bputc(b, D_FILE); 452 Bputc(b, 1); 453 Bputc(b, '<'); 454 Bwrite(b, p, n); 455 Bputc(b, 0); 456 } 457 p = q; 458 if(p == 0 && op) { 459 p = op; 460 op = 0; 461 } 462 } 463 pg.lineno = h->line; 464 pg.to.type = zprog.to.type; 465 pg.to.offset = h->offset; 466 if(h->offset) 467 pg.to.type = D_CONST; 468 469 Bputc(b, pg.as); 470 Bputc(b, pg.lineno); 471 Bputc(b, pg.lineno>>8); 472 Bputc(b, pg.lineno>>16); 473 Bputc(b, pg.lineno>>24); 474 Bputc(b, 0); /* reg */ 475 zaddr(b, &pg.from, 0); 476 zaddr(b, &pg.to, 0); 477 } 478 } 479 480 void 481 zname(Biobuf *b, char *n, int t, int s) 482 { 483 484 Bputc(b, ANAME); /* as */ 485 Bputc(b, t); /* type */ 486 Bputc(b, s); /* sym */ 487 while(*n) { 488 Bputc(b, *n); 489 n++; 490 } 491 Bputc(b, 0); 492 } 493 494 void 495 zaddr(Biobuf *b, Adr *a, int s) 496 { 497 long l; 498 int i, t; 499 char *n; 500 Ieee e; 501 502 t = 0; 503 if(a->index != D_NONE || a->scale != 0) 504 t |= T_INDEX; 505 if(s != 0) 506 t |= T_SYM; 507 508 switch(a->type) { 509 default: 510 t |= T_TYPE; 511 case D_NONE: 512 if(a->offset != 0) 513 t |= T_OFFSET; 514 break; 515 case D_FCONST: 516 t |= T_FCONST; 517 break; 518 case D_SCONST: 519 t |= T_SCONST; 520 break; 521 } 522 Bputc(b, t); 523 524 if(t & T_INDEX) { /* implies index, scale */ 525 Bputc(b, a->index); 526 Bputc(b, a->scale); 527 } 528 if(t & T_OFFSET) { /* implies offset */ 529 l = a->offset; 530 Bputc(b, l); 531 Bputc(b, l>>8); 532 Bputc(b, l>>16); 533 Bputc(b, l>>24); 534 } 535 if(t & T_SYM) /* implies sym */ 536 Bputc(b, s); 537 if(t & T_FCONST) { 538 ieeedtod(&e, a->dval); 539 l = e.l; 540 Bputc(b, l); 541 Bputc(b, l>>8); 542 Bputc(b, l>>16); 543 Bputc(b, l>>24); 544 l = e.h; 545 Bputc(b, l); 546 Bputc(b, l>>8); 547 Bputc(b, l>>16); 548 Bputc(b, l>>24); 549 return; 550 } 551 if(t & T_SCONST) { 552 n = a->sval; 553 for(i=0; i<NSNAME; i++) { 554 Bputc(b, *n); 555 n++; 556 } 557 return; 558 } 559 if(t & T_TYPE) 560 Bputc(b, a->type); 561 } 562 563 void 564 ieeedtod(Ieee *ieee, double native) 565 { 566 double fr, ho, f; 567 int exp; 568 569 if(native < 0) { 570 ieeedtod(ieee, -native); 571 ieee->h |= 0x80000000L; 572 return; 573 } 574 if(native == 0) { 575 ieee->l = 0; 576 ieee->h = 0; 577 return; 578 } 579 fr = frexp(native, &exp); 580 f = 2097152L; /* shouldnt use fp constants here */ 581 fr = modf(fr*f, &ho); 582 ieee->h = ho; 583 ieee->h &= 0xfffffL; 584 ieee->h |= (exp+1022L) << 20; 585 f = 65536L; 586 fr = modf(fr*f, &ho); 587 ieee->l = ho; 588 ieee->l <<= 16; 589 ieee->l |= (long)(fr*f); 590 } 591 592 char* xonames[] = 593 { 594 "INDEX", 595 "XEND", 596 }; 597 598 char* 599 xOconv(int a) 600 { 601 if(a <= OEND || a > OXEND) 602 return "**badO**"; 603 return xonames[a-OEND-1]; 604 } 605 606 int 607 endian(int w) 608 { 609 610 USED(w); 611 return 0; 612 } 613 614 int 615 passbypointer(int et) 616 { 617 618 return typesuv[et]; 619 } 620 621 int 622 argalign(long typewidth, long offset, int offsp) 623 { 624 USED(typewidth,offset,offsp); 625 return 0; 626 } 627