001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.compilers.opt.ir.operand; 014 015import org.jikesrvm.compilers.opt.OptimizingCompilerException; 016import org.vmmagic.unboxed.Address; 017import org.jikesrvm.runtime.Magic; 018 019/** 020 * Encodes the condition codes for branches. 021 * 022 * @see Operand 023 */ 024public final class ConditionOperand extends Operand { 025 026 /* signed integer arithmetic */ 027 /** Integer equal == */ 028 public static final int EQUAL = 0; 029 /** Integer not equal != */ 030 public static final int NOT_EQUAL = 1; 031 /** Signed integer < */ 032 public static final int LESS = 2; 033 /** Signed integer >= */ 034 public static final int GREATER_EQUAL = 3; 035 /** Signed integer > */ 036 public static final int GREATER = 4; 037 /** Signed integer <= */ 038 public static final int LESS_EQUAL = 5; 039 040 /* unsigned integer arithmetic */ 041 /** Unsigned integer > - >U */ 042 public static final int HIGHER = 6; 043 /** Unsigned integer < - <U */ 044 public static final int LOWER = 7; 045 /** Unsigned integer >= - >=U */ 046 public static final int HIGHER_EQUAL = 8; 047 /** Unsigned integer <= - <=U */ 048 public static final int LOWER_EQUAL = 9; 049 050 /* floating-point arithmethic */ 051 // branches that fall through when unordered 052 /** Branch if == (equivalent to CMPG_EQUAL) - ==F */ 053 public static final int CMPL_EQUAL = 10; 054 /** Branch if > - >F */ 055 public static final int CMPL_GREATER = 11; 056 /** Branch if < - <F */ 057 public static final int CMPG_LESS = 12; 058 /** Branch if >= - >=F */ 059 public static final int CMPL_GREATER_EQUAL = 13; 060 /** Branch if <= - <=F */ 061 public static final int CMPG_LESS_EQUAL = 14; 062 063 // branches that are taken when unordered 064 /** Branch if != (equivalent to CMPG_NOT_EQUAL) - !=FU */ 065 public static final int CMPL_NOT_EQUAL = 15; 066 /** Branch if < or unordered - <FU */ 067 public static final int CMPL_LESS = 16; 068 /** Brach if >= or unordered - >=FU */ 069 public static final int CMPG_GREATER_EQUAL = 17; 070 /** Branch if > or unordered - >FU */ 071 public static final int CMPG_GREATER = 18; 072 /** Branch if <= or unordered - <=FU */ 073 public static final int CMPL_LESS_EQUAL = 19; 074 075 /* integer arithmetic flag operations */ 076 /** Would a+b produce a carry? */ 077 public static final int CARRY_FROM_ADD = 20; 078 /** Would a+b not produce a carry? */ 079 public static final int NO_CARRY_FROM_ADD = 21; 080 081 /** Would a+b cause an overflow? */ 082 public static final int OVERFLOW_FROM_ADD = 22; 083 /** Would a+b not cause an overflow? */ 084 public static final int NO_OVERFLOW_FROM_ADD = 23; 085 086 /** Would a-b produce a borrow? */ 087 public static final int BORROW_FROM_SUB = 24; 088 /** Would a-b not produce a borrow? */ 089 public static final int NO_BORROW_FROM_SUB = 25; 090 /** Would b-a produce a borrow? */ 091 public static final int BORROW_FROM_RSUB = 26; 092 /** Would b-a not produce a borrow? */ 093 public static final int NO_BORROW_FROM_RSUB = 27; 094 095 /** Would a-b cause an overflow? */ 096 public static final int OVERFLOW_FROM_SUB = 28; 097 /** Would a-b not cause an overflow? */ 098 public static final int NO_OVERFLOW_FROM_SUB = 29; 099 /** Would b-a cause an overflow? */ 100 public static final int OVERFLOW_FROM_RSUB = 30; 101 /** Would b-a not cause an overflow? */ 102 public static final int NO_OVERFLOW_FROM_RSUB = 31; 103 104 /** Would is bit b set in a? */ 105 public static final int BIT_TEST = 32; 106 /** Would is bit b not set in a? */ 107 public static final int NO_BIT_TEST = 33; 108 /** Would is bit a set in b? */ 109 public static final int RBIT_TEST = 34; 110 /** Would is bit a not set in b? */ 111 public static final int NO_RBIT_TEST = 35; 112 113 /** Would a*b cause an overflow? */ 114 public static final int OVERFLOW_FROM_MUL = 36; 115 /** Would a*b not cause an overflow? */ 116 public static final int NO_OVERFLOW_FROM_MUL = 37; 117 118 /* Results from evaluations */ 119 /** Evaluation result is false */ 120 public static final int FALSE = 0; 121 /** Evaluation result is true */ 122 public static final int TRUE = 1; 123 /** Evaluation result is unknown */ 124 public static final int UNKNOWN = 2; 125 126 /** 127 * Value of this operand. 128 */ 129 public int value; 130 131 /** 132 * @param code the condition code 133 */ 134 private ConditionOperand(int code) { 135 value = code; 136 } 137 138 /** 139 * Create the condition code operand for EQUAL 140 * 141 * @return a new condition code operand 142 */ 143 public static ConditionOperand EQUAL() { 144 return new ConditionOperand(EQUAL); 145 } 146 147 /** 148 * Create the condition code operand for NOT_EQUAL 149 * 150 * @return a newly created condition code operand 151 */ 152 public static ConditionOperand NOT_EQUAL() { 153 return new ConditionOperand(NOT_EQUAL); 154 } 155 156 /** 157 * Create the condition code operand for LESS 158 * 159 * @return a newly created condition code operand 160 */ 161 public static ConditionOperand LESS() { 162 return new ConditionOperand(LESS); 163 } 164 165 /** 166 * Create the condition code operand for GREATER_EQUAL 167 * 168 * @return a newly created condition code operand 169 */ 170 public static ConditionOperand GREATER_EQUAL() { 171 return new ConditionOperand(GREATER_EQUAL); 172 } 173 174 /** 175 * Create the condition code operand for GREATER 176 * 177 * @return a newly created condition code operand 178 */ 179 public static ConditionOperand GREATER() { 180 return new ConditionOperand(GREATER); 181 } 182 183 /** 184 * Create the condition code operand for LESS_EQUAL 185 * 186 * @return a newly created condition code operand 187 */ 188 public static ConditionOperand LESS_EQUAL() { 189 return new ConditionOperand(LESS_EQUAL); 190 } 191 192 /** 193 * Create the condition code operand for HIGHER 194 * 195 * @return a newly created condition code operand 196 */ 197 public static ConditionOperand HIGHER() { 198 return new ConditionOperand(HIGHER); 199 } 200 201 /** 202 * Create the condition code operand for LOWER 203 * 204 * @return a newly created condition code operand 205 */ 206 public static ConditionOperand LOWER() { 207 return new ConditionOperand(LOWER); 208 } 209 210 /** 211 * Create the condition code operand for HIGHER_EQUAL 212 * 213 * @return a newly created condition code operand 214 */ 215 public static ConditionOperand HIGHER_EQUAL() { 216 return new ConditionOperand(HIGHER_EQUAL); 217 } 218 219 /** 220 * Create the condition code operand for LOWER_EQUAL 221 * 222 * @return a newly created condition code operand 223 */ 224 public static ConditionOperand LOWER_EQUAL() { 225 return new ConditionOperand(LOWER_EQUAL); 226 } 227 228 /** 229 * Create the condition code operand for CMPL_EQUAL 230 * 231 * @return a newly created condition code operand 232 */ 233 public static ConditionOperand CMPL_EQUAL() { 234 return new ConditionOperand(CMPL_EQUAL); 235 } 236 237 /** 238 * Create the condition code operand for CMPL_NOT_EQUAL 239 * 240 * @return a newly created condition code operand 241 */ 242 public static ConditionOperand CMPL_NOT_EQUAL() { 243 return new ConditionOperand(CMPL_NOT_EQUAL); 244 } 245 246 /** 247 * Create the condition code operand for CMPL_GREATER 248 * 249 * @return a newly created condition code operand 250 */ 251 public static ConditionOperand CMPL_GREATER() { 252 return new ConditionOperand(CMPL_GREATER); 253 } 254 255 /** 256 * Create the condition code operand for CMPL_GREATER_EQUAL 257 * 258 * @return a newly created condition code operand 259 */ 260 public static ConditionOperand CMPL_GREATER_EQUAL() { 261 return new ConditionOperand(CMPL_GREATER_EQUAL); 262 } 263 264 /** 265 * Create the condition code operand for CMPG_LESS 266 * 267 * @return a newly created condition code operand 268 */ 269 public static ConditionOperand CMPG_LESS() { 270 return new ConditionOperand(CMPG_LESS); 271 } 272 273 /** 274 * Create the condition code operand for CARRY_FROM_ADD 275 * 276 * @return a newly created condition code operand 277 */ 278 public static ConditionOperand CARRY_FROM_ADD() { 279 return new ConditionOperand(CARRY_FROM_ADD); 280 } 281 282 /** 283 * Create the condition code operand for OVERFLOW_FROM_ADD 284 * 285 * @return a newly created condition code operand 286 */ 287 public static ConditionOperand OVERFLOW_FROM_ADD() { 288 return new ConditionOperand(OVERFLOW_FROM_ADD); 289 } 290 291 /** 292 * Create the condition code operand for BORROW_FROM_SUB 293 * 294 * @return a newly created condition code operand 295 */ 296 public static ConditionOperand BORROW_FROM_SUB() { 297 return new ConditionOperand(BORROW_FROM_SUB); 298 } 299 300 /** 301 * Create the condition code operand for OVERFLOW_FROM_SUB 302 * 303 * @return a newly created condition code operand 304 */ 305 public static ConditionOperand OVERFLOW_FROM_SUB() { 306 return new ConditionOperand(OVERFLOW_FROM_SUB); 307 } 308 309 /** 310 * Create the condition code operand for BIT_TEST 311 * 312 * @return a newly created condition code operand 313 */ 314 public static ConditionOperand BIT_TEST() { 315 return new ConditionOperand(BIT_TEST); 316 } 317 318 /** 319 * Create the condition code operand for OVERFLOW_FROM_ADD 320 * 321 * @return a newly created condition code operand 322 */ 323 public static ConditionOperand OVERFLOW_FROM_MUL() { 324 return new ConditionOperand(OVERFLOW_FROM_MUL); 325 } 326 327 /** 328 * Is x higher (unsigned >) than y? 329 * @param x first value for comparison 330 * @param y second value for comparison 331 * @return {@code true} if x is higher (unsigned >) 332 * than y, {@code false} otherwise 333 */ 334 private static boolean higher(int x, int y) { 335 return (x & 0xFFFFFFFFL) > ((long)y & 0xFFFFFFFF); 336 } 337 338 /** 339 * Is x lower (unsigned <) than y? 340 * @param x first value for comparison 341 * @param y second value for comparison 342 * @return {@code true} if x is lower (unsigned <) 343 * than y, {@code false} otherwise 344 */ 345 private static boolean lower(int x, int y) { 346 return (x & 0xFFFFFFFFL) < ((long)y & 0xFFFFFFFF); 347 } 348 349 /** 350 * Is x higher equal (unsigned >=) than y? 351 * @param x first value for comparison 352 * @param y second value for comparison 353 * @return {@code true} if x is higher equal (unsigned >=) 354 * than y, {@code false} otherwise 355 */ 356 private static boolean higher_equal(int x, int y) { 357 return (x & 0xFFFFFFFFL) >= ((long)y & 0xFFFFFFFF); 358 } 359 360 /** 361 * Is x lower equal (unsigned <=) than y? 362 * @param x first value for comparison 363 * @param y second value for comparison 364 * @return {@code true} if x is lower equal (unsigned <=) 365 * than y, {@code false} otherwise 366 */ 367 private static boolean lower_equal(int x, int y) { 368 return (x & 0xFFFFFFFFL) <= ((long)y & 0xFFFFFFFF); 369 } 370 371 /** 372 * Would {@code x + y} produce a carry? 373 * @param x first summand 374 * @param y second summand 375 * @return {@code true} if the addition would produce 376 * a carry, {@code false} otherwise 377 */ 378 private static boolean carry_from_add(int x, int y) { 379 int sum = x + y; 380 return lower(sum, x); 381 } 382 383 /** 384 * Would {@code x - y} produce a borrow? 385 * @param x minuend 386 * @param y subtrahend 387 * @return {@code true} if the subtraction would produce 388 * a borrow, {@code false} otherwise 389 */ 390 private static boolean borrow_from_sub(int x, int y) { 391 return lower(x, y); 392 } 393 394 /** 395 * Would {@code x + y} overflow a register? 396 * @param x first summand 397 * @param y second summand 398 * @return {@code true} if the addition would overflow, 399 * {@code false} otherwise 400 */ 401 private static boolean overflow_from_add(int x, int y) { 402 if (y >= 0) 403 return x > (Integer.MAX_VALUE - y); 404 else 405 return x < (Integer.MIN_VALUE - y); 406 } 407 408 /** 409 * Would {@code x - y} overflow a register? 410 * @param x minuend 411 * @param y subtrahend 412 * @return {@code true} if the subtraction would overflow, 413 * {@code false} otherwise 414 */ 415 private static boolean overflow_from_sub(int x, int y) { 416 if (y >= 0) 417 return x < (Integer.MIN_VALUE + y); 418 else 419 return x > (Integer.MAX_VALUE + y); 420 } 421 422 /** 423 * Would {@code x * y} overflow a register? 424 * @param x first factor 425 * @param y second factor 426 * @return {@code true} if the multiplication would overflow, 427 * {@code false} otherwise 428 */ 429 private static boolean overflow_from_mul(int x, int y) { 430 int z = x * y; 431 long z2 = ((long)x) * ((long)y); 432 return z != z2; 433 } 434 435 /** 436 * Is bit y of x set? 437 * 438 * @param x the number to check 439 * @param y the bit position (0 is least significant bit) 440 * @return whether bit position y of x is set (LSB is 0) 441 */ 442 private static boolean bit_test(int x, int y) { 443 return (x & (1 << y)) != 0; 444 } 445 446 /** 447 * Is the condition code EQUAL? 448 * 449 * @return <code>true</code> if it is or <code>false</code> if it is not 450 */ 451 public boolean isEQUAL() { 452 return value == EQUAL; 453 } 454 455 /** 456 * Is the condition code NOT_EQUAL? 457 * 458 * @return <code>true</code> if it is or <code>false</code> if it is not 459 */ 460 public boolean isNOT_EQUAL() { 461 return value == NOT_EQUAL; 462 } 463 464 /** 465 * Is the condition code LESS EQUAL? 466 * 467 * @return <code>true</code> if it is or <code>false</code> if it is not 468 */ 469 public boolean isLESS_EQUAL() { 470 return value == LESS_EQUAL; 471 } 472 473 /** 474 * Is the condition code GREATER_EQUAL? 475 * 476 * @return <code>true</code> if it is or <code>false</code> if it is not 477 */ 478 public boolean isGREATER_EQUAL() { 479 return value == GREATER_EQUAL; 480 } 481 482 /** 483 * Is the condition code GREATER? 484 * 485 * @return <code>true</code> if it is or <code>false</code> if it is not 486 */ 487 public boolean isGREATER() { 488 return value == GREATER; 489 } 490 491 /** 492 * Is the condition code LESS? 493 * 494 * @return <code>true</code> if it is or <code>false</code> if it is not 495 */ 496 public boolean isLESS() { 497 return value == LESS; 498 } 499 500 /** 501 * Is the condition code HIGHER? 502 * 503 * @return <code>true</code> if it is or <code>false</code> if it is not 504 */ 505 public boolean isHIGHER() { 506 return value == HIGHER; 507 } 508 509 /** 510 * Is the condition code LOWER? 511 * 512 * @return <code>true</code> if it is or <code>false</code> if it is not 513 */ 514 public boolean isLOWER() { 515 return value == LOWER; 516 } 517 518 /** 519 * Is the condition code HIGHER_EQUAL? 520 * 521 * @return <code>true</code> if it is or <code>false</code> if it is not 522 */ 523 public boolean isHIGHER_EQUAL() { 524 return value == HIGHER_EQUAL; 525 } 526 527 /** 528 * Is the condition code LOWER_EQUAL? 529 * 530 * @return <code>true</code> if it is or <code>false</code> if it is not 531 */ 532 public boolean isLOWER_EQUAL() { 533 return value == LOWER_EQUAL; 534 } 535 536 /** 537 * Is the condition code an unsigned comparison? 538 * @return <code>true</code> if it is or <code>false</code> if it is not 539 */ 540 public boolean isUNSIGNED() { 541 switch (value) { 542 case HIGHER: 543 case LOWER: 544 case HIGHER_EQUAL: 545 case LOWER_EQUAL: 546 return true; 547 default: 548 return false; 549 } 550 } 551 552 /** 553 * Is the condition code a flag operation? 554 * @return <code>true</code> if it is or <code>false</code> if it is not 555 */ 556 public boolean isFLAG_OPERATION() { 557 switch (value) { 558 case CARRY_FROM_ADD: 559 case NO_CARRY_FROM_ADD: 560 case OVERFLOW_FROM_ADD: 561 case NO_OVERFLOW_FROM_ADD: 562 case BORROW_FROM_SUB: 563 case NO_BORROW_FROM_SUB: 564 case OVERFLOW_FROM_SUB: 565 case NO_OVERFLOW_FROM_SUB: 566 case BORROW_FROM_RSUB: 567 case NO_BORROW_FROM_RSUB: 568 case OVERFLOW_FROM_RSUB: 569 case NO_OVERFLOW_FROM_RSUB: 570 case BIT_TEST: 571 case NO_BIT_TEST: 572 case RBIT_TEST: 573 case NO_RBIT_TEST: 574 case OVERFLOW_FROM_MUL: 575 case NO_OVERFLOW_FROM_MUL: 576 return true; 577 default: 578 return false; 579 } 580 } 581 582 /** 583 * Is the condition code a flag operation following an add? 584 * @return <code>true</code> if it is or <code>false</code> if it is not 585 */ 586 public boolean isFLAG_OPERATION_FROM_ADD() { 587 switch (value) { 588 case CARRY_FROM_ADD: 589 case NO_CARRY_FROM_ADD: 590 case OVERFLOW_FROM_ADD: 591 case NO_OVERFLOW_FROM_ADD: 592 return true; 593 default: 594 return false; 595 } 596 } 597 598 /** 599 * Is the condition code a flag operation following a subtract? 600 * @return <code>true</code> if it is or <code>false</code> if it is not 601 */ 602 public boolean isFLAG_OPERATION_FROM_SUB() { 603 switch (value) { 604 case BORROW_FROM_SUB: 605 case NO_BORROW_FROM_SUB: 606 case OVERFLOW_FROM_SUB: 607 case NO_OVERFLOW_FROM_SUB: 608 return true; 609 default: 610 return false; 611 } 612 } 613 614 /** 615 * Is the condition code a flag operation following a reversed subtract? 616 * @return <code>true</code> if it is or <code>false</code> if it is not 617 */ 618 public boolean isFLAG_OPERATION_FROM_RSUB() { 619 switch (value) { 620 case BORROW_FROM_RSUB: 621 case NO_BORROW_FROM_RSUB: 622 case OVERFLOW_FROM_RSUB: 623 case NO_OVERFLOW_FROM_RSUB: 624 return true; 625 default: 626 return false; 627 } 628 } 629 630 /** 631 * Is the condition code a flag operation following a bit test? 632 * @return <code>true</code> if it is or <code>false</code> if it is not 633 */ 634 public boolean isBIT_TEST() { 635 switch (value) { 636 case BIT_TEST: 637 case NO_BIT_TEST: 638 return true; 639 default: 640 return false; 641 } 642 } 643 644 /** 645 * Is the condition code a flag operation following a reversed bit test? 646 * @return <code>true</code> if it is or <code>false</code> if it is not 647 */ 648 public boolean isRBIT_TEST() { 649 switch (value) { 650 case RBIT_TEST: 651 case NO_RBIT_TEST: 652 return true; 653 default: 654 return false; 655 } 656 } 657 658 /** 659 * Is the condition code a floating point compare? 660 * @return <code>true</code> if it is or <code>false</code> if it is not 661 */ 662 public boolean isFLOATINGPOINT() { 663 switch (value) { 664 case CMPL_EQUAL: 665 case CMPL_GREATER: 666 case CMPG_LESS: 667 case CMPL_GREATER_EQUAL: 668 case CMPG_LESS_EQUAL: 669 case CMPL_NOT_EQUAL: 670 case CMPL_LESS: 671 case CMPG_GREATER_EQUAL: 672 case CMPG_GREATER: 673 case CMPL_LESS_EQUAL: 674 return true; 675 default: 676 return false; 677 } 678 } 679 680 /** 681 * Will this floating point compare branch if the results are 682 * unordered? 683 * @return <code>true</code> if it is or <code>false</code> if it is not 684 */ 685 public boolean branchIfUnordered() { 686 switch (value) { 687 case CMPL_EQUAL: 688 case CMPL_GREATER: 689 case CMPG_LESS: 690 case CMPL_GREATER_EQUAL: 691 case CMPG_LESS_EQUAL: 692 return false; 693 case CMPL_NOT_EQUAL: 694 case CMPL_LESS: 695 case CMPG_GREATER_EQUAL: 696 case CMPG_GREATER: 697 case CMPL_LESS_EQUAL: 698 return true; 699 default: 700 throw new OptimizingCompilerException("invalid condition " + this); 701 } 702 } 703 704 /** 705 * Convert this integer compare to a floating point cmpl 706 * compare. Used during BC2IR. 707 */ 708 public void translateCMPL() { 709 switch (value) { 710 case EQUAL: 711 value = CMPL_EQUAL; 712 break; 713 case NOT_EQUAL: 714 value = CMPL_NOT_EQUAL; 715 break; 716 case LESS: 717 value = CMPL_LESS; 718 break; 719 case GREATER_EQUAL: 720 value = CMPL_GREATER_EQUAL; 721 break; 722 case GREATER: 723 value = CMPL_GREATER; 724 break; 725 case LESS_EQUAL: 726 value = CMPL_LESS_EQUAL; 727 break; 728 default: 729 throw new OptimizingCompilerException("invalid condition " + this); 730 } 731 } 732 733 /** 734 * Convert this integer compare to a floating point cmpg 735 * compare. Used during BC2IR. 736 */ 737 public void translateCMPG() { 738 switch (value) { 739 case EQUAL: 740 value = CMPL_EQUAL; 741 break; 742 case NOT_EQUAL: 743 value = CMPL_NOT_EQUAL; 744 break; 745 case LESS: 746 value = CMPG_LESS; 747 break; 748 case GREATER_EQUAL: 749 value = CMPG_GREATER_EQUAL; 750 break; 751 case GREATER: 752 value = CMPG_GREATER; 753 break; 754 case LESS_EQUAL: 755 value = CMPG_LESS_EQUAL; 756 break; 757 default: 758 throw new OptimizingCompilerException("invalid condition " + this); 759 } 760 } 761 762 /** 763 * Convert this floating point compare to the equivalent unsigned 764 * integer compare. Used during IA-32 BURS.<p> 765 * 766 * NB this doesn't respect ordered/unordered operation, so it 767 * should only be used when it's safe to. 768 * 769 * @return this 770 */ 771 public ConditionOperand translateUNSIGNED() { 772 switch (value) { 773 case CMPL_EQUAL: value = EQUAL; break; 774 case CMPL_GREATER: value = HIGHER; break; 775 case CMPG_LESS: value = LOWER; break; 776 case CMPL_GREATER_EQUAL: value = HIGHER_EQUAL; break; 777 case CMPG_LESS_EQUAL: value = LOWER_EQUAL; break; 778 case CMPL_NOT_EQUAL: value = NOT_EQUAL; break; 779 case CMPL_LESS: value = LOWER; break; 780 case CMPG_GREATER_EQUAL: value = HIGHER_EQUAL; break; 781 case CMPG_GREATER: value = HIGHER; break; 782 case CMPL_LESS_EQUAL: value = LOWER_EQUAL; break; 783 default: 784 throw new OptimizingCompilerException("invalid condition " + this); 785 } 786 return this; 787 } 788 789 @Override 790 public Operand copy() { 791 return new ConditionOperand(value); 792 } 793 794 @Override 795 public boolean similar(Operand op) { 796 return (op instanceof ConditionOperand) && (((ConditionOperand) op).value == value); 797 } 798 799 /** 800 * Given two operands, evaluate the condition on them. 801 * 802 * @param v1 first operand to condition 803 * @param v2 second operand to condition 804 * @return <code>TRUE</code> if (v1 cond v2) or 805 * <code>FALSE</code> if !(v1 cond v2) or 806 * <code>UNKNOWN</code> 807 */ 808 public int evaluate(Operand v1, Operand v2) { 809 if (v1.isAddressConstant()) { 810 if (v2.isAddressConstant()) { 811 return evaluate(v1.asAddressConstant().value, v2.asAddressConstant().value); 812 } else if (v2.isNullConstant()) { 813 return evaluate(v1.asAddressConstant().value, Address.zero()); 814 } else if (v2.isIntConstant()) { 815 return evaluate(v1.asAddressConstant().value, Address.fromIntSignExtend(v2.asIntConstant().value)); 816 } else if (v2.isObjectConstant() && !v2.isMovableObjectConstant()) { 817 return evaluate(v1.asAddressConstant().value, 818 Magic.objectAsAddress(v2.asObjectConstant().value)); 819 } 820 } else if (v1.isIntConstant()) { 821 if (v2.isIntConstant()) { 822 return evaluate(v1.asIntConstant().value, v2.asIntConstant().value); 823 } else if (v2.isNullConstant()) { 824 return evaluate(v1.asIntConstant().value, 0); 825 } else if (v2.isAddressConstant()) { 826 return evaluate(Address.fromIntSignExtend(v1.asIntConstant().value), v2.asAddressConstant().value); 827 } else if (v2.isObjectConstant() && !v2.isMovableObjectConstant()) { 828 return evaluate(Address.fromIntSignExtend(v1.asIntConstant().value), 829 Magic.objectAsAddress(v2.asObjectConstant().value)); 830 } 831 } else if (v1.isLongConstant()) { 832 if (v2.isLongConstant()) { 833 return evaluate(v1.asLongConstant().value, v2.asLongConstant().value); 834 } 835 } else if (v1.isFloatConstant()) { 836 if (v2.isFloatConstant()) { 837 return evaluate(v1.asFloatConstant().value, v2.asFloatConstant().value); 838 } 839 } else if (v1.isDoubleConstant()) { 840 if (v2.isDoubleConstant()) { 841 return evaluate(v1.asDoubleConstant().value, v2.asDoubleConstant().value); 842 } 843 } else if (v1.isObjectConstant()) { 844 if (v2.isObjectConstant()) { 845 if (!v1.isMovableObjectConstant() && !v2.isMovableObjectConstant()) { 846 return evaluate(Magic.objectAsAddress(v1.asObjectConstant().value), 847 Magic.objectAsAddress(v2.asObjectConstant().value)); 848 } else if (isEQUAL()) { 849 return (v1.asObjectConstant().value == v2.asObjectConstant().value) ? TRUE : FALSE; 850 } else if (isNOT_EQUAL()) { 851 return (v1.asObjectConstant().value != v2.asObjectConstant().value) ? TRUE : FALSE; 852 } 853 } 854 if (v2.isNullConstant() || (v2.isIntConstant() && v2.asIntConstant().value == 0)) { 855 return evaluate(1,0); 856 } 857 if (!v1.isMovableObjectConstant()) { 858 if (v2.isIntConstant()) { 859 return evaluate(Magic.objectAsAddress(v1.asObjectConstant().value), 860 Address.fromIntSignExtend(v2.asIntConstant().value)); 861 } else if (v2.isAddressConstant()) { 862 return evaluate(Magic.objectAsAddress(v1.asObjectConstant().value), 863 v2.asAddressConstant().value); 864 } else if (v2.isNullConstant()) { 865 return evaluate(Magic.objectAsAddress(v1.asObjectConstant().value), 866 Address.zero()); 867 } 868 } 869 } else if (v1.isNullConstant()) { 870 if (v2.isNullConstant()) { 871 return evaluate(0, 0); 872 } else if (v2.isIntConstant()) { 873 return evaluate(0, v2.asIntConstant().value); 874 } else if (v2.isAddressConstant()) { 875 return evaluate(Address.zero(), v2.asAddressConstant().value); 876 } else if (v2.isObjectConstant()) { 877 if (!v2.isMovableObjectConstant()) { 878 return evaluate(Address.zero(), 879 Magic.objectAsAddress(v2.asObjectConstant().value)); 880 } else if (isEQUAL()) { 881 return FALSE; 882 } else if (isNOT_EQUAL()) { 883 return TRUE; 884 } 885 } 886 } else if (v1.similar(v2) && !isFLOATINGPOINT()) { 887 // comparisons of identical operands can be evaluated, except 888 // for floating point NaN cases 889 switch (value) { 890 case EQUAL: 891 case GREATER_EQUAL: 892 case LESS_EQUAL: 893 case HIGHER_EQUAL: 894 case LOWER_EQUAL: 895 return TRUE; 896 case NOT_EQUAL: 897 case LESS: 898 case GREATER: 899 case HIGHER: 900 case LOWER: 901 case BORROW_FROM_SUB: 902 case NO_BORROW_FROM_SUB: 903 case BORROW_FROM_RSUB: 904 case NO_BORROW_FROM_RSUB: 905 case OVERFLOW_FROM_SUB: 906 case NO_OVERFLOW_FROM_SUB: 907 case OVERFLOW_FROM_RSUB: 908 case NO_OVERFLOW_FROM_RSUB: 909 return FALSE; 910 case CARRY_FROM_ADD: 911 case NO_CARRY_FROM_ADD: 912 case OVERFLOW_FROM_ADD: 913 case NO_OVERFLOW_FROM_ADD: 914 case BIT_TEST: 915 case NO_BIT_TEST: 916 case RBIT_TEST: 917 case NO_RBIT_TEST: 918 case OVERFLOW_FROM_MUL: 919 case NO_OVERFLOW_FROM_MUL: 920 return UNKNOWN; 921 default: 922 throw new OptimizingCompilerException("invalid condition " + this); 923 } 924 } 925 return UNKNOWN; 926 } 927 928 /** 929 * Given two ints, evaluate the condition on them. 930 * 931 * @param v1 first operand to condition 932 * @param v2 second operand to condition 933 * @return <code>TRUE</code> if (v1 cond v2) or 934 * <code>FALSE</code> if !(v1 cond v2) or 935 * <code>UNKNOWN</code> 936 */ 937 public int evaluate(int v1, int v2) { 938 switch (value) { 939 case EQUAL: return (v1 == v2) ? TRUE : FALSE; 940 case NOT_EQUAL: return (v1 != v2) ? TRUE : FALSE; 941 case GREATER: return (v1 > v2) ? TRUE : FALSE; 942 case LESS: return (v1 < v2) ? TRUE : FALSE; 943 case GREATER_EQUAL: return (v1 >= v2) ? TRUE : FALSE; 944 case LESS_EQUAL: return (v1 <= v2) ? TRUE : FALSE; 945 case LOWER: return lower(v1, v2) ? TRUE : FALSE; 946 case LOWER_EQUAL: return lower_equal(v1, v2) ? TRUE : FALSE; 947 case HIGHER: return higher(v1, v2) ? TRUE : FALSE; 948 case HIGHER_EQUAL: return higher_equal(v1, v2) ? TRUE : FALSE; 949 case CARRY_FROM_ADD: return carry_from_add(v1, v2) ? TRUE : FALSE; 950 case NO_CARRY_FROM_ADD: return carry_from_add(v1, v2) ? FALSE : TRUE; 951 case OVERFLOW_FROM_ADD: return overflow_from_add(v1, v2) ? TRUE : FALSE; 952 case NO_OVERFLOW_FROM_ADD: return overflow_from_add(v1, v2) ? FALSE : TRUE; 953 case BORROW_FROM_SUB: return borrow_from_sub(v1, v2) ? TRUE : FALSE; 954 case NO_BORROW_FROM_SUB: return borrow_from_sub(v1, v2) ? FALSE : TRUE; 955 case BORROW_FROM_RSUB: return borrow_from_sub(v2, v1) ? TRUE : FALSE; 956 case NO_BORROW_FROM_RSUB: return borrow_from_sub(v2, v1) ? FALSE : TRUE; 957 case OVERFLOW_FROM_SUB: return overflow_from_sub(v1, v2) ? TRUE : FALSE; 958 case NO_OVERFLOW_FROM_SUB: return overflow_from_sub(v1, v2) ? FALSE : TRUE; 959 case OVERFLOW_FROM_RSUB: return overflow_from_sub(v2, v1) ? TRUE : FALSE; 960 case NO_OVERFLOW_FROM_RSUB: return overflow_from_sub(v2, v1) ? FALSE : TRUE; 961 case BIT_TEST: return bit_test(v1, v2) ? TRUE : FALSE; 962 case NO_BIT_TEST: return bit_test(v1, v2) ? FALSE : TRUE; 963 case RBIT_TEST: return bit_test(v2, v1) ? TRUE : FALSE; 964 case NO_RBIT_TEST: return bit_test(v2, v1) ? FALSE : TRUE; 965 case OVERFLOW_FROM_MUL: return overflow_from_mul(v1, v2) ? TRUE : FALSE; 966 case NO_OVERFLOW_FROM_MUL: return overflow_from_mul(v1, v2) ? FALSE : TRUE; 967 } 968 throw new OptimizingCompilerException("invalid condition " + this); 969 } 970 971 /** 972 * Given two longs, evaluate the condition on them. 973 * 974 * @param v1 first operand to condition 975 * @param v2 second operand to condition 976 * @return <code>TRUE</code> if (v1 cond v2) or 977 * <code>FALSE</code> if !(v1 cond v2) or 978 * <code>UNKNOWN</code> 979 */ 980 public int evaluate(long v1, long v2) { 981 switch (value) { 982 case EQUAL: return (v1 == v2) ? TRUE : FALSE; 983 case NOT_EQUAL: return (v1 != v2) ? TRUE : FALSE; 984 case GREATER: return (v1 > v2) ? TRUE : FALSE; 985 case LESS: return (v1 < v2) ? TRUE : FALSE; 986 case GREATER_EQUAL: return (v1 >= v2) ? TRUE : FALSE; 987 case LESS_EQUAL: return (v1 <= v2) ? TRUE : FALSE; 988 } 989 throw new OptimizingCompilerException("invalid condition " + this); 990 } 991 992 /** 993 * Given two floats, evaluate the condition on them. 994 * 995 * @param v1 first operand to condition 996 * @param v2 second operand to condition 997 * @return <code>true</code> if (v1 cond v2) or 998 * <code>false</code> otherwise 999 */ 1000 public int evaluate(float v1, float v2) { 1001 switch (value) { 1002 // Return FALSE when UNORDERED 1003 case CMPL_EQUAL: return (v1 == v2) ? TRUE : FALSE; 1004 case CMPL_GREATER: return (v1 > v2) ? TRUE : FALSE; 1005 case CMPG_LESS: return (v1 < v2) ? TRUE : FALSE; 1006 case CMPL_GREATER_EQUAL: return (v1 >= v2) ? TRUE : FALSE; 1007 case CMPG_LESS_EQUAL: return (v1 <= v2) ? TRUE : FALSE; 1008 // Return TRUE when UNORDERED 1009 case CMPL_NOT_EQUAL: return (v1 == v2) ? FALSE : TRUE; 1010 case CMPL_LESS: return (v1 >= v2) ? FALSE : TRUE; 1011 case CMPG_GREATER_EQUAL: return (v1 < v2) ? FALSE : TRUE; 1012 case CMPG_GREATER: return (v1 <= v2) ? FALSE : TRUE; 1013 case CMPL_LESS_EQUAL: return (v1 > v2) ? FALSE : TRUE; 1014 } 1015 throw new OptimizingCompilerException("invalid condition " + this); 1016 } 1017 1018 /** 1019 * Given two doubles, evaluate the condition on them. 1020 * 1021 * @param v1 first operand to condition 1022 * @param v2 second operand to condition 1023 * @return <code>true</code> if (v1 cond v2) or 1024 * <code>false</code> otherwise 1025 */ 1026 public int evaluate(double v1, double v2) { 1027 switch (value) { 1028 // Return FALSE when UNORDERED 1029 case CMPL_EQUAL: return (v1 == v2) ? TRUE : FALSE; 1030 case CMPL_GREATER: return (v1 > v2) ? TRUE : FALSE; 1031 case CMPG_LESS: return (v1 < v2) ? TRUE : FALSE; 1032 case CMPL_GREATER_EQUAL: return (v1 >= v2) ? TRUE : FALSE; 1033 case CMPG_LESS_EQUAL: return (v1 <= v2) ? TRUE : FALSE; 1034 // Return TRUE when UNORDERED 1035 case CMPL_NOT_EQUAL: return (v1 == v2) ? FALSE : TRUE; 1036 case CMPL_LESS: return (v1 >= v2) ? FALSE : TRUE; 1037 case CMPG_GREATER_EQUAL: return (v1 < v2) ? FALSE : TRUE; 1038 case CMPG_GREATER: return (v1 <= v2) ? FALSE : TRUE; 1039 case CMPL_LESS_EQUAL: return (v1 > v2) ? FALSE : TRUE; 1040 } 1041 throw new OptimizingCompilerException("invalid condition " + this); 1042 } 1043 1044 /** 1045 * Given two Addresses, evaluate the condition on them. 1046 * 1047 * @param v1 first operand to condition 1048 * @param v2 second operand to condition 1049 * @return <code>TRUE</code> if (v1 cond v2) or 1050 * <code>FALSE</code> if !(v1 cond v2) or 1051 * <code>UNKNOWN</code> 1052 */ 1053 public int evaluate(Address v1, Address v2) { 1054 switch (value) { 1055 case EQUAL: return (v1.EQ(v2)) ? TRUE : FALSE; 1056 case NOT_EQUAL: return (v1.NE(v2)) ? TRUE : FALSE; 1057 case GREATER: return (v1.toWord().toOffset().sGT(v2.toWord().toOffset())) ? TRUE : FALSE; 1058 case LESS: return (v1.toWord().toOffset().sLT(v2.toWord().toOffset())) ? TRUE : FALSE; 1059 case GREATER_EQUAL: return (v1.toWord().toOffset().sGE(v2.toWord().toOffset())) ? TRUE : FALSE; 1060 case LESS_EQUAL: return (v1.toWord().toOffset().sLE(v2.toWord().toOffset())) ? TRUE : FALSE; 1061 case LOWER: return (v1.LT(v2)) ? TRUE : FALSE; 1062 case LOWER_EQUAL: return (v1.LE(v2)) ? TRUE : FALSE; 1063 case HIGHER: return (v1.GT(v2)) ? TRUE : FALSE; 1064 case HIGHER_EQUAL: return (v1.GE(v2)) ? TRUE : FALSE; 1065 } 1066 throw new OptimizingCompilerException("invalid condition " + this); 1067 } 1068 1069 /** 1070 * Flip the direction of the condition. Typical use is if you want to 1071 * change the direction of a branch. i.e. to transform: 1072 * <code> 1073 * if (condition) goto A 1074 * goto B 1075 * A: 1076 * </code> 1077 * into: 1078 * <code> 1079 * if (!condition) goto B 1080 * A: 1081 * </code> 1082 * Note that this is not the same as calling {@link #flipOperands}. 1083 * 1084 * @return this 1085 */ 1086 public ConditionOperand flipCode() { 1087 switch (value) { 1088 case EQUAL: value = NOT_EQUAL; break; 1089 case NOT_EQUAL: value = EQUAL; break; 1090 case LESS: value = GREATER_EQUAL; break; 1091 case LESS_EQUAL: value = GREATER; break; 1092 case GREATER: value = LESS_EQUAL; break; 1093 case GREATER_EQUAL: value = LESS; break; 1094 1095 case HIGHER: value = LOWER_EQUAL; break; 1096 case LOWER: value = HIGHER_EQUAL; break; 1097 case HIGHER_EQUAL: value = LOWER; break; 1098 case LOWER_EQUAL: value = HIGHER; break; 1099 1100 case CMPL_EQUAL: value = CMPL_NOT_EQUAL; break; 1101 case CMPL_GREATER: value = CMPL_LESS_EQUAL; break; 1102 case CMPG_LESS: value = CMPG_GREATER_EQUAL; break; 1103 case CMPL_GREATER_EQUAL: value = CMPL_LESS; break; 1104 case CMPG_LESS_EQUAL: value = CMPG_GREATER; break; 1105 case CMPL_NOT_EQUAL: value = CMPL_EQUAL; break; 1106 case CMPL_LESS: value = CMPL_GREATER_EQUAL; break; 1107 case CMPG_GREATER_EQUAL: value = CMPG_LESS; break; 1108 case CMPG_GREATER: value = CMPG_LESS_EQUAL; break; 1109 case CMPL_LESS_EQUAL: value = CMPL_GREATER; break; 1110 1111 case CARRY_FROM_ADD: value = NO_CARRY_FROM_ADD; break; 1112 case NO_CARRY_FROM_ADD: value = CARRY_FROM_ADD; break; 1113 1114 case OVERFLOW_FROM_ADD: value = NO_OVERFLOW_FROM_ADD; break; 1115 case NO_OVERFLOW_FROM_ADD: value = OVERFLOW_FROM_ADD; break; 1116 1117 case BORROW_FROM_SUB: value = NO_BORROW_FROM_SUB; break; 1118 case NO_BORROW_FROM_SUB: value = BORROW_FROM_SUB; break; 1119 case BORROW_FROM_RSUB: value = NO_BORROW_FROM_RSUB; break; 1120 case NO_BORROW_FROM_RSUB: value = BORROW_FROM_RSUB; break; 1121 1122 case OVERFLOW_FROM_SUB: value = NO_OVERFLOW_FROM_SUB; break; 1123 case NO_OVERFLOW_FROM_SUB: value = OVERFLOW_FROM_SUB; break; 1124 case OVERFLOW_FROM_RSUB: value = NO_OVERFLOW_FROM_RSUB; break; 1125 case NO_OVERFLOW_FROM_RSUB: value = OVERFLOW_FROM_RSUB; break; 1126 1127 case BIT_TEST: value = NO_BIT_TEST; break; 1128 case NO_BIT_TEST: value = BIT_TEST; break; 1129 case RBIT_TEST: value = NO_RBIT_TEST; break; 1130 case NO_RBIT_TEST: value = RBIT_TEST; break; 1131 1132 case OVERFLOW_FROM_MUL: value = NO_OVERFLOW_FROM_MUL; break; 1133 case NO_OVERFLOW_FROM_MUL: value = OVERFLOW_FROM_MUL; break; 1134 1135 default: 1136 OptimizingCompilerException.UNREACHABLE(); 1137 } 1138 return this; 1139 } 1140 1141 /** 1142 * Change the condition code to allow the order of the operands to 1143 * be flipped. i.e. So that: 1144 * <code> 1145 * if x < y then goto A 1146 * </code> 1147 * becomes: 1148 * <code> 1149 * if y > x then goto A 1150 * </code> 1151 * Note that this is not the same as calling {@link #flipCode}. 1152 * 1153 * @return this 1154 */ 1155 public ConditionOperand flipOperands() { 1156 switch (value) { 1157 case EQUAL: value = EQUAL; break; 1158 case NOT_EQUAL: value = NOT_EQUAL; break; 1159 case LESS: value = GREATER; break; 1160 case LESS_EQUAL: value = GREATER_EQUAL; break; 1161 case GREATER: value = LESS; break; 1162 case GREATER_EQUAL: value = LESS_EQUAL; break; 1163 1164 case HIGHER: value = LOWER; break; 1165 case LOWER: value = HIGHER; break; 1166 case HIGHER_EQUAL: value = LOWER_EQUAL; break; 1167 case LOWER_EQUAL: value = HIGHER_EQUAL; break; 1168 1169 case CMPL_EQUAL: value = CMPL_EQUAL; break; 1170 case CMPL_GREATER: value = CMPG_LESS; break; 1171 case CMPG_LESS: value = CMPL_GREATER; break; 1172 case CMPL_GREATER_EQUAL: value = CMPG_LESS_EQUAL; break; 1173 case CMPG_LESS_EQUAL: value = CMPL_GREATER_EQUAL; break; 1174 case CMPL_NOT_EQUAL: value = CMPL_NOT_EQUAL; break; 1175 case CMPL_LESS: value = CMPG_GREATER; break; 1176 case CMPG_GREATER_EQUAL: value = CMPL_LESS_EQUAL; break; 1177 case CMPG_GREATER: value = CMPL_LESS; break; 1178 case CMPL_LESS_EQUAL: value = CMPG_GREATER_EQUAL; break; 1179 1180 case CARRY_FROM_ADD: break; // add is commutative 1181 case NO_CARRY_FROM_ADD: break; 1182 1183 case OVERFLOW_FROM_ADD: break; 1184 case NO_OVERFLOW_FROM_ADD: break; 1185 1186 case BORROW_FROM_SUB: value = BORROW_FROM_RSUB; break; 1187 case NO_BORROW_FROM_SUB: value = NO_BORROW_FROM_RSUB; break; 1188 case BORROW_FROM_RSUB: value = BORROW_FROM_SUB; break; 1189 case NO_BORROW_FROM_RSUB: value = NO_BORROW_FROM_SUB; break; 1190 1191 case OVERFLOW_FROM_SUB: value = OVERFLOW_FROM_RSUB; break; 1192 case NO_OVERFLOW_FROM_SUB: value = NO_OVERFLOW_FROM_RSUB; break; 1193 case OVERFLOW_FROM_RSUB: value = OVERFLOW_FROM_SUB; break; 1194 case NO_OVERFLOW_FROM_RSUB: value = NO_OVERFLOW_FROM_SUB; break; 1195 1196 case BIT_TEST: value = RBIT_TEST; break; 1197 case NO_BIT_TEST: value = NO_RBIT_TEST; break; 1198 case RBIT_TEST: value = BIT_TEST; break; 1199 case NO_RBIT_TEST: value = NO_BIT_TEST; break; 1200 1201 case OVERFLOW_FROM_MUL: break; // mul is commutative 1202 case NO_OVERFLOW_FROM_MUL: break; 1203 1204 default: 1205 OptimizingCompilerException.UNREACHABLE(); 1206 } 1207 return this; 1208 } 1209 1210 /** 1211 * Returns the string representation of this operand. Postfix 1212 * meanings: 1213 * <ul><li>U - unsigned comparison</li> 1214 * <li>F - floating point compare that doesn't branch when 1215 * operands are unordered</li> 1216 * <li>FU - floating point compare that does branch when 1217 * operands are unordered</li> 1218 * </ul> 1219 * 1220 * @return a string representation of this operand. 1221 */ 1222 @Override 1223 public String toString() { 1224 switch (value) { 1225 case EQUAL: return "=="; 1226 case NOT_EQUAL: return "!="; 1227 case LESS: return "<"; 1228 case LESS_EQUAL: return "<="; 1229 case GREATER: return ">"; 1230 case GREATER_EQUAL: return ">="; 1231 1232 case HIGHER: return ">U"; 1233 case LOWER: return "<U"; 1234 case HIGHER_EQUAL: return ">=U"; 1235 case LOWER_EQUAL: return "<=U"; 1236 1237 case CMPL_EQUAL: return "==F"; 1238 case CMPL_GREATER: return ">F"; 1239 case CMPG_LESS: return "<F"; 1240 case CMPL_GREATER_EQUAL: return ">=F"; 1241 case CMPG_LESS_EQUAL: return "<=F"; 1242 1243 case CMPL_NOT_EQUAL: return "!=FU"; 1244 case CMPL_LESS: return "<FU"; 1245 case CMPG_GREATER_EQUAL: return ">=FU"; 1246 case CMPG_GREATER: return ">FU"; 1247 case CMPL_LESS_EQUAL: return "<=FU"; 1248 1249 case CARRY_FROM_ADD: return "carry(+)"; 1250 case NO_CARRY_FROM_ADD: return "nocarry(+)"; 1251 1252 case OVERFLOW_FROM_ADD: return "overflow(+)"; 1253 case NO_OVERFLOW_FROM_ADD: return "nooverflow(+)"; 1254 1255 case BORROW_FROM_SUB: return "borrow(-)"; 1256 case NO_BORROW_FROM_SUB: return "noborrow(-)"; 1257 case BORROW_FROM_RSUB: return "borrow(r-)"; 1258 case NO_BORROW_FROM_RSUB: return "noborrow(r-)"; 1259 1260 case OVERFLOW_FROM_SUB: return "overflow(-)"; 1261 case NO_OVERFLOW_FROM_SUB: return "nooverflow(-)"; 1262 case OVERFLOW_FROM_RSUB: return "overflow(r-)"; 1263 case NO_OVERFLOW_FROM_RSUB: return "nooverflow(r-)"; 1264 1265 case BIT_TEST: return "bt"; 1266 case NO_BIT_TEST: return "!bt"; 1267 case RBIT_TEST: return "rbt"; 1268 case NO_RBIT_TEST: return "!rbt"; 1269 1270 case OVERFLOW_FROM_MUL: return "overflow(*)"; 1271 case NO_OVERFLOW_FROM_MUL: return "nooverflow(*)"; 1272 1273 default: return "UNKNOWN"; 1274 } 1275 } 1276}