OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
895 miss); | 895 miss); |
896 if (result->IsFailure()) return result; | 896 if (result->IsFailure()) return result; |
897 } | 897 } |
898 ASSERT(current->IsJSObject()); | 898 ASSERT(current->IsJSObject()); |
899 current = JSObject::cast(current->GetPrototype()); | 899 current = JSObject::cast(current->GetPrototype()); |
900 } | 900 } |
901 return NULL; | 901 return NULL; |
902 } | 902 } |
903 | 903 |
904 | 904 |
| 905 // Convert and store int passed in register ival to IEEE 754 single precision |
| 906 // floating point value at memory location (dst + 4 * wordoffset) |
| 907 // If VFP3 is available use it for conversion. |
| 908 static void StoreIntAsFloat(MacroAssembler* masm, |
| 909 Register dst, |
| 910 Register wordoffset, |
| 911 Register ival, |
| 912 Register fval, |
| 913 Register scratch1, |
| 914 Register scratch2) { |
| 915 if (CpuFeatures::IsSupported(VFP3)) { |
| 916 CpuFeatures::Scope scope(VFP3); |
| 917 __ vmov(s0, ival); |
| 918 __ add(scratch1, dst, Operand(wordoffset, LSL, 2)); |
| 919 __ vcvt_f32_s32(s0, s0); |
| 920 __ vstr(s0, scratch1, 0); |
| 921 } else { |
| 922 Label not_special, done; |
| 923 // Move sign bit from source to destination. This works because the sign |
| 924 // bit in the exponent word of the double has the same position and polarity |
| 925 // as the 2's complement sign bit in a Smi. |
| 926 ASSERT(kBinary32SignMask == 0x80000000u); |
| 927 |
| 928 __ and_(fval, ival, Operand(kBinary32SignMask), SetCC); |
| 929 // Negate value if it is negative. |
| 930 __ rsb(ival, ival, Operand(0, RelocInfo::NONE), LeaveCC, ne); |
| 931 |
| 932 // We have -1, 0 or 1, which we treat specially. Register ival contains |
| 933 // absolute value: it is either equal to 1 (special case of -1 and 1), |
| 934 // greater than 1 (not a special case) or less than 1 (special case of 0). |
| 935 __ cmp(ival, Operand(1)); |
| 936 __ b(gt, ¬_special); |
| 937 |
| 938 // For 1 or -1 we need to or in the 0 exponent (biased). |
| 939 static const uint32_t exponent_word_for_1 = |
| 940 kBinary32ExponentBias << kBinary32ExponentShift; |
| 941 |
| 942 __ orr(fval, fval, Operand(exponent_word_for_1), LeaveCC, eq); |
| 943 __ b(&done); |
| 944 |
| 945 __ bind(¬_special); |
| 946 // Count leading zeros. |
| 947 // Gets the wrong answer for 0, but we already checked for that case above. |
| 948 Register zeros = scratch2; |
| 949 __ CountLeadingZeros(zeros, ival, scratch1); |
| 950 |
| 951 // Compute exponent and or it into the exponent register. |
| 952 __ rsb(scratch1, |
| 953 zeros, |
| 954 Operand((kBitsPerInt - 1) + kBinary32ExponentBias)); |
| 955 |
| 956 __ orr(fval, |
| 957 fval, |
| 958 Operand(scratch1, LSL, kBinary32ExponentShift)); |
| 959 |
| 960 // Shift up the source chopping the top bit off. |
| 961 __ add(zeros, zeros, Operand(1)); |
| 962 // This wouldn't work for 1 and -1 as the shift would be 32 which means 0. |
| 963 __ mov(ival, Operand(ival, LSL, zeros)); |
| 964 // And the top (top 20 bits). |
| 965 __ orr(fval, |
| 966 fval, |
| 967 Operand(ival, LSR, kBitsPerInt - kBinary32MantissaBits)); |
| 968 |
| 969 __ bind(&done); |
| 970 __ str(fval, MemOperand(dst, wordoffset, LSL, 2)); |
| 971 } |
| 972 } |
| 973 |
| 974 |
| 975 // Convert unsigned integer with specified number of leading zeroes in binary |
| 976 // representation to IEEE 754 double. |
| 977 // Integer to convert is passed in register hiword. |
| 978 // Resulting double is returned in registers hiword:loword. |
| 979 // This functions does not work correctly for 0. |
| 980 static void GenerateUInt2Double(MacroAssembler* masm, |
| 981 Register hiword, |
| 982 Register loword, |
| 983 Register scratch, |
| 984 int leading_zeroes) { |
| 985 const int meaningful_bits = kBitsPerInt - leading_zeroes - 1; |
| 986 const int biased_exponent = HeapNumber::kExponentBias + meaningful_bits; |
| 987 |
| 988 const int mantissa_shift_for_hi_word = |
| 989 meaningful_bits - HeapNumber::kMantissaBitsInTopWord; |
| 990 |
| 991 const int mantissa_shift_for_lo_word = |
| 992 kBitsPerInt - mantissa_shift_for_hi_word; |
| 993 |
| 994 __ mov(scratch, Operand(biased_exponent << HeapNumber::kExponentShift)); |
| 995 if (mantissa_shift_for_hi_word > 0) { |
| 996 __ mov(loword, Operand(hiword, LSL, mantissa_shift_for_lo_word)); |
| 997 __ orr(hiword, scratch, Operand(hiword, LSR, mantissa_shift_for_hi_word)); |
| 998 } else { |
| 999 __ mov(loword, Operand(0, RelocInfo::NONE)); |
| 1000 __ orr(hiword, scratch, Operand(hiword, LSL, mantissa_shift_for_hi_word)); |
| 1001 } |
| 1002 |
| 1003 // If least significant bit of biased exponent was not 1 it was corrupted |
| 1004 // by most significant bit of mantissa so we should fix that. |
| 1005 if (!(biased_exponent & 1)) { |
| 1006 __ bic(hiword, hiword, Operand(1 << HeapNumber::kExponentShift)); |
| 1007 } |
| 1008 } |
| 1009 |
905 | 1010 |
906 #undef __ | 1011 #undef __ |
907 #define __ ACCESS_MASM(masm()) | 1012 #define __ ACCESS_MASM(masm()) |
908 | 1013 |
909 | 1014 |
910 Register StubCompiler::CheckPrototypes(JSObject* object, | 1015 Register StubCompiler::CheckPrototypes(JSObject* object, |
911 Register object_reg, | 1016 Register object_reg, |
912 JSObject* holder, | 1017 JSObject* holder, |
913 Register holder_reg, | 1018 Register holder_reg, |
914 Register scratch1, | 1019 Register scratch1, |
(...skipping 2484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3399 __ b(ne, &box_int_1); | 3504 __ b(ne, &box_int_1); |
3400 // Tag integer as smi and return it. | 3505 // Tag integer as smi and return it. |
3401 __ mov(r0, Operand(value, LSL, kSmiTagSize)); | 3506 __ mov(r0, Operand(value, LSL, kSmiTagSize)); |
3402 __ Ret(); | 3507 __ Ret(); |
3403 | 3508 |
3404 Register hiword = value; // r2. | 3509 Register hiword = value; // r2. |
3405 Register loword = r3; | 3510 Register loword = r3; |
3406 | 3511 |
3407 __ bind(&box_int_0); | 3512 __ bind(&box_int_0); |
3408 // Integer does not have leading zeros. | 3513 // Integer does not have leading zeros. |
3409 GenerateUInt2Double(masm, hiword, loword, r4, 0); | 3514 GenerateUInt2Double(masm(), hiword, loword, r4, 0); |
3410 __ b(&done); | 3515 __ b(&done); |
3411 | 3516 |
3412 __ bind(&box_int_1); | 3517 __ bind(&box_int_1); |
3413 // Integer has one leading zero. | 3518 // Integer has one leading zero. |
3414 GenerateUInt2Double(masm, hiword, loword, r4, 1); | 3519 GenerateUInt2Double(masm(), hiword, loword, r4, 1); |
3415 | 3520 |
3416 | 3521 |
3417 __ bind(&done); | 3522 __ bind(&done); |
3418 // Integer was converted to double in registers hiword:loword. | 3523 // Integer was converted to double in registers hiword:loword. |
3419 // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber | 3524 // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber |
3420 // clobbers all registers - also when jumping due to exhausted young | 3525 // clobbers all registers - also when jumping due to exhausted young |
3421 // space. | 3526 // space. |
3422 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); | 3527 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
3423 __ AllocateHeapNumber(r4, r5, r7, r6, &slow); | 3528 __ AllocateHeapNumber(r4, r5, r7, r6, &slow); |
3424 | 3529 |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3588 case kExternalShortArray: | 3693 case kExternalShortArray: |
3589 case kExternalUnsignedShortArray: | 3694 case kExternalUnsignedShortArray: |
3590 __ strh(r5, MemOperand(r3, r4, LSL, 1)); | 3695 __ strh(r5, MemOperand(r3, r4, LSL, 1)); |
3591 break; | 3696 break; |
3592 case kExternalIntArray: | 3697 case kExternalIntArray: |
3593 case kExternalUnsignedIntArray: | 3698 case kExternalUnsignedIntArray: |
3594 __ str(r5, MemOperand(r3, r4, LSL, 2)); | 3699 __ str(r5, MemOperand(r3, r4, LSL, 2)); |
3595 break; | 3700 break; |
3596 case kExternalFloatArray: | 3701 case kExternalFloatArray: |
3597 // Perform int-to-float conversion and store to memory. | 3702 // Perform int-to-float conversion and store to memory. |
3598 StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9); | 3703 StoreIntAsFloat(masm(), r3, r4, r5, r6, r7, r9); |
3599 break; | 3704 break; |
3600 default: | 3705 default: |
3601 UNREACHABLE(); | 3706 UNREACHABLE(); |
3602 break; | 3707 break; |
3603 } | 3708 } |
3604 | 3709 |
3605 // Entry registers are intact, r0 holds the value which is the return value. | 3710 // Entry registers are intact, r0 holds the value which is the return value. |
3606 __ Ret(); | 3711 __ Ret(); |
3607 | 3712 |
3608 | 3713 |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3819 | 3924 |
3820 return GetCode(flags); | 3925 return GetCode(flags); |
3821 } | 3926 } |
3822 | 3927 |
3823 | 3928 |
3824 #undef __ | 3929 #undef __ |
3825 | 3930 |
3826 } } // namespace v8::internal | 3931 } } // namespace v8::internal |
3827 | 3932 |
3828 #endif // V8_TARGET_ARCH_ARM | 3933 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |