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