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