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