github.com/ccccaoqing/test@v0.0.0-20220510085219-3985d23445c0/src/cmd/8c/txt.c (about) 1 // Inferno utils/8c/txt.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8c/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 #include "gc.h" 32 33 34 int thechar = '8'; 35 char *thestring = "386"; 36 37 LinkArch *thelinkarch = &link386; 38 39 void 40 linkarchinit(void) 41 { 42 } 43 44 void 45 ginit(void) 46 { 47 int i; 48 Type *t; 49 50 exregoffset = 0; 51 exfregoffset = 0; 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.from.type = D_NONE; 66 zprog.from.index = D_NONE; 67 zprog.from.scale = 0; 68 zprog.to = zprog.from; 69 70 regnode.op = OREGISTER; 71 regnode.class = CEXREG; 72 regnode.reg = REGTMP; 73 regnode.complex = 0; 74 regnode.addable = 11; 75 regnode.type = types[TLONG]; 76 77 fregnode0 = regnode; 78 fregnode0.reg = D_F0; 79 fregnode0.type = types[TDOUBLE]; 80 81 fregnode1 = fregnode0; 82 fregnode1.reg = D_F0+1; 83 84 constnode.op = OCONST; 85 constnode.class = CXXX; 86 constnode.complex = 0; 87 constnode.addable = 20; 88 constnode.type = types[TLONG]; 89 90 fconstnode.op = OCONST; 91 fconstnode.class = CXXX; 92 fconstnode.complex = 0; 93 fconstnode.addable = 20; 94 fconstnode.type = types[TDOUBLE]; 95 96 nodsafe = new(ONAME, Z, Z); 97 nodsafe->sym = slookup(".safe"); 98 nodsafe->type = types[TINT]; 99 nodsafe->etype = types[TINT]->etype; 100 nodsafe->class = CAUTO; 101 complex(nodsafe); 102 103 t = typ(TARRAY, types[TCHAR]); 104 symrathole = slookup(".rathole"); 105 symrathole->class = CGLOBL; 106 symrathole->type = t; 107 108 nodrat = new(ONAME, Z, Z); 109 nodrat->sym = symrathole; 110 nodrat->type = types[TIND]; 111 nodrat->etype = TVOID; 112 nodrat->class = CGLOBL; 113 complex(nodrat); 114 nodrat->type = t; 115 116 nodret = new(ONAME, Z, Z); 117 nodret->sym = slookup(".ret"); 118 nodret->type = types[TIND]; 119 nodret->etype = TIND; 120 nodret->class = CPARAM; 121 nodret = new(OIND, nodret, Z); 122 complex(nodret); 123 124 com64init(); 125 126 for(i=0; i<nelem(reg); i++) { 127 reg[i] = 1; 128 if(i >= D_AX && i <= D_DI && i != D_SP) 129 reg[i] = 0; 130 } 131 } 132 133 void 134 gclean(void) 135 { 136 int i; 137 Sym *s; 138 139 reg[D_SP]--; 140 for(i=D_AX; i<=D_DI; i++) 141 if(reg[i]) 142 diag(Z, "reg %R left allocated", i); 143 while(mnstring) 144 outstring("", 1L); 145 symstring->type->width = nstring; 146 symrathole->type->width = nrathole; 147 for(i=0; i<NHASH; i++) 148 for(s = hash[i]; s != S; s = s->link) { 149 if(s->type == T) 150 continue; 151 if(s->type->width == 0) 152 continue; 153 if(s->class != CGLOBL && s->class != CSTATIC) 154 continue; 155 if(s->type == types[TENUM]) 156 continue; 157 gpseudo(AGLOBL, s, nodconst(s->type->width)); 158 } 159 nextpc(); 160 p->as = AEND; 161 outcode(); 162 } 163 164 void 165 nextpc(void) 166 { 167 Plist *pl; 168 169 p = alloc(sizeof(*p)); 170 *p = zprog; 171 p->lineno = nearln; 172 p->pc = pc; 173 pc++; 174 if(lastp == nil) { 175 pl = linknewplist(ctxt); 176 pl->firstpc = p; 177 } else 178 lastp->link = p; 179 lastp = p; 180 } 181 182 void 183 gargs(Node *n, Node *tn1, Node *tn2) 184 { 185 int32 regs; 186 Node fnxargs[20], *fnxp; 187 188 regs = cursafe; 189 190 fnxp = fnxargs; 191 garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */ 192 193 curarg = 0; 194 fnxp = fnxargs; 195 garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */ 196 197 cursafe = regs; 198 } 199 200 int 201 nareg(void) 202 { 203 int i, n; 204 205 n = 0; 206 for(i=D_AX; i<=D_DI; i++) 207 if(reg[i] == 0) 208 n++; 209 return n; 210 } 211 212 void 213 garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp) 214 { 215 Node nod; 216 217 if(n == Z) 218 return; 219 if(n->op == OLIST) { 220 garg1(n->left, tn1, tn2, f, fnxp); 221 garg1(n->right, tn1, tn2, f, fnxp); 222 return; 223 } 224 if(f == 0) { 225 if(n->complex >= FNX) { 226 regsalloc(*fnxp, n); 227 nod = znode; 228 nod.op = OAS; 229 nod.left = *fnxp; 230 nod.right = n; 231 nod.type = n->type; 232 cgen(&nod, Z); 233 (*fnxp)++; 234 } 235 return; 236 } 237 if(typesu[n->type->etype] || typev[n->type->etype]) { 238 regaalloc(tn2, n); 239 if(n->complex >= FNX) { 240 sugen(*fnxp, tn2, n->type->width); 241 (*fnxp)++; 242 } else 243 sugen(n, tn2, n->type->width); 244 return; 245 } 246 if(REGARG >= 0 && curarg == 0 && typeilp[n->type->etype]) { 247 regaalloc1(tn1, n); 248 if(n->complex >= FNX) { 249 cgen(*fnxp, tn1); 250 (*fnxp)++; 251 } else 252 cgen(n, tn1); 253 return; 254 } 255 if(vconst(n) == 0) { 256 regaalloc(tn2, n); 257 gmove(n, tn2); 258 return; 259 } 260 regalloc(tn1, n, Z); 261 if(n->complex >= FNX) { 262 cgen(*fnxp, tn1); 263 (*fnxp)++; 264 } else 265 cgen(n, tn1); 266 regaalloc(tn2, n); 267 gmove(tn1, tn2); 268 regfree(tn1); 269 } 270 271 Node* 272 nodconst(int32 v) 273 { 274 constnode.vconst = v; 275 return &constnode; 276 } 277 278 Node* 279 nodfconst(double d) 280 { 281 fconstnode.fconst = d; 282 return &fconstnode; 283 } 284 285 int 286 isreg(Node *n, int r) 287 { 288 289 if(n->op == OREGISTER) 290 if(n->reg == r) 291 return 1; 292 return 0; 293 } 294 295 int 296 nodreg(Node *n, Node *nn, int r) 297 { 298 299 *n = regnode; 300 n->reg = r; 301 if(reg[r] == 0) 302 return 0; 303 if(nn != Z) { 304 n->type = nn->type; 305 n->lineno = nn->lineno; 306 if(nn->op == OREGISTER) 307 if(nn->reg == r) 308 return 0; 309 } 310 return 1; 311 } 312 313 void 314 regret(Node *n, Node *nn, Type *t, int mode) 315 { 316 int r; 317 318 if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) { 319 r = REGRET; 320 if(typefd[nn->type->etype]) 321 r = FREGRET; 322 nodreg(n, nn, r); 323 reg[r]++; 324 return; 325 } 326 327 if(mode == 1) { 328 // fetch returned value after call. 329 // already called gargs, so curarg is set. 330 curarg = (curarg+3) & ~3; 331 regaalloc(n, nn); 332 return; 333 } 334 335 if(mode == 2) { 336 // store value to be returned. 337 // must compute arg offset. 338 if(t->etype != TFUNC) 339 fatal(Z, "bad regret func %T", t); 340 *n = *nn; 341 n->op = ONAME; 342 n->class = CPARAM; 343 n->sym = slookup(".retx"); 344 n->complex = 0; 345 n->addable = 20; 346 n->xoffset = argsize(0); 347 return; 348 } 349 350 fatal(Z, "bad regret"); 351 } 352 353 void 354 regalloc(Node *n, Node *tn, Node *o) 355 { 356 int i; 357 358 switch(tn->type->etype) { 359 case TCHAR: 360 case TUCHAR: 361 case TSHORT: 362 case TUSHORT: 363 case TINT: 364 case TUINT: 365 case TLONG: 366 case TULONG: 367 case TIND: 368 if(o != Z && o->op == OREGISTER) { 369 i = o->reg; 370 if(i >= D_AX && i <= D_DI) 371 goto out; 372 } 373 for(i=D_AX; i<=D_DI; i++) 374 if(reg[i] == 0) 375 goto out; 376 diag(tn, "out of fixed registers"); 377 goto err; 378 379 case TFLOAT: 380 case TDOUBLE: 381 case TVLONG: 382 i = D_F0; 383 goto out; 384 } 385 diag(tn, "unknown type in regalloc: %T", tn->type); 386 err: 387 i = 0; 388 out: 389 if(i) 390 reg[i]++; 391 nodreg(n, tn, i); 392 } 393 394 void 395 regialloc(Node *n, Node *tn, Node *o) 396 { 397 Node nod; 398 399 nod = *tn; 400 nod.type = types[TIND]; 401 regalloc(n, &nod, o); 402 } 403 404 void 405 regfree(Node *n) 406 { 407 int i; 408 409 i = 0; 410 if(n->op != OREGISTER && n->op != OINDREG) 411 goto err; 412 i = n->reg; 413 if(i < 0 || i >= nelem(reg)) 414 goto err; 415 if(reg[i] <= 0) 416 goto err; 417 reg[i]--; 418 return; 419 err: 420 diag(n, "error in regfree: %R", i); 421 } 422 423 void 424 regsalloc(Node *n, Node *nn) 425 { 426 cursafe = align(cursafe, nn->type, Aaut3, nil); 427 maxargsafe = maxround(maxargsafe, cursafe+curarg); 428 *n = *nodsafe; 429 n->xoffset = -(stkoff + cursafe); 430 n->type = nn->type; 431 n->etype = nn->type->etype; 432 n->lineno = nn->lineno; 433 } 434 435 void 436 regaalloc1(Node *n, Node *nn) 437 { 438 if(REGARG < 0) { 439 fatal(n, "regaalloc1 and REGARG<0"); 440 return; 441 } 442 nodreg(n, nn, REGARG); 443 reg[REGARG]++; 444 curarg = align(curarg, nn->type, Aarg1, nil); 445 curarg = align(curarg, nn->type, Aarg2, nil); 446 maxargsafe = maxround(maxargsafe, cursafe+curarg); 447 } 448 449 void 450 regaalloc(Node *n, Node *nn) 451 { 452 curarg = align(curarg, nn->type, Aarg1, nil); 453 *n = *nn; 454 n->op = OINDREG; 455 n->reg = REGSP; 456 n->xoffset = curarg; 457 n->complex = 0; 458 n->addable = 20; 459 curarg = align(curarg, nn->type, Aarg2, nil); 460 maxargsafe = maxround(maxargsafe, cursafe+curarg); 461 } 462 463 void 464 regind(Node *n, Node *nn) 465 { 466 467 if(n->op != OREGISTER) { 468 diag(n, "regind not OREGISTER"); 469 return; 470 } 471 n->op = OINDREG; 472 n->type = nn->type; 473 } 474 475 void 476 naddr(Node *n, Addr *a) 477 { 478 int32 v; 479 480 a->type = D_NONE; 481 if(n == Z) 482 return; 483 switch(n->op) { 484 default: 485 bad: 486 diag(n, "bad in naddr: %O %D", n->op, a); 487 break; 488 489 case OREGISTER: 490 a->type = n->reg; 491 a->sym = nil; 492 break; 493 494 case OEXREG: 495 a->type = D_INDIR + D_TLS; 496 a->offset = n->reg - 1; 497 break; 498 499 case OIND: 500 naddr(n->left, a); 501 if(a->type >= D_AX && a->type <= D_DI) 502 a->type += D_INDIR; 503 else 504 if(a->type == D_CONST) 505 a->type = D_NONE+D_INDIR; 506 else 507 if(a->type == D_ADDR) { 508 a->type = a->index; 509 a->index = D_NONE; 510 } else 511 goto bad; 512 break; 513 514 case OINDEX: 515 a->type = idx.ptr; 516 if(n->left->op == OADDR || n->left->op == OCONST) 517 naddr(n->left, a); 518 if(a->type >= D_AX && a->type <= D_DI) 519 a->type += D_INDIR; 520 else 521 if(a->type == D_CONST) 522 a->type = D_NONE+D_INDIR; 523 else 524 if(a->type == D_ADDR) { 525 a->type = a->index; 526 a->index = D_NONE; 527 } else 528 goto bad; 529 a->index = idx.reg; 530 a->scale = n->scale; 531 a->offset += n->xoffset; 532 break; 533 534 case OINDREG: 535 a->type = n->reg+D_INDIR; 536 a->sym = nil; 537 a->offset = n->xoffset; 538 break; 539 540 case ONAME: 541 a->etype = n->etype; 542 a->type = D_STATIC; 543 a->sym = linksym(n->sym); 544 a->offset = n->xoffset; 545 if(n->class == CSTATIC) 546 break; 547 if(n->class == CEXTERN || n->class == CGLOBL) { 548 a->type = D_EXTERN; 549 break; 550 } 551 if(n->class == CAUTO) { 552 a->type = D_AUTO; 553 break; 554 } 555 if(n->class == CPARAM) { 556 a->type = D_PARAM; 557 break; 558 } 559 goto bad; 560 561 case OCONST: 562 if(typefd[n->type->etype]) { 563 a->type = D_FCONST; 564 a->u.dval = n->fconst; 565 break; 566 } 567 a->sym = nil; 568 a->type = D_CONST; 569 a->offset = n->vconst; 570 break; 571 572 case OADDR: 573 naddr(n->left, a); 574 if(a->type >= D_INDIR) { 575 a->type -= D_INDIR; 576 break; 577 } 578 if(a->type == D_EXTERN || a->type == D_STATIC || 579 a->type == D_AUTO || a->type == D_PARAM) 580 if(a->index == D_NONE) { 581 a->index = a->type; 582 a->type = D_ADDR; 583 break; 584 } 585 goto bad; 586 587 case OADD: 588 if(n->right->op == OCONST) { 589 v = n->right->vconst; 590 naddr(n->left, a); 591 } else 592 if(n->left->op == OCONST) { 593 v = n->left->vconst; 594 naddr(n->right, a); 595 } else 596 goto bad; 597 a->offset += v; 598 break; 599 600 } 601 } 602 603 #define CASE(a,b) ((a<<8)|(b<<0)) 604 605 void 606 gmove(Node *f, Node *t) 607 { 608 int ft, tt, a; 609 Node nod, nod1; 610 Prog *p1; 611 612 ft = f->type->etype; 613 tt = t->type->etype; 614 if(debug['M']) 615 print("gop: %O %O[%s],%O[%s]\n", OAS, 616 f->op, tnames[ft], t->op, tnames[tt]); 617 if(typefd[ft] && f->op == OCONST) { 618 if(f->fconst == 0) 619 gins(AFLDZ, Z, Z); 620 else 621 if(f->fconst == 1) 622 gins(AFLD1, Z, Z); 623 else 624 gins(AFMOVD, f, &fregnode0); 625 gmove(&fregnode0, t); 626 return; 627 } 628 /* 629 * load 630 */ 631 if(f->op == ONAME || f->op == OINDREG || 632 f->op == OIND || f->op == OINDEX) 633 switch(ft) { 634 case TCHAR: 635 a = AMOVBLSX; 636 goto ld; 637 case TUCHAR: 638 a = AMOVBLZX; 639 goto ld; 640 case TSHORT: 641 if(typefd[tt]) { 642 gins(AFMOVW, f, &fregnode0); 643 gmove(&fregnode0, t); 644 return; 645 } 646 a = AMOVWLSX; 647 goto ld; 648 case TUSHORT: 649 a = AMOVWLZX; 650 goto ld; 651 case TINT: 652 case TUINT: 653 case TLONG: 654 case TULONG: 655 case TIND: 656 if(typefd[tt]) { 657 gins(AFMOVL, f, &fregnode0); 658 gmove(&fregnode0, t); 659 return; 660 } 661 a = AMOVL; 662 663 ld: 664 regalloc(&nod, f, t); 665 nod.type = types[TLONG]; 666 gins(a, f, &nod); 667 gmove(&nod, t); 668 regfree(&nod); 669 return; 670 671 case TFLOAT: 672 gins(AFMOVF, f, t); 673 return; 674 case TDOUBLE: 675 gins(AFMOVD, f, t); 676 return; 677 case TVLONG: 678 gins(AFMOVV, f, t); 679 return; 680 } 681 682 /* 683 * store 684 */ 685 if(t->op == ONAME || t->op == OINDREG || 686 t->op == OIND || t->op == OINDEX) 687 switch(tt) { 688 case TCHAR: 689 case TUCHAR: 690 a = AMOVB; goto st; 691 case TSHORT: 692 case TUSHORT: 693 a = AMOVW; goto st; 694 case TINT: 695 case TUINT: 696 case TLONG: 697 case TULONG: 698 case TIND: 699 a = AMOVL; goto st; 700 701 st: 702 if(f->op == OCONST) { 703 gins(a, f, t); 704 return; 705 } 706 regalloc(&nod, t, f); 707 gmove(f, &nod); 708 gins(a, &nod, t); 709 regfree(&nod); 710 return; 711 712 case TFLOAT: 713 gins(AFMOVFP, f, t); 714 return; 715 case TDOUBLE: 716 gins(AFMOVDP, f, t); 717 return; 718 case TVLONG: 719 gins(AFMOVVP, f, t); 720 return; 721 } 722 723 /* 724 * convert 725 */ 726 switch(CASE(ft,tt)) { 727 default: 728 /* 729 * integer to integer 730 ******** 731 a = AGOK; break; 732 733 case CASE( TCHAR, TCHAR): 734 case CASE( TUCHAR, TCHAR): 735 case CASE( TSHORT, TCHAR): 736 case CASE( TUSHORT,TCHAR): 737 case CASE( TINT, TCHAR): 738 case CASE( TUINT, TCHAR): 739 case CASE( TLONG, TCHAR): 740 case CASE( TULONG, TCHAR): 741 case CASE( TIND, TCHAR): 742 743 case CASE( TCHAR, TUCHAR): 744 case CASE( TUCHAR, TUCHAR): 745 case CASE( TSHORT, TUCHAR): 746 case CASE( TUSHORT,TUCHAR): 747 case CASE( TINT, TUCHAR): 748 case CASE( TUINT, TUCHAR): 749 case CASE( TLONG, TUCHAR): 750 case CASE( TULONG, TUCHAR): 751 case CASE( TIND, TUCHAR): 752 753 case CASE( TSHORT, TSHORT): 754 case CASE( TUSHORT,TSHORT): 755 case CASE( TINT, TSHORT): 756 case CASE( TUINT, TSHORT): 757 case CASE( TLONG, TSHORT): 758 case CASE( TULONG, TSHORT): 759 case CASE( TIND, TSHORT): 760 761 case CASE( TSHORT, TUSHORT): 762 case CASE( TUSHORT,TUSHORT): 763 case CASE( TINT, TUSHORT): 764 case CASE( TUINT, TUSHORT): 765 case CASE( TLONG, TUSHORT): 766 case CASE( TULONG, TUSHORT): 767 case CASE( TIND, TUSHORT): 768 769 case CASE( TINT, TINT): 770 case CASE( TUINT, TINT): 771 case CASE( TLONG, TINT): 772 case CASE( TULONG, TINT): 773 case CASE( TIND, TINT): 774 775 case CASE( TINT, TUINT): 776 case CASE( TUINT, TUINT): 777 case CASE( TLONG, TUINT): 778 case CASE( TULONG, TUINT): 779 case CASE( TIND, TUINT): 780 781 case CASE( TINT, TLONG): 782 case CASE( TUINT, TLONG): 783 case CASE( TLONG, TLONG): 784 case CASE( TULONG, TLONG): 785 case CASE( TIND, TLONG): 786 787 case CASE( TINT, TULONG): 788 case CASE( TUINT, TULONG): 789 case CASE( TLONG, TULONG): 790 case CASE( TULONG, TULONG): 791 case CASE( TIND, TULONG): 792 793 case CASE( TINT, TIND): 794 case CASE( TUINT, TIND): 795 case CASE( TLONG, TIND): 796 case CASE( TULONG, TIND): 797 case CASE( TIND, TIND): 798 *****/ 799 a = AMOVL; 800 break; 801 802 case CASE( TSHORT, TINT): 803 case CASE( TSHORT, TUINT): 804 case CASE( TSHORT, TLONG): 805 case CASE( TSHORT, TULONG): 806 case CASE( TSHORT, TIND): 807 a = AMOVWLSX; 808 if(f->op == OCONST) { 809 f->vconst &= 0xffff; 810 if(f->vconst & 0x8000) 811 f->vconst |= 0xffff0000; 812 a = AMOVL; 813 } 814 break; 815 816 case CASE( TUSHORT,TINT): 817 case CASE( TUSHORT,TUINT): 818 case CASE( TUSHORT,TLONG): 819 case CASE( TUSHORT,TULONG): 820 case CASE( TUSHORT,TIND): 821 a = AMOVWLZX; 822 if(f->op == OCONST) { 823 f->vconst &= 0xffff; 824 a = AMOVL; 825 } 826 break; 827 828 case CASE( TCHAR, TSHORT): 829 case CASE( TCHAR, TUSHORT): 830 case CASE( TCHAR, TINT): 831 case CASE( TCHAR, TUINT): 832 case CASE( TCHAR, TLONG): 833 case CASE( TCHAR, TULONG): 834 case CASE( TCHAR, TIND): 835 a = AMOVBLSX; 836 if(f->op == OCONST) { 837 f->vconst &= 0xff; 838 if(f->vconst & 0x80) 839 f->vconst |= 0xffffff00; 840 a = AMOVL; 841 } 842 break; 843 844 case CASE( TUCHAR, TSHORT): 845 case CASE( TUCHAR, TUSHORT): 846 case CASE( TUCHAR, TINT): 847 case CASE( TUCHAR, TUINT): 848 case CASE( TUCHAR, TLONG): 849 case CASE( TUCHAR, TULONG): 850 case CASE( TUCHAR, TIND): 851 a = AMOVBLZX; 852 if(f->op == OCONST) { 853 f->vconst &= 0xff; 854 a = AMOVL; 855 } 856 break; 857 858 /* 859 * float to fix 860 */ 861 case CASE( TFLOAT, TCHAR): 862 case CASE( TFLOAT, TUCHAR): 863 case CASE( TFLOAT, TSHORT): 864 case CASE( TFLOAT, TUSHORT): 865 case CASE( TFLOAT, TINT): 866 case CASE( TFLOAT, TUINT): 867 case CASE( TFLOAT, TLONG): 868 case CASE( TFLOAT, TULONG): 869 case CASE( TFLOAT, TIND): 870 871 case CASE( TDOUBLE,TCHAR): 872 case CASE( TDOUBLE,TUCHAR): 873 case CASE( TDOUBLE,TSHORT): 874 case CASE( TDOUBLE,TUSHORT): 875 case CASE( TDOUBLE,TINT): 876 case CASE( TDOUBLE,TUINT): 877 case CASE( TDOUBLE,TLONG): 878 case CASE( TDOUBLE,TULONG): 879 case CASE( TDOUBLE,TIND): 880 881 case CASE( TVLONG, TCHAR): 882 case CASE( TVLONG, TUCHAR): 883 case CASE( TVLONG, TSHORT): 884 case CASE( TVLONG, TUSHORT): 885 case CASE( TVLONG, TINT): 886 case CASE( TVLONG, TUINT): 887 case CASE( TVLONG, TLONG): 888 case CASE( TVLONG, TULONG): 889 case CASE( TVLONG, TIND): 890 if(fproundflg) { 891 regsalloc(&nod, ®node); 892 gins(AFMOVLP, f, &nod); 893 gmove(&nod, t); 894 return; 895 } 896 regsalloc(&nod, ®node); 897 regsalloc(&nod1, ®node); 898 gins(AFSTCW, Z, &nod1); 899 nod1.xoffset += 2; 900 gins(AMOVW, nodconst(0xf7f), &nod1); 901 gins(AFLDCW, &nod1, Z); 902 gins(AFMOVLP, f, &nod); 903 nod1.xoffset -= 2; 904 gins(AFLDCW, &nod1, Z); 905 gmove(&nod, t); 906 return; 907 908 /* 909 * ulong to float 910 */ 911 case CASE( TULONG, TDOUBLE): 912 case CASE( TULONG, TVLONG): 913 case CASE( TULONG, TFLOAT): 914 case CASE( TUINT, TDOUBLE): 915 case CASE( TUINT, TVLONG): 916 case CASE( TUINT, TFLOAT): 917 regalloc(&nod, f, f); 918 gmove(f, &nod); 919 regsalloc(&nod1, ®node); 920 gmove(&nod, &nod1); 921 gins(AFMOVL, &nod1, &fregnode0); 922 gins(ACMPL, &nod, nodconst(0)); 923 gins(AJGE, Z, Z); 924 p1 = p; 925 gins(AFADDD, nodfconst(4294967296.), &fregnode0); 926 patch(p1, pc); 927 regfree(&nod); 928 return; 929 930 /* 931 * fix to float 932 */ 933 case CASE( TCHAR, TFLOAT): 934 case CASE( TUCHAR, TFLOAT): 935 case CASE( TSHORT, TFLOAT): 936 case CASE( TUSHORT,TFLOAT): 937 case CASE( TINT, TFLOAT): 938 case CASE( TLONG, TFLOAT): 939 case CASE( TIND, TFLOAT): 940 941 case CASE( TCHAR, TDOUBLE): 942 case CASE( TUCHAR, TDOUBLE): 943 case CASE( TSHORT, TDOUBLE): 944 case CASE( TUSHORT,TDOUBLE): 945 case CASE( TINT, TDOUBLE): 946 case CASE( TLONG, TDOUBLE): 947 case CASE( TIND, TDOUBLE): 948 949 case CASE( TCHAR, TVLONG): 950 case CASE( TUCHAR, TVLONG): 951 case CASE( TSHORT, TVLONG): 952 case CASE( TUSHORT,TVLONG): 953 case CASE( TINT, TVLONG): 954 case CASE( TLONG, TVLONG): 955 case CASE( TIND, TVLONG): 956 regsalloc(&nod, ®node); 957 gmove(f, &nod); 958 gins(AFMOVL, &nod, &fregnode0); 959 return; 960 961 /* 962 * float to float 963 */ 964 case CASE( TFLOAT, TFLOAT): 965 case CASE( TDOUBLE,TFLOAT): 966 case CASE( TVLONG, TFLOAT): 967 968 case CASE( TFLOAT, TDOUBLE): 969 case CASE( TDOUBLE,TDOUBLE): 970 case CASE( TVLONG, TDOUBLE): 971 972 case CASE( TFLOAT, TVLONG): 973 case CASE( TDOUBLE,TVLONG): 974 case CASE( TVLONG, TVLONG): 975 a = AFMOVD; break; 976 } 977 if(a == AMOVL || a == AFMOVD) 978 if(samaddr(f, t)) 979 return; 980 gins(a, f, t); 981 } 982 983 void 984 doindex(Node *n) 985 { 986 Node nod, nod1; 987 int32 v; 988 989 if(debug['Y']) 990 prtree(n, "index"); 991 992 if(n->left->complex >= FNX) 993 print("botch in doindex\n"); 994 995 regalloc(&nod, ®node, Z); 996 v = constnode.vconst; 997 cgen(n->right, &nod); 998 idx.ptr = D_NONE; 999 if(n->left->op == OCONST) 1000 idx.ptr = D_CONST; 1001 else if(n->left->op == OREGISTER) 1002 idx.ptr = n->left->reg; 1003 else if(n->left->op != OADDR) { 1004 reg[D_BP]++; // can't be used as a base 1005 regalloc(&nod1, ®node, Z); 1006 cgen(n->left, &nod1); 1007 idx.ptr = nod1.reg; 1008 regfree(&nod1); 1009 reg[D_BP]--; 1010 } 1011 idx.reg = nod.reg; 1012 regfree(&nod); 1013 constnode.vconst = v; 1014 } 1015 1016 void 1017 gins(int a, Node *f, Node *t) 1018 { 1019 1020 if(f != Z && f->op == OINDEX) 1021 doindex(f); 1022 if(t != Z && t->op == OINDEX) 1023 doindex(t); 1024 nextpc(); 1025 p->as = a; 1026 if(f != Z) 1027 naddr(f, &p->from); 1028 if(t != Z) 1029 naddr(t, &p->to); 1030 if(debug['g']) 1031 print("%P\n", p); 1032 } 1033 1034 void 1035 fgopcode(int o, Node *f, Node *t, int pop, int rev) 1036 { 1037 int a, et; 1038 Node nod; 1039 1040 et = TLONG; 1041 if(f != Z && f->type != T) 1042 et = f->type->etype; 1043 if(!typefd[et]) { 1044 diag(f, "fop: integer %O", o); 1045 return; 1046 } 1047 if(debug['M']) { 1048 if(t != Z && t->type != T) 1049 print("gop: %O %O-%s Z\n", o, f->op, tnames[et]); 1050 else 1051 print("gop: %O %O-%s %O-%s\n", o, 1052 f->op, tnames[et], t->op, tnames[t->type->etype]); 1053 } 1054 a = AGOK; 1055 switch(o) { 1056 1057 case OASADD: 1058 case OADD: 1059 if(et == TFLOAT) 1060 a = AFADDF; 1061 else 1062 if(et == TDOUBLE || et == TVLONG) { 1063 a = AFADDD; 1064 if(pop) 1065 a = AFADDDP; 1066 } 1067 break; 1068 1069 case OASSUB: 1070 case OSUB: 1071 if(et == TFLOAT) { 1072 a = AFSUBF; 1073 if(rev) 1074 a = AFSUBRF; 1075 } else 1076 if(et == TDOUBLE || et == TVLONG) { 1077 a = AFSUBD; 1078 if(pop) 1079 a = AFSUBDP; 1080 if(rev) { 1081 a = AFSUBRD; 1082 if(pop) 1083 a = AFSUBRDP; 1084 } 1085 } 1086 break; 1087 1088 case OASMUL: 1089 case OMUL: 1090 if(et == TFLOAT) 1091 a = AFMULF; 1092 else 1093 if(et == TDOUBLE || et == TVLONG) { 1094 a = AFMULD; 1095 if(pop) 1096 a = AFMULDP; 1097 } 1098 break; 1099 1100 case OASMOD: 1101 case OMOD: 1102 case OASDIV: 1103 case ODIV: 1104 if(et == TFLOAT) { 1105 a = AFDIVF; 1106 if(rev) 1107 a = AFDIVRF; 1108 } else 1109 if(et == TDOUBLE || et == TVLONG) { 1110 a = AFDIVD; 1111 if(pop) 1112 a = AFDIVDP; 1113 if(rev) { 1114 a = AFDIVRD; 1115 if(pop) 1116 a = AFDIVRDP; 1117 } 1118 } 1119 break; 1120 1121 case OEQ: 1122 case ONE: 1123 case OLT: 1124 case OLE: 1125 case OGE: 1126 case OGT: 1127 pop += rev; 1128 if(et == TFLOAT) { 1129 a = AFCOMF; 1130 if(pop) { 1131 a = AFCOMFP; 1132 if(pop > 1) 1133 a = AGOK; 1134 } 1135 } else 1136 if(et == TDOUBLE || et == TVLONG) { 1137 a = AFCOMF; 1138 if(pop) { 1139 a = AFCOMDP; 1140 if(pop > 1) 1141 a = AFCOMDPP; 1142 } 1143 } 1144 gins(a, f, t); 1145 regalloc(&nod, ®node, Z); 1146 if(nod.reg != D_AX) { 1147 regfree(&nod); 1148 nod.reg = D_AX; 1149 gins(APUSHL, &nod, Z); 1150 gins(AWAIT, Z, Z); 1151 gins(AFSTSW, Z, &nod); 1152 gins(ASAHF, Z, Z); 1153 gins(APOPL, Z, &nod); 1154 } else { 1155 gins(AWAIT, Z, Z); 1156 gins(AFSTSW, Z, &nod); 1157 gins(ASAHF, Z, Z); 1158 regfree(&nod); 1159 } 1160 switch(o) { 1161 case OEQ: a = AJEQ; break; 1162 case ONE: a = AJNE; break; 1163 case OLT: a = AJCS; break; 1164 case OLE: a = AJLS; break; 1165 case OGE: a = AJCC; break; 1166 case OGT: a = AJHI; break; 1167 } 1168 gins(a, Z, Z); 1169 return; 1170 } 1171 if(a == AGOK) 1172 diag(Z, "bad in gopcode %O", o); 1173 gins(a, f, t); 1174 } 1175 1176 void 1177 gopcode(int o, Type *ty, Node *f, Node *t) 1178 { 1179 int a, et; 1180 1181 et = TLONG; 1182 if(ty != T) 1183 et = ty->etype; 1184 if(typefd[et] && o != OADDR && o != OFUNC) { 1185 diag(f, "gop: float %O", o); 1186 return; 1187 } 1188 if(debug['M']) { 1189 if(f != Z && f->type != T) 1190 print("gop: %O %O[%s],", o, f->op, tnames[et]); 1191 else 1192 print("gop: %O Z,", o); 1193 if(t != Z && t->type != T) 1194 print("%O[%s]\n", t->op, tnames[t->type->etype]); 1195 else 1196 print("Z\n"); 1197 } 1198 a = AGOK; 1199 switch(o) { 1200 case OCOM: 1201 a = ANOTL; 1202 if(et == TCHAR || et == TUCHAR) 1203 a = ANOTB; 1204 if(et == TSHORT || et == TUSHORT) 1205 a = ANOTW; 1206 break; 1207 1208 case ONEG: 1209 a = ANEGL; 1210 if(et == TCHAR || et == TUCHAR) 1211 a = ANEGB; 1212 if(et == TSHORT || et == TUSHORT) 1213 a = ANEGW; 1214 break; 1215 1216 case OADDR: 1217 a = ALEAL; 1218 break; 1219 1220 case OASADD: 1221 case OADD: 1222 a = AADDL; 1223 if(et == TCHAR || et == TUCHAR) 1224 a = AADDB; 1225 if(et == TSHORT || et == TUSHORT) 1226 a = AADDW; 1227 break; 1228 1229 case OASSUB: 1230 case OSUB: 1231 a = ASUBL; 1232 if(et == TCHAR || et == TUCHAR) 1233 a = ASUBB; 1234 if(et == TSHORT || et == TUSHORT) 1235 a = ASUBW; 1236 break; 1237 1238 case OASOR: 1239 case OOR: 1240 a = AORL; 1241 if(et == TCHAR || et == TUCHAR) 1242 a = AORB; 1243 if(et == TSHORT || et == TUSHORT) 1244 a = AORW; 1245 break; 1246 1247 case OASAND: 1248 case OAND: 1249 a = AANDL; 1250 if(et == TCHAR || et == TUCHAR) 1251 a = AANDB; 1252 if(et == TSHORT || et == TUSHORT) 1253 a = AANDW; 1254 break; 1255 1256 case OASXOR: 1257 case OXOR: 1258 a = AXORL; 1259 if(et == TCHAR || et == TUCHAR) 1260 a = AXORB; 1261 if(et == TSHORT || et == TUSHORT) 1262 a = AXORW; 1263 break; 1264 1265 case OASLSHR: 1266 case OLSHR: 1267 a = ASHRL; 1268 if(et == TCHAR || et == TUCHAR) 1269 a = ASHRB; 1270 if(et == TSHORT || et == TUSHORT) 1271 a = ASHRW; 1272 break; 1273 1274 case OASASHR: 1275 case OASHR: 1276 a = ASARL; 1277 if(et == TCHAR || et == TUCHAR) 1278 a = ASARB; 1279 if(et == TSHORT || et == TUSHORT) 1280 a = ASARW; 1281 break; 1282 1283 case OASASHL: 1284 case OASHL: 1285 a = ASALL; 1286 if(et == TCHAR || et == TUCHAR) 1287 a = ASALB; 1288 if(et == TSHORT || et == TUSHORT) 1289 a = ASALW; 1290 break; 1291 1292 case OROTL: 1293 a = AROLL; 1294 if(et == TCHAR || et == TUCHAR) 1295 a = AROLB; 1296 if(et == TSHORT || et == TUSHORT) 1297 a = AROLW; 1298 break; 1299 1300 case OFUNC: 1301 a = ACALL; 1302 break; 1303 1304 case OASMUL: 1305 case OMUL: 1306 if(f->op == OREGISTER && t != Z && isreg(t, D_AX) && reg[D_DX] == 0) 1307 t = Z; 1308 a = AIMULL; 1309 break; 1310 1311 case OASMOD: 1312 case OMOD: 1313 case OASDIV: 1314 case ODIV: 1315 a = AIDIVL; 1316 break; 1317 1318 case OASLMUL: 1319 case OLMUL: 1320 a = AMULL; 1321 break; 1322 1323 case OASLMOD: 1324 case OLMOD: 1325 case OASLDIV: 1326 case OLDIV: 1327 a = ADIVL; 1328 break; 1329 1330 case OEQ: 1331 case ONE: 1332 case OLT: 1333 case OLE: 1334 case OGE: 1335 case OGT: 1336 case OLO: 1337 case OLS: 1338 case OHS: 1339 case OHI: 1340 a = ACMPL; 1341 if(et == TCHAR || et == TUCHAR) 1342 a = ACMPB; 1343 if(et == TSHORT || et == TUSHORT) 1344 a = ACMPW; 1345 gins(a, f, t); 1346 switch(o) { 1347 case OEQ: a = AJEQ; break; 1348 case ONE: a = AJNE; break; 1349 case OLT: a = AJLT; break; 1350 case OLE: a = AJLE; break; 1351 case OGE: a = AJGE; break; 1352 case OGT: a = AJGT; break; 1353 case OLO: a = AJCS; break; 1354 case OLS: a = AJLS; break; 1355 case OHS: a = AJCC; break; 1356 case OHI: a = AJHI; break; 1357 } 1358 gins(a, Z, Z); 1359 return; 1360 } 1361 if(a == AGOK) 1362 diag(Z, "bad in gopcode %O", o); 1363 gins(a, f, t); 1364 } 1365 1366 int 1367 samaddr(Node *f, Node *t) 1368 { 1369 1370 if(f->op != t->op) 1371 return 0; 1372 switch(f->op) { 1373 1374 case OREGISTER: 1375 if(f->reg != t->reg) 1376 break; 1377 return 1; 1378 } 1379 return 0; 1380 } 1381 1382 void 1383 gbranch(int o) 1384 { 1385 int a; 1386 1387 a = AGOK; 1388 switch(o) { 1389 case ORETURN: 1390 a = ARET; 1391 break; 1392 case OGOTO: 1393 a = AJMP; 1394 break; 1395 } 1396 nextpc(); 1397 if(a == AGOK) { 1398 diag(Z, "bad in gbranch %O", o); 1399 nextpc(); 1400 } 1401 p->as = a; 1402 } 1403 1404 void 1405 patch(Prog *op, int32 pc) 1406 { 1407 op->to.offset = pc; 1408 op->to.type = D_BRANCH; 1409 op->to.u.branch = nil; 1410 op->pcond = nil; 1411 } 1412 1413 void 1414 gpseudo(int a, Sym *s, Node *n) 1415 { 1416 1417 nextpc(); 1418 p->as = a; 1419 p->from.type = D_EXTERN; 1420 p->from.sym = linksym(s); 1421 1422 switch(a) { 1423 case ATEXT: 1424 p->from.scale = textflag; 1425 textflag = 0; 1426 break; 1427 case AGLOBL: 1428 p->from.scale = s->dataflag; 1429 break; 1430 } 1431 1432 if(s->class == CSTATIC) 1433 p->from.type = D_STATIC; 1434 naddr(n, &p->to); 1435 if(a == ADATA || a == AGLOBL) 1436 pc--; 1437 } 1438 1439 void 1440 gpcdata(int index, int value) 1441 { 1442 Node n1; 1443 1444 n1 = *nodconst(index); 1445 gins(APCDATA, &n1, nodconst(value)); 1446 } 1447 1448 void 1449 gprefetch(Node *n) 1450 { 1451 Node n1; 1452 1453 if(strcmp(getgo386(), "sse2") != 0) // assume no prefetch on old machines 1454 return; 1455 1456 regalloc(&n1, n, Z); 1457 gmove(n, &n1); 1458 n1.op = OINDREG; 1459 gins(APREFETCHNTA, &n1, Z); 1460 regfree(&n1); 1461 } 1462 1463 int 1464 sconst(Node *n) 1465 { 1466 int32 v; 1467 1468 if(n->op == OCONST && !typefd[n->type->etype]) { 1469 v = n->vconst; 1470 if(v >= -32766L && v < 32766L) 1471 return 1; 1472 } 1473 return 0; 1474 } 1475 1476 int32 1477 exreg(Type *t) 1478 { 1479 int32 o; 1480 1481 if(typechlp[t->etype]){ 1482 if(exregoffset >= 32) 1483 return 0; 1484 o = exregoffset; 1485 exregoffset += 4; 1486 return o+1; // +1 to avoid 0 == failure; naddr case OEXREG will -1. 1487 } 1488 1489 return 0; 1490 } 1491 1492 schar ewidth[NTYPE] = 1493 { 1494 -1, /*[TXXX]*/ 1495 SZ_CHAR, /*[TCHAR]*/ 1496 SZ_CHAR, /*[TUCHAR]*/ 1497 SZ_SHORT, /*[TSHORT]*/ 1498 SZ_SHORT, /*[TUSHORT]*/ 1499 SZ_INT, /*[TINT]*/ 1500 SZ_INT, /*[TUINT]*/ 1501 SZ_LONG, /*[TLONG]*/ 1502 SZ_LONG, /*[TULONG]*/ 1503 SZ_VLONG, /*[TVLONG]*/ 1504 SZ_VLONG, /*[TUVLONG]*/ 1505 SZ_FLOAT, /*[TFLOAT]*/ 1506 SZ_DOUBLE, /*[TDOUBLE]*/ 1507 SZ_IND, /*[TIND]*/ 1508 0, /*[TFUNC]*/ 1509 -1, /*[TARRAY]*/ 1510 0, /*[TVOID]*/ 1511 -1, /*[TSTRUCT]*/ 1512 -1, /*[TUNION]*/ 1513 SZ_INT, /*[TENUM]*/ 1514 }; 1515 int32 ncast[NTYPE] = 1516 { 1517 0, /*[TXXX]*/ 1518 BCHAR|BUCHAR, /*[TCHAR]*/ 1519 BCHAR|BUCHAR, /*[TUCHAR]*/ 1520 BSHORT|BUSHORT, /*[TSHORT]*/ 1521 BSHORT|BUSHORT, /*[TUSHORT]*/ 1522 BINT|BUINT|BLONG|BULONG|BIND, /*[TINT]*/ 1523 BINT|BUINT|BLONG|BULONG|BIND, /*[TUINT]*/ 1524 BINT|BUINT|BLONG|BULONG|BIND, /*[TLONG]*/ 1525 BINT|BUINT|BLONG|BULONG|BIND, /*[TULONG]*/ 1526 BVLONG|BUVLONG, /*[TVLONG]*/ 1527 BVLONG|BUVLONG, /*[TUVLONG]*/ 1528 BFLOAT, /*[TFLOAT]*/ 1529 BDOUBLE, /*[TDOUBLE]*/ 1530 BLONG|BULONG|BIND, /*[TIND]*/ 1531 0, /*[TFUNC]*/ 1532 0, /*[TARRAY]*/ 1533 0, /*[TVOID]*/ 1534 BSTRUCT, /*[TSTRUCT]*/ 1535 BUNION, /*[TUNION]*/ 1536 0, /*[TENUM]*/ 1537 };