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