| 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 1312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1323 __ bind(&runtime_call); | 1323 __ bind(&runtime_call); |
| 1324 __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1); | 1324 __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1); |
| 1325 } | 1325 } |
| 1326 | 1326 |
| 1327 | 1327 |
| 1328 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { | 1328 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { |
| 1329 switch (type_) { | 1329 switch (type_) { |
| 1330 // Add more cases when necessary. | 1330 // Add more cases when necessary. |
| 1331 case TranscendentalCache::SIN: return Runtime::kMath_sin; | 1331 case TranscendentalCache::SIN: return Runtime::kMath_sin; |
| 1332 case TranscendentalCache::COS: return Runtime::kMath_cos; | 1332 case TranscendentalCache::COS: return Runtime::kMath_cos; |
| 1333 case TranscendentalCache::LOG: return Runtime::kMath_log; |
| 1333 default: | 1334 default: |
| 1334 UNIMPLEMENTED(); | 1335 UNIMPLEMENTED(); |
| 1335 return Runtime::kAbort; | 1336 return Runtime::kAbort; |
| 1336 } | 1337 } |
| 1337 } | 1338 } |
| 1338 | 1339 |
| 1339 | 1340 |
| 1340 void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) { | 1341 void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) { |
| 1341 // Only free register is edi. | 1342 // Only free register is edi. |
| 1343 // Input value is on FP stack, and also in ebx/edx. Address of result |
| 1344 // (a newly allocated HeapNumber) is in eax. |
| 1342 NearLabel done; | 1345 NearLabel done; |
| 1343 ASSERT(type_ == TranscendentalCache::SIN || | 1346 if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) { |
| 1344 type_ == TranscendentalCache::COS); | 1347 // Both fsin and fcos require arguments in the range +/-2^63 and |
| 1345 // More transcendental types can be added later. | 1348 // return NaN for infinities and NaN. They can share all code except |
| 1349 // the actual fsin/fcos operation. |
| 1350 NearLabel in_range; |
| 1351 // If argument is outside the range -2^63..2^63, fsin/cos doesn't |
| 1352 // work. We must reduce it to the appropriate range. |
| 1353 __ mov(edi, edx); |
| 1354 __ and_(Operand(edi), Immediate(0x7ff00000)); // Exponent only. |
| 1355 int supported_exponent_limit = |
| 1356 (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift; |
| 1357 __ cmp(Operand(edi), Immediate(supported_exponent_limit)); |
| 1358 __ j(below, &in_range, taken); |
| 1359 // Check for infinity and NaN. Both return NaN for sin. |
| 1360 __ cmp(Operand(edi), Immediate(0x7ff00000)); |
| 1361 NearLabel non_nan_result; |
| 1362 __ j(not_equal, &non_nan_result, taken); |
| 1363 // Input is +/-Infinity or NaN. Result is NaN. |
| 1364 __ fstp(0); |
| 1365 // NaN is represented by 0x7ff8000000000000. |
| 1366 __ push(Immediate(0x7ff80000)); |
| 1367 __ push(Immediate(0)); |
| 1368 __ fld_d(Operand(esp, 0)); |
| 1369 __ add(Operand(esp), Immediate(2 * kPointerSize)); |
| 1370 __ jmp(&done); |
| 1346 | 1371 |
| 1347 // Both fsin and fcos require arguments in the range +/-2^63 and | 1372 __ bind(&non_nan_result); |
| 1348 // return NaN for infinities and NaN. They can share all code except | |
| 1349 // the actual fsin/fcos operation. | |
| 1350 NearLabel in_range; | |
| 1351 // If argument is outside the range -2^63..2^63, fsin/cos doesn't | |
| 1352 // work. We must reduce it to the appropriate range. | |
| 1353 __ mov(edi, edx); | |
| 1354 __ and_(Operand(edi), Immediate(0x7ff00000)); // Exponent only. | |
| 1355 int supported_exponent_limit = | |
| 1356 (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift; | |
| 1357 __ cmp(Operand(edi), Immediate(supported_exponent_limit)); | |
| 1358 __ j(below, &in_range, taken); | |
| 1359 // Check for infinity and NaN. Both return NaN for sin. | |
| 1360 __ cmp(Operand(edi), Immediate(0x7ff00000)); | |
| 1361 NearLabel non_nan_result; | |
| 1362 __ j(not_equal, &non_nan_result, taken); | |
| 1363 // Input is +/-Infinity or NaN. Result is NaN. | |
| 1364 __ fstp(0); | |
| 1365 // NaN is represented by 0x7ff8000000000000. | |
| 1366 __ push(Immediate(0x7ff80000)); | |
| 1367 __ push(Immediate(0)); | |
| 1368 __ fld_d(Operand(esp, 0)); | |
| 1369 __ add(Operand(esp), Immediate(2 * kPointerSize)); | |
| 1370 __ jmp(&done); | |
| 1371 | 1373 |
| 1372 __ bind(&non_nan_result); | 1374 // Use fpmod to restrict argument to the range +/-2*PI. |
| 1375 __ mov(edi, eax); // Save eax before using fnstsw_ax. |
| 1376 __ fldpi(); |
| 1377 __ fadd(0); |
| 1378 __ fld(1); |
| 1379 // FPU Stack: input, 2*pi, input. |
| 1380 { |
| 1381 NearLabel no_exceptions; |
| 1382 __ fwait(); |
| 1383 __ fnstsw_ax(); |
| 1384 // Clear if Illegal Operand or Zero Division exceptions are set. |
| 1385 __ test(Operand(eax), Immediate(5)); |
| 1386 __ j(zero, &no_exceptions); |
| 1387 __ fnclex(); |
| 1388 __ bind(&no_exceptions); |
| 1389 } |
| 1373 | 1390 |
| 1374 // Use fpmod to restrict argument to the range +/-2*PI. | 1391 // Compute st(0) % st(1) |
| 1375 __ mov(edi, eax); // Save eax before using fnstsw_ax. | 1392 { |
| 1376 __ fldpi(); | 1393 NearLabel partial_remainder_loop; |
| 1377 __ fadd(0); | 1394 __ bind(&partial_remainder_loop); |
| 1378 __ fld(1); | 1395 __ fprem1(); |
| 1379 // FPU Stack: input, 2*pi, input. | 1396 __ fwait(); |
| 1380 { | 1397 __ fnstsw_ax(); |
| 1381 NearLabel no_exceptions; | 1398 __ test(Operand(eax), Immediate(0x400 /* C2 */)); |
| 1382 __ fwait(); | 1399 // If C2 is set, computation only has partial result. Loop to |
| 1383 __ fnstsw_ax(); | 1400 // continue computation. |
| 1384 // Clear if Illegal Operand or Zero Division exceptions are set. | 1401 __ j(not_zero, &partial_remainder_loop); |
| 1385 __ test(Operand(eax), Immediate(5)); | 1402 } |
| 1386 __ j(zero, &no_exceptions); | 1403 // FPU Stack: input, 2*pi, input % 2*pi |
| 1387 __ fnclex(); | 1404 __ fstp(2); |
| 1388 __ bind(&no_exceptions); | 1405 __ fstp(0); |
| 1406 __ mov(eax, edi); // Restore eax (allocated HeapNumber pointer). |
| 1407 |
| 1408 // FPU Stack: input % 2*pi |
| 1409 __ bind(&in_range); |
| 1410 switch (type_) { |
| 1411 case TranscendentalCache::SIN: |
| 1412 __ fsin(); |
| 1413 break; |
| 1414 case TranscendentalCache::COS: |
| 1415 __ fcos(); |
| 1416 break; |
| 1417 default: |
| 1418 UNREACHABLE(); |
| 1419 } |
| 1420 __ bind(&done); |
| 1421 } else { |
| 1422 ASSERT(type_ == TranscendentalCache::LOG); |
| 1423 __ fldln2(); |
| 1424 __ fxch(); |
| 1425 __ fyl2x(); |
| 1389 } | 1426 } |
| 1390 | |
| 1391 // Compute st(0) % st(1) | |
| 1392 { | |
| 1393 NearLabel partial_remainder_loop; | |
| 1394 __ bind(&partial_remainder_loop); | |
| 1395 __ fprem1(); | |
| 1396 __ fwait(); | |
| 1397 __ fnstsw_ax(); | |
| 1398 __ test(Operand(eax), Immediate(0x400 /* C2 */)); | |
| 1399 // If C2 is set, computation only has partial result. Loop to | |
| 1400 // continue computation. | |
| 1401 __ j(not_zero, &partial_remainder_loop); | |
| 1402 } | |
| 1403 // FPU Stack: input, 2*pi, input % 2*pi | |
| 1404 __ fstp(2); | |
| 1405 __ fstp(0); | |
| 1406 __ mov(eax, edi); // Restore eax (allocated HeapNumber pointer). | |
| 1407 | |
| 1408 // FPU Stack: input % 2*pi | |
| 1409 __ bind(&in_range); | |
| 1410 switch (type_) { | |
| 1411 case TranscendentalCache::SIN: | |
| 1412 __ fsin(); | |
| 1413 break; | |
| 1414 case TranscendentalCache::COS: | |
| 1415 __ fcos(); | |
| 1416 break; | |
| 1417 default: | |
| 1418 UNREACHABLE(); | |
| 1419 } | |
| 1420 __ bind(&done); | |
| 1421 } | 1427 } |
| 1422 | 1428 |
| 1423 | 1429 |
| 1424 // Get the integer part of a heap number. Surprisingly, all this bit twiddling | 1430 // Get the integer part of a heap number. Surprisingly, all this bit twiddling |
| 1425 // is faster than using the built-in instructions on floating point registers. | 1431 // is faster than using the built-in instructions on floating point registers. |
| 1426 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the | 1432 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the |
| 1427 // trashed registers. | 1433 // trashed registers. |
| 1428 void IntegerConvert(MacroAssembler* masm, | 1434 void IntegerConvert(MacroAssembler* masm, |
| 1429 Register source, | 1435 Register source, |
| 1430 TypeInfo type_info, | 1436 TypeInfo type_info, |
| (...skipping 3140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4571 // tagged as a small integer. | 4577 // tagged as a small integer. |
| 4572 __ bind(&runtime); | 4578 __ bind(&runtime); |
| 4573 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 4579 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 4574 } | 4580 } |
| 4575 | 4581 |
| 4576 #undef __ | 4582 #undef __ |
| 4577 | 4583 |
| 4578 } } // namespace v8::internal | 4584 } } // namespace v8::internal |
| 4579 | 4585 |
| 4580 #endif // V8_TARGET_ARCH_IA32 | 4586 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |