github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/8g/gsubr.c (about) 1 // Derived from 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 <u.h> 32 #include <libc.h> 33 #include "gg.h" 34 35 // TODO(rsc): Can make this bigger if we move 36 // the text segment up higher in 8l for all GOOS. 37 uint32 unmappedzero = 4096; 38 39 #define CASE(a,b) (((a)<<16)|((b)<<0)) 40 41 void 42 clearp(Prog *p) 43 { 44 p->as = AEND; 45 p->from.type = D_NONE; 46 p->from.index = D_NONE; 47 p->to.type = D_NONE; 48 p->to.index = D_NONE; 49 p->loc = pcloc; 50 pcloc++; 51 } 52 53 static int ddumped; 54 static Prog *dfirst; 55 static Prog *dpc; 56 57 /* 58 * generate and return proc with p->as = as, 59 * linked into program. pc is next instruction. 60 */ 61 Prog* 62 prog(int as) 63 { 64 Prog *p; 65 66 if(as == ADATA || as == AGLOBL) { 67 if(ddumped) 68 fatal("already dumped data"); 69 if(dpc == nil) { 70 dpc = mal(sizeof(*dpc)); 71 dfirst = dpc; 72 } 73 p = dpc; 74 dpc = mal(sizeof(*dpc)); 75 p->link = dpc; 76 } else { 77 p = pc; 78 pc = mal(sizeof(*pc)); 79 clearp(pc); 80 p->link = pc; 81 } 82 83 if(lineno == 0) { 84 if(debug['K']) 85 warn("prog: line 0"); 86 } 87 88 p->as = as; 89 p->lineno = lineno; 90 return p; 91 } 92 93 void 94 dumpdata(void) 95 { 96 ddumped = 1; 97 if(dfirst == nil) 98 return; 99 newplist(); 100 *pc = *dfirst; 101 pc = dpc; 102 clearp(pc); 103 } 104 105 /* 106 * generate a branch. 107 * t is ignored. 108 * likely values are for branch prediction: 109 * -1 unlikely 110 * 0 no opinion 111 * +1 likely 112 */ 113 Prog* 114 gbranch(int as, Type *t, int likely) 115 { 116 Prog *p; 117 118 USED(t); 119 p = prog(as); 120 p->to.type = D_BRANCH; 121 p->to.u.branch = P; 122 if(likely != 0) { 123 p->from.type = D_CONST; 124 p->from.offset = likely > 0; 125 } 126 return p; 127 } 128 129 /* 130 * patch previous branch to jump to to. 131 */ 132 void 133 patch(Prog *p, Prog *to) 134 { 135 if(p->to.type != D_BRANCH) 136 fatal("patch: not a branch"); 137 p->to.u.branch = to; 138 p->to.offset = to->loc; 139 } 140 141 Prog* 142 unpatch(Prog *p) 143 { 144 Prog *q; 145 146 if(p->to.type != D_BRANCH) 147 fatal("unpatch: not a branch"); 148 q = p->to.u.branch; 149 p->to.u.branch = P; 150 p->to.offset = 0; 151 return q; 152 } 153 154 /* 155 * start a new Prog list. 156 */ 157 Plist* 158 newplist(void) 159 { 160 Plist *pl; 161 162 pl = mal(sizeof(*pl)); 163 if(plist == nil) 164 plist = pl; 165 else 166 plast->link = pl; 167 plast = pl; 168 169 pc = mal(sizeof(*pc)); 170 clearp(pc); 171 pl->firstpc = pc; 172 173 return pl; 174 } 175 176 void 177 gused(Node *n) 178 { 179 gins(ANOP, n, N); // used 180 } 181 182 Prog* 183 gjmp(Prog *to) 184 { 185 Prog *p; 186 187 p = gbranch(AJMP, T, 0); 188 if(to != P) 189 patch(p, to); 190 return p; 191 } 192 193 void 194 ggloblnod(Node *nam) 195 { 196 Prog *p; 197 198 p = gins(AGLOBL, nam, N); 199 p->lineno = nam->lineno; 200 p->from.gotype = ngotype(nam); 201 p->to.sym = S; 202 p->to.type = D_CONST; 203 p->to.offset = nam->type->width; 204 if(nam->readonly) 205 p->from.scale = RODATA; 206 if(nam->type != T && !haspointers(nam->type)) 207 p->from.scale |= NOPTR; 208 } 209 210 void 211 ggloblsym(Sym *s, int32 width, int dupok, int rodata) 212 { 213 Prog *p; 214 215 p = gins(AGLOBL, N, N); 216 p->from.type = D_EXTERN; 217 p->from.index = D_NONE; 218 p->from.sym = s; 219 p->to.type = D_CONST; 220 p->to.index = D_NONE; 221 p->to.offset = width; 222 if(dupok) 223 p->from.scale |= DUPOK; 224 if(rodata) 225 p->from.scale |= RODATA; 226 } 227 228 void 229 gtrack(Sym *s) 230 { 231 Prog *p; 232 233 p = gins(AUSEFIELD, N, N); 234 p->from.type = D_EXTERN; 235 p->from.index = D_NONE; 236 p->from.sym = s; 237 } 238 239 int 240 isfat(Type *t) 241 { 242 if(t != T) 243 switch(t->etype) { 244 case TSTRUCT: 245 case TARRAY: 246 case TSTRING: 247 case TINTER: // maybe remove later 248 return 1; 249 } 250 return 0; 251 } 252 253 /* 254 * naddr of func generates code for address of func. 255 * if using opcode that can take address implicitly, 256 * call afunclit to fix up the argument. 257 */ 258 void 259 afunclit(Addr *a, Node *n) 260 { 261 if(a->type == D_ADDR && a->index == D_EXTERN) { 262 a->type = D_EXTERN; 263 a->index = D_NONE; 264 a->sym = n->sym; 265 } 266 } 267 268 /* 269 * return Axxx for Oxxx on type t. 270 */ 271 int 272 optoas(int op, Type *t) 273 { 274 int a; 275 276 if(t == T) 277 fatal("optoas: t is nil"); 278 279 a = AGOK; 280 switch(CASE(op, simtype[t->etype])) { 281 default: 282 fatal("optoas: no entry %O-%T", op, t); 283 break; 284 285 case CASE(OADDR, TPTR32): 286 a = ALEAL; 287 break; 288 289 case CASE(OEQ, TBOOL): 290 case CASE(OEQ, TINT8): 291 case CASE(OEQ, TUINT8): 292 case CASE(OEQ, TINT16): 293 case CASE(OEQ, TUINT16): 294 case CASE(OEQ, TINT32): 295 case CASE(OEQ, TUINT32): 296 case CASE(OEQ, TINT64): 297 case CASE(OEQ, TUINT64): 298 case CASE(OEQ, TPTR32): 299 case CASE(OEQ, TPTR64): 300 case CASE(OEQ, TFLOAT32): 301 case CASE(OEQ, TFLOAT64): 302 a = AJEQ; 303 break; 304 305 case CASE(ONE, TBOOL): 306 case CASE(ONE, TINT8): 307 case CASE(ONE, TUINT8): 308 case CASE(ONE, TINT16): 309 case CASE(ONE, TUINT16): 310 case CASE(ONE, TINT32): 311 case CASE(ONE, TUINT32): 312 case CASE(ONE, TINT64): 313 case CASE(ONE, TUINT64): 314 case CASE(ONE, TPTR32): 315 case CASE(ONE, TPTR64): 316 case CASE(ONE, TFLOAT32): 317 case CASE(ONE, TFLOAT64): 318 a = AJNE; 319 break; 320 321 case CASE(OLT, TINT8): 322 case CASE(OLT, TINT16): 323 case CASE(OLT, TINT32): 324 case CASE(OLT, TINT64): 325 a = AJLT; 326 break; 327 328 case CASE(OLT, TUINT8): 329 case CASE(OLT, TUINT16): 330 case CASE(OLT, TUINT32): 331 case CASE(OLT, TUINT64): 332 a = AJCS; 333 break; 334 335 case CASE(OLE, TINT8): 336 case CASE(OLE, TINT16): 337 case CASE(OLE, TINT32): 338 case CASE(OLE, TINT64): 339 a = AJLE; 340 break; 341 342 case CASE(OLE, TUINT8): 343 case CASE(OLE, TUINT16): 344 case CASE(OLE, TUINT32): 345 case CASE(OLE, TUINT64): 346 a = AJLS; 347 break; 348 349 case CASE(OGT, TINT8): 350 case CASE(OGT, TINT16): 351 case CASE(OGT, TINT32): 352 case CASE(OGT, TINT64): 353 a = AJGT; 354 break; 355 356 case CASE(OGT, TUINT8): 357 case CASE(OGT, TUINT16): 358 case CASE(OGT, TUINT32): 359 case CASE(OGT, TUINT64): 360 case CASE(OLT, TFLOAT32): 361 case CASE(OLT, TFLOAT64): 362 a = AJHI; 363 break; 364 365 case CASE(OGE, TINT8): 366 case CASE(OGE, TINT16): 367 case CASE(OGE, TINT32): 368 case CASE(OGE, TINT64): 369 a = AJGE; 370 break; 371 372 case CASE(OGE, TUINT8): 373 case CASE(OGE, TUINT16): 374 case CASE(OGE, TUINT32): 375 case CASE(OGE, TUINT64): 376 case CASE(OLE, TFLOAT32): 377 case CASE(OLE, TFLOAT64): 378 a = AJCC; 379 break; 380 381 case CASE(OCMP, TBOOL): 382 case CASE(OCMP, TINT8): 383 case CASE(OCMP, TUINT8): 384 a = ACMPB; 385 break; 386 387 case CASE(OCMP, TINT16): 388 case CASE(OCMP, TUINT16): 389 a = ACMPW; 390 break; 391 392 case CASE(OCMP, TINT32): 393 case CASE(OCMP, TUINT32): 394 case CASE(OCMP, TPTR32): 395 a = ACMPL; 396 break; 397 398 case CASE(OAS, TBOOL): 399 case CASE(OAS, TINT8): 400 case CASE(OAS, TUINT8): 401 a = AMOVB; 402 break; 403 404 case CASE(OAS, TINT16): 405 case CASE(OAS, TUINT16): 406 a = AMOVW; 407 break; 408 409 case CASE(OAS, TINT32): 410 case CASE(OAS, TUINT32): 411 case CASE(OAS, TPTR32): 412 a = AMOVL; 413 break; 414 415 case CASE(OADD, TINT8): 416 case CASE(OADD, TUINT8): 417 a = AADDB; 418 break; 419 420 case CASE(OADD, TINT16): 421 case CASE(OADD, TUINT16): 422 a = AADDW; 423 break; 424 425 case CASE(OADD, TINT32): 426 case CASE(OADD, TUINT32): 427 case CASE(OADD, TPTR32): 428 a = AADDL; 429 break; 430 431 case CASE(OSUB, TINT8): 432 case CASE(OSUB, TUINT8): 433 a = ASUBB; 434 break; 435 436 case CASE(OSUB, TINT16): 437 case CASE(OSUB, TUINT16): 438 a = ASUBW; 439 break; 440 441 case CASE(OSUB, TINT32): 442 case CASE(OSUB, TUINT32): 443 case CASE(OSUB, TPTR32): 444 a = ASUBL; 445 break; 446 447 case CASE(OINC, TINT8): 448 case CASE(OINC, TUINT8): 449 a = AINCB; 450 break; 451 452 case CASE(OINC, TINT16): 453 case CASE(OINC, TUINT16): 454 a = AINCW; 455 break; 456 457 case CASE(OINC, TINT32): 458 case CASE(OINC, TUINT32): 459 case CASE(OINC, TPTR32): 460 a = AINCL; 461 break; 462 463 case CASE(ODEC, TINT8): 464 case CASE(ODEC, TUINT8): 465 a = ADECB; 466 break; 467 468 case CASE(ODEC, TINT16): 469 case CASE(ODEC, TUINT16): 470 a = ADECW; 471 break; 472 473 case CASE(ODEC, TINT32): 474 case CASE(ODEC, TUINT32): 475 case CASE(ODEC, TPTR32): 476 a = ADECL; 477 break; 478 479 case CASE(OCOM, TINT8): 480 case CASE(OCOM, TUINT8): 481 a = ANOTB; 482 break; 483 484 case CASE(OCOM, TINT16): 485 case CASE(OCOM, TUINT16): 486 a = ANOTW; 487 break; 488 489 case CASE(OCOM, TINT32): 490 case CASE(OCOM, TUINT32): 491 case CASE(OCOM, TPTR32): 492 a = ANOTL; 493 break; 494 495 case CASE(OMINUS, TINT8): 496 case CASE(OMINUS, TUINT8): 497 a = ANEGB; 498 break; 499 500 case CASE(OMINUS, TINT16): 501 case CASE(OMINUS, TUINT16): 502 a = ANEGW; 503 break; 504 505 case CASE(OMINUS, TINT32): 506 case CASE(OMINUS, TUINT32): 507 case CASE(OMINUS, TPTR32): 508 a = ANEGL; 509 break; 510 511 case CASE(OAND, TINT8): 512 case CASE(OAND, TUINT8): 513 a = AANDB; 514 break; 515 516 case CASE(OAND, TINT16): 517 case CASE(OAND, TUINT16): 518 a = AANDW; 519 break; 520 521 case CASE(OAND, TINT32): 522 case CASE(OAND, TUINT32): 523 case CASE(OAND, TPTR32): 524 a = AANDL; 525 break; 526 527 case CASE(OOR, TINT8): 528 case CASE(OOR, TUINT8): 529 a = AORB; 530 break; 531 532 case CASE(OOR, TINT16): 533 case CASE(OOR, TUINT16): 534 a = AORW; 535 break; 536 537 case CASE(OOR, TINT32): 538 case CASE(OOR, TUINT32): 539 case CASE(OOR, TPTR32): 540 a = AORL; 541 break; 542 543 case CASE(OXOR, TINT8): 544 case CASE(OXOR, TUINT8): 545 a = AXORB; 546 break; 547 548 case CASE(OXOR, TINT16): 549 case CASE(OXOR, TUINT16): 550 a = AXORW; 551 break; 552 553 case CASE(OXOR, TINT32): 554 case CASE(OXOR, TUINT32): 555 case CASE(OXOR, TPTR32): 556 a = AXORL; 557 break; 558 559 case CASE(OLROT, TINT8): 560 case CASE(OLROT, TUINT8): 561 a = AROLB; 562 break; 563 564 case CASE(OLROT, TINT16): 565 case CASE(OLROT, TUINT16): 566 a = AROLW; 567 break; 568 569 case CASE(OLROT, TINT32): 570 case CASE(OLROT, TUINT32): 571 case CASE(OLROT, TPTR32): 572 a = AROLL; 573 break; 574 575 case CASE(OLSH, TINT8): 576 case CASE(OLSH, TUINT8): 577 a = ASHLB; 578 break; 579 580 case CASE(OLSH, TINT16): 581 case CASE(OLSH, TUINT16): 582 a = ASHLW; 583 break; 584 585 case CASE(OLSH, TINT32): 586 case CASE(OLSH, TUINT32): 587 case CASE(OLSH, TPTR32): 588 a = ASHLL; 589 break; 590 591 case CASE(ORSH, TUINT8): 592 a = ASHRB; 593 break; 594 595 case CASE(ORSH, TUINT16): 596 a = ASHRW; 597 break; 598 599 case CASE(ORSH, TUINT32): 600 case CASE(ORSH, TPTR32): 601 a = ASHRL; 602 break; 603 604 case CASE(ORSH, TINT8): 605 a = ASARB; 606 break; 607 608 case CASE(ORSH, TINT16): 609 a = ASARW; 610 break; 611 612 case CASE(ORSH, TINT32): 613 a = ASARL; 614 break; 615 616 case CASE(OHMUL, TINT8): 617 case CASE(OMUL, TINT8): 618 case CASE(OMUL, TUINT8): 619 a = AIMULB; 620 break; 621 622 case CASE(OHMUL, TINT16): 623 case CASE(OMUL, TINT16): 624 case CASE(OMUL, TUINT16): 625 a = AIMULW; 626 break; 627 628 case CASE(OHMUL, TINT32): 629 case CASE(OMUL, TINT32): 630 case CASE(OMUL, TUINT32): 631 case CASE(OMUL, TPTR32): 632 a = AIMULL; 633 break; 634 635 case CASE(OHMUL, TUINT8): 636 a = AMULB; 637 break; 638 639 case CASE(OHMUL, TUINT16): 640 a = AMULW; 641 break; 642 643 case CASE(OHMUL, TUINT32): 644 case CASE(OHMUL, TPTR32): 645 a = AMULL; 646 break; 647 648 case CASE(ODIV, TINT8): 649 case CASE(OMOD, TINT8): 650 a = AIDIVB; 651 break; 652 653 case CASE(ODIV, TUINT8): 654 case CASE(OMOD, TUINT8): 655 a = ADIVB; 656 break; 657 658 case CASE(ODIV, TINT16): 659 case CASE(OMOD, TINT16): 660 a = AIDIVW; 661 break; 662 663 case CASE(ODIV, TUINT16): 664 case CASE(OMOD, TUINT16): 665 a = ADIVW; 666 break; 667 668 case CASE(ODIV, TINT32): 669 case CASE(OMOD, TINT32): 670 a = AIDIVL; 671 break; 672 673 case CASE(ODIV, TUINT32): 674 case CASE(ODIV, TPTR32): 675 case CASE(OMOD, TUINT32): 676 case CASE(OMOD, TPTR32): 677 a = ADIVL; 678 break; 679 680 case CASE(OEXTEND, TINT16): 681 a = ACWD; 682 break; 683 684 case CASE(OEXTEND, TINT32): 685 a = ACDQ; 686 break; 687 } 688 return a; 689 } 690 691 #define FCASE(a, b, c) (((a)<<16)|((b)<<8)|(c)) 692 int 693 foptoas(int op, Type *t, int flg) 694 { 695 int et, a; 696 697 a = AGOK; 698 et = simtype[t->etype]; 699 700 if(use_sse) 701 goto sse; 702 703 // If we need Fpop, it means we're working on 704 // two different floating-point registers, not memory. 705 // There the instruction only has a float64 form. 706 if(flg & Fpop) 707 et = TFLOAT64; 708 709 // clear Frev if unneeded 710 switch(op) { 711 case OADD: 712 case OMUL: 713 flg &= ~Frev; 714 break; 715 } 716 717 switch(FCASE(op, et, flg)) { 718 case FCASE(OADD, TFLOAT32, 0): 719 return AFADDF; 720 case FCASE(OADD, TFLOAT64, 0): 721 return AFADDD; 722 case FCASE(OADD, TFLOAT64, Fpop): 723 return AFADDDP; 724 725 case FCASE(OSUB, TFLOAT32, 0): 726 return AFSUBF; 727 case FCASE(OSUB, TFLOAT32, Frev): 728 return AFSUBRF; 729 730 case FCASE(OSUB, TFLOAT64, 0): 731 return AFSUBD; 732 case FCASE(OSUB, TFLOAT64, Frev): 733 return AFSUBRD; 734 case FCASE(OSUB, TFLOAT64, Fpop): 735 return AFSUBDP; 736 case FCASE(OSUB, TFLOAT64, Fpop|Frev): 737 return AFSUBRDP; 738 739 case FCASE(OMUL, TFLOAT32, 0): 740 return AFMULF; 741 case FCASE(OMUL, TFLOAT64, 0): 742 return AFMULD; 743 case FCASE(OMUL, TFLOAT64, Fpop): 744 return AFMULDP; 745 746 case FCASE(ODIV, TFLOAT32, 0): 747 return AFDIVF; 748 case FCASE(ODIV, TFLOAT32, Frev): 749 return AFDIVRF; 750 751 case FCASE(ODIV, TFLOAT64, 0): 752 return AFDIVD; 753 case FCASE(ODIV, TFLOAT64, Frev): 754 return AFDIVRD; 755 case FCASE(ODIV, TFLOAT64, Fpop): 756 return AFDIVDP; 757 case FCASE(ODIV, TFLOAT64, Fpop|Frev): 758 return AFDIVRDP; 759 760 case FCASE(OCMP, TFLOAT32, 0): 761 return AFCOMF; 762 case FCASE(OCMP, TFLOAT32, Fpop): 763 return AFCOMFP; 764 case FCASE(OCMP, TFLOAT64, 0): 765 return AFCOMD; 766 case FCASE(OCMP, TFLOAT64, Fpop): 767 return AFCOMDP; 768 case FCASE(OCMP, TFLOAT64, Fpop2): 769 return AFCOMDPP; 770 771 case FCASE(OMINUS, TFLOAT32, 0): 772 return AFCHS; 773 case FCASE(OMINUS, TFLOAT64, 0): 774 return AFCHS; 775 } 776 777 fatal("foptoas %O %T %#x", op, t, flg); 778 return 0; 779 780 sse: 781 switch(CASE(op, et)) { 782 default: 783 fatal("foptoas-sse: no entry %O-%T", op, t); 784 break; 785 786 case CASE(OCMP, TFLOAT32): 787 a = AUCOMISS; 788 break; 789 790 case CASE(OCMP, TFLOAT64): 791 a = AUCOMISD; 792 break; 793 794 case CASE(OAS, TFLOAT32): 795 a = AMOVSS; 796 break; 797 798 case CASE(OAS, TFLOAT64): 799 a = AMOVSD; 800 break; 801 802 case CASE(OADD, TFLOAT32): 803 a = AADDSS; 804 break; 805 806 case CASE(OADD, TFLOAT64): 807 a = AADDSD; 808 break; 809 810 case CASE(OSUB, TFLOAT32): 811 a = ASUBSS; 812 break; 813 814 case CASE(OSUB, TFLOAT64): 815 a = ASUBSD; 816 break; 817 818 case CASE(OMUL, TFLOAT32): 819 a = AMULSS; 820 break; 821 822 case CASE(OMUL, TFLOAT64): 823 a = AMULSD; 824 break; 825 826 case CASE(ODIV, TFLOAT32): 827 a = ADIVSS; 828 break; 829 830 case CASE(ODIV, TFLOAT64): 831 a = ADIVSD; 832 break; 833 } 834 return a; 835 } 836 837 838 static int resvd[] = 839 { 840 // D_DI, // for movstring 841 // D_SI, // for movstring 842 843 D_AX, // for divide 844 D_CX, // for shift 845 D_DX, // for divide 846 D_SP, // for stack 847 848 D_BL, // because D_BX can be allocated 849 D_BH, 850 }; 851 852 void 853 ginit(void) 854 { 855 int i; 856 857 for(i=0; i<nelem(reg); i++) 858 reg[i] = 1; 859 for(i=D_AX; i<=D_DI; i++) 860 reg[i] = 0; 861 for(i=D_X0; i<=D_X7; i++) 862 reg[i] = 0; 863 for(i=0; i<nelem(resvd); i++) 864 reg[resvd[i]]++; 865 } 866 867 uintptr regpc[D_NONE]; 868 869 void 870 gclean(void) 871 { 872 int i; 873 874 for(i=0; i<nelem(resvd); i++) 875 reg[resvd[i]]--; 876 877 for(i=D_AX; i<=D_DI; i++) 878 if(reg[i]) 879 yyerror("reg %R left allocated at %ux", i, regpc[i]); 880 for(i=D_X0; i<=D_X7; i++) 881 if(reg[i]) 882 yyerror("reg %R left allocated\n", i); 883 } 884 885 int32 886 anyregalloc(void) 887 { 888 int i, j; 889 890 for(i=D_AX; i<=D_DI; i++) { 891 if(reg[i] == 0) 892 goto ok; 893 for(j=0; j<nelem(resvd); j++) 894 if(resvd[j] == i) 895 goto ok; 896 return 1; 897 ok:; 898 } 899 for(i=D_X0; i<=D_X7; i++) 900 if(reg[i]) 901 return 1; 902 return 0; 903 } 904 905 /* 906 * allocate register of type t, leave in n. 907 * if o != N, o is desired fixed register. 908 * caller must regfree(n). 909 */ 910 void 911 regalloc(Node *n, Type *t, Node *o) 912 { 913 int i, et; 914 915 if(t == T) 916 fatal("regalloc: t nil"); 917 et = simtype[t->etype]; 918 919 switch(et) { 920 case TINT64: 921 case TUINT64: 922 fatal("regalloc64"); 923 924 case TINT8: 925 case TUINT8: 926 case TINT16: 927 case TUINT16: 928 case TINT32: 929 case TUINT32: 930 case TPTR32: 931 case TPTR64: 932 case TBOOL: 933 if(o != N && o->op == OREGISTER) { 934 i = o->val.u.reg; 935 if(i >= D_AX && i <= D_DI) 936 goto out; 937 } 938 for(i=D_AX; i<=D_DI; i++) 939 if(reg[i] == 0) 940 goto out; 941 942 fprint(2, "registers allocated at\n"); 943 for(i=D_AX; i<=D_DI; i++) 944 fprint(2, "\t%R\t%#lux\n", i, regpc[i]); 945 yyerror("out of fixed registers"); 946 goto err; 947 948 case TFLOAT32: 949 case TFLOAT64: 950 if(!use_sse) { 951 i = D_F0; 952 goto out; 953 } 954 if(o != N && o->op == OREGISTER) { 955 i = o->val.u.reg; 956 if(i >= D_X0 && i <= D_X7) 957 goto out; 958 } 959 for(i=D_X0; i<=D_X7; i++) 960 if(reg[i] == 0) 961 goto out; 962 fprint(2, "registers allocated at\n"); 963 for(i=D_X0; i<=D_X7; i++) 964 fprint(2, "\t%R\t%#lux\n", i, regpc[i]); 965 fatal("out of floating registers"); 966 } 967 yyerror("regalloc: unknown type %T", t); 968 969 err: 970 nodreg(n, t, 0); 971 return; 972 973 out: 974 if (i == D_SP) 975 print("alloc SP\n"); 976 if(reg[i] == 0) { 977 regpc[i] = (uintptr)getcallerpc(&n); 978 if(i == D_AX || i == D_CX || i == D_DX || i == D_SP) { 979 dump("regalloc-o", o); 980 fatal("regalloc %R", i); 981 } 982 } 983 reg[i]++; 984 nodreg(n, t, i); 985 } 986 987 void 988 regfree(Node *n) 989 { 990 int i; 991 992 if(n->op == ONAME) 993 return; 994 if(n->op != OREGISTER && n->op != OINDREG) 995 fatal("regfree: not a register"); 996 i = n->val.u.reg; 997 if(i == D_SP) 998 return; 999 if(i < 0 || i >= nelem(reg)) 1000 fatal("regfree: reg out of range"); 1001 if(reg[i] <= 0) 1002 fatal("regfree: reg not allocated"); 1003 reg[i]--; 1004 if(reg[i] == 0 && (i == D_AX || i == D_CX || i == D_DX || i == D_SP)) 1005 fatal("regfree %R", i); 1006 } 1007 1008 /* 1009 * initialize n to be register r of type t. 1010 */ 1011 void 1012 nodreg(Node *n, Type *t, int r) 1013 { 1014 if(t == T) 1015 fatal("nodreg: t nil"); 1016 1017 memset(n, 0, sizeof(*n)); 1018 n->op = OREGISTER; 1019 n->addable = 1; 1020 ullmancalc(n); 1021 n->val.u.reg = r; 1022 n->type = t; 1023 } 1024 1025 /* 1026 * initialize n to be indirect of register r; n is type t. 1027 */ 1028 void 1029 nodindreg(Node *n, Type *t, int r) 1030 { 1031 nodreg(n, t, r); 1032 n->op = OINDREG; 1033 } 1034 1035 Node* 1036 nodarg(Type *t, int fp) 1037 { 1038 Node *n; 1039 Type *first; 1040 Iter savet; 1041 1042 // entire argument struct, not just one arg 1043 switch(t->etype) { 1044 default: 1045 fatal("nodarg %T", t); 1046 1047 case TSTRUCT: 1048 if(!t->funarg) 1049 fatal("nodarg: TSTRUCT but not funarg"); 1050 n = nod(ONAME, N, N); 1051 n->sym = lookup(".args"); 1052 n->type = t; 1053 first = structfirst(&savet, &t); 1054 if(first == nil) 1055 fatal("nodarg: bad struct"); 1056 if(first->width == BADWIDTH) 1057 fatal("nodarg: offset not computed for %T", t); 1058 n->xoffset = first->width; 1059 n->addable = 1; 1060 break; 1061 1062 case TFIELD: 1063 n = nod(ONAME, N, N); 1064 n->type = t->type; 1065 n->sym = t->sym; 1066 if(t->width == BADWIDTH) 1067 fatal("nodarg: offset not computed for %T", t); 1068 n->xoffset = t->width; 1069 n->addable = 1; 1070 n->orig = t->nname; 1071 break; 1072 } 1073 1074 // Rewrite argument named _ to __, 1075 // or else the assignment to _ will be 1076 // discarded during code generation. 1077 if(isblank(n)) 1078 n->sym = lookup("__"); 1079 1080 switch(fp) { 1081 default: 1082 fatal("nodarg %T %d", t, fp); 1083 1084 case 0: // output arg 1085 n->op = OINDREG; 1086 n->val.u.reg = D_SP; 1087 break; 1088 1089 case 1: // input arg 1090 n->class = PPARAM; 1091 break; 1092 } 1093 1094 n->typecheck = 1; 1095 return n; 1096 } 1097 1098 /* 1099 * generate 1100 * as $c, reg 1101 */ 1102 void 1103 gconreg(int as, vlong c, int reg) 1104 { 1105 Node n1, n2; 1106 1107 nodconst(&n1, types[TINT64], c); 1108 nodreg(&n2, types[TINT64], reg); 1109 gins(as, &n1, &n2); 1110 } 1111 1112 /* 1113 * swap node contents 1114 */ 1115 void 1116 nswap(Node *a, Node *b) 1117 { 1118 Node t; 1119 1120 t = *a; 1121 *a = *b; 1122 *b = t; 1123 } 1124 1125 /* 1126 * return constant i node. 1127 * overwritten by next call, but useful in calls to gins. 1128 */ 1129 Node* 1130 ncon(uint32 i) 1131 { 1132 static Node n; 1133 1134 if(n.type == T) 1135 nodconst(&n, types[TUINT32], 0); 1136 mpmovecfix(n.val.u.xval, i); 1137 return &n; 1138 } 1139 1140 /* 1141 * Is this node a memory operand? 1142 */ 1143 int 1144 ismem(Node *n) 1145 { 1146 switch(n->op) { 1147 case OITAB: 1148 case OLEN: 1149 case OCAP: 1150 case OINDREG: 1151 case ONAME: 1152 case OPARAM: 1153 case OCLOSUREVAR: 1154 return 1; 1155 } 1156 return 0; 1157 } 1158 1159 Node sclean[10]; 1160 int nsclean; 1161 1162 /* 1163 * n is a 64-bit value. fill in lo and hi to refer to its 32-bit halves. 1164 */ 1165 void 1166 split64(Node *n, Node *lo, Node *hi) 1167 { 1168 Node n1; 1169 int64 i; 1170 1171 if(!is64(n->type)) 1172 fatal("split64 %T", n->type); 1173 1174 if(nsclean >= nelem(sclean)) 1175 fatal("split64 clean"); 1176 sclean[nsclean].op = OEMPTY; 1177 nsclean++; 1178 switch(n->op) { 1179 default: 1180 if(!dotaddable(n, &n1)) { 1181 igen(n, &n1, N); 1182 sclean[nsclean-1] = n1; 1183 } 1184 n = &n1; 1185 goto common; 1186 case ONAME: 1187 if(n->class == PPARAMREF) { 1188 cgen(n->heapaddr, &n1); 1189 sclean[nsclean-1] = n1; 1190 // fall through. 1191 n = &n1; 1192 } 1193 goto common; 1194 case OINDREG: 1195 common: 1196 *lo = *n; 1197 *hi = *n; 1198 lo->type = types[TUINT32]; 1199 if(n->type->etype == TINT64) 1200 hi->type = types[TINT32]; 1201 else 1202 hi->type = types[TUINT32]; 1203 hi->xoffset += 4; 1204 break; 1205 1206 case OLITERAL: 1207 convconst(&n1, n->type, &n->val); 1208 i = mpgetfix(n1.val.u.xval); 1209 nodconst(lo, types[TUINT32], (uint32)i); 1210 i >>= 32; 1211 if(n->type->etype == TINT64) 1212 nodconst(hi, types[TINT32], (int32)i); 1213 else 1214 nodconst(hi, types[TUINT32], (uint32)i); 1215 break; 1216 } 1217 } 1218 1219 void 1220 splitclean(void) 1221 { 1222 if(nsclean <= 0) 1223 fatal("splitclean"); 1224 nsclean--; 1225 if(sclean[nsclean].op != OEMPTY) 1226 regfree(&sclean[nsclean]); 1227 } 1228 1229 /* 1230 * set up nodes representing fp constants 1231 */ 1232 Node zerof; 1233 Node two64f; 1234 Node two63f; 1235 1236 void 1237 bignodes(void) 1238 { 1239 static int did; 1240 1241 if(did) 1242 return; 1243 did = 1; 1244 1245 two64f = *ncon(0); 1246 two64f.type = types[TFLOAT64]; 1247 two64f.val.ctype = CTFLT; 1248 two64f.val.u.fval = mal(sizeof *two64f.val.u.fval); 1249 mpmovecflt(two64f.val.u.fval, 18446744073709551616.); 1250 1251 two63f = two64f; 1252 two63f.val.u.fval = mal(sizeof *two63f.val.u.fval); 1253 mpmovecflt(two63f.val.u.fval, 9223372036854775808.); 1254 1255 zerof = two64f; 1256 zerof.val.u.fval = mal(sizeof *zerof.val.u.fval); 1257 mpmovecflt(zerof.val.u.fval, 0); 1258 } 1259 1260 void 1261 memname(Node *n, Type *t) 1262 { 1263 tempname(n, t); 1264 strcpy(namebuf, n->sym->name); 1265 namebuf[0] = '.'; // keep optimizer from registerizing 1266 n->sym = lookup(namebuf); 1267 n->orig->sym = n->sym; 1268 } 1269 1270 static void floatmove(Node *f, Node *t); 1271 static void floatmove_387(Node *f, Node *t); 1272 static void floatmove_sse(Node *f, Node *t); 1273 1274 void 1275 gmove(Node *f, Node *t) 1276 { 1277 int a, ft, tt; 1278 Type *cvt; 1279 Node r1, r2, flo, fhi, tlo, thi, con; 1280 1281 if(debug['M']) 1282 print("gmove %N -> %N\n", f, t); 1283 1284 ft = simsimtype(f->type); 1285 tt = simsimtype(t->type); 1286 cvt = t->type; 1287 1288 if(iscomplex[ft] || iscomplex[tt]) { 1289 complexmove(f, t); 1290 return; 1291 } 1292 if(isfloat[ft] || isfloat[tt]) { 1293 floatmove(f, t); 1294 return; 1295 } 1296 1297 // cannot have two integer memory operands; 1298 // except 64-bit, which always copies via registers anyway. 1299 if(isint[ft] && isint[tt] && !is64(f->type) && !is64(t->type) && ismem(f) && ismem(t)) 1300 goto hard; 1301 1302 // convert constant to desired type 1303 if(f->op == OLITERAL) { 1304 convconst(&con, t->type, &f->val); 1305 f = &con; 1306 ft = simsimtype(con.type); 1307 } 1308 1309 // value -> value copy, only one memory operand. 1310 // figure out the instruction to use. 1311 // break out of switch for one-instruction gins. 1312 // goto rdst for "destination must be register". 1313 // goto hard for "convert to cvt type first". 1314 // otherwise handle and return. 1315 1316 switch(CASE(ft, tt)) { 1317 default: 1318 goto fatal; 1319 1320 /* 1321 * integer copy and truncate 1322 */ 1323 case CASE(TINT8, TINT8): // same size 1324 case CASE(TINT8, TUINT8): 1325 case CASE(TUINT8, TINT8): 1326 case CASE(TUINT8, TUINT8): 1327 a = AMOVB; 1328 break; 1329 1330 case CASE(TINT16, TINT8): // truncate 1331 case CASE(TUINT16, TINT8): 1332 case CASE(TINT32, TINT8): 1333 case CASE(TUINT32, TINT8): 1334 case CASE(TINT16, TUINT8): 1335 case CASE(TUINT16, TUINT8): 1336 case CASE(TINT32, TUINT8): 1337 case CASE(TUINT32, TUINT8): 1338 a = AMOVB; 1339 goto rsrc; 1340 1341 case CASE(TINT64, TINT8): // truncate low word 1342 case CASE(TUINT64, TINT8): 1343 case CASE(TINT64, TUINT8): 1344 case CASE(TUINT64, TUINT8): 1345 split64(f, &flo, &fhi); 1346 nodreg(&r1, t->type, D_AX); 1347 gmove(&flo, &r1); 1348 gins(AMOVB, &r1, t); 1349 splitclean(); 1350 return; 1351 1352 case CASE(TINT16, TINT16): // same size 1353 case CASE(TINT16, TUINT16): 1354 case CASE(TUINT16, TINT16): 1355 case CASE(TUINT16, TUINT16): 1356 a = AMOVW; 1357 break; 1358 1359 case CASE(TINT32, TINT16): // truncate 1360 case CASE(TUINT32, TINT16): 1361 case CASE(TINT32, TUINT16): 1362 case CASE(TUINT32, TUINT16): 1363 a = AMOVW; 1364 goto rsrc; 1365 1366 case CASE(TINT64, TINT16): // truncate low word 1367 case CASE(TUINT64, TINT16): 1368 case CASE(TINT64, TUINT16): 1369 case CASE(TUINT64, TUINT16): 1370 split64(f, &flo, &fhi); 1371 nodreg(&r1, t->type, D_AX); 1372 gmove(&flo, &r1); 1373 gins(AMOVW, &r1, t); 1374 splitclean(); 1375 return; 1376 1377 case CASE(TINT32, TINT32): // same size 1378 case CASE(TINT32, TUINT32): 1379 case CASE(TUINT32, TINT32): 1380 case CASE(TUINT32, TUINT32): 1381 a = AMOVL; 1382 break; 1383 1384 case CASE(TINT64, TINT32): // truncate 1385 case CASE(TUINT64, TINT32): 1386 case CASE(TINT64, TUINT32): 1387 case CASE(TUINT64, TUINT32): 1388 split64(f, &flo, &fhi); 1389 nodreg(&r1, t->type, D_AX); 1390 gmove(&flo, &r1); 1391 gins(AMOVL, &r1, t); 1392 splitclean(); 1393 return; 1394 1395 case CASE(TINT64, TINT64): // same size 1396 case CASE(TINT64, TUINT64): 1397 case CASE(TUINT64, TINT64): 1398 case CASE(TUINT64, TUINT64): 1399 split64(f, &flo, &fhi); 1400 split64(t, &tlo, &thi); 1401 if(f->op == OLITERAL) { 1402 gins(AMOVL, &flo, &tlo); 1403 gins(AMOVL, &fhi, &thi); 1404 } else { 1405 nodreg(&r1, t->type, D_AX); 1406 nodreg(&r2, t->type, D_DX); 1407 gins(AMOVL, &flo, &r1); 1408 gins(AMOVL, &fhi, &r2); 1409 gins(AMOVL, &r1, &tlo); 1410 gins(AMOVL, &r2, &thi); 1411 } 1412 splitclean(); 1413 splitclean(); 1414 return; 1415 1416 /* 1417 * integer up-conversions 1418 */ 1419 case CASE(TINT8, TINT16): // sign extend int8 1420 case CASE(TINT8, TUINT16): 1421 a = AMOVBWSX; 1422 goto rdst; 1423 case CASE(TINT8, TINT32): 1424 case CASE(TINT8, TUINT32): 1425 a = AMOVBLSX; 1426 goto rdst; 1427 case CASE(TINT8, TINT64): // convert via int32 1428 case CASE(TINT8, TUINT64): 1429 cvt = types[TINT32]; 1430 goto hard; 1431 1432 case CASE(TUINT8, TINT16): // zero extend uint8 1433 case CASE(TUINT8, TUINT16): 1434 a = AMOVBWZX; 1435 goto rdst; 1436 case CASE(TUINT8, TINT32): 1437 case CASE(TUINT8, TUINT32): 1438 a = AMOVBLZX; 1439 goto rdst; 1440 case CASE(TUINT8, TINT64): // convert via uint32 1441 case CASE(TUINT8, TUINT64): 1442 cvt = types[TUINT32]; 1443 goto hard; 1444 1445 case CASE(TINT16, TINT32): // sign extend int16 1446 case CASE(TINT16, TUINT32): 1447 a = AMOVWLSX; 1448 goto rdst; 1449 case CASE(TINT16, TINT64): // convert via int32 1450 case CASE(TINT16, TUINT64): 1451 cvt = types[TINT32]; 1452 goto hard; 1453 1454 case CASE(TUINT16, TINT32): // zero extend uint16 1455 case CASE(TUINT16, TUINT32): 1456 a = AMOVWLZX; 1457 goto rdst; 1458 case CASE(TUINT16, TINT64): // convert via uint32 1459 case CASE(TUINT16, TUINT64): 1460 cvt = types[TUINT32]; 1461 goto hard; 1462 1463 case CASE(TINT32, TINT64): // sign extend int32 1464 case CASE(TINT32, TUINT64): 1465 split64(t, &tlo, &thi); 1466 nodreg(&flo, tlo.type, D_AX); 1467 nodreg(&fhi, thi.type, D_DX); 1468 gmove(f, &flo); 1469 gins(ACDQ, N, N); 1470 gins(AMOVL, &flo, &tlo); 1471 gins(AMOVL, &fhi, &thi); 1472 splitclean(); 1473 return; 1474 1475 case CASE(TUINT32, TINT64): // zero extend uint32 1476 case CASE(TUINT32, TUINT64): 1477 split64(t, &tlo, &thi); 1478 gmove(f, &tlo); 1479 gins(AMOVL, ncon(0), &thi); 1480 splitclean(); 1481 return; 1482 } 1483 1484 gins(a, f, t); 1485 return; 1486 1487 rsrc: 1488 // requires register source 1489 regalloc(&r1, f->type, t); 1490 gmove(f, &r1); 1491 gins(a, &r1, t); 1492 regfree(&r1); 1493 return; 1494 1495 rdst: 1496 // requires register destination 1497 regalloc(&r1, t->type, t); 1498 gins(a, f, &r1); 1499 gmove(&r1, t); 1500 regfree(&r1); 1501 return; 1502 1503 hard: 1504 // requires register intermediate 1505 regalloc(&r1, cvt, t); 1506 gmove(f, &r1); 1507 gmove(&r1, t); 1508 regfree(&r1); 1509 return; 1510 1511 fatal: 1512 // should not happen 1513 fatal("gmove %N -> %N", f, t); 1514 } 1515 1516 static void 1517 floatmove(Node *f, Node *t) 1518 { 1519 Node r1, r2, t1, t2, tlo, thi, con, f0, f1, ax, dx, cx; 1520 Type *cvt; 1521 int ft, tt; 1522 Prog *p1, *p2, *p3; 1523 1524 ft = simsimtype(f->type); 1525 tt = simsimtype(t->type); 1526 cvt = t->type; 1527 1528 // cannot have two floating point memory operands. 1529 if(isfloat[ft] && isfloat[tt] && ismem(f) && ismem(t)) 1530 goto hard; 1531 1532 // convert constant to desired type 1533 if(f->op == OLITERAL) { 1534 convconst(&con, t->type, &f->val); 1535 f = &con; 1536 ft = simsimtype(con.type); 1537 1538 // some constants can't move directly to memory. 1539 if(ismem(t)) { 1540 // float constants come from memory. 1541 if(isfloat[tt]) 1542 goto hard; 1543 } 1544 } 1545 1546 // value -> value copy, only one memory operand. 1547 // figure out the instruction to use. 1548 // break out of switch for one-instruction gins. 1549 // goto rdst for "destination must be register". 1550 // goto hard for "convert to cvt type first". 1551 // otherwise handle and return. 1552 1553 switch(CASE(ft, tt)) { 1554 default: 1555 if(use_sse) 1556 floatmove_sse(f, t); 1557 else 1558 floatmove_387(f, t); 1559 return; 1560 1561 // float to very long integer. 1562 case CASE(TFLOAT32, TINT64): 1563 case CASE(TFLOAT64, TINT64): 1564 if(f->op == OREGISTER) { 1565 cvt = f->type; 1566 goto hardmem; 1567 } 1568 nodreg(&r1, types[ft], D_F0); 1569 if(ft == TFLOAT32) 1570 gins(AFMOVF, f, &r1); 1571 else 1572 gins(AFMOVD, f, &r1); 1573 1574 // set round to zero mode during conversion 1575 memname(&t1, types[TUINT16]); 1576 memname(&t2, types[TUINT16]); 1577 gins(AFSTCW, N, &t1); 1578 gins(AMOVW, ncon(0xf7f), &t2); 1579 gins(AFLDCW, &t2, N); 1580 if(tt == TINT16) 1581 gins(AFMOVWP, &r1, t); 1582 else if(tt == TINT32) 1583 gins(AFMOVLP, &r1, t); 1584 else 1585 gins(AFMOVVP, &r1, t); 1586 gins(AFLDCW, &t1, N); 1587 return; 1588 1589 case CASE(TFLOAT32, TUINT64): 1590 case CASE(TFLOAT64, TUINT64): 1591 if(!ismem(f)) { 1592 cvt = f->type; 1593 goto hardmem; 1594 } 1595 bignodes(); 1596 nodreg(&f0, types[ft], D_F0); 1597 nodreg(&f1, types[ft], D_F0 + 1); 1598 nodreg(&ax, types[TUINT16], D_AX); 1599 1600 if(ft == TFLOAT32) 1601 gins(AFMOVF, f, &f0); 1602 else 1603 gins(AFMOVD, f, &f0); 1604 1605 // if 0 > v { answer = 0 } 1606 gins(AFMOVD, &zerof, &f0); 1607 gins(AFUCOMIP, &f0, &f1); 1608 p1 = gbranch(optoas(OGT, types[tt]), T, 0); 1609 // if 1<<64 <= v { answer = 0 too } 1610 gins(AFMOVD, &two64f, &f0); 1611 gins(AFUCOMIP, &f0, &f1); 1612 p2 = gbranch(optoas(OGT, types[tt]), T, 0); 1613 patch(p1, pc); 1614 gins(AFMOVVP, &f0, t); // don't care about t, but will pop the stack 1615 split64(t, &tlo, &thi); 1616 gins(AMOVL, ncon(0), &tlo); 1617 gins(AMOVL, ncon(0), &thi); 1618 splitclean(); 1619 p1 = gbranch(AJMP, T, 0); 1620 patch(p2, pc); 1621 1622 // in range; algorithm is: 1623 // if small enough, use native float64 -> int64 conversion. 1624 // otherwise, subtract 2^63, convert, and add it back. 1625 1626 // set round to zero mode during conversion 1627 memname(&t1, types[TUINT16]); 1628 memname(&t2, types[TUINT16]); 1629 gins(AFSTCW, N, &t1); 1630 gins(AMOVW, ncon(0xf7f), &t2); 1631 gins(AFLDCW, &t2, N); 1632 1633 // actual work 1634 gins(AFMOVD, &two63f, &f0); 1635 gins(AFUCOMIP, &f0, &f1); 1636 p2 = gbranch(optoas(OLE, types[tt]), T, 0); 1637 gins(AFMOVVP, &f0, t); 1638 p3 = gbranch(AJMP, T, 0); 1639 patch(p2, pc); 1640 gins(AFMOVD, &two63f, &f0); 1641 gins(AFSUBDP, &f0, &f1); 1642 gins(AFMOVVP, &f0, t); 1643 split64(t, &tlo, &thi); 1644 gins(AXORL, ncon(0x80000000), &thi); // + 2^63 1645 patch(p3, pc); 1646 splitclean(); 1647 // restore rounding mode 1648 gins(AFLDCW, &t1, N); 1649 1650 patch(p1, pc); 1651 return; 1652 1653 /* 1654 * integer to float 1655 */ 1656 case CASE(TINT64, TFLOAT32): 1657 case CASE(TINT64, TFLOAT64): 1658 if(t->op == OREGISTER) 1659 goto hardmem; 1660 nodreg(&f0, t->type, D_F0); 1661 gins(AFMOVV, f, &f0); 1662 if(tt == TFLOAT32) 1663 gins(AFMOVFP, &f0, t); 1664 else 1665 gins(AFMOVDP, &f0, t); 1666 return; 1667 1668 case CASE(TUINT64, TFLOAT32): 1669 case CASE(TUINT64, TFLOAT64): 1670 // algorithm is: 1671 // if small enough, use native int64 -> float64 conversion. 1672 // otherwise, halve (rounding to odd?), convert, and double. 1673 nodreg(&ax, types[TUINT32], D_AX); 1674 nodreg(&dx, types[TUINT32], D_DX); 1675 nodreg(&cx, types[TUINT32], D_CX); 1676 tempname(&t1, f->type); 1677 split64(&t1, &tlo, &thi); 1678 gmove(f, &t1); 1679 gins(ACMPL, &thi, ncon(0)); 1680 p1 = gbranch(AJLT, T, 0); 1681 // native 1682 t1.type = types[TINT64]; 1683 nodreg(&r1, types[tt], D_F0); 1684 gins(AFMOVV, &t1, &r1); 1685 if(tt == TFLOAT32) 1686 gins(AFMOVFP, &r1, t); 1687 else 1688 gins(AFMOVDP, &r1, t); 1689 p2 = gbranch(AJMP, T, 0); 1690 // simulated 1691 patch(p1, pc); 1692 gmove(&tlo, &ax); 1693 gmove(&thi, &dx); 1694 p1 = gins(ASHRL, ncon(1), &ax); 1695 p1->from.index = D_DX; // double-width shift DX -> AX 1696 p1->from.scale = 0; 1697 gins(AMOVL, ncon(0), &cx); 1698 gins(ASETCC, N, &cx); 1699 gins(AORL, &cx, &ax); 1700 gins(ASHRL, ncon(1), &dx); 1701 gmove(&dx, &thi); 1702 gmove(&ax, &tlo); 1703 nodreg(&r1, types[tt], D_F0); 1704 nodreg(&r2, types[tt], D_F0 + 1); 1705 gins(AFMOVV, &t1, &r1); 1706 gins(AFMOVD, &r1, &r1); 1707 gins(AFADDDP, &r1, &r2); 1708 if(tt == TFLOAT32) 1709 gins(AFMOVFP, &r1, t); 1710 else 1711 gins(AFMOVDP, &r1, t); 1712 patch(p2, pc); 1713 splitclean(); 1714 return; 1715 } 1716 1717 hard: 1718 // requires register intermediate 1719 regalloc(&r1, cvt, t); 1720 gmove(f, &r1); 1721 gmove(&r1, t); 1722 regfree(&r1); 1723 return; 1724 1725 hardmem: 1726 // requires memory intermediate 1727 tempname(&r1, cvt); 1728 gmove(f, &r1); 1729 gmove(&r1, t); 1730 return; 1731 } 1732 1733 static void 1734 floatmove_387(Node *f, Node *t) 1735 { 1736 Node r1, t1, t2; 1737 Type *cvt; 1738 Prog *p1, *p2, *p3; 1739 int a, ft, tt; 1740 1741 ft = simsimtype(f->type); 1742 tt = simsimtype(t->type); 1743 cvt = t->type; 1744 1745 switch(CASE(ft, tt)) { 1746 default: 1747 goto fatal; 1748 1749 /* 1750 * float to integer 1751 */ 1752 case CASE(TFLOAT32, TINT16): 1753 case CASE(TFLOAT32, TINT32): 1754 case CASE(TFLOAT32, TINT64): 1755 case CASE(TFLOAT64, TINT16): 1756 case CASE(TFLOAT64, TINT32): 1757 case CASE(TFLOAT64, TINT64): 1758 if(t->op == OREGISTER) 1759 goto hardmem; 1760 nodreg(&r1, types[ft], D_F0); 1761 if(f->op != OREGISTER) { 1762 if(ft == TFLOAT32) 1763 gins(AFMOVF, f, &r1); 1764 else 1765 gins(AFMOVD, f, &r1); 1766 } 1767 1768 // set round to zero mode during conversion 1769 memname(&t1, types[TUINT16]); 1770 memname(&t2, types[TUINT16]); 1771 gins(AFSTCW, N, &t1); 1772 gins(AMOVW, ncon(0xf7f), &t2); 1773 gins(AFLDCW, &t2, N); 1774 if(tt == TINT16) 1775 gins(AFMOVWP, &r1, t); 1776 else if(tt == TINT32) 1777 gins(AFMOVLP, &r1, t); 1778 else 1779 gins(AFMOVVP, &r1, t); 1780 gins(AFLDCW, &t1, N); 1781 return; 1782 1783 case CASE(TFLOAT32, TINT8): 1784 case CASE(TFLOAT32, TUINT16): 1785 case CASE(TFLOAT32, TUINT8): 1786 case CASE(TFLOAT64, TINT8): 1787 case CASE(TFLOAT64, TUINT16): 1788 case CASE(TFLOAT64, TUINT8): 1789 // convert via int32. 1790 tempname(&t1, types[TINT32]); 1791 gmove(f, &t1); 1792 switch(tt) { 1793 default: 1794 fatal("gmove %T", t); 1795 case TINT8: 1796 gins(ACMPL, &t1, ncon(-0x80)); 1797 p1 = gbranch(optoas(OLT, types[TINT32]), T, -1); 1798 gins(ACMPL, &t1, ncon(0x7f)); 1799 p2 = gbranch(optoas(OGT, types[TINT32]), T, -1); 1800 p3 = gbranch(AJMP, T, 0); 1801 patch(p1, pc); 1802 patch(p2, pc); 1803 gmove(ncon(-0x80), &t1); 1804 patch(p3, pc); 1805 gmove(&t1, t); 1806 break; 1807 case TUINT8: 1808 gins(ATESTL, ncon(0xffffff00), &t1); 1809 p1 = gbranch(AJEQ, T, +1); 1810 gins(AMOVL, ncon(0), &t1); 1811 patch(p1, pc); 1812 gmove(&t1, t); 1813 break; 1814 case TUINT16: 1815 gins(ATESTL, ncon(0xffff0000), &t1); 1816 p1 = gbranch(AJEQ, T, +1); 1817 gins(AMOVL, ncon(0), &t1); 1818 patch(p1, pc); 1819 gmove(&t1, t); 1820 break; 1821 } 1822 return; 1823 1824 case CASE(TFLOAT32, TUINT32): 1825 case CASE(TFLOAT64, TUINT32): 1826 // convert via int64. 1827 cvt = types[TINT64]; 1828 goto hardmem; 1829 1830 /* 1831 * integer to float 1832 */ 1833 case CASE(TINT16, TFLOAT32): 1834 case CASE(TINT16, TFLOAT64): 1835 case CASE(TINT32, TFLOAT32): 1836 case CASE(TINT32, TFLOAT64): 1837 case CASE(TINT64, TFLOAT32): 1838 case CASE(TINT64, TFLOAT64): 1839 if(t->op != OREGISTER) 1840 goto hard; 1841 if(f->op == OREGISTER) { 1842 cvt = f->type; 1843 goto hardmem; 1844 } 1845 switch(ft) { 1846 case TINT16: 1847 a = AFMOVW; 1848 break; 1849 case TINT32: 1850 a = AFMOVL; 1851 break; 1852 default: 1853 a = AFMOVV; 1854 break; 1855 } 1856 break; 1857 1858 case CASE(TINT8, TFLOAT32): 1859 case CASE(TINT8, TFLOAT64): 1860 case CASE(TUINT16, TFLOAT32): 1861 case CASE(TUINT16, TFLOAT64): 1862 case CASE(TUINT8, TFLOAT32): 1863 case CASE(TUINT8, TFLOAT64): 1864 // convert via int32 memory 1865 cvt = types[TINT32]; 1866 goto hardmem; 1867 1868 case CASE(TUINT32, TFLOAT32): 1869 case CASE(TUINT32, TFLOAT64): 1870 // convert via int64 memory 1871 cvt = types[TINT64]; 1872 goto hardmem; 1873 1874 /* 1875 * float to float 1876 */ 1877 case CASE(TFLOAT32, TFLOAT32): 1878 case CASE(TFLOAT64, TFLOAT64): 1879 // The way the code generator uses floating-point 1880 // registers, a move from F0 to F0 is intended as a no-op. 1881 // On the x86, it's not: it pushes a second copy of F0 1882 // on the floating point stack. So toss it away here. 1883 // Also, F0 is the *only* register we ever evaluate 1884 // into, so we should only see register/register as F0/F0. 1885 if(ismem(f) && ismem(t)) 1886 goto hard; 1887 if(f->op == OREGISTER && t->op == OREGISTER) { 1888 if(f->val.u.reg != D_F0 || t->val.u.reg != D_F0) 1889 goto fatal; 1890 return; 1891 } 1892 a = AFMOVF; 1893 if(ft == TFLOAT64) 1894 a = AFMOVD; 1895 if(ismem(t)) { 1896 if(f->op != OREGISTER || f->val.u.reg != D_F0) 1897 fatal("gmove %N", f); 1898 a = AFMOVFP; 1899 if(ft == TFLOAT64) 1900 a = AFMOVDP; 1901 } 1902 break; 1903 1904 case CASE(TFLOAT32, TFLOAT64): 1905 if(ismem(f) && ismem(t)) 1906 goto hard; 1907 if(f->op == OREGISTER && t->op == OREGISTER) { 1908 if(f->val.u.reg != D_F0 || t->val.u.reg != D_F0) 1909 goto fatal; 1910 return; 1911 } 1912 if(f->op == OREGISTER) 1913 gins(AFMOVDP, f, t); 1914 else 1915 gins(AFMOVF, f, t); 1916 return; 1917 1918 case CASE(TFLOAT64, TFLOAT32): 1919 if(ismem(f) && ismem(t)) 1920 goto hard; 1921 if(f->op == OREGISTER && t->op == OREGISTER) { 1922 tempname(&r1, types[TFLOAT32]); 1923 gins(AFMOVFP, f, &r1); 1924 gins(AFMOVF, &r1, t); 1925 return; 1926 } 1927 if(f->op == OREGISTER) 1928 gins(AFMOVFP, f, t); 1929 else 1930 gins(AFMOVD, f, t); 1931 return; 1932 } 1933 1934 gins(a, f, t); 1935 return; 1936 1937 hard: 1938 // requires register intermediate 1939 regalloc(&r1, cvt, t); 1940 gmove(f, &r1); 1941 gmove(&r1, t); 1942 regfree(&r1); 1943 return; 1944 1945 hardmem: 1946 // requires memory intermediate 1947 tempname(&r1, cvt); 1948 gmove(f, &r1); 1949 gmove(&r1, t); 1950 return; 1951 1952 fatal: 1953 // should not happen 1954 fatal("gmove %lN -> %lN", f, t); 1955 return; 1956 } 1957 1958 static void 1959 floatmove_sse(Node *f, Node *t) 1960 { 1961 Node r1; 1962 Type *cvt; 1963 int a, ft, tt; 1964 1965 ft = simsimtype(f->type); 1966 tt = simsimtype(t->type); 1967 1968 switch(CASE(ft, tt)) { 1969 default: 1970 // should not happen 1971 fatal("gmove %N -> %N", f, t); 1972 return; 1973 /* 1974 * float to integer 1975 */ 1976 case CASE(TFLOAT32, TINT16): 1977 case CASE(TFLOAT32, TINT8): 1978 case CASE(TFLOAT32, TUINT16): 1979 case CASE(TFLOAT32, TUINT8): 1980 case CASE(TFLOAT64, TINT16): 1981 case CASE(TFLOAT64, TINT8): 1982 case CASE(TFLOAT64, TUINT16): 1983 case CASE(TFLOAT64, TUINT8): 1984 // convert via int32. 1985 cvt = types[TINT32]; 1986 goto hard; 1987 1988 case CASE(TFLOAT32, TUINT32): 1989 case CASE(TFLOAT64, TUINT32): 1990 // convert via int64. 1991 cvt = types[TINT64]; 1992 goto hardmem; 1993 1994 case CASE(TFLOAT32, TINT32): 1995 a = ACVTTSS2SL; 1996 goto rdst; 1997 1998 case CASE(TFLOAT64, TINT32): 1999 a = ACVTTSD2SL; 2000 goto rdst; 2001 2002 /* 2003 * integer to float 2004 */ 2005 case CASE(TINT8, TFLOAT32): 2006 case CASE(TINT8, TFLOAT64): 2007 case CASE(TINT16, TFLOAT32): 2008 case CASE(TINT16, TFLOAT64): 2009 case CASE(TUINT16, TFLOAT32): 2010 case CASE(TUINT16, TFLOAT64): 2011 case CASE(TUINT8, TFLOAT32): 2012 case CASE(TUINT8, TFLOAT64): 2013 // convert via int32 memory 2014 cvt = types[TINT32]; 2015 goto hard; 2016 2017 case CASE(TUINT32, TFLOAT32): 2018 case CASE(TUINT32, TFLOAT64): 2019 // convert via int64 memory 2020 cvt = types[TINT64]; 2021 goto hardmem; 2022 2023 case CASE(TINT32, TFLOAT32): 2024 a = ACVTSL2SS; 2025 goto rdst; 2026 2027 case CASE(TINT32, TFLOAT64): 2028 a = ACVTSL2SD; 2029 goto rdst; 2030 2031 /* 2032 * float to float 2033 */ 2034 case CASE(TFLOAT32, TFLOAT32): 2035 a = AMOVSS; 2036 break; 2037 2038 case CASE(TFLOAT64, TFLOAT64): 2039 a = AMOVSD; 2040 break; 2041 2042 case CASE(TFLOAT32, TFLOAT64): 2043 a = ACVTSS2SD; 2044 goto rdst; 2045 2046 case CASE(TFLOAT64, TFLOAT32): 2047 a = ACVTSD2SS; 2048 goto rdst; 2049 } 2050 2051 gins(a, f, t); 2052 return; 2053 2054 hard: 2055 // requires register intermediate 2056 regalloc(&r1, cvt, t); 2057 gmove(f, &r1); 2058 gmove(&r1, t); 2059 regfree(&r1); 2060 return; 2061 2062 hardmem: 2063 // requires memory intermediate 2064 tempname(&r1, cvt); 2065 gmove(f, &r1); 2066 gmove(&r1, t); 2067 return; 2068 2069 rdst: 2070 // requires register destination 2071 regalloc(&r1, t->type, t); 2072 gins(a, f, &r1); 2073 gmove(&r1, t); 2074 regfree(&r1); 2075 return; 2076 } 2077 2078 int 2079 samaddr(Node *f, Node *t) 2080 { 2081 2082 if(f->op != t->op) 2083 return 0; 2084 2085 switch(f->op) { 2086 case OREGISTER: 2087 if(f->val.u.reg != t->val.u.reg) 2088 break; 2089 return 1; 2090 } 2091 return 0; 2092 } 2093 /* 2094 * generate one instruction: 2095 * as f, t 2096 */ 2097 Prog* 2098 gins(int as, Node *f, Node *t) 2099 { 2100 Prog *p; 2101 Addr af, at; 2102 int w; 2103 2104 if(as == AFMOVF && f && f->op == OREGISTER && t && t->op == OREGISTER) 2105 fatal("gins MOVF reg, reg"); 2106 if(as == ACVTSD2SS && f && f->op == OLITERAL) 2107 fatal("gins CVTSD2SS const"); 2108 if(as == AMOVSD && t && t->op == OREGISTER && t->val.u.reg == D_F0) 2109 fatal("gins MOVSD into F0"); 2110 2111 switch(as) { 2112 case AMOVB: 2113 case AMOVW: 2114 case AMOVL: 2115 if(f != N && t != N && samaddr(f, t)) 2116 return nil; 2117 break; 2118 2119 case ALEAL: 2120 if(f != N && isconst(f, CTNIL)) 2121 fatal("gins LEAL nil %T", f->type); 2122 break; 2123 } 2124 2125 memset(&af, 0, sizeof af); 2126 memset(&at, 0, sizeof at); 2127 if(f != N) 2128 naddr(f, &af, 1); 2129 if(t != N) 2130 naddr(t, &at, 1); 2131 p = prog(as); 2132 if(f != N) 2133 p->from = af; 2134 if(t != N) 2135 p->to = at; 2136 if(debug['g']) 2137 print("%P\n", p); 2138 2139 w = 0; 2140 switch(as) { 2141 case AMOVB: 2142 w = 1; 2143 break; 2144 case AMOVW: 2145 w = 2; 2146 break; 2147 case AMOVL: 2148 w = 4; 2149 break; 2150 } 2151 2152 if(1 && w != 0 && f != N && (af.width > w || at.width > w)) { 2153 dump("bad width from:", f); 2154 dump("bad width to:", t); 2155 fatal("bad width: %P (%d, %d)\n", p, af.width, at.width); 2156 } 2157 2158 return p; 2159 } 2160 2161 // Generate an instruction referencing *n 2162 // to force segv on nil pointer dereference. 2163 void 2164 checkref(Node *n, int force) 2165 { 2166 Node m; 2167 2168 if(!force && isptr[n->type->etype] && n->type->type->width < unmappedzero) 2169 return; 2170 2171 regalloc(&m, types[TUINTPTR], n); 2172 cgen(n, &m); 2173 m.xoffset = 0; 2174 m.op = OINDREG; 2175 m.type = types[TUINT8]; 2176 gins(ATESTB, nodintconst(0), &m); 2177 regfree(&m); 2178 } 2179 2180 static void 2181 checkoffset(Addr *a, int canemitcode) 2182 { 2183 Prog *p; 2184 2185 if(a->offset < unmappedzero) 2186 return; 2187 if(!canemitcode) 2188 fatal("checkoffset %#x, cannot emit code", a->offset); 2189 2190 // cannot rely on unmapped nil page at 0 to catch 2191 // reference with large offset. instead, emit explicit 2192 // test of 0(reg). 2193 p = gins(ATESTB, nodintconst(0), N); 2194 p->to = *a; 2195 p->to.offset = 0; 2196 } 2197 2198 /* 2199 * generate code to compute n; 2200 * make a refer to result. 2201 */ 2202 void 2203 naddr(Node *n, Addr *a, int canemitcode) 2204 { 2205 a->scale = 0; 2206 a->index = D_NONE; 2207 a->type = D_NONE; 2208 a->gotype = S; 2209 a->node = N; 2210 if(n == N) 2211 return; 2212 2213 switch(n->op) { 2214 default: 2215 fatal("naddr: bad %O %D", n->op, a); 2216 break; 2217 2218 case OREGISTER: 2219 a->type = n->val.u.reg; 2220 a->sym = S; 2221 break; 2222 2223 case OINDREG: 2224 a->type = n->val.u.reg+D_INDIR; 2225 a->sym = n->sym; 2226 a->offset = n->xoffset; 2227 break; 2228 2229 case OPARAM: 2230 // n->left is PHEAP ONAME for stack parameter. 2231 // compute address of actual parameter on stack. 2232 a->etype = n->left->type->etype; 2233 a->width = n->left->type->width; 2234 a->offset = n->xoffset; 2235 a->sym = n->left->sym; 2236 a->type = D_PARAM; 2237 a->node = n->left->orig; 2238 break; 2239 2240 case OCLOSUREVAR: 2241 a->type = D_DX+D_INDIR; 2242 a->offset = n->xoffset; 2243 a->sym = S; 2244 break; 2245 2246 case OCFUNC: 2247 naddr(n->left, a, canemitcode); 2248 a->sym = n->left->sym; 2249 break; 2250 2251 case ONAME: 2252 a->etype = 0; 2253 a->width = 0; 2254 if(n->type != T) { 2255 a->etype = simtype[n->type->etype]; 2256 dowidth(n->type); 2257 a->width = n->type->width; 2258 } 2259 a->offset = n->xoffset; 2260 a->sym = n->sym; 2261 a->node = n->orig; 2262 //if(a->node >= (Node*)&n) 2263 // fatal("stack node"); 2264 if(a->sym == S) 2265 a->sym = lookup(".noname"); 2266 if(n->method) { 2267 if(n->type != T) 2268 if(n->type->sym != S) 2269 if(n->type->sym->pkg != nil) 2270 a->sym = pkglookup(a->sym->name, n->type->sym->pkg); 2271 } 2272 2273 switch(n->class) { 2274 default: 2275 fatal("naddr: ONAME class %S %d\n", n->sym, n->class); 2276 case PEXTERN: 2277 a->type = D_EXTERN; 2278 break; 2279 case PAUTO: 2280 a->type = D_AUTO; 2281 break; 2282 case PPARAM: 2283 case PPARAMOUT: 2284 a->type = D_PARAM; 2285 break; 2286 case PFUNC: 2287 a->index = D_EXTERN; 2288 a->type = D_ADDR; 2289 a->sym = funcsym(a->sym); 2290 break; 2291 } 2292 break; 2293 2294 case OLITERAL: 2295 switch(n->val.ctype) { 2296 default: 2297 fatal("naddr: const %lT", n->type); 2298 break; 2299 case CTFLT: 2300 a->type = D_FCONST; 2301 a->u.dval = mpgetflt(n->val.u.fval); 2302 break; 2303 case CTINT: 2304 case CTRUNE: 2305 a->sym = S; 2306 a->type = D_CONST; 2307 a->offset = mpgetfix(n->val.u.xval); 2308 break; 2309 case CTSTR: 2310 datagostring(n->val.u.sval, a); 2311 break; 2312 case CTBOOL: 2313 a->sym = S; 2314 a->type = D_CONST; 2315 a->offset = n->val.u.bval; 2316 break; 2317 case CTNIL: 2318 a->sym = S; 2319 a->type = D_CONST; 2320 a->offset = 0; 2321 break; 2322 } 2323 break; 2324 2325 case OADDR: 2326 naddr(n->left, a, canemitcode); 2327 if(a->type >= D_INDIR) { 2328 a->type -= D_INDIR; 2329 break; 2330 } 2331 if(a->type == D_EXTERN || a->type == D_STATIC || 2332 a->type == D_AUTO || a->type == D_PARAM) 2333 if(a->index == D_NONE) { 2334 a->index = a->type; 2335 a->type = D_ADDR; 2336 break; 2337 } 2338 fatal("naddr: OADDR\n"); 2339 2340 case OITAB: 2341 // itable of interface value 2342 naddr(n->left, a, canemitcode); 2343 if(a->type == D_CONST && a->offset == 0) 2344 break; // len(nil) 2345 a->etype = tptr; 2346 a->width = widthptr; 2347 if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero) 2348 checkoffset(a, canemitcode); 2349 break; 2350 2351 case OLEN: 2352 // len of string or slice 2353 naddr(n->left, a, canemitcode); 2354 if(a->type == D_CONST && a->offset == 0) 2355 break; // len(nil) 2356 a->etype = TUINT32; 2357 a->offset += Array_nel; 2358 a->width = 4; 2359 if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero) 2360 checkoffset(a, canemitcode); 2361 break; 2362 2363 case OCAP: 2364 // cap of string or slice 2365 naddr(n->left, a, canemitcode); 2366 if(a->type == D_CONST && a->offset == 0) 2367 break; // cap(nil) 2368 a->etype = TUINT32; 2369 a->offset += Array_cap; 2370 a->width = 4; 2371 if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero) 2372 checkoffset(a, canemitcode); 2373 break; 2374 2375 // case OADD: 2376 // if(n->right->op == OLITERAL) { 2377 // v = n->right->vconst; 2378 // naddr(n->left, a, canemitcode); 2379 // } else 2380 // if(n->left->op == OLITERAL) { 2381 // v = n->left->vconst; 2382 // naddr(n->right, a, canemitcode); 2383 // } else 2384 // goto bad; 2385 // a->offset += v; 2386 // break; 2387 2388 } 2389 } 2390 2391 int 2392 dotaddable(Node *n, Node *n1) 2393 { 2394 int o; 2395 int64 oary[10]; 2396 Node *nn; 2397 2398 if(n->op != ODOT) 2399 return 0; 2400 2401 o = dotoffset(n, oary, &nn); 2402 if(nn != N && nn->addable && o == 1 && oary[0] >= 0) { 2403 *n1 = *nn; 2404 n1->type = n->type; 2405 n1->xoffset += oary[0]; 2406 return 1; 2407 } 2408 return 0; 2409 } 2410 2411 void 2412 sudoclean(void) 2413 { 2414 } 2415 2416 int 2417 sudoaddable(int as, Node *n, Addr *a) 2418 { 2419 USED(as); 2420 USED(n); 2421 USED(a); 2422 2423 return 0; 2424 }