github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/8c/cgen.c (about) 1 // Inferno utils/8c/cgen.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8c/cgen.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 "gc.h" 32 33 /* ,x/^(print|prtree)\(/i/\/\/ */ 34 35 void 36 cgen(Node *n, Node *nn) 37 { 38 Node *l, *r, *t; 39 Prog *p1; 40 Node nod, nod1, nod2, nod3, nod4; 41 int o, hardleft; 42 int32 v, curs; 43 vlong c; 44 45 if(debug['g']) { 46 prtree(nn, "cgen lhs"); 47 prtree(n, "cgen"); 48 } 49 if(n == Z || n->type == T) 50 return; 51 if(typesuv[n->type->etype]) { 52 sugen(n, nn, n->type->width); 53 return; 54 } 55 l = n->left; 56 r = n->right; 57 o = n->op; 58 59 if(n->op == OEXREG || (nn != Z && nn->op == OEXREG)) { 60 gmove(n, nn); 61 return; 62 } 63 64 if(n->addable >= INDEXED) { 65 if(nn == Z) { 66 switch(o) { 67 default: 68 nullwarn(Z, Z); 69 break; 70 case OINDEX: 71 nullwarn(l, r); 72 break; 73 } 74 return; 75 } 76 gmove(n, nn); 77 return; 78 } 79 curs = cursafe; 80 81 if(l->complex >= FNX) 82 if(r != Z && r->complex >= FNX) 83 switch(o) { 84 default: 85 if(cond(o) && typesuv[l->type->etype]) 86 break; 87 88 regret(&nod, r); 89 cgen(r, &nod); 90 91 regsalloc(&nod1, r); 92 gmove(&nod, &nod1); 93 94 regfree(&nod); 95 nod = *n; 96 nod.right = &nod1; 97 98 cgen(&nod, nn); 99 return; 100 101 case OFUNC: 102 case OCOMMA: 103 case OANDAND: 104 case OOROR: 105 case OCOND: 106 case ODOT: 107 break; 108 } 109 110 hardleft = l->addable < INDEXED || l->complex >= FNX; 111 switch(o) { 112 default: 113 diag(n, "unknown op in cgen: %O", o); 114 break; 115 116 case ONEG: 117 case OCOM: 118 if(nn == Z) { 119 nullwarn(l, Z); 120 break; 121 } 122 regalloc(&nod, l, nn); 123 cgen(l, &nod); 124 gopcode(o, n->type, Z, &nod); 125 gmove(&nod, nn); 126 regfree(&nod); 127 break; 128 129 case OAS: 130 if(typefd[n->type->etype]) { 131 cgen(r, &fregnode0); 132 if(nn != Z) 133 gins(AFMOVD, &fregnode0, &fregnode0); 134 if(l->addable < INDEXED) { 135 reglcgen(&nod, l, Z); 136 gmove(&fregnode0, &nod); 137 regfree(&nod); 138 } else 139 gmove(&fregnode0, l); 140 if(nn != Z) 141 gmove(&fregnode0, nn); 142 return; 143 } 144 if(l->op == OBIT) 145 goto bitas; 146 if(!hardleft) { 147 if(nn != Z || r->addable < INDEXED) { 148 if(r->complex >= FNX && nn == Z) 149 regret(&nod, r); 150 else 151 regalloc(&nod, r, nn); 152 cgen(r, &nod); 153 gmove(&nod, l); 154 if(nn != Z) 155 gmove(&nod, nn); 156 regfree(&nod); 157 } else 158 gmove(r, l); 159 break; 160 } 161 if(l->complex >= r->complex) { 162 if(l->op == OINDEX && r->op == OCONST) { 163 gmove(r, l); 164 break; 165 } 166 reglcgen(&nod1, l, Z); 167 if(r->addable >= INDEXED) { 168 gmove(r, &nod1); 169 if(nn != Z) 170 gmove(r, nn); 171 regfree(&nod1); 172 break; 173 } 174 regalloc(&nod, r, nn); 175 cgen(r, &nod); 176 } else { 177 regalloc(&nod, r, nn); 178 cgen(r, &nod); 179 reglcgen(&nod1, l, Z); 180 } 181 gmove(&nod, &nod1); 182 regfree(&nod); 183 regfree(&nod1); 184 break; 185 186 bitas: 187 n = l->left; 188 regalloc(&nod, r, nn); 189 if(l->complex >= r->complex) { 190 reglcgen(&nod1, n, Z); 191 cgen(r, &nod); 192 } else { 193 cgen(r, &nod); 194 reglcgen(&nod1, n, Z); 195 } 196 regalloc(&nod2, n, Z); 197 gmove(&nod1, &nod2); 198 bitstore(l, &nod, &nod1, &nod2, nn); 199 break; 200 201 case OBIT: 202 if(nn == Z) { 203 nullwarn(l, Z); 204 break; 205 } 206 bitload(n, &nod, Z, Z, nn); 207 gmove(&nod, nn); 208 regfree(&nod); 209 break; 210 211 case OLSHR: 212 case OASHL: 213 case OASHR: 214 if(nn == Z) { 215 nullwarn(l, r); 216 break; 217 } 218 if(r->op == OCONST) { 219 if(r->vconst == 0) { 220 cgen(l, nn); 221 break; 222 } 223 regalloc(&nod, l, nn); 224 cgen(l, &nod); 225 if(o == OASHL && r->vconst == 1) 226 gopcode(OADD, n->type, &nod, &nod); 227 else 228 gopcode(o, n->type, r, &nod); 229 gmove(&nod, nn); 230 regfree(&nod); 231 break; 232 } 233 234 /* 235 * get nod to be D_CX 236 */ 237 if(nodreg(&nod, nn, D_CX)) { 238 regsalloc(&nod1, n); 239 gmove(&nod, &nod1); 240 cgen(n, &nod); /* probably a bug */ 241 gmove(&nod, nn); 242 gmove(&nod1, &nod); 243 break; 244 } 245 reg[D_CX]++; 246 if(nn->op == OREGISTER && nn->reg == D_CX) 247 regalloc(&nod1, l, Z); 248 else 249 regalloc(&nod1, l, nn); 250 if(r->complex >= l->complex) { 251 cgen(r, &nod); 252 cgen(l, &nod1); 253 } else { 254 cgen(l, &nod1); 255 cgen(r, &nod); 256 } 257 gopcode(o, n->type, &nod, &nod1); 258 gmove(&nod1, nn); 259 regfree(&nod); 260 regfree(&nod1); 261 break; 262 263 case OADD: 264 case OSUB: 265 case OOR: 266 case OXOR: 267 case OAND: 268 if(nn == Z) { 269 nullwarn(l, r); 270 break; 271 } 272 if(typefd[n->type->etype]) 273 goto fop; 274 if(r->op == OCONST) { 275 if(r->vconst == 0 && o != OAND) { 276 cgen(l, nn); 277 break; 278 } 279 } 280 if(n->op == OOR && l->op == OASHL && r->op == OLSHR 281 && l->right->op == OCONST && r->right->op == OCONST 282 && l->left->op == ONAME && r->left->op == ONAME 283 && l->left->sym == r->left->sym 284 && l->right->vconst + r->right->vconst == 8 * l->left->type->width) { 285 regalloc(&nod, l->left, nn); 286 cgen(l->left, &nod); 287 gopcode(OROTL, n->type, l->right, &nod); 288 gmove(&nod, nn); 289 regfree(&nod); 290 break; 291 } 292 if(n->op == OADD && l->op == OASHL && l->right->op == OCONST 293 && (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) { 294 c = l->right->vconst; 295 if(c > 0 && c <= 3) { 296 if(l->left->complex >= r->complex) { 297 regalloc(&nod, l->left, nn); 298 cgen(l->left, &nod); 299 if(r->addable < INDEXED) { 300 regalloc(&nod1, r, Z); 301 cgen(r, &nod1); 302 genmuladd(&nod, &nod, 1 << c, &nod1); 303 regfree(&nod1); 304 } 305 else 306 genmuladd(&nod, &nod, 1 << c, r); 307 } 308 else { 309 regalloc(&nod, r, nn); 310 cgen(r, &nod); 311 regalloc(&nod1, l->left, Z); 312 cgen(l->left, &nod1); 313 genmuladd(&nod, &nod1, 1 << c, &nod); 314 regfree(&nod1); 315 } 316 gmove(&nod, nn); 317 regfree(&nod); 318 break; 319 } 320 } 321 if(r->addable >= INDEXED) { 322 regalloc(&nod, l, nn); 323 cgen(l, &nod); 324 gopcode(o, n->type, r, &nod); 325 gmove(&nod, nn); 326 regfree(&nod); 327 break; 328 } 329 if(l->complex >= r->complex) { 330 regalloc(&nod, l, nn); 331 cgen(l, &nod); 332 regalloc(&nod1, r, Z); 333 cgen(r, &nod1); 334 gopcode(o, n->type, &nod1, &nod); 335 } else { 336 regalloc(&nod1, r, nn); 337 cgen(r, &nod1); 338 regalloc(&nod, l, Z); 339 cgen(l, &nod); 340 gopcode(o, n->type, &nod1, &nod); 341 } 342 gmove(&nod, nn); 343 regfree(&nod); 344 regfree(&nod1); 345 break; 346 347 case OLMOD: 348 case OMOD: 349 case OLMUL: 350 case OLDIV: 351 case OMUL: 352 case ODIV: 353 if(nn == Z) { 354 nullwarn(l, r); 355 break; 356 } 357 if(typefd[n->type->etype]) 358 goto fop; 359 if(r->op == OCONST) { 360 SET(v); 361 switch(o) { 362 case ODIV: 363 case OMOD: 364 c = r->vconst; 365 if(c < 0) 366 c = -c; 367 v = xlog2(c); 368 if(v < 0) 369 break; 370 /* fall thru */ 371 case OMUL: 372 case OLMUL: 373 regalloc(&nod, l, nn); 374 cgen(l, &nod); 375 switch(o) { 376 case OMUL: 377 case OLMUL: 378 mulgen(n->type, r, &nod); 379 break; 380 case ODIV: 381 sdiv2(r->vconst, v, l, &nod); 382 break; 383 case OMOD: 384 smod2(r->vconst, v, l, &nod); 385 break; 386 } 387 gmove(&nod, nn); 388 regfree(&nod); 389 goto done; 390 case OLDIV: 391 c = r->vconst; 392 if((c & 0x80000000) == 0) 393 break; 394 regalloc(&nod1, l, Z); 395 cgen(l, &nod1); 396 regalloc(&nod, l, nn); 397 zeroregm(&nod); 398 gins(ACMPL, &nod1, nodconst(c)); 399 gins(ASBBL, nodconst(-1), &nod); 400 regfree(&nod1); 401 gmove(&nod, nn); 402 regfree(&nod); 403 goto done; 404 } 405 } 406 407 if(o == OMUL) { 408 if(l->addable >= INDEXED) { 409 t = l; 410 l = r; 411 r = t; 412 } 413 /* should favour AX */ 414 regalloc(&nod, l, nn); 415 cgen(l, &nod); 416 if(r->addable < INDEXED) { 417 regalloc(&nod1, r, Z); 418 cgen(r, &nod1); 419 gopcode(OMUL, n->type, &nod1, &nod); 420 regfree(&nod1); 421 }else 422 gopcode(OMUL, n->type, r, &nod); /* addressible */ 423 gmove(&nod, nn); 424 regfree(&nod); 425 break; 426 } 427 428 /* 429 * get nod to be D_AX 430 * get nod1 to be D_DX 431 */ 432 if(nodreg(&nod, nn, D_AX)) { 433 regsalloc(&nod2, n); 434 gmove(&nod, &nod2); 435 v = reg[D_AX]; 436 reg[D_AX] = 0; 437 438 if(isreg(l, D_AX)) { 439 nod3 = *n; 440 nod3.left = &nod2; 441 cgen(&nod3, nn); 442 } else 443 if(isreg(r, D_AX)) { 444 nod3 = *n; 445 nod3.right = &nod2; 446 cgen(&nod3, nn); 447 } else 448 cgen(n, nn); 449 450 gmove(&nod2, &nod); 451 reg[D_AX] = v; 452 break; 453 } 454 if(nodreg(&nod1, nn, D_DX)) { 455 regsalloc(&nod2, n); 456 gmove(&nod1, &nod2); 457 v = reg[D_DX]; 458 reg[D_DX] = 0; 459 460 if(isreg(l, D_DX)) { 461 nod3 = *n; 462 nod3.left = &nod2; 463 cgen(&nod3, nn); 464 } else 465 if(isreg(r, D_DX)) { 466 nod3 = *n; 467 nod3.right = &nod2; 468 cgen(&nod3, nn); 469 } else 470 cgen(n, nn); 471 472 gmove(&nod2, &nod1); 473 reg[D_DX] = v; 474 break; 475 } 476 reg[D_AX]++; 477 478 if(r->op == OCONST && (o == ODIV || o == OLDIV)) { 479 reg[D_DX]++; 480 if(l->addable < INDEXED) { 481 regalloc(&nod2, l, Z); 482 cgen(l, &nod2); 483 l = &nod2; 484 } 485 if(o == ODIV) 486 sdivgen(l, r, &nod, &nod1); 487 else 488 udivgen(l, r, &nod, &nod1); 489 gmove(&nod1, nn); 490 if(l == &nod2) 491 regfree(l); 492 goto freeaxdx; 493 } 494 495 if(l->complex >= r->complex) { 496 cgen(l, &nod); 497 reg[D_DX]++; 498 if(o == ODIV || o == OMOD) 499 gins(ACDQ, Z, Z); 500 if(o == OLDIV || o == OLMOD) 501 zeroregm(&nod1); 502 if(r->addable < INDEXED || r->op == OCONST) { 503 regsalloc(&nod3, r); 504 cgen(r, &nod3); 505 gopcode(o, n->type, &nod3, Z); 506 } else 507 gopcode(o, n->type, r, Z); 508 } else { 509 regsalloc(&nod3, r); 510 cgen(r, &nod3); 511 cgen(l, &nod); 512 reg[D_DX]++; 513 if(o == ODIV || o == OMOD) 514 gins(ACDQ, Z, Z); 515 if(o == OLDIV || o == OLMOD) 516 zeroregm(&nod1); 517 gopcode(o, n->type, &nod3, Z); 518 } 519 if(o == OMOD || o == OLMOD) 520 gmove(&nod1, nn); 521 else 522 gmove(&nod, nn); 523 freeaxdx: 524 regfree(&nod); 525 regfree(&nod1); 526 break; 527 528 case OASLSHR: 529 case OASASHL: 530 case OASASHR: 531 if(r->op == OCONST) 532 goto asand; 533 if(l->op == OBIT) 534 goto asbitop; 535 if(typefd[n->type->etype]) 536 goto asfop; 537 538 /* 539 * get nod to be D_CX 540 */ 541 if(nodreg(&nod, nn, D_CX)) { 542 regsalloc(&nod1, n); 543 gmove(&nod, &nod1); 544 cgen(n, &nod); 545 if(nn != Z) 546 gmove(&nod, nn); 547 gmove(&nod1, &nod); 548 break; 549 } 550 reg[D_CX]++; 551 552 if(r->complex >= l->complex) { 553 cgen(r, &nod); 554 if(hardleft) 555 reglcgen(&nod1, l, Z); 556 else 557 nod1 = *l; 558 } else { 559 if(hardleft) 560 reglcgen(&nod1, l, Z); 561 else 562 nod1 = *l; 563 cgen(r, &nod); 564 } 565 566 gopcode(o, l->type, &nod, &nod1); 567 regfree(&nod); 568 if(nn != Z) 569 gmove(&nod1, nn); 570 if(hardleft) 571 regfree(&nod1); 572 break; 573 574 case OASAND: 575 case OASADD: 576 case OASSUB: 577 case OASXOR: 578 case OASOR: 579 asand: 580 if(l->op == OBIT) 581 goto asbitop; 582 if(typefd[n->type->etype]||typefd[r->type->etype]) 583 goto asfop; 584 if(l->complex >= r->complex) { 585 if(hardleft) 586 reglcgen(&nod, l, Z); 587 else 588 nod = *l; 589 if(r->op != OCONST) { 590 regalloc(&nod1, r, nn); 591 cgen(r, &nod1); 592 gopcode(o, l->type, &nod1, &nod); 593 regfree(&nod1); 594 } else 595 gopcode(o, l->type, r, &nod); 596 } else { 597 regalloc(&nod1, r, nn); 598 cgen(r, &nod1); 599 if(hardleft) 600 reglcgen(&nod, l, Z); 601 else 602 nod = *l; 603 gopcode(o, l->type, &nod1, &nod); 604 regfree(&nod1); 605 } 606 if(nn != Z) 607 gmove(&nod, nn); 608 if(hardleft) 609 regfree(&nod); 610 break; 611 612 case OASLMUL: 613 case OASLDIV: 614 case OASLMOD: 615 case OASMUL: 616 case OASDIV: 617 case OASMOD: 618 if(l->op == OBIT) 619 goto asbitop; 620 if(typefd[n->type->etype]||typefd[r->type->etype]) 621 goto asfop; 622 if(r->op == OCONST) { 623 SET(v); 624 switch(o) { 625 case OASDIV: 626 case OASMOD: 627 c = r->vconst; 628 if(c < 0) 629 c = -c; 630 v = xlog2(c); 631 if(v < 0) 632 break; 633 /* fall thru */ 634 case OASMUL: 635 case OASLMUL: 636 if(hardleft) 637 reglcgen(&nod2, l, Z); 638 else 639 nod2 = *l; 640 regalloc(&nod, l, nn); 641 cgen(&nod2, &nod); 642 switch(o) { 643 case OASMUL: 644 case OASLMUL: 645 mulgen(n->type, r, &nod); 646 break; 647 case OASDIV: 648 sdiv2(r->vconst, v, l, &nod); 649 break; 650 case OASMOD: 651 smod2(r->vconst, v, l, &nod); 652 break; 653 } 654 havev: 655 gmove(&nod, &nod2); 656 if(nn != Z) 657 gmove(&nod, nn); 658 if(hardleft) 659 regfree(&nod2); 660 regfree(&nod); 661 goto done; 662 case OASLDIV: 663 c = r->vconst; 664 if((c & 0x80000000) == 0) 665 break; 666 if(hardleft) 667 reglcgen(&nod2, l, Z); 668 else 669 nod2 = *l; 670 regalloc(&nod1, l, nn); 671 cgen(&nod2, &nod1); 672 regalloc(&nod, l, nn); 673 zeroregm(&nod); 674 gins(ACMPL, &nod1, nodconst(c)); 675 gins(ASBBL, nodconst(-1), &nod); 676 regfree(&nod1); 677 goto havev; 678 } 679 } 680 681 if(o == OASMUL) { 682 /* should favour AX */ 683 regalloc(&nod, l, nn); 684 if(r->complex >= FNX) { 685 regalloc(&nod1, r, Z); 686 cgen(r, &nod1); 687 r = &nod1; 688 } 689 if(hardleft) 690 reglcgen(&nod2, l, Z); 691 else 692 nod2 = *l; 693 cgen(&nod2, &nod); 694 if(r->addable < INDEXED) { 695 if(r->complex < FNX) { 696 regalloc(&nod1, r, Z); 697 cgen(r, &nod1); 698 } 699 gopcode(OASMUL, n->type, &nod1, &nod); 700 regfree(&nod1); 701 } 702 else 703 gopcode(OASMUL, n->type, r, &nod); 704 if(r == &nod1) 705 regfree(r); 706 gmove(&nod, &nod2); 707 if(nn != Z) 708 gmove(&nod, nn); 709 regfree(&nod); 710 if(hardleft) 711 regfree(&nod2); 712 break; 713 } 714 715 /* 716 * get nod to be D_AX 717 * get nod1 to be D_DX 718 */ 719 if(nodreg(&nod, nn, D_AX)) { 720 regsalloc(&nod2, n); 721 gmove(&nod, &nod2); 722 v = reg[D_AX]; 723 reg[D_AX] = 0; 724 725 if(isreg(l, D_AX)) { 726 nod3 = *n; 727 nod3.left = &nod2; 728 cgen(&nod3, nn); 729 } else 730 if(isreg(r, D_AX)) { 731 nod3 = *n; 732 nod3.right = &nod2; 733 cgen(&nod3, nn); 734 } else 735 cgen(n, nn); 736 737 gmove(&nod2, &nod); 738 reg[D_AX] = v; 739 break; 740 } 741 if(nodreg(&nod1, nn, D_DX)) { 742 regsalloc(&nod2, n); 743 gmove(&nod1, &nod2); 744 v = reg[D_DX]; 745 reg[D_DX] = 0; 746 747 if(isreg(l, D_DX)) { 748 nod3 = *n; 749 nod3.left = &nod2; 750 cgen(&nod3, nn); 751 } else 752 if(isreg(r, D_DX)) { 753 nod3 = *n; 754 nod3.right = &nod2; 755 cgen(&nod3, nn); 756 } else 757 cgen(n, nn); 758 759 gmove(&nod2, &nod1); 760 reg[D_DX] = v; 761 break; 762 } 763 reg[D_AX]++; 764 reg[D_DX]++; 765 766 if(l->complex >= r->complex) { 767 if(hardleft) 768 reglcgen(&nod2, l, Z); 769 else 770 nod2 = *l; 771 cgen(&nod2, &nod); 772 if(r->op == OCONST) { 773 switch(o) { 774 case OASDIV: 775 sdivgen(&nod2, r, &nod, &nod1); 776 goto divdone; 777 case OASLDIV: 778 udivgen(&nod2, r, &nod, &nod1); 779 divdone: 780 gmove(&nod1, &nod2); 781 if(nn != Z) 782 gmove(&nod1, nn); 783 goto freelxaxdx; 784 } 785 } 786 if(o == OASDIV || o == OASMOD) 787 gins(ACDQ, Z, Z); 788 if(o == OASLDIV || o == OASLMOD) 789 zeroregm(&nod1); 790 if(r->addable < INDEXED || r->op == OCONST || 791 !typeil[r->type->etype]) { 792 regalloc(&nod3, r, Z); 793 cgen(r, &nod3); 794 gopcode(o, l->type, &nod3, Z); 795 regfree(&nod3); 796 } else 797 gopcode(o, n->type, r, Z); 798 } else { 799 regalloc(&nod3, r, Z); 800 cgen(r, &nod3); 801 if(hardleft) 802 reglcgen(&nod2, l, Z); 803 else 804 nod2 = *l; 805 cgen(&nod2, &nod); 806 if(o == OASDIV || o == OASMOD) 807 gins(ACDQ, Z, Z); 808 if(o == OASLDIV || o == OASLMOD) 809 zeroregm(&nod1); 810 gopcode(o, l->type, &nod3, Z); 811 regfree(&nod3); 812 } 813 if(o == OASMOD || o == OASLMOD) { 814 gmove(&nod1, &nod2); 815 if(nn != Z) 816 gmove(&nod1, nn); 817 } else { 818 gmove(&nod, &nod2); 819 if(nn != Z) 820 gmove(&nod, nn); 821 } 822 freelxaxdx: 823 if(hardleft) 824 regfree(&nod2); 825 regfree(&nod); 826 regfree(&nod1); 827 break; 828 829 fop: 830 if(l->complex >= r->complex) { 831 cgen(l, &fregnode0); 832 if(r->addable < INDEXED) { 833 cgen(r, &fregnode0); 834 fgopcode(o, &fregnode0, &fregnode1, 1, 0); 835 } else 836 fgopcode(o, r, &fregnode0, 0, 0); 837 } else { 838 cgen(r, &fregnode0); 839 if(l->addable < INDEXED) { 840 cgen(l, &fregnode0); 841 fgopcode(o, &fregnode0, &fregnode1, 1, 1); 842 } else 843 fgopcode(o, l, &fregnode0, 0, 1); 844 } 845 gmove(&fregnode0, nn); 846 break; 847 848 asfop: 849 if(l->complex >= r->complex) { 850 if(hardleft) 851 reglcgen(&nod, l, Z); 852 else 853 nod = *l; 854 cgen(r, &fregnode0); 855 } else { 856 cgen(r, &fregnode0); 857 if(hardleft) 858 reglcgen(&nod, l, Z); 859 else 860 nod = *l; 861 } 862 if(!typefd[l->type->etype]) { 863 gmove(&nod, &fregnode0); 864 fgopcode(o, &fregnode0, &fregnode1, 1, 1); 865 } else 866 fgopcode(o, &nod, &fregnode0, 0, 1); 867 if(nn != Z) 868 gins(AFMOVD, &fregnode0, &fregnode0); 869 gmove(&fregnode0, &nod); 870 if(nn != Z) 871 gmove(&fregnode0, nn); 872 if(hardleft) 873 regfree(&nod); 874 break; 875 876 asbitop: 877 regalloc(&nod4, n, nn); 878 if(l->complex >= r->complex) { 879 bitload(l, &nod, &nod1, &nod2, &nod4); 880 regalloc(&nod3, r, Z); 881 cgen(r, &nod3); 882 } else { 883 regalloc(&nod3, r, Z); 884 cgen(r, &nod3); 885 bitload(l, &nod, &nod1, &nod2, &nod4); 886 } 887 gmove(&nod, &nod4); 888 889 if(typefd[nod3.type->etype]) 890 fgopcode(o, &fregnode0, &fregnode1, 1, 1); 891 else { 892 Node onod; 893 894 /* incredible grot ... */ 895 onod = nod3; 896 onod.op = o; 897 onod.complex = 2; 898 onod.addable = 0; 899 onod.type = tfield; 900 onod.left = &nod4; 901 onod.right = &nod3; 902 cgen(&onod, Z); 903 } 904 regfree(&nod3); 905 gmove(&nod4, &nod); 906 regfree(&nod4); 907 bitstore(l, &nod, &nod1, &nod2, nn); 908 break; 909 910 case OADDR: 911 if(nn == Z) { 912 nullwarn(l, Z); 913 break; 914 } 915 lcgen(l, nn); 916 break; 917 918 case OFUNC: 919 if(l->complex >= FNX) { 920 if(l->op != OIND) 921 diag(n, "bad function call"); 922 923 regret(&nod, l->left); 924 cgen(l->left, &nod); 925 regsalloc(&nod1, l->left); 926 gmove(&nod, &nod1); 927 regfree(&nod); 928 929 nod = *n; 930 nod.left = &nod2; 931 nod2 = *l; 932 nod2.left = &nod1; 933 nod2.complex = 1; 934 cgen(&nod, nn); 935 936 return; 937 } 938 gargs(r, &nod, &nod1); 939 if(l->addable < INDEXED) { 940 reglcgen(&nod, l, nn); 941 nod.op = OREGISTER; 942 gopcode(OFUNC, n->type, Z, &nod); 943 regfree(&nod); 944 } else 945 gopcode(OFUNC, n->type, Z, l); 946 if(REGARG >= 0 && reg[REGARG]) 947 reg[REGARG]--; 948 if(nn != Z) { 949 regret(&nod, n); 950 gmove(&nod, nn); 951 regfree(&nod); 952 } else 953 if(typefd[n->type->etype]) 954 gins(AFMOVDP, &fregnode0, &fregnode0); 955 break; 956 957 case OIND: 958 if(nn == Z) { 959 nullwarn(l, Z); 960 break; 961 } 962 regialloc(&nod, n, nn); 963 r = l; 964 while(r->op == OADD) 965 r = r->right; 966 if(sconst(r)) { 967 v = r->vconst; 968 r->vconst = 0; 969 cgen(l, &nod); 970 nod.xoffset += v; 971 r->vconst = v; 972 } else 973 cgen(l, &nod); 974 regind(&nod, n); 975 gmove(&nod, nn); 976 regfree(&nod); 977 break; 978 979 case OEQ: 980 case ONE: 981 case OLE: 982 case OLT: 983 case OGE: 984 case OGT: 985 case OLO: 986 case OLS: 987 case OHI: 988 case OHS: 989 if(nn == Z) { 990 nullwarn(l, r); 991 break; 992 } 993 boolgen(n, 1, nn); 994 break; 995 996 case OANDAND: 997 case OOROR: 998 boolgen(n, 1, nn); 999 if(nn == Z) 1000 patch(p, pc); 1001 break; 1002 1003 case ONOT: 1004 if(nn == Z) { 1005 nullwarn(l, Z); 1006 break; 1007 } 1008 boolgen(n, 1, nn); 1009 break; 1010 1011 case OCOMMA: 1012 cgen(l, Z); 1013 cgen(r, nn); 1014 break; 1015 1016 case OCAST: 1017 if(nn == Z) { 1018 nullwarn(l, Z); 1019 break; 1020 } 1021 /* 1022 * convert from types l->n->nn 1023 */ 1024 if(nocast(l->type, n->type) && nocast(n->type, nn->type)) { 1025 /* both null, gen l->nn */ 1026 cgen(l, nn); 1027 break; 1028 } 1029 if(typev[l->type->etype]) { 1030 cgen64(n, nn); 1031 break; 1032 } 1033 regalloc(&nod, l, nn); 1034 cgen(l, &nod); 1035 regalloc(&nod1, n, &nod); 1036 gmove(&nod, &nod1); 1037 gmove(&nod1, nn); 1038 regfree(&nod1); 1039 regfree(&nod); 1040 break; 1041 1042 case ODOT: 1043 sugen(l, nodrat, l->type->width); 1044 if(nn == Z) 1045 break; 1046 warn(n, "non-interruptable temporary"); 1047 nod = *nodrat; 1048 if(!r || r->op != OCONST) { 1049 diag(n, "DOT and no offset"); 1050 break; 1051 } 1052 nod.xoffset += (int32)r->vconst; 1053 nod.type = n->type; 1054 cgen(&nod, nn); 1055 break; 1056 1057 case OCOND: 1058 bcgen(l, 1); 1059 p1 = p; 1060 cgen(r->left, nn); 1061 gbranch(OGOTO); 1062 patch(p1, pc); 1063 p1 = p; 1064 cgen(r->right, nn); 1065 patch(p1, pc); 1066 break; 1067 1068 case OPOSTINC: 1069 case OPOSTDEC: 1070 v = 1; 1071 if(l->type->etype == TIND) 1072 v = l->type->link->width; 1073 if(o == OPOSTDEC) 1074 v = -v; 1075 if(l->op == OBIT) 1076 goto bitinc; 1077 if(nn == Z) 1078 goto pre; 1079 1080 if(hardleft) 1081 reglcgen(&nod, l, Z); 1082 else 1083 nod = *l; 1084 1085 if(typefd[n->type->etype]) 1086 goto fltinc; 1087 gmove(&nod, nn); 1088 gopcode(OADD, n->type, nodconst(v), &nod); 1089 if(hardleft) 1090 regfree(&nod); 1091 break; 1092 1093 case OPREINC: 1094 case OPREDEC: 1095 v = 1; 1096 if(l->type->etype == TIND) 1097 v = l->type->link->width; 1098 if(o == OPREDEC) 1099 v = -v; 1100 if(l->op == OBIT) 1101 goto bitinc; 1102 1103 pre: 1104 if(hardleft) 1105 reglcgen(&nod, l, Z); 1106 else 1107 nod = *l; 1108 if(typefd[n->type->etype]) 1109 goto fltinc; 1110 gopcode(OADD, n->type, nodconst(v), &nod); 1111 if(nn != Z) 1112 gmove(&nod, nn); 1113 if(hardleft) 1114 regfree(&nod); 1115 break; 1116 1117 fltinc: 1118 gmove(&nod, &fregnode0); 1119 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) 1120 gins(AFMOVD, &fregnode0, &fregnode0); 1121 gins(AFLD1, Z, Z); 1122 if(v < 0) 1123 fgopcode(OSUB, &fregnode0, &fregnode1, 1, 0); 1124 else 1125 fgopcode(OADD, &fregnode0, &fregnode1, 1, 0); 1126 if(nn != Z && (o == OPREINC || o == OPREDEC)) 1127 gins(AFMOVD, &fregnode0, &fregnode0); 1128 gmove(&fregnode0, &nod); 1129 if(hardleft) 1130 regfree(&nod); 1131 break; 1132 1133 bitinc: 1134 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { 1135 bitload(l, &nod, &nod1, &nod2, Z); 1136 gmove(&nod, nn); 1137 gopcode(OADD, tfield, nodconst(v), &nod); 1138 bitstore(l, &nod, &nod1, &nod2, Z); 1139 break; 1140 } 1141 bitload(l, &nod, &nod1, &nod2, nn); 1142 gopcode(OADD, tfield, nodconst(v), &nod); 1143 bitstore(l, &nod, &nod1, &nod2, nn); 1144 break; 1145 } 1146 done: 1147 cursafe = curs; 1148 } 1149 1150 void 1151 reglcgen(Node *t, Node *n, Node *nn) 1152 { 1153 Node *r; 1154 int32 v; 1155 1156 regialloc(t, n, nn); 1157 if(n->op == OIND) { 1158 r = n->left; 1159 while(r->op == OADD) 1160 r = r->right; 1161 if(sconst(r)) { 1162 v = r->vconst; 1163 r->vconst = 0; 1164 lcgen(n, t); 1165 t->xoffset += v; 1166 r->vconst = v; 1167 regind(t, n); 1168 return; 1169 } 1170 } 1171 lcgen(n, t); 1172 regind(t, n); 1173 } 1174 1175 void 1176 lcgen(Node *n, Node *nn) 1177 { 1178 Prog *p1; 1179 Node nod; 1180 1181 if(debug['g']) { 1182 prtree(nn, "lcgen lhs"); 1183 prtree(n, "lcgen"); 1184 } 1185 if(n == Z || n->type == T) 1186 return; 1187 if(nn == Z) { 1188 nn = &nod; 1189 regalloc(&nod, n, Z); 1190 } 1191 switch(n->op) { 1192 default: 1193 if(n->addable < INDEXED) { 1194 diag(n, "unknown op in lcgen: %O", n->op); 1195 break; 1196 } 1197 gopcode(OADDR, n->type, n, nn); 1198 break; 1199 1200 case OCOMMA: 1201 cgen(n->left, n->left); 1202 lcgen(n->right, nn); 1203 break; 1204 1205 case OIND: 1206 cgen(n->left, nn); 1207 break; 1208 1209 case OCOND: 1210 bcgen(n->left, 1); 1211 p1 = p; 1212 lcgen(n->right->left, nn); 1213 gbranch(OGOTO); 1214 patch(p1, pc); 1215 p1 = p; 1216 lcgen(n->right->right, nn); 1217 patch(p1, pc); 1218 break; 1219 } 1220 } 1221 1222 void 1223 bcgen(Node *n, int true) 1224 { 1225 1226 if(n->type == T) 1227 gbranch(OGOTO); 1228 else 1229 boolgen(n, true, Z); 1230 } 1231 1232 void 1233 boolgen(Node *n, int true, Node *nn) 1234 { 1235 int o; 1236 Prog *p1, *p2, *p3; 1237 Node *l, *r, nod, nod1; 1238 int32 curs; 1239 1240 if(debug['g']) { 1241 prtree(nn, "boolgen lhs"); 1242 prtree(n, "boolgen"); 1243 } 1244 curs = cursafe; 1245 l = n->left; 1246 r = n->right; 1247 switch(n->op) { 1248 1249 default: 1250 if(typev[n->type->etype]) { 1251 testv(n, true); 1252 goto com; 1253 } 1254 o = ONE; 1255 if(true) 1256 o = OEQ; 1257 if(typefd[n->type->etype]) { 1258 if(n->addable < INDEXED) { 1259 cgen(n, &fregnode0); 1260 gins(AFLDZ, Z, Z); 1261 fgopcode(o, &fregnode0, &fregnode1, 1, 1); 1262 } else { 1263 gins(AFLDZ, Z, Z); 1264 fgopcode(o, n, &fregnode0, 0, 1); 1265 } 1266 goto com; 1267 } 1268 /* bad, 13 is address of external that becomes constant */ 1269 if(n->addable >= INDEXED && n->addable != 13) { 1270 gopcode(o, n->type, n, nodconst(0)); 1271 goto com; 1272 } 1273 regalloc(&nod, n, nn); 1274 cgen(n, &nod); 1275 gopcode(o, n->type, &nod, nodconst(0)); 1276 regfree(&nod); 1277 goto com; 1278 1279 case OCONST: 1280 o = vconst(n); 1281 if(!true) 1282 o = !o; 1283 gbranch(OGOTO); 1284 if(o) { 1285 p1 = p; 1286 gbranch(OGOTO); 1287 patch(p1, pc); 1288 } 1289 goto com; 1290 1291 case OCOMMA: 1292 cgen(l, Z); 1293 boolgen(r, true, nn); 1294 break; 1295 1296 case ONOT: 1297 boolgen(l, !true, nn); 1298 break; 1299 1300 case OCOND: 1301 bcgen(l, 1); 1302 p1 = p; 1303 bcgen(r->left, true); 1304 p2 = p; 1305 gbranch(OGOTO); 1306 patch(p1, pc); 1307 p1 = p; 1308 bcgen(r->right, !true); 1309 patch(p2, pc); 1310 p2 = p; 1311 gbranch(OGOTO); 1312 patch(p1, pc); 1313 patch(p2, pc); 1314 goto com; 1315 1316 case OANDAND: 1317 if(!true) 1318 goto caseor; 1319 1320 caseand: 1321 bcgen(l, true); 1322 p1 = p; 1323 bcgen(r, !true); 1324 p2 = p; 1325 patch(p1, pc); 1326 gbranch(OGOTO); 1327 patch(p2, pc); 1328 goto com; 1329 1330 case OOROR: 1331 if(!true) 1332 goto caseand; 1333 1334 caseor: 1335 bcgen(l, !true); 1336 p1 = p; 1337 bcgen(r, !true); 1338 p2 = p; 1339 gbranch(OGOTO); 1340 patch(p1, pc); 1341 patch(p2, pc); 1342 goto com; 1343 1344 case OEQ: 1345 case ONE: 1346 case OLE: 1347 case OLT: 1348 case OGE: 1349 case OGT: 1350 case OHI: 1351 case OHS: 1352 case OLO: 1353 case OLS: 1354 o = n->op; 1355 if(typev[l->type->etype]) { 1356 if(!true) 1357 n->op = comrel[relindex(o)]; 1358 cgen64(n, Z); 1359 goto com; 1360 } 1361 if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) { 1362 // Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs. 1363 // Jump around instead. 1364 boolgen(n, 0, Z); 1365 p1 = p; 1366 gbranch(OGOTO); 1367 patch(p1, pc); 1368 goto com; 1369 } 1370 if(true) 1371 o = comrel[relindex(o)]; 1372 if(l->complex >= FNX && r->complex >= FNX) { 1373 regret(&nod, r); 1374 cgen(r, &nod); 1375 regsalloc(&nod1, r); 1376 gmove(&nod, &nod1); 1377 regfree(&nod); 1378 nod = *n; 1379 nod.right = &nod1; 1380 boolgen(&nod, true, nn); 1381 break; 1382 } 1383 if(typefd[l->type->etype]) { 1384 if(l->complex >= r->complex) { 1385 cgen(l, &fregnode0); 1386 if(r->addable < INDEXED) { 1387 cgen(r, &fregnode0); 1388 o = invrel[relindex(o)]; 1389 fgopcode(o, &fregnode0, &fregnode1, 1, 1); 1390 } else 1391 fgopcode(o, r, &fregnode0, 0, 1); 1392 } else { 1393 o = invrel[relindex(o)]; 1394 cgen(r, &fregnode0); 1395 if(l->addable < INDEXED) { 1396 cgen(l, &fregnode0); 1397 o = invrel[relindex(o)]; 1398 fgopcode(o, &fregnode0, &fregnode1, 1, 1); 1399 } else 1400 fgopcode(o, l, &fregnode0, 0, 1); 1401 } 1402 switch(o) { 1403 case OEQ: 1404 // Already emitted AJEQ; want AJEQ and AJPC. 1405 p1 = p; 1406 gbranch(OGOTO); 1407 p2 = p; 1408 patch(p1, pc); 1409 gins(AJPC, Z, Z); 1410 patch(p2, pc); 1411 break; 1412 1413 case ONE: 1414 // Already emitted AJNE; want AJNE or AJPS. 1415 p1 = p; 1416 gins(AJPS, Z, Z); 1417 p2 = p; 1418 gbranch(OGOTO); 1419 p3 = p; 1420 patch(p1, pc); 1421 patch(p2, pc); 1422 gbranch(OGOTO); 1423 patch(p3, pc); 1424 break; 1425 } 1426 goto com; 1427 } 1428 if(l->op == OCONST) { 1429 o = invrel[relindex(o)]; 1430 /* bad, 13 is address of external that becomes constant */ 1431 if(r->addable < INDEXED || r->addable == 13) { 1432 regalloc(&nod, r, nn); 1433 cgen(r, &nod); 1434 gopcode(o, l->type, &nod, l); 1435 regfree(&nod); 1436 } else 1437 gopcode(o, l->type, r, l); 1438 goto com; 1439 } 1440 if(l->complex >= r->complex) { 1441 regalloc(&nod, l, nn); 1442 cgen(l, &nod); 1443 if(r->addable < INDEXED) { 1444 regalloc(&nod1, r, Z); 1445 cgen(r, &nod1); 1446 gopcode(o, l->type, &nod, &nod1); 1447 regfree(&nod1); 1448 } else 1449 gopcode(o, l->type, &nod, r); 1450 regfree(&nod); 1451 goto com; 1452 } 1453 regalloc(&nod, r, nn); 1454 cgen(r, &nod); 1455 if(l->addable < INDEXED || l->addable == 13) { 1456 regalloc(&nod1, l, Z); 1457 cgen(l, &nod1); 1458 if(typechlp[l->type->etype]) 1459 gopcode(o, types[TINT], &nod1, &nod); 1460 else 1461 gopcode(o, l->type, &nod1, &nod); 1462 regfree(&nod1); 1463 } else 1464 gopcode(o, l->type, l, &nod); 1465 regfree(&nod); 1466 1467 com: 1468 if(nn != Z) { 1469 p1 = p; 1470 gmove(nodconst(1L), nn); 1471 gbranch(OGOTO); 1472 p2 = p; 1473 patch(p1, pc); 1474 gmove(nodconst(0L), nn); 1475 patch(p2, pc); 1476 } 1477 break; 1478 } 1479 cursafe = curs; 1480 } 1481 1482 void 1483 sugen(Node *n, Node *nn, int32 w) 1484 { 1485 Prog *p1; 1486 Node nod0, nod1, nod2, nod3, nod4, *h, *l, *r; 1487 Type *t; 1488 int c, v, x; 1489 1490 if(n == Z || n->type == T) 1491 return; 1492 if(debug['g']) { 1493 prtree(nn, "sugen lhs"); 1494 prtree(n, "sugen"); 1495 } 1496 if(nn == nodrat) 1497 if(w > nrathole) 1498 nrathole = w; 1499 switch(n->op) { 1500 case OIND: 1501 if(nn == Z) { 1502 nullwarn(n->left, Z); 1503 break; 1504 } 1505 1506 default: 1507 goto copy; 1508 1509 case OCONST: 1510 if(n->type && typev[n->type->etype]) { 1511 if(nn == Z) { 1512 nullwarn(n->left, Z); 1513 break; 1514 } 1515 1516 if(nn->op == OREGPAIR) { 1517 loadpair(n, nn); 1518 break; 1519 } 1520 else if(!vaddr(nn, 0)) { 1521 t = nn->type; 1522 nn->type = types[TLONG]; 1523 reglcgen(&nod1, nn, Z); 1524 nn->type = t; 1525 1526 gmove(lo64(n), &nod1); 1527 nod1.xoffset += SZ_LONG; 1528 gmove(hi64(n), &nod1); 1529 regfree(&nod1); 1530 } 1531 else { 1532 gins(AMOVL, lo64(n), nn); 1533 nn->xoffset += SZ_LONG; 1534 gins(AMOVL, hi64(n), nn); 1535 nn->xoffset -= SZ_LONG; 1536 break; 1537 } 1538 break; 1539 } 1540 goto copy; 1541 1542 case ODOT: 1543 l = n->left; 1544 sugen(l, nodrat, l->type->width); 1545 if(nn == Z) 1546 break; 1547 warn(n, "non-interruptable temporary"); 1548 nod1 = *nodrat; 1549 r = n->right; 1550 if(!r || r->op != OCONST) { 1551 diag(n, "DOT and no offset"); 1552 break; 1553 } 1554 nod1.xoffset += (int32)r->vconst; 1555 nod1.type = n->type; 1556 sugen(&nod1, nn, w); 1557 break; 1558 1559 case OSTRUCT: 1560 /* 1561 * rewrite so lhs has no fn call 1562 */ 1563 if(nn != Z && side(nn)) { 1564 nod1 = *n; 1565 nod1.type = typ(TIND, n->type); 1566 regret(&nod2, &nod1); 1567 lcgen(nn, &nod2); 1568 regsalloc(&nod0, &nod1); 1569 cgen(&nod2, &nod0); 1570 regfree(&nod2); 1571 1572 nod1 = *n; 1573 nod1.op = OIND; 1574 nod1.left = &nod0; 1575 nod1.right = Z; 1576 nod1.complex = 1; 1577 1578 sugen(n, &nod1, w); 1579 return; 1580 } 1581 1582 r = n->left; 1583 for(t = n->type->link; t != T; t = t->down) { 1584 l = r; 1585 if(r->op == OLIST) { 1586 l = r->left; 1587 r = r->right; 1588 } 1589 if(nn == Z) { 1590 cgen(l, nn); 1591 continue; 1592 } 1593 /* 1594 * hand craft *(&nn + o) = l 1595 */ 1596 nod0 = znode; 1597 nod0.op = OAS; 1598 nod0.type = t; 1599 nod0.left = &nod1; 1600 nod0.right = nil; 1601 1602 nod1 = znode; 1603 nod1.op = OIND; 1604 nod1.type = t; 1605 nod1.left = &nod2; 1606 1607 nod2 = znode; 1608 nod2.op = OADD; 1609 nod2.type = typ(TIND, t); 1610 nod2.left = &nod3; 1611 nod2.right = &nod4; 1612 1613 nod3 = znode; 1614 nod3.op = OADDR; 1615 nod3.type = nod2.type; 1616 nod3.left = nn; 1617 1618 nod4 = znode; 1619 nod4.op = OCONST; 1620 nod4.type = nod2.type; 1621 nod4.vconst = t->offset; 1622 1623 ccom(&nod0); 1624 acom(&nod0); 1625 xcom(&nod0); 1626 nod0.addable = 0; 1627 nod0.right = l; 1628 1629 // prtree(&nod0, "hand craft"); 1630 cgen(&nod0, Z); 1631 } 1632 break; 1633 1634 case OAS: 1635 if(nn == Z) { 1636 if(n->addable < INDEXED) 1637 sugen(n->right, n->left, w); 1638 break; 1639 } 1640 1641 sugen(n->right, nodrat, w); 1642 warn(n, "non-interruptable temporary"); 1643 sugen(nodrat, n->left, w); 1644 sugen(nodrat, nn, w); 1645 break; 1646 1647 case OFUNC: 1648 if(nn == Z) { 1649 sugen(n, nodrat, w); 1650 break; 1651 } 1652 h = nn; 1653 if(nn->op == OREGPAIR) { 1654 regsalloc(&nod1, nn); 1655 nn = &nod1; 1656 } 1657 if(nn->op != OIND) { 1658 nn = new1(OADDR, nn, Z); 1659 nn->type = types[TIND]; 1660 nn->addable = 0; 1661 } else 1662 nn = nn->left; 1663 n = new(OFUNC, n->left, new(OLIST, nn, n->right)); 1664 n->type = types[TVOID]; 1665 n->left->type = types[TVOID]; 1666 cgen(n, Z); 1667 if(h->op == OREGPAIR) 1668 loadpair(nn->left, h); 1669 break; 1670 1671 case OCOND: 1672 bcgen(n->left, 1); 1673 p1 = p; 1674 sugen(n->right->left, nn, w); 1675 gbranch(OGOTO); 1676 patch(p1, pc); 1677 p1 = p; 1678 sugen(n->right->right, nn, w); 1679 patch(p1, pc); 1680 break; 1681 1682 case OCOMMA: 1683 cgen(n->left, Z); 1684 sugen(n->right, nn, w); 1685 break; 1686 } 1687 return; 1688 1689 copy: 1690 if(nn == Z) { 1691 switch(n->op) { 1692 case OASADD: 1693 case OASSUB: 1694 case OASAND: 1695 case OASOR: 1696 case OASXOR: 1697 1698 case OASMUL: 1699 case OASLMUL: 1700 1701 1702 case OASASHL: 1703 case OASASHR: 1704 case OASLSHR: 1705 break; 1706 1707 case OPOSTINC: 1708 case OPOSTDEC: 1709 case OPREINC: 1710 case OPREDEC: 1711 break; 1712 1713 default: 1714 return; 1715 } 1716 } 1717 1718 v = w == 8; 1719 if(n->complex >= FNX && nn != nil && nn->complex >= FNX) { 1720 t = nn->type; 1721 nn->type = types[TLONG]; 1722 regialloc(&nod1, nn, Z); 1723 lcgen(nn, &nod1); 1724 regsalloc(&nod2, nn); 1725 nn->type = t; 1726 1727 gins(AMOVL, &nod1, &nod2); 1728 regfree(&nod1); 1729 1730 nod2.type = typ(TIND, t); 1731 1732 nod1 = nod2; 1733 nod1.op = OIND; 1734 nod1.left = &nod2; 1735 nod1.right = Z; 1736 nod1.complex = 1; 1737 nod1.type = t; 1738 1739 sugen(n, &nod1, w); 1740 return; 1741 } 1742 1743 x = 0; 1744 if(v) { 1745 if(nn != nil && nn->complex >= FNX) { 1746 t = nn->type; 1747 nn->type = types[TLONG]; 1748 regialloc(&nod2, nn, Z); 1749 lcgen(nn, &nod2); 1750 nn->type = t; 1751 1752 nod2.type = typ(TIND, t); 1753 1754 nod1 = nod2; 1755 nod1.op = OIND; 1756 nod1.left = &nod2; 1757 nod1.right = Z; 1758 nod1.complex = 1; 1759 nod1.type = t; 1760 1761 sugen(n, &nod1, w); 1762 regfree(&nod2); 1763 return; 1764 } 1765 1766 c = cursafe; 1767 if(n->left != Z && n->left->complex >= FNX 1768 && n->right != Z && n->right->complex >= FNX) { 1769 // warn(n, "toughie"); 1770 regsalloc(&nod1, n->right); 1771 cgen(n->right, &nod1); 1772 nod2 = *n; 1773 nod2.right = &nod1; 1774 cgen(&nod2, nn); 1775 cursafe = c; 1776 return; 1777 } 1778 if(cgen64(n, nn)) { 1779 cursafe = c; 1780 return; 1781 } 1782 if(n->op == OCOM) { 1783 n = n->left; 1784 x = 1; 1785 } 1786 } 1787 1788 /* botch, need to save in .safe */ 1789 c = 0; 1790 if(n->complex > nn->complex) { 1791 t = n->type; 1792 n->type = types[TLONG]; 1793 if(v) { 1794 regalloc(&nod0, n, Z); 1795 if(!vaddr(n, 0)) { 1796 reglcgen(&nod1, n, Z); 1797 n->type = t; 1798 n = &nod1; 1799 } 1800 else 1801 n->type = t; 1802 } 1803 else { 1804 nodreg(&nod1, n, D_SI); 1805 if(reg[D_SI]) { 1806 gins(APUSHL, &nod1, Z); 1807 c |= 1; 1808 reg[D_SI]++; 1809 } 1810 lcgen(n, &nod1); 1811 n->type = t; 1812 } 1813 1814 t = nn->type; 1815 nn->type = types[TLONG]; 1816 if(v) { 1817 if(!vaddr(nn, 0)) { 1818 reglcgen(&nod2, nn, Z); 1819 nn->type = t; 1820 nn = &nod2; 1821 } 1822 else 1823 nn->type = t; 1824 } 1825 else { 1826 nodreg(&nod2, nn, D_DI); 1827 if(reg[D_DI]) { 1828 gins(APUSHL, &nod2, Z); 1829 c |= 2; 1830 reg[D_DI]++; 1831 } 1832 lcgen(nn, &nod2); 1833 nn->type = t; 1834 } 1835 } else { 1836 t = nn->type; 1837 nn->type = types[TLONG]; 1838 if(v) { 1839 regalloc(&nod0, nn, Z); 1840 if(!vaddr(nn, 0)) { 1841 reglcgen(&nod2, nn, Z); 1842 nn->type = t; 1843 nn = &nod2; 1844 } 1845 else 1846 nn->type = t; 1847 } 1848 else { 1849 nodreg(&nod2, nn, D_DI); 1850 if(reg[D_DI]) { 1851 gins(APUSHL, &nod2, Z); 1852 c |= 2; 1853 reg[D_DI]++; 1854 } 1855 lcgen(nn, &nod2); 1856 nn->type = t; 1857 } 1858 1859 t = n->type; 1860 n->type = types[TLONG]; 1861 if(v) { 1862 if(!vaddr(n, 0)) { 1863 reglcgen(&nod1, n, Z); 1864 n->type = t; 1865 n = &nod1; 1866 } 1867 else 1868 n->type = t; 1869 } 1870 else { 1871 nodreg(&nod1, n, D_SI); 1872 if(reg[D_SI]) { 1873 gins(APUSHL, &nod1, Z); 1874 c |= 1; 1875 reg[D_SI]++; 1876 } 1877 lcgen(n, &nod1); 1878 n->type = t; 1879 } 1880 } 1881 if(v) { 1882 gins(AMOVL, n, &nod0); 1883 if(x) 1884 gins(ANOTL, Z, &nod0); 1885 gins(AMOVL, &nod0, nn); 1886 n->xoffset += SZ_LONG; 1887 nn->xoffset += SZ_LONG; 1888 gins(AMOVL, n, &nod0); 1889 if(x) 1890 gins(ANOTL, Z, &nod0); 1891 gins(AMOVL, &nod0, nn); 1892 n->xoffset -= SZ_LONG; 1893 nn->xoffset -= SZ_LONG; 1894 if(nn == &nod2) 1895 regfree(&nod2); 1896 if(n == &nod1) 1897 regfree(&nod1); 1898 regfree(&nod0); 1899 return; 1900 } 1901 nodreg(&nod3, n, D_CX); 1902 if(reg[D_CX]) { 1903 gins(APUSHL, &nod3, Z); 1904 c |= 4; 1905 reg[D_CX]++; 1906 } 1907 gins(AMOVL, nodconst(w/SZ_LONG), &nod3); 1908 gins(ACLD, Z, Z); 1909 gins(AREP, Z, Z); 1910 gins(AMOVSL, Z, Z); 1911 if(c & 4) { 1912 gins(APOPL, Z, &nod3); 1913 reg[D_CX]--; 1914 } 1915 if(c & 2) { 1916 gins(APOPL, Z, &nod2); 1917 reg[nod2.reg]--; 1918 } 1919 if(c & 1) { 1920 gins(APOPL, Z, &nod1); 1921 reg[nod1.reg]--; 1922 } 1923 }