OLD | NEW |
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 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1100 __ movq(Operand(rcx, 2 * kIntSize), rax); | 1100 __ movq(Operand(rcx, 2 * kIntSize), rax); |
1101 __ ret(kPointerSize); | 1101 __ ret(kPointerSize); |
1102 } | 1102 } |
1103 | 1103 |
1104 | 1104 |
1105 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { | 1105 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { |
1106 switch (type_) { | 1106 switch (type_) { |
1107 // Add more cases when necessary. | 1107 // Add more cases when necessary. |
1108 case TranscendentalCache::SIN: return Runtime::kMath_sin; | 1108 case TranscendentalCache::SIN: return Runtime::kMath_sin; |
1109 case TranscendentalCache::COS: return Runtime::kMath_cos; | 1109 case TranscendentalCache::COS: return Runtime::kMath_cos; |
| 1110 case TranscendentalCache::LOG: return Runtime::kMath_log; |
1110 default: | 1111 default: |
1111 UNIMPLEMENTED(); | 1112 UNIMPLEMENTED(); |
1112 return Runtime::kAbort; | 1113 return Runtime::kAbort; |
1113 } | 1114 } |
1114 } | 1115 } |
1115 | 1116 |
1116 | 1117 |
1117 void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm, | 1118 void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm, |
1118 Label* on_nan_result) { | 1119 Label* on_nan_result) { |
1119 // Registers: | 1120 // Registers: |
1120 // rbx: Bits of input double. Must be preserved. | 1121 // rbx: Bits of input double. Must be preserved. |
1121 // rcx: Pointer to cache entry. Must be preserved. | 1122 // rcx: Pointer to cache entry. Must be preserved. |
1122 // st(0): Input double | 1123 // st(0): Input double |
1123 Label done; | 1124 Label done; |
1124 ASSERT(type_ == TranscendentalCache::SIN || | 1125 if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) { |
1125 type_ == TranscendentalCache::COS); | 1126 // Both fsin and fcos require arguments in the range +/-2^63 and |
1126 // More transcendental types can be added later. | 1127 // return NaN for infinities and NaN. They can share all code except |
| 1128 // the actual fsin/fcos operation. |
| 1129 Label in_range; |
| 1130 // If argument is outside the range -2^63..2^63, fsin/cos doesn't |
| 1131 // work. We must reduce it to the appropriate range. |
| 1132 __ movq(rdi, rbx); |
| 1133 // Move exponent and sign bits to low bits. |
| 1134 __ shr(rdi, Immediate(HeapNumber::kMantissaBits)); |
| 1135 // Remove sign bit. |
| 1136 __ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1)); |
| 1137 int supported_exponent_limit = (63 + HeapNumber::kExponentBias); |
| 1138 __ cmpl(rdi, Immediate(supported_exponent_limit)); |
| 1139 __ j(below, &in_range); |
| 1140 // Check for infinity and NaN. Both return NaN for sin. |
| 1141 __ cmpl(rdi, Immediate(0x7ff)); |
| 1142 __ j(equal, on_nan_result); |
1127 | 1143 |
1128 // Both fsin and fcos require arguments in the range +/-2^63 and | 1144 // Use fpmod to restrict argument to the range +/-2*PI. |
1129 // return NaN for infinities and NaN. They can share all code except | 1145 __ fldpi(); |
1130 // the actual fsin/fcos operation. | 1146 __ fadd(0); |
1131 Label in_range; | 1147 __ fld(1); |
1132 // If argument is outside the range -2^63..2^63, fsin/cos doesn't | 1148 // FPU Stack: input, 2*pi, input. |
1133 // work. We must reduce it to the appropriate range. | 1149 { |
1134 __ movq(rdi, rbx); | 1150 Label no_exceptions; |
1135 // Move exponent and sign bits to low bits. | 1151 __ fwait(); |
1136 __ shr(rdi, Immediate(HeapNumber::kMantissaBits)); | 1152 __ fnstsw_ax(); |
1137 // Remove sign bit. | 1153 // Clear if Illegal Operand or Zero Division exceptions are set. |
1138 __ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1)); | 1154 __ testl(rax, Immediate(5)); // #IO and #ZD flags of FPU status word. |
1139 int supported_exponent_limit = (63 + HeapNumber::kExponentBias); | 1155 __ j(zero, &no_exceptions); |
1140 __ cmpl(rdi, Immediate(supported_exponent_limit)); | 1156 __ fnclex(); |
1141 __ j(below, &in_range); | 1157 __ bind(&no_exceptions); |
1142 // Check for infinity and NaN. Both return NaN for sin. | 1158 } |
1143 __ cmpl(rdi, Immediate(0x7ff)); | |
1144 __ j(equal, on_nan_result); | |
1145 | 1159 |
1146 // Use fpmod to restrict argument to the range +/-2*PI. | 1160 // Compute st(0) % st(1) |
1147 __ fldpi(); | 1161 { |
1148 __ fadd(0); | 1162 NearLabel partial_remainder_loop; |
1149 __ fld(1); | 1163 __ bind(&partial_remainder_loop); |
1150 // FPU Stack: input, 2*pi, input. | 1164 __ fprem1(); |
1151 { | 1165 __ fwait(); |
1152 Label no_exceptions; | 1166 __ fnstsw_ax(); |
1153 __ fwait(); | 1167 __ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word. |
1154 __ fnstsw_ax(); | 1168 // If C2 is set, computation only has partial result. Loop to |
1155 // Clear if Illegal Operand or Zero Division exceptions are set. | 1169 // continue computation. |
1156 __ testl(rax, Immediate(5)); // #IO and #ZD flags of FPU status word. | 1170 __ j(not_zero, &partial_remainder_loop); |
1157 __ j(zero, &no_exceptions); | |
1158 __ fnclex(); | |
1159 __ bind(&no_exceptions); | |
1160 } | 1171 } |
1161 | 1172 // FPU Stack: input, 2*pi, input % 2*pi |
1162 // Compute st(0) % st(1) | 1173 __ fstp(2); |
1163 { | 1174 // FPU Stack: input % 2*pi, 2*pi, |
1164 NearLabel partial_remainder_loop; | 1175 __ fstp(0); |
1165 __ bind(&partial_remainder_loop); | 1176 // FPU Stack: input % 2*pi |
1166 __ fprem1(); | 1177 __ bind(&in_range); |
1167 __ fwait(); | 1178 switch (type_) { |
1168 __ fnstsw_ax(); | 1179 case TranscendentalCache::SIN: |
1169 __ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word. | 1180 __ fsin(); |
1170 // If C2 is set, computation only has partial result. Loop to | 1181 break; |
1171 // continue computation. | 1182 case TranscendentalCache::COS: |
1172 __ j(not_zero, &partial_remainder_loop); | 1183 __ fcos(); |
| 1184 break; |
| 1185 default: |
| 1186 UNREACHABLE(); |
| 1187 } |
| 1188 __ bind(&done); |
| 1189 } else { |
| 1190 ASSERT(type_ == TranscendentalCache::LOG); |
| 1191 __ fldln2(); |
| 1192 __ fxch(); |
| 1193 __ fyl2x(); |
1173 } | 1194 } |
1174 // FPU Stack: input, 2*pi, input % 2*pi | |
1175 __ fstp(2); | |
1176 // FPU Stack: input % 2*pi, 2*pi, | |
1177 __ fstp(0); | |
1178 // FPU Stack: input % 2*pi | |
1179 __ bind(&in_range); | |
1180 switch (type_) { | |
1181 case TranscendentalCache::SIN: | |
1182 __ fsin(); | |
1183 break; | |
1184 case TranscendentalCache::COS: | |
1185 __ fcos(); | |
1186 break; | |
1187 default: | |
1188 UNREACHABLE(); | |
1189 } | |
1190 __ bind(&done); | |
1191 } | 1195 } |
1192 | 1196 |
1193 | 1197 |
1194 // Get the integer part of a heap number. | 1198 // Get the integer part of a heap number. |
1195 // Overwrites the contents of rdi, rbx and rcx. Result cannot be rdi or rbx. | 1199 // Overwrites the contents of rdi, rbx and rcx. Result cannot be rdi or rbx. |
1196 void IntegerConvert(MacroAssembler* masm, | 1200 void IntegerConvert(MacroAssembler* masm, |
1197 Register result, | 1201 Register result, |
1198 Register source) { | 1202 Register source) { |
1199 // Result may be rcx. If result and source are the same register, source will | 1203 // Result may be rcx. If result and source are the same register, source will |
1200 // be overwritten. | 1204 // be overwritten. |
(...skipping 2783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3984 // tagged as a small integer. | 3988 // tagged as a small integer. |
3985 __ bind(&runtime); | 3989 __ bind(&runtime); |
3986 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3990 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3987 } | 3991 } |
3988 | 3992 |
3989 #undef __ | 3993 #undef __ |
3990 | 3994 |
3991 } } // namespace v8::internal | 3995 } } // namespace v8::internal |
3992 | 3996 |
3993 #endif // V8_TARGET_ARCH_X64 | 3997 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |