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