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