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