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

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
« no previous file with comments | « src/arm/simulator-arm.h ('k') | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_ =
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 ASSERT((mode == RN) || (mode == RM) || (mode == RZ));
2658 double max_uint = static_cast<double>(0xffffffffu);
2659 double max_int = static_cast<double>(kMaxInt);
2660 double min_int = static_cast<double>(kMinInt);
2661
2662 // Check for NaN.
2663 if (val != val) {
2664 return true;
2665 }
2666
2667 // Check for overflow. This code works because 32bit integers can be
2668 // exactly represented by ieee-754 64bit floating-point values.
2669 switch (mode) {
2670 case RN:
2671 return unsigned_ ? (val >= (max_uint + 0.5)) ||
2672 (val < -0.5)
2673 : (val >= (max_int + 0.5)) ||
2674 (val < (min_int - 0.5));
2675
2676 case RM:
2677 return unsigned_ ? (val >= (max_uint + 1.0)) ||
2678 (val < 0)
2679 : (val >= (max_int + 1.0)) ||
2680 (val < min_int);
2681
2682 case RZ:
2683 return unsigned_ ? (val >= (max_uint + 1.0)) ||
2684 (val <= -1)
2685 : (val >= (max_int + 1.0)) ||
2686 (val <= (min_int - 1.0));
2687 default:
2688 UNREACHABLE();
2689 return true;
2690 }
2691 }
2692
2693
2694 // We call this function only if we had a vfp invalid exception.
2695 // It returns the correct saturated value.
2696 int VFPConversionSaturate(double val, bool unsigned_res) {
2697 if (val != val) {
2698 return 0;
2699 } else {
2700 if (unsigned_res) {
2701 return (val < 0) ? 0 : 0xffffffffu;
2702 } else {
2703 return (val < 0) ? kMinInt : kMaxInt;
2704 }
2705 }
2706 }
2707
2654 2708
2655 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { 2709 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
2656 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 2710 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
2711 (instr->Bits(27, 23) == 0x1D));
2657 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || 2712 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
2658 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); 2713 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
2659 2714
2660 // Conversion between floating-point and integer. 2715 // Conversion between floating-point and integer.
2661 bool to_integer = (instr->Bit(18) == 1); 2716 bool to_integer = (instr->Bit(18) == 1);
2662 2717
2663 VFPRegPrecision src_precision = kSinglePrecision; 2718 VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision
2664 if (instr->SzValue() == 1) { 2719 : kSinglePrecision;
2665 src_precision = kDoublePrecision;
2666 }
2667 2720
2668 if (to_integer) { 2721 if (to_integer) {
2669 bool unsigned_integer = (instr->Bit(16) == 0); 2722 // We are playing with code close to the C++ standard's limits below,
2670 FPSCRRoundingModes mode; 2723 // hence the very simple code and heavy checks.
2671 if (instr->Bit(7) != 1) { 2724 //
2672 // Use FPSCR defined rounding mode. 2725 // Note:
2673 mode = FPSCR_rounding_mode_; 2726 // C++ defines default type casting from floating point to integer as
2674 // Only RZ and RM modes are supported. 2727 // (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 2728
2681 int dst = instr->VFPDRegValue(kSinglePrecision); 2729 int dst = instr->VFPDRegValue(kSinglePrecision);
2682 int src = instr->VFPMRegValue(src_precision); 2730 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 2731
2690 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); 2732 // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding
2733 // mode or the default Round to Zero mode.
2734 VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_
2735 : RZ;
2736 ASSERT((mode == RM) || (mode == RZ) || (mode == RN));
2691 2737
2692 int sint = unsigned_integer ? static_cast<uint32_t>(val) : 2738 bool unsigned_integer = (instr->Bit(16) == 0);
2693 static_cast<int32_t>(val); 2739 bool double_precision = (src_precision == kDoublePrecision);
2694 sint = sint > val ? sint - 1 : sint;
2695 2740
2696 set_s_register_from_sinteger(dst, sint); 2741 double val = double_precision ? get_double_from_d_register(src)
2697 } else { 2742 : get_float_from_s_register(src);
2698 float val = get_float_from_s_register(src);
2699 2743
2700 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); 2744 int temp = unsigned_integer ? static_cast<uint32_t>(val)
2745 : static_cast<int32_t>(val);
2701 2746
2702 int sint = unsigned_integer ? static_cast<uint32_t>(val) : 2747 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 2748
2706 set_s_register_from_sinteger(dst, sint); 2749 if (inv_op_vfp_flag_) {
2750 temp = VFPConversionSaturate(val, unsigned_integer);
2751 } else {
2752 switch (mode) {
2753 case RN: {
2754 double abs_diff =
2755 unsigned_integer ? fabs(val - static_cast<uint32_t>(temp))
2756 : fabs(val - temp);
2757 int val_sign = (val > 0) ? 1 : -1;
2758 if (abs_diff > 0.5) {
2759 temp += val_sign;
2760 } else if (abs_diff == 0.5) {
2761 // Round to even if exactly halfway.
2762 temp = ((temp % 2) == 0) ? temp : temp + val_sign;
2763 }
2764 break;
2707 } 2765 }
2708 break;
2709 case RZ:
2710 if (src_precision == kDoublePrecision) {
2711 double val = get_double_from_d_register(src);
2712 2766
2713 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); 2767 case RM:
2768 temp = temp > val ? temp - 1 : temp;
2769 break;
2714 2770
2715 int sint = unsigned_integer ? static_cast<uint32_t>(val) : 2771 case RZ:
2716 static_cast<int32_t>(val); 2772 // Nothing to do.
2773 break;
2717 2774
2718 set_s_register_from_sinteger(dst, sint); 2775 default:
2719 } else { 2776 UNREACHABLE();
2720 float val = get_float_from_s_register(src); 2777 }
2778 }
2721 2779
2722 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); 2780 // Update the destination register.
2723 2781 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 2782
2735 } else { 2783 } else {
2736 bool unsigned_integer = (instr->Bit(7) == 0); 2784 bool unsigned_integer = (instr->Bit(7) == 0);
2737 2785
2738 int dst = instr->VFPDRegValue(src_precision); 2786 int dst = instr->VFPDRegValue(src_precision);
2739 int src = instr->VFPMRegValue(kSinglePrecision); 2787 int src = instr->VFPMRegValue(kSinglePrecision);
2740 2788
2741 int val = get_sinteger_from_s_register(src); 2789 int val = get_sinteger_from_s_register(src);
2742 2790
2743 if (src_precision == kDoublePrecision) { 2791 if (src_precision == kDoublePrecision) {
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
3052 uintptr_t address = *stack_slot; 3100 uintptr_t address = *stack_slot;
3053 set_register(sp, current_sp + sizeof(uintptr_t)); 3101 set_register(sp, current_sp + sizeof(uintptr_t));
3054 return address; 3102 return address;
3055 } 3103 }
3056 3104
3057 } } // namespace v8::internal 3105 } } // namespace v8::internal
3058 3106
3059 #endif // USE_SIMULATOR 3107 #endif // USE_SIMULATOR
3060 3108
3061 #endif // V8_TARGET_ARCH_ARM 3109 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/simulator-arm.h ('k') | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698