| 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 |