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