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