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 |