github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/src/cmd/9g/gsubr.c (about) 1 // Derived from Inferno utils/6c/txt.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6c/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 6l for all GOOS. 38 // At the same time, can raise StackBig in ../../runtime/stack.h. 39 vlong unmappedzero = 4096; 40 41 void 42 clearp(Prog *p) 43 { 44 *p = zprog; 45 p->as = AEND; 46 p->pc = pcloc; 47 pcloc++; 48 } 49 50 static int ddumped; 51 static Prog *dfirst; 52 static Prog *dpc; 53 54 /* 55 * generate and return proc with p->as = as, 56 * linked into program. pc is next instruction. 57 */ 58 Prog* 59 prog(int as) 60 { 61 Prog *p; 62 63 if(as == ADATA || as == AGLOBL) { 64 if(ddumped) 65 fatal("already dumped data"); 66 if(dpc == nil) { 67 dpc = mal(sizeof(*dpc)); 68 dfirst = dpc; 69 } 70 p = dpc; 71 dpc = mal(sizeof(*dpc)); 72 p->link = dpc; 73 p->reg = 0; // used for flags 74 } else { 75 p = pc; 76 pc = mal(sizeof(*pc)); 77 clearp(pc); 78 p->link = pc; 79 } 80 81 if(lineno == 0) { 82 if(debug['K']) 83 warn("prog: line 0"); 84 } 85 86 p->as = as; 87 p->lineno = lineno; 88 return p; 89 } 90 91 void 92 dumpdata(void) 93 { 94 ddumped = 1; 95 if(dfirst == nil) 96 return; 97 newplist(); 98 *pc = *dfirst; 99 pc = dpc; 100 clearp(pc); 101 } 102 103 /* 104 * generate a branch. 105 * t is ignored. 106 * likely values are for branch prediction: 107 * -1 unlikely 108 * 0 no opinion 109 * +1 likely 110 */ 111 Prog* 112 gbranch(int as, Type *t, int likely) 113 { 114 Prog *p; 115 116 USED(t); 117 118 p = prog(as); 119 p->to.type = D_BRANCH; 120 p->to.u.branch = P; 121 // TODO(minux): Enable this code. 122 // Note: liblink used Bcc CR0, label form, so we need another way 123 // to set likely/unlikely flag. Also note the y bit is not exactly 124 // likely/unlikely bit. 125 if(0 && as != ABR && 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(ABR, 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->reg = RODATA; 204 if(nam->type != T && !haspointers(nam->type)) 205 p->reg |= NOPTR; 206 } 207 208 void 209 gtrack(Sym *s) 210 { 211 Prog *p; 212 213 p = gins(AUSEFIELD, N, N); 214 p->from.type = D_OREG; 215 p->from.name = D_EXTERN; 216 p->from.sym = linksym(s); 217 } 218 219 void 220 ggloblsym(Sym *s, int32 width, int8 flags) 221 { 222 Prog *p; 223 224 p = gins(AGLOBL, N, N); 225 p->from.type = D_OREG; 226 p->from.name = D_EXTERN; 227 p->from.sym = linksym(s); 228 p->to.type = D_CONST; 229 p->to.name = D_NONE; 230 p->to.offset = width; 231 p->reg = flags; 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_CONST && a->name == D_EXTERN) { 257 a->type = D_OREG; 258 a->sym = linksym(n->sym); 259 } 260 } 261 262 static int resvd[] = 263 { 264 REGZERO, 265 REGSP, // reserved for SP, XXX: not reserved in 9c. 266 30, // for g 267 REGTMP, // REGTMP 268 FREGCVI+NREG, 269 FREGZERO+NREG, 270 FREGHALF+NREG, 271 FREGONE+NREG, 272 FREGTWO+NREG, 273 }; 274 275 void 276 ginit(void) 277 { 278 int i; 279 280 for(i=0; i<nelem(reg); i++) 281 reg[i] = 1; 282 for(i=0; i<NREG; i++) 283 reg[i] = 0; 284 for(i=NREG; i<NREG+NREG; i++) 285 reg[i] = 0; 286 287 for(i=0; i<nelem(resvd); i++) 288 reg[resvd[i]]++; 289 } 290 291 static uintptr regpc[nelem(reg)]; 292 293 void 294 gclean(void) 295 { 296 int i; 297 298 for(i=0; i<nelem(resvd); i++) 299 reg[resvd[i]]--; 300 301 for(i=0; i<nelem(reg); i++) 302 if(reg[i]) 303 yyerror("reg %R left allocated, %p\n", i, regpc[i]); 304 } 305 306 int32 307 anyregalloc(void) 308 { 309 int i, j; 310 311 for(i=0; i<nelem(reg); i++) { 312 if(reg[i] == 0) 313 goto ok; 314 for(j=0; j<nelem(resvd); j++) 315 if(resvd[j] == i) 316 goto ok; 317 return 1; 318 ok:; 319 } 320 return 0; 321 } 322 323 /* 324 * allocate register of type t, leave in n. 325 * if o != N, o is desired fixed register. 326 * caller must regfree(n). 327 */ 328 void 329 regalloc(Node *n, Type *t, Node *o) 330 { 331 int i, et; 332 int fixfree, fltfree; 333 334 if(t == T) 335 fatal("regalloc: t nil"); 336 et = simtype[t->etype]; 337 338 if(debug['r']) { 339 fixfree = 0; 340 fltfree = 0; 341 for(i = D_R0; i < D_F0+NREG; i++) 342 if(reg[i] == 0) { 343 if(i < D_F0) 344 fixfree++; 345 else 346 fltfree++; 347 } 348 print("regalloc fix %d flt %d free\n", fixfree, fltfree); 349 } 350 351 switch(et) { 352 case TINT8: 353 case TUINT8: 354 case TINT16: 355 case TUINT16: 356 case TINT32: 357 case TUINT32: 358 case TINT64: 359 case TUINT64: 360 case TPTR32: 361 case TPTR64: 362 case TBOOL: 363 if(o != N && o->op == OREGISTER) { 364 i = o->val.u.reg; 365 if(i >= D_R0+REGMIN && i <= D_R0+REGMAX) 366 goto out; 367 } 368 for(i=D_R0+REGMIN; i<=D_R0+REGMAX; i++) 369 if(reg[i] == 0) { 370 regpc[i] = (uintptr)getcallerpc(&n); 371 goto out; 372 } 373 flusherrors(); 374 for(i=D_R0; i<D_R0+NREG; i++) 375 print("R%d %p\n", i, regpc[i]); 376 fatal("out of fixed registers"); 377 378 case TFLOAT32: 379 case TFLOAT64: 380 if(o != N && o->op == OREGISTER) { 381 i = o->val.u.reg; 382 if(i >= D_F0+FREGMIN && i <= D_F0+FREGMAX) 383 goto out; 384 } 385 for(i=D_F0+FREGMIN; i<=D_F0+FREGMAX; i++) 386 if(reg[i] == 0) { 387 regpc[i] = (uintptr)getcallerpc(&n); 388 goto out; 389 } 390 flusherrors(); 391 for(i=D_F0; i<D_F0+NREG; i++) 392 print("F%d %p\n", i, regpc[i]); 393 fatal("out of floating registers"); 394 395 case TCOMPLEX64: 396 case TCOMPLEX128: 397 tempname(n, t); 398 return; 399 } 400 fatal("regalloc: unknown type %T", t); 401 return; 402 403 out: 404 reg[i]++; 405 nodreg(n, t, i); 406 } 407 408 void 409 regfree(Node *n) 410 { 411 int i; 412 413 if(n->op == ONAME) 414 return; 415 if(n->op != OREGISTER && n->op != OINDREG) 416 fatal("regfree: not a register"); 417 i = n->val.u.reg; 418 if(i == D_R0 + REGSP) 419 return; 420 if(i < 0 || i >= nelem(reg)) 421 fatal("regfree: reg out of range"); 422 if(reg[i] <= 0) 423 fatal("regfree: reg not allocated"); 424 reg[i]--; 425 if(reg[i] == 0) 426 regpc[i] = 0; 427 } 428 429 /* 430 * initialize n to be register r of type t. 431 */ 432 void 433 nodreg(Node *n, Type *t, int r) 434 { 435 if(t == T) 436 fatal("nodreg: t nil"); 437 438 memset(n, 0, sizeof(*n)); 439 n->op = OREGISTER; 440 n->addable = 1; 441 ullmancalc(n); 442 n->val.u.reg = r; 443 n->type = t; 444 } 445 446 /* 447 * initialize n to be indirect of register r; n is type t. 448 */ 449 void 450 nodindreg(Node *n, Type *t, int r) 451 { 452 nodreg(n, t, r); 453 n->op = OINDREG; 454 } 455 456 Node* 457 nodarg(Type *t, int fp) 458 { 459 Node *n; 460 NodeList *l; 461 Type *first; 462 Iter savet; 463 464 // entire argument struct, not just one arg 465 if(t->etype == TSTRUCT && t->funarg) { 466 n = nod(ONAME, N, N); 467 n->sym = lookup(".args"); 468 n->type = t; 469 first = structfirst(&savet, &t); 470 if(first == nil) 471 fatal("nodarg: bad struct"); 472 if(first->width == BADWIDTH) 473 fatal("nodarg: offset not computed for %T", t); 474 n->xoffset = first->width; 475 n->addable = 1; 476 goto fp; 477 } 478 479 if(t->etype != TFIELD) 480 fatal("nodarg: not field %T", t); 481 482 if(fp == 1) { 483 for(l=curfn->dcl; l; l=l->next) { 484 n = l->n; 485 if((n->class == PPARAM || n->class == PPARAMOUT) && !isblanksym(t->sym) && n->sym == t->sym) 486 return n; 487 } 488 } 489 490 n = nod(ONAME, N, N); 491 n->type = t->type; 492 n->sym = t->sym; 493 494 if(t->width == BADWIDTH) 495 fatal("nodarg: offset not computed for %T", t); 496 n->xoffset = t->width; 497 n->addable = 1; 498 n->orig = t->nname; 499 500 fp: 501 // Rewrite argument named _ to __, 502 // or else the assignment to _ will be 503 // discarded during code generation. 504 if(isblank(n)) 505 n->sym = lookup("__"); 506 507 switch(fp) { 508 default: 509 fatal("nodarg %T %d", t, fp); 510 511 case 0: // output arg for calling another function 512 n->op = OINDREG; 513 n->val.u.reg = D_R0+REGSP; 514 n->xoffset += 8; 515 break; 516 517 case 1: // input arg to current function 518 n->class = PPARAM; 519 break; 520 521 case 2: // offset output arg 522 fatal("shouldn't be used"); 523 n->op = OINDREG; 524 n->val.u.reg = D_R0 + REGSP; 525 n->xoffset += types[tptr]->width; 526 break; 527 } 528 n->typecheck = 1; 529 return n; 530 } 531 532 /* 533 * generate 534 * as $c, n 535 */ 536 void 537 ginscon(int as, vlong c, Node *n2) 538 { 539 Node n1, ntmp; 540 541 nodconst(&n1, types[TINT64], c); 542 543 if(as != AMOVD && (c < -BIG || c > BIG)) { 544 // cannot have more than 16-bit of immediate in ADD, etc. 545 // instead, MOV into register first. 546 regalloc(&ntmp, types[TINT64], N); 547 gins(AMOVD, &n1, &ntmp); 548 gins(as, &ntmp, n2); 549 regfree(&ntmp); 550 return; 551 } 552 gins(as, &n1, n2); 553 } 554 555 /* 556 * generate 557 * as n, $c (CMP/CMPU) 558 */ 559 void 560 ginscon2(int as, Node *n2, vlong c) 561 { 562 Node n1, ntmp; 563 564 nodconst(&n1, types[TINT64], c); 565 566 switch(as) { 567 default: 568 fatal("ginscon2"); 569 case ACMP: 570 if(-BIG <= c && c <= BIG) { 571 gins(as, n2, &n1); 572 return; 573 } 574 break; 575 case ACMPU: 576 if(0 <= c && c <= 2*BIG) { 577 gins(as, n2, &n1); 578 return; 579 } 580 break; 581 } 582 // MOV n1 into register first 583 regalloc(&ntmp, types[TINT64], N); 584 gins(AMOVD, &n1, &ntmp); 585 gins(as, n2, &ntmp); 586 regfree(&ntmp); 587 } 588 589 #define CASE(a,b) (((a)<<16)|((b)<<0)) 590 /*c2go int CASE(int, int); */ 591 592 /* 593 * Is this node a memory operand? 594 */ 595 int 596 ismem(Node *n) 597 { 598 switch(n->op) { 599 case OITAB: 600 case OSPTR: 601 case OLEN: 602 case OCAP: 603 case OINDREG: 604 case ONAME: 605 case OPARAM: 606 case OCLOSUREVAR: 607 case OADDR: 608 return 1; 609 } 610 return 0; 611 } 612 613 /* 614 * set up nodes representing 2^63 615 */ 616 Node bigi; 617 Node bigf; 618 619 void 620 bignodes(void) 621 { 622 static int did; 623 624 if(did) 625 return; 626 did = 1; 627 628 nodconst(&bigi, types[TUINT64], 1); 629 mpshiftfix(bigi.val.u.xval, 63); 630 631 bigf = bigi; 632 bigf.type = types[TFLOAT64]; 633 bigf.val.ctype = CTFLT; 634 bigf.val.u.fval = mal(sizeof *bigf.val.u.fval); 635 mpmovefixflt(bigf.val.u.fval, bigi.val.u.xval); 636 } 637 638 /* 639 * generate move: 640 * t = f 641 * hard part is conversions. 642 */ 643 void 644 gmove(Node *f, Node *t) 645 { 646 int a, ft, tt; 647 Type *cvt; 648 Node r1, r2, r3, con; 649 Prog *p1, *p2; 650 651 if(debug['M']) 652 print("gmove %lN -> %lN\n", f, t); 653 654 ft = simsimtype(f->type); 655 tt = simsimtype(t->type); 656 cvt = t->type; 657 658 if(iscomplex[ft] || iscomplex[tt]) { 659 complexmove(f, t); 660 return; 661 } 662 663 // cannot have two memory operands 664 if(ismem(f) && ismem(t)) 665 goto hard; 666 667 // convert constant to desired type 668 if(f->op == OLITERAL) { 669 switch(tt) { 670 default: 671 convconst(&con, t->type, &f->val); 672 break; 673 674 case TINT32: 675 case TINT16: 676 case TINT8: 677 convconst(&con, types[TINT64], &f->val); 678 regalloc(&r1, con.type, t); 679 gins(AMOVD, &con, &r1); 680 gmove(&r1, t); 681 regfree(&r1); 682 return; 683 684 case TUINT32: 685 case TUINT16: 686 case TUINT8: 687 convconst(&con, types[TUINT64], &f->val); 688 regalloc(&r1, con.type, t); 689 gins(AMOVD, &con, &r1); 690 gmove(&r1, t); 691 regfree(&r1); 692 return; 693 } 694 695 f = &con; 696 ft = tt; // so big switch will choose a simple mov 697 698 // constants can't move directly to memory. 699 if(ismem(t)) { 700 goto hard; 701 // float constants come from memory. 702 //if(isfloat[tt]) 703 // goto hard; 704 705 // 64-bit immediates are also from memory. 706 //if(isint[tt]) 707 // goto hard; 708 //// 64-bit immediates are really 32-bit sign-extended 709 //// unless moving into a register. 710 //if(isint[tt]) { 711 // if(mpcmpfixfix(con.val.u.xval, minintval[TINT32]) < 0) 712 // goto hard; 713 // if(mpcmpfixfix(con.val.u.xval, maxintval[TINT32]) > 0) 714 // goto hard; 715 //} 716 } 717 } 718 719 // value -> value copy, only one memory operand. 720 // figure out the instruction to use. 721 // break out of switch for one-instruction gins. 722 // goto rdst for "destination must be register". 723 // goto hard for "convert to cvt type first". 724 // otherwise handle and return. 725 726 switch(CASE(ft, tt)) { 727 default: 728 fatal("gmove %lT -> %lT", f->type, t->type); 729 730 /* 731 * integer copy and truncate 732 */ 733 case CASE(TINT8, TINT8): // same size 734 case CASE(TUINT8, TINT8): 735 case CASE(TINT16, TINT8): // truncate 736 case CASE(TUINT16, TINT8): 737 case CASE(TINT32, TINT8): 738 case CASE(TUINT32, TINT8): 739 case CASE(TINT64, TINT8): 740 case CASE(TUINT64, TINT8): 741 a = AMOVB; 742 break; 743 744 case CASE(TINT8, TUINT8): // same size 745 case CASE(TUINT8, TUINT8): 746 case CASE(TINT16, TUINT8): // truncate 747 case CASE(TUINT16, TUINT8): 748 case CASE(TINT32, TUINT8): 749 case CASE(TUINT32, TUINT8): 750 case CASE(TINT64, TUINT8): 751 case CASE(TUINT64, TUINT8): 752 a = AMOVBZ; 753 break; 754 755 case CASE(TINT16, TINT16): // same size 756 case CASE(TUINT16, TINT16): 757 case CASE(TINT32, TINT16): // truncate 758 case CASE(TUINT32, TINT16): 759 case CASE(TINT64, TINT16): 760 case CASE(TUINT64, TINT16): 761 a = AMOVH; 762 break; 763 764 case CASE(TINT16, TUINT16): // same size 765 case CASE(TUINT16, TUINT16): 766 case CASE(TINT32, TUINT16): // truncate 767 case CASE(TUINT32, TUINT16): 768 case CASE(TINT64, TUINT16): 769 case CASE(TUINT64, TUINT16): 770 a = AMOVHZ; 771 break; 772 773 case CASE(TINT32, TINT32): // same size 774 case CASE(TUINT32, TINT32): 775 case CASE(TINT64, TINT32): // truncate 776 case CASE(TUINT64, TINT32): 777 a = AMOVW; 778 break; 779 780 case CASE(TINT32, TUINT32): // same size 781 case CASE(TUINT32, TUINT32): 782 case CASE(TINT64, TUINT32): 783 case CASE(TUINT64, TUINT32): 784 a = AMOVWZ; 785 break; 786 787 case CASE(TINT64, TINT64): // same size 788 case CASE(TINT64, TUINT64): 789 case CASE(TUINT64, TINT64): 790 case CASE(TUINT64, TUINT64): 791 a = AMOVD; 792 break; 793 794 /* 795 * integer up-conversions 796 */ 797 case CASE(TINT8, TINT16): // sign extend int8 798 case CASE(TINT8, TUINT16): 799 case CASE(TINT8, TINT32): 800 case CASE(TINT8, TUINT32): 801 case CASE(TINT8, TINT64): 802 case CASE(TINT8, TUINT64): 803 a = AMOVB; 804 goto rdst; 805 806 case CASE(TUINT8, TINT16): // zero extend uint8 807 case CASE(TUINT8, TUINT16): 808 case CASE(TUINT8, TINT32): 809 case CASE(TUINT8, TUINT32): 810 case CASE(TUINT8, TINT64): 811 case CASE(TUINT8, TUINT64): 812 a = AMOVBZ; 813 goto rdst; 814 815 case CASE(TINT16, TINT32): // sign extend int16 816 case CASE(TINT16, TUINT32): 817 case CASE(TINT16, TINT64): 818 case CASE(TINT16, TUINT64): 819 a = AMOVH; 820 goto rdst; 821 822 case CASE(TUINT16, TINT32): // zero extend uint16 823 case CASE(TUINT16, TUINT32): 824 case CASE(TUINT16, TINT64): 825 case CASE(TUINT16, TUINT64): 826 a = AMOVHZ; 827 goto rdst; 828 829 case CASE(TINT32, TINT64): // sign extend int32 830 case CASE(TINT32, TUINT64): 831 a = AMOVW; 832 goto rdst; 833 834 case CASE(TUINT32, TINT64): // zero extend uint32 835 case CASE(TUINT32, TUINT64): 836 a = AMOVWZ; 837 goto rdst; 838 839 /* 840 * float to integer 841 */ 842 case CASE(TFLOAT32, TINT32): 843 case CASE(TFLOAT64, TINT32): 844 case CASE(TFLOAT32, TINT64): 845 case CASE(TFLOAT64, TINT64): 846 case CASE(TFLOAT32, TINT16): 847 case CASE(TFLOAT32, TINT8): 848 case CASE(TFLOAT32, TUINT16): 849 case CASE(TFLOAT32, TUINT8): 850 case CASE(TFLOAT64, TINT16): 851 case CASE(TFLOAT64, TINT8): 852 case CASE(TFLOAT64, TUINT16): 853 case CASE(TFLOAT64, TUINT8): 854 case CASE(TFLOAT32, TUINT32): 855 case CASE(TFLOAT64, TUINT32): 856 case CASE(TFLOAT32, TUINT64): 857 case CASE(TFLOAT64, TUINT64): 858 //warn("gmove: convert float to int not implemented: %N -> %N\n", f, t); 859 //return; 860 // algorithm is: 861 // if small enough, use native float64 -> int64 conversion. 862 // otherwise, subtract 2^63, convert, and add it back. 863 bignodes(); 864 regalloc(&r1, types[ft], f); 865 gmove(f, &r1); 866 if(tt == TUINT64) { 867 regalloc(&r2, types[TFLOAT64], N); 868 gmove(&bigf, &r2); 869 gins(AFCMPU, &r1, &r2); 870 p1 = gbranch(optoas(OLT, types[TFLOAT64]), T, +1); 871 gins(AFSUB, &r2, &r1); 872 patch(p1, pc); 873 regfree(&r2); 874 } 875 regalloc(&r2, types[TFLOAT64], N); 876 regalloc(&r3, types[TINT64], t); 877 gins(AFCTIDZ, &r1, &r2); 878 p1 = gins(AFMOVD, &r2, N); 879 p1->to.type = D_OREG; 880 p1->to.reg = REGSP; 881 p1->to.offset = -8; 882 p1 = gins(AMOVD, N, &r3); 883 p1->from.type = D_OREG; 884 p1->from.reg = REGSP; 885 p1->from.offset = -8; 886 regfree(&r2); 887 regfree(&r1); 888 if(tt == TUINT64) { 889 p1 = gbranch(optoas(OLT, types[TFLOAT64]), T, +1); // use CR0 here again 890 nodreg(&r1, types[TINT64], D_R0+REGTMP); 891 gins(AMOVD, &bigi, &r1); 892 gins(AADD, &r1, &r3); 893 patch(p1, pc); 894 } 895 gmove(&r3, t); 896 regfree(&r3); 897 return; 898 899 /* 900 * integer to float 901 */ 902 case CASE(TINT32, TFLOAT32): 903 case CASE(TINT32, TFLOAT64): 904 case CASE(TINT64, TFLOAT32): 905 case CASE(TINT64, TFLOAT64): 906 case CASE(TINT16, TFLOAT32): 907 case CASE(TINT16, TFLOAT64): 908 case CASE(TINT8, TFLOAT32): 909 case CASE(TINT8, TFLOAT64): 910 case CASE(TUINT16, TFLOAT32): 911 case CASE(TUINT16, TFLOAT64): 912 case CASE(TUINT8, TFLOAT32): 913 case CASE(TUINT8, TFLOAT64): 914 case CASE(TUINT32, TFLOAT32): 915 case CASE(TUINT32, TFLOAT64): 916 case CASE(TUINT64, TFLOAT32): 917 case CASE(TUINT64, TFLOAT64): 918 //warn("gmove: convert int to float not implemented: %N -> %N\n", f, t); 919 //return; 920 // algorithm is: 921 // if small enough, use native int64 -> uint64 conversion. 922 // otherwise, halve (rounding to odd?), convert, and double. 923 bignodes(); 924 regalloc(&r1, types[TINT64], N); 925 gmove(f, &r1); 926 if(ft == TUINT64) { 927 nodreg(&r2, types[TUINT64], D_R0+REGTMP); 928 gmove(&bigi, &r2); 929 gins(ACMPU, &r1, &r2); 930 p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1); 931 p2 = gins(ASRD, N, &r1); 932 p2->from.type = D_CONST; 933 p2->from.offset = 1; 934 patch(p1, pc); 935 } 936 regalloc(&r2, types[TFLOAT64], t); 937 p1 = gins(AMOVD, &r1, N); 938 p1->to.type = D_OREG; 939 p1->to.reg = REGSP; 940 p1->to.offset = -8; 941 p1 = gins(AFMOVD, N, &r2); 942 p1->from.type = D_OREG; 943 p1->from.reg = REGSP; 944 p1->from.offset = -8; 945 gins(AFCFID, &r2, &r2); 946 regfree(&r1); 947 if(ft == TUINT64) { 948 p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1); // use CR0 here again 949 nodreg(&r1, types[TFLOAT64], D_F0+FREGTWO); 950 gins(AFMUL, &r1, &r2); 951 patch(p1, pc); 952 } 953 gmove(&r2, t); 954 regfree(&r2); 955 return; 956 957 /* 958 * float to float 959 */ 960 case CASE(TFLOAT32, TFLOAT32): 961 a = AFMOVS; 962 break; 963 964 case CASE(TFLOAT64, TFLOAT64): 965 a = AFMOVD; 966 break; 967 968 case CASE(TFLOAT32, TFLOAT64): 969 a = AFMOVS; 970 goto rdst; 971 972 case CASE(TFLOAT64, TFLOAT32): 973 a = AFRSP; 974 goto rdst; 975 } 976 977 gins(a, f, t); 978 return; 979 980 rdst: 981 // requires register destination 982 regalloc(&r1, t->type, t); 983 gins(a, f, &r1); 984 gmove(&r1, t); 985 regfree(&r1); 986 return; 987 988 hard: 989 // requires register intermediate 990 regalloc(&r1, cvt, t); 991 gmove(f, &r1); 992 gmove(&r1, t); 993 regfree(&r1); 994 return; 995 } 996 997 /* 998 * generate one instruction: 999 * as f, t 1000 */ 1001 Prog* 1002 gins(int as, Node *f, Node *t) 1003 { 1004 int32 w; 1005 Prog *p; 1006 Addr af, at; 1007 1008 // TODO(austin): Add self-move test like in 6g (but be careful 1009 // of truncation moves) 1010 1011 memset(&af, 0, sizeof af); 1012 memset(&at, 0, sizeof at); 1013 if(f != N) 1014 naddr(f, &af, 1); 1015 if(t != N) 1016 naddr(t, &at, 1); 1017 p = prog(as); 1018 if(f != N) 1019 p->from = af; 1020 if(t != N) 1021 p->to = at; 1022 if(as == ATEXT) 1023 p->reg = 0; 1024 if(debug['g']) 1025 print("%P\n", p); 1026 1027 w = 0; 1028 switch(as) { 1029 case AMOVB: 1030 case AMOVBU: 1031 case AMOVBZ: 1032 case AMOVBZU: 1033 w = 1; 1034 break; 1035 case AMOVH: 1036 case AMOVHU: 1037 case AMOVHZ: 1038 case AMOVHZU: 1039 w = 2; 1040 break; 1041 case AMOVW: 1042 case AMOVWU: 1043 case AMOVWZ: 1044 case AMOVWZU: 1045 w = 4; 1046 break; 1047 case AMOVD: 1048 case AMOVDU: 1049 if(af.type == D_CONST) 1050 break; 1051 w = 8; 1052 break; 1053 } 1054 if(w != 0 && ((f != N && af.width < w) || (t != N && at.type != D_REG && at.width > w))) { 1055 dump("f", f); 1056 dump("t", t); 1057 fatal("bad width: %P (%d, %d)\n", p, af.width, at.width); 1058 } 1059 1060 return p; 1061 } 1062 1063 void 1064 fixlargeoffset(Node *n) 1065 { 1066 Node a; 1067 1068 if(n == N) 1069 return; 1070 if(n->op != OINDREG) 1071 return; 1072 if(n->val.u.reg == D_R0+REGSP) // stack offset cannot be large 1073 return; 1074 if(n->xoffset != (int32)n->xoffset) { 1075 // TODO(minux): offset too large, move into R31 and add to R31 instead. 1076 // this is used only in test/fixedbugs/issue6036.go. 1077 print("offset too large: %N\n", n); 1078 noimpl; 1079 a = *n; 1080 a.op = OREGISTER; 1081 a.type = types[tptr]; 1082 a.xoffset = 0; 1083 cgen_checknil(&a); 1084 ginscon(optoas(OADD, types[tptr]), n->xoffset, &a); 1085 n->xoffset = 0; 1086 } 1087 } 1088 1089 /* 1090 * generate code to compute n; 1091 * make a refer to result. 1092 */ 1093 void 1094 naddr(Node *n, Addr *a, int canemitcode) 1095 { 1096 Sym *s; 1097 1098 a->type = D_NONE; 1099 a->name = D_NONE; 1100 a->reg = NREG; 1101 a->gotype = nil; 1102 a->node = N; 1103 a->etype = 0; 1104 a->width = 0; 1105 if(n == N) 1106 return; 1107 1108 if(n->type != T && n->type->etype != TIDEAL) { 1109 dowidth(n->type); 1110 a->width = n->type->width; 1111 } 1112 1113 switch(n->op) { 1114 default: 1115 fatal("naddr: bad %O %D", n->op, a); 1116 break; 1117 1118 case ONAME: 1119 a->etype = 0; 1120 a->reg = NREG; 1121 if(n->type != T) 1122 a->etype = simtype[n->type->etype]; 1123 a->offset = n->xoffset; 1124 s = n->sym; 1125 a->node = n->orig; 1126 //if(a->node >= (Node*)&n) 1127 // fatal("stack node"); 1128 if(s == S) 1129 s = lookup(".noname"); 1130 if(n->method) { 1131 if(n->type != T) 1132 if(n->type->sym != S) 1133 if(n->type->sym->pkg != nil) 1134 s = pkglookup(s->name, n->type->sym->pkg); 1135 } 1136 1137 a->type = D_OREG; 1138 switch(n->class) { 1139 default: 1140 fatal("naddr: ONAME class %S %d\n", n->sym, n->class); 1141 case PEXTERN: 1142 a->name = D_EXTERN; 1143 break; 1144 case PAUTO: 1145 a->name = D_AUTO; 1146 break; 1147 case PPARAM: 1148 case PPARAMOUT: 1149 a->name = D_PARAM; 1150 break; 1151 case PFUNC: 1152 a->name = D_EXTERN; 1153 a->type = D_CONST; 1154 a->width = widthptr; 1155 s = funcsym(s); 1156 break; 1157 } 1158 a->sym = linksym(s); 1159 break; 1160 1161 case OLITERAL: 1162 switch(n->val.ctype) { 1163 default: 1164 fatal("naddr: const %lT", n->type); 1165 break; 1166 case CTFLT: 1167 a->type = D_FCONST; 1168 a->u.dval = mpgetflt(n->val.u.fval); 1169 break; 1170 case CTINT: 1171 case CTRUNE: 1172 a->sym = nil; 1173 a->type = D_CONST; 1174 a->offset = mpgetfix(n->val.u.xval); 1175 break; 1176 case CTSTR: 1177 datagostring(n->val.u.sval, a); 1178 break; 1179 case CTBOOL: 1180 a->sym = nil; 1181 a->type = D_CONST; 1182 a->offset = n->val.u.bval; 1183 break; 1184 case CTNIL: 1185 a->sym = nil; 1186 a->type = D_CONST; 1187 a->offset = 0; 1188 break; 1189 } 1190 break; 1191 1192 case OREGISTER: 1193 if(n->val.u.reg < D_F0) { 1194 a->type = D_REG; 1195 a->reg = n->val.u.reg; 1196 } else { 1197 a->type = D_FREG; 1198 a->reg = n->val.u.reg - D_F0; 1199 } 1200 a->sym = nil; 1201 break; 1202 1203 case OINDREG: 1204 a->type = D_OREG; 1205 a->reg = n->val.u.reg; 1206 a->sym = linksym(n->sym); 1207 a->offset = n->xoffset; 1208 if(a->offset != (int32)a->offset) 1209 yyerror("offset %lld too large for OINDREG", a->offset); 1210 break; 1211 1212 case OPARAM: 1213 // n->left is PHEAP ONAME for stack parameter. 1214 // compute address of actual parameter on stack. 1215 a->etype = simtype[n->left->type->etype]; 1216 a->width = n->left->type->width; 1217 a->offset = n->xoffset; 1218 a->sym = linksym(n->left->sym); 1219 a->type = D_OREG; 1220 a->name = D_PARAM; 1221 a->node = n->left->orig; 1222 break; 1223 1224 case OCLOSUREVAR: 1225 if(!curfn->needctxt) 1226 fatal("closurevar without needctxt"); 1227 a->type = D_OREG; 1228 a->reg = REGENV; 1229 a->offset = n->xoffset; 1230 a->sym = nil; 1231 break; 1232 1233 case OCFUNC: 1234 naddr(n->left, a, canemitcode); 1235 a->sym = linksym(n->left->sym); 1236 break; 1237 1238 case OITAB: 1239 // itable of interface value 1240 naddr(n->left, a, canemitcode); 1241 a->etype = simtype[tptr]; 1242 if(a->type == D_CONST && a->offset == 0) 1243 break; // itab(nil) 1244 a->width = widthptr; 1245 break; 1246 1247 case OSPTR: 1248 // pointer in a string or slice 1249 naddr(n->left, a, canemitcode); 1250 a->etype = simtype[tptr]; 1251 if(a->type == D_CONST && a->offset == 0) 1252 break; // ptr(nil) 1253 a->offset += Array_array; 1254 a->width = widthptr; 1255 break; 1256 1257 case OLEN: 1258 // len of string or slice 1259 naddr(n->left, a, canemitcode); 1260 a->etype = simtype[TINT]; 1261 if(a->type == D_CONST && a->offset == 0) 1262 break; // len(nil) 1263 a->offset += Array_nel; 1264 a->width = widthint; 1265 break; 1266 1267 case OCAP: 1268 // cap of string or slice 1269 naddr(n->left, a, canemitcode); 1270 a->etype = simtype[TINT]; 1271 if(a->type == D_CONST && a->offset == 0) 1272 break; // cap(nil) 1273 a->offset += Array_cap; 1274 a->width = widthint; 1275 break; 1276 1277 case OADDR: 1278 naddr(n->left, a, canemitcode); 1279 a->etype = tptr; 1280 switch(a->type) { 1281 case D_OREG: 1282 a->type = D_CONST; 1283 break; 1284 1285 case D_REG: 1286 case D_CONST: 1287 break; 1288 1289 default: 1290 fatal("naddr: OADDR %d\n", a->type); 1291 } 1292 break; 1293 } 1294 } 1295 1296 /* 1297 * return Axxx for Oxxx on type t. 1298 */ 1299 int 1300 optoas(int op, Type *t) 1301 { 1302 int a; 1303 1304 if(t == T) 1305 fatal("optoas: t is nil"); 1306 1307 a = AGOK; 1308 switch(CASE(op, simtype[t->etype])) { 1309 default: 1310 fatal("optoas: no entry for op=%O type=%T", op, t); 1311 break; 1312 1313 case CASE(OEQ, TBOOL): 1314 case CASE(OEQ, TINT8): 1315 case CASE(OEQ, TUINT8): 1316 case CASE(OEQ, TINT16): 1317 case CASE(OEQ, TUINT16): 1318 case CASE(OEQ, TINT32): 1319 case CASE(OEQ, TUINT32): 1320 case CASE(OEQ, TINT64): 1321 case CASE(OEQ, TUINT64): 1322 case CASE(OEQ, TPTR32): 1323 case CASE(OEQ, TPTR64): 1324 case CASE(OEQ, TFLOAT32): 1325 case CASE(OEQ, TFLOAT64): 1326 a = ABEQ; 1327 break; 1328 1329 case CASE(ONE, TBOOL): 1330 case CASE(ONE, TINT8): 1331 case CASE(ONE, TUINT8): 1332 case CASE(ONE, TINT16): 1333 case CASE(ONE, TUINT16): 1334 case CASE(ONE, TINT32): 1335 case CASE(ONE, TUINT32): 1336 case CASE(ONE, TINT64): 1337 case CASE(ONE, TUINT64): 1338 case CASE(ONE, TPTR32): 1339 case CASE(ONE, TPTR64): 1340 case CASE(ONE, TFLOAT32): 1341 case CASE(ONE, TFLOAT64): 1342 a = ABNE; 1343 break; 1344 1345 case CASE(OLT, TINT8): // ACMP 1346 case CASE(OLT, TINT16): 1347 case CASE(OLT, TINT32): 1348 case CASE(OLT, TINT64): 1349 case CASE(OLT, TUINT8): // ACMPU 1350 case CASE(OLT, TUINT16): 1351 case CASE(OLT, TUINT32): 1352 case CASE(OLT, TUINT64): 1353 case CASE(OLT, TFLOAT32): // AFCMPU 1354 case CASE(OLT, TFLOAT64): 1355 a = ABLT; 1356 break; 1357 1358 case CASE(OLE, TINT8): // ACMP 1359 case CASE(OLE, TINT16): 1360 case CASE(OLE, TINT32): 1361 case CASE(OLE, TINT64): 1362 case CASE(OLE, TUINT8): // ACMPU 1363 case CASE(OLE, TUINT16): 1364 case CASE(OLE, TUINT32): 1365 case CASE(OLE, TUINT64): 1366 case CASE(OLE, TFLOAT32): // AFCMPU 1367 case CASE(OLE, TFLOAT64): 1368 a = ABLE; 1369 break; 1370 1371 case CASE(OGT, TINT8): 1372 case CASE(OGT, TINT16): 1373 case CASE(OGT, TINT32): 1374 case CASE(OGT, TINT64): 1375 case CASE(OGT, TUINT8): 1376 case CASE(OGT, TUINT16): 1377 case CASE(OGT, TUINT32): 1378 case CASE(OGT, TUINT64): 1379 case CASE(OGT, TFLOAT32): 1380 case CASE(OGT, TFLOAT64): 1381 a = ABGT; 1382 break; 1383 1384 case CASE(OGE, TINT8): 1385 case CASE(OGE, TINT16): 1386 case CASE(OGE, TINT32): 1387 case CASE(OGE, TINT64): 1388 case CASE(OGE, TUINT8): 1389 case CASE(OGE, TUINT16): 1390 case CASE(OGE, TUINT32): 1391 case CASE(OGE, TUINT64): 1392 case CASE(OGE, TFLOAT32): 1393 case CASE(OGE, TFLOAT64): 1394 a = ABGE; 1395 break; 1396 1397 case CASE(OCMP, TBOOL): 1398 case CASE(OCMP, TINT8): 1399 case CASE(OCMP, TINT16): 1400 case CASE(OCMP, TINT32): 1401 case CASE(OCMP, TPTR32): 1402 case CASE(OCMP, TINT64): 1403 a = ACMP; 1404 break; 1405 1406 case CASE(OCMP, TUINT8): 1407 case CASE(OCMP, TUINT16): 1408 case CASE(OCMP, TUINT32): 1409 case CASE(OCMP, TUINT64): 1410 case CASE(OCMP, TPTR64): 1411 a = ACMPU; 1412 break; 1413 1414 case CASE(OCMP, TFLOAT32): 1415 case CASE(OCMP, TFLOAT64): 1416 a = AFCMPU; 1417 break; 1418 1419 case CASE(OAS, TBOOL): 1420 case CASE(OAS, TINT8): 1421 a = AMOVB; 1422 break; 1423 1424 case CASE(OAS, TUINT8): 1425 a = AMOVBZ; 1426 break; 1427 1428 case CASE(OAS, TINT16): 1429 a = AMOVH; 1430 break; 1431 1432 case CASE(OAS, TUINT16): 1433 a = AMOVHZ; 1434 break; 1435 1436 case CASE(OAS, TINT32): 1437 a = AMOVW; 1438 break; 1439 1440 case CASE(OAS, TUINT32): 1441 case CASE(OAS, TPTR32): 1442 a = AMOVWZ; 1443 break; 1444 1445 case CASE(OAS, TINT64): 1446 case CASE(OAS, TUINT64): 1447 case CASE(OAS, TPTR64): 1448 a = AMOVD; 1449 break; 1450 1451 case CASE(OAS, TFLOAT32): 1452 a = AFMOVS; 1453 break; 1454 1455 case CASE(OAS, TFLOAT64): 1456 a = AFMOVD; 1457 break; 1458 1459 case CASE(OADD, TINT8): 1460 case CASE(OADD, TUINT8): 1461 case CASE(OADD, TINT16): 1462 case CASE(OADD, TUINT16): 1463 case CASE(OADD, TINT32): 1464 case CASE(OADD, TUINT32): 1465 case CASE(OADD, TPTR32): 1466 case CASE(OADD, TINT64): 1467 case CASE(OADD, TUINT64): 1468 case CASE(OADD, TPTR64): 1469 a = AADD; 1470 break; 1471 1472 case CASE(OADD, TFLOAT32): 1473 a = AFADDS; 1474 break; 1475 1476 case CASE(OADD, TFLOAT64): 1477 a = AFADD; 1478 break; 1479 1480 case CASE(OSUB, TINT8): 1481 case CASE(OSUB, TUINT8): 1482 case CASE(OSUB, TINT16): 1483 case CASE(OSUB, TUINT16): 1484 case CASE(OSUB, TINT32): 1485 case CASE(OSUB, TUINT32): 1486 case CASE(OSUB, TPTR32): 1487 case CASE(OSUB, TINT64): 1488 case CASE(OSUB, TUINT64): 1489 case CASE(OSUB, TPTR64): 1490 a = ASUB; 1491 break; 1492 1493 case CASE(OSUB, TFLOAT32): 1494 a = AFSUBS; 1495 break; 1496 1497 case CASE(OSUB, TFLOAT64): 1498 a = AFSUB; 1499 break; 1500 1501 case CASE(OMINUS, TINT8): 1502 case CASE(OMINUS, TUINT8): 1503 case CASE(OMINUS, TINT16): 1504 case CASE(OMINUS, TUINT16): 1505 case CASE(OMINUS, TINT32): 1506 case CASE(OMINUS, TUINT32): 1507 case CASE(OMINUS, TPTR32): 1508 case CASE(OMINUS, TINT64): 1509 case CASE(OMINUS, TUINT64): 1510 case CASE(OMINUS, TPTR64): 1511 a = ANEG; 1512 break; 1513 1514 case CASE(OAND, TINT8): 1515 case CASE(OAND, TUINT8): 1516 case CASE(OAND, TINT16): 1517 case CASE(OAND, TUINT16): 1518 case CASE(OAND, TINT32): 1519 case CASE(OAND, TUINT32): 1520 case CASE(OAND, TPTR32): 1521 case CASE(OAND, TINT64): 1522 case CASE(OAND, TUINT64): 1523 case CASE(OAND, TPTR64): 1524 a = AAND; 1525 break; 1526 1527 case CASE(OOR, TINT8): 1528 case CASE(OOR, TUINT8): 1529 case CASE(OOR, TINT16): 1530 case CASE(OOR, TUINT16): 1531 case CASE(OOR, TINT32): 1532 case CASE(OOR, TUINT32): 1533 case CASE(OOR, TPTR32): 1534 case CASE(OOR, TINT64): 1535 case CASE(OOR, TUINT64): 1536 case CASE(OOR, TPTR64): 1537 a = AOR; 1538 break; 1539 1540 case CASE(OXOR, TINT8): 1541 case CASE(OXOR, TUINT8): 1542 case CASE(OXOR, TINT16): 1543 case CASE(OXOR, TUINT16): 1544 case CASE(OXOR, TINT32): 1545 case CASE(OXOR, TUINT32): 1546 case CASE(OXOR, TPTR32): 1547 case CASE(OXOR, TINT64): 1548 case CASE(OXOR, TUINT64): 1549 case CASE(OXOR, TPTR64): 1550 a = AXOR; 1551 break; 1552 1553 // TODO(minux): handle rotates 1554 //case CASE(OLROT, TINT8): 1555 //case CASE(OLROT, TUINT8): 1556 //case CASE(OLROT, TINT16): 1557 //case CASE(OLROT, TUINT16): 1558 //case CASE(OLROT, TINT32): 1559 //case CASE(OLROT, TUINT32): 1560 //case CASE(OLROT, TPTR32): 1561 //case CASE(OLROT, TINT64): 1562 //case CASE(OLROT, TUINT64): 1563 //case CASE(OLROT, TPTR64): 1564 // a = 0//???; RLDC? 1565 // break; 1566 1567 case CASE(OLSH, TINT8): 1568 case CASE(OLSH, TUINT8): 1569 case CASE(OLSH, TINT16): 1570 case CASE(OLSH, TUINT16): 1571 case CASE(OLSH, TINT32): 1572 case CASE(OLSH, TUINT32): 1573 case CASE(OLSH, TPTR32): 1574 case CASE(OLSH, TINT64): 1575 case CASE(OLSH, TUINT64): 1576 case CASE(OLSH, TPTR64): 1577 a = ASLD; 1578 break; 1579 1580 case CASE(ORSH, TUINT8): 1581 case CASE(ORSH, TUINT16): 1582 case CASE(ORSH, TUINT32): 1583 case CASE(ORSH, TPTR32): 1584 case CASE(ORSH, TUINT64): 1585 case CASE(ORSH, TPTR64): 1586 a = ASRD; 1587 break; 1588 1589 case CASE(ORSH, TINT8): 1590 case CASE(ORSH, TINT16): 1591 case CASE(ORSH, TINT32): 1592 case CASE(ORSH, TINT64): 1593 a = ASRAD; 1594 break; 1595 1596 // TODO(minux): handle rotates 1597 //case CASE(ORROTC, TINT8): 1598 //case CASE(ORROTC, TUINT8): 1599 //case CASE(ORROTC, TINT16): 1600 //case CASE(ORROTC, TUINT16): 1601 //case CASE(ORROTC, TINT32): 1602 //case CASE(ORROTC, TUINT32): 1603 //case CASE(ORROTC, TINT64): 1604 //case CASE(ORROTC, TUINT64): 1605 // a = 0//??? RLDC?? 1606 // break; 1607 1608 case CASE(OHMUL, TINT64): 1609 a = AMULHD; 1610 break; 1611 case CASE(OHMUL, TUINT64): 1612 case CASE(OHMUL, TPTR64): 1613 a = AMULHDU; 1614 break; 1615 1616 case CASE(OMUL, TINT8): 1617 case CASE(OMUL, TINT16): 1618 case CASE(OMUL, TINT32): 1619 case CASE(OMUL, TINT64): 1620 a = AMULLD; 1621 break; 1622 1623 case CASE(OMUL, TUINT8): 1624 case CASE(OMUL, TUINT16): 1625 case CASE(OMUL, TUINT32): 1626 case CASE(OMUL, TPTR32): 1627 // don't use word multiply, the high 32-bit are undefined. 1628 // fallthrough 1629 case CASE(OMUL, TUINT64): 1630 case CASE(OMUL, TPTR64): 1631 a = AMULLD; // for 64-bit multiplies, signedness doesn't matter. 1632 break; 1633 1634 case CASE(OMUL, TFLOAT32): 1635 a = AFMULS; 1636 break; 1637 1638 case CASE(OMUL, TFLOAT64): 1639 a = AFMUL; 1640 break; 1641 1642 case CASE(ODIV, TINT8): 1643 case CASE(ODIV, TINT16): 1644 case CASE(ODIV, TINT32): 1645 case CASE(ODIV, TINT64): 1646 a = ADIVD; 1647 break; 1648 1649 case CASE(ODIV, TUINT8): 1650 case CASE(ODIV, TUINT16): 1651 case CASE(ODIV, TUINT32): 1652 case CASE(ODIV, TPTR32): 1653 case CASE(ODIV, TUINT64): 1654 case CASE(ODIV, TPTR64): 1655 a = ADIVDU; 1656 break; 1657 1658 case CASE(ODIV, TFLOAT32): 1659 a = AFDIVS; 1660 break; 1661 1662 case CASE(ODIV, TFLOAT64): 1663 a = AFDIV; 1664 break; 1665 1666 } 1667 return a; 1668 } 1669 1670 enum 1671 { 1672 ODynam = 1<<0, 1673 OAddable = 1<<1, 1674 }; 1675 1676 int 1677 xgen(Node *n, Node *a, int o) 1678 { 1679 // TODO(minux) 1680 USED(n); USED(a); USED(o); 1681 return -1; 1682 } 1683 1684 void 1685 sudoclean(void) 1686 { 1687 return; 1688 } 1689 1690 /* 1691 * generate code to compute address of n, 1692 * a reference to a (perhaps nested) field inside 1693 * an array or struct. 1694 * return 0 on failure, 1 on success. 1695 * on success, leaves usable address in a. 1696 * 1697 * caller is responsible for calling sudoclean 1698 * after successful sudoaddable, 1699 * to release the register used for a. 1700 */ 1701 int 1702 sudoaddable(int as, Node *n, Addr *a) 1703 { 1704 // TODO(minux) 1705 USED(as); USED(n); USED(a); 1706 return 0; 1707 }