github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/5c/txt.c (about) 1 // Inferno utils/5c/txt.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5c/txt.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 32 #include "gc.h" 33 34 35 int thechar = '5'; 36 char *thestring = "arm"; 37 38 LinkArch *thelinkarch = &linkarm; 39 40 void 41 linkarchinit(void) 42 { 43 } 44 45 void 46 ginit(void) 47 { 48 Type *t; 49 50 exregoffset = REGEXT; 51 exfregoffset = FREGEXT; 52 listinit(); 53 nstring = 0; 54 mnstring = 0; 55 nrathole = 0; 56 pc = 0; 57 breakpc = -1; 58 continpc = -1; 59 cases = C; 60 lastp = P; 61 tfield = types[TLONG]; 62 63 zprog.link = P; 64 zprog.as = AGOK; 65 zprog.reg = NREG; 66 zprog.from.type = D_NONE; 67 zprog.from.name = D_NONE; 68 zprog.from.reg = NREG; 69 zprog.to = zprog.from; 70 zprog.scond = 0xE; 71 72 regnode.op = OREGISTER; 73 regnode.class = CEXREG; 74 regnode.reg = REGTMP; 75 regnode.complex = 0; 76 regnode.addable = 11; 77 regnode.type = types[TLONG]; 78 79 constnode.op = OCONST; 80 constnode.class = CXXX; 81 constnode.complex = 0; 82 constnode.addable = 20; 83 constnode.type = types[TLONG]; 84 85 fconstnode.op = OCONST; 86 fconstnode.class = CXXX; 87 fconstnode.complex = 0; 88 fconstnode.addable = 20; 89 fconstnode.type = types[TDOUBLE]; 90 91 nodsafe = new(ONAME, Z, Z); 92 nodsafe->sym = slookup(".safe"); 93 nodsafe->type = types[TINT]; 94 nodsafe->etype = types[TINT]->etype; 95 nodsafe->class = CAUTO; 96 complex(nodsafe); 97 98 t = typ(TARRAY, types[TCHAR]); 99 symrathole = slookup(".rathole"); 100 symrathole->class = CGLOBL; 101 symrathole->type = t; 102 103 nodrat = new(ONAME, Z, Z); 104 nodrat->sym = symrathole; 105 nodrat->type = types[TIND]; 106 nodrat->etype = TVOID; 107 nodrat->class = CGLOBL; 108 complex(nodrat); 109 nodrat->type = t; 110 111 nodret = new(ONAME, Z, Z); 112 nodret->sym = slookup(".ret"); 113 nodret->type = types[TIND]; 114 nodret->etype = TIND; 115 nodret->class = CPARAM; 116 nodret = new(OIND, nodret, Z); 117 complex(nodret); 118 119 com64init(); 120 121 memset(reg, 0, sizeof(reg)); 122 } 123 124 void 125 gclean(void) 126 { 127 int i; 128 Sym *s; 129 130 for(i=0; i<NREG; i++) 131 if(reg[i]) 132 diag(Z, "reg %d left allocated", i); 133 for(i=NREG; i<NREG+NFREG; i++) 134 if(reg[i]) 135 diag(Z, "freg %d left allocated", i-NREG); 136 while(mnstring) 137 outstring("", 1L); 138 symstring->type->width = nstring; 139 symrathole->type->width = nrathole; 140 for(i=0; i<NHASH; i++) 141 for(s = hash[i]; s != S; s = s->link) { 142 if(s->type == T) 143 continue; 144 if(s->type->width == 0) 145 continue; 146 if(s->class != CGLOBL && s->class != CSTATIC) 147 continue; 148 if(s->type == types[TENUM]) 149 continue; 150 gpseudo(AGLOBL, s, nodconst(s->type->width)); 151 } 152 nextpc(); 153 p->as = AEND; 154 outcode(); 155 } 156 157 void 158 nextpc(void) 159 { 160 Plist *pl; 161 162 p = alloc(sizeof(*p)); 163 *p = zprog; 164 p->lineno = nearln; 165 pc++; 166 if(lastp == nil) { 167 pl = linknewplist(ctxt); 168 pl->firstpc = p; 169 } else 170 lastp->link = p; 171 lastp = p; 172 } 173 174 void 175 gargs(Node *n, Node *tn1, Node *tn2) 176 { 177 int32 regs; 178 Node fnxargs[20], *fnxp; 179 180 regs = cursafe; 181 182 fnxp = fnxargs; 183 garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */ 184 185 curarg = 0; 186 fnxp = fnxargs; 187 garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */ 188 189 cursafe = regs; 190 } 191 192 void 193 garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp) 194 { 195 Node nod; 196 197 if(n == Z) 198 return; 199 if(n->op == OLIST) { 200 garg1(n->left, tn1, tn2, f, fnxp); 201 garg1(n->right, tn1, tn2, f, fnxp); 202 return; 203 } 204 if(f == 0) { 205 if(n->complex >= FNX) { 206 regsalloc(*fnxp, n); 207 nod = znode; 208 nod.op = OAS; 209 nod.left = *fnxp; 210 nod.right = n; 211 nod.type = n->type; 212 cgen(&nod, Z); 213 (*fnxp)++; 214 } 215 return; 216 } 217 if(typesuv[n->type->etype]) { 218 regaalloc(tn2, n); 219 if(n->complex >= FNX) { 220 sugen(*fnxp, tn2, n->type->width); 221 (*fnxp)++; 222 } else 223 sugen(n, tn2, n->type->width); 224 return; 225 } 226 if(REGARG >= 0 && curarg == 0 && typechlp[n->type->etype]) { 227 regaalloc1(tn1, n); 228 if(n->complex >= FNX) { 229 cgen(*fnxp, tn1); 230 (*fnxp)++; 231 } else 232 cgen(n, tn1); 233 return; 234 } 235 regalloc(tn1, n, Z); 236 if(n->complex >= FNX) { 237 cgen(*fnxp, tn1); 238 (*fnxp)++; 239 } else 240 cgen(n, tn1); 241 regaalloc(tn2, n); 242 gopcode(OAS, tn1, Z, tn2); 243 regfree(tn1); 244 } 245 246 Node* 247 nodconst(int32 v) 248 { 249 constnode.vconst = v; 250 return &constnode; 251 } 252 253 Node* 254 nod32const(vlong v) 255 { 256 constnode.vconst = v & MASK(32); 257 return &constnode; 258 } 259 260 Node* 261 nodfconst(double d) 262 { 263 fconstnode.fconst = d; 264 return &fconstnode; 265 } 266 267 void 268 nodreg(Node *n, Node *nn, int reg) 269 { 270 *n = regnode; 271 n->reg = reg; 272 n->type = nn->type; 273 n->lineno = nn->lineno; 274 } 275 276 void 277 regret(Node *n, Node *nn) 278 { 279 int r; 280 281 r = REGRET; 282 if(typefd[nn->type->etype]) 283 r = FREGRET+NREG; 284 nodreg(n, nn, r); 285 reg[r]++; 286 } 287 288 int 289 tmpreg(void) 290 { 291 int i; 292 293 for(i=REGRET+1; i<NREG; i++) 294 if(reg[i] == 0) 295 return i; 296 diag(Z, "out of fixed registers"); 297 return 0; 298 } 299 300 void 301 regalloc(Node *n, Node *tn, Node *o) 302 { 303 int i; 304 305 switch(tn->type->etype) { 306 case TCHAR: 307 case TUCHAR: 308 case TSHORT: 309 case TUSHORT: 310 case TINT: 311 case TUINT: 312 case TLONG: 313 case TULONG: 314 case TIND: 315 if(o != Z && o->op == OREGISTER) { 316 i = o->reg; 317 if(i >= 0 && i < NREG) 318 goto out; 319 } 320 for(i=REGRET+1; i<=REGEXT-2; i++) 321 if(reg[i] == 0) 322 goto out; 323 diag(tn, "out of fixed registers"); 324 goto err; 325 326 case TFLOAT: 327 case TDOUBLE: 328 case TVLONG: 329 if(o != Z && o->op == OREGISTER) { 330 i = o->reg; 331 if(i >= NREG && i < NREG+NFREG) 332 goto out; 333 } 334 for(i=NREG; i<NREG+NFREG; i++) 335 if(reg[i] == 0) 336 goto out; 337 diag(tn, "out of float registers"); 338 goto err; 339 } 340 diag(tn, "unknown type in regalloc: %T", tn->type); 341 err: 342 nodreg(n, tn, 0); 343 return; 344 out: 345 reg[i]++; 346 nodreg(n, tn, i); 347 } 348 349 void 350 regialloc(Node *n, Node *tn, Node *o) 351 { 352 Node nod; 353 354 nod = *tn; 355 nod.type = types[TIND]; 356 regalloc(n, &nod, o); 357 } 358 359 void 360 regfree(Node *n) 361 { 362 int i; 363 364 i = 0; 365 if(n->op != OREGISTER && n->op != OINDREG) 366 goto err; 367 i = n->reg; 368 if(i < 0 || i >= nelem(reg)) 369 goto err; 370 if(reg[i] <= 0) 371 goto err; 372 reg[i]--; 373 return; 374 err: 375 diag(n, "error in regfree: %d", i); 376 } 377 378 void 379 regsalloc(Node *n, Node *nn) 380 { 381 cursafe = align(cursafe, nn->type, Aaut3, nil); 382 maxargsafe = maxround(maxargsafe, cursafe+curarg); 383 *n = *nodsafe; 384 n->xoffset = -(stkoff + cursafe); 385 n->type = nn->type; 386 n->etype = nn->type->etype; 387 n->lineno = nn->lineno; 388 } 389 390 void 391 regaalloc1(Node *n, Node *nn) 392 { 393 if(REGARG < 0) { 394 fatal(n, "regaalloc1 and REGARG<0"); 395 return; 396 } 397 nodreg(n, nn, REGARG); 398 reg[REGARG]++; 399 curarg = align(curarg, nn->type, Aarg1, nil); 400 curarg = align(curarg, nn->type, Aarg2, nil); 401 maxargsafe = maxround(maxargsafe, cursafe+curarg); 402 } 403 404 void 405 regaalloc(Node *n, Node *nn) 406 { 407 curarg = align(curarg, nn->type, Aarg1, nil); 408 *n = *nn; 409 n->op = OINDREG; 410 n->reg = REGSP; 411 n->xoffset = curarg + SZ_LONG; 412 n->complex = 0; 413 n->addable = 20; 414 curarg = align(curarg, nn->type, Aarg2, nil); 415 maxargsafe = maxround(maxargsafe, cursafe+curarg); 416 } 417 418 void 419 regind(Node *n, Node *nn) 420 { 421 422 if(n->op != OREGISTER) { 423 diag(n, "regind not OREGISTER"); 424 return; 425 } 426 n->op = OINDREG; 427 n->type = nn->type; 428 } 429 430 void 431 raddr(Node *n, Prog *p) 432 { 433 Addr a; 434 435 naddr(n, &a); 436 if(R0ISZERO && a.type == D_CONST && a.offset == 0) { 437 a.type = D_REG; 438 a.reg = 0; 439 } 440 if(a.type != D_REG && a.type != D_FREG) { 441 if(n) 442 diag(n, "bad in raddr: %O", n->op); 443 else 444 diag(n, "bad in raddr: <null>"); 445 p->reg = NREG; 446 } else 447 p->reg = a.reg; 448 } 449 450 void 451 naddr(Node *n, Addr *a) 452 { 453 int32 v; 454 455 a->type = D_NONE; 456 if(n == Z) 457 return; 458 switch(n->op) { 459 default: 460 bad: 461 diag(n, "bad in naddr: %O", n->op); 462 break; 463 464 case OREGISTER: 465 a->type = D_REG; 466 a->sym = nil; 467 a->reg = n->reg; 468 if(a->reg >= NREG) { 469 a->type = D_FREG; 470 a->reg -= NREG; 471 } 472 break; 473 474 case OIND: 475 naddr(n->left, a); 476 if(a->type == D_REG) { 477 a->type = D_OREG; 478 break; 479 } 480 if(a->type == D_CONST) { 481 a->type = D_OREG; 482 break; 483 } 484 goto bad; 485 486 case OINDREG: 487 a->type = D_OREG; 488 a->sym = nil; 489 a->offset = n->xoffset; 490 a->reg = n->reg; 491 break; 492 493 case ONAME: 494 a->etype = n->etype; 495 a->type = D_OREG; 496 a->name = D_STATIC; 497 a->sym = linksym(n->sym); 498 a->offset = n->xoffset; 499 if(n->class == CSTATIC) 500 break; 501 if(n->class == CEXTERN || n->class == CGLOBL) { 502 a->name = D_EXTERN; 503 break; 504 } 505 if(n->class == CAUTO) { 506 a->name = D_AUTO; 507 break; 508 } 509 if(n->class == CPARAM) { 510 a->name = D_PARAM; 511 break; 512 } 513 goto bad; 514 515 case OCONST: 516 a->sym = nil; 517 a->reg = NREG; 518 if(typefd[n->type->etype]) { 519 a->type = D_FCONST; 520 a->u.dval = n->fconst; 521 } else { 522 a->type = D_CONST; 523 a->offset = n->vconst; 524 } 525 break; 526 527 case OADDR: 528 naddr(n->left, a); 529 if(a->type == D_OREG) { 530 a->type = D_CONST; 531 break; 532 } 533 goto bad; 534 535 case OADD: 536 if(n->left->op == OCONST) { 537 naddr(n->left, a); 538 v = a->offset; 539 naddr(n->right, a); 540 } else { 541 naddr(n->right, a); 542 v = a->offset; 543 naddr(n->left, a); 544 } 545 a->offset += v; 546 break; 547 548 } 549 } 550 551 void 552 fop(int as, int f1, int f2, Node *t) 553 { 554 Node nod1, nod2, nod3; 555 556 nodreg(&nod1, t, NREG+f1); 557 nodreg(&nod2, t, NREG+f2); 558 regalloc(&nod3, t, t); 559 gopcode(as, &nod1, &nod2, &nod3); 560 gmove(&nod3, t); 561 regfree(&nod3); 562 } 563 564 void 565 gmovm(Node *f, Node *t, int w) 566 { 567 gins(AMOVM, f, t); 568 p->scond |= C_UBIT; 569 if(w) 570 p->scond |= C_WBIT; 571 } 572 573 void 574 gmove(Node *f, Node *t) 575 { 576 int ft, tt, a; 577 Node nod, nod1; 578 Prog *p1; 579 580 ft = f->type->etype; 581 tt = t->type->etype; 582 583 if(ft == TDOUBLE && f->op == OCONST) { 584 } 585 if(ft == TFLOAT && f->op == OCONST) { 586 } 587 588 /* 589 * a load -- 590 * put it into a register then 591 * worry what to do with it. 592 */ 593 if(f->op == ONAME || f->op == OINDREG || f->op == OIND) { 594 switch(ft) { 595 default: 596 a = AMOVW; 597 break; 598 case TFLOAT: 599 a = AMOVF; 600 break; 601 case TDOUBLE: 602 a = AMOVD; 603 break; 604 case TCHAR: 605 a = AMOVBS; 606 break; 607 case TUCHAR: 608 a = AMOVBU; 609 break; 610 case TSHORT: 611 a = AMOVHS; 612 break; 613 case TUSHORT: 614 a = AMOVHU; 615 break; 616 } 617 if(typechlp[ft] && typeilp[tt]) 618 regalloc(&nod, t, t); 619 else 620 regalloc(&nod, f, t); 621 gins(a, f, &nod); 622 gmove(&nod, t); 623 regfree(&nod); 624 return; 625 } 626 627 /* 628 * a store -- 629 * put it into a register then 630 * store it. 631 */ 632 if(t->op == ONAME || t->op == OINDREG || t->op == OIND) { 633 switch(tt) { 634 default: 635 a = AMOVW; 636 break; 637 case TUCHAR: 638 a = AMOVBU; 639 break; 640 case TCHAR: 641 a = AMOVBS; 642 break; 643 case TUSHORT: 644 a = AMOVHU; 645 break; 646 case TSHORT: 647 a = AMOVHS; 648 break; 649 case TFLOAT: 650 a = AMOVF; 651 break; 652 case TVLONG: 653 case TDOUBLE: 654 a = AMOVD; 655 break; 656 } 657 if(ft == tt) 658 regalloc(&nod, t, f); 659 else 660 regalloc(&nod, t, Z); 661 gmove(f, &nod); 662 gins(a, &nod, t); 663 regfree(&nod); 664 return; 665 } 666 667 /* 668 * type x type cross table 669 */ 670 a = AGOK; 671 switch(ft) { 672 case TDOUBLE: 673 case TVLONG: 674 case TFLOAT: 675 switch(tt) { 676 case TDOUBLE: 677 case TVLONG: 678 a = AMOVD; 679 if(ft == TFLOAT) 680 a = AMOVFD; 681 break; 682 case TFLOAT: 683 a = AMOVDF; 684 if(ft == TFLOAT) 685 a = AMOVF; 686 break; 687 case TINT: 688 case TUINT: 689 case TLONG: 690 case TULONG: 691 case TIND: 692 a = AMOVDW; 693 if(ft == TFLOAT) 694 a = AMOVFW; 695 break; 696 case TSHORT: 697 case TUSHORT: 698 case TCHAR: 699 case TUCHAR: 700 a = AMOVDW; 701 if(ft == TFLOAT) 702 a = AMOVFW; 703 break; 704 } 705 break; 706 case TUINT: 707 case TULONG: 708 if(tt == TFLOAT || tt == TDOUBLE) { 709 // ugly and probably longer than necessary, 710 // but vfp has a single instruction for this, 711 // so hopefully it won't last long. 712 // 713 // tmp = f 714 // tmp1 = tmp & 0x80000000 715 // tmp ^= tmp1 716 // t = float(int32(tmp)) 717 // if(tmp1) 718 // t += 2147483648. 719 // 720 regalloc(&nod, f, Z); 721 regalloc(&nod1, f, Z); 722 gins(AMOVW, f, &nod); 723 gins(AMOVW, &nod, &nod1); 724 gins(AAND, nodconst(0x80000000), &nod1); 725 gins(AEOR, &nod1, &nod); 726 if(tt == TFLOAT) 727 gins(AMOVWF, &nod, t); 728 else 729 gins(AMOVWD, &nod, t); 730 gins(ACMP, nodconst(0), Z); 731 raddr(&nod1, p); 732 gins(ABEQ, Z, Z); 733 regfree(&nod); 734 regfree(&nod1); 735 p1 = p; 736 regalloc(&nod, t, Z); 737 gins(AMOVF, nodfconst(2147483648.), &nod); 738 gins(AADDF, &nod, t); 739 regfree(&nod); 740 patch(p1, pc); 741 return; 742 } 743 // fall through 744 745 case TINT: 746 case TLONG: 747 case TIND: 748 switch(tt) { 749 case TDOUBLE: 750 gins(AMOVWD, f, t); 751 return; 752 case TFLOAT: 753 gins(AMOVWF, f, t); 754 return; 755 case TINT: 756 case TUINT: 757 case TLONG: 758 case TULONG: 759 case TIND: 760 case TSHORT: 761 case TUSHORT: 762 case TCHAR: 763 case TUCHAR: 764 a = AMOVW; 765 break; 766 } 767 break; 768 case TSHORT: 769 switch(tt) { 770 case TDOUBLE: 771 regalloc(&nod, f, Z); 772 gins(AMOVHS, f, &nod); 773 gins(AMOVWD, &nod, t); 774 regfree(&nod); 775 return; 776 case TFLOAT: 777 regalloc(&nod, f, Z); 778 gins(AMOVHS, f, &nod); 779 gins(AMOVWF, &nod, t); 780 regfree(&nod); 781 return; 782 case TUINT: 783 case TINT: 784 case TULONG: 785 case TLONG: 786 case TIND: 787 a = AMOVHS; 788 break; 789 case TSHORT: 790 case TUSHORT: 791 case TCHAR: 792 case TUCHAR: 793 a = AMOVW; 794 break; 795 } 796 break; 797 case TUSHORT: 798 switch(tt) { 799 case TDOUBLE: 800 regalloc(&nod, f, Z); 801 gins(AMOVHU, f, &nod); 802 gins(AMOVWD, &nod, t); 803 regfree(&nod); 804 return; 805 case TFLOAT: 806 regalloc(&nod, f, Z); 807 gins(AMOVHU, f, &nod); 808 gins(AMOVWF, &nod, t); 809 regfree(&nod); 810 return; 811 case TINT: 812 case TUINT: 813 case TLONG: 814 case TULONG: 815 case TIND: 816 a = AMOVHU; 817 break; 818 case TSHORT: 819 case TUSHORT: 820 case TCHAR: 821 case TUCHAR: 822 a = AMOVW; 823 break; 824 } 825 break; 826 case TCHAR: 827 switch(tt) { 828 case TDOUBLE: 829 regalloc(&nod, f, Z); 830 gins(AMOVBS, f, &nod); 831 gins(AMOVWD, &nod, t); 832 regfree(&nod); 833 return; 834 case TFLOAT: 835 regalloc(&nod, f, Z); 836 gins(AMOVBS, f, &nod); 837 gins(AMOVWF, &nod, t); 838 regfree(&nod); 839 return; 840 case TINT: 841 case TUINT: 842 case TLONG: 843 case TULONG: 844 case TIND: 845 case TSHORT: 846 case TUSHORT: 847 a = AMOVBS; 848 break; 849 case TCHAR: 850 case TUCHAR: 851 a = AMOVW; 852 break; 853 } 854 break; 855 case TUCHAR: 856 switch(tt) { 857 case TDOUBLE: 858 regalloc(&nod, f, Z); 859 gins(AMOVBU, f, &nod); 860 gins(AMOVWD, &nod, t); 861 regfree(&nod); 862 return; 863 case TFLOAT: 864 regalloc(&nod, f, Z); 865 gins(AMOVBU, f, &nod); 866 gins(AMOVWF, &nod, t); 867 regfree(&nod); 868 return; 869 case TINT: 870 case TUINT: 871 case TLONG: 872 case TULONG: 873 case TIND: 874 case TSHORT: 875 case TUSHORT: 876 a = AMOVBU; 877 break; 878 case TCHAR: 879 case TUCHAR: 880 a = AMOVW; 881 break; 882 } 883 break; 884 } 885 if(a == AGOK) 886 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type); 887 if(a == AMOVW || a == AMOVF || a == AMOVD) 888 if(samaddr(f, t)) 889 return; 890 gins(a, f, t); 891 } 892 893 void 894 gmover(Node *f, Node *t) 895 { 896 int ft, tt, a; 897 898 ft = f->type->etype; 899 tt = t->type->etype; 900 a = AGOK; 901 if(typechlp[ft] && typechlp[tt] && ewidth[ft] >= ewidth[tt]){ 902 switch(tt){ 903 case TSHORT: 904 a = AMOVHS; 905 break; 906 case TUSHORT: 907 a = AMOVHU; 908 break; 909 case TCHAR: 910 a = AMOVBS; 911 break; 912 case TUCHAR: 913 a = AMOVBU; 914 break; 915 } 916 } 917 if(a == AGOK) 918 gmove(f, t); 919 else 920 gins(a, f, t); 921 } 922 923 void 924 gins(int a, Node *f, Node *t) 925 { 926 927 nextpc(); 928 p->as = a; 929 if(f != Z) 930 naddr(f, &p->from); 931 if(t != Z) 932 naddr(t, &p->to); 933 if(debug['g']) 934 print("%P\n", p); 935 } 936 937 void 938 gopcode(int o, Node *f1, Node *f2, Node *t) 939 { 940 int a, et; 941 Addr ta; 942 943 et = TLONG; 944 if(f1 != Z && f1->type != T) 945 et = f1->type->etype; 946 a = AGOK; 947 switch(o) { 948 case OAS: 949 gmove(f1, t); 950 return; 951 952 case OASADD: 953 case OADD: 954 a = AADD; 955 if(et == TFLOAT) 956 a = AADDF; 957 else 958 if(et == TDOUBLE || et == TVLONG) 959 a = AADDD; 960 break; 961 962 case OASSUB: 963 case OSUB: 964 if(f2 && f2->op == OCONST) { 965 Node *t = f1; 966 f1 = f2; 967 f2 = t; 968 a = ARSB; 969 } else 970 a = ASUB; 971 if(et == TFLOAT) 972 a = ASUBF; 973 else 974 if(et == TDOUBLE || et == TVLONG) 975 a = ASUBD; 976 break; 977 978 case OASOR: 979 case OOR: 980 a = AORR; 981 break; 982 983 case OASAND: 984 case OAND: 985 a = AAND; 986 break; 987 988 case OASXOR: 989 case OXOR: 990 a = AEOR; 991 break; 992 993 case OASLSHR: 994 case OLSHR: 995 a = ASRL; 996 break; 997 998 case OASASHR: 999 case OASHR: 1000 a = ASRA; 1001 break; 1002 1003 case OASASHL: 1004 case OASHL: 1005 a = ASLL; 1006 break; 1007 1008 case OFUNC: 1009 a = ABL; 1010 break; 1011 1012 case OASMUL: 1013 case OMUL: 1014 a = AMUL; 1015 if(et == TFLOAT) 1016 a = AMULF; 1017 else 1018 if(et == TDOUBLE || et == TVLONG) 1019 a = AMULD; 1020 break; 1021 1022 case OASDIV: 1023 case ODIV: 1024 a = ADIV; 1025 if(et == TFLOAT) 1026 a = ADIVF; 1027 else 1028 if(et == TDOUBLE || et == TVLONG) 1029 a = ADIVD; 1030 break; 1031 1032 case OASMOD: 1033 case OMOD: 1034 a = AMOD; 1035 break; 1036 1037 case OASLMUL: 1038 case OLMUL: 1039 a = AMULU; 1040 break; 1041 1042 case OASLMOD: 1043 case OLMOD: 1044 a = AMODU; 1045 break; 1046 1047 case OASLDIV: 1048 case OLDIV: 1049 a = ADIVU; 1050 break; 1051 1052 case OCASE: 1053 case OEQ: 1054 case ONE: 1055 case OLT: 1056 case OLE: 1057 case OGE: 1058 case OGT: 1059 case OLO: 1060 case OLS: 1061 case OHS: 1062 case OHI: 1063 a = ACMP; 1064 if(et == TFLOAT) 1065 a = ACMPF; 1066 else 1067 if(et == TDOUBLE || et == TVLONG) 1068 a = ACMPD; 1069 nextpc(); 1070 p->as = a; 1071 naddr(f1, &p->from); 1072 if(a == ACMP && f1->op == OCONST && p->from.offset < 0) { 1073 p->as = ACMN; 1074 p->from.offset = -p->from.offset; 1075 } 1076 raddr(f2, p); 1077 switch(o) { 1078 case OEQ: 1079 a = ABEQ; 1080 break; 1081 case ONE: 1082 a = ABNE; 1083 break; 1084 case OLT: 1085 a = ABLT; 1086 break; 1087 case OLE: 1088 a = ABLE; 1089 break; 1090 case OGE: 1091 a = ABGE; 1092 break; 1093 case OGT: 1094 a = ABGT; 1095 break; 1096 case OLO: 1097 a = ABLO; 1098 break; 1099 case OLS: 1100 a = ABLS; 1101 break; 1102 case OHS: 1103 a = ABHS; 1104 break; 1105 case OHI: 1106 a = ABHI; 1107 break; 1108 case OCASE: 1109 nextpc(); 1110 p->as = ACASE; 1111 p->scond = 0x9; 1112 naddr(f2, &p->from); 1113 a = ABHI; 1114 break; 1115 } 1116 f1 = Z; 1117 f2 = Z; 1118 break; 1119 } 1120 if(a == AGOK) 1121 diag(Z, "bad in gopcode %O", o); 1122 nextpc(); 1123 p->as = a; 1124 if(f1 != Z) 1125 naddr(f1, &p->from); 1126 if(f2 != Z) { 1127 naddr(f2, &ta); 1128 p->reg = ta.reg; 1129 } 1130 if(t != Z) 1131 naddr(t, &p->to); 1132 if(debug['g']) 1133 print("%P\n", p); 1134 } 1135 1136 int 1137 samaddr(Node *f, Node *t) 1138 { 1139 1140 if(f->op != t->op) 1141 return 0; 1142 switch(f->op) { 1143 1144 case OREGISTER: 1145 if(f->reg != t->reg) 1146 break; 1147 return 1; 1148 } 1149 return 0; 1150 } 1151 1152 void 1153 gbranch(int o) 1154 { 1155 int a; 1156 1157 a = AGOK; 1158 switch(o) { 1159 case ORETURN: 1160 a = ARET; 1161 break; 1162 case OGOTO: 1163 a = AB; 1164 break; 1165 } 1166 nextpc(); 1167 if(a == AGOK) { 1168 diag(Z, "bad in gbranch %O", o); 1169 nextpc(); 1170 } 1171 p->as = a; 1172 } 1173 1174 void 1175 patch(Prog *op, int32 pc) 1176 { 1177 1178 op->to.offset = pc; 1179 op->to.type = D_BRANCH; 1180 } 1181 1182 void 1183 gpseudo(int a, Sym *s, Node *n) 1184 { 1185 nextpc(); 1186 p->as = a; 1187 p->from.type = D_OREG; 1188 p->from.sym = linksym(s); 1189 p->from.name = D_EXTERN; 1190 1191 switch(a) { 1192 case ATEXT: 1193 p->reg = textflag; 1194 textflag = 0; 1195 break; 1196 case AGLOBL: 1197 p->reg = s->dataflag; 1198 break; 1199 } 1200 1201 if(s->class == CSTATIC) 1202 p->from.name = D_STATIC; 1203 naddr(n, &p->to); 1204 if(a == ADATA || a == AGLOBL) 1205 pc--; 1206 } 1207 1208 void 1209 gpcdata(int index, int value) 1210 { 1211 Node n1; 1212 1213 n1 = *nodconst(index); 1214 gins(APCDATA, &n1, nodconst(value)); 1215 } 1216 1217 void 1218 gprefetch(Node *n) 1219 { 1220 Node n1; 1221 1222 regalloc(&n1, n, Z); 1223 gmove(n, &n1); 1224 n1.op = OINDREG; 1225 gins(APLD, &n1, Z); 1226 regfree(&n1); 1227 } 1228 1229 int 1230 sconst(Node *n) 1231 { 1232 vlong vv; 1233 1234 if(n->op == OCONST) { 1235 if(!typefd[n->type->etype]) { 1236 vv = n->vconst; 1237 if(vv >= (vlong)(-32766) && vv < (vlong)32766) 1238 return 1; 1239 /* 1240 * should be specialised for constant values which will 1241 * fit in different instructionsl; for now, let 5l 1242 * sort it out 1243 */ 1244 return 1; 1245 } 1246 } 1247 return 0; 1248 } 1249 1250 int 1251 sval(int32 v) 1252 { 1253 int i; 1254 1255 for(i=0; i<16; i++) { 1256 if((v & ~0xff) == 0) 1257 return 1; 1258 if((~v & ~0xff) == 0) 1259 return 1; 1260 v = (v<<2) | ((uint32)v>>30); 1261 } 1262 return 0; 1263 } 1264 1265 int32 1266 exreg(Type *t) 1267 { 1268 int32 o; 1269 1270 if(typechlp[t->etype]) { 1271 if(exregoffset <= REGEXT-4) 1272 return 0; 1273 o = exregoffset; 1274 exregoffset--; 1275 return o; 1276 } 1277 if(typefd[t->etype]) { 1278 if(exfregoffset <= NFREG-1) 1279 return 0; 1280 o = exfregoffset + NREG; 1281 exfregoffset--; 1282 return o; 1283 } 1284 return 0; 1285 } 1286 1287 schar ewidth[NTYPE] = 1288 { 1289 -1, /* [TXXX] */ 1290 SZ_CHAR, /* [TCHAR] */ 1291 SZ_CHAR, /* [TUCHAR] */ 1292 SZ_SHORT, /* [TSHORT] */ 1293 SZ_SHORT, /* [TUSHORT] */ 1294 SZ_INT, /* [TINT] */ 1295 SZ_INT, /* [TUINT] */ 1296 SZ_LONG, /* [TLONG] */ 1297 SZ_LONG, /* [TULONG] */ 1298 SZ_VLONG, /* [TVLONG] */ 1299 SZ_VLONG, /* [TUVLONG] */ 1300 SZ_FLOAT, /* [TFLOAT] */ 1301 SZ_DOUBLE, /* [TDOUBLE] */ 1302 SZ_IND, /* [TIND] */ 1303 0, /* [TFUNC] */ 1304 -1, /* [TARRAY] */ 1305 0, /* [TVOID] */ 1306 -1, /* [TSTRUCT] */ 1307 -1, /* [TUNION] */ 1308 SZ_INT, /* [TENUM] */ 1309 }; 1310 1311 int32 ncast[NTYPE] = 1312 { 1313 0, /* [TXXX] */ 1314 BCHAR|BUCHAR, /* [TCHAR] */ 1315 BCHAR|BUCHAR, /* [TUCHAR] */ 1316 BSHORT|BUSHORT, /* [TSHORT] */ 1317 BSHORT|BUSHORT, /* [TUSHORT] */ 1318 BINT|BUINT|BLONG|BULONG|BIND, /* [TINT] */ 1319 BINT|BUINT|BLONG|BULONG|BIND, /* [TUINT] */ 1320 BINT|BUINT|BLONG|BULONG|BIND, /* [TLONG] */ 1321 BINT|BUINT|BLONG|BULONG|BIND, /* [TULONG] */ 1322 BVLONG|BUVLONG, /* [TVLONG] */ 1323 BVLONG|BUVLONG, /* [TUVLONG] */ 1324 BFLOAT, /* [TFLOAT] */ 1325 BDOUBLE, /* [TDOUBLE] */ 1326 BLONG|BULONG|BIND, /* [TIND] */ 1327 0, /* [TFUNC] */ 1328 0, /* [TARRAY] */ 1329 0, /* [TVOID] */ 1330 BSTRUCT, /* [TSTRUCT] */ 1331 BUNION, /* [TUNION] */ 1332 0, /* [TENUM] */ 1333 };