OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 878 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
889 __ CallRuntime(RuntimeFunction(), 1); | 889 __ CallRuntime(RuntimeFunction(), 1); |
890 } | 890 } |
891 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 891 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
892 __ Ret(); | 892 __ Ret(); |
893 } | 893 } |
894 } | 894 } |
895 | 895 |
896 | 896 |
897 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { | 897 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { |
898 switch (type_) { | 898 switch (type_) { |
899 case TranscendentalCache::SIN: return Runtime::kMath_sin; | |
900 case TranscendentalCache::COS: return Runtime::kMath_cos; | |
901 case TranscendentalCache::TAN: return Runtime::kMath_tan; | |
902 case TranscendentalCache::LOG: return Runtime::kMath_log; | 899 case TranscendentalCache::LOG: return Runtime::kMath_log; |
903 default: | 900 default: |
904 UNIMPLEMENTED(); | 901 UNIMPLEMENTED(); |
905 return Runtime::kAbort; | 902 return Runtime::kAbort; |
906 } | 903 } |
907 } | 904 } |
908 | 905 |
909 | 906 |
910 void TranscendentalCacheStub::GenerateOperation( | 907 void TranscendentalCacheStub::GenerateOperation( |
911 MacroAssembler* masm, TranscendentalCache::Type type) { | 908 MacroAssembler* masm, TranscendentalCache::Type type) { |
912 // Only free register is edi. | 909 // Only free register is edi. |
913 // Input value is on FP stack, and also in ebx/edx. | 910 // Input value is on FP stack, and also in ebx/edx. |
914 // Input value is possibly in xmm1. | 911 // Input value is possibly in xmm1. |
915 // Address of result (a newly allocated HeapNumber) may be in eax. | 912 // Address of result (a newly allocated HeapNumber) may be in eax. |
916 if (type == TranscendentalCache::SIN || | 913 ASSERT(type == TranscendentalCache::LOG); |
917 type == TranscendentalCache::COS || | 914 __ fldln2(); |
918 type == TranscendentalCache::TAN) { | 915 __ fxch(); |
919 // Both fsin and fcos require arguments in the range +/-2^63 and | 916 __ fyl2x(); |
920 // return NaN for infinities and NaN. They can share all code except | |
921 // the actual fsin/fcos operation. | |
922 Label in_range, done; | |
923 // If argument is outside the range -2^63..2^63, fsin/cos doesn't | |
924 // work. We must reduce it to the appropriate range. | |
925 __ mov(edi, edx); | |
926 __ and_(edi, Immediate(0x7ff00000)); // Exponent only. | |
927 int supported_exponent_limit = | |
928 (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift; | |
929 __ cmp(edi, Immediate(supported_exponent_limit)); | |
930 __ j(below, &in_range, Label::kNear); | |
931 // Check for infinity and NaN. Both return NaN for sin. | |
932 __ cmp(edi, Immediate(0x7ff00000)); | |
933 Label non_nan_result; | |
934 __ j(not_equal, &non_nan_result, Label::kNear); | |
935 // Input is +/-Infinity or NaN. Result is NaN. | |
936 __ fstp(0); | |
937 // NaN is represented by 0x7ff8000000000000. | |
938 __ push(Immediate(0x7ff80000)); | |
939 __ push(Immediate(0)); | |
940 __ fld_d(Operand(esp, 0)); | |
941 __ add(esp, Immediate(2 * kPointerSize)); | |
942 __ jmp(&done, Label::kNear); | |
943 | |
944 __ bind(&non_nan_result); | |
945 | |
946 // Use fpmod to restrict argument to the range +/-2*PI. | |
947 __ mov(edi, eax); // Save eax before using fnstsw_ax. | |
948 __ fldpi(); | |
949 __ fadd(0); | |
950 __ fld(1); | |
951 // FPU Stack: input, 2*pi, input. | |
952 { | |
953 Label no_exceptions; | |
954 __ fwait(); | |
955 __ fnstsw_ax(); | |
956 // Clear if Illegal Operand or Zero Division exceptions are set. | |
957 __ test(eax, Immediate(5)); | |
958 __ j(zero, &no_exceptions, Label::kNear); | |
959 __ fnclex(); | |
960 __ bind(&no_exceptions); | |
961 } | |
962 | |
963 // Compute st(0) % st(1) | |
964 { | |
965 Label partial_remainder_loop; | |
966 __ bind(&partial_remainder_loop); | |
967 __ fprem1(); | |
968 __ fwait(); | |
969 __ fnstsw_ax(); | |
970 __ test(eax, Immediate(0x400 /* C2 */)); | |
971 // If C2 is set, computation only has partial result. Loop to | |
972 // continue computation. | |
973 __ j(not_zero, &partial_remainder_loop); | |
974 } | |
975 // FPU Stack: input, 2*pi, input % 2*pi | |
976 __ fstp(2); | |
977 __ fstp(0); | |
978 __ mov(eax, edi); // Restore eax (allocated HeapNumber pointer). | |
979 | |
980 // FPU Stack: input % 2*pi | |
981 __ bind(&in_range); | |
982 switch (type) { | |
983 case TranscendentalCache::SIN: | |
984 __ fsin(); | |
985 break; | |
986 case TranscendentalCache::COS: | |
987 __ fcos(); | |
988 break; | |
989 case TranscendentalCache::TAN: | |
990 // FPTAN calculates tangent onto st(0) and pushes 1.0 onto the | |
991 // FP register stack. | |
992 __ fptan(); | |
993 __ fstp(0); // Pop FP register stack. | |
994 break; | |
995 default: | |
996 UNREACHABLE(); | |
997 } | |
998 __ bind(&done); | |
999 } else { | |
1000 ASSERT(type == TranscendentalCache::LOG); | |
1001 __ fldln2(); | |
1002 __ fxch(); | |
1003 __ fyl2x(); | |
1004 } | |
1005 } | 917 } |
1006 | 918 |
1007 | 919 |
1008 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 920 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
1009 Register number) { | 921 Register number) { |
1010 Label load_smi, done; | 922 Label load_smi, done; |
1011 | 923 |
1012 __ JumpIfSmi(number, &load_smi, Label::kNear); | 924 __ JumpIfSmi(number, &load_smi, Label::kNear); |
1013 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); | 925 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); |
1014 __ jmp(&done, Label::kNear); | 926 __ jmp(&done, Label::kNear); |
(...skipping 4966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5981 __ bind(&fast_elements_case); | 5893 __ bind(&fast_elements_case); |
5982 GenerateCase(masm, FAST_ELEMENTS); | 5894 GenerateCase(masm, FAST_ELEMENTS); |
5983 } | 5895 } |
5984 | 5896 |
5985 | 5897 |
5986 #undef __ | 5898 #undef __ |
5987 | 5899 |
5988 } } // namespace v8::internal | 5900 } } // namespace v8::internal |
5989 | 5901 |
5990 #endif // V8_TARGET_ARCH_IA32 | 5902 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |