| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 __ Mov(constants, Operand(ExternalReference::math_exp_constants(0))); | 522 __ Mov(constants, Operand(ExternalReference::math_exp_constants(0))); |
| 523 | 523 |
| 524 // We have to do a four-way split here: | 524 // We have to do a four-way split here: |
| 525 // - If input <= about -708.4, the output always rounds to zero. | 525 // - If input <= about -708.4, the output always rounds to zero. |
| 526 // - If input >= about 709.8, the output always rounds to +infinity. | 526 // - If input >= about 709.8, the output always rounds to +infinity. |
| 527 // - If the input is NaN, the output is NaN. | 527 // - If the input is NaN, the output is NaN. |
| 528 // - Otherwise, the result needs to be calculated. | 528 // - Otherwise, the result needs to be calculated. |
| 529 Label result_is_finite_non_zero; | 529 Label result_is_finite_non_zero; |
| 530 // Assert that we can load offset 0 (the small input threshold) and offset 1 | 530 // Assert that we can load offset 0 (the small input threshold) and offset 1 |
| 531 // (the large input threshold) with a single ldp. | 531 // (the large input threshold) with a single ldp. |
| 532 ASSERT(kDRegSizeInBytes == (ExpConstant(constants, 1).offset() - | 532 ASSERT(kDRegSize == (ExpConstant(constants, 1).offset() - |
| 533 ExpConstant(constants, 0).offset())); | 533 ExpConstant(constants, 0).offset())); |
| 534 __ Ldp(double_temp1, double_temp2, ExpConstant(constants, 0)); | 534 __ Ldp(double_temp1, double_temp2, ExpConstant(constants, 0)); |
| 535 | 535 |
| 536 __ Fcmp(input, double_temp1); | 536 __ Fcmp(input, double_temp1); |
| 537 __ Fccmp(input, double_temp2, NoFlag, hi); | 537 __ Fccmp(input, double_temp2, NoFlag, hi); |
| 538 // At this point, the condition flags can be in one of five states: | 538 // At this point, the condition flags can be in one of five states: |
| 539 // NZCV | 539 // NZCV |
| 540 // 1000 -708.4 < input < 709.8 result = exp(input) | 540 // 1000 -708.4 < input < 709.8 result = exp(input) |
| 541 // 0110 input == 709.8 result = +infinity | 541 // 0110 input == 709.8 result = +infinity |
| 542 // 0010 input > 709.8 result = +infinity | 542 // 0010 input > 709.8 result = +infinity |
| (...skipping 11 matching lines...) Expand all Loading... |
| 554 // Select between +0.0 and +infinity. 'lo' tests C == 0. | 554 // Select between +0.0 and +infinity. 'lo' tests C == 0. |
| 555 __ Fcsel(result, double_temp1, double_temp2, lo); | 555 __ Fcsel(result, double_temp1, double_temp2, lo); |
| 556 // Select between {+0.0 or +infinity} and input. 'vc' tests V == 0. | 556 // Select between {+0.0 or +infinity} and input. 'vc' tests V == 0. |
| 557 __ Fcsel(result, result, input, vc); | 557 __ Fcsel(result, result, input, vc); |
| 558 __ B(&done); | 558 __ B(&done); |
| 559 | 559 |
| 560 // The rest is magic, as described in InitializeMathExpData(). | 560 // The rest is magic, as described in InitializeMathExpData(). |
| 561 __ Bind(&result_is_finite_non_zero); | 561 __ Bind(&result_is_finite_non_zero); |
| 562 | 562 |
| 563 // Assert that we can load offset 3 and offset 4 with a single ldp. | 563 // Assert that we can load offset 3 and offset 4 with a single ldp. |
| 564 ASSERT(kDRegSizeInBytes == (ExpConstant(constants, 4).offset() - | 564 ASSERT(kDRegSize == (ExpConstant(constants, 4).offset() - |
| 565 ExpConstant(constants, 3).offset())); | 565 ExpConstant(constants, 3).offset())); |
| 566 __ Ldp(double_temp1, double_temp3, ExpConstant(constants, 3)); | 566 __ Ldp(double_temp1, double_temp3, ExpConstant(constants, 3)); |
| 567 __ Fmadd(double_temp1, double_temp1, input, double_temp3); | 567 __ Fmadd(double_temp1, double_temp1, input, double_temp3); |
| 568 __ Fmov(temp2.W(), double_temp1.S()); | 568 __ Fmov(temp2.W(), double_temp1.S()); |
| 569 __ Fsub(double_temp1, double_temp1, double_temp3); | 569 __ Fsub(double_temp1, double_temp1, double_temp3); |
| 570 | 570 |
| 571 // Assert that we can load offset 5 and offset 6 with a single ldp. | 571 // Assert that we can load offset 5 and offset 6 with a single ldp. |
| 572 ASSERT(kDRegSizeInBytes == (ExpConstant(constants, 6).offset() - | 572 ASSERT(kDRegSize == (ExpConstant(constants, 6).offset() - |
| 573 ExpConstant(constants, 5).offset())); | 573 ExpConstant(constants, 5).offset())); |
| 574 __ Ldp(double_temp2, double_temp3, ExpConstant(constants, 5)); | 574 __ Ldp(double_temp2, double_temp3, ExpConstant(constants, 5)); |
| 575 // TODO(jbramley): Consider using Fnmsub here. | 575 // TODO(jbramley): Consider using Fnmsub here. |
| 576 __ Fmul(double_temp1, double_temp1, double_temp2); | 576 __ Fmul(double_temp1, double_temp1, double_temp2); |
| 577 __ Fsub(double_temp1, double_temp1, input); | 577 __ Fsub(double_temp1, double_temp1, input); |
| 578 | 578 |
| 579 __ Fmul(double_temp2, double_temp1, double_temp1); | 579 __ Fmul(double_temp2, double_temp1, double_temp1); |
| 580 __ Fsub(double_temp3, double_temp3, double_temp1); | 580 __ Fsub(double_temp3, double_temp3, double_temp1); |
| 581 __ Fmul(double_temp3, double_temp3, double_temp2); | 581 __ Fmul(double_temp3, double_temp3, double_temp2); |
| 582 | 582 |
| 583 __ Mov(temp1.W(), Operand(temp2.W(), LSR, 11)); | 583 __ Mov(temp1.W(), Operand(temp2.W(), LSR, 11)); |
| 584 | 584 |
| 585 __ Ldr(double_temp2, ExpConstant(constants, 7)); | 585 __ Ldr(double_temp2, ExpConstant(constants, 7)); |
| 586 // TODO(jbramley): Consider using Fnmsub here. | 586 // TODO(jbramley): Consider using Fnmsub here. |
| 587 __ Fmul(double_temp3, double_temp3, double_temp2); | 587 __ Fmul(double_temp3, double_temp3, double_temp2); |
| 588 __ Fsub(double_temp3, double_temp3, double_temp1); | 588 __ Fsub(double_temp3, double_temp3, double_temp1); |
| 589 | 589 |
| 590 // The 8th constant is 1.0, so use an immediate move rather than a load. | 590 // The 8th constant is 1.0, so use an immediate move rather than a load. |
| 591 // We can't generate a runtime assertion here as we would need to call Abort | 591 // We can't generate a runtime assertion here as we would need to call Abort |
| 592 // in the runtime and we don't have an Isolate when we generate this code. | 592 // in the runtime and we don't have an Isolate when we generate this code. |
| 593 __ Fmov(double_temp2, 1.0); | 593 __ Fmov(double_temp2, 1.0); |
| 594 __ Fadd(double_temp3, double_temp3, double_temp2); | 594 __ Fadd(double_temp3, double_temp3, double_temp2); |
| 595 | 595 |
| 596 __ And(temp2, temp2, 0x7ff); | 596 __ And(temp2, temp2, 0x7ff); |
| 597 __ Add(temp1, temp1, 0x3ff); | 597 __ Add(temp1, temp1, 0x3ff); |
| 598 | 598 |
| 599 // Do the final table lookup. | 599 // Do the final table lookup. |
| 600 __ Mov(temp3, Operand(ExternalReference::math_exp_log_table())); | 600 __ Mov(temp3, Operand(ExternalReference::math_exp_log_table())); |
| 601 | 601 |
| 602 __ Add(temp3, temp3, Operand(temp2, LSL, kDRegSizeInBytesLog2)); | 602 __ Add(temp3, temp3, Operand(temp2, LSL, kDRegSizeLog2)); |
| 603 __ Ldp(temp2.W(), temp3.W(), MemOperand(temp3)); | 603 __ Ldp(temp2.W(), temp3.W(), MemOperand(temp3)); |
| 604 __ Orr(temp1.W(), temp3.W(), Operand(temp1.W(), LSL, 20)); | 604 __ Orr(temp1.W(), temp3.W(), Operand(temp1.W(), LSL, 20)); |
| 605 __ Bfi(temp2, temp1, 32, 32); | 605 __ Bfi(temp2, temp1, 32, 32); |
| 606 __ Fmov(double_temp1, temp2); | 606 __ Fmov(double_temp1, temp2); |
| 607 | 607 |
| 608 __ Fmul(result, double_temp3, double_temp1); | 608 __ Fmul(result, double_temp3, double_temp1); |
| 609 | 609 |
| 610 __ Bind(&done); | 610 __ Bind(&done); |
| 611 } | 611 } |
| 612 | 612 |
| 613 #undef __ | 613 #undef __ |
| 614 | 614 |
| 615 } } // namespace v8::internal | 615 } } // namespace v8::internal |
| 616 | 616 |
| 617 #endif // V8_TARGET_ARCH_A64 | 617 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |