github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/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, Type *t, int mode) 278 { 279 int r; 280 281 if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) { 282 r = REGRET; 283 if(typefd[nn->type->etype]) 284 r = FREGRET+NREG; 285 nodreg(n, nn, r); 286 reg[r]++; 287 return; 288 } 289 290 if(mode == 1) { 291 // fetch returned value after call. 292 // already called gargs, so curarg is set. 293 curarg = (curarg+3) & ~3; 294 regaalloc(n, nn); 295 return; 296 } 297 298 if(mode == 2) { 299 // store value to be returned. 300 // must compute arg offset. 301 if(t->etype != TFUNC) 302 fatal(Z, "bad regret func %T", t); 303 *n = *nn; 304 n->op = ONAME; 305 n->class = CPARAM; 306 n->sym = slookup(".ret"); 307 n->complex = nodret->complex; 308 n->xoffset = argsize(0); 309 n->addable = 20; 310 return; 311 } 312 313 fatal(Z, "bad regret"); 314 } 315 316 int 317 tmpreg(void) 318 { 319 int i; 320 321 for(i=REGRET+1; i<NREG; i++) 322 if(reg[i] == 0) 323 return i; 324 diag(Z, "out of fixed registers"); 325 return 0; 326 } 327 328 void 329 regalloc(Node *n, Node *tn, Node *o) 330 { 331 int i; 332 333 switch(tn->type->etype) { 334 case TCHAR: 335 case TUCHAR: 336 case TSHORT: 337 case TUSHORT: 338 case TINT: 339 case TUINT: 340 case TLONG: 341 case TULONG: 342 case TIND: 343 if(o != Z && o->op == OREGISTER) { 344 i = o->reg; 345 if(i >= 0 && i < NREG) 346 goto out; 347 } 348 for(i=REGRET+1; i<=REGEXT-2; i++) 349 if(reg[i] == 0) 350 goto out; 351 diag(tn, "out of fixed registers"); 352 goto err; 353 354 case TFLOAT: 355 case TDOUBLE: 356 case TVLONG: 357 if(o != Z && o->op == OREGISTER) { 358 i = o->reg; 359 if(i >= NREG && i < NREG+NFREG) 360 goto out; 361 } 362 for(i=NREG; i<NREG+NFREG; i++) 363 if(reg[i] == 0) 364 goto out; 365 diag(tn, "out of float registers"); 366 goto err; 367 } 368 diag(tn, "unknown type in regalloc: %T", tn->type); 369 err: 370 nodreg(n, tn, 0); 371 return; 372 out: 373 reg[i]++; 374 nodreg(n, tn, i); 375 } 376 377 void 378 regialloc(Node *n, Node *tn, Node *o) 379 { 380 Node nod; 381 382 nod = *tn; 383 nod.type = types[TIND]; 384 regalloc(n, &nod, o); 385 } 386 387 void 388 regfree(Node *n) 389 { 390 int i; 391 392 i = 0; 393 if(n->op != OREGISTER && n->op != OINDREG) 394 goto err; 395 i = n->reg; 396 if(i < 0 || i >= nelem(reg)) 397 goto err; 398 if(reg[i] <= 0) 399 goto err; 400 reg[i]--; 401 return; 402 err: 403 diag(n, "error in regfree: %d", i); 404 } 405 406 void 407 regsalloc(Node *n, Node *nn) 408 { 409 cursafe = align(cursafe, nn->type, Aaut3, nil); 410 maxargsafe = maxround(maxargsafe, cursafe+curarg); 411 *n = *nodsafe; 412 n->xoffset = -(stkoff + cursafe); 413 n->type = nn->type; 414 n->etype = nn->type->etype; 415 n->lineno = nn->lineno; 416 } 417 418 void 419 regaalloc1(Node *n, Node *nn) 420 { 421 if(REGARG < 0) { 422 fatal(n, "regaalloc1 and REGARG<0"); 423 return; 424 } 425 nodreg(n, nn, REGARG); 426 reg[REGARG]++; 427 curarg = align(curarg, nn->type, Aarg1, nil); 428 curarg = align(curarg, nn->type, Aarg2, nil); 429 maxargsafe = maxround(maxargsafe, cursafe+curarg); 430 } 431 432 void 433 regaalloc(Node *n, Node *nn) 434 { 435 curarg = align(curarg, nn->type, Aarg1, nil); 436 *n = *nn; 437 n->op = OINDREG; 438 n->reg = REGSP; 439 n->xoffset = curarg + SZ_LONG; 440 n->complex = 0; 441 n->addable = 20; 442 curarg = align(curarg, nn->type, Aarg2, nil); 443 maxargsafe = maxround(maxargsafe, cursafe+curarg); 444 } 445 446 void 447 regind(Node *n, Node *nn) 448 { 449 450 if(n->op != OREGISTER) { 451 diag(n, "regind not OREGISTER"); 452 return; 453 } 454 n->op = OINDREG; 455 n->type = nn->type; 456 } 457 458 void 459 raddr(Node *n, Prog *p) 460 { 461 Addr a; 462 463 naddr(n, &a); 464 if(R0ISZERO && a.type == D_CONST && a.offset == 0) { 465 a.type = D_REG; 466 a.reg = 0; 467 } 468 if(a.type != D_REG && a.type != D_FREG) { 469 if(n) 470 diag(n, "bad in raddr: %O", n->op); 471 else 472 diag(n, "bad in raddr: <null>"); 473 p->reg = NREG; 474 } else 475 p->reg = a.reg; 476 } 477 478 void 479 naddr(Node *n, Addr *a) 480 { 481 int32 v; 482 483 a->type = D_NONE; 484 if(n == Z) 485 return; 486 switch(n->op) { 487 default: 488 bad: 489 diag(n, "bad in naddr: %O", n->op); 490 break; 491 492 case OREGISTER: 493 a->type = D_REG; 494 a->sym = nil; 495 a->reg = n->reg; 496 if(a->reg >= NREG) { 497 a->type = D_FREG; 498 a->reg -= NREG; 499 } 500 break; 501 502 case OIND: 503 naddr(n->left, a); 504 if(a->type == D_REG) { 505 a->type = D_OREG; 506 break; 507 } 508 if(a->type == D_CONST) { 509 a->type = D_OREG; 510 break; 511 } 512 goto bad; 513 514 case OINDREG: 515 a->type = D_OREG; 516 a->sym = nil; 517 a->offset = n->xoffset; 518 a->reg = n->reg; 519 break; 520 521 case ONAME: 522 a->etype = n->etype; 523 a->type = D_OREG; 524 a->name = D_STATIC; 525 a->sym = linksym(n->sym); 526 a->offset = n->xoffset; 527 if(n->class == CSTATIC) 528 break; 529 if(n->class == CEXTERN || n->class == CGLOBL) { 530 a->name = D_EXTERN; 531 break; 532 } 533 if(n->class == CAUTO) { 534 a->name = D_AUTO; 535 break; 536 } 537 if(n->class == CPARAM) { 538 a->name = D_PARAM; 539 break; 540 } 541 goto bad; 542 543 case OCONST: 544 a->sym = nil; 545 a->reg = NREG; 546 if(typefd[n->type->etype]) { 547 a->type = D_FCONST; 548 a->u.dval = n->fconst; 549 } else { 550 a->type = D_CONST; 551 a->offset = n->vconst; 552 } 553 break; 554 555 case OADDR: 556 naddr(n->left, a); 557 if(a->type == D_OREG) { 558 a->type = D_CONST; 559 break; 560 } 561 goto bad; 562 563 case OADD: 564 if(n->left->op == OCONST) { 565 naddr(n->left, a); 566 v = a->offset; 567 naddr(n->right, a); 568 } else { 569 naddr(n->right, a); 570 v = a->offset; 571 naddr(n->left, a); 572 } 573 a->offset += v; 574 break; 575 576 } 577 } 578 579 void 580 fop(int as, int f1, int f2, Node *t) 581 { 582 Node nod1, nod2, nod3; 583 584 nodreg(&nod1, t, NREG+f1); 585 nodreg(&nod2, t, NREG+f2); 586 regalloc(&nod3, t, t); 587 gopcode(as, &nod1, &nod2, &nod3); 588 gmove(&nod3, t); 589 regfree(&nod3); 590 } 591 592 void 593 gmovm(Node *f, Node *t, int w) 594 { 595 gins(AMOVM, f, t); 596 p->scond |= C_UBIT; 597 if(w) 598 p->scond |= C_WBIT; 599 } 600 601 void 602 gmove(Node *f, Node *t) 603 { 604 int ft, tt, a; 605 Node nod, nod1; 606 Prog *p1; 607 608 ft = f->type->etype; 609 tt = t->type->etype; 610 611 if(ft == TDOUBLE && f->op == OCONST) { 612 } 613 if(ft == TFLOAT && f->op == OCONST) { 614 } 615 616 /* 617 * a load -- 618 * put it into a register then 619 * worry what to do with it. 620 */ 621 if(f->op == ONAME || f->op == OINDREG || f->op == OIND) { 622 switch(ft) { 623 default: 624 a = AMOVW; 625 break; 626 case TFLOAT: 627 a = AMOVF; 628 break; 629 case TDOUBLE: 630 a = AMOVD; 631 break; 632 case TCHAR: 633 a = AMOVBS; 634 break; 635 case TUCHAR: 636 a = AMOVBU; 637 break; 638 case TSHORT: 639 a = AMOVHS; 640 break; 641 case TUSHORT: 642 a = AMOVHU; 643 break; 644 } 645 if(typechlp[ft] && typeilp[tt]) 646 regalloc(&nod, t, t); 647 else 648 regalloc(&nod, f, t); 649 gins(a, f, &nod); 650 gmove(&nod, t); 651 regfree(&nod); 652 return; 653 } 654 655 /* 656 * a store -- 657 * put it into a register then 658 * store it. 659 */ 660 if(t->op == ONAME || t->op == OINDREG || t->op == OIND) { 661 switch(tt) { 662 default: 663 a = AMOVW; 664 break; 665 case TUCHAR: 666 a = AMOVBU; 667 break; 668 case TCHAR: 669 a = AMOVBS; 670 break; 671 case TUSHORT: 672 a = AMOVHU; 673 break; 674 case TSHORT: 675 a = AMOVHS; 676 break; 677 case TFLOAT: 678 a = AMOVF; 679 break; 680 case TVLONG: 681 case TDOUBLE: 682 a = AMOVD; 683 break; 684 } 685 if(ft == tt) 686 regalloc(&nod, t, f); 687 else 688 regalloc(&nod, t, Z); 689 gmove(f, &nod); 690 gins(a, &nod, t); 691 regfree(&nod); 692 return; 693 } 694 695 /* 696 * type x type cross table 697 */ 698 a = AGOK; 699 switch(ft) { 700 case TDOUBLE: 701 case TVLONG: 702 case TFLOAT: 703 switch(tt) { 704 case TDOUBLE: 705 case TVLONG: 706 a = AMOVD; 707 if(ft == TFLOAT) 708 a = AMOVFD; 709 break; 710 case TFLOAT: 711 a = AMOVDF; 712 if(ft == TFLOAT) 713 a = AMOVF; 714 break; 715 case TINT: 716 case TUINT: 717 case TLONG: 718 case TULONG: 719 case TIND: 720 a = AMOVDW; 721 if(ft == TFLOAT) 722 a = AMOVFW; 723 break; 724 case TSHORT: 725 case TUSHORT: 726 case TCHAR: 727 case TUCHAR: 728 a = AMOVDW; 729 if(ft == TFLOAT) 730 a = AMOVFW; 731 break; 732 } 733 break; 734 case TUINT: 735 case TULONG: 736 if(tt == TFLOAT || tt == TDOUBLE) { 737 // ugly and probably longer than necessary, 738 // but vfp has a single instruction for this, 739 // so hopefully it won't last long. 740 // 741 // tmp = f 742 // tmp1 = tmp & 0x80000000 743 // tmp ^= tmp1 744 // t = float(int32(tmp)) 745 // if(tmp1) 746 // t += 2147483648. 747 // 748 regalloc(&nod, f, Z); 749 regalloc(&nod1, f, Z); 750 gins(AMOVW, f, &nod); 751 gins(AMOVW, &nod, &nod1); 752 gins(AAND, nodconst(0x80000000), &nod1); 753 gins(AEOR, &nod1, &nod); 754 if(tt == TFLOAT) 755 gins(AMOVWF, &nod, t); 756 else 757 gins(AMOVWD, &nod, t); 758 gins(ACMP, nodconst(0), Z); 759 raddr(&nod1, p); 760 gins(ABEQ, Z, Z); 761 regfree(&nod); 762 regfree(&nod1); 763 p1 = p; 764 regalloc(&nod, t, Z); 765 gins(AMOVF, nodfconst(2147483648.), &nod); 766 gins(AADDF, &nod, t); 767 regfree(&nod); 768 patch(p1, pc); 769 return; 770 } 771 // fall through 772 773 case TINT: 774 case TLONG: 775 case TIND: 776 switch(tt) { 777 case TDOUBLE: 778 gins(AMOVWD, f, t); 779 return; 780 case TFLOAT: 781 gins(AMOVWF, f, t); 782 return; 783 case TINT: 784 case TUINT: 785 case TLONG: 786 case TULONG: 787 case TIND: 788 case TSHORT: 789 case TUSHORT: 790 case TCHAR: 791 case TUCHAR: 792 a = AMOVW; 793 break; 794 } 795 break; 796 case TSHORT: 797 switch(tt) { 798 case TDOUBLE: 799 regalloc(&nod, f, Z); 800 gins(AMOVHS, f, &nod); 801 gins(AMOVWD, &nod, t); 802 regfree(&nod); 803 return; 804 case TFLOAT: 805 regalloc(&nod, f, Z); 806 gins(AMOVHS, f, &nod); 807 gins(AMOVWF, &nod, t); 808 regfree(&nod); 809 return; 810 case TUINT: 811 case TINT: 812 case TULONG: 813 case TLONG: 814 case TIND: 815 a = AMOVHS; 816 break; 817 case TSHORT: 818 case TUSHORT: 819 case TCHAR: 820 case TUCHAR: 821 a = AMOVW; 822 break; 823 } 824 break; 825 case TUSHORT: 826 switch(tt) { 827 case TDOUBLE: 828 regalloc(&nod, f, Z); 829 gins(AMOVHU, f, &nod); 830 gins(AMOVWD, &nod, t); 831 regfree(&nod); 832 return; 833 case TFLOAT: 834 regalloc(&nod, f, Z); 835 gins(AMOVHU, f, &nod); 836 gins(AMOVWF, &nod, t); 837 regfree(&nod); 838 return; 839 case TINT: 840 case TUINT: 841 case TLONG: 842 case TULONG: 843 case TIND: 844 a = AMOVHU; 845 break; 846 case TSHORT: 847 case TUSHORT: 848 case TCHAR: 849 case TUCHAR: 850 a = AMOVW; 851 break; 852 } 853 break; 854 case TCHAR: 855 switch(tt) { 856 case TDOUBLE: 857 regalloc(&nod, f, Z); 858 gins(AMOVBS, f, &nod); 859 gins(AMOVWD, &nod, t); 860 regfree(&nod); 861 return; 862 case TFLOAT: 863 regalloc(&nod, f, Z); 864 gins(AMOVBS, f, &nod); 865 gins(AMOVWF, &nod, t); 866 regfree(&nod); 867 return; 868 case TINT: 869 case TUINT: 870 case TLONG: 871 case TULONG: 872 case TIND: 873 case TSHORT: 874 case TUSHORT: 875 a = AMOVBS; 876 break; 877 case TCHAR: 878 case TUCHAR: 879 a = AMOVW; 880 break; 881 } 882 break; 883 case TUCHAR: 884 switch(tt) { 885 case TDOUBLE: 886 regalloc(&nod, f, Z); 887 gins(AMOVBU, f, &nod); 888 gins(AMOVWD, &nod, t); 889 regfree(&nod); 890 return; 891 case TFLOAT: 892 regalloc(&nod, f, Z); 893 gins(AMOVBU, f, &nod); 894 gins(AMOVWF, &nod, t); 895 regfree(&nod); 896 return; 897 case TINT: 898 case TUINT: 899 case TLONG: 900 case TULONG: 901 case TIND: 902 case TSHORT: 903 case TUSHORT: 904 a = AMOVBU; 905 break; 906 case TCHAR: 907 case TUCHAR: 908 a = AMOVW; 909 break; 910 } 911 break; 912 } 913 if(a == AGOK) 914 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type); 915 if(a == AMOVW || a == AMOVF || a == AMOVD) 916 if(samaddr(f, t)) 917 return; 918 gins(a, f, t); 919 } 920 921 void 922 gmover(Node *f, Node *t) 923 { 924 int ft, tt, a; 925 926 ft = f->type->etype; 927 tt = t->type->etype; 928 a = AGOK; 929 if(typechlp[ft] && typechlp[tt] && ewidth[ft] >= ewidth[tt]){ 930 switch(tt){ 931 case TSHORT: 932 a = AMOVHS; 933 break; 934 case TUSHORT: 935 a = AMOVHU; 936 break; 937 case TCHAR: 938 a = AMOVBS; 939 break; 940 case TUCHAR: 941 a = AMOVBU; 942 break; 943 } 944 } 945 if(a == AGOK) 946 gmove(f, t); 947 else 948 gins(a, f, t); 949 } 950 951 void 952 gins(int a, Node *f, Node *t) 953 { 954 955 nextpc(); 956 p->as = a; 957 if(f != Z) 958 naddr(f, &p->from); 959 if(t != Z) 960 naddr(t, &p->to); 961 if(debug['g']) 962 print("%P\n", p); 963 } 964 965 void 966 gopcode(int o, Node *f1, Node *f2, Node *t) 967 { 968 int a, et; 969 Addr ta; 970 971 et = TLONG; 972 if(f1 != Z && f1->type != T) 973 et = f1->type->etype; 974 a = AGOK; 975 switch(o) { 976 case OAS: 977 gmove(f1, t); 978 return; 979 980 case OASADD: 981 case OADD: 982 a = AADD; 983 if(et == TFLOAT) 984 a = AADDF; 985 else 986 if(et == TDOUBLE || et == TVLONG) 987 a = AADDD; 988 break; 989 990 case OASSUB: 991 case OSUB: 992 if(f2 && f2->op == OCONST) { 993 Node *t = f1; 994 f1 = f2; 995 f2 = t; 996 a = ARSB; 997 } else 998 a = ASUB; 999 if(et == TFLOAT) 1000 a = ASUBF; 1001 else 1002 if(et == TDOUBLE || et == TVLONG) 1003 a = ASUBD; 1004 break; 1005 1006 case OASOR: 1007 case OOR: 1008 a = AORR; 1009 break; 1010 1011 case OASAND: 1012 case OAND: 1013 a = AAND; 1014 break; 1015 1016 case OASXOR: 1017 case OXOR: 1018 a = AEOR; 1019 break; 1020 1021 case OASLSHR: 1022 case OLSHR: 1023 a = ASRL; 1024 break; 1025 1026 case OASASHR: 1027 case OASHR: 1028 a = ASRA; 1029 break; 1030 1031 case OASASHL: 1032 case OASHL: 1033 a = ASLL; 1034 break; 1035 1036 case OFUNC: 1037 a = ABL; 1038 break; 1039 1040 case OASMUL: 1041 case OMUL: 1042 a = AMUL; 1043 if(et == TFLOAT) 1044 a = AMULF; 1045 else 1046 if(et == TDOUBLE || et == TVLONG) 1047 a = AMULD; 1048 break; 1049 1050 case OASDIV: 1051 case ODIV: 1052 a = ADIV; 1053 if(et == TFLOAT) 1054 a = ADIVF; 1055 else 1056 if(et == TDOUBLE || et == TVLONG) 1057 a = ADIVD; 1058 break; 1059 1060 case OASMOD: 1061 case OMOD: 1062 a = AMOD; 1063 break; 1064 1065 case OASLMUL: 1066 case OLMUL: 1067 a = AMULU; 1068 break; 1069 1070 case OASLMOD: 1071 case OLMOD: 1072 a = AMODU; 1073 break; 1074 1075 case OASLDIV: 1076 case OLDIV: 1077 a = ADIVU; 1078 break; 1079 1080 case OCASE: 1081 case OEQ: 1082 case ONE: 1083 case OLT: 1084 case OLE: 1085 case OGE: 1086 case OGT: 1087 case OLO: 1088 case OLS: 1089 case OHS: 1090 case OHI: 1091 a = ACMP; 1092 if(et == TFLOAT) 1093 a = ACMPF; 1094 else 1095 if(et == TDOUBLE || et == TVLONG) 1096 a = ACMPD; 1097 nextpc(); 1098 p->as = a; 1099 naddr(f1, &p->from); 1100 if(a == ACMP && f1->op == OCONST && p->from.offset < 0) { 1101 p->as = ACMN; 1102 p->from.offset = -p->from.offset; 1103 } 1104 raddr(f2, p); 1105 switch(o) { 1106 case OEQ: 1107 a = ABEQ; 1108 break; 1109 case ONE: 1110 a = ABNE; 1111 break; 1112 case OLT: 1113 a = ABLT; 1114 break; 1115 case OLE: 1116 a = ABLE; 1117 break; 1118 case OGE: 1119 a = ABGE; 1120 break; 1121 case OGT: 1122 a = ABGT; 1123 break; 1124 case OLO: 1125 a = ABLO; 1126 break; 1127 case OLS: 1128 a = ABLS; 1129 break; 1130 case OHS: 1131 a = ABHS; 1132 break; 1133 case OHI: 1134 a = ABHI; 1135 break; 1136 case OCASE: 1137 nextpc(); 1138 p->as = ACASE; 1139 p->scond = 0x9; 1140 naddr(f2, &p->from); 1141 a = ABHI; 1142 break; 1143 } 1144 f1 = Z; 1145 f2 = Z; 1146 break; 1147 } 1148 if(a == AGOK) 1149 diag(Z, "bad in gopcode %O", o); 1150 nextpc(); 1151 p->as = a; 1152 if(f1 != Z) 1153 naddr(f1, &p->from); 1154 if(f2 != Z) { 1155 naddr(f2, &ta); 1156 p->reg = ta.reg; 1157 } 1158 if(t != Z) 1159 naddr(t, &p->to); 1160 if(debug['g']) 1161 print("%P\n", p); 1162 } 1163 1164 int 1165 samaddr(Node *f, Node *t) 1166 { 1167 1168 if(f->op != t->op) 1169 return 0; 1170 switch(f->op) { 1171 1172 case OREGISTER: 1173 if(f->reg != t->reg) 1174 break; 1175 return 1; 1176 } 1177 return 0; 1178 } 1179 1180 void 1181 gbranch(int o) 1182 { 1183 int a; 1184 1185 a = AGOK; 1186 switch(o) { 1187 case ORETURN: 1188 a = ARET; 1189 break; 1190 case OGOTO: 1191 a = AB; 1192 break; 1193 } 1194 nextpc(); 1195 if(a == AGOK) { 1196 diag(Z, "bad in gbranch %O", o); 1197 nextpc(); 1198 } 1199 p->as = a; 1200 } 1201 1202 void 1203 patch(Prog *op, int32 pc) 1204 { 1205 1206 op->to.offset = pc; 1207 op->to.type = D_BRANCH; 1208 } 1209 1210 void 1211 gpseudo(int a, Sym *s, Node *n) 1212 { 1213 nextpc(); 1214 p->as = a; 1215 p->from.type = D_OREG; 1216 p->from.sym = linksym(s); 1217 p->from.name = D_EXTERN; 1218 1219 switch(a) { 1220 case ATEXT: 1221 p->reg = textflag; 1222 textflag = 0; 1223 break; 1224 case AGLOBL: 1225 p->reg = s->dataflag; 1226 break; 1227 } 1228 1229 if(s->class == CSTATIC) 1230 p->from.name = D_STATIC; 1231 naddr(n, &p->to); 1232 if(a == ADATA || a == AGLOBL) 1233 pc--; 1234 } 1235 1236 void 1237 gpcdata(int index, int value) 1238 { 1239 Node n1; 1240 1241 n1 = *nodconst(index); 1242 gins(APCDATA, &n1, nodconst(value)); 1243 } 1244 1245 void 1246 gprefetch(Node *n) 1247 { 1248 Node n1; 1249 1250 regalloc(&n1, n, Z); 1251 gmove(n, &n1); 1252 n1.op = OINDREG; 1253 gins(APLD, &n1, Z); 1254 regfree(&n1); 1255 } 1256 1257 int 1258 sconst(Node *n) 1259 { 1260 vlong vv; 1261 1262 if(n->op == OCONST) { 1263 if(!typefd[n->type->etype]) { 1264 vv = n->vconst; 1265 if(vv >= (vlong)(-32766) && vv < (vlong)32766) 1266 return 1; 1267 /* 1268 * should be specialised for constant values which will 1269 * fit in different instructionsl; for now, let 5l 1270 * sort it out 1271 */ 1272 return 1; 1273 } 1274 } 1275 return 0; 1276 } 1277 1278 int 1279 sval(int32 v) 1280 { 1281 int i; 1282 1283 for(i=0; i<16; i++) { 1284 if((v & ~0xff) == 0) 1285 return 1; 1286 if((~v & ~0xff) == 0) 1287 return 1; 1288 v = (v<<2) | ((uint32)v>>30); 1289 } 1290 return 0; 1291 } 1292 1293 int32 1294 exreg(Type *t) 1295 { 1296 int32 o; 1297 1298 if(typechlp[t->etype]) { 1299 if(exregoffset <= REGEXT-4) 1300 return 0; 1301 o = exregoffset; 1302 exregoffset--; 1303 return o; 1304 } 1305 if(typefd[t->etype]) { 1306 if(exfregoffset <= NFREG-1) 1307 return 0; 1308 o = exfregoffset + NREG; 1309 exfregoffset--; 1310 return o; 1311 } 1312 return 0; 1313 } 1314 1315 schar ewidth[NTYPE] = 1316 { 1317 -1, /* [TXXX] */ 1318 SZ_CHAR, /* [TCHAR] */ 1319 SZ_CHAR, /* [TUCHAR] */ 1320 SZ_SHORT, /* [TSHORT] */ 1321 SZ_SHORT, /* [TUSHORT] */ 1322 SZ_INT, /* [TINT] */ 1323 SZ_INT, /* [TUINT] */ 1324 SZ_LONG, /* [TLONG] */ 1325 SZ_LONG, /* [TULONG] */ 1326 SZ_VLONG, /* [TVLONG] */ 1327 SZ_VLONG, /* [TUVLONG] */ 1328 SZ_FLOAT, /* [TFLOAT] */ 1329 SZ_DOUBLE, /* [TDOUBLE] */ 1330 SZ_IND, /* [TIND] */ 1331 0, /* [TFUNC] */ 1332 -1, /* [TARRAY] */ 1333 0, /* [TVOID] */ 1334 -1, /* [TSTRUCT] */ 1335 -1, /* [TUNION] */ 1336 SZ_INT, /* [TENUM] */ 1337 }; 1338 1339 int32 ncast[NTYPE] = 1340 { 1341 0, /* [TXXX] */ 1342 BCHAR|BUCHAR, /* [TCHAR] */ 1343 BCHAR|BUCHAR, /* [TUCHAR] */ 1344 BSHORT|BUSHORT, /* [TSHORT] */ 1345 BSHORT|BUSHORT, /* [TUSHORT] */ 1346 BINT|BUINT|BLONG|BULONG|BIND, /* [TINT] */ 1347 BINT|BUINT|BLONG|BULONG|BIND, /* [TUINT] */ 1348 BINT|BUINT|BLONG|BULONG|BIND, /* [TLONG] */ 1349 BINT|BUINT|BLONG|BULONG|BIND, /* [TULONG] */ 1350 BVLONG|BUVLONG, /* [TVLONG] */ 1351 BVLONG|BUVLONG, /* [TUVLONG] */ 1352 BFLOAT, /* [TFLOAT] */ 1353 BDOUBLE, /* [TDOUBLE] */ 1354 BLONG|BULONG|BIND, /* [TIND] */ 1355 0, /* [TFUNC] */ 1356 0, /* [TARRAY] */ 1357 0, /* [TVOID] */ 1358 BSTRUCT, /* [TSTRUCT] */ 1359 BUNION, /* [TUNION] */ 1360 0, /* [TENUM] */ 1361 };