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