Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: src/arm/simulator-arm.cc

Issue 6368053: Implements DoubleToI on ARM. Refactor some VFP code at the same time and... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 2521 matching lines...) Expand 10 before | Expand all | Expand 10 after
2532 // Emulate FPSCR from the Simulator flags. 2532 // Emulate FPSCR from the Simulator flags.
2533 uint32_t fpscr = (n_flag_FPSCR_ << 31) | 2533 uint32_t fpscr = (n_flag_FPSCR_ << 31) |
2534 (z_flag_FPSCR_ << 30) | 2534 (z_flag_FPSCR_ << 30) |
2535 (c_flag_FPSCR_ << 29) | 2535 (c_flag_FPSCR_ << 29) |
2536 (v_flag_FPSCR_ << 28) | 2536 (v_flag_FPSCR_ << 28) |
2537 (inexact_vfp_flag_ << 4) | 2537 (inexact_vfp_flag_ << 4) |
2538 (underflow_vfp_flag_ << 3) | 2538 (underflow_vfp_flag_ << 3) |
2539 (overflow_vfp_flag_ << 2) | 2539 (overflow_vfp_flag_ << 2) |
2540 (div_zero_vfp_flag_ << 1) | 2540 (div_zero_vfp_flag_ << 1) |
2541 (inv_op_vfp_flag_ << 0) | 2541 (inv_op_vfp_flag_ << 0) |
2542 (FPSCR_rounding_mode_ << 22); 2542 (FPSCR_rounding_mode_);
2543 set_register(rt, fpscr); 2543 set_register(rt, fpscr);
2544 } 2544 }
2545 } else if ((instr->VLValue() == 0x0) && 2545 } else if ((instr->VLValue() == 0x0) &&
2546 (instr->VCValue() == 0x0) && 2546 (instr->VCValue() == 0x0) &&
2547 (instr->VAValue() == 0x7) && 2547 (instr->VAValue() == 0x7) &&
2548 (instr->Bits(19, 16) == 0x1)) { 2548 (instr->Bits(19, 16) == 0x1)) {
2549 // vmsr 2549 // vmsr
2550 uint32_t rt = instr->RtValue(); 2550 uint32_t rt = instr->RtValue();
2551 if (rt == pc) { 2551 if (rt == pc) {
2552 UNREACHABLE(); 2552 UNREACHABLE();
2553 } else { 2553 } else {
2554 uint32_t rt_value = get_register(rt); 2554 uint32_t rt_value = get_register(rt);
2555 n_flag_FPSCR_ = (rt_value >> 31) & 1; 2555 n_flag_FPSCR_ = (rt_value >> 31) & 1;
2556 z_flag_FPSCR_ = (rt_value >> 30) & 1; 2556 z_flag_FPSCR_ = (rt_value >> 30) & 1;
2557 c_flag_FPSCR_ = (rt_value >> 29) & 1; 2557 c_flag_FPSCR_ = (rt_value >> 29) & 1;
2558 v_flag_FPSCR_ = (rt_value >> 28) & 1; 2558 v_flag_FPSCR_ = (rt_value >> 28) & 1;
2559 inexact_vfp_flag_ = (rt_value >> 4) & 1; 2559 inexact_vfp_flag_ = (rt_value >> 4) & 1;
2560 underflow_vfp_flag_ = (rt_value >> 3) & 1; 2560 underflow_vfp_flag_ = (rt_value >> 3) & 1;
2561 overflow_vfp_flag_ = (rt_value >> 2) & 1; 2561 overflow_vfp_flag_ = (rt_value >> 2) & 1;
2562 div_zero_vfp_flag_ = (rt_value >> 1) & 1; 2562 div_zero_vfp_flag_ = (rt_value >> 1) & 1;
2563 inv_op_vfp_flag_ = (rt_value >> 0) & 1; 2563 inv_op_vfp_flag_ = (rt_value >> 0) & 1;
2564 FPSCR_rounding_mode_ = 2564 FPSCR_rounding_mode_ =
Søren Thygesen Gjesse 2011/02/03 09:07:17 4 char indent.
Rodolph Perfetta 2011/02/03 15:03:39 Done.
2565 static_cast<FPSCRRoundingModes>((rt_value >> 22) & 3); 2565 static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask);
2566 } 2566 }
2567 } else { 2567 } else {
2568 UNIMPLEMENTED(); // Not used by V8. 2568 UNIMPLEMENTED(); // Not used by V8.
2569 } 2569 }
2570 } 2570 }
2571 } 2571 }
2572 2572
2573 2573
2574 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( 2574 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
2575 Instruction* instr) { 2575 Instruction* instr) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2644 2644
2645 if (dst_precision == kSinglePrecision) { 2645 if (dst_precision == kSinglePrecision) {
2646 double val = get_double_from_d_register(src); 2646 double val = get_double_from_d_register(src);
2647 set_s_register_from_float(dst, static_cast<float>(val)); 2647 set_s_register_from_float(dst, static_cast<float>(val));
2648 } else { 2648 } else {
2649 float val = get_float_from_s_register(src); 2649 float val = get_float_from_s_register(src);
2650 set_d_register_from_double(dst, static_cast<double>(val)); 2650 set_d_register_from_double(dst, static_cast<double>(val));
2651 } 2651 }
2652 } 2652 }
2653 2653
2654 bool get_inv_op_vfp_flag(VFPRoundingMode mode,
2655 double val,
2656 bool unsigned_) {
2657 double max_uint = static_cast<double>(0xffffffffu);
2658 double max_int = static_cast<double>(kMaxInt);
2659 double min_int = static_cast<double>(kMinInt);
2660 // This code works because 32bit integers can be exactly represented by
2661 // ieee-754 64bit floating-point values.
2662 switch (mode) {
2663 case RN:
2664 return unsigned_ ? (val >= (max_uint + 0.5)) ||
2665 (val < -0.5) ||
Søren Thygesen Gjesse 2011/02/03 09:07:17 Please comment on what val != val checks. Maybe ha
Rodolph Perfetta 2011/02/03 15:03:39 made a separate check for NaN.
2666 (val != val)
2667 : (val >= (max_int + 0.5)) ||
2668 (val < (min_int - 0.5)) ||
2669 (val != val);
2670
2671 case RP:
2672 UNIMPLEMENTED();
2673 return false;
2674
2675 case RM:
2676 return unsigned_ ? (val >= (max_uint + 1.0)) ||
2677 (val < 0) ||
2678 (val != val)
2679 : (val >= (max_int + 1.0)) ||
2680 (val < min_int) ||
2681 (val != val);
2682
2683 case RZ:
2684 return unsigned_ ? (val >= (max_uint + 1.0)) ||
2685 (val <= -1) ||
2686 (val != val)
2687 : (val >= (max_int + 1.0)) ||
2688 (val <= (min_int - 1.0)) ||
2689 (val != val);
2690 default:
2691 UNREACHABLE();
2692 return false;
2693 }
2694 }
2695
2696
2697 // We call this function only if we had a vfp invalid exception.
2698 // It returns the correct saturated value.
2699 int VFPConversionSaturate(double val, bool unsigned_res) {
2700 if (val != val) {
2701 return 0;
2702 } else {
2703 if (unsigned_res) {
2704 return (val < 0) ? 0 : 0xffffffffu;
2705 } else {
2706 return (val < 0) ? kMinInt : kMaxInt;
2707 }
2708 }
2709 }
2710
2654 2711
2655 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { 2712 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
2656 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 2713 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
2714 (instr->Bits(27, 23) == 0x1D));
2657 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || 2715 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
2658 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); 2716 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
2659 2717
2660 // Conversion between floating-point and integer. 2718 // Conversion between floating-point and integer.
2661 bool to_integer = (instr->Bit(18) == 1); 2719 bool to_integer = (instr->Bit(18) == 1);
2662 2720
2663 VFPRegPrecision src_precision = kSinglePrecision; 2721 VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision
2664 if (instr->SzValue() == 1) { 2722 : kSinglePrecision;
2665 src_precision = kDoublePrecision;
2666 }
2667 2723
2668 if (to_integer) { 2724 if (to_integer) {
2669 bool unsigned_integer = (instr->Bit(16) == 0); 2725 // We are playing with code close to the C++ standard's limits below,
2670 FPSCRRoundingModes mode; 2726 // hence the very simple code and heavy checks.
2671 if (instr->Bit(7) != 1) { 2727 //
2672 // Use FPSCR defined rounding mode. 2728 // Note:
2673 mode = FPSCR_rounding_mode_; 2729 // C++ defines default type casting from floating point to integer as
2674 // Only RZ and RM modes are supported. 2730 // (close to) rounding toward zero ("fractional part discarded").
2675 ASSERT((mode == RM) || (mode == RZ));
2676 } else {
2677 // VFP uses round towards zero by default.
2678 mode = RZ;
2679 }
2680 2731
2681 int dst = instr->VFPDRegValue(kSinglePrecision); 2732 int dst = instr->VFPDRegValue(kSinglePrecision);
2682 int src = instr->VFPMRegValue(src_precision); 2733 int src = instr->VFPMRegValue(src_precision);
2683 int32_t kMaxInt = v8::internal::kMaxInt;
2684 int32_t kMinInt = v8::internal::kMinInt;
2685 switch (mode) {
2686 case RM:
2687 if (src_precision == kDoublePrecision) {
2688 double val = get_double_from_d_register(src);
2689 2734
2690 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); 2735 // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding
2736 // mode or the default Round to Zero mode.
2737 VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_
Søren Thygesen Gjesse 2011/02/03 09:07:17 Indentation.
Rodolph Perfetta 2011/02/03 15:03:39 Done.
2738 : RZ;
2739 ASSERT((mode == RM) || (mode == RZ) || (mode == RN));
2691 2740
2692 int sint = unsigned_integer ? static_cast<uint32_t>(val) : 2741 bool unsigned_integer = (instr->Bit(16) == 0);
2693 static_cast<int32_t>(val); 2742 bool double_precision = (src_precision == kDoublePrecision);
2694 sint = sint > val ? sint - 1 : sint;
2695 2743
2696 set_s_register_from_sinteger(dst, sint); 2744 double val = double_precision ? get_double_from_d_register(src)
2697 } else { 2745 : get_float_from_s_register(src);
2698 float val = get_float_from_s_register(src);
2699 2746
2700 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); 2747 int temp = unsigned_integer ? static_cast<uint32_t>(val) :
Søren Thygesen Gjesse 2011/02/03 09:07:17 Please be consistent with where the : is placed.
Rodolph Perfetta 2011/02/03 15:03:39 Done.
2748 static_cast<int32_t>(val);
2701 2749
2702 int sint = unsigned_integer ? static_cast<uint32_t>(val) : 2750 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
2703 static_cast<int32_t>(val);
2704 sint = sint > val ? sint - 1 : sint;
2705 2751
2706 set_s_register_from_sinteger(dst, sint); 2752 if (inv_op_vfp_flag_) {
2753 temp = VFPConversionSaturate(val, unsigned_integer);
2754 } else {
2755 switch (mode) {
2756 case RN: {
2757 double abs_diff =
2758 unsigned_integer ? fabs(val - static_cast<uint32_t>(temp))
2759 : fabs(val - temp);
2760 int val_sign = (val > 0) ? 1 : -1;
2761 if (abs_diff > 0.5) {
2762 temp += val_sign;
2763 } else if (abs_diff == 0.5) {
2764 // Round to even if exactly halfway.
2765 temp = ((temp % 2) == 0) ? temp : temp + val_sign;
2766 }
2767 break;
2707 } 2768 }
2708 break;
2709 case RZ:
2710 if (src_precision == kDoublePrecision) {
2711 double val = get_double_from_d_register(src);
2712 2769
2713 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); 2770 case RM:
2771 temp = temp > val ? temp - 1 : temp;
2772 break;
2714 2773
2715 int sint = unsigned_integer ? static_cast<uint32_t>(val) : 2774 case RZ:
2716 static_cast<int32_t>(val); 2775 // Nothing to do.
2776 break;
2717 2777
2718 set_s_register_from_sinteger(dst, sint); 2778 default:
2719 } else { 2779 UNREACHABLE();
2720 float val = get_float_from_s_register(src); 2780 }
2781 }
2721 2782
2722 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); 2783 // Update the destination register.
2723 2784 set_s_register_from_sinteger(dst, temp);
2724 int sint = unsigned_integer ? static_cast<uint32_t>(val) :
2725 static_cast<int32_t>(val);
2726
2727 set_s_register_from_sinteger(dst, sint);
2728 }
2729 break;
2730
2731 default:
2732 UNREACHABLE();
2733 }
2734 2785
2735 } else { 2786 } else {
2736 bool unsigned_integer = (instr->Bit(7) == 0); 2787 bool unsigned_integer = (instr->Bit(7) == 0);
2737 2788
2738 int dst = instr->VFPDRegValue(src_precision); 2789 int dst = instr->VFPDRegValue(src_precision);
2739 int src = instr->VFPMRegValue(kSinglePrecision); 2790 int src = instr->VFPMRegValue(kSinglePrecision);
2740 2791
2741 int val = get_sinteger_from_s_register(src); 2792 int val = get_sinteger_from_s_register(src);
2742 2793
2743 if (src_precision == kDoublePrecision) { 2794 if (src_precision == kDoublePrecision) {
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
3052 uintptr_t address = *stack_slot; 3103 uintptr_t address = *stack_slot;
3053 set_register(sp, current_sp + sizeof(uintptr_t)); 3104 set_register(sp, current_sp + sizeof(uintptr_t));
3054 return address; 3105 return address;
3055 } 3106 }
3056 3107
3057 } } // namespace v8::internal 3108 } } // namespace v8::internal
3058 3109
3059 #endif // USE_SIMULATOR 3110 #endif // USE_SIMULATOR
3060 3111
3061 #endif // V8_TARGET_ARCH_ARM 3112 #endif // V8_TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698