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 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 __ str(r1, MemOperand(r0, 2 * kPointerSize)); | 188 __ str(r1, MemOperand(r0, 2 * kPointerSize)); |
189 __ cmp(r0, sp); | 189 __ cmp(r0, sp); |
190 __ b(ne, &loop); | 190 __ b(ne, &loop); |
191 __ pop(r1); | 191 __ pop(r1); |
192 __ pop(r0); | 192 __ pop(r0); |
193 } else { | 193 } else { |
194 __ sub(sp, sp, Operand(slots * kPointerSize)); | 194 __ sub(sp, sp, Operand(slots * kPointerSize)); |
195 } | 195 } |
196 } | 196 } |
197 | 197 |
198 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(VFP2)) { | 198 if (info()->saves_caller_doubles()) { |
199 CpuFeatureScope scope(masm(), VFP2); | |
200 Comment(";;; Save clobbered callee double registers"); | 199 Comment(";;; Save clobbered callee double registers"); |
201 int count = 0; | 200 int count = 0; |
202 BitVector* doubles = chunk()->allocated_double_registers(); | 201 BitVector* doubles = chunk()->allocated_double_registers(); |
203 BitVector::Iterator save_iterator(doubles); | 202 BitVector::Iterator save_iterator(doubles); |
204 while (!save_iterator.Done()) { | 203 while (!save_iterator.Done()) { |
205 __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), | 204 __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
206 MemOperand(sp, count * kDoubleSize)); | 205 MemOperand(sp, count * kDoubleSize)); |
207 save_iterator.Advance(); | 206 save_iterator.Advance(); |
208 count++; | 207 count++; |
209 } | 208 } |
(...skipping 992 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1202 | 1201 |
1203 ASSERT(!dividend.is(divisor)); | 1202 ASSERT(!dividend.is(divisor)); |
1204 ASSERT(!dividend.is(quotient)); | 1203 ASSERT(!dividend.is(quotient)); |
1205 ASSERT(!divisor.is(quotient)); | 1204 ASSERT(!divisor.is(quotient)); |
1206 ASSERT(!scratch.is(left)); | 1205 ASSERT(!scratch.is(left)); |
1207 ASSERT(!scratch.is(right)); | 1206 ASSERT(!scratch.is(right)); |
1208 ASSERT(!scratch.is(result)); | 1207 ASSERT(!scratch.is(result)); |
1209 | 1208 |
1210 Label vfp_modulo, both_positive, right_negative; | 1209 Label vfp_modulo, both_positive, right_negative; |
1211 | 1210 |
1212 CpuFeatureScope scope(masm(), VFP2); | |
1213 | |
1214 // Check for x % 0. | 1211 // Check for x % 0. |
1215 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1212 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
1216 __ cmp(right, Operand::Zero()); | 1213 __ cmp(right, Operand::Zero()); |
1217 DeoptimizeIf(eq, instr->environment()); | 1214 DeoptimizeIf(eq, instr->environment()); |
1218 } | 1215 } |
1219 | 1216 |
1220 __ Move(result, left); | 1217 __ Move(result, left); |
1221 | 1218 |
1222 // (0 % x) must yield 0 (if x is finite, which is the case here). | 1219 // (0 % x) must yield 0 (if x is finite, which is the case here). |
1223 __ cmp(left, Operand::Zero()); | 1220 __ cmp(left, Operand::Zero()); |
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1608 | 1605 |
1609 __ bind(&done); | 1606 __ bind(&done); |
1610 } | 1607 } |
1611 } | 1608 } |
1612 | 1609 |
1613 | 1610 |
1614 void LCodeGen::DoDeferredBinaryOpStub(LPointerMap* pointer_map, | 1611 void LCodeGen::DoDeferredBinaryOpStub(LPointerMap* pointer_map, |
1615 LOperand* left_argument, | 1612 LOperand* left_argument, |
1616 LOperand* right_argument, | 1613 LOperand* right_argument, |
1617 Token::Value op) { | 1614 Token::Value op) { |
1618 CpuFeatureScope vfp_scope(masm(), VFP2); | |
1619 Register left = ToRegister(left_argument); | 1615 Register left = ToRegister(left_argument); |
1620 Register right = ToRegister(right_argument); | 1616 Register right = ToRegister(right_argument); |
1621 | 1617 |
1622 PushSafepointRegistersScope scope(this, Safepoint::kWithRegistersAndDoubles); | 1618 PushSafepointRegistersScope scope(this, Safepoint::kWithRegistersAndDoubles); |
1623 // Move left to r1 and right to r0 for the stub call. | 1619 // Move left to r1 and right to r0 for the stub call. |
1624 if (left.is(r1)) { | 1620 if (left.is(r1)) { |
1625 __ Move(r0, right); | 1621 __ Move(r0, right); |
1626 } else if (left.is(r0) && right.is(r1)) { | 1622 } else if (left.is(r0) && right.is(r1)) { |
1627 __ Swap(r0, r1, r2); | 1623 __ Swap(r0, r1, r2); |
1628 } else if (left.is(r0)) { | 1624 } else if (left.is(r0)) { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1894 | 1890 |
1895 void LCodeGen::DoConstantI(LConstantI* instr) { | 1891 void LCodeGen::DoConstantI(LConstantI* instr) { |
1896 ASSERT(instr->result()->IsRegister()); | 1892 ASSERT(instr->result()->IsRegister()); |
1897 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1893 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
1898 } | 1894 } |
1899 | 1895 |
1900 | 1896 |
1901 void LCodeGen::DoConstantD(LConstantD* instr) { | 1897 void LCodeGen::DoConstantD(LConstantD* instr) { |
1902 ASSERT(instr->result()->IsDoubleRegister()); | 1898 ASSERT(instr->result()->IsDoubleRegister()); |
1903 DwVfpRegister result = ToDoubleRegister(instr->result()); | 1899 DwVfpRegister result = ToDoubleRegister(instr->result()); |
1904 CpuFeatureScope scope(masm(), VFP2); | |
1905 double v = instr->value(); | 1900 double v = instr->value(); |
1906 __ Vmov(result, v, scratch0()); | 1901 __ Vmov(result, v, scratch0()); |
1907 } | 1902 } |
1908 | 1903 |
1909 | 1904 |
1910 void LCodeGen::DoConstantT(LConstantT* instr) { | 1905 void LCodeGen::DoConstantT(LConstantT* instr) { |
1911 Handle<Object> value = instr->value(); | 1906 Handle<Object> value = instr->value(); |
1912 if (value->IsSmi()) { | 1907 if (value->IsSmi()) { |
1913 __ mov(ToRegister(instr->result()), Operand(value)); | 1908 __ mov(ToRegister(instr->result()), Operand(value)); |
1914 } else { | 1909 } else { |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2065 ? ToOperand(right) | 2060 ? ToOperand(right) |
2066 : Operand(EmitLoadRegister(right, ip)); | 2061 : Operand(EmitLoadRegister(right, ip)); |
2067 Register result_reg = ToRegister(instr->result()); | 2062 Register result_reg = ToRegister(instr->result()); |
2068 __ cmp(left_reg, right_op); | 2063 __ cmp(left_reg, right_op); |
2069 if (!result_reg.is(left_reg)) { | 2064 if (!result_reg.is(left_reg)) { |
2070 __ mov(result_reg, left_reg, LeaveCC, condition); | 2065 __ mov(result_reg, left_reg, LeaveCC, condition); |
2071 } | 2066 } |
2072 __ mov(result_reg, right_op, LeaveCC, NegateCondition(condition)); | 2067 __ mov(result_reg, right_op, LeaveCC, NegateCondition(condition)); |
2073 } else { | 2068 } else { |
2074 ASSERT(instr->hydrogen()->representation().IsDouble()); | 2069 ASSERT(instr->hydrogen()->representation().IsDouble()); |
2075 CpuFeatureScope scope(masm(), VFP2); | |
2076 DwVfpRegister left_reg = ToDoubleRegister(left); | 2070 DwVfpRegister left_reg = ToDoubleRegister(left); |
2077 DwVfpRegister right_reg = ToDoubleRegister(right); | 2071 DwVfpRegister right_reg = ToDoubleRegister(right); |
2078 DwVfpRegister result_reg = ToDoubleRegister(instr->result()); | 2072 DwVfpRegister result_reg = ToDoubleRegister(instr->result()); |
2079 Label check_nan_left, check_zero, return_left, return_right, done; | 2073 Label check_nan_left, check_zero, return_left, return_right, done; |
2080 __ VFPCompareAndSetFlags(left_reg, right_reg); | 2074 __ VFPCompareAndSetFlags(left_reg, right_reg); |
2081 __ b(vs, &check_nan_left); | 2075 __ b(vs, &check_nan_left); |
2082 __ b(eq, &check_zero); | 2076 __ b(eq, &check_zero); |
2083 __ b(condition, &return_left); | 2077 __ b(condition, &return_left); |
2084 __ b(al, &return_right); | 2078 __ b(al, &return_right); |
2085 | 2079 |
(...skipping 25 matching lines...) Expand all Loading... |
2111 __ bind(&return_left); | 2105 __ bind(&return_left); |
2112 if (!left_reg.is(result_reg)) { | 2106 if (!left_reg.is(result_reg)) { |
2113 __ vmov(result_reg, left_reg); | 2107 __ vmov(result_reg, left_reg); |
2114 } | 2108 } |
2115 __ bind(&done); | 2109 __ bind(&done); |
2116 } | 2110 } |
2117 } | 2111 } |
2118 | 2112 |
2119 | 2113 |
2120 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 2114 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
2121 CpuFeatureScope scope(masm(), VFP2); | |
2122 DwVfpRegister left = ToDoubleRegister(instr->left()); | 2115 DwVfpRegister left = ToDoubleRegister(instr->left()); |
2123 DwVfpRegister right = ToDoubleRegister(instr->right()); | 2116 DwVfpRegister right = ToDoubleRegister(instr->right()); |
2124 DwVfpRegister result = ToDoubleRegister(instr->result()); | 2117 DwVfpRegister result = ToDoubleRegister(instr->result()); |
2125 switch (instr->op()) { | 2118 switch (instr->op()) { |
2126 case Token::ADD: | 2119 case Token::ADD: |
2127 __ vadd(result, left, right); | 2120 __ vadd(result, left, right); |
2128 break; | 2121 break; |
2129 case Token::SUB: | 2122 case Token::SUB: |
2130 __ vsub(result, left, right); | 2123 __ vsub(result, left, right); |
2131 break; | 2124 break; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2202 void LCodeGen::DoBranch(LBranch* instr) { | 2195 void LCodeGen::DoBranch(LBranch* instr) { |
2203 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2196 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2204 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2197 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2205 | 2198 |
2206 Representation r = instr->hydrogen()->value()->representation(); | 2199 Representation r = instr->hydrogen()->value()->representation(); |
2207 if (r.IsInteger32()) { | 2200 if (r.IsInteger32()) { |
2208 Register reg = ToRegister(instr->value()); | 2201 Register reg = ToRegister(instr->value()); |
2209 __ cmp(reg, Operand::Zero()); | 2202 __ cmp(reg, Operand::Zero()); |
2210 EmitBranch(true_block, false_block, ne); | 2203 EmitBranch(true_block, false_block, ne); |
2211 } else if (r.IsDouble()) { | 2204 } else if (r.IsDouble()) { |
2212 CpuFeatureScope scope(masm(), VFP2); | |
2213 DwVfpRegister reg = ToDoubleRegister(instr->value()); | 2205 DwVfpRegister reg = ToDoubleRegister(instr->value()); |
2214 Register scratch = scratch0(); | 2206 Register scratch = scratch0(); |
2215 | 2207 |
2216 // Test the double value. Zero and NaN are false. | 2208 // Test the double value. Zero and NaN are false. |
2217 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); | 2209 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); |
2218 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 2210 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); |
2219 EmitBranch(true_block, false_block, eq); | 2211 EmitBranch(true_block, false_block, eq); |
2220 } else { | 2212 } else { |
2221 ASSERT(r.IsTagged()); | 2213 ASSERT(r.IsTagged()); |
2222 Register reg = ToRegister(instr->value()); | 2214 Register reg = ToRegister(instr->value()); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2294 __ bind(¬_string); | 2286 __ bind(¬_string); |
2295 } | 2287 } |
2296 | 2288 |
2297 if (expected.Contains(ToBooleanStub::SYMBOL)) { | 2289 if (expected.Contains(ToBooleanStub::SYMBOL)) { |
2298 // Symbol value -> true. | 2290 // Symbol value -> true. |
2299 __ CompareInstanceType(map, ip, SYMBOL_TYPE); | 2291 __ CompareInstanceType(map, ip, SYMBOL_TYPE); |
2300 __ b(eq, true_label); | 2292 __ b(eq, true_label); |
2301 } | 2293 } |
2302 | 2294 |
2303 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 2295 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
2304 CpuFeatureScope scope(masm(), VFP2); | |
2305 // heap number -> false iff +0, -0, or NaN. | 2296 // heap number -> false iff +0, -0, or NaN. |
2306 DwVfpRegister dbl_scratch = double_scratch0(); | 2297 DwVfpRegister dbl_scratch = double_scratch0(); |
2307 Label not_heap_number; | 2298 Label not_heap_number; |
2308 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 2299 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
2309 __ b(ne, ¬_heap_number); | 2300 __ b(ne, ¬_heap_number); |
2310 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2301 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
2311 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); | 2302 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); |
2312 __ b(vs, false_label); // NaN -> false. | 2303 __ b(vs, false_label); // NaN -> false. |
2313 __ b(eq, false_label); // +0, -0 -> false. | 2304 __ b(eq, false_label); // +0, -0 -> false. |
2314 __ b(true_label); | 2305 __ b(true_label); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2374 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 2365 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
2375 // We can statically evaluate the comparison. | 2366 // We can statically evaluate the comparison. |
2376 double left_val = ToDouble(LConstantOperand::cast(left)); | 2367 double left_val = ToDouble(LConstantOperand::cast(left)); |
2377 double right_val = ToDouble(LConstantOperand::cast(right)); | 2368 double right_val = ToDouble(LConstantOperand::cast(right)); |
2378 int next_block = | 2369 int next_block = |
2379 EvalComparison(instr->op(), left_val, right_val) ? true_block | 2370 EvalComparison(instr->op(), left_val, right_val) ? true_block |
2380 : false_block; | 2371 : false_block; |
2381 EmitGoto(next_block); | 2372 EmitGoto(next_block); |
2382 } else { | 2373 } else { |
2383 if (instr->is_double()) { | 2374 if (instr->is_double()) { |
2384 CpuFeatureScope scope(masm(), VFP2); | |
2385 // Compare left and right operands as doubles and load the | 2375 // Compare left and right operands as doubles and load the |
2386 // resulting flags into the normal status register. | 2376 // resulting flags into the normal status register. |
2387 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); | 2377 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); |
2388 // If a NaN is involved, i.e. the result is unordered (V set), | 2378 // If a NaN is involved, i.e. the result is unordered (V set), |
2389 // jump to false block label. | 2379 // jump to false block label. |
2390 __ b(vs, chunk_->GetAssemblyLabel(false_block)); | 2380 __ b(vs, chunk_->GetAssemblyLabel(false_block)); |
2391 } else { | 2381 } else { |
2392 if (right->IsConstantOperand()) { | 2382 if (right->IsConstantOperand()) { |
2393 __ cmp(ToRegister(left), | 2383 __ cmp(ToRegister(left), |
2394 Operand(ToInteger32(LConstantOperand::cast(right)))); | 2384 Operand(ToInteger32(LConstantOperand::cast(right)))); |
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2929 } | 2919 } |
2930 | 2920 |
2931 | 2921 |
2932 void LCodeGen::DoReturn(LReturn* instr) { | 2922 void LCodeGen::DoReturn(LReturn* instr) { |
2933 if (FLAG_trace && info()->IsOptimizing()) { | 2923 if (FLAG_trace && info()->IsOptimizing()) { |
2934 // Push the return value on the stack as the parameter. | 2924 // Push the return value on the stack as the parameter. |
2935 // Runtime::TraceExit returns its parameter in r0. | 2925 // Runtime::TraceExit returns its parameter in r0. |
2936 __ push(r0); | 2926 __ push(r0); |
2937 __ CallRuntime(Runtime::kTraceExit, 1); | 2927 __ CallRuntime(Runtime::kTraceExit, 1); |
2938 } | 2928 } |
2939 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(VFP2)) { | 2929 if (info()->saves_caller_doubles()) { |
2940 CpuFeatureScope scope(masm(), VFP2); | |
2941 ASSERT(NeedsEagerFrame()); | 2930 ASSERT(NeedsEagerFrame()); |
2942 BitVector* doubles = chunk()->allocated_double_registers(); | 2931 BitVector* doubles = chunk()->allocated_double_registers(); |
2943 BitVector::Iterator save_iterator(doubles); | 2932 BitVector::Iterator save_iterator(doubles); |
2944 int count = 0; | 2933 int count = 0; |
2945 while (!save_iterator.Done()) { | 2934 while (!save_iterator.Done()) { |
2946 __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), | 2935 __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
2947 MemOperand(sp, count * kDoubleSize)); | 2936 MemOperand(sp, count * kDoubleSize)); |
2948 save_iterator.Advance(); | 2937 save_iterator.Advance(); |
2949 count++; | 2938 count++; |
2950 } | 2939 } |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3312 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 3301 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
3313 int additional_offset = instr->additional_index() << element_size_shift; | 3302 int additional_offset = instr->additional_index() << element_size_shift; |
3314 | 3303 |
3315 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 3304 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
3316 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 3305 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
3317 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3306 DwVfpRegister result = ToDoubleRegister(instr->result()); |
3318 Operand operand = key_is_constant | 3307 Operand operand = key_is_constant |
3319 ? Operand(constant_key << element_size_shift) | 3308 ? Operand(constant_key << element_size_shift) |
3320 : Operand(key, LSL, shift_size); | 3309 : Operand(key, LSL, shift_size); |
3321 __ add(scratch0(), external_pointer, operand); | 3310 __ add(scratch0(), external_pointer, operand); |
3322 if (CpuFeatures::IsSupported(VFP2)) { | 3311 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
3323 CpuFeatureScope scope(masm(), VFP2); | 3312 __ vldr(kScratchDoubleReg.low(), scratch0(), additional_offset); |
3324 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | 3313 __ vcvt_f64_f32(result, kScratchDoubleReg.low()); |
3325 __ vldr(kScratchDoubleReg.low(), scratch0(), additional_offset); | 3314 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
3326 __ vcvt_f64_f32(result, kScratchDoubleReg.low()); | 3315 __ vldr(result, scratch0(), additional_offset); |
3327 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS | |
3328 __ vldr(result, scratch0(), additional_offset); | |
3329 } | |
3330 } else { | |
3331 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | |
3332 Register value = external_pointer; | |
3333 __ ldr(value, MemOperand(scratch0(), additional_offset)); | |
3334 __ and_(sfpd_lo, value, Operand(kBinary32MantissaMask)); | |
3335 | |
3336 __ mov(scratch0(), Operand(value, LSR, kBinary32MantissaBits)); | |
3337 __ and_(scratch0(), scratch0(), | |
3338 Operand(kBinary32ExponentMask >> kBinary32MantissaBits)); | |
3339 | |
3340 Label exponent_rebiased; | |
3341 __ teq(scratch0(), Operand(0x00)); | |
3342 __ b(eq, &exponent_rebiased); | |
3343 | |
3344 __ teq(scratch0(), Operand(0xff)); | |
3345 __ mov(scratch0(), Operand(0x7ff), LeaveCC, eq); | |
3346 __ b(eq, &exponent_rebiased); | |
3347 | |
3348 // Rebias exponent. | |
3349 __ add(scratch0(), | |
3350 scratch0(), | |
3351 Operand(-kBinary32ExponentBias + HeapNumber::kExponentBias)); | |
3352 | |
3353 __ bind(&exponent_rebiased); | |
3354 __ and_(sfpd_hi, value, Operand(kBinary32SignMask)); | |
3355 __ orr(sfpd_hi, sfpd_hi, | |
3356 Operand(scratch0(), LSL, HeapNumber::kMantissaBitsInTopWord)); | |
3357 | |
3358 // Shift mantissa. | |
3359 static const int kMantissaShiftForHiWord = | |
3360 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; | |
3361 | |
3362 static const int kMantissaShiftForLoWord = | |
3363 kBitsPerInt - kMantissaShiftForHiWord; | |
3364 | |
3365 __ orr(sfpd_hi, sfpd_hi, | |
3366 Operand(sfpd_lo, LSR, kMantissaShiftForHiWord)); | |
3367 __ mov(sfpd_lo, Operand(sfpd_lo, LSL, kMantissaShiftForLoWord)); | |
3368 | |
3369 } else { | |
3370 __ ldr(sfpd_lo, MemOperand(scratch0(), additional_offset)); | |
3371 __ ldr(sfpd_hi, MemOperand(scratch0(), | |
3372 additional_offset + kPointerSize)); | |
3373 } | |
3374 } | 3316 } |
3375 } else { | 3317 } else { |
3376 Register result = ToRegister(instr->result()); | 3318 Register result = ToRegister(instr->result()); |
3377 MemOperand mem_operand = PrepareKeyedOperand( | 3319 MemOperand mem_operand = PrepareKeyedOperand( |
3378 key, external_pointer, key_is_constant, constant_key, | 3320 key, external_pointer, key_is_constant, constant_key, |
3379 element_size_shift, shift_size, | 3321 element_size_shift, shift_size, |
3380 instr->additional_index(), additional_offset); | 3322 instr->additional_index(), additional_offset); |
3381 switch (elements_kind) { | 3323 switch (elements_kind) { |
3382 case EXTERNAL_BYTE_ELEMENTS: | 3324 case EXTERNAL_BYTE_ELEMENTS: |
3383 __ ldrsb(result, mem_operand); | 3325 __ ldrsb(result, mem_operand); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3437 } | 3379 } |
3438 } else { | 3380 } else { |
3439 key = ToRegister(instr->key()); | 3381 key = ToRegister(instr->key()); |
3440 } | 3382 } |
3441 | 3383 |
3442 int base_offset = (FixedDoubleArray::kHeaderSize - kHeapObjectTag) + | 3384 int base_offset = (FixedDoubleArray::kHeaderSize - kHeapObjectTag) + |
3443 ((constant_key + instr->additional_index()) << element_size_shift); | 3385 ((constant_key + instr->additional_index()) << element_size_shift); |
3444 if (!key_is_constant) { | 3386 if (!key_is_constant) { |
3445 __ add(elements, elements, Operand(key, LSL, shift_size)); | 3387 __ add(elements, elements, Operand(key, LSL, shift_size)); |
3446 } | 3388 } |
3447 if (CpuFeatures::IsSupported(VFP2)) { | 3389 __ add(elements, elements, Operand(base_offset)); |
3448 CpuFeatureScope scope(masm(), VFP2); | 3390 __ vldr(result, elements, 0); |
3449 __ add(elements, elements, Operand(base_offset)); | 3391 if (instr->hydrogen()->RequiresHoleCheck()) { |
3450 __ vldr(result, elements, 0); | 3392 __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); |
3451 if (instr->hydrogen()->RequiresHoleCheck()) { | 3393 __ cmp(scratch, Operand(kHoleNanUpper32)); |
3452 __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); | 3394 DeoptimizeIf(eq, instr->environment()); |
3453 __ cmp(scratch, Operand(kHoleNanUpper32)); | |
3454 DeoptimizeIf(eq, instr->environment()); | |
3455 } | |
3456 } else { | |
3457 __ ldr(sfpd_hi, MemOperand(elements, base_offset + kPointerSize)); | |
3458 __ ldr(sfpd_lo, MemOperand(elements, base_offset)); | |
3459 if (instr->hydrogen()->RequiresHoleCheck()) { | |
3460 ASSERT(kPointerSize == sizeof(kHoleNanLower32)); | |
3461 __ cmp(sfpd_hi, Operand(kHoleNanUpper32)); | |
3462 DeoptimizeIf(eq, instr->environment()); | |
3463 } | |
3464 } | 3395 } |
3465 } | 3396 } |
3466 | 3397 |
3467 | 3398 |
3468 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3399 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
3469 Register elements = ToRegister(instr->elements()); | 3400 Register elements = ToRegister(instr->elements()); |
3470 Register result = ToRegister(instr->result()); | 3401 Register result = ToRegister(instr->result()); |
3471 Register scratch = scratch0(); | 3402 Register scratch = scratch0(); |
3472 Register store_base = scratch; | 3403 Register store_base = scratch; |
3473 int offset = 0; | 3404 int offset = 0; |
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3895 // We can make rsb conditional because the previous cmp instruction | 3826 // We can make rsb conditional because the previous cmp instruction |
3896 // will clear the V (overflow) flag and rsb won't set this flag | 3827 // will clear the V (overflow) flag and rsb won't set this flag |
3897 // if input is positive. | 3828 // if input is positive. |
3898 __ rsb(result, input, Operand::Zero(), SetCC, mi); | 3829 __ rsb(result, input, Operand::Zero(), SetCC, mi); |
3899 // Deoptimize on overflow. | 3830 // Deoptimize on overflow. |
3900 DeoptimizeIf(vs, instr->environment()); | 3831 DeoptimizeIf(vs, instr->environment()); |
3901 } | 3832 } |
3902 | 3833 |
3903 | 3834 |
3904 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 3835 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
3905 CpuFeatureScope scope(masm(), VFP2); | |
3906 // Class for deferred case. | 3836 // Class for deferred case. |
3907 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3837 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
3908 public: | 3838 public: |
3909 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 3839 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
3910 LUnaryMathOperation* instr) | 3840 LUnaryMathOperation* instr) |
3911 : LDeferredCode(codegen), instr_(instr) { } | 3841 : LDeferredCode(codegen), instr_(instr) { } |
3912 virtual void Generate() { | 3842 virtual void Generate() { |
3913 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3843 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
3914 } | 3844 } |
3915 virtual LInstruction* instr() { return instr_; } | 3845 virtual LInstruction* instr() { return instr_; } |
(...skipping 16 matching lines...) Expand all Loading... |
3932 // Smi check. | 3862 // Smi check. |
3933 __ JumpIfNotSmi(input, deferred->entry()); | 3863 __ JumpIfNotSmi(input, deferred->entry()); |
3934 // If smi, handle it directly. | 3864 // If smi, handle it directly. |
3935 EmitIntegerMathAbs(instr); | 3865 EmitIntegerMathAbs(instr); |
3936 __ bind(deferred->exit()); | 3866 __ bind(deferred->exit()); |
3937 } | 3867 } |
3938 } | 3868 } |
3939 | 3869 |
3940 | 3870 |
3941 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 3871 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
3942 CpuFeatureScope scope(masm(), VFP2); | |
3943 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3872 DwVfpRegister input = ToDoubleRegister(instr->value()); |
3944 Register result = ToRegister(instr->result()); | 3873 Register result = ToRegister(instr->result()); |
3945 Register input_high = scratch0(); | 3874 Register input_high = scratch0(); |
3946 Label done, exact; | 3875 Label done, exact; |
3947 | 3876 |
3948 __ vmov(input_high, input.high()); | 3877 __ vmov(input_high, input.high()); |
3949 __ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact); | 3878 __ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact); |
3950 DeoptimizeIf(al, instr->environment()); | 3879 DeoptimizeIf(al, instr->environment()); |
3951 | 3880 |
3952 __ bind(&exact); | 3881 __ bind(&exact); |
3953 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3882 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3954 // Test for -0. | 3883 // Test for -0. |
3955 __ cmp(result, Operand::Zero()); | 3884 __ cmp(result, Operand::Zero()); |
3956 __ b(ne, &done); | 3885 __ b(ne, &done); |
3957 __ cmp(input_high, Operand::Zero()); | 3886 __ cmp(input_high, Operand::Zero()); |
3958 DeoptimizeIf(mi, instr->environment()); | 3887 DeoptimizeIf(mi, instr->environment()); |
3959 } | 3888 } |
3960 __ bind(&done); | 3889 __ bind(&done); |
3961 } | 3890 } |
3962 | 3891 |
3963 | 3892 |
3964 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 3893 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
3965 CpuFeatureScope scope(masm(), VFP2); | |
3966 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3894 DwVfpRegister input = ToDoubleRegister(instr->value()); |
3967 Register result = ToRegister(instr->result()); | 3895 Register result = ToRegister(instr->result()); |
3968 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp()); | 3896 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp()); |
3969 DwVfpRegister input_plus_dot_five = double_scratch1; | 3897 DwVfpRegister input_plus_dot_five = double_scratch1; |
3970 Register input_high = scratch0(); | 3898 Register input_high = scratch0(); |
3971 DwVfpRegister dot_five = double_scratch0(); | 3899 DwVfpRegister dot_five = double_scratch0(); |
3972 Label convert, done; | 3900 Label convert, done; |
3973 | 3901 |
3974 __ Vmov(dot_five, 0.5, scratch0()); | 3902 __ Vmov(dot_five, 0.5, scratch0()); |
3975 __ vabs(double_scratch1, input); | 3903 __ vabs(double_scratch1, input); |
(...skipping 19 matching lines...) Expand all Loading... |
3995 __ vmov(input_high, input_plus_dot_five.high()); | 3923 __ vmov(input_high, input_plus_dot_five.high()); |
3996 // Reuse dot_five (double_scratch0) as we no longer need this value. | 3924 // Reuse dot_five (double_scratch0) as we no longer need this value. |
3997 __ TryInt32Floor(result, input_plus_dot_five, input_high, double_scratch0(), | 3925 __ TryInt32Floor(result, input_plus_dot_five, input_high, double_scratch0(), |
3998 &done, &done); | 3926 &done, &done); |
3999 DeoptimizeIf(al, instr->environment()); | 3927 DeoptimizeIf(al, instr->environment()); |
4000 __ bind(&done); | 3928 __ bind(&done); |
4001 } | 3929 } |
4002 | 3930 |
4003 | 3931 |
4004 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 3932 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
4005 CpuFeatureScope scope(masm(), VFP2); | |
4006 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3933 DwVfpRegister input = ToDoubleRegister(instr->value()); |
4007 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3934 DwVfpRegister result = ToDoubleRegister(instr->result()); |
4008 __ vsqrt(result, input); | 3935 __ vsqrt(result, input); |
4009 } | 3936 } |
4010 | 3937 |
4011 | 3938 |
4012 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 3939 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
4013 CpuFeatureScope scope(masm(), VFP2); | |
4014 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3940 DwVfpRegister input = ToDoubleRegister(instr->value()); |
4015 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3941 DwVfpRegister result = ToDoubleRegister(instr->result()); |
4016 DwVfpRegister temp = ToDoubleRegister(instr->temp()); | 3942 DwVfpRegister temp = ToDoubleRegister(instr->temp()); |
4017 | 3943 |
4018 // Note that according to ECMA-262 15.8.2.13: | 3944 // Note that according to ECMA-262 15.8.2.13: |
4019 // Math.pow(-Infinity, 0.5) == Infinity | 3945 // Math.pow(-Infinity, 0.5) == Infinity |
4020 // Math.sqrt(-Infinity) == NaN | 3946 // Math.sqrt(-Infinity) == NaN |
4021 Label done; | 3947 Label done; |
4022 __ vmov(temp, -V8_INFINITY, scratch0()); | 3948 __ vmov(temp, -V8_INFINITY, scratch0()); |
4023 __ VFPCompareAndSetFlags(input, temp); | 3949 __ VFPCompareAndSetFlags(input, temp); |
4024 __ vneg(result, temp, eq); | 3950 __ vneg(result, temp, eq); |
4025 __ b(&done, eq); | 3951 __ b(&done, eq); |
4026 | 3952 |
4027 // Add +0 to convert -0 to +0. | 3953 // Add +0 to convert -0 to +0. |
4028 __ vadd(result, input, kDoubleRegZero); | 3954 __ vadd(result, input, kDoubleRegZero); |
4029 __ vsqrt(result, result); | 3955 __ vsqrt(result, result); |
4030 __ bind(&done); | 3956 __ bind(&done); |
4031 } | 3957 } |
4032 | 3958 |
4033 | 3959 |
4034 void LCodeGen::DoPower(LPower* instr) { | 3960 void LCodeGen::DoPower(LPower* instr) { |
4035 CpuFeatureScope scope(masm(), VFP2); | |
4036 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3961 Representation exponent_type = instr->hydrogen()->right()->representation(); |
4037 // Having marked this as a call, we can use any registers. | 3962 // Having marked this as a call, we can use any registers. |
4038 // Just make sure that the input/output registers are the expected ones. | 3963 // Just make sure that the input/output registers are the expected ones. |
4039 ASSERT(!instr->right()->IsDoubleRegister() || | 3964 ASSERT(!instr->right()->IsDoubleRegister() || |
4040 ToDoubleRegister(instr->right()).is(d2)); | 3965 ToDoubleRegister(instr->right()).is(d2)); |
4041 ASSERT(!instr->right()->IsRegister() || | 3966 ASSERT(!instr->right()->IsRegister() || |
4042 ToRegister(instr->right()).is(r2)); | 3967 ToRegister(instr->right()).is(r2)); |
4043 ASSERT(ToDoubleRegister(instr->left()).is(d1)); | 3968 ASSERT(ToDoubleRegister(instr->left()).is(d1)); |
4044 ASSERT(ToDoubleRegister(instr->result()).is(d3)); | 3969 ASSERT(ToDoubleRegister(instr->result()).is(d3)); |
4045 | 3970 |
(...skipping 12 matching lines...) Expand all Loading... |
4058 __ CallStub(&stub); | 3983 __ CallStub(&stub); |
4059 } else { | 3984 } else { |
4060 ASSERT(exponent_type.IsDouble()); | 3985 ASSERT(exponent_type.IsDouble()); |
4061 MathPowStub stub(MathPowStub::DOUBLE); | 3986 MathPowStub stub(MathPowStub::DOUBLE); |
4062 __ CallStub(&stub); | 3987 __ CallStub(&stub); |
4063 } | 3988 } |
4064 } | 3989 } |
4065 | 3990 |
4066 | 3991 |
4067 void LCodeGen::DoRandom(LRandom* instr) { | 3992 void LCodeGen::DoRandom(LRandom* instr) { |
4068 CpuFeatureScope scope(masm(), VFP2); | |
4069 class DeferredDoRandom: public LDeferredCode { | 3993 class DeferredDoRandom: public LDeferredCode { |
4070 public: | 3994 public: |
4071 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) | 3995 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) |
4072 : LDeferredCode(codegen), instr_(instr) { } | 3996 : LDeferredCode(codegen), instr_(instr) { } |
4073 virtual void Generate() { codegen()->DoDeferredRandom(instr_); } | 3997 virtual void Generate() { codegen()->DoDeferredRandom(instr_); } |
4074 virtual LInstruction* instr() { return instr_; } | 3998 virtual LInstruction* instr() { return instr_; } |
4075 private: | 3999 private: |
4076 LRandom* instr_; | 4000 LRandom* instr_; |
4077 }; | 4001 }; |
4078 | 4002 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4137 | 4061 |
4138 | 4062 |
4139 void LCodeGen::DoDeferredRandom(LRandom* instr) { | 4063 void LCodeGen::DoDeferredRandom(LRandom* instr) { |
4140 __ PrepareCallCFunction(1, scratch0()); | 4064 __ PrepareCallCFunction(1, scratch0()); |
4141 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); | 4065 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); |
4142 // Return value is in r0. | 4066 // Return value is in r0. |
4143 } | 4067 } |
4144 | 4068 |
4145 | 4069 |
4146 void LCodeGen::DoMathExp(LMathExp* instr) { | 4070 void LCodeGen::DoMathExp(LMathExp* instr) { |
4147 CpuFeatureScope scope(masm(), VFP2); | |
4148 DwVfpRegister input = ToDoubleRegister(instr->value()); | 4071 DwVfpRegister input = ToDoubleRegister(instr->value()); |
4149 DwVfpRegister result = ToDoubleRegister(instr->result()); | 4072 DwVfpRegister result = ToDoubleRegister(instr->result()); |
4150 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->double_temp()); | 4073 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->double_temp()); |
4151 DwVfpRegister double_scratch2 = double_scratch0(); | 4074 DwVfpRegister double_scratch2 = double_scratch0(); |
4152 Register temp1 = ToRegister(instr->temp1()); | 4075 Register temp1 = ToRegister(instr->temp1()); |
4153 Register temp2 = ToRegister(instr->temp2()); | 4076 Register temp2 = ToRegister(instr->temp2()); |
4154 | 4077 |
4155 MathExpGenerator::EmitMathExp( | 4078 MathExpGenerator::EmitMathExp( |
4156 masm(), input, result, double_scratch1, double_scratch2, | 4079 masm(), input, result, double_scratch1, double_scratch2, |
4157 temp1, temp2, scratch0()); | 4080 temp1, temp2, scratch0()); |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4435 } | 4358 } |
4436 __ cmp(ip, ToRegister(instr->length())); | 4359 __ cmp(ip, ToRegister(instr->length())); |
4437 } else { | 4360 } else { |
4438 __ cmp(ToRegister(instr->index()), ToRegister(instr->length())); | 4361 __ cmp(ToRegister(instr->index()), ToRegister(instr->length())); |
4439 } | 4362 } |
4440 DeoptimizeIf(hs, instr->environment()); | 4363 DeoptimizeIf(hs, instr->environment()); |
4441 } | 4364 } |
4442 | 4365 |
4443 | 4366 |
4444 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4367 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
4445 CpuFeatureScope scope(masm(), VFP2); | |
4446 Register external_pointer = ToRegister(instr->elements()); | 4368 Register external_pointer = ToRegister(instr->elements()); |
4447 Register key = no_reg; | 4369 Register key = no_reg; |
4448 ElementsKind elements_kind = instr->elements_kind(); | 4370 ElementsKind elements_kind = instr->elements_kind(); |
4449 bool key_is_constant = instr->key()->IsConstantOperand(); | 4371 bool key_is_constant = instr->key()->IsConstantOperand(); |
4450 int constant_key = 0; | 4372 int constant_key = 0; |
4451 if (key_is_constant) { | 4373 if (key_is_constant) { |
4452 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 4374 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
4453 if (constant_key & 0xF0000000) { | 4375 if (constant_key & 0xF0000000) { |
4454 Abort("array index constant value too big."); | 4376 Abort("array index constant value too big."); |
4455 } | 4377 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4506 case DICTIONARY_ELEMENTS: | 4428 case DICTIONARY_ELEMENTS: |
4507 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4429 case NON_STRICT_ARGUMENTS_ELEMENTS: |
4508 UNREACHABLE(); | 4430 UNREACHABLE(); |
4509 break; | 4431 break; |
4510 } | 4432 } |
4511 } | 4433 } |
4512 } | 4434 } |
4513 | 4435 |
4514 | 4436 |
4515 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { | 4437 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { |
4516 CpuFeatureScope scope(masm(), VFP2); | |
4517 DwVfpRegister value = ToDoubleRegister(instr->value()); | 4438 DwVfpRegister value = ToDoubleRegister(instr->value()); |
4518 Register elements = ToRegister(instr->elements()); | 4439 Register elements = ToRegister(instr->elements()); |
4519 Register key = no_reg; | 4440 Register key = no_reg; |
4520 Register scratch = scratch0(); | 4441 Register scratch = scratch0(); |
4521 bool key_is_constant = instr->key()->IsConstantOperand(); | 4442 bool key_is_constant = instr->key()->IsConstantOperand(); |
4522 int constant_key = 0; | 4443 int constant_key = 0; |
4523 | 4444 |
4524 // Calculate the effective address of the slot in the array to store the | 4445 // Calculate the effective address of the slot in the array to store the |
4525 // double value. | 4446 // double value. |
4526 if (key_is_constant) { | 4447 if (key_is_constant) { |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4807 | 4728 |
4808 | 4729 |
4809 void LCodeGen::DoStringLength(LStringLength* instr) { | 4730 void LCodeGen::DoStringLength(LStringLength* instr) { |
4810 Register string = ToRegister(instr->string()); | 4731 Register string = ToRegister(instr->string()); |
4811 Register result = ToRegister(instr->result()); | 4732 Register result = ToRegister(instr->result()); |
4812 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); | 4733 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); |
4813 } | 4734 } |
4814 | 4735 |
4815 | 4736 |
4816 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4737 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
4817 CpuFeatureScope scope(masm(), VFP2); | |
4818 LOperand* input = instr->value(); | 4738 LOperand* input = instr->value(); |
4819 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4739 ASSERT(input->IsRegister() || input->IsStackSlot()); |
4820 LOperand* output = instr->result(); | 4740 LOperand* output = instr->result(); |
4821 ASSERT(output->IsDoubleRegister()); | 4741 ASSERT(output->IsDoubleRegister()); |
4822 SwVfpRegister single_scratch = double_scratch0().low(); | 4742 SwVfpRegister single_scratch = double_scratch0().low(); |
4823 if (input->IsStackSlot()) { | 4743 if (input->IsStackSlot()) { |
4824 Register scratch = scratch0(); | 4744 Register scratch = scratch0(); |
4825 __ ldr(scratch, ToMemOperand(input)); | 4745 __ ldr(scratch, ToMemOperand(input)); |
4826 __ vmov(single_scratch, scratch); | 4746 __ vmov(single_scratch, scratch); |
4827 } else { | 4747 } else { |
4828 __ vmov(single_scratch, ToRegister(input)); | 4748 __ vmov(single_scratch, ToRegister(input)); |
4829 } | 4749 } |
4830 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); | 4750 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); |
4831 } | 4751 } |
4832 | 4752 |
4833 | 4753 |
4834 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 4754 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
4835 CpuFeatureScope scope(masm(), VFP2); | |
4836 LOperand* input = instr->value(); | 4755 LOperand* input = instr->value(); |
4837 LOperand* output = instr->result(); | 4756 LOperand* output = instr->result(); |
4838 | 4757 |
4839 SwVfpRegister flt_scratch = double_scratch0().low(); | 4758 SwVfpRegister flt_scratch = double_scratch0().low(); |
4840 __ vmov(flt_scratch, ToRegister(input)); | 4759 __ vmov(flt_scratch, ToRegister(input)); |
4841 __ vcvt_f64_u32(ToDoubleRegister(output), flt_scratch); | 4760 __ vcvt_f64_u32(ToDoubleRegister(output), flt_scratch); |
4842 } | 4761 } |
4843 | 4762 |
4844 | 4763 |
4845 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4764 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4887 Register reg = ToRegister(input); | 4806 Register reg = ToRegister(input); |
4888 | 4807 |
4889 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4808 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
4890 __ cmp(reg, Operand(Smi::kMaxValue)); | 4809 __ cmp(reg, Operand(Smi::kMaxValue)); |
4891 __ b(hi, deferred->entry()); | 4810 __ b(hi, deferred->entry()); |
4892 __ SmiTag(reg, reg); | 4811 __ SmiTag(reg, reg); |
4893 __ bind(deferred->exit()); | 4812 __ bind(deferred->exit()); |
4894 } | 4813 } |
4895 | 4814 |
4896 | 4815 |
4897 // Convert unsigned integer with specified number of leading zeroes in binary | |
4898 // representation to IEEE 754 double. | |
4899 // Integer to convert is passed in register src. | |
4900 // Resulting double is returned in registers hiword:loword. | |
4901 // This functions does not work correctly for 0. | |
4902 static void GenerateUInt2Double(MacroAssembler* masm, | |
4903 Register src, | |
4904 Register hiword, | |
4905 Register loword, | |
4906 Register scratch, | |
4907 int leading_zeroes) { | |
4908 const int meaningful_bits = kBitsPerInt - leading_zeroes - 1; | |
4909 const int biased_exponent = HeapNumber::kExponentBias + meaningful_bits; | |
4910 | |
4911 const int mantissa_shift_for_hi_word = | |
4912 meaningful_bits - HeapNumber::kMantissaBitsInTopWord; | |
4913 const int mantissa_shift_for_lo_word = | |
4914 kBitsPerInt - mantissa_shift_for_hi_word; | |
4915 masm->mov(scratch, Operand(biased_exponent << HeapNumber::kExponentShift)); | |
4916 if (mantissa_shift_for_hi_word > 0) { | |
4917 masm->mov(loword, Operand(src, LSL, mantissa_shift_for_lo_word)); | |
4918 masm->orr(hiword, scratch, | |
4919 Operand(src, LSR, mantissa_shift_for_hi_word)); | |
4920 } else { | |
4921 masm->mov(loword, Operand::Zero()); | |
4922 masm->orr(hiword, scratch, | |
4923 Operand(src, LSL, -mantissa_shift_for_hi_word)); | |
4924 } | |
4925 | |
4926 // If least significant bit of biased exponent was not 1 it was corrupted | |
4927 // by most significant bit of mantissa so we should fix that. | |
4928 if (!(biased_exponent & 1)) { | |
4929 masm->bic(hiword, hiword, Operand(1 << HeapNumber::kExponentShift)); | |
4930 } | |
4931 } | |
4932 | |
4933 | |
4934 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, | 4816 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, |
4935 LOperand* value, | 4817 LOperand* value, |
4936 IntegerSignedness signedness) { | 4818 IntegerSignedness signedness) { |
4937 Label slow; | 4819 Label slow; |
4938 Register src = ToRegister(value); | 4820 Register src = ToRegister(value); |
4939 Register dst = ToRegister(instr->result()); | 4821 Register dst = ToRegister(instr->result()); |
4940 DwVfpRegister dbl_scratch = double_scratch0(); | 4822 DwVfpRegister dbl_scratch = double_scratch0(); |
4941 SwVfpRegister flt_scratch = dbl_scratch.low(); | 4823 SwVfpRegister flt_scratch = dbl_scratch.low(); |
4942 | 4824 |
4943 // Preserve the value of all registers. | 4825 // Preserve the value of all registers. |
4944 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4826 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4945 | 4827 |
4946 Label done; | 4828 Label done; |
4947 if (signedness == SIGNED_INT32) { | 4829 if (signedness == SIGNED_INT32) { |
4948 // There was overflow, so bits 30 and 31 of the original integer | 4830 // There was overflow, so bits 30 and 31 of the original integer |
4949 // disagree. Try to allocate a heap number in new space and store | 4831 // disagree. Try to allocate a heap number in new space and store |
4950 // the value in there. If that fails, call the runtime system. | 4832 // the value in there. If that fails, call the runtime system. |
4951 if (dst.is(src)) { | 4833 if (dst.is(src)) { |
4952 __ SmiUntag(src, dst); | 4834 __ SmiUntag(src, dst); |
4953 __ eor(src, src, Operand(0x80000000)); | 4835 __ eor(src, src, Operand(0x80000000)); |
4954 } | 4836 } |
4955 if (CpuFeatures::IsSupported(VFP2)) { | 4837 __ vmov(flt_scratch, src); |
4956 CpuFeatureScope scope(masm(), VFP2); | 4838 __ vcvt_f64_s32(dbl_scratch, flt_scratch); |
4957 __ vmov(flt_scratch, src); | |
4958 __ vcvt_f64_s32(dbl_scratch, flt_scratch); | |
4959 } else { | |
4960 FloatingPointHelper::Destination dest = | |
4961 FloatingPointHelper::kCoreRegisters; | |
4962 FloatingPointHelper::ConvertIntToDouble(masm(), src, dest, d0, | |
4963 sfpd_lo, sfpd_hi, | |
4964 scratch0(), s0); | |
4965 } | |
4966 } else { | 4839 } else { |
4967 if (CpuFeatures::IsSupported(VFP2)) { | 4840 __ vmov(flt_scratch, src); |
4968 CpuFeatureScope scope(masm(), VFP2); | 4841 __ vcvt_f64_u32(dbl_scratch, flt_scratch); |
4969 __ vmov(flt_scratch, src); | |
4970 __ vcvt_f64_u32(dbl_scratch, flt_scratch); | |
4971 } else { | |
4972 Label no_leading_zero, convert_done; | |
4973 __ tst(src, Operand(0x80000000)); | |
4974 __ b(ne, &no_leading_zero); | |
4975 | |
4976 // Integer has one leading zeros. | |
4977 GenerateUInt2Double(masm(), src, sfpd_hi, sfpd_lo, r9, 1); | |
4978 __ b(&convert_done); | |
4979 | |
4980 __ bind(&no_leading_zero); | |
4981 GenerateUInt2Double(masm(), src, sfpd_hi, sfpd_lo, r9, 0); | |
4982 __ bind(&convert_done); | |
4983 } | |
4984 } | 4842 } |
4985 | 4843 |
4986 if (FLAG_inline_new) { | 4844 if (FLAG_inline_new) { |
4987 __ LoadRoot(scratch0(), Heap::kHeapNumberMapRootIndex); | 4845 __ LoadRoot(scratch0(), Heap::kHeapNumberMapRootIndex); |
4988 __ AllocateHeapNumber(r5, r3, r4, scratch0(), &slow, DONT_TAG_RESULT); | 4846 __ AllocateHeapNumber(r5, r3, r4, scratch0(), &slow, DONT_TAG_RESULT); |
4989 __ Move(dst, r5); | 4847 __ Move(dst, r5); |
4990 __ b(&done); | 4848 __ b(&done); |
4991 } | 4849 } |
4992 | 4850 |
4993 // Slow case: Call the runtime system to do the number allocation. | 4851 // Slow case: Call the runtime system to do the number allocation. |
4994 __ bind(&slow); | 4852 __ bind(&slow); |
4995 | 4853 |
4996 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 4854 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
4997 // register is stored, as this register is in the pointer map, but contains an | 4855 // register is stored, as this register is in the pointer map, but contains an |
4998 // integer value. | 4856 // integer value. |
4999 if (!CpuFeatures::IsSupported(VFP2)) { | |
5000 // Preserve sfpd_lo. | |
5001 __ mov(r9, sfpd_lo); | |
5002 } | |
5003 __ mov(ip, Operand::Zero()); | 4857 __ mov(ip, Operand::Zero()); |
5004 __ StoreToSafepointRegisterSlot(ip, dst); | 4858 __ StoreToSafepointRegisterSlot(ip, dst); |
5005 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4859 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
5006 __ Move(dst, r0); | 4860 __ Move(dst, r0); |
5007 if (!CpuFeatures::IsSupported(VFP2)) { | |
5008 // Restore sfpd_lo. | |
5009 __ mov(sfpd_lo, r9); | |
5010 } | |
5011 __ sub(dst, dst, Operand(kHeapObjectTag)); | 4861 __ sub(dst, dst, Operand(kHeapObjectTag)); |
5012 | 4862 |
5013 // Done. Put the value in dbl_scratch into the value of the allocated heap | 4863 // Done. Put the value in dbl_scratch into the value of the allocated heap |
5014 // number. | 4864 // number. |
5015 __ bind(&done); | 4865 __ bind(&done); |
5016 if (CpuFeatures::IsSupported(VFP2)) { | 4866 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); |
5017 CpuFeatureScope scope(masm(), VFP2); | |
5018 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); | |
5019 } else { | |
5020 __ str(sfpd_lo, MemOperand(dst, HeapNumber::kMantissaOffset)); | |
5021 __ str(sfpd_hi, MemOperand(dst, HeapNumber::kExponentOffset)); | |
5022 } | |
5023 __ add(dst, dst, Operand(kHeapObjectTag)); | 4867 __ add(dst, dst, Operand(kHeapObjectTag)); |
5024 __ StoreToSafepointRegisterSlot(dst, dst); | 4868 __ StoreToSafepointRegisterSlot(dst, dst); |
5025 } | 4869 } |
5026 | 4870 |
5027 | 4871 |
5028 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 4872 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
5029 class DeferredNumberTagD: public LDeferredCode { | 4873 class DeferredNumberTagD: public LDeferredCode { |
5030 public: | 4874 public: |
5031 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4875 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
5032 : LDeferredCode(codegen), instr_(instr) { } | 4876 : LDeferredCode(codegen), instr_(instr) { } |
(...skipping 12 matching lines...) Expand all Loading... |
5045 bool convert_hole = false; | 4889 bool convert_hole = false; |
5046 HValue* change_input = instr->hydrogen()->value(); | 4890 HValue* change_input = instr->hydrogen()->value(); |
5047 if (change_input->IsLoadKeyed()) { | 4891 if (change_input->IsLoadKeyed()) { |
5048 HLoadKeyed* load = HLoadKeyed::cast(change_input); | 4892 HLoadKeyed* load = HLoadKeyed::cast(change_input); |
5049 convert_hole = load->UsesMustHandleHole(); | 4893 convert_hole = load->UsesMustHandleHole(); |
5050 } | 4894 } |
5051 | 4895 |
5052 Label no_special_nan_handling; | 4896 Label no_special_nan_handling; |
5053 Label done; | 4897 Label done; |
5054 if (convert_hole) { | 4898 if (convert_hole) { |
5055 if (CpuFeatures::IsSupported(VFP2)) { | 4899 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); |
5056 CpuFeatureScope scope(masm(), VFP2); | 4900 __ VFPCompareAndSetFlags(input_reg, input_reg); |
5057 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); | 4901 __ b(vc, &no_special_nan_handling); |
5058 __ VFPCompareAndSetFlags(input_reg, input_reg); | 4902 __ vmov(reg, scratch0(), input_reg); |
5059 __ b(vc, &no_special_nan_handling); | 4903 __ cmp(scratch0(), Operand(kHoleNanUpper32)); |
5060 __ vmov(reg, scratch0(), input_reg); | 4904 Label canonicalize; |
5061 __ cmp(scratch0(), Operand(kHoleNanUpper32)); | 4905 __ b(ne, &canonicalize); |
5062 Label canonicalize; | 4906 __ Move(reg, factory()->the_hole_value()); |
5063 __ b(ne, &canonicalize); | 4907 __ b(&done); |
5064 __ Move(reg, factory()->the_hole_value()); | 4908 __ bind(&canonicalize); |
5065 __ b(&done); | 4909 __ Vmov(input_reg, |
5066 __ bind(&canonicalize); | 4910 FixedDoubleArray::canonical_not_the_hole_nan_as_double(), |
5067 __ Vmov(input_reg, | 4911 no_reg); |
5068 FixedDoubleArray::canonical_not_the_hole_nan_as_double(), | |
5069 no_reg); | |
5070 } else { | |
5071 Label not_hole; | |
5072 __ cmp(sfpd_hi, Operand(kHoleNanUpper32)); | |
5073 __ b(ne, ¬_hole); | |
5074 __ Move(reg, factory()->the_hole_value()); | |
5075 __ b(&done); | |
5076 __ bind(¬_hole); | |
5077 __ and_(scratch, sfpd_hi, Operand(0x7ff00000)); | |
5078 __ cmp(scratch, Operand(0x7ff00000)); | |
5079 __ b(ne, &no_special_nan_handling); | |
5080 Label special_nan_handling; | |
5081 __ tst(sfpd_hi, Operand(0x000FFFFF)); | |
5082 __ b(ne, &special_nan_handling); | |
5083 __ cmp(sfpd_lo, Operand(0)); | |
5084 __ b(eq, &no_special_nan_handling); | |
5085 __ bind(&special_nan_handling); | |
5086 double canonical_nan = | |
5087 FixedDoubleArray::canonical_not_the_hole_nan_as_double(); | |
5088 uint64_t casted_nan = BitCast<uint64_t>(canonical_nan); | |
5089 __ mov(sfpd_lo, | |
5090 Operand(static_cast<uint32_t>(casted_nan & 0xFFFFFFFF))); | |
5091 __ mov(sfpd_hi, | |
5092 Operand(static_cast<uint32_t>(casted_nan >> 32))); | |
5093 } | |
5094 } | 4912 } |
5095 | 4913 |
5096 __ bind(&no_special_nan_handling); | 4914 __ bind(&no_special_nan_handling); |
5097 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4915 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
5098 if (FLAG_inline_new) { | 4916 if (FLAG_inline_new) { |
5099 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 4917 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
5100 // We want the untagged address first for performance | 4918 // We want the untagged address first for performance |
5101 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), | 4919 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), |
5102 DONT_TAG_RESULT); | 4920 DONT_TAG_RESULT); |
5103 } else { | 4921 } else { |
5104 __ jmp(deferred->entry()); | 4922 __ jmp(deferred->entry()); |
5105 } | 4923 } |
5106 __ bind(deferred->exit()); | 4924 __ bind(deferred->exit()); |
5107 if (CpuFeatures::IsSupported(VFP2)) { | 4925 __ vstr(input_reg, reg, HeapNumber::kValueOffset); |
5108 CpuFeatureScope scope(masm(), VFP2); | |
5109 __ vstr(input_reg, reg, HeapNumber::kValueOffset); | |
5110 } else { | |
5111 __ str(sfpd_lo, MemOperand(reg, HeapNumber::kValueOffset)); | |
5112 __ str(sfpd_hi, MemOperand(reg, HeapNumber::kValueOffset + kPointerSize)); | |
5113 } | |
5114 // Now that we have finished with the object's real address tag it | 4926 // Now that we have finished with the object's real address tag it |
5115 __ add(reg, reg, Operand(kHeapObjectTag)); | 4927 __ add(reg, reg, Operand(kHeapObjectTag)); |
5116 __ bind(&done); | 4928 __ bind(&done); |
5117 } | 4929 } |
5118 | 4930 |
5119 | 4931 |
5120 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4932 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
5121 // TODO(3095996): Get rid of this. For now, we need to make the | 4933 // TODO(3095996): Get rid of this. For now, we need to make the |
5122 // result register contain a valid pointer because it is already | 4934 // result register contain a valid pointer because it is already |
5123 // contained in the register pointer map. | 4935 // contained in the register pointer map. |
(...skipping 29 matching lines...) Expand all Loading... |
5153 | 4965 |
5154 void LCodeGen::EmitNumberUntagD(Register input_reg, | 4966 void LCodeGen::EmitNumberUntagD(Register input_reg, |
5155 DwVfpRegister result_reg, | 4967 DwVfpRegister result_reg, |
5156 bool deoptimize_on_undefined, | 4968 bool deoptimize_on_undefined, |
5157 bool deoptimize_on_minus_zero, | 4969 bool deoptimize_on_minus_zero, |
5158 LEnvironment* env, | 4970 LEnvironment* env, |
5159 NumberUntagDMode mode) { | 4971 NumberUntagDMode mode) { |
5160 Register scratch = scratch0(); | 4972 Register scratch = scratch0(); |
5161 SwVfpRegister flt_scratch = double_scratch0().low(); | 4973 SwVfpRegister flt_scratch = double_scratch0().low(); |
5162 ASSERT(!result_reg.is(double_scratch0())); | 4974 ASSERT(!result_reg.is(double_scratch0())); |
5163 CpuFeatureScope scope(masm(), VFP2); | |
5164 | 4975 |
5165 Label load_smi, heap_number, done; | 4976 Label load_smi, heap_number, done; |
5166 | 4977 |
5167 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { | 4978 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
5168 // Smi check. | 4979 // Smi check. |
5169 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); | 4980 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); |
5170 | 4981 |
5171 // Heap number map check. | 4982 // Heap number map check. |
5172 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4983 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
5173 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 4984 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5242 // SmiUntag(heap_object, SetCC) | 5053 // SmiUntag(heap_object, SetCC) |
5243 STATIC_ASSERT(kHeapObjectTag == 1); | 5054 STATIC_ASSERT(kHeapObjectTag == 1); |
5244 __ adc(input_reg, input_reg, Operand(input_reg)); | 5055 __ adc(input_reg, input_reg, Operand(input_reg)); |
5245 | 5056 |
5246 // Heap number map check. | 5057 // Heap number map check. |
5247 __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 5058 __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
5248 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 5059 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
5249 __ cmp(scratch1, Operand(ip)); | 5060 __ cmp(scratch1, Operand(ip)); |
5250 | 5061 |
5251 if (instr->truncating()) { | 5062 if (instr->truncating()) { |
5252 CpuFeatureScope scope(masm(), VFP2); | |
5253 Register scratch3 = ToRegister(instr->temp2()); | 5063 Register scratch3 = ToRegister(instr->temp2()); |
5254 ASSERT(!scratch3.is(input_reg) && | 5064 ASSERT(!scratch3.is(input_reg) && |
5255 !scratch3.is(scratch1) && | 5065 !scratch3.is(scratch1) && |
5256 !scratch3.is(scratch2)); | 5066 !scratch3.is(scratch2)); |
5257 // Performs a truncating conversion of a floating point number as used by | 5067 // Performs a truncating conversion of a floating point number as used by |
5258 // the JS bitwise operations. | 5068 // the JS bitwise operations. |
5259 Label heap_number; | 5069 Label heap_number; |
5260 __ b(eq, &heap_number); | 5070 __ b(eq, &heap_number); |
5261 // Check for undefined. Undefined is converted to zero for truncating | 5071 // Check for undefined. Undefined is converted to zero for truncating |
5262 // conversions. | 5072 // conversions. |
5263 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 5073 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
5264 __ cmp(input_reg, Operand(ip)); | 5074 __ cmp(input_reg, Operand(ip)); |
5265 DeoptimizeIf(ne, instr->environment()); | 5075 DeoptimizeIf(ne, instr->environment()); |
5266 __ mov(input_reg, Operand::Zero()); | 5076 __ mov(input_reg, Operand::Zero()); |
5267 __ b(&done); | 5077 __ b(&done); |
5268 | 5078 |
5269 __ bind(&heap_number); | 5079 __ bind(&heap_number); |
5270 __ sub(scratch1, input_reg, Operand(kHeapObjectTag)); | 5080 __ sub(scratch1, input_reg, Operand(kHeapObjectTag)); |
5271 __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset); | 5081 __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset); |
5272 | 5082 |
5273 __ ECMAToInt32VFP(input_reg, double_scratch2, double_scratch, | 5083 __ ECMAToInt32(input_reg, double_scratch2, double_scratch, |
5274 scratch1, scratch2, scratch3); | 5084 scratch1, scratch2, scratch3); |
5275 | 5085 |
5276 } else { | 5086 } else { |
5277 CpuFeatureScope scope(masm(), VFP3); | 5087 CpuFeatureScope scope(masm(), VFP3); |
5278 // Deoptimize if we don't have a heap number. | 5088 // Deoptimize if we don't have a heap number. |
5279 DeoptimizeIf(ne, instr->environment()); | 5089 DeoptimizeIf(ne, instr->environment()); |
5280 | 5090 |
5281 __ sub(ip, input_reg, Operand(kHeapObjectTag)); | 5091 __ sub(ip, input_reg, Operand(kHeapObjectTag)); |
5282 __ vldr(double_scratch, ip, HeapNumber::kValueOffset); | 5092 __ vldr(double_scratch, ip, HeapNumber::kValueOffset); |
5283 __ TryDoubleToInt32Exact(input_reg, double_scratch, double_scratch2); | 5093 __ TryDoubleToInt32Exact(input_reg, double_scratch, double_scratch2); |
5284 DeoptimizeIf(ne, instr->environment()); | 5094 DeoptimizeIf(ne, instr->environment()); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5362 Register result_reg = ToRegister(instr->result()); | 5172 Register result_reg = ToRegister(instr->result()); |
5363 Register scratch1 = scratch0(); | 5173 Register scratch1 = scratch0(); |
5364 Register scratch2 = ToRegister(instr->temp()); | 5174 Register scratch2 = ToRegister(instr->temp()); |
5365 DwVfpRegister double_input = ToDoubleRegister(instr->value()); | 5175 DwVfpRegister double_input = ToDoubleRegister(instr->value()); |
5366 DwVfpRegister double_scratch = double_scratch0(); | 5176 DwVfpRegister double_scratch = double_scratch0(); |
5367 | 5177 |
5368 Label done; | 5178 Label done; |
5369 | 5179 |
5370 if (instr->truncating()) { | 5180 if (instr->truncating()) { |
5371 Register scratch3 = ToRegister(instr->temp2()); | 5181 Register scratch3 = ToRegister(instr->temp2()); |
5372 __ ECMAToInt32VFP(result_reg, double_input, double_scratch, | 5182 __ ECMAToInt32(result_reg, double_input, double_scratch, |
5373 scratch1, scratch2, scratch3); | 5183 scratch1, scratch2, scratch3); |
5374 } else { | 5184 } else { |
5375 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); | 5185 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); |
5376 // Deoptimize if the input wasn't a int32 (inside a double). | 5186 // Deoptimize if the input wasn't a int32 (inside a double). |
5377 DeoptimizeIf(ne, instr->environment()); | 5187 DeoptimizeIf(ne, instr->environment()); |
5378 } | 5188 } |
5379 __ bind(&done); | 5189 __ bind(&done); |
5380 } | 5190 } |
5381 | 5191 |
5382 | 5192 |
5383 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 5193 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5479 __ CompareMap(map_reg, map, &success, REQUIRE_EXACT_MAP); | 5289 __ CompareMap(map_reg, map, &success, REQUIRE_EXACT_MAP); |
5480 __ b(eq, &success); | 5290 __ b(eq, &success); |
5481 } | 5291 } |
5482 Handle<Map> map = map_set->last(); | 5292 Handle<Map> map = map_set->last(); |
5483 DoCheckMapCommon(map_reg, map, REQUIRE_EXACT_MAP, instr->environment()); | 5293 DoCheckMapCommon(map_reg, map, REQUIRE_EXACT_MAP, instr->environment()); |
5484 __ bind(&success); | 5294 __ bind(&success); |
5485 } | 5295 } |
5486 | 5296 |
5487 | 5297 |
5488 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 5298 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
5489 CpuFeatureScope vfp_scope(masm(), VFP2); | |
5490 DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped()); | 5299 DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped()); |
5491 Register result_reg = ToRegister(instr->result()); | 5300 Register result_reg = ToRegister(instr->result()); |
5492 DwVfpRegister temp_reg = ToDoubleRegister(instr->temp()); | 5301 DwVfpRegister temp_reg = ToDoubleRegister(instr->temp()); |
5493 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); | 5302 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); |
5494 } | 5303 } |
5495 | 5304 |
5496 | 5305 |
5497 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { | 5306 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
5498 CpuFeatureScope scope(masm(), VFP2); | |
5499 Register unclamped_reg = ToRegister(instr->unclamped()); | 5307 Register unclamped_reg = ToRegister(instr->unclamped()); |
5500 Register result_reg = ToRegister(instr->result()); | 5308 Register result_reg = ToRegister(instr->result()); |
5501 __ ClampUint8(result_reg, unclamped_reg); | 5309 __ ClampUint8(result_reg, unclamped_reg); |
5502 } | 5310 } |
5503 | 5311 |
5504 | 5312 |
5505 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { | 5313 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
5506 CpuFeatureScope scope(masm(), VFP2); | |
5507 Register scratch = scratch0(); | 5314 Register scratch = scratch0(); |
5508 Register input_reg = ToRegister(instr->unclamped()); | 5315 Register input_reg = ToRegister(instr->unclamped()); |
5509 Register result_reg = ToRegister(instr->result()); | 5316 Register result_reg = ToRegister(instr->result()); |
5510 DwVfpRegister temp_reg = ToDoubleRegister(instr->temp()); | 5317 DwVfpRegister temp_reg = ToDoubleRegister(instr->temp()); |
5511 Label is_smi, done, heap_number; | 5318 Label is_smi, done, heap_number; |
5512 | 5319 |
5513 // Both smi and heap number cases are handled. | 5320 // Both smi and heap number cases are handled. |
5514 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); | 5321 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); |
5515 | 5322 |
5516 // Check for heap number | 5323 // Check for heap number |
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6397 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); | 6204 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); |
6398 __ ldr(result, FieldMemOperand(scratch, | 6205 __ ldr(result, FieldMemOperand(scratch, |
6399 FixedArray::kHeaderSize - kPointerSize)); | 6206 FixedArray::kHeaderSize - kPointerSize)); |
6400 __ bind(&done); | 6207 __ bind(&done); |
6401 } | 6208 } |
6402 | 6209 |
6403 | 6210 |
6404 #undef __ | 6211 #undef __ |
6405 | 6212 |
6406 } } // namespace v8::internal | 6213 } } // namespace v8::internal |
OLD | NEW |