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