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