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