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