github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/5g/gsubr.c (about) 1 // Derived from Inferno utils/5c/txt.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5c/txt.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 #include <u.h> 32 #include <libc.h> 33 #include "gg.h" 34 35 // TODO(kaib): Can make this bigger if we move 36 // the text segment up higher in 5l for all GOOS. 37 long unmappedzero = 4096; 38 39 void 40 clearp(Prog *p) 41 { 42 p->as = AEND; 43 p->reg = NREG; 44 p->scond = C_SCOND_NONE; 45 p->from.type = D_NONE; 46 p->from.name = D_NONE; 47 p->from.reg = NREG; 48 p->to.type = D_NONE; 49 p->to.name = D_NONE; 50 p->to.reg = NREG; 51 p->loc = pcloc; 52 pcloc++; 53 } 54 55 static int ddumped; 56 static Prog *dfirst; 57 static Prog *dpc; 58 59 /* 60 * generate and return proc with p->as = as, 61 * linked into program. pc is next instruction. 62 */ 63 Prog* 64 prog(int as) 65 { 66 Prog *p; 67 68 if(as == ADATA || as == AGLOBL) { 69 if(ddumped) 70 fatal("already dumped data"); 71 if(dpc == nil) { 72 dpc = mal(sizeof(*dpc)); 73 dfirst = dpc; 74 } 75 p = dpc; 76 dpc = mal(sizeof(*dpc)); 77 p->link = dpc; 78 p->reg = 0; // used for flags 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 USED(likely); // TODO: record this for linker 123 124 p = prog(as); 125 p->to.type = D_BRANCH; 126 p->to.u.branch = P; 127 return p; 128 } 129 130 /* 131 * patch previous branch to jump to to. 132 */ 133 void 134 patch(Prog *p, Prog *to) 135 { 136 if(p->to.type != D_BRANCH) 137 fatal("patch: not a branch"); 138 p->to.u.branch = to; 139 p->to.offset = to->loc; 140 } 141 142 Prog* 143 unpatch(Prog *p) 144 { 145 Prog *q; 146 147 if(p->to.type != D_BRANCH) 148 fatal("unpatch: not a branch"); 149 q = p->to.u.branch; 150 p->to.u.branch = P; 151 p->to.offset = 0; 152 return q; 153 } 154 155 /* 156 * start a new Prog list. 157 */ 158 Plist* 159 newplist(void) 160 { 161 Plist *pl; 162 163 pl = mal(sizeof(*pl)); 164 if(plist == nil) 165 plist = pl; 166 else 167 plast->link = pl; 168 plast = pl; 169 170 pc = mal(sizeof(*pc)); 171 clearp(pc); 172 pl->firstpc = pc; 173 174 return pl; 175 } 176 177 void 178 gused(Node *n) 179 { 180 gins(ANOP, n, N); // used 181 } 182 183 Prog* 184 gjmp(Prog *to) 185 { 186 Prog *p; 187 188 p = gbranch(AB, T, 0); 189 if(to != P) 190 patch(p, to); 191 return p; 192 } 193 194 void 195 ggloblnod(Node *nam) 196 { 197 Prog *p; 198 199 p = gins(AGLOBL, nam, N); 200 p->lineno = nam->lineno; 201 p->from.gotype = ngotype(nam); 202 p->to.sym = S; 203 p->to.type = D_CONST; 204 p->to.offset = nam->type->width; 205 if(nam->readonly) 206 p->reg = RODATA; 207 if(nam->type != T && !haspointers(nam->type)) 208 p->reg |= NOPTR; 209 } 210 211 void 212 ggloblsym(Sym *s, int32 width, int dupok, int rodata) 213 { 214 Prog *p; 215 216 p = gins(AGLOBL, N, N); 217 p->from.type = D_OREG; 218 p->from.name = D_EXTERN; 219 p->from.sym = s; 220 p->to.type = D_CONST; 221 p->to.name = D_NONE; 222 p->to.offset = width; 223 if(dupok) 224 p->reg |= DUPOK; 225 if(rodata) 226 p->reg |= RODATA; 227 } 228 229 void 230 gtrack(Sym *s) 231 { 232 Prog *p; 233 234 p = gins(AUSEFIELD, N, N); 235 p->from.type = D_OREG; 236 p->from.name = D_EXTERN; 237 p->from.sym = s; 238 } 239 240 int 241 isfat(Type *t) 242 { 243 if(t != T) 244 switch(t->etype) { 245 case TSTRUCT: 246 case TARRAY: 247 case TSTRING: 248 case TINTER: // maybe remove later 249 return 1; 250 } 251 return 0; 252 } 253 254 /* 255 * naddr of func generates code for address of func. 256 * if using opcode that can take address implicitly, 257 * call afunclit to fix up the argument. 258 * also fix up direct register references to be D_OREG. 259 */ 260 void 261 afunclit(Addr *a, Node *n) 262 { 263 if(a->type == D_CONST && a->name == D_EXTERN || a->type == D_REG) { 264 a->type = D_OREG; 265 if(n->op == ONAME) 266 a->sym = n->sym; 267 } 268 } 269 270 static int resvd[] = 271 { 272 9, // reserved for m 273 10, // reserved for g 274 REGSP, // reserved for SP 275 }; 276 277 void 278 ginit(void) 279 { 280 int i; 281 282 for(i=0; i<nelem(reg); i++) 283 reg[i] = 0; 284 for(i=0; i<nelem(resvd); i++) 285 reg[resvd[i]]++; 286 } 287 288 void 289 gclean(void) 290 { 291 int i; 292 293 for(i=0; i<nelem(resvd); i++) 294 reg[resvd[i]]--; 295 296 for(i=0; i<nelem(reg); i++) 297 if(reg[i]) 298 yyerror("reg %R left allocated\n", i); 299 } 300 301 int32 302 anyregalloc(void) 303 { 304 int i, j; 305 306 for(i=0; i<nelem(reg); i++) { 307 if(reg[i] == 0) 308 goto ok; 309 for(j=0; j<nelem(resvd); j++) 310 if(resvd[j] == i) 311 goto ok; 312 return 1; 313 ok:; 314 } 315 return 0; 316 } 317 318 uintptr regpc[REGALLOC_FMAX+1]; 319 320 /* 321 * allocate register of type t, leave in n. 322 * if o != N, o is desired fixed register. 323 * caller must regfree(n). 324 */ 325 void 326 regalloc(Node *n, Type *t, Node *o) 327 { 328 int i, et, fixfree, floatfree; 329 330 if(0 && debug['r']) { 331 fixfree = 0; 332 for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++) 333 if(reg[i] == 0) 334 fixfree++; 335 floatfree = 0; 336 for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++) 337 if(reg[i] == 0) 338 floatfree++; 339 print("regalloc fix %d float %d\n", fixfree, floatfree); 340 } 341 342 if(t == T) 343 fatal("regalloc: t nil"); 344 et = simtype[t->etype]; 345 if(is64(t)) 346 fatal("regalloc: 64 bit type %T"); 347 348 switch(et) { 349 case TINT8: 350 case TUINT8: 351 case TINT16: 352 case TUINT16: 353 case TINT32: 354 case TUINT32: 355 case TPTR32: 356 case TBOOL: 357 if(o != N && o->op == OREGISTER) { 358 i = o->val.u.reg; 359 if(i >= REGALLOC_R0 && i <= REGALLOC_RMAX) 360 goto out; 361 } 362 for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++) 363 if(reg[i] == 0) { 364 regpc[i] = (uintptr)getcallerpc(&n); 365 goto out; 366 } 367 print("registers allocated at\n"); 368 for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++) 369 print("%d %p\n", i, regpc[i]); 370 yyerror("out of fixed registers"); 371 goto err; 372 373 case TFLOAT32: 374 case TFLOAT64: 375 if(o != N && o->op == OREGISTER) { 376 i = o->val.u.reg; 377 if(i >= REGALLOC_F0 && i <= REGALLOC_FMAX) 378 goto out; 379 } 380 for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++) 381 if(reg[i] == 0) 382 goto out; 383 yyerror("out of floating point registers"); 384 goto err; 385 386 case TCOMPLEX64: 387 case TCOMPLEX128: 388 tempname(n, t); 389 return; 390 } 391 yyerror("regalloc: unknown type %T", t); 392 393 err: 394 nodreg(n, t, 0); 395 return; 396 397 out: 398 reg[i]++; 399 nodreg(n, t, i); 400 } 401 402 void 403 regfree(Node *n) 404 { 405 int i, fixfree, floatfree; 406 407 if(0 && debug['r']) { 408 fixfree = 0; 409 for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++) 410 if(reg[i] == 0) 411 fixfree++; 412 floatfree = 0; 413 for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++) 414 if(reg[i] == 0) 415 floatfree++; 416 print("regalloc fix %d float %d\n", fixfree, floatfree); 417 } 418 419 if(n->op == ONAME) 420 return; 421 if(n->op != OREGISTER && n->op != OINDREG) 422 fatal("regfree: not a register"); 423 i = n->val.u.reg; 424 if(i == REGSP) 425 return; 426 if(i < 0 || i >= nelem(reg) || i >= nelem(regpc)) 427 fatal("regfree: reg out of range"); 428 if(reg[i] <= 0) 429 fatal("regfree: reg %R not allocated", i); 430 reg[i]--; 431 if(reg[i] == 0) 432 regpc[i] = 0; 433 } 434 435 /* 436 * initialize n to be register r of type t. 437 */ 438 void 439 nodreg(Node *n, Type *t, int r) 440 { 441 if(t == T) 442 fatal("nodreg: t nil"); 443 444 memset(n, 0, sizeof(*n)); 445 n->op = OREGISTER; 446 n->addable = 1; 447 ullmancalc(n); 448 n->val.u.reg = r; 449 n->type = t; 450 } 451 452 /* 453 * initialize n to be indirect of register r; n is type t. 454 */ 455 void 456 nodindreg(Node *n, Type *t, int r) 457 { 458 nodreg(n, t, r); 459 n->op = OINDREG; 460 } 461 462 Node* 463 nodarg(Type *t, int fp) 464 { 465 Node *n; 466 Type *first; 467 Iter savet; 468 469 // entire argument struct, not just one arg 470 if(t->etype == TSTRUCT && t->funarg) { 471 n = nod(ONAME, N, N); 472 n->sym = lookup(".args"); 473 n->type = t; 474 first = structfirst(&savet, &t); 475 if(first == nil) 476 fatal("nodarg: bad struct"); 477 if(first->width == BADWIDTH) 478 fatal("nodarg: offset not computed for %T", t); 479 n->xoffset = first->width; 480 n->addable = 1; 481 goto fp; 482 } 483 484 if(t->etype != TFIELD) 485 fatal("nodarg: not field %T", t); 486 487 n = nod(ONAME, N, N); 488 n->type = t->type; 489 n->sym = t->sym; 490 if(t->width == BADWIDTH) 491 fatal("nodarg: offset not computed for %T", t); 492 n->xoffset = t->width; 493 n->addable = 1; 494 n->orig = t->nname; 495 496 fp: 497 // Rewrite argument named _ to __, 498 // or else the assignment to _ will be 499 // discarded during code generation. 500 if(isblank(n)) 501 n->sym = lookup("__"); 502 503 switch(fp) { 504 default: 505 fatal("nodarg %T %d", t, fp); 506 507 case 0: // output arg for calling another function 508 n->op = OINDREG; 509 n->val.u.reg = REGSP; 510 n->xoffset += 4; 511 break; 512 513 case 1: // input arg to current function 514 n->class = PPARAM; 515 break; 516 } 517 n->typecheck = 1; 518 return n; 519 } 520 521 /* 522 * return constant i node. 523 * overwritten by next call, but useful in calls to gins. 524 */ 525 Node* 526 ncon(uint32 i) 527 { 528 static Node n; 529 530 if(n.type == T) 531 nodconst(&n, types[TUINT32], 0); 532 mpmovecfix(n.val.u.xval, i); 533 return &n; 534 } 535 536 /* 537 * Is this node a memory operand? 538 */ 539 int 540 ismem(Node *n) 541 { 542 switch(n->op) { 543 case OINDREG: 544 case ONAME: 545 case OPARAM: 546 case OCLOSUREVAR: 547 return 1; 548 } 549 return 0; 550 } 551 552 Node sclean[10]; 553 int nsclean; 554 555 /* 556 * n is a 64-bit value. fill in lo and hi to refer to its 32-bit halves. 557 */ 558 void 559 split64(Node *n, Node *lo, Node *hi) 560 { 561 Node n1; 562 int64 i; 563 564 if(!is64(n->type)) 565 fatal("split64 %T", n->type); 566 567 if(nsclean >= nelem(sclean)) 568 fatal("split64 clean"); 569 sclean[nsclean].op = OEMPTY; 570 nsclean++; 571 switch(n->op) { 572 default: 573 if(!dotaddable(n, &n1)) { 574 igen(n, &n1, N); 575 sclean[nsclean-1] = n1; 576 } 577 n = &n1; 578 goto common; 579 case ONAME: 580 if(n->class == PPARAMREF) { 581 cgen(n->heapaddr, &n1); 582 sclean[nsclean-1] = n1; 583 // fall through. 584 n = &n1; 585 } 586 goto common; 587 case OINDREG: 588 common: 589 *lo = *n; 590 *hi = *n; 591 lo->type = types[TUINT32]; 592 if(n->type->etype == TINT64) 593 hi->type = types[TINT32]; 594 else 595 hi->type = types[TUINT32]; 596 hi->xoffset += 4; 597 break; 598 599 case OLITERAL: 600 convconst(&n1, n->type, &n->val); 601 i = mpgetfix(n1.val.u.xval); 602 nodconst(lo, types[TUINT32], (uint32)i); 603 i >>= 32; 604 if(n->type->etype == TINT64) 605 nodconst(hi, types[TINT32], (int32)i); 606 else 607 nodconst(hi, types[TUINT32], (uint32)i); 608 break; 609 } 610 } 611 612 void 613 splitclean(void) 614 { 615 if(nsclean <= 0) 616 fatal("splitclean"); 617 nsclean--; 618 if(sclean[nsclean].op != OEMPTY) 619 regfree(&sclean[nsclean]); 620 } 621 622 #define CASE(a,b) (((a)<<16)|((b)<<0)) 623 624 void 625 gmove(Node *f, Node *t) 626 { 627 int a, ft, tt, fa, ta; 628 Type *cvt; 629 Node r1, r2, flo, fhi, tlo, thi, con; 630 Prog *p1; 631 632 if(debug['M']) 633 print("gmove %N -> %N\n", f, t); 634 635 ft = simsimtype(f->type); 636 tt = simsimtype(t->type); 637 cvt = t->type; 638 639 if(iscomplex[ft] || iscomplex[tt]) { 640 complexmove(f, t); 641 return; 642 } 643 644 // cannot have two memory operands; 645 // except 64-bit, which always copies via registers anyway. 646 if(!is64(f->type) && !is64(t->type) && ismem(f) && ismem(t)) 647 goto hard; 648 649 // convert constant to desired type 650 if(f->op == OLITERAL) { 651 switch(tt) { 652 default: 653 convconst(&con, t->type, &f->val); 654 break; 655 656 case TINT16: 657 case TINT8: 658 convconst(&con, types[TINT32], &f->val); 659 regalloc(&r1, con.type, t); 660 gins(AMOVW, &con, &r1); 661 gmove(&r1, t); 662 regfree(&r1); 663 return; 664 665 case TUINT16: 666 case TUINT8: 667 convconst(&con, types[TUINT32], &f->val); 668 regalloc(&r1, con.type, t); 669 gins(AMOVW, &con, &r1); 670 gmove(&r1, t); 671 regfree(&r1); 672 return; 673 } 674 675 f = &con; 676 ft = simsimtype(con.type); 677 678 // constants can't move directly to memory 679 if(ismem(t) && !is64(t->type)) goto hard; 680 } 681 682 // value -> value copy, only one memory operand. 683 // figure out the instruction to use. 684 // break out of switch for one-instruction gins. 685 // goto rdst for "destination must be register". 686 // goto hard for "convert to cvt type first". 687 // otherwise handle and return. 688 689 switch(CASE(ft, tt)) { 690 default: 691 goto fatal; 692 693 /* 694 * integer copy and truncate 695 */ 696 case CASE(TINT8, TINT8): // same size 697 case CASE(TUINT8, TINT8): 698 case CASE(TINT16, TINT8): // truncate 699 case CASE(TUINT16, TINT8): 700 case CASE(TINT32, TINT8): 701 case CASE(TUINT32, TINT8): 702 a = AMOVB; 703 break; 704 705 case CASE(TINT8, TUINT8): 706 case CASE(TUINT8, TUINT8): 707 case CASE(TINT16, TUINT8): 708 case CASE(TUINT16, TUINT8): 709 case CASE(TINT32, TUINT8): 710 case CASE(TUINT32, TUINT8): 711 a = AMOVBU; 712 break; 713 714 case CASE(TINT64, TINT8): // truncate low word 715 case CASE(TUINT64, TINT8): 716 a = AMOVB; 717 goto trunc64; 718 719 case CASE(TINT64, TUINT8): 720 case CASE(TUINT64, TUINT8): 721 a = AMOVBU; 722 goto trunc64; 723 724 case CASE(TINT16, TINT16): // same size 725 case CASE(TUINT16, TINT16): 726 case CASE(TINT32, TINT16): // truncate 727 case CASE(TUINT32, TINT16): 728 a = AMOVH; 729 break; 730 731 case CASE(TINT16, TUINT16): 732 case CASE(TUINT16, TUINT16): 733 case CASE(TINT32, TUINT16): 734 case CASE(TUINT32, TUINT16): 735 a = AMOVHU; 736 break; 737 738 case CASE(TINT64, TINT16): // truncate low word 739 case CASE(TUINT64, TINT16): 740 a = AMOVH; 741 goto trunc64; 742 743 case CASE(TINT64, TUINT16): 744 case CASE(TUINT64, TUINT16): 745 a = AMOVHU; 746 goto trunc64; 747 748 case CASE(TINT32, TINT32): // same size 749 case CASE(TINT32, TUINT32): 750 case CASE(TUINT32, TINT32): 751 case CASE(TUINT32, TUINT32): 752 a = AMOVW; 753 break; 754 755 case CASE(TINT64, TINT32): // truncate 756 case CASE(TUINT64, TINT32): 757 case CASE(TINT64, TUINT32): 758 case CASE(TUINT64, TUINT32): 759 split64(f, &flo, &fhi); 760 regalloc(&r1, t->type, N); 761 gins(AMOVW, &flo, &r1); 762 gins(AMOVW, &r1, t); 763 regfree(&r1); 764 splitclean(); 765 return; 766 767 case CASE(TINT64, TINT64): // same size 768 case CASE(TINT64, TUINT64): 769 case CASE(TUINT64, TINT64): 770 case CASE(TUINT64, TUINT64): 771 split64(f, &flo, &fhi); 772 split64(t, &tlo, &thi); 773 regalloc(&r1, flo.type, N); 774 regalloc(&r2, fhi.type, N); 775 gins(AMOVW, &flo, &r1); 776 gins(AMOVW, &fhi, &r2); 777 gins(AMOVW, &r1, &tlo); 778 gins(AMOVW, &r2, &thi); 779 regfree(&r1); 780 regfree(&r2); 781 splitclean(); 782 splitclean(); 783 return; 784 785 /* 786 * integer up-conversions 787 */ 788 case CASE(TINT8, TINT16): // sign extend int8 789 case CASE(TINT8, TUINT16): 790 case CASE(TINT8, TINT32): 791 case CASE(TINT8, TUINT32): 792 a = AMOVB; 793 goto rdst; 794 case CASE(TINT8, TINT64): // convert via int32 795 case CASE(TINT8, TUINT64): 796 cvt = types[TINT32]; 797 goto hard; 798 799 case CASE(TUINT8, TINT16): // zero extend uint8 800 case CASE(TUINT8, TUINT16): 801 case CASE(TUINT8, TINT32): 802 case CASE(TUINT8, TUINT32): 803 a = AMOVBU; 804 goto rdst; 805 case CASE(TUINT8, TINT64): // convert via uint32 806 case CASE(TUINT8, TUINT64): 807 cvt = types[TUINT32]; 808 goto hard; 809 810 case CASE(TINT16, TINT32): // sign extend int16 811 case CASE(TINT16, TUINT32): 812 a = AMOVH; 813 goto rdst; 814 case CASE(TINT16, TINT64): // convert via int32 815 case CASE(TINT16, TUINT64): 816 cvt = types[TINT32]; 817 goto hard; 818 819 case CASE(TUINT16, TINT32): // zero extend uint16 820 case CASE(TUINT16, TUINT32): 821 a = AMOVHU; 822 goto rdst; 823 case CASE(TUINT16, TINT64): // convert via uint32 824 case CASE(TUINT16, TUINT64): 825 cvt = types[TUINT32]; 826 goto hard; 827 828 case CASE(TINT32, TINT64): // sign extend int32 829 case CASE(TINT32, TUINT64): 830 split64(t, &tlo, &thi); 831 regalloc(&r1, tlo.type, N); 832 regalloc(&r2, thi.type, N); 833 gmove(f, &r1); 834 p1 = gins(AMOVW, &r1, &r2); 835 p1->from.type = D_SHIFT; 836 p1->from.offset = 2 << 5 | 31 << 7 | r1.val.u.reg; // r1->31 837 p1->from.reg = NREG; 838 //print("gmove: %P\n", p1); 839 gins(AMOVW, &r1, &tlo); 840 gins(AMOVW, &r2, &thi); 841 regfree(&r1); 842 regfree(&r2); 843 splitclean(); 844 return; 845 846 case CASE(TUINT32, TINT64): // zero extend uint32 847 case CASE(TUINT32, TUINT64): 848 split64(t, &tlo, &thi); 849 gmove(f, &tlo); 850 regalloc(&r1, thi.type, N); 851 gins(AMOVW, ncon(0), &r1); 852 gins(AMOVW, &r1, &thi); 853 regfree(&r1); 854 splitclean(); 855 return; 856 857 /* 858 * float to integer 859 */ 860 case CASE(TFLOAT32, TINT8): 861 case CASE(TFLOAT32, TUINT8): 862 case CASE(TFLOAT32, TINT16): 863 case CASE(TFLOAT32, TUINT16): 864 case CASE(TFLOAT32, TINT32): 865 case CASE(TFLOAT32, TUINT32): 866 // case CASE(TFLOAT32, TUINT64): 867 868 case CASE(TFLOAT64, TINT8): 869 case CASE(TFLOAT64, TUINT8): 870 case CASE(TFLOAT64, TINT16): 871 case CASE(TFLOAT64, TUINT16): 872 case CASE(TFLOAT64, TINT32): 873 case CASE(TFLOAT64, TUINT32): 874 // case CASE(TFLOAT64, TUINT64): 875 fa = AMOVF; 876 a = AMOVFW; 877 if(ft == TFLOAT64) { 878 fa = AMOVD; 879 a = AMOVDW; 880 } 881 ta = AMOVW; 882 switch(tt) { 883 case TINT8: 884 ta = AMOVB; 885 break; 886 case TUINT8: 887 ta = AMOVBU; 888 break; 889 case TINT16: 890 ta = AMOVH; 891 break; 892 case TUINT16: 893 ta = AMOVHU; 894 break; 895 } 896 897 regalloc(&r1, types[ft], f); 898 regalloc(&r2, types[tt], t); 899 gins(fa, f, &r1); // load to fpu 900 p1 = gins(a, &r1, &r1); // convert to w 901 switch(tt) { 902 case TUINT8: 903 case TUINT16: 904 case TUINT32: 905 p1->scond |= C_UBIT; 906 } 907 gins(AMOVW, &r1, &r2); // copy to cpu 908 gins(ta, &r2, t); // store 909 regfree(&r1); 910 regfree(&r2); 911 return; 912 913 /* 914 * integer to float 915 */ 916 case CASE(TINT8, TFLOAT32): 917 case CASE(TUINT8, TFLOAT32): 918 case CASE(TINT16, TFLOAT32): 919 case CASE(TUINT16, TFLOAT32): 920 case CASE(TINT32, TFLOAT32): 921 case CASE(TUINT32, TFLOAT32): 922 case CASE(TINT8, TFLOAT64): 923 case CASE(TUINT8, TFLOAT64): 924 case CASE(TINT16, TFLOAT64): 925 case CASE(TUINT16, TFLOAT64): 926 case CASE(TINT32, TFLOAT64): 927 case CASE(TUINT32, TFLOAT64): 928 fa = AMOVW; 929 switch(ft) { 930 case TINT8: 931 fa = AMOVB; 932 break; 933 case TUINT8: 934 fa = AMOVBU; 935 break; 936 case TINT16: 937 fa = AMOVH; 938 break; 939 case TUINT16: 940 fa = AMOVHU; 941 break; 942 } 943 a = AMOVWF; 944 ta = AMOVF; 945 if(tt == TFLOAT64) { 946 a = AMOVWD; 947 ta = AMOVD; 948 } 949 regalloc(&r1, types[ft], f); 950 regalloc(&r2, types[tt], t); 951 gins(fa, f, &r1); // load to cpu 952 gins(AMOVW, &r1, &r2); // copy to fpu 953 p1 = gins(a, &r2, &r2); // convert 954 switch(ft) { 955 case TUINT8: 956 case TUINT16: 957 case TUINT32: 958 p1->scond |= C_UBIT; 959 } 960 gins(ta, &r2, t); // store 961 regfree(&r1); 962 regfree(&r2); 963 return; 964 965 case CASE(TUINT64, TFLOAT32): 966 case CASE(TUINT64, TFLOAT64): 967 fatal("gmove UINT64, TFLOAT not implemented"); 968 return; 969 970 971 /* 972 * float to float 973 */ 974 case CASE(TFLOAT32, TFLOAT32): 975 a = AMOVF; 976 break; 977 978 case CASE(TFLOAT64, TFLOAT64): 979 a = AMOVD; 980 break; 981 982 case CASE(TFLOAT32, TFLOAT64): 983 regalloc(&r1, types[TFLOAT64], t); 984 gins(AMOVF, f, &r1); 985 gins(AMOVFD, &r1, &r1); 986 gins(AMOVD, &r1, t); 987 regfree(&r1); 988 return; 989 990 case CASE(TFLOAT64, TFLOAT32): 991 regalloc(&r1, types[TFLOAT64], t); 992 gins(AMOVD, f, &r1); 993 gins(AMOVDF, &r1, &r1); 994 gins(AMOVF, &r1, t); 995 regfree(&r1); 996 return; 997 } 998 999 gins(a, f, t); 1000 return; 1001 1002 rdst: 1003 // TODO(kaib): we almost always require a register dest anyway, this can probably be 1004 // removed. 1005 // requires register destination 1006 regalloc(&r1, t->type, t); 1007 gins(a, f, &r1); 1008 gmove(&r1, t); 1009 regfree(&r1); 1010 return; 1011 1012 hard: 1013 // requires register intermediate 1014 regalloc(&r1, cvt, t); 1015 gmove(f, &r1); 1016 gmove(&r1, t); 1017 regfree(&r1); 1018 return; 1019 1020 trunc64: 1021 // truncate 64 bit integer 1022 split64(f, &flo, &fhi); 1023 regalloc(&r1, t->type, N); 1024 gins(a, &flo, &r1); 1025 gins(a, &r1, t); 1026 regfree(&r1); 1027 splitclean(); 1028 return; 1029 1030 fatal: 1031 // should not happen 1032 fatal("gmove %N -> %N", f, t); 1033 } 1034 1035 int 1036 samaddr(Node *f, Node *t) 1037 { 1038 1039 if(f->op != t->op) 1040 return 0; 1041 1042 switch(f->op) { 1043 case OREGISTER: 1044 if(f->val.u.reg != t->val.u.reg) 1045 break; 1046 return 1; 1047 } 1048 return 0; 1049 } 1050 1051 /* 1052 * generate one instruction: 1053 * as f, t 1054 */ 1055 Prog* 1056 gins(int as, Node *f, Node *t) 1057 { 1058 // Node nod; 1059 // int32 v; 1060 Prog *p; 1061 Addr af, at; 1062 1063 if(f != N && f->op == OINDEX) { 1064 fatal("gins OINDEX not implemented"); 1065 // regalloc(&nod, ®node, Z); 1066 // v = constnode.vconst; 1067 // cgen(f->right, &nod); 1068 // constnode.vconst = v; 1069 // idx.reg = nod.reg; 1070 // regfree(&nod); 1071 } 1072 if(t != N && t->op == OINDEX) { 1073 fatal("gins OINDEX not implemented"); 1074 // regalloc(&nod, ®node, Z); 1075 // v = constnode.vconst; 1076 // cgen(t->right, &nod); 1077 // constnode.vconst = v; 1078 // idx.reg = nod.reg; 1079 // regfree(&nod); 1080 } 1081 1082 memset(&af, 0, sizeof af); 1083 memset(&at, 0, sizeof at); 1084 if(f != N) 1085 naddr(f, &af, 1); 1086 if(t != N) 1087 naddr(t, &at, 1); 1088 p = prog(as); 1089 if(f != N) 1090 p->from = af; 1091 if(t != N) 1092 p->to = at; 1093 if(debug['g']) 1094 print("%P\n", p); 1095 return p; 1096 } 1097 1098 /* 1099 * insert n into reg slot of p 1100 */ 1101 void 1102 raddr(Node *n, Prog *p) 1103 { 1104 Addr a; 1105 1106 naddr(n, &a, 1); 1107 if(a.type != D_REG && a.type != D_FREG) { 1108 if(n) 1109 fatal("bad in raddr: %O", n->op); 1110 else 1111 fatal("bad in raddr: <null>"); 1112 p->reg = NREG; 1113 } else 1114 p->reg = a.reg; 1115 } 1116 1117 /* generate a comparison 1118 TODO(kaib): one of the args can actually be a small constant. relax the constraint and fix call sites. 1119 */ 1120 Prog* 1121 gcmp(int as, Node *lhs, Node *rhs) 1122 { 1123 Prog *p; 1124 1125 if(lhs->op != OREGISTER) 1126 fatal("bad operands to gcmp: %O %O", lhs->op, rhs->op); 1127 1128 p = gins(as, rhs, N); 1129 raddr(lhs, p); 1130 return p; 1131 } 1132 1133 /* generate a constant shift 1134 * arm encodes a shift by 32 as 0, thus asking for 0 shift is illegal. 1135 */ 1136 Prog* 1137 gshift(int as, Node *lhs, int32 stype, int32 sval, Node *rhs) 1138 { 1139 Prog *p; 1140 1141 if(sval <= 0 || sval > 32) 1142 fatal("bad shift value: %d", sval); 1143 1144 sval = sval&0x1f; 1145 1146 p = gins(as, N, rhs); 1147 p->from.type = D_SHIFT; 1148 p->from.offset = stype | sval<<7 | lhs->val.u.reg; 1149 return p; 1150 } 1151 1152 /* generate a register shift 1153 */ 1154 Prog * 1155 gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs) 1156 { 1157 Prog *p; 1158 p = gins(as, N, rhs); 1159 p->from.type = D_SHIFT; 1160 p->from.offset = stype | reg->val.u.reg << 8 | 1<<4 | lhs->val.u.reg; 1161 return p; 1162 } 1163 1164 // Generate an instruction referencing *n 1165 // to force segv on nil pointer dereference. 1166 void 1167 checkref(Node *n, int force) 1168 { 1169 Node m1, m2; 1170 1171 if(!force && isptr[n->type->etype] && n->type->type->width < unmappedzero) 1172 return; 1173 1174 regalloc(&m1, types[TUINTPTR], n); 1175 regalloc(&m2, types[TUINT8], n); 1176 cgen(n, &m1); 1177 m1.xoffset = 0; 1178 m1.op = OINDREG; 1179 m1.type = types[TUINT8]; 1180 gins(AMOVBU, &m1, &m2); 1181 regfree(&m2); 1182 regfree(&m1); 1183 } 1184 1185 static void 1186 checkoffset(Addr *a, int canemitcode) 1187 { 1188 Prog *p; 1189 Node n1; 1190 1191 if(a->offset < unmappedzero) 1192 return; 1193 if(!canemitcode) 1194 fatal("checkoffset %#x, cannot emit code", a->offset); 1195 1196 // cannot rely on unmapped nil page at 0 to catch 1197 // reference with large offset. instead, emit explicit 1198 // test of 0(reg). 1199 regalloc(&n1, types[TUINTPTR], N); 1200 p = gins(AMOVB, N, &n1); 1201 p->from = *a; 1202 p->from.offset = 0; 1203 regfree(&n1); 1204 } 1205 1206 /* 1207 * generate code to compute n; 1208 * make a refer to result. 1209 */ 1210 void 1211 naddr(Node *n, Addr *a, int canemitcode) 1212 { 1213 a->type = D_NONE; 1214 a->name = D_NONE; 1215 a->reg = NREG; 1216 a->gotype = S; 1217 a->node = N; 1218 a->etype = 0; 1219 if(n == N) 1220 return; 1221 1222 if(n->type != T && n->type->etype != TIDEAL) { 1223 dowidth(n->type); 1224 a->width = n->type->width; 1225 } 1226 1227 switch(n->op) { 1228 default: 1229 fatal("naddr: bad %O %D", n->op, a); 1230 break; 1231 1232 case OREGISTER: 1233 if(n->val.u.reg <= REGALLOC_RMAX) { 1234 a->type = D_REG; 1235 a->reg = n->val.u.reg; 1236 } else { 1237 a->type = D_FREG; 1238 a->reg = n->val.u.reg - REGALLOC_F0; 1239 } 1240 a->sym = S; 1241 break; 1242 1243 case OINDEX: 1244 case OIND: 1245 fatal("naddr: OINDEX"); 1246 // naddr(n->left, a); 1247 // if(a->type >= D_AX && a->type <= D_DI) 1248 // a->type += D_INDIR; 1249 // else 1250 // if(a->type == D_CONST) 1251 // a->type = D_NONE+D_INDIR; 1252 // else 1253 // if(a->type == D_ADDR) { 1254 // a->type = a->index; 1255 // a->index = D_NONE; 1256 // } else 1257 // goto bad; 1258 // if(n->op == OINDEX) { 1259 // a->index = idx.reg; 1260 // a->scale = n->scale; 1261 // } 1262 // break; 1263 1264 case OINDREG: 1265 a->type = D_OREG; 1266 a->reg = n->val.u.reg; 1267 a->sym = n->sym; 1268 a->offset = n->xoffset; 1269 checkoffset(a, canemitcode); 1270 break; 1271 1272 case OPARAM: 1273 // n->left is PHEAP ONAME for stack parameter. 1274 // compute address of actual parameter on stack. 1275 a->etype = simtype[n->left->type->etype]; 1276 a->width = n->left->type->width; 1277 a->offset = n->xoffset; 1278 a->sym = n->left->sym; 1279 a->type = D_OREG; 1280 a->name = D_PARAM; 1281 a->node = n->left->orig; 1282 break; 1283 1284 case OCLOSUREVAR: 1285 a->type = D_OREG; 1286 a->reg = 7; 1287 a->offset = n->xoffset; 1288 a->sym = S; 1289 break; 1290 1291 case OCFUNC: 1292 naddr(n->left, a, canemitcode); 1293 a->sym = n->left->sym; 1294 break; 1295 1296 case ONAME: 1297 a->etype = 0; 1298 a->width = 0; 1299 a->reg = NREG; 1300 if(n->type != T) { 1301 a->etype = simtype[n->type->etype]; 1302 a->width = n->type->width; 1303 } 1304 a->offset = n->xoffset; 1305 a->sym = n->sym; 1306 a->node = n->orig; 1307 //if(a->node >= (Node*)&n) 1308 // fatal("stack node"); 1309 if(a->sym == S) 1310 a->sym = lookup(".noname"); 1311 if(n->method) { 1312 if(n->type != T) 1313 if(n->type->sym != S) 1314 if(n->type->sym->pkg != nil) 1315 a->sym = pkglookup(a->sym->name, n->type->sym->pkg); 1316 } 1317 1318 a->type = D_OREG; 1319 switch(n->class) { 1320 default: 1321 fatal("naddr: ONAME class %S %d\n", n->sym, n->class); 1322 case PEXTERN: 1323 a->name = D_EXTERN; 1324 break; 1325 case PAUTO: 1326 a->name = D_AUTO; 1327 break; 1328 case PPARAM: 1329 case PPARAMOUT: 1330 a->name = D_PARAM; 1331 break; 1332 case PFUNC: 1333 a->name = D_EXTERN; 1334 a->type = D_CONST; 1335 a->sym = funcsym(a->sym); 1336 break; 1337 } 1338 break; 1339 1340 case OLITERAL: 1341 switch(n->val.ctype) { 1342 default: 1343 fatal("naddr: const %lT", n->type); 1344 break; 1345 case CTFLT: 1346 a->type = D_FCONST; 1347 a->u.dval = mpgetflt(n->val.u.fval); 1348 break; 1349 case CTINT: 1350 case CTRUNE: 1351 a->sym = S; 1352 a->type = D_CONST; 1353 a->offset = mpgetfix(n->val.u.xval); 1354 break; 1355 case CTSTR: 1356 datagostring(n->val.u.sval, a); 1357 break; 1358 case CTBOOL: 1359 a->sym = S; 1360 a->type = D_CONST; 1361 a->offset = n->val.u.bval; 1362 break; 1363 case CTNIL: 1364 a->sym = S; 1365 a->type = D_CONST; 1366 a->offset = 0; 1367 break; 1368 } 1369 break; 1370 1371 case OITAB: 1372 // itable of interface value 1373 naddr(n->left, a, canemitcode); 1374 a->etype = TINT32; 1375 if(a->type == D_CONST && a->offset == 0) 1376 break; // len(nil) 1377 if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero) 1378 checkoffset(a, canemitcode); 1379 break; 1380 1381 case OLEN: 1382 // len of string or slice 1383 naddr(n->left, a, canemitcode); 1384 a->etype = TINT32; 1385 if(a->type == D_CONST && a->offset == 0) 1386 break; // len(nil) 1387 a->offset += Array_nel; 1388 if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero) 1389 checkoffset(a, canemitcode); 1390 break; 1391 1392 case OCAP: 1393 // cap of string or slice 1394 naddr(n->left, a, canemitcode); 1395 a->etype = TINT32; 1396 if(a->type == D_CONST && a->offset == 0) 1397 break; // cap(nil) 1398 a->offset += Array_cap; 1399 if(a->offset >= unmappedzero && a->offset-Array_cap < unmappedzero) 1400 checkoffset(a, canemitcode); 1401 break; 1402 1403 case OADDR: 1404 naddr(n->left, a, canemitcode); 1405 a->etype = tptr; 1406 switch(a->type) { 1407 case D_OREG: 1408 a->type = D_CONST; 1409 break; 1410 1411 case D_REG: 1412 case D_CONST: 1413 break; 1414 1415 default: 1416 fatal("naddr: OADDR %d\n", a->type); 1417 } 1418 } 1419 1420 if(a->width < 0) 1421 fatal("naddr: bad width for %N -> %D", n, a); 1422 } 1423 1424 /* 1425 * return Axxx for Oxxx on type t. 1426 */ 1427 int 1428 optoas(int op, Type *t) 1429 { 1430 int a; 1431 1432 if(t == T) 1433 fatal("optoas: t is nil"); 1434 1435 a = AGOK; 1436 switch(CASE(op, simtype[t->etype])) { 1437 default: 1438 fatal("optoas: no entry %O-%T etype %T simtype %T", op, t, types[t->etype], types[simtype[t->etype]]); 1439 break; 1440 1441 /* case CASE(OADDR, TPTR32): 1442 a = ALEAL; 1443 break; 1444 1445 case CASE(OADDR, TPTR64): 1446 a = ALEAQ; 1447 break; 1448 */ 1449 // TODO(kaib): make sure the conditional branches work on all edge cases 1450 case CASE(OEQ, TBOOL): 1451 case CASE(OEQ, TINT8): 1452 case CASE(OEQ, TUINT8): 1453 case CASE(OEQ, TINT16): 1454 case CASE(OEQ, TUINT16): 1455 case CASE(OEQ, TINT32): 1456 case CASE(OEQ, TUINT32): 1457 case CASE(OEQ, TINT64): 1458 case CASE(OEQ, TUINT64): 1459 case CASE(OEQ, TPTR32): 1460 case CASE(OEQ, TPTR64): 1461 case CASE(OEQ, TFLOAT32): 1462 case CASE(OEQ, TFLOAT64): 1463 a = ABEQ; 1464 break; 1465 1466 case CASE(ONE, TBOOL): 1467 case CASE(ONE, TINT8): 1468 case CASE(ONE, TUINT8): 1469 case CASE(ONE, TINT16): 1470 case CASE(ONE, TUINT16): 1471 case CASE(ONE, TINT32): 1472 case CASE(ONE, TUINT32): 1473 case CASE(ONE, TINT64): 1474 case CASE(ONE, TUINT64): 1475 case CASE(ONE, TPTR32): 1476 case CASE(ONE, TPTR64): 1477 case CASE(ONE, TFLOAT32): 1478 case CASE(ONE, TFLOAT64): 1479 a = ABNE; 1480 break; 1481 1482 case CASE(OLT, TINT8): 1483 case CASE(OLT, TINT16): 1484 case CASE(OLT, TINT32): 1485 case CASE(OLT, TINT64): 1486 case CASE(OLT, TFLOAT32): 1487 case CASE(OLT, TFLOAT64): 1488 a = ABLT; 1489 break; 1490 1491 case CASE(OLT, TUINT8): 1492 case CASE(OLT, TUINT16): 1493 case CASE(OLT, TUINT32): 1494 case CASE(OLT, TUINT64): 1495 a = ABLO; 1496 break; 1497 1498 case CASE(OLE, TINT8): 1499 case CASE(OLE, TINT16): 1500 case CASE(OLE, TINT32): 1501 case CASE(OLE, TINT64): 1502 case CASE(OLE, TFLOAT32): 1503 case CASE(OLE, TFLOAT64): 1504 a = ABLE; 1505 break; 1506 1507 case CASE(OLE, TUINT8): 1508 case CASE(OLE, TUINT16): 1509 case CASE(OLE, TUINT32): 1510 case CASE(OLE, TUINT64): 1511 a = ABLS; 1512 break; 1513 1514 case CASE(OGT, TINT8): 1515 case CASE(OGT, TINT16): 1516 case CASE(OGT, TINT32): 1517 case CASE(OGT, TINT64): 1518 case CASE(OGT, TFLOAT32): 1519 case CASE(OGT, TFLOAT64): 1520 a = ABGT; 1521 break; 1522 1523 case CASE(OGT, TUINT8): 1524 case CASE(OGT, TUINT16): 1525 case CASE(OGT, TUINT32): 1526 case CASE(OGT, TUINT64): 1527 a = ABHI; 1528 break; 1529 1530 case CASE(OGE, TINT8): 1531 case CASE(OGE, TINT16): 1532 case CASE(OGE, TINT32): 1533 case CASE(OGE, TINT64): 1534 case CASE(OGE, TFLOAT32): 1535 case CASE(OGE, TFLOAT64): 1536 a = ABGE; 1537 break; 1538 1539 case CASE(OGE, TUINT8): 1540 case CASE(OGE, TUINT16): 1541 case CASE(OGE, TUINT32): 1542 case CASE(OGE, TUINT64): 1543 a = ABHS; 1544 break; 1545 1546 case CASE(OCMP, TBOOL): 1547 case CASE(OCMP, TINT8): 1548 case CASE(OCMP, TUINT8): 1549 case CASE(OCMP, TINT16): 1550 case CASE(OCMP, TUINT16): 1551 case CASE(OCMP, TINT32): 1552 case CASE(OCMP, TUINT32): 1553 case CASE(OCMP, TPTR32): 1554 a = ACMP; 1555 break; 1556 1557 case CASE(OCMP, TFLOAT32): 1558 a = ACMPF; 1559 break; 1560 1561 case CASE(OCMP, TFLOAT64): 1562 a = ACMPD; 1563 break; 1564 1565 case CASE(OAS, TBOOL): 1566 case CASE(OAS, TINT8): 1567 a = AMOVB; 1568 break; 1569 1570 case CASE(OAS, TUINT8): 1571 a = AMOVBU; 1572 break; 1573 1574 case CASE(OAS, TINT16): 1575 a = AMOVH; 1576 break; 1577 1578 case CASE(OAS, TUINT16): 1579 a = AMOVHU; 1580 break; 1581 1582 case CASE(OAS, TINT32): 1583 case CASE(OAS, TUINT32): 1584 case CASE(OAS, TPTR32): 1585 a = AMOVW; 1586 break; 1587 1588 case CASE(OAS, TFLOAT32): 1589 a = AMOVF; 1590 break; 1591 1592 case CASE(OAS, TFLOAT64): 1593 a = AMOVD; 1594 break; 1595 1596 case CASE(OADD, TINT8): 1597 case CASE(OADD, TUINT8): 1598 case CASE(OADD, TINT16): 1599 case CASE(OADD, TUINT16): 1600 case CASE(OADD, TINT32): 1601 case CASE(OADD, TUINT32): 1602 case CASE(OADD, TPTR32): 1603 a = AADD; 1604 break; 1605 1606 case CASE(OADD, TFLOAT32): 1607 a = AADDF; 1608 break; 1609 1610 case CASE(OADD, TFLOAT64): 1611 a = AADDD; 1612 break; 1613 1614 case CASE(OSUB, TINT8): 1615 case CASE(OSUB, TUINT8): 1616 case CASE(OSUB, TINT16): 1617 case CASE(OSUB, TUINT16): 1618 case CASE(OSUB, TINT32): 1619 case CASE(OSUB, TUINT32): 1620 case CASE(OSUB, TPTR32): 1621 a = ASUB; 1622 break; 1623 1624 case CASE(OSUB, TFLOAT32): 1625 a = ASUBF; 1626 break; 1627 1628 case CASE(OSUB, TFLOAT64): 1629 a = ASUBD; 1630 break; 1631 1632 case CASE(OMINUS, TINT8): 1633 case CASE(OMINUS, TUINT8): 1634 case CASE(OMINUS, TINT16): 1635 case CASE(OMINUS, TUINT16): 1636 case CASE(OMINUS, TINT32): 1637 case CASE(OMINUS, TUINT32): 1638 case CASE(OMINUS, TPTR32): 1639 a = ARSB; 1640 break; 1641 1642 case CASE(OAND, TINT8): 1643 case CASE(OAND, TUINT8): 1644 case CASE(OAND, TINT16): 1645 case CASE(OAND, TUINT16): 1646 case CASE(OAND, TINT32): 1647 case CASE(OAND, TUINT32): 1648 case CASE(OAND, TPTR32): 1649 a = AAND; 1650 break; 1651 1652 case CASE(OOR, TINT8): 1653 case CASE(OOR, TUINT8): 1654 case CASE(OOR, TINT16): 1655 case CASE(OOR, TUINT16): 1656 case CASE(OOR, TINT32): 1657 case CASE(OOR, TUINT32): 1658 case CASE(OOR, TPTR32): 1659 a = AORR; 1660 break; 1661 1662 case CASE(OXOR, TINT8): 1663 case CASE(OXOR, TUINT8): 1664 case CASE(OXOR, TINT16): 1665 case CASE(OXOR, TUINT16): 1666 case CASE(OXOR, TINT32): 1667 case CASE(OXOR, TUINT32): 1668 case CASE(OXOR, TPTR32): 1669 a = AEOR; 1670 break; 1671 1672 case CASE(OLSH, TINT8): 1673 case CASE(OLSH, TUINT8): 1674 case CASE(OLSH, TINT16): 1675 case CASE(OLSH, TUINT16): 1676 case CASE(OLSH, TINT32): 1677 case CASE(OLSH, TUINT32): 1678 case CASE(OLSH, TPTR32): 1679 a = ASLL; 1680 break; 1681 1682 case CASE(ORSH, TUINT8): 1683 case CASE(ORSH, TUINT16): 1684 case CASE(ORSH, TUINT32): 1685 case CASE(ORSH, TPTR32): 1686 a = ASRL; 1687 break; 1688 1689 case CASE(ORSH, TINT8): 1690 case CASE(ORSH, TINT16): 1691 case CASE(ORSH, TINT32): 1692 a = ASRA; 1693 break; 1694 1695 case CASE(OMUL, TUINT8): 1696 case CASE(OMUL, TUINT16): 1697 case CASE(OMUL, TUINT32): 1698 case CASE(OMUL, TPTR32): 1699 a = AMULU; 1700 break; 1701 1702 case CASE(OMUL, TINT8): 1703 case CASE(OMUL, TINT16): 1704 case CASE(OMUL, TINT32): 1705 a = AMUL; 1706 break; 1707 1708 case CASE(OMUL, TFLOAT32): 1709 a = AMULF; 1710 break; 1711 1712 case CASE(OMUL, TFLOAT64): 1713 a = AMULD; 1714 break; 1715 1716 case CASE(ODIV, TUINT8): 1717 case CASE(ODIV, TUINT16): 1718 case CASE(ODIV, TUINT32): 1719 case CASE(ODIV, TPTR32): 1720 a = ADIVU; 1721 break; 1722 1723 case CASE(ODIV, TINT8): 1724 case CASE(ODIV, TINT16): 1725 case CASE(ODIV, TINT32): 1726 a = ADIV; 1727 break; 1728 1729 case CASE(OMOD, TUINT8): 1730 case CASE(OMOD, TUINT16): 1731 case CASE(OMOD, TUINT32): 1732 case CASE(OMOD, TPTR32): 1733 a = AMODU; 1734 break; 1735 1736 case CASE(OMOD, TINT8): 1737 case CASE(OMOD, TINT16): 1738 case CASE(OMOD, TINT32): 1739 a = AMOD; 1740 break; 1741 1742 // case CASE(OEXTEND, TINT16): 1743 // a = ACWD; 1744 // break; 1745 1746 // case CASE(OEXTEND, TINT32): 1747 // a = ACDQ; 1748 // break; 1749 1750 // case CASE(OEXTEND, TINT64): 1751 // a = ACQO; 1752 // break; 1753 1754 case CASE(ODIV, TFLOAT32): 1755 a = ADIVF; 1756 break; 1757 1758 case CASE(ODIV, TFLOAT64): 1759 a = ADIVD; 1760 break; 1761 1762 } 1763 return a; 1764 } 1765 1766 enum 1767 { 1768 ODynam = 1<<0, 1769 OPtrto = 1<<1, 1770 }; 1771 1772 static Node clean[20]; 1773 static int cleani = 0; 1774 1775 void 1776 sudoclean(void) 1777 { 1778 if(clean[cleani-1].op != OEMPTY) 1779 regfree(&clean[cleani-1]); 1780 if(clean[cleani-2].op != OEMPTY) 1781 regfree(&clean[cleani-2]); 1782 cleani -= 2; 1783 } 1784 1785 int 1786 dotaddable(Node *n, Node *n1) 1787 { 1788 int o; 1789 int64 oary[10]; 1790 Node *nn; 1791 1792 if(n->op != ODOT) 1793 return 0; 1794 1795 o = dotoffset(n, oary, &nn); 1796 if(nn != N && nn->addable && o == 1 && oary[0] >= 0) { 1797 *n1 = *nn; 1798 n1->type = n->type; 1799 n1->xoffset += oary[0]; 1800 return 1; 1801 } 1802 return 0; 1803 } 1804 1805 /* 1806 * generate code to compute address of n, 1807 * a reference to a (perhaps nested) field inside 1808 * an array or struct. 1809 * return 0 on failure, 1 on success. 1810 * on success, leaves usable address in a. 1811 * 1812 * caller is responsible for calling sudoclean 1813 * after successful sudoaddable, 1814 * to release the register used for a. 1815 */ 1816 int 1817 sudoaddable(int as, Node *n, Addr *a, int *w) 1818 { 1819 int o, i; 1820 int64 oary[10]; 1821 int64 v; 1822 Node n1, n2, n3, n4, *nn, *l, *r; 1823 Node *reg, *reg1; 1824 Prog *p1, *p2; 1825 Type *t; 1826 1827 if(n->type == T) 1828 return 0; 1829 1830 switch(n->op) { 1831 case OLITERAL: 1832 if(!isconst(n, CTINT)) 1833 break; 1834 v = mpgetfix(n->val.u.xval); 1835 if(v >= 32000 || v <= -32000) 1836 break; 1837 goto lit; 1838 1839 case ODOT: 1840 case ODOTPTR: 1841 cleani += 2; 1842 reg = &clean[cleani-1]; 1843 reg1 = &clean[cleani-2]; 1844 reg->op = OEMPTY; 1845 reg1->op = OEMPTY; 1846 goto odot; 1847 1848 case OINDEX: 1849 return 0; 1850 // disabled: OINDEX case is now covered by agenr 1851 // for a more suitable register allocation pattern. 1852 if(n->left->type->etype == TSTRING) 1853 return 0; 1854 cleani += 2; 1855 reg = &clean[cleani-1]; 1856 reg1 = &clean[cleani-2]; 1857 reg->op = OEMPTY; 1858 reg1->op = OEMPTY; 1859 goto oindex; 1860 } 1861 return 0; 1862 1863 lit: 1864 switch(as) { 1865 default: 1866 return 0; 1867 case AADD: case ASUB: case AAND: case AORR: case AEOR: 1868 case AMOVB: case AMOVBU: case AMOVH: case AMOVHU: 1869 case AMOVW: 1870 break; 1871 } 1872 1873 cleani += 2; 1874 reg = &clean[cleani-1]; 1875 reg1 = &clean[cleani-2]; 1876 reg->op = OEMPTY; 1877 reg1->op = OEMPTY; 1878 naddr(n, a, 1); 1879 goto yes; 1880 1881 odot: 1882 o = dotoffset(n, oary, &nn); 1883 if(nn == N) 1884 goto no; 1885 1886 if(nn->addable && o == 1 && oary[0] >= 0) { 1887 // directly addressable set of DOTs 1888 n1 = *nn; 1889 n1.type = n->type; 1890 n1.xoffset += oary[0]; 1891 naddr(&n1, a, 1); 1892 goto yes; 1893 } 1894 1895 regalloc(reg, types[tptr], N); 1896 n1 = *reg; 1897 n1.op = OINDREG; 1898 if(oary[0] >= 0) { 1899 agen(nn, reg); 1900 n1.xoffset = oary[0]; 1901 } else { 1902 cgen(nn, reg); 1903 n1.xoffset = -(oary[0]+1); 1904 } 1905 1906 for(i=1; i<o; i++) { 1907 if(oary[i] >= 0) 1908 fatal("cant happen"); 1909 gins(AMOVW, &n1, reg); 1910 n1.xoffset = -(oary[i]+1); 1911 } 1912 1913 a->type = D_NONE; 1914 a->name = D_NONE; 1915 n1.type = n->type; 1916 naddr(&n1, a, 1); 1917 goto yes; 1918 1919 oindex: 1920 l = n->left; 1921 r = n->right; 1922 if(l->ullman >= UINF && r->ullman >= UINF) 1923 goto no; 1924 1925 // set o to type of array 1926 o = 0; 1927 if(isptr[l->type->etype]) { 1928 o += OPtrto; 1929 if(l->type->type->etype != TARRAY) 1930 fatal("not ptr ary"); 1931 if(l->type->type->bound < 0) 1932 o += ODynam; 1933 } else { 1934 if(l->type->etype != TARRAY) 1935 fatal("not ary"); 1936 if(l->type->bound < 0) 1937 o += ODynam; 1938 } 1939 1940 *w = n->type->width; 1941 if(isconst(r, CTINT)) 1942 goto oindex_const; 1943 1944 switch(*w) { 1945 default: 1946 goto no; 1947 case 1: 1948 case 2: 1949 case 4: 1950 case 8: 1951 break; 1952 } 1953 1954 // load the array (reg) 1955 if(l->ullman > r->ullman) { 1956 regalloc(reg, types[tptr], N); 1957 if(o & OPtrto) 1958 cgen(l, reg); 1959 else 1960 agen(l, reg); 1961 } 1962 1963 // load the index (reg1) 1964 t = types[TUINT32]; 1965 if(issigned[r->type->etype]) 1966 t = types[TINT32]; 1967 regalloc(reg1, t, N); 1968 regalloc(&n3, types[TINT32], reg1); 1969 p2 = cgenindex(r, &n3, debug['B'] || n->bounded); 1970 gmove(&n3, reg1); 1971 regfree(&n3); 1972 1973 // load the array (reg) 1974 if(l->ullman <= r->ullman) { 1975 regalloc(reg, types[tptr], N); 1976 if(o & OPtrto) 1977 cgen(l, reg); 1978 else 1979 agen(l, reg); 1980 } 1981 1982 // check bounds 1983 if(!debug['B']) { 1984 if(o & ODynam) { 1985 n2 = *reg; 1986 n2.op = OINDREG; 1987 n2.type = types[tptr]; 1988 n2.xoffset = Array_nel; 1989 } else { 1990 if(l->type->width >= unmappedzero && l->op == OIND) { 1991 // cannot rely on page protections to 1992 // catch array ptr == 0, so dereference. 1993 n2 = *reg; 1994 n2.op = OINDREG; 1995 n2.type = types[TUINTPTR]; 1996 n2.xoffset = 0; 1997 regalloc(&n3, n2.type, N); 1998 gins(AMOVW, &n2, &n3); 1999 regfree(&n3); 2000 } 2001 nodconst(&n2, types[TUINT32], l->type->bound); 2002 if(o & OPtrto) 2003 nodconst(&n2, types[TUINT32], l->type->type->bound); 2004 } 2005 regalloc(&n3, n2.type, N); 2006 cgen(&n2, &n3); 2007 gcmp(optoas(OCMP, types[TUINT32]), reg1, &n3); 2008 regfree(&n3); 2009 p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1); 2010 if(p2) 2011 patch(p2, pc); 2012 ginscall(panicindex, 0); 2013 patch(p1, pc); 2014 } 2015 2016 if(o & ODynam) { 2017 n2 = *reg; 2018 n2.op = OINDREG; 2019 n2.type = types[tptr]; 2020 n2.xoffset = Array_array; 2021 gmove(&n2, reg); 2022 } 2023 2024 switch(*w) { 2025 case 1: 2026 gins(AADD, reg1, reg); 2027 break; 2028 case 2: 2029 gshift(AADD, reg1, SHIFT_LL, 1, reg); 2030 break; 2031 case 4: 2032 gshift(AADD, reg1, SHIFT_LL, 2, reg); 2033 break; 2034 case 8: 2035 gshift(AADD, reg1, SHIFT_LL, 3, reg); 2036 break; 2037 } 2038 2039 naddr(reg1, a, 1); 2040 a->type = D_OREG; 2041 a->reg = reg->val.u.reg; 2042 a->offset = 0; 2043 goto yes; 2044 2045 oindex_const: 2046 // index is constant 2047 // can check statically and 2048 // can multiply by width statically 2049 2050 regalloc(reg, types[tptr], N); 2051 if(o & OPtrto) 2052 cgen(l, reg); 2053 else 2054 agen(l, reg); 2055 2056 v = mpgetfix(r->val.u.xval); 2057 if(o & ODynam) { 2058 2059 if(!debug['B'] && !n->bounded) { 2060 n1 = *reg; 2061 n1.op = OINDREG; 2062 n1.type = types[tptr]; 2063 n1.xoffset = Array_nel; 2064 nodconst(&n2, types[TUINT32], v); 2065 regalloc(&n3, types[TUINT32], N); 2066 cgen(&n2, &n3); 2067 regalloc(&n4, n1.type, N); 2068 cgen(&n1, &n4); 2069 gcmp(optoas(OCMP, types[TUINT32]), &n4, &n3); 2070 regfree(&n4); 2071 regfree(&n3); 2072 p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1); 2073 ginscall(panicindex, 0); 2074 patch(p1, pc); 2075 } 2076 2077 n1 = *reg; 2078 n1.op = OINDREG; 2079 n1.type = types[tptr]; 2080 n1.xoffset = Array_array; 2081 gmove(&n1, reg); 2082 } 2083 2084 n2 = *reg; 2085 n2.op = OINDREG; 2086 n2.xoffset = v * (*w); 2087 a->type = D_NONE; 2088 a->name = D_NONE; 2089 naddr(&n2, a, 1); 2090 goto yes; 2091 2092 yes: 2093 return 1; 2094 2095 no: 2096 sudoclean(); 2097 return 0; 2098 }