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