1 #include "gc.h" 2 3 void 4 cgen(Node *n, Node *nn) 5 { 6 Node *l, *r; 7 Prog *p1; 8 Node nod, nod1, nod2; 9 int o; 10 long v, curs; 11 12 if(debug['g']) { 13 prtree(nn, "cgen lhs"); 14 prtree(n, "cgen"); 15 } 16 if(n == Z || n->type == T) 17 return; 18 if(typesu[n->type->etype]) { 19 sugen(n, nn, n->type->width); 20 return; 21 } 22 if(n->addable >= INDEXED) { 23 if(nn != Z) 24 gmove(n, nn); 25 return; 26 } 27 curs = cursafe; 28 l = n->left; 29 r = n->right; 30 o = n->op; 31 32 if(n->complex >= FNX) 33 if(l->complex >= FNX) 34 if(r != Z && r->complex >= FNX) 35 switch(o) { 36 default: 37 regret(&nod, r); 38 cgen(r, &nod); 39 40 regsalloc(&nod1, r); 41 gmove(&nod, &nod1); 42 43 regfree(&nod); 44 nod = *n; 45 nod.right = &nod1; 46 47 cgen(&nod, nn); 48 return; 49 50 case OFUNC: 51 case OCOMMA: 52 case OANDAND: 53 case OOROR: 54 case OCOND: 55 case ODOT: 56 break; 57 } 58 59 switch(o) { 60 default: 61 diag(n, "unknown op in cgen: %O", o); 62 break; 63 64 case OAS: 65 if(typefd[n->type->etype]) { 66 diag(n, "no floating"); 67 return; 68 } 69 if(l->op == OBIT) 70 goto bitas; 71 if(l->addable >= INDEXED) { 72 if(nn != Z || r->addable < INDEXED) { 73 regalloc(&nod, r, nn); 74 cgen(r, &nod); 75 gmove(&nod, l); 76 regfree(&nod); 77 } else 78 gmove(r, l); 79 break; 80 } 81 if(l->complex >= r->complex) { 82 reglcgen(&nod1, l, Z); 83 if(r->addable >= INDEXED) { 84 gmove(r, &nod1); 85 if(nn != Z) 86 gmove(r, nn); 87 regfree(&nod1); 88 break; 89 } 90 regalloc(&nod, r, nn); 91 cgen(r, &nod); 92 } else { 93 regalloc(&nod, r, nn); 94 cgen(r, &nod); 95 reglcgen(&nod1, l, Z); 96 } 97 gmove(&nod, &nod1); 98 regfree(&nod); 99 regfree(&nod1); 100 break; 101 102 bitas: 103 n = l->left; 104 regalloc(&nod, r, nn); 105 if(l->complex >= r->complex) { 106 reglcgen(&nod1, n, Z); 107 cgen(r, &nod); 108 } else { 109 cgen(r, &nod); 110 reglcgen(&nod1, n, Z); 111 } 112 regalloc(&nod2, n, Z); 113 gopcode(OAS, &nod1, Z, &nod2); 114 bitstore(l, &nod, &nod1, &nod2, nn); 115 break; 116 117 case OBIT: 118 if(nn == Z) { 119 nullwarn(l, Z); 120 break; 121 } 122 bitload(n, &nod, Z, Z, nn); 123 gmove(&nod, nn); 124 regfree(&nod); 125 break; 126 127 case OLSHR: 128 case OASHL: 129 case OASHR: 130 case OADD: 131 case OSUB: 132 case OOR: 133 case OXOR: 134 case OAND: 135 /* 136 * immediate operands 137 */ 138 if(nn != Z) 139 if(r->op == OCONST) 140 if(!typefd[n->type->etype]) { 141 cgen(l, nn); 142 if(r->vconst == 0) 143 if(o != OAND) 144 break; 145 if(nn != Z) 146 gopcode(o, r, Z, nn); 147 break; 148 } 149 150 case OLMOD: 151 case OMOD: 152 case OLMUL: 153 case OLDIV: 154 case OMUL: 155 case ODIV: 156 if(nn == Z) { 157 nullwarn(l, r); 158 break; 159 } 160 if(typefd[n->type->etype]) 161 goto fop; 162 if(l->complex >= r->complex) { 163 regalloc(&nod, l, nn); 164 cgen(l, &nod); 165 regalloc(&nod1, r, Z); 166 cgen(r, &nod1); 167 gopcode(o, &nod1, Z, &nod); 168 } else { 169 regalloc(&nod1, r, nn); 170 cgen(r, &nod1); 171 regalloc(&nod, l, Z); 172 cgen(l, &nod); 173 gopcode(o, &nod1, Z, &nod); 174 } 175 gmove(&nod, nn); 176 regfree(&nod); 177 regfree(&nod1); 178 break; 179 180 case OASLSHR: 181 case OASASHL: 182 case OASASHR: 183 case OASAND: 184 case OASADD: 185 case OASSUB: 186 case OASXOR: 187 case OASOR: 188 case OASLMUL: 189 case OASLDIV: 190 case OASLMOD: 191 case OASMUL: 192 case OASDIV: 193 case OASMOD: 194 asand: 195 if(typefd[n->type->etype]) 196 goto asfop; 197 if(l->complex >= r->complex) { 198 if(l->addable < INDEXED) 199 reglcgen(&nod2, l, Z); 200 else 201 nod2 = *l; 202 regalloc(&nod1, r, Z); 203 cgen(r, &nod1); 204 } else { 205 regalloc(&nod1, r, Z); 206 cgen(r, &nod1); 207 if(l->addable < INDEXED) 208 reglcgen(&nod2, l, Z); 209 else 210 nod2 = *l; 211 } 212 213 regalloc(&nod, n, nn); 214 gmove(&nod2, &nod); 215 gopcode(o, &nod1, Z, &nod); 216 gmove(&nod, &nod2); 217 if(nn != Z) 218 gmove(&nod, nn); 219 regfree(&nod); 220 regfree(&nod1); 221 if(l->addable < INDEXED) 222 regfree(&nod2); 223 break; 224 225 fop: 226 diag(n, "no floating"); 227 break; 228 229 asfop: 230 diag(n, "no floating"); 231 break; 232 233 case OADDR: 234 if(nn == Z) { 235 nullwarn(l, Z); 236 break; 237 } 238 lcgen(l, nn); 239 break; 240 241 case OFUNC: 242 if(l->complex >= FNX) { 243 if(l->op != OIND) 244 diag(n, "bad function call"); 245 246 regret(&nod, l->left); 247 cgen(l->left, &nod); 248 regsalloc(&nod1, l->left); 249 gmove(&nod, &nod1); 250 regfree(&nod); 251 252 nod = *n; 253 nod.left = &nod2; 254 nod2 = *l; 255 nod2.left = &nod1; 256 nod2.complex = 1; 257 cgen(&nod, nn); 258 259 return; 260 } 261 gargs(r, &nod, &nod1); 262 if(l->addable < INDEXED) { 263 reglcgen(&nod, l, nn); 264 gopcode(OFUNC, Z, Z, &nod); 265 regfree(&nod); 266 } else 267 gopcode(OFUNC, Z, Z, l); 268 if(REGARG && reg[REGARG]) 269 reg[REGARG]--; 270 if(nn != Z) { 271 regret(&nod, n); 272 gmove(&nod, nn); 273 regfree(&nod); 274 } 275 break; 276 277 case OIND: 278 if(nn == Z) { 279 nullwarn(l, Z); 280 break; 281 } 282 regialloc(&nod, n, nn); 283 r = l; 284 while(r->op == OADD) 285 r = r->right; 286 if(sconst(r)) { 287 v = r->vconst; 288 r->vconst = 0; 289 cgen(l, &nod); 290 nod.xoffset += v; 291 r->vconst = v; 292 } else 293 cgen(l, &nod); 294 regind(&nod, n); 295 gmove(&nod, nn); 296 regfree(&nod); 297 break; 298 299 case OEQ: 300 case ONE: 301 case OLE: 302 case OLT: 303 case OGE: 304 case OGT: 305 case OLO: 306 case OLS: 307 case OHI: 308 case OHS: 309 if(nn == Z) { 310 nullwarn(l, r); 311 break; 312 } 313 boolgen(n, 1, nn); 314 break; 315 316 case OANDAND: 317 case OOROR: 318 boolgen(n, 1, nn); 319 if(nn == Z) 320 patch(p, pc); 321 break; 322 323 case ONOT: 324 if(nn == Z) { 325 nullwarn(l, Z); 326 break; 327 } 328 boolgen(n, 1, nn); 329 break; 330 331 case OCOMMA: 332 cgen(l, Z); 333 cgen(r, nn); 334 break; 335 336 case OCAST: 337 if(nn == Z) { 338 nullwarn(l, Z); 339 break; 340 } 341 /* 342 * convert from types l->n->nn 343 */ 344 if(nocast(l->type, n->type) && nocast(n->type, nn->type)) { 345 /* both null, gen l->nn */ 346 cgen(l, nn); 347 break; 348 } 349 regalloc(&nod, l, nn); 350 cgen(l, &nod); 351 regalloc(&nod1, n, &nod); 352 gmove(&nod, &nod1); 353 gmove(&nod1, nn); 354 regfree(&nod1); 355 regfree(&nod); 356 break; 357 358 case ODOT: 359 sugen(l, nodrat, l->type->width); 360 if(nn != Z) { 361 warn(n, "non-interruptable temporary"); 362 nod = *nodrat; 363 if(!r || r->op != OCONST) { 364 diag(n, "DOT and no offset"); 365 break; 366 } 367 nod.xoffset += r->vconst; 368 nod.type = n->type; 369 cgen(&nod, nn); 370 } 371 break; 372 373 case OCOND: 374 bcgen(l, 1); 375 p1 = p; 376 cgen(r->left, nn); 377 gbranch(OGOTO); 378 patch(p1, pc); 379 p1 = p; 380 cgen(r->right, nn); 381 patch(p1, pc); 382 break; 383 384 case OPOSTINC: 385 case OPOSTDEC: 386 v = 1; 387 if(l->type->etype == TIND) 388 v = l->type->link->width; 389 if(o == OPOSTDEC) 390 v = -v; 391 if(l->op == OBIT) 392 goto bitinc; 393 if(nn == Z) 394 goto pre; 395 396 if(l->addable < INDEXED) 397 reglcgen(&nod2, l, Z); 398 else 399 nod2 = *l; 400 401 regalloc(&nod, l, nn); 402 gmove(&nod2, &nod); 403 regalloc(&nod1, l, Z); 404 if(typefd[l->type->etype]) { 405 diag(n, "no floating"); 406 } else 407 gopcode(OADD, nodconst(v), &nod, &nod1); 408 gmove(&nod1, &nod2); 409 410 regfree(&nod); 411 regfree(&nod1); 412 if(l->addable < INDEXED) 413 regfree(&nod2); 414 break; 415 416 case OPREINC: 417 case OPREDEC: 418 v = 1; 419 if(l->type->etype == TIND) 420 v = l->type->link->width; 421 if(o == OPREDEC) 422 v = -v; 423 if(l->op == OBIT) 424 goto bitinc; 425 426 pre: 427 if(l->addable < INDEXED) 428 reglcgen(&nod2, l, Z); 429 else 430 nod2 = *l; 431 432 regalloc(&nod, l, nn); 433 gmove(&nod2, &nod); 434 if(typefd[l->type->etype]) { 435 diag(n, "no floating"); 436 } else 437 gopcode(OADD, nodconst(v), Z, &nod); 438 gmove(&nod, &nod2); 439 440 regfree(&nod); 441 if(l->addable < INDEXED) 442 regfree(&nod2); 443 break; 444 445 bitinc: 446 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) 447 diag(n, "botch"); 448 bitload(l, &nod, &nod1, &nod2, nn); 449 gopcode(OADD, nodconst(v), Z, &nod); 450 bitstore(l, &nod, &nod1, &nod2, nn); 451 break; 452 } 453 cursafe = curs; 454 return; 455 456 bad: 457 cursafe = curs; 458 diag(n, "%O not implemented", o); 459 } 460 461 void 462 reglcgen(Node *t, Node *n, Node *nn) 463 { 464 Node *r; 465 long v; 466 467 regialloc(t, n, nn); 468 if(n->op == OIND) { 469 r = n->left; 470 while(r->op == OADD) 471 r = r->right; 472 if(sconst(r)) { 473 v = r->vconst; 474 r->vconst = 0; 475 lcgen(n, t); 476 t->xoffset += v; 477 r->vconst = v; 478 regind(t, n); 479 return; 480 } 481 } 482 lcgen(n, t); 483 regind(t, n); 484 } 485 486 void 487 lcgen(Node *n, Node *nn) 488 { 489 Prog *p1; 490 Node nod; 491 492 if(debug['g']) { 493 prtree(nn, "lcgen lhs"); 494 prtree(n, "lcgen"); 495 } 496 if(n == Z || n->type == T) 497 return; 498 if(nn == Z) { 499 nn = &nod; 500 regalloc(&nod, n, Z); 501 } 502 switch(n->op) { 503 default: 504 if(n->addable < INDEXED) { 505 diag(n, "unknown op in lcgen: %O", n->op); 506 break; 507 } 508 gopcode(OADDR, n, Z, nn); 509 break; 510 511 case OCOMMA: 512 cgen(n->left, n->left); 513 lcgen(n->right, nn); 514 break; 515 516 case OIND: 517 cgen(n->left, nn); 518 break; 519 520 case OCOND: 521 bcgen(n->left, 1); 522 p1 = p; 523 lcgen(n->right->left, nn); 524 gbranch(OGOTO); 525 patch(p1, pc); 526 p1 = p; 527 lcgen(n->right->right, nn); 528 patch(p1, pc); 529 break; 530 } 531 } 532 533 void 534 bcgen(Node *n, int true) 535 { 536 537 if(n->type == T) 538 gbranch(OGOTO); 539 else 540 boolgen(n, true, Z); 541 } 542 543 void 544 boolgen(Node *n, int true, Node *nn) 545 { 546 int o; 547 Prog *p1, *p2; 548 Node *l, *r, nod, nod1; 549 long curs; 550 551 if(debug['g']) { 552 prtree(nn, "boolgen lhs"); 553 prtree(n, "boolgen"); 554 } 555 curs = cursafe; 556 l = n->left; 557 r = n->right; 558 switch(n->op) { 559 560 default: 561 regalloc(&nod, n, nn); 562 cgen(n, &nod); 563 o = ONE; 564 if(true) 565 o = comrel[relindex(o)]; 566 if(typefd[n->type->etype]) { 567 diag(n, "no floating"); 568 } else 569 gopcode(o, &nod, Z, nodconst(0L)); 570 regfree(&nod); 571 goto com; 572 573 case OCONST: 574 o = vconst(n); 575 if(!true) 576 o = !o; 577 gbranch(OGOTO); 578 if(o) { 579 p1 = p; 580 gbranch(OGOTO); 581 patch(p1, pc); 582 } 583 goto com; 584 585 case OCOMMA: 586 cgen(l, Z); 587 boolgen(r, true, nn); 588 break; 589 590 case ONOT: 591 boolgen(l, !true, nn); 592 break; 593 594 case OCOND: 595 bcgen(l, 1); 596 p1 = p; 597 bcgen(r->left, true); 598 p2 = p; 599 gbranch(OGOTO); 600 patch(p1, pc); 601 p1 = p; 602 bcgen(r->right, !true); 603 patch(p2, pc); 604 p2 = p; 605 gbranch(OGOTO); 606 patch(p1, pc); 607 patch(p2, pc); 608 goto com; 609 610 case OANDAND: 611 if(!true) 612 goto caseor; 613 614 caseand: 615 bcgen(l, true); 616 p1 = p; 617 bcgen(r, !true); 618 p2 = p; 619 patch(p1, pc); 620 gbranch(OGOTO); 621 patch(p2, pc); 622 goto com; 623 624 case OOROR: 625 if(!true) 626 goto caseand; 627 628 caseor: 629 bcgen(l, !true); 630 p1 = p; 631 bcgen(r, !true); 632 p2 = p; 633 gbranch(OGOTO); 634 patch(p1, pc); 635 patch(p2, pc); 636 goto com; 637 638 case OEQ: 639 case ONE: 640 case OLE: 641 case OLT: 642 case OGE: 643 case OGT: 644 case OHI: 645 case OHS: 646 case OLO: 647 case OLS: 648 o = n->op; 649 if(true) 650 o = comrel[relindex(o)]; 651 if(l->complex >= FNX && r->complex >= FNX) { 652 regret(&nod, r); 653 cgen(r, &nod); 654 regsalloc(&nod1, r); 655 gmove(&nod, &nod1); 656 regfree(&nod); 657 nod = *n; 658 nod.right = &nod1; 659 boolgen(&nod, true, nn); 660 break; 661 } 662 if(typefd[l->type->etype]) { 663 diag(n, "no floating"); 664 break; 665 } 666 if(l->op == OCONST) { 667 regalloc(&nod, r, nn); 668 cgen(r, &nod); 669 gopcode(o, l, Z, &nod); 670 regfree(&nod); 671 goto com; 672 } 673 if(r->op == OCONST) { 674 o = invrel[relindex(o)]; 675 regalloc(&nod, l, nn); 676 cgen(l, &nod); 677 gopcode(o, r, Z, &nod); 678 regfree(&nod); 679 goto com; 680 } 681 if(l->complex >= r->complex) { 682 regalloc(&nod1, l, nn); 683 cgen(l, &nod1); 684 regalloc(&nod, r, Z); 685 cgen(r, &nod); 686 } else { 687 regalloc(&nod, r, nn); 688 cgen(r, &nod); 689 regalloc(&nod1, l, Z); 690 cgen(l, &nod1); 691 } 692 gopcode(o, &nod1, Z, &nod); 693 regfree(&nod); 694 regfree(&nod1); 695 696 com: 697 if(nn != Z) { 698 p1 = p; 699 gmove(nodconst(1L), nn); 700 gbranch(OGOTO); 701 p2 = p; 702 patch(p1, pc); 703 gmove(nodconst(0L), nn); 704 patch(p2, pc); 705 } 706 break; 707 } 708 cursafe = curs; 709 } 710 711 void 712 sugen(Node *n, Node *nn, long w) 713 { 714 Prog *p1; 715 Node nod0, nod1, nod2, nod3, nod4, *l, *r; 716 Type *t; 717 long pc1; 718 int i, m, c; 719 720 if(n == Z || n->type == T) 721 return; 722 if(debug['g']) { 723 prtree(nn, "sugen lhs"); 724 prtree(n, "sugen"); 725 } 726 if(nn == nodrat) 727 if(w > nrathole) 728 nrathole = w; 729 switch(n->op) { 730 case OIND: 731 if(nn == Z) { 732 nullwarn(n->left, Z); 733 break; 734 } 735 736 default: 737 goto copy; 738 739 case ODOT: 740 l = n->left; 741 sugen(l, nodrat, l->type->width); 742 if(nn != Z) { 743 warn(n, "non-interruptable temporary"); 744 nod1 = *nodrat; 745 r = n->right; 746 if(!r || r->op != OCONST) { 747 diag(n, "DOT and no offset"); 748 break; 749 } 750 nod1.xoffset += r->vconst; 751 nod1.type = n->type; 752 sugen(&nod1, nn, w); 753 } 754 break; 755 756 case OSTRUCT: 757 /* 758 * rewrite so lhs has no fn call 759 */ 760 if(nn != Z && nn->complex >= FNX) { 761 nod1 = *n; 762 nod1.type = typ(TIND, n->type); 763 regret(&nod2, &nod1); 764 lcgen(nn, &nod2); 765 regsalloc(&nod0, &nod1); 766 gopcode(OAS, &nod2, Z, &nod0); 767 regfree(&nod2); 768 769 nod1 = *n; 770 nod1.op = OIND; 771 nod1.left = &nod0; 772 nod1.right = Z; 773 nod1.complex = 1; 774 775 sugen(n, &nod1, w); 776 return; 777 } 778 779 r = n->left; 780 for(t = n->type->link; t != T; t = t->down) { 781 l = r; 782 if(r->op == OLIST) { 783 l = r->left; 784 r = r->right; 785 } 786 if(nn == Z) { 787 cgen(l, nn); 788 continue; 789 } 790 /* 791 * hand craft *(&nn + o) = l 792 */ 793 nod0 = znode; 794 nod0.op = OAS; 795 nod0.type = t; 796 nod0.left = &nod1; 797 nod0.right = l; 798 799 nod1 = znode; 800 nod1.op = OIND; 801 nod1.type = t; 802 nod1.left = &nod2; 803 804 nod2 = znode; 805 nod2.op = OADD; 806 nod2.type = typ(TIND, t); 807 nod2.left = &nod3; 808 nod2.right = &nod4; 809 810 nod3 = znode; 811 nod3.op = OADDR; 812 nod3.type = nod2.type; 813 nod3.left = nn; 814 815 nod4 = znode; 816 nod4.op = OCONST; 817 nod4.type = nod2.type; 818 nod4.vconst = t->offset; 819 820 ccom(&nod0); 821 acom(&nod0); 822 xcom(&nod0); 823 nod0.addable = 0; 824 825 /* prtree(&nod0, "hand craft"); /* */ 826 cgen(&nod0, Z); 827 } 828 break; 829 830 case OAS: 831 if(nn == Z) { 832 if(n->addable < INDEXED) 833 sugen(n->right, n->left, w); 834 break; 835 } 836 /* BOTCH -- functions can clobber rathole */ 837 sugen(n->right, nodrat, w); 838 warn(n, "non-interruptable temporary"); 839 sugen(nodrat, n->left, w); 840 sugen(nodrat, nn, w); 841 break; 842 843 case OFUNC: 844 if(nn == Z) { 845 sugen(n, nodrat, w); 846 break; 847 } 848 if(nn->op != OIND) { 849 nn = new1(OADDR, nn, Z); 850 nn->type = types[TIND]; 851 nn->addable = 0; 852 } else 853 nn = nn->left; 854 n = new(OFUNC, n->left, new(OLIST, nn, n->right)); 855 n->type = types[TVOID]; 856 n->left->type = types[TVOID]; 857 cgen(n, Z); 858 break; 859 860 case OCOND: 861 bcgen(n->left, 1); 862 p1 = p; 863 sugen(n->right->left, nn, w); 864 gbranch(OGOTO); 865 patch(p1, pc); 866 p1 = p; 867 sugen(n->right->right, nn, w); 868 patch(p1, pc); 869 break; 870 871 case OCOMMA: 872 cgen(n->left, Z); 873 sugen(n->right, nn, w); 874 break; 875 } 876 return; 877 878 copy: 879 if(nn == Z) 880 return; 881 if(n->complex >= FNX && nn->complex >= FNX) { 882 diag(n, "Ah, come on. Is that you, Rob?"); 883 return; 884 } 885 886 if(n->complex > nn->complex) { 887 t = n->type; 888 n->type = types[TLONG]; 889 reglcgen(&nod1, n, Z); 890 n->type = t; 891 892 t = nn->type; 893 nn->type = types[TLONG]; 894 reglcgen(&nod2, nn, Z); 895 nn->type = t; 896 } else { 897 t = nn->type; 898 nn->type = types[TLONG]; 899 reglcgen(&nod2, nn, Z); 900 nn->type = t; 901 902 t = n->type; 903 n->type = types[TLONG]; 904 reglcgen(&nod1, n, Z); 905 n->type = t; 906 } 907 908 w /= SZ_LONG; 909 if(w <= 5) { 910 layout(&nod1, &nod2, w, 0, Z); 911 goto out; 912 } 913 914 /* 915 * minimize space for unrolling loop 916 * 3,4,5 times. (6 or more is never minimum) 917 * if small structure, try 2 also. 918 */ 919 c = 0; /* set */ 920 m = 100; 921 i = 3; 922 if(w <= 15) 923 i = 2; 924 for(; i<=5; i++) 925 if(i + w%i <= m) { 926 c = i; 927 m = c + w%c; 928 } 929 930 regalloc(&nod3, ®node, Z); 931 layout(&nod1, &nod2, w%c, w/c, &nod3); 932 933 pc1 = pc; 934 layout(&nod1, &nod2, c, 0, Z); 935 936 gopcode(OSUB, nodconst(1L), Z, &nod3); 937 nod1.op = OREGISTER; 938 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1); 939 nod2.op = OREGISTER; 940 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2); 941 942 gopcode(OEQ, &nod3, Z, Z); 943 p->as = ACMPIBGE; 944 patch(p, pc1); 945 946 regfree(&nod3); 947 out: 948 regfree(&nod1); 949 regfree(&nod2); 950 } 951 952 void 953 layout(Node *f, Node *t, int c, int cv, Node *cn) 954 { 955 Node t1, t2; 956 957 while(c > 3) { 958 layout(f, t, 2, 0, Z); 959 c -= 2; 960 } 961 962 regalloc(&t1, ®node, Z); 963 regalloc(&t2, ®node, Z); 964 if(c > 0) { 965 gmove(f, &t1); 966 f->xoffset += SZ_LONG; 967 } 968 if(cn != Z) 969 gmove(nodconst(cv), cn); 970 if(c > 1) { 971 gmove(f, &t2); 972 f->xoffset += SZ_LONG; 973 } 974 if(c > 0) { 975 gmove(&t1, t); 976 t->xoffset += SZ_LONG; 977 } 978 if(c > 2) { 979 gmove(f, &t1); 980 f->xoffset += SZ_LONG; 981 } 982 if(c > 1) { 983 gmove(&t2, t); 984 t->xoffset += SZ_LONG; 985 } 986 if(c > 2) { 987 gmove(&t1, t); 988 t->xoffset += SZ_LONG; 989 } 990 regfree(&t1); 991 regfree(&t2); 992 } 993