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 1041 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 } | 1052 } |
1053 | 1053 |
1054 | 1054 |
1055 // Convert and store int passed in register ival to IEEE 754 single precision | 1055 // Convert and store int passed in register ival to IEEE 754 single precision |
1056 // floating point value at memory location (dst + 4 * wordoffset) | 1056 // floating point value at memory location (dst + 4 * wordoffset) |
1057 // If FPU is available use it for conversion. | 1057 // If FPU is available use it for conversion. |
1058 static void StoreIntAsFloat(MacroAssembler* masm, | 1058 static void StoreIntAsFloat(MacroAssembler* masm, |
1059 Register dst, | 1059 Register dst, |
1060 Register wordoffset, | 1060 Register wordoffset, |
1061 Register ival, | 1061 Register ival, |
1062 Register fval, | 1062 Register scratch1) { |
1063 Register scratch1, | 1063 __ mtc1(ival, f0); |
1064 Register scratch2) { | 1064 __ cvt_s_w(f0, f0); |
1065 if (CpuFeatures::IsSupported(FPU)) { | 1065 __ sll(scratch1, wordoffset, 2); |
1066 CpuFeatureScope scope(masm, FPU); | 1066 __ addu(scratch1, dst, scratch1); |
1067 __ mtc1(ival, f0); | 1067 __ swc1(f0, MemOperand(scratch1, 0)); |
1068 __ cvt_s_w(f0, f0); | |
1069 __ sll(scratch1, wordoffset, 2); | |
1070 __ addu(scratch1, dst, scratch1); | |
1071 __ swc1(f0, MemOperand(scratch1, 0)); | |
1072 } else { | |
1073 // FPU is not available, do manual conversions. | |
1074 | |
1075 Label not_special, done; | |
1076 // Move sign bit from source to destination. This works because the sign | |
1077 // bit in the exponent word of the double has the same position and polarity | |
1078 // as the 2's complement sign bit in a Smi. | |
1079 ASSERT(kBinary32SignMask == 0x80000000u); | |
1080 | |
1081 __ And(fval, ival, Operand(kBinary32SignMask)); | |
1082 // Negate value if it is negative. | |
1083 __ subu(scratch1, zero_reg, ival); | |
1084 __ Movn(ival, scratch1, fval); | |
1085 | |
1086 // We have -1, 0 or 1, which we treat specially. Register ival contains | |
1087 // absolute value: it is either equal to 1 (special case of -1 and 1), | |
1088 // greater than 1 (not a special case) or less than 1 (special case of 0). | |
1089 __ Branch(¬_special, gt, ival, Operand(1)); | |
1090 | |
1091 // For 1 or -1 we need to or in the 0 exponent (biased). | |
1092 static const uint32_t exponent_word_for_1 = | |
1093 kBinary32ExponentBias << kBinary32ExponentShift; | |
1094 | |
1095 __ Xor(scratch1, ival, Operand(1)); | |
1096 __ li(scratch2, exponent_word_for_1); | |
1097 __ or_(scratch2, fval, scratch2); | |
1098 __ Movz(fval, scratch2, scratch1); // Only if ival is equal to 1. | |
1099 __ Branch(&done); | |
1100 | |
1101 __ bind(¬_special); | |
1102 // Count leading zeros. | |
1103 // Gets the wrong answer for 0, but we already checked for that case above. | |
1104 Register zeros = scratch2; | |
1105 __ Clz(zeros, ival); | |
1106 | |
1107 // Compute exponent and or it into the exponent register. | |
1108 __ li(scratch1, (kBitsPerInt - 1) + kBinary32ExponentBias); | |
1109 __ subu(scratch1, scratch1, zeros); | |
1110 | |
1111 __ sll(scratch1, scratch1, kBinary32ExponentShift); | |
1112 __ or_(fval, fval, scratch1); | |
1113 | |
1114 // Shift up the source chopping the top bit off. | |
1115 __ Addu(zeros, zeros, Operand(1)); | |
1116 // This wouldn't work for 1 and -1 as the shift would be 32 which means 0. | |
1117 __ sllv(ival, ival, zeros); | |
1118 // And the top (top 20 bits). | |
1119 __ srl(scratch1, ival, kBitsPerInt - kBinary32MantissaBits); | |
1120 __ or_(fval, fval, scratch1); | |
1121 | |
1122 __ bind(&done); | |
1123 | |
1124 __ sll(scratch1, wordoffset, 2); | |
1125 __ addu(scratch1, dst, scratch1); | |
1126 __ sw(fval, MemOperand(scratch1, 0)); | |
1127 } | |
1128 } | 1068 } |
1129 | 1069 |
1130 | 1070 |
1131 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1071 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
1132 __ Jump(code, RelocInfo::CODE_TARGET); | 1072 __ Jump(code, RelocInfo::CODE_TARGET); |
1133 } | 1073 } |
1134 | 1074 |
1135 | 1075 |
1136 #undef __ | 1076 #undef __ |
1137 #define __ ACCESS_MASM(masm()) | 1077 #define __ ACCESS_MASM(masm()) |
(...skipping 1032 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2170 Handle<JSFunction> function, | 2110 Handle<JSFunction> function, |
2171 Handle<String> name) { | 2111 Handle<String> name) { |
2172 // ----------- S t a t e ------------- | 2112 // ----------- S t a t e ------------- |
2173 // -- a2 : function name | 2113 // -- a2 : function name |
2174 // -- ra : return address | 2114 // -- ra : return address |
2175 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 2115 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
2176 // -- ... | 2116 // -- ... |
2177 // -- sp[argc * 4] : receiver | 2117 // -- sp[argc * 4] : receiver |
2178 // ----------------------------------- | 2118 // ----------------------------------- |
2179 | 2119 |
2180 if (!CpuFeatures::IsSupported(FPU)) { | |
2181 return Handle<Code>::null(); | |
2182 } | |
2183 | 2120 |
2184 CpuFeatureScope scope_fpu(masm(), FPU); | |
2185 const int argc = arguments().immediate(); | 2121 const int argc = arguments().immediate(); |
2186 // If the object is not a JSObject or we got an unexpected number of | 2122 // If the object is not a JSObject or we got an unexpected number of |
2187 // arguments, bail out to the regular call. | 2123 // arguments, bail out to the regular call. |
2188 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2124 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
2189 | 2125 |
2190 Label miss, slow; | 2126 Label miss, slow; |
2191 GenerateNameCheck(name, &miss); | 2127 GenerateNameCheck(name, &miss); |
2192 | 2128 |
2193 if (cell.is_null()) { | 2129 if (cell.is_null()) { |
2194 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | 2130 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); |
(...skipping 1045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3240 | 3176 |
3241 // ---------- S t a t e -------------- | 3177 // ---------- S t a t e -------------- |
3242 // -- ra : return address | 3178 // -- ra : return address |
3243 // -- a0 : key | 3179 // -- a0 : key |
3244 // -- a1 : receiver | 3180 // -- a1 : receiver |
3245 // ----------------------------------- | 3181 // ----------------------------------- |
3246 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3182 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
3247 } | 3183 } |
3248 | 3184 |
3249 | 3185 |
3250 static bool IsElementTypeSigned(ElementsKind elements_kind) { | |
3251 switch (elements_kind) { | |
3252 case EXTERNAL_BYTE_ELEMENTS: | |
3253 case EXTERNAL_SHORT_ELEMENTS: | |
3254 case EXTERNAL_INT_ELEMENTS: | |
3255 return true; | |
3256 | |
3257 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
3258 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
3259 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
3260 case EXTERNAL_PIXEL_ELEMENTS: | |
3261 return false; | |
3262 | |
3263 case EXTERNAL_FLOAT_ELEMENTS: | |
3264 case EXTERNAL_DOUBLE_ELEMENTS: | |
3265 case FAST_SMI_ELEMENTS: | |
3266 case FAST_ELEMENTS: | |
3267 case FAST_DOUBLE_ELEMENTS: | |
3268 case FAST_HOLEY_SMI_ELEMENTS: | |
3269 case FAST_HOLEY_ELEMENTS: | |
3270 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
3271 case DICTIONARY_ELEMENTS: | |
3272 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
3273 UNREACHABLE(); | |
3274 return false; | |
3275 } | |
3276 return false; | |
3277 } | |
3278 | |
3279 | |
3280 static void GenerateSmiKeyCheck(MacroAssembler* masm, | 3186 static void GenerateSmiKeyCheck(MacroAssembler* masm, |
3281 Register key, | 3187 Register key, |
3282 Register scratch0, | 3188 Register scratch0, |
3283 Register scratch1, | 3189 Register scratch1, |
3284 FPURegister double_scratch0, | 3190 FPURegister double_scratch0, |
3285 FPURegister double_scratch1, | 3191 FPURegister double_scratch1, |
3286 Label* fail) { | 3192 Label* fail) { |
3287 if (CpuFeatures::IsSupported(FPU)) { | 3193 Label key_ok; |
3288 CpuFeatureScope scope(masm, FPU); | 3194 // Check for smi or a smi inside a heap number. We convert the heap |
3289 Label key_ok; | 3195 // number and check if the conversion is exact and fits into the smi |
3290 // Check for smi or a smi inside a heap number. We convert the heap | 3196 // range. |
3291 // number and check if the conversion is exact and fits into the smi | 3197 __ JumpIfSmi(key, &key_ok); |
3292 // range. | 3198 __ CheckMap(key, |
3293 __ JumpIfSmi(key, &key_ok); | 3199 scratch0, |
3294 __ CheckMap(key, | 3200 Heap::kHeapNumberMapRootIndex, |
3295 scratch0, | 3201 fail, |
3296 Heap::kHeapNumberMapRootIndex, | 3202 DONT_DO_SMI_CHECK); |
3297 fail, | 3203 __ ldc1(double_scratch0, FieldMemOperand(key, HeapNumber::kValueOffset)); |
3298 DONT_DO_SMI_CHECK); | 3204 __ EmitFPUTruncate(kRoundToZero, |
3299 __ ldc1(double_scratch0, FieldMemOperand(key, HeapNumber::kValueOffset)); | 3205 scratch0, |
3300 __ EmitFPUTruncate(kRoundToZero, | 3206 double_scratch0, |
3301 scratch0, | 3207 at, |
3302 double_scratch0, | 3208 double_scratch1, |
3303 at, | 3209 scratch1, |
3304 double_scratch1, | 3210 kCheckForInexactConversion); |
3305 scratch1, | |
3306 kCheckForInexactConversion); | |
3307 | 3211 |
3308 __ Branch(fail, ne, scratch1, Operand(zero_reg)); | 3212 __ Branch(fail, ne, scratch1, Operand(zero_reg)); |
3309 | 3213 |
3310 __ SmiTagCheckOverflow(key, scratch0, scratch1); | 3214 __ SmiTagCheckOverflow(key, scratch0, scratch1); |
3311 __ BranchOnOverflow(fail, scratch1); | 3215 __ BranchOnOverflow(fail, scratch1); |
3312 __ bind(&key_ok); | 3216 __ bind(&key_ok); |
3313 } else { | |
3314 // Check that the key is a smi. | |
3315 __ JumpIfNotSmi(key, fail); | |
3316 } | |
3317 } | 3217 } |
3318 | 3218 |
3319 | 3219 |
3320 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3220 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
3321 MacroAssembler* masm, | 3221 MacroAssembler* masm, |
3322 ElementsKind elements_kind) { | 3222 ElementsKind elements_kind) { |
3323 // ---------- S t a t e -------------- | 3223 // ---------- S t a t e -------------- |
3324 // -- a0 : value | 3224 // -- a0 : value |
3325 // -- a1 : key | 3225 // -- a1 : key |
3326 // -- a2 : receiver | 3226 // -- a2 : receiver |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3397 break; | 3297 break; |
3398 case EXTERNAL_INT_ELEMENTS: | 3298 case EXTERNAL_INT_ELEMENTS: |
3399 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3299 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
3400 __ sll(t8, key, 1); | 3300 __ sll(t8, key, 1); |
3401 __ addu(t8, a3, t8); | 3301 __ addu(t8, a3, t8); |
3402 __ sw(t1, MemOperand(t8, 0)); | 3302 __ sw(t1, MemOperand(t8, 0)); |
3403 break; | 3303 break; |
3404 case EXTERNAL_FLOAT_ELEMENTS: | 3304 case EXTERNAL_FLOAT_ELEMENTS: |
3405 // Perform int-to-float conversion and store to memory. | 3305 // Perform int-to-float conversion and store to memory. |
3406 __ SmiUntag(t0, key); | 3306 __ SmiUntag(t0, key); |
3407 StoreIntAsFloat(masm, a3, t0, t1, t2, t3, t4); | 3307 StoreIntAsFloat(masm, a3, t0, t1, t2); |
3408 break; | 3308 break; |
3409 case EXTERNAL_DOUBLE_ELEMENTS: | 3309 case EXTERNAL_DOUBLE_ELEMENTS: |
3410 __ sll(t8, key, 2); | 3310 __ sll(t8, key, 2); |
3411 __ addu(a3, a3, t8); | 3311 __ addu(a3, a3, t8); |
3412 // a3: effective address of the double element | 3312 // a3: effective address of the double element |
3413 FloatingPointHelper::Destination destination; | 3313 FloatingPointHelper::Destination destination; |
3414 if (CpuFeatures::IsSupported(FPU)) { | 3314 destination = FloatingPointHelper::kFPURegisters; |
3415 destination = FloatingPointHelper::kFPURegisters; | |
3416 } else { | |
3417 destination = FloatingPointHelper::kCoreRegisters; | |
3418 } | |
3419 FloatingPointHelper::ConvertIntToDouble( | 3315 FloatingPointHelper::ConvertIntToDouble( |
3420 masm, t1, destination, | 3316 masm, t1, destination, |
3421 f0, t2, t3, // These are: double_dst, dst_mantissa, dst_exponent. | 3317 f0, t2, t3, // These are: double_dst, dst_mantissa, dst_exponent. |
3422 t0, f2); // These are: scratch2, single_scratch. | 3318 t0, f2); // These are: scratch2, single_scratch. |
3423 if (destination == FloatingPointHelper::kFPURegisters) { | 3319 __ sdc1(f0, MemOperand(a3, 0)); |
3424 CpuFeatureScope scope(masm, FPU); | |
3425 __ sdc1(f0, MemOperand(a3, 0)); | |
3426 } else { | |
3427 __ sw(t2, MemOperand(a3, 0)); | |
3428 __ sw(t3, MemOperand(a3, Register::kSizeInBytes)); | |
3429 } | |
3430 break; | 3320 break; |
3431 case FAST_ELEMENTS: | 3321 case FAST_ELEMENTS: |
3432 case FAST_SMI_ELEMENTS: | 3322 case FAST_SMI_ELEMENTS: |
3433 case FAST_DOUBLE_ELEMENTS: | 3323 case FAST_DOUBLE_ELEMENTS: |
3434 case FAST_HOLEY_ELEMENTS: | 3324 case FAST_HOLEY_ELEMENTS: |
3435 case FAST_HOLEY_SMI_ELEMENTS: | 3325 case FAST_HOLEY_SMI_ELEMENTS: |
3436 case FAST_HOLEY_DOUBLE_ELEMENTS: | 3326 case FAST_HOLEY_DOUBLE_ELEMENTS: |
3437 case DICTIONARY_ELEMENTS: | 3327 case DICTIONARY_ELEMENTS: |
3438 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3328 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3439 UNREACHABLE(); | 3329 UNREACHABLE(); |
(...skipping 11 matching lines...) Expand all Loading... |
3451 __ Branch(&slow, ne, t2, Operand(HEAP_NUMBER_TYPE)); | 3341 __ Branch(&slow, ne, t2, Operand(HEAP_NUMBER_TYPE)); |
3452 | 3342 |
3453 __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); | 3343 __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); |
3454 | 3344 |
3455 // a3: base pointer of external storage. | 3345 // a3: base pointer of external storage. |
3456 | 3346 |
3457 // The WebGL specification leaves the behavior of storing NaN and | 3347 // The WebGL specification leaves the behavior of storing NaN and |
3458 // +/-Infinity into integer arrays basically undefined. For more | 3348 // +/-Infinity into integer arrays basically undefined. For more |
3459 // reproducible behavior, convert these to zero. | 3349 // reproducible behavior, convert these to zero. |
3460 | 3350 |
3461 if (CpuFeatures::IsSupported(FPU)) { | |
3462 CpuFeatureScope scope(masm, FPU); | |
3463 | 3351 |
3464 __ ldc1(f0, FieldMemOperand(a0, HeapNumber::kValueOffset)); | 3352 __ ldc1(f0, FieldMemOperand(a0, HeapNumber::kValueOffset)); |
3465 | 3353 |
3466 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | 3354 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
3467 __ cvt_s_d(f0, f0); | 3355 __ cvt_s_d(f0, f0); |
3468 __ sll(t8, key, 1); | 3356 __ sll(t8, key, 1); |
3469 __ addu(t8, a3, t8); | 3357 __ addu(t8, a3, t8); |
3470 __ swc1(f0, MemOperand(t8, 0)); | 3358 __ swc1(f0, MemOperand(t8, 0)); |
3471 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 3359 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
3472 __ sll(t8, key, 2); | 3360 __ sll(t8, key, 2); |
3473 __ addu(t8, a3, t8); | 3361 __ addu(t8, a3, t8); |
3474 __ sdc1(f0, MemOperand(t8, 0)); | 3362 __ sdc1(f0, MemOperand(t8, 0)); |
3475 } else { | 3363 } else { |
3476 __ EmitECMATruncate(t3, f0, f2, t2, t1, t5); | 3364 __ EmitECMATruncate(t3, f0, f2, t2, t1, t5); |
3477 | 3365 |
3478 switch (elements_kind) { | 3366 switch (elements_kind) { |
3479 case EXTERNAL_BYTE_ELEMENTS: | 3367 case EXTERNAL_BYTE_ELEMENTS: |
3480 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3368 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
3481 __ srl(t8, key, 1); | 3369 __ srl(t8, key, 1); |
3482 __ addu(t8, a3, t8); | 3370 __ addu(t8, a3, t8); |
3483 __ sb(t3, MemOperand(t8, 0)); | 3371 __ sb(t3, MemOperand(t8, 0)); |
3484 break; | 3372 break; |
3485 case EXTERNAL_SHORT_ELEMENTS: | 3373 case EXTERNAL_SHORT_ELEMENTS: |
3486 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3374 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
3487 __ addu(t8, a3, key); | 3375 __ addu(t8, a3, key); |
3488 __ sh(t3, MemOperand(t8, 0)); | 3376 __ sh(t3, MemOperand(t8, 0)); |
3489 break; | 3377 break; |
3490 case EXTERNAL_INT_ELEMENTS: | 3378 case EXTERNAL_INT_ELEMENTS: |
3491 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3379 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
3492 __ sll(t8, key, 1); | 3380 __ sll(t8, key, 1); |
3493 __ addu(t8, a3, t8); | 3381 __ addu(t8, a3, t8); |
3494 __ sw(t3, MemOperand(t8, 0)); | 3382 __ sw(t3, MemOperand(t8, 0)); |
3495 break; | 3383 break; |
3496 case EXTERNAL_PIXEL_ELEMENTS: | 3384 case EXTERNAL_PIXEL_ELEMENTS: |
3497 case EXTERNAL_FLOAT_ELEMENTS: | 3385 case EXTERNAL_FLOAT_ELEMENTS: |
3498 case EXTERNAL_DOUBLE_ELEMENTS: | 3386 case EXTERNAL_DOUBLE_ELEMENTS: |
3499 case FAST_ELEMENTS: | 3387 case FAST_ELEMENTS: |
3500 case FAST_SMI_ELEMENTS: | 3388 case FAST_SMI_ELEMENTS: |
3501 case FAST_DOUBLE_ELEMENTS: | 3389 case FAST_DOUBLE_ELEMENTS: |
3502 case FAST_HOLEY_ELEMENTS: | 3390 case FAST_HOLEY_ELEMENTS: |
3503 case FAST_HOLEY_SMI_ELEMENTS: | 3391 case FAST_HOLEY_SMI_ELEMENTS: |
3504 case FAST_HOLEY_DOUBLE_ELEMENTS: | 3392 case FAST_HOLEY_DOUBLE_ELEMENTS: |
3505 case DICTIONARY_ELEMENTS: | 3393 case DICTIONARY_ELEMENTS: |
3506 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3394 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3507 UNREACHABLE(); | 3395 UNREACHABLE(); |
3508 break; | 3396 break; |
3509 } | |
3510 } | |
3511 | |
3512 // Entry registers are intact, a0 holds the value | |
3513 // which is the return value. | |
3514 __ mov(v0, a0); | |
3515 __ Ret(); | |
3516 } else { | |
3517 // FPU is not available, do manual conversions. | |
3518 | |
3519 __ lw(t3, FieldMemOperand(value, HeapNumber::kExponentOffset)); | |
3520 __ lw(t4, FieldMemOperand(value, HeapNumber::kMantissaOffset)); | |
3521 | |
3522 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | |
3523 Label done, nan_or_infinity_or_zero; | |
3524 static const int kMantissaInHiWordShift = | |
3525 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; | |
3526 | |
3527 static const int kMantissaInLoWordShift = | |
3528 kBitsPerInt - kMantissaInHiWordShift; | |
3529 | |
3530 // Test for all special exponent values: zeros, subnormal numbers, NaNs | |
3531 // and infinities. All these should be converted to 0. | |
3532 __ li(t5, HeapNumber::kExponentMask); | |
3533 __ and_(t6, t3, t5); | |
3534 __ Branch(&nan_or_infinity_or_zero, eq, t6, Operand(zero_reg)); | |
3535 | |
3536 __ xor_(t1, t6, t5); | |
3537 __ li(t2, kBinary32ExponentMask); | |
3538 __ Movz(t6, t2, t1); // Only if t6 is equal to t5. | |
3539 __ Branch(&nan_or_infinity_or_zero, eq, t1, Operand(zero_reg)); | |
3540 | |
3541 // Rebias exponent. | |
3542 __ srl(t6, t6, HeapNumber::kExponentShift); | |
3543 __ Addu(t6, | |
3544 t6, | |
3545 Operand(kBinary32ExponentBias - HeapNumber::kExponentBias)); | |
3546 | |
3547 __ li(t1, Operand(kBinary32MaxExponent)); | |
3548 __ Slt(t1, t1, t6); | |
3549 __ And(t2, t3, Operand(HeapNumber::kSignMask)); | |
3550 __ Or(t2, t2, Operand(kBinary32ExponentMask)); | |
3551 __ Movn(t3, t2, t1); // Only if t6 is gt kBinary32MaxExponent. | |
3552 __ Branch(&done, gt, t6, Operand(kBinary32MaxExponent)); | |
3553 | |
3554 __ Slt(t1, t6, Operand(kBinary32MinExponent)); | |
3555 __ And(t2, t3, Operand(HeapNumber::kSignMask)); | |
3556 __ Movn(t3, t2, t1); // Only if t6 is lt kBinary32MinExponent. | |
3557 __ Branch(&done, lt, t6, Operand(kBinary32MinExponent)); | |
3558 | |
3559 __ And(t7, t3, Operand(HeapNumber::kSignMask)); | |
3560 __ And(t3, t3, Operand(HeapNumber::kMantissaMask)); | |
3561 __ sll(t3, t3, kMantissaInHiWordShift); | |
3562 __ or_(t7, t7, t3); | |
3563 __ srl(t4, t4, kMantissaInLoWordShift); | |
3564 __ or_(t7, t7, t4); | |
3565 __ sll(t6, t6, kBinary32ExponentShift); | |
3566 __ or_(t3, t7, t6); | |
3567 | |
3568 __ bind(&done); | |
3569 __ sll(t9, key, 1); | |
3570 __ addu(t9, a3, t9); | |
3571 __ sw(t3, MemOperand(t9, 0)); | |
3572 | |
3573 // Entry registers are intact, a0 holds the value which is the return | |
3574 // value. | |
3575 __ mov(v0, a0); | |
3576 __ Ret(); | |
3577 | |
3578 __ bind(&nan_or_infinity_or_zero); | |
3579 __ And(t7, t3, Operand(HeapNumber::kSignMask)); | |
3580 __ And(t3, t3, Operand(HeapNumber::kMantissaMask)); | |
3581 __ or_(t6, t6, t7); | |
3582 __ sll(t3, t3, kMantissaInHiWordShift); | |
3583 __ or_(t6, t6, t3); | |
3584 __ srl(t4, t4, kMantissaInLoWordShift); | |
3585 __ or_(t3, t6, t4); | |
3586 __ Branch(&done); | |
3587 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | |
3588 __ sll(t8, key, 2); | |
3589 __ addu(t8, a3, t8); | |
3590 // t8: effective address of destination element. | |
3591 __ sw(t4, MemOperand(t8, 0)); | |
3592 __ sw(t3, MemOperand(t8, Register::kSizeInBytes)); | |
3593 __ mov(v0, a0); | |
3594 __ Ret(); | |
3595 } else { | |
3596 bool is_signed_type = IsElementTypeSigned(elements_kind); | |
3597 int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt; | |
3598 int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000; | |
3599 | |
3600 Label done, sign; | |
3601 | |
3602 // Test for all special exponent values: zeros, subnormal numbers, NaNs | |
3603 // and infinities. All these should be converted to 0. | |
3604 __ li(t5, HeapNumber::kExponentMask); | |
3605 __ and_(t6, t3, t5); | |
3606 __ Movz(t3, zero_reg, t6); // Only if t6 is equal to zero. | |
3607 __ Branch(&done, eq, t6, Operand(zero_reg)); | |
3608 | |
3609 __ xor_(t2, t6, t5); | |
3610 __ Movz(t3, zero_reg, t2); // Only if t6 is equal to t5. | |
3611 __ Branch(&done, eq, t6, Operand(t5)); | |
3612 | |
3613 // Unbias exponent. | |
3614 __ srl(t6, t6, HeapNumber::kExponentShift); | |
3615 __ Subu(t6, t6, Operand(HeapNumber::kExponentBias)); | |
3616 // If exponent is negative then result is 0. | |
3617 __ slt(t2, t6, zero_reg); | |
3618 __ Movn(t3, zero_reg, t2); // Only if exponent is negative. | |
3619 __ Branch(&done, lt, t6, Operand(zero_reg)); | |
3620 | |
3621 // If exponent is too big then result is minimal value. | |
3622 __ slti(t1, t6, meaningfull_bits - 1); | |
3623 __ li(t2, min_value); | |
3624 __ Movz(t3, t2, t1); // Only if t6 is ge meaningfull_bits - 1. | |
3625 __ Branch(&done, ge, t6, Operand(meaningfull_bits - 1)); | |
3626 | |
3627 __ And(t5, t3, Operand(HeapNumber::kSignMask)); | |
3628 __ And(t3, t3, Operand(HeapNumber::kMantissaMask)); | |
3629 __ Or(t3, t3, Operand(1u << HeapNumber::kMantissaBitsInTopWord)); | |
3630 | |
3631 __ li(t9, HeapNumber::kMantissaBitsInTopWord); | |
3632 __ subu(t6, t9, t6); | |
3633 __ slt(t1, t6, zero_reg); | |
3634 __ srlv(t2, t3, t6); | |
3635 __ Movz(t3, t2, t1); // Only if t6 is positive. | |
3636 __ Branch(&sign, ge, t6, Operand(zero_reg)); | |
3637 | |
3638 __ subu(t6, zero_reg, t6); | |
3639 __ sllv(t3, t3, t6); | |
3640 __ li(t9, meaningfull_bits); | |
3641 __ subu(t6, t9, t6); | |
3642 __ srlv(t4, t4, t6); | |
3643 __ or_(t3, t3, t4); | |
3644 | |
3645 __ bind(&sign); | |
3646 __ subu(t2, t3, zero_reg); | |
3647 __ Movz(t3, t2, t5); // Only if t5 is zero. | |
3648 | |
3649 __ bind(&done); | |
3650 | |
3651 // Result is in t3. | |
3652 // This switch block should be exactly the same as above (FPU mode). | |
3653 switch (elements_kind) { | |
3654 case EXTERNAL_BYTE_ELEMENTS: | |
3655 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
3656 __ srl(t8, key, 1); | |
3657 __ addu(t8, a3, t8); | |
3658 __ sb(t3, MemOperand(t8, 0)); | |
3659 break; | |
3660 case EXTERNAL_SHORT_ELEMENTS: | |
3661 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
3662 __ addu(t8, a3, key); | |
3663 __ sh(t3, MemOperand(t8, 0)); | |
3664 break; | |
3665 case EXTERNAL_INT_ELEMENTS: | |
3666 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
3667 __ sll(t8, key, 1); | |
3668 __ addu(t8, a3, t8); | |
3669 __ sw(t3, MemOperand(t8, 0)); | |
3670 break; | |
3671 case EXTERNAL_PIXEL_ELEMENTS: | |
3672 case EXTERNAL_FLOAT_ELEMENTS: | |
3673 case EXTERNAL_DOUBLE_ELEMENTS: | |
3674 case FAST_ELEMENTS: | |
3675 case FAST_SMI_ELEMENTS: | |
3676 case FAST_DOUBLE_ELEMENTS: | |
3677 case FAST_HOLEY_ELEMENTS: | |
3678 case FAST_HOLEY_SMI_ELEMENTS: | |
3679 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
3680 case DICTIONARY_ELEMENTS: | |
3681 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
3682 UNREACHABLE(); | |
3683 break; | |
3684 } | |
3685 } | 3397 } |
3686 } | 3398 } |
| 3399 |
| 3400 // Entry registers are intact, a0 holds the value |
| 3401 // which is the return value. |
| 3402 __ mov(v0, a0); |
| 3403 __ Ret(); |
3687 } | 3404 } |
3688 | 3405 |
3689 // Slow case, key and receiver still in a0 and a1. | 3406 // Slow case, key and receiver still in a0 and a1. |
3690 __ bind(&slow); | 3407 __ bind(&slow); |
3691 __ IncrementCounter( | 3408 __ IncrementCounter( |
3692 masm->isolate()->counters()->keyed_load_external_array_slow(), | 3409 masm->isolate()->counters()->keyed_load_external_array_slow(), |
3693 1, a2, a3); | 3410 1, a2, a3); |
3694 // Entry registers are intact. | 3411 // Entry registers are intact. |
3695 // ---------- S t a t e -------------- | 3412 // ---------- S t a t e -------------- |
3696 // -- ra : return address | 3413 // -- ra : return address |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4028 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); | 3745 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
4029 } | 3746 } |
4030 } | 3747 } |
4031 | 3748 |
4032 | 3749 |
4033 #undef __ | 3750 #undef __ |
4034 | 3751 |
4035 } } // namespace v8::internal | 3752 } } // namespace v8::internal |
4036 | 3753 |
4037 #endif // V8_TARGET_ARCH_MIPS | 3754 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |