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