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