| 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 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 __ Subu(a0, a0, Operand(kPointerSize)); | 185 __ Subu(a0, a0, Operand(kPointerSize)); |
| 186 __ sw(a1, MemOperand(a0, 2 * kPointerSize)); | 186 __ sw(a1, MemOperand(a0, 2 * kPointerSize)); |
| 187 __ Branch(&loop, ne, a0, Operand(sp)); | 187 __ Branch(&loop, ne, a0, Operand(sp)); |
| 188 __ pop(a1); | 188 __ pop(a1); |
| 189 __ pop(a0); | 189 __ pop(a0); |
| 190 } else { | 190 } else { |
| 191 __ Subu(sp, sp, Operand(slots * kPointerSize)); | 191 __ Subu(sp, sp, Operand(slots * kPointerSize)); |
| 192 } | 192 } |
| 193 } | 193 } |
| 194 | 194 |
| 195 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(FPU)) { | 195 if (info()->saves_caller_doubles()) { |
| 196 CpuFeatureScope scope(masm(), FPU); | |
| 197 Comment(";;; Save clobbered callee double registers"); | 196 Comment(";;; Save clobbered callee double registers"); |
| 198 int count = 0; | 197 int count = 0; |
| 199 BitVector* doubles = chunk()->allocated_double_registers(); | 198 BitVector* doubles = chunk()->allocated_double_registers(); |
| 200 BitVector::Iterator save_iterator(doubles); | 199 BitVector::Iterator save_iterator(doubles); |
| 201 while (!save_iterator.Done()) { | 200 while (!save_iterator.Done()) { |
| 202 __ sdc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()), | 201 __ sdc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()), |
| 203 MemOperand(sp, count * kDoubleSize)); | 202 MemOperand(sp, count * kDoubleSize)); |
| 204 save_iterator.Advance(); | 203 save_iterator.Advance(); |
| 205 count++; | 204 count++; |
| 206 } | 205 } |
| (...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1207 | 1206 |
| 1208 | 1207 |
| 1209 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { | 1208 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { |
| 1210 DoubleRegister addend = ToDoubleRegister(instr->addend()); | 1209 DoubleRegister addend = ToDoubleRegister(instr->addend()); |
| 1211 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); | 1210 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); |
| 1212 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); | 1211 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); |
| 1213 | 1212 |
| 1214 // This is computed in-place. | 1213 // This is computed in-place. |
| 1215 ASSERT(addend.is(ToDoubleRegister(instr->result()))); | 1214 ASSERT(addend.is(ToDoubleRegister(instr->result()))); |
| 1216 | 1215 |
| 1217 CpuFeatureScope scope(masm(), FPU); | |
| 1218 __ madd_d(addend, addend, multiplier, multiplicand); | 1216 __ madd_d(addend, addend, multiplier, multiplicand); |
| 1219 } | 1217 } |
| 1220 | 1218 |
| 1221 | 1219 |
| 1222 void LCodeGen::DoMulI(LMulI* instr) { | 1220 void LCodeGen::DoMulI(LMulI* instr) { |
| 1223 Register scratch = scratch0(); | 1221 Register scratch = scratch0(); |
| 1224 Register result = ToRegister(instr->result()); | 1222 Register result = ToRegister(instr->result()); |
| 1225 // Note that result may alias left. | 1223 // Note that result may alias left. |
| 1226 Register left = ToRegister(instr->left()); | 1224 Register left = ToRegister(instr->left()); |
| 1227 LOperand* right_op = instr->right(); | 1225 LOperand* right_op = instr->right(); |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1470 | 1468 |
| 1471 void LCodeGen::DoConstantI(LConstantI* instr) { | 1469 void LCodeGen::DoConstantI(LConstantI* instr) { |
| 1472 ASSERT(instr->result()->IsRegister()); | 1470 ASSERT(instr->result()->IsRegister()); |
| 1473 __ li(ToRegister(instr->result()), Operand(instr->value())); | 1471 __ li(ToRegister(instr->result()), Operand(instr->value())); |
| 1474 } | 1472 } |
| 1475 | 1473 |
| 1476 | 1474 |
| 1477 void LCodeGen::DoConstantD(LConstantD* instr) { | 1475 void LCodeGen::DoConstantD(LConstantD* instr) { |
| 1478 ASSERT(instr->result()->IsDoubleRegister()); | 1476 ASSERT(instr->result()->IsDoubleRegister()); |
| 1479 DoubleRegister result = ToDoubleRegister(instr->result()); | 1477 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 1480 CpuFeatureScope scope(masm(), FPU); | |
| 1481 double v = instr->value(); | 1478 double v = instr->value(); |
| 1482 __ Move(result, v); | 1479 __ Move(result, v); |
| 1483 } | 1480 } |
| 1484 | 1481 |
| 1485 | 1482 |
| 1486 void LCodeGen::DoConstantT(LConstantT* instr) { | 1483 void LCodeGen::DoConstantT(LConstantT* instr) { |
| 1487 Handle<Object> value = instr->value(); | 1484 Handle<Object> value = instr->value(); |
| 1488 if (value->IsSmi()) { | 1485 if (value->IsSmi()) { |
| 1489 __ li(ToRegister(instr->result()), Operand(value)); | 1486 __ li(ToRegister(instr->result()), Operand(value)); |
| 1490 } else { | 1487 } else { |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1661 __ Branch(&return_right, NegateCondition(condition), left_reg, right_op); | 1658 __ Branch(&return_right, NegateCondition(condition), left_reg, right_op); |
| 1662 __ mov(result_reg, left_reg); | 1659 __ mov(result_reg, left_reg); |
| 1663 __ Branch(&done); | 1660 __ Branch(&done); |
| 1664 } | 1661 } |
| 1665 __ Branch(&done, condition, left_reg, right_op); | 1662 __ Branch(&done, condition, left_reg, right_op); |
| 1666 __ bind(&return_right); | 1663 __ bind(&return_right); |
| 1667 __ Addu(result_reg, zero_reg, right_op); | 1664 __ Addu(result_reg, zero_reg, right_op); |
| 1668 __ bind(&done); | 1665 __ bind(&done); |
| 1669 } else { | 1666 } else { |
| 1670 ASSERT(instr->hydrogen()->representation().IsDouble()); | 1667 ASSERT(instr->hydrogen()->representation().IsDouble()); |
| 1671 CpuFeatureScope scope(masm(), FPU); | |
| 1672 FPURegister left_reg = ToDoubleRegister(left); | 1668 FPURegister left_reg = ToDoubleRegister(left); |
| 1673 FPURegister right_reg = ToDoubleRegister(right); | 1669 FPURegister right_reg = ToDoubleRegister(right); |
| 1674 FPURegister result_reg = ToDoubleRegister(instr->result()); | 1670 FPURegister result_reg = ToDoubleRegister(instr->result()); |
| 1675 Label check_nan_left, check_zero, return_left, return_right, done; | 1671 Label check_nan_left, check_zero, return_left, return_right, done; |
| 1676 __ BranchF(&check_zero, &check_nan_left, eq, left_reg, right_reg); | 1672 __ BranchF(&check_zero, &check_nan_left, eq, left_reg, right_reg); |
| 1677 __ BranchF(&return_left, NULL, condition, left_reg, right_reg); | 1673 __ BranchF(&return_left, NULL, condition, left_reg, right_reg); |
| 1678 __ Branch(&return_right); | 1674 __ Branch(&return_right); |
| 1679 | 1675 |
| 1680 __ bind(&check_zero); | 1676 __ bind(&check_zero); |
| 1681 // left == right != 0. | 1677 // left == right != 0. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1702 __ bind(&return_left); | 1698 __ bind(&return_left); |
| 1703 if (!left_reg.is(result_reg)) { | 1699 if (!left_reg.is(result_reg)) { |
| 1704 __ mov_d(result_reg, left_reg); | 1700 __ mov_d(result_reg, left_reg); |
| 1705 } | 1701 } |
| 1706 __ bind(&done); | 1702 __ bind(&done); |
| 1707 } | 1703 } |
| 1708 } | 1704 } |
| 1709 | 1705 |
| 1710 | 1706 |
| 1711 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1707 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
| 1712 CpuFeatureScope scope(masm(), FPU); | |
| 1713 DoubleRegister left = ToDoubleRegister(instr->left()); | 1708 DoubleRegister left = ToDoubleRegister(instr->left()); |
| 1714 DoubleRegister right = ToDoubleRegister(instr->right()); | 1709 DoubleRegister right = ToDoubleRegister(instr->right()); |
| 1715 DoubleRegister result = ToDoubleRegister(instr->result()); | 1710 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 1716 switch (instr->op()) { | 1711 switch (instr->op()) { |
| 1717 case Token::ADD: | 1712 case Token::ADD: |
| 1718 __ add_d(result, left, right); | 1713 __ add_d(result, left, right); |
| 1719 break; | 1714 break; |
| 1720 case Token::SUB: | 1715 case Token::SUB: |
| 1721 __ sub_d(result, left, right); | 1716 __ sub_d(result, left, right); |
| 1722 break; | 1717 break; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1812 | 1807 |
| 1813 void LCodeGen::DoBranch(LBranch* instr) { | 1808 void LCodeGen::DoBranch(LBranch* instr) { |
| 1814 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1809 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1815 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1810 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1816 | 1811 |
| 1817 Representation r = instr->hydrogen()->value()->representation(); | 1812 Representation r = instr->hydrogen()->value()->representation(); |
| 1818 if (r.IsInteger32()) { | 1813 if (r.IsInteger32()) { |
| 1819 Register reg = ToRegister(instr->value()); | 1814 Register reg = ToRegister(instr->value()); |
| 1820 EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg)); | 1815 EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg)); |
| 1821 } else if (r.IsDouble()) { | 1816 } else if (r.IsDouble()) { |
| 1822 CpuFeatureScope scope(masm(), FPU); | |
| 1823 DoubleRegister reg = ToDoubleRegister(instr->value()); | 1817 DoubleRegister reg = ToDoubleRegister(instr->value()); |
| 1824 // Test the double value. Zero and NaN are false. | 1818 // Test the double value. Zero and NaN are false. |
| 1825 EmitBranchF(true_block, false_block, nue, reg, kDoubleRegZero); | 1819 EmitBranchF(true_block, false_block, nue, reg, kDoubleRegZero); |
| 1826 } else { | 1820 } else { |
| 1827 ASSERT(r.IsTagged()); | 1821 ASSERT(r.IsTagged()); |
| 1828 Register reg = ToRegister(instr->value()); | 1822 Register reg = ToRegister(instr->value()); |
| 1829 HType type = instr->hydrogen()->value()->type(); | 1823 HType type = instr->hydrogen()->value()->type(); |
| 1830 if (type.IsBoolean()) { | 1824 if (type.IsBoolean()) { |
| 1831 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 1825 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
| 1832 EmitBranch(true_block, false_block, eq, reg, Operand(at)); | 1826 EmitBranch(true_block, false_block, eq, reg, Operand(at)); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1897 } | 1891 } |
| 1898 | 1892 |
| 1899 if (expected.Contains(ToBooleanStub::SYMBOL)) { | 1893 if (expected.Contains(ToBooleanStub::SYMBOL)) { |
| 1900 // Symbol value -> true. | 1894 // Symbol value -> true. |
| 1901 const Register scratch = scratch1(); | 1895 const Register scratch = scratch1(); |
| 1902 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 1896 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 1903 __ Branch(true_label, eq, scratch, Operand(SYMBOL_TYPE)); | 1897 __ Branch(true_label, eq, scratch, Operand(SYMBOL_TYPE)); |
| 1904 } | 1898 } |
| 1905 | 1899 |
| 1906 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 1900 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
| 1907 CpuFeatureScope scope(masm(), FPU); | |
| 1908 // heap number -> false iff +0, -0, or NaN. | 1901 // heap number -> false iff +0, -0, or NaN. |
| 1909 DoubleRegister dbl_scratch = double_scratch0(); | 1902 DoubleRegister dbl_scratch = double_scratch0(); |
| 1910 Label not_heap_number; | 1903 Label not_heap_number; |
| 1911 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 1904 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 1912 __ Branch(¬_heap_number, ne, map, Operand(at)); | 1905 __ Branch(¬_heap_number, ne, map, Operand(at)); |
| 1913 __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 1906 __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
| 1914 __ BranchF(true_label, false_label, ne, dbl_scratch, kDoubleRegZero); | 1907 __ BranchF(true_label, false_label, ne, dbl_scratch, kDoubleRegZero); |
| 1915 // Falls through if dbl_scratch == 0. | 1908 // Falls through if dbl_scratch == 0. |
| 1916 __ Branch(false_label); | 1909 __ Branch(false_label); |
| 1917 __ bind(¬_heap_number); | 1910 __ bind(¬_heap_number); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1977 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 1970 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
| 1978 // We can statically evaluate the comparison. | 1971 // We can statically evaluate the comparison. |
| 1979 double left_val = ToDouble(LConstantOperand::cast(left)); | 1972 double left_val = ToDouble(LConstantOperand::cast(left)); |
| 1980 double right_val = ToDouble(LConstantOperand::cast(right)); | 1973 double right_val = ToDouble(LConstantOperand::cast(right)); |
| 1981 int next_block = | 1974 int next_block = |
| 1982 EvalComparison(instr->op(), left_val, right_val) ? true_block | 1975 EvalComparison(instr->op(), left_val, right_val) ? true_block |
| 1983 : false_block; | 1976 : false_block; |
| 1984 EmitGoto(next_block); | 1977 EmitGoto(next_block); |
| 1985 } else { | 1978 } else { |
| 1986 if (instr->is_double()) { | 1979 if (instr->is_double()) { |
| 1987 CpuFeatureScope scope(masm(), FPU); | |
| 1988 // Compare left and right as doubles and load the | 1980 // Compare left and right as doubles and load the |
| 1989 // resulting flags into the normal status register. | 1981 // resulting flags into the normal status register. |
| 1990 FPURegister left_reg = ToDoubleRegister(left); | 1982 FPURegister left_reg = ToDoubleRegister(left); |
| 1991 FPURegister right_reg = ToDoubleRegister(right); | 1983 FPURegister right_reg = ToDoubleRegister(right); |
| 1992 | 1984 |
| 1993 // If a NaN is involved, i.e. the result is unordered, | 1985 // If a NaN is involved, i.e. the result is unordered, |
| 1994 // jump to false block label. | 1986 // jump to false block label. |
| 1995 __ BranchF(NULL, chunk_->GetAssemblyLabel(false_block), eq, | 1987 __ BranchF(NULL, chunk_->GetAssemblyLabel(false_block), eq, |
| 1996 left_reg, right_reg); | 1988 left_reg, right_reg); |
| 1997 | 1989 |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2540 } | 2532 } |
| 2541 | 2533 |
| 2542 | 2534 |
| 2543 void LCodeGen::DoReturn(LReturn* instr) { | 2535 void LCodeGen::DoReturn(LReturn* instr) { |
| 2544 if (FLAG_trace && info()->IsOptimizing()) { | 2536 if (FLAG_trace && info()->IsOptimizing()) { |
| 2545 // Push the return value on the stack as the parameter. | 2537 // Push the return value on the stack as the parameter. |
| 2546 // Runtime::TraceExit returns its parameter in v0. | 2538 // Runtime::TraceExit returns its parameter in v0. |
| 2547 __ push(v0); | 2539 __ push(v0); |
| 2548 __ CallRuntime(Runtime::kTraceExit, 1); | 2540 __ CallRuntime(Runtime::kTraceExit, 1); |
| 2549 } | 2541 } |
| 2550 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(FPU)) { | 2542 if (info()->saves_caller_doubles()) { |
| 2551 CpuFeatureScope scope(masm(), FPU); | |
| 2552 ASSERT(NeedsEagerFrame()); | 2543 ASSERT(NeedsEagerFrame()); |
| 2553 BitVector* doubles = chunk()->allocated_double_registers(); | 2544 BitVector* doubles = chunk()->allocated_double_registers(); |
| 2554 BitVector::Iterator save_iterator(doubles); | 2545 BitVector::Iterator save_iterator(doubles); |
| 2555 int count = 0; | 2546 int count = 0; |
| 2556 while (!save_iterator.Done()) { | 2547 while (!save_iterator.Done()) { |
| 2557 __ ldc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()), | 2548 __ ldc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()), |
| 2558 MemOperand(sp, count * kDoubleSize)); | 2549 MemOperand(sp, count * kDoubleSize)); |
| 2559 save_iterator.Advance(); | 2550 save_iterator.Advance(); |
| 2560 count++; | 2551 count++; |
| 2561 } | 2552 } |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2928 | 2919 |
| 2929 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 2920 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
| 2930 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 2921 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| 2931 FPURegister result = ToDoubleRegister(instr->result()); | 2922 FPURegister result = ToDoubleRegister(instr->result()); |
| 2932 if (key_is_constant) { | 2923 if (key_is_constant) { |
| 2933 __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); | 2924 __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); |
| 2934 } else { | 2925 } else { |
| 2935 __ sll(scratch0(), key, shift_size); | 2926 __ sll(scratch0(), key, shift_size); |
| 2936 __ Addu(scratch0(), scratch0(), external_pointer); | 2927 __ Addu(scratch0(), scratch0(), external_pointer); |
| 2937 } | 2928 } |
| 2938 if (CpuFeatures::IsSupported(FPU)) { | 2929 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
| 2939 CpuFeatureScope scope(masm(), FPU); | 2930 __ lwc1(result, MemOperand(scratch0(), additional_offset)); |
| 2940 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | 2931 __ cvt_d_s(result, result); |
| 2941 __ lwc1(result, MemOperand(scratch0(), additional_offset)); | 2932 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
| 2942 __ cvt_d_s(result, result); | 2933 __ ldc1(result, MemOperand(scratch0(), additional_offset)); |
| 2943 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS | |
| 2944 __ ldc1(result, MemOperand(scratch0(), additional_offset)); | |
| 2945 } | |
| 2946 } else { | |
| 2947 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | |
| 2948 Register value = external_pointer; | |
| 2949 __ lw(value, MemOperand(scratch0(), additional_offset)); | |
| 2950 __ And(sfpd_lo, value, Operand(kBinary32MantissaMask)); | |
| 2951 | |
| 2952 __ srl(scratch0(), value, kBinary32MantissaBits); | |
| 2953 __ And(scratch0(), scratch0(), | |
| 2954 Operand(kBinary32ExponentMask >> kBinary32MantissaBits)); | |
| 2955 | |
| 2956 Label exponent_rebiased; | |
| 2957 __ Xor(at, scratch0(), Operand(0x00)); | |
| 2958 __ Branch(&exponent_rebiased, eq, at, Operand(zero_reg)); | |
| 2959 | |
| 2960 __ Xor(at, scratch0(), Operand(0xff)); | |
| 2961 Label skip; | |
| 2962 __ Branch(&skip, ne, at, Operand(zero_reg)); | |
| 2963 __ li(scratch0(), Operand(0x7ff)); | |
| 2964 __ bind(&skip); | |
| 2965 __ Branch(&exponent_rebiased, eq, at, Operand(zero_reg)); | |
| 2966 | |
| 2967 // Rebias exponent. | |
| 2968 __ Addu(scratch0(), | |
| 2969 scratch0(), | |
| 2970 Operand(-kBinary32ExponentBias + HeapNumber::kExponentBias)); | |
| 2971 | |
| 2972 __ bind(&exponent_rebiased); | |
| 2973 __ And(sfpd_hi, value, Operand(kBinary32SignMask)); | |
| 2974 __ sll(at, scratch0(), HeapNumber::kMantissaBitsInTopWord); | |
| 2975 __ Or(sfpd_hi, sfpd_hi, at); | |
| 2976 | |
| 2977 // Shift mantissa. | |
| 2978 static const int kMantissaShiftForHiWord = | |
| 2979 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; | |
| 2980 | |
| 2981 static const int kMantissaShiftForLoWord = | |
| 2982 kBitsPerInt - kMantissaShiftForHiWord; | |
| 2983 | |
| 2984 __ srl(at, sfpd_lo, kMantissaShiftForHiWord); | |
| 2985 __ Or(sfpd_hi, sfpd_hi, at); | |
| 2986 __ sll(sfpd_lo, sfpd_lo, kMantissaShiftForLoWord); | |
| 2987 | |
| 2988 } else { | |
| 2989 __ lw(sfpd_lo, MemOperand(scratch0(), additional_offset)); | |
| 2990 __ lw(sfpd_hi, MemOperand(scratch0(), | |
| 2991 additional_offset + kPointerSize)); | |
| 2992 } | |
| 2993 } | 2934 } |
| 2994 } else { | 2935 } else { |
| 2995 Register result = ToRegister(instr->result()); | 2936 Register result = ToRegister(instr->result()); |
| 2996 MemOperand mem_operand = PrepareKeyedOperand( | 2937 MemOperand mem_operand = PrepareKeyedOperand( |
| 2997 key, external_pointer, key_is_constant, constant_key, | 2938 key, external_pointer, key_is_constant, constant_key, |
| 2998 element_size_shift, shift_size, | 2939 element_size_shift, shift_size, |
| 2999 instr->additional_index(), additional_offset); | 2940 instr->additional_index(), additional_offset); |
| 3000 switch (elements_kind) { | 2941 switch (elements_kind) { |
| 3001 case EXTERNAL_BYTE_ELEMENTS: | 2942 case EXTERNAL_BYTE_ELEMENTS: |
| 3002 __ lb(result, mem_operand); | 2943 __ lb(result, mem_operand); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3057 } else { | 2998 } else { |
| 3058 key = ToRegister(instr->key()); | 2999 key = ToRegister(instr->key()); |
| 3059 } | 3000 } |
| 3060 | 3001 |
| 3061 int base_offset = (FixedDoubleArray::kHeaderSize - kHeapObjectTag) + | 3002 int base_offset = (FixedDoubleArray::kHeaderSize - kHeapObjectTag) + |
| 3062 ((constant_key + instr->additional_index()) << element_size_shift); | 3003 ((constant_key + instr->additional_index()) << element_size_shift); |
| 3063 if (!key_is_constant) { | 3004 if (!key_is_constant) { |
| 3064 __ sll(scratch, key, shift_size); | 3005 __ sll(scratch, key, shift_size); |
| 3065 __ Addu(elements, elements, scratch); | 3006 __ Addu(elements, elements, scratch); |
| 3066 } | 3007 } |
| 3067 if (CpuFeatures::IsSupported(FPU)) { | 3008 __ Addu(elements, elements, Operand(base_offset)); |
| 3068 CpuFeatureScope scope(masm(), FPU); | 3009 __ ldc1(result, MemOperand(elements)); |
| 3069 __ Addu(elements, elements, Operand(base_offset)); | 3010 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3070 __ ldc1(result, MemOperand(elements)); | 3011 __ lw(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); |
| 3071 if (instr->hydrogen()->RequiresHoleCheck()) { | 3012 DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32)); |
| 3072 __ lw(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); | |
| 3073 DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32)); | |
| 3074 } | |
| 3075 } else { | |
| 3076 __ lw(sfpd_hi, MemOperand(elements, base_offset + kPointerSize)); | |
| 3077 __ lw(sfpd_lo, MemOperand(elements, base_offset)); | |
| 3078 if (instr->hydrogen()->RequiresHoleCheck()) { | |
| 3079 ASSERT(kPointerSize == sizeof(kHoleNanLower32)); | |
| 3080 DeoptimizeIf(eq, instr->environment(), sfpd_hi, Operand(kHoleNanUpper32)); | |
| 3081 } | |
| 3082 } | 3013 } |
| 3083 } | 3014 } |
| 3084 | 3015 |
| 3085 | 3016 |
| 3086 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3017 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 3087 Register elements = ToRegister(instr->elements()); | 3018 Register elements = ToRegister(instr->elements()); |
| 3088 Register result = ToRegister(instr->result()); | 3019 Register result = ToRegister(instr->result()); |
| 3089 Register scratch = scratch0(); | 3020 Register scratch = scratch0(); |
| 3090 Register store_base = scratch; | 3021 Register store_base = scratch; |
| 3091 int offset = 0; | 3022 int offset = 0; |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3519 Label done; | 3450 Label done; |
| 3520 __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); | 3451 __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); |
| 3521 __ mov(result, input); | 3452 __ mov(result, input); |
| 3522 // Overflow if result is still negative, i.e. 0x80000000. | 3453 // Overflow if result is still negative, i.e. 0x80000000. |
| 3523 DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); | 3454 DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); |
| 3524 __ bind(&done); | 3455 __ bind(&done); |
| 3525 } | 3456 } |
| 3526 | 3457 |
| 3527 | 3458 |
| 3528 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3459 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
| 3529 CpuFeatureScope scope(masm(), FPU); | |
| 3530 // Class for deferred case. | 3460 // Class for deferred case. |
| 3531 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3461 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
| 3532 public: | 3462 public: |
| 3533 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) | 3463 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
| 3534 : LDeferredCode(codegen), instr_(instr) { } | 3464 : LDeferredCode(codegen), instr_(instr) { } |
| 3535 virtual void Generate() { | 3465 virtual void Generate() { |
| 3536 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3466 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 3537 } | 3467 } |
| 3538 virtual LInstruction* instr() { return instr_; } | 3468 virtual LInstruction* instr() { return instr_; } |
| 3539 private: | 3469 private: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3555 // Smi check. | 3485 // Smi check. |
| 3556 __ JumpIfNotSmi(input, deferred->entry()); | 3486 __ JumpIfNotSmi(input, deferred->entry()); |
| 3557 // If smi, handle it directly. | 3487 // If smi, handle it directly. |
| 3558 EmitIntegerMathAbs(instr); | 3488 EmitIntegerMathAbs(instr); |
| 3559 __ bind(deferred->exit()); | 3489 __ bind(deferred->exit()); |
| 3560 } | 3490 } |
| 3561 } | 3491 } |
| 3562 | 3492 |
| 3563 | 3493 |
| 3564 void LCodeGen::DoMathFloor(LMathFloor* instr) { | 3494 void LCodeGen::DoMathFloor(LMathFloor* instr) { |
| 3565 CpuFeatureScope scope(masm(), FPU); | |
| 3566 DoubleRegister input = ToDoubleRegister(instr->value()); | 3495 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3567 Register result = ToRegister(instr->result()); | 3496 Register result = ToRegister(instr->result()); |
| 3568 Register scratch1 = scratch0(); | 3497 Register scratch1 = scratch0(); |
| 3569 Register except_flag = ToRegister(instr->temp()); | 3498 Register except_flag = ToRegister(instr->temp()); |
| 3570 | 3499 |
| 3571 __ EmitFPUTruncate(kRoundToMinusInf, | 3500 __ EmitFPUTruncate(kRoundToMinusInf, |
| 3572 result, | 3501 result, |
| 3573 input, | 3502 input, |
| 3574 scratch1, | 3503 scratch1, |
| 3575 double_scratch0(), | 3504 double_scratch0(), |
| 3576 except_flag); | 3505 except_flag); |
| 3577 | 3506 |
| 3578 // Deopt if the operation did not succeed. | 3507 // Deopt if the operation did not succeed. |
| 3579 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 3508 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); |
| 3580 | 3509 |
| 3581 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3510 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3582 // Test for -0. | 3511 // Test for -0. |
| 3583 Label done; | 3512 Label done; |
| 3584 __ Branch(&done, ne, result, Operand(zero_reg)); | 3513 __ Branch(&done, ne, result, Operand(zero_reg)); |
| 3585 __ mfc1(scratch1, input.high()); | 3514 __ mfc1(scratch1, input.high()); |
| 3586 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); | 3515 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
| 3587 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); | 3516 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); |
| 3588 __ bind(&done); | 3517 __ bind(&done); |
| 3589 } | 3518 } |
| 3590 } | 3519 } |
| 3591 | 3520 |
| 3592 | 3521 |
| 3593 void LCodeGen::DoMathRound(LMathRound* instr) { | 3522 void LCodeGen::DoMathRound(LMathRound* instr) { |
| 3594 CpuFeatureScope scope(masm(), FPU); | |
| 3595 DoubleRegister input = ToDoubleRegister(instr->value()); | 3523 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3596 Register result = ToRegister(instr->result()); | 3524 Register result = ToRegister(instr->result()); |
| 3597 DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp()); | 3525 DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp()); |
| 3598 Register scratch = scratch0(); | 3526 Register scratch = scratch0(); |
| 3599 Label done, check_sign_on_zero; | 3527 Label done, check_sign_on_zero; |
| 3600 | 3528 |
| 3601 // Extract exponent bits. | 3529 // Extract exponent bits. |
| 3602 __ mfc1(result, input.high()); | 3530 __ mfc1(result, input.high()); |
| 3603 __ Ext(scratch, | 3531 __ Ext(scratch, |
| 3604 result, | 3532 result, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3661 __ bind(&check_sign_on_zero); | 3589 __ bind(&check_sign_on_zero); |
| 3662 __ mfc1(scratch, input.high()); | 3590 __ mfc1(scratch, input.high()); |
| 3663 __ And(scratch, scratch, Operand(HeapNumber::kSignMask)); | 3591 __ And(scratch, scratch, Operand(HeapNumber::kSignMask)); |
| 3664 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); | 3592 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); |
| 3665 } | 3593 } |
| 3666 __ bind(&done); | 3594 __ bind(&done); |
| 3667 } | 3595 } |
| 3668 | 3596 |
| 3669 | 3597 |
| 3670 void LCodeGen::DoMathSqrt(LMathSqrt* instr) { | 3598 void LCodeGen::DoMathSqrt(LMathSqrt* instr) { |
| 3671 CpuFeatureScope scope(masm(), FPU); | |
| 3672 DoubleRegister input = ToDoubleRegister(instr->value()); | 3599 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3673 DoubleRegister result = ToDoubleRegister(instr->result()); | 3600 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 3674 __ sqrt_d(result, input); | 3601 __ sqrt_d(result, input); |
| 3675 } | 3602 } |
| 3676 | 3603 |
| 3677 | 3604 |
| 3678 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { | 3605 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { |
| 3679 CpuFeatureScope scope(masm(), FPU); | |
| 3680 DoubleRegister input = ToDoubleRegister(instr->value()); | 3606 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3681 DoubleRegister result = ToDoubleRegister(instr->result()); | 3607 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 3682 DoubleRegister temp = ToDoubleRegister(instr->temp()); | 3608 DoubleRegister temp = ToDoubleRegister(instr->temp()); |
| 3683 | 3609 |
| 3684 ASSERT(!input.is(result)); | 3610 ASSERT(!input.is(result)); |
| 3685 | 3611 |
| 3686 // Note that according to ECMA-262 15.8.2.13: | 3612 // Note that according to ECMA-262 15.8.2.13: |
| 3687 // Math.pow(-Infinity, 0.5) == Infinity | 3613 // Math.pow(-Infinity, 0.5) == Infinity |
| 3688 // Math.sqrt(-Infinity) == NaN | 3614 // Math.sqrt(-Infinity) == NaN |
| 3689 Label done; | 3615 Label done; |
| 3690 __ Move(temp, -V8_INFINITY); | 3616 __ Move(temp, -V8_INFINITY); |
| 3691 __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, temp, input); | 3617 __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, temp, input); |
| 3692 // Set up Infinity in the delay slot. | 3618 // Set up Infinity in the delay slot. |
| 3693 // result is overwritten if the branch is not taken. | 3619 // result is overwritten if the branch is not taken. |
| 3694 __ neg_d(result, temp); | 3620 __ neg_d(result, temp); |
| 3695 | 3621 |
| 3696 // Add +0 to convert -0 to +0. | 3622 // Add +0 to convert -0 to +0. |
| 3697 __ add_d(result, input, kDoubleRegZero); | 3623 __ add_d(result, input, kDoubleRegZero); |
| 3698 __ sqrt_d(result, result); | 3624 __ sqrt_d(result, result); |
| 3699 __ bind(&done); | 3625 __ bind(&done); |
| 3700 } | 3626 } |
| 3701 | 3627 |
| 3702 | 3628 |
| 3703 void LCodeGen::DoPower(LPower* instr) { | 3629 void LCodeGen::DoPower(LPower* instr) { |
| 3704 CpuFeatureScope scope(masm(), FPU); | |
| 3705 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3630 Representation exponent_type = instr->hydrogen()->right()->representation(); |
| 3706 // Having marked this as a call, we can use any registers. | 3631 // Having marked this as a call, we can use any registers. |
| 3707 // Just make sure that the input/output registers are the expected ones. | 3632 // Just make sure that the input/output registers are the expected ones. |
| 3708 ASSERT(!instr->right()->IsDoubleRegister() || | 3633 ASSERT(!instr->right()->IsDoubleRegister() || |
| 3709 ToDoubleRegister(instr->right()).is(f4)); | 3634 ToDoubleRegister(instr->right()).is(f4)); |
| 3710 ASSERT(!instr->right()->IsRegister() || | 3635 ASSERT(!instr->right()->IsRegister() || |
| 3711 ToRegister(instr->right()).is(a2)); | 3636 ToRegister(instr->right()).is(a2)); |
| 3712 ASSERT(ToDoubleRegister(instr->left()).is(f2)); | 3637 ASSERT(ToDoubleRegister(instr->left()).is(f2)); |
| 3713 ASSERT(ToDoubleRegister(instr->result()).is(f0)); | 3638 ASSERT(ToDoubleRegister(instr->result()).is(f0)); |
| 3714 | 3639 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3725 __ CallStub(&stub); | 3650 __ CallStub(&stub); |
| 3726 } else { | 3651 } else { |
| 3727 ASSERT(exponent_type.IsDouble()); | 3652 ASSERT(exponent_type.IsDouble()); |
| 3728 MathPowStub stub(MathPowStub::DOUBLE); | 3653 MathPowStub stub(MathPowStub::DOUBLE); |
| 3729 __ CallStub(&stub); | 3654 __ CallStub(&stub); |
| 3730 } | 3655 } |
| 3731 } | 3656 } |
| 3732 | 3657 |
| 3733 | 3658 |
| 3734 void LCodeGen::DoRandom(LRandom* instr) { | 3659 void LCodeGen::DoRandom(LRandom* instr) { |
| 3735 CpuFeatureScope scope(masm(), FPU); | |
| 3736 class DeferredDoRandom: public LDeferredCode { | 3660 class DeferredDoRandom: public LDeferredCode { |
| 3737 public: | 3661 public: |
| 3738 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) | 3662 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) |
| 3739 : LDeferredCode(codegen), instr_(instr) { } | 3663 : LDeferredCode(codegen), instr_(instr) { } |
| 3740 virtual void Generate() { codegen()->DoDeferredRandom(instr_); } | 3664 virtual void Generate() { codegen()->DoDeferredRandom(instr_); } |
| 3741 virtual LInstruction* instr() { return instr_; } | 3665 virtual LInstruction* instr() { return instr_; } |
| 3742 private: | 3666 private: |
| 3743 LRandom* instr_; | 3667 LRandom* instr_; |
| 3744 }; | 3668 }; |
| 3745 | 3669 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3802 } | 3726 } |
| 3803 | 3727 |
| 3804 void LCodeGen::DoDeferredRandom(LRandom* instr) { | 3728 void LCodeGen::DoDeferredRandom(LRandom* instr) { |
| 3805 __ PrepareCallCFunction(1, scratch0()); | 3729 __ PrepareCallCFunction(1, scratch0()); |
| 3806 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); | 3730 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); |
| 3807 // Return value is in v0. | 3731 // Return value is in v0. |
| 3808 } | 3732 } |
| 3809 | 3733 |
| 3810 | 3734 |
| 3811 void LCodeGen::DoMathExp(LMathExp* instr) { | 3735 void LCodeGen::DoMathExp(LMathExp* instr) { |
| 3812 CpuFeatureScope scope(masm(), FPU); | |
| 3813 DoubleRegister input = ToDoubleRegister(instr->value()); | 3736 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3814 DoubleRegister result = ToDoubleRegister(instr->result()); | 3737 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 3815 DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp()); | 3738 DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp()); |
| 3816 DoubleRegister double_scratch2 = double_scratch0(); | 3739 DoubleRegister double_scratch2 = double_scratch0(); |
| 3817 Register temp1 = ToRegister(instr->temp1()); | 3740 Register temp1 = ToRegister(instr->temp1()); |
| 3818 Register temp2 = ToRegister(instr->temp2()); | 3741 Register temp2 = ToRegister(instr->temp2()); |
| 3819 | 3742 |
| 3820 MathExpGenerator::EmitMathExp( | 3743 MathExpGenerator::EmitMathExp( |
| 3821 masm(), input, result, double_scratch1, double_scratch2, | 3744 masm(), input, result, double_scratch1, double_scratch2, |
| 3822 temp1, temp2, scratch0()); | 3745 temp1, temp2, scratch0()); |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4069 } else { | 3992 } else { |
| 4070 DeoptimizeIf(hs, | 3993 DeoptimizeIf(hs, |
| 4071 instr->environment(), | 3994 instr->environment(), |
| 4072 ToRegister(instr->index()), | 3995 ToRegister(instr->index()), |
| 4073 Operand(ToRegister(instr->length()))); | 3996 Operand(ToRegister(instr->length()))); |
| 4074 } | 3997 } |
| 4075 } | 3998 } |
| 4076 | 3999 |
| 4077 | 4000 |
| 4078 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4001 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
| 4079 CpuFeatureScope scope(masm(), FPU); | |
| 4080 Register external_pointer = ToRegister(instr->elements()); | 4002 Register external_pointer = ToRegister(instr->elements()); |
| 4081 Register key = no_reg; | 4003 Register key = no_reg; |
| 4082 ElementsKind elements_kind = instr->elements_kind(); | 4004 ElementsKind elements_kind = instr->elements_kind(); |
| 4083 bool key_is_constant = instr->key()->IsConstantOperand(); | 4005 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 4084 int constant_key = 0; | 4006 int constant_key = 0; |
| 4085 if (key_is_constant) { | 4007 if (key_is_constant) { |
| 4086 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 4008 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| 4087 if (constant_key & 0xF0000000) { | 4009 if (constant_key & 0xF0000000) { |
| 4088 Abort("array index constant value too big."); | 4010 Abort("array index constant value too big."); |
| 4089 } | 4011 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4143 case DICTIONARY_ELEMENTS: | 4065 case DICTIONARY_ELEMENTS: |
| 4144 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4066 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 4145 UNREACHABLE(); | 4067 UNREACHABLE(); |
| 4146 break; | 4068 break; |
| 4147 } | 4069 } |
| 4148 } | 4070 } |
| 4149 } | 4071 } |
| 4150 | 4072 |
| 4151 | 4073 |
| 4152 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { | 4074 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { |
| 4153 CpuFeatureScope scope(masm(), FPU); | |
| 4154 DoubleRegister value = ToDoubleRegister(instr->value()); | 4075 DoubleRegister value = ToDoubleRegister(instr->value()); |
| 4155 Register elements = ToRegister(instr->elements()); | 4076 Register elements = ToRegister(instr->elements()); |
| 4156 Register key = no_reg; | 4077 Register key = no_reg; |
| 4157 Register scratch = scratch0(); | 4078 Register scratch = scratch0(); |
| 4158 bool key_is_constant = instr->key()->IsConstantOperand(); | 4079 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 4159 int constant_key = 0; | 4080 int constant_key = 0; |
| 4160 Label not_nan; | 4081 Label not_nan; |
| 4161 | 4082 |
| 4162 // Calculate the effective address of the slot in the array to store the | 4083 // Calculate the effective address of the slot in the array to store the |
| 4163 // double value. | 4084 // double value. |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4447 | 4368 |
| 4448 | 4369 |
| 4449 void LCodeGen::DoStringLength(LStringLength* instr) { | 4370 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 4450 Register string = ToRegister(instr->string()); | 4371 Register string = ToRegister(instr->string()); |
| 4451 Register result = ToRegister(instr->result()); | 4372 Register result = ToRegister(instr->result()); |
| 4452 __ lw(result, FieldMemOperand(string, String::kLengthOffset)); | 4373 __ lw(result, FieldMemOperand(string, String::kLengthOffset)); |
| 4453 } | 4374 } |
| 4454 | 4375 |
| 4455 | 4376 |
| 4456 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4377 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 4457 CpuFeatureScope scope(masm(), FPU); | |
| 4458 LOperand* input = instr->value(); | 4378 LOperand* input = instr->value(); |
| 4459 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4379 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 4460 LOperand* output = instr->result(); | 4380 LOperand* output = instr->result(); |
| 4461 ASSERT(output->IsDoubleRegister()); | 4381 ASSERT(output->IsDoubleRegister()); |
| 4462 FPURegister single_scratch = double_scratch0().low(); | 4382 FPURegister single_scratch = double_scratch0().low(); |
| 4463 if (input->IsStackSlot()) { | 4383 if (input->IsStackSlot()) { |
| 4464 Register scratch = scratch0(); | 4384 Register scratch = scratch0(); |
| 4465 __ lw(scratch, ToMemOperand(input)); | 4385 __ lw(scratch, ToMemOperand(input)); |
| 4466 __ mtc1(scratch, single_scratch); | 4386 __ mtc1(scratch, single_scratch); |
| 4467 } else { | 4387 } else { |
| 4468 __ mtc1(ToRegister(input), single_scratch); | 4388 __ mtc1(ToRegister(input), single_scratch); |
| 4469 } | 4389 } |
| 4470 __ cvt_d_w(ToDoubleRegister(output), single_scratch); | 4390 __ cvt_d_w(ToDoubleRegister(output), single_scratch); |
| 4471 } | 4391 } |
| 4472 | 4392 |
| 4473 | 4393 |
| 4474 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 4394 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
| 4475 CpuFeatureScope scope(masm(), FPU); | |
| 4476 LOperand* input = instr->value(); | 4395 LOperand* input = instr->value(); |
| 4477 LOperand* output = instr->result(); | 4396 LOperand* output = instr->result(); |
| 4478 | 4397 |
| 4479 FPURegister dbl_scratch = double_scratch0(); | 4398 FPURegister dbl_scratch = double_scratch0(); |
| 4480 __ mtc1(ToRegister(input), dbl_scratch); | 4399 __ mtc1(ToRegister(input), dbl_scratch); |
| 4481 __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22); | 4400 __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22); |
| 4482 } | 4401 } |
| 4483 | 4402 |
| 4484 | 4403 |
| 4485 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4404 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4527 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4446 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4528 Register reg = ToRegister(input); | 4447 Register reg = ToRegister(input); |
| 4529 | 4448 |
| 4530 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4449 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
| 4531 __ Branch(deferred->entry(), hi, reg, Operand(Smi::kMaxValue)); | 4450 __ Branch(deferred->entry(), hi, reg, Operand(Smi::kMaxValue)); |
| 4532 __ SmiTag(reg, reg); | 4451 __ SmiTag(reg, reg); |
| 4533 __ bind(deferred->exit()); | 4452 __ bind(deferred->exit()); |
| 4534 } | 4453 } |
| 4535 | 4454 |
| 4536 | 4455 |
| 4537 // Convert unsigned integer with specified number of leading zeroes in binary | |
| 4538 // representation to IEEE 754 double. | |
| 4539 // Integer to convert is passed in register src. | |
| 4540 // Resulting double is returned in registers hiword:loword. | |
| 4541 // This functions does not work correctly for 0. | |
| 4542 static void GenerateUInt2Double(MacroAssembler* masm, | |
| 4543 Register src, | |
| 4544 Register hiword, | |
| 4545 Register loword, | |
| 4546 Register scratch, | |
| 4547 int leading_zeroes) { | |
| 4548 const int meaningful_bits = kBitsPerInt - leading_zeroes - 1; | |
| 4549 const int biased_exponent = HeapNumber::kExponentBias + meaningful_bits; | |
| 4550 | |
| 4551 const int mantissa_shift_for_hi_word = | |
| 4552 meaningful_bits - HeapNumber::kMantissaBitsInTopWord; | |
| 4553 const int mantissa_shift_for_lo_word = | |
| 4554 kBitsPerInt - mantissa_shift_for_hi_word; | |
| 4555 masm->li(scratch, Operand(biased_exponent << HeapNumber::kExponentShift)); | |
| 4556 if (mantissa_shift_for_hi_word > 0) { | |
| 4557 masm->sll(loword, src, mantissa_shift_for_lo_word); | |
| 4558 masm->srl(hiword, src, mantissa_shift_for_hi_word); | |
| 4559 masm->Or(hiword, scratch, hiword); | |
| 4560 } else { | |
| 4561 masm->mov(loword, zero_reg); | |
| 4562 masm->sll(hiword, src, mantissa_shift_for_hi_word); | |
| 4563 masm->Or(hiword, scratch, hiword); | |
| 4564 } | |
| 4565 | |
| 4566 // If least significant bit of biased exponent was not 1 it was corrupted | |
| 4567 // by most significant bit of mantissa so we should fix that. | |
| 4568 if (!(biased_exponent & 1)) { | |
| 4569 masm->li(scratch, 1 << HeapNumber::kExponentShift); | |
| 4570 masm->nor(scratch, scratch, scratch); | |
| 4571 masm->and_(hiword, hiword, scratch); | |
| 4572 } | |
| 4573 } | |
| 4574 | |
| 4575 | |
| 4576 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, | 4456 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, |
| 4577 LOperand* value, | 4457 LOperand* value, |
| 4578 IntegerSignedness signedness) { | 4458 IntegerSignedness signedness) { |
| 4579 Label slow; | 4459 Label slow; |
| 4580 Register src = ToRegister(value); | 4460 Register src = ToRegister(value); |
| 4581 Register dst = ToRegister(instr->result()); | 4461 Register dst = ToRegister(instr->result()); |
| 4582 DoubleRegister dbl_scratch = double_scratch0(); | 4462 DoubleRegister dbl_scratch = double_scratch0(); |
| 4583 | 4463 |
| 4584 // Preserve the value of all registers. | 4464 // Preserve the value of all registers. |
| 4585 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4465 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 4586 | 4466 |
| 4587 Label done; | 4467 Label done; |
| 4588 if (signedness == SIGNED_INT32) { | 4468 if (signedness == SIGNED_INT32) { |
| 4589 // There was overflow, so bits 30 and 31 of the original integer | 4469 // There was overflow, so bits 30 and 31 of the original integer |
| 4590 // disagree. Try to allocate a heap number in new space and store | 4470 // disagree. Try to allocate a heap number in new space and store |
| 4591 // the value in there. If that fails, call the runtime system. | 4471 // the value in there. If that fails, call the runtime system. |
| 4592 if (dst.is(src)) { | 4472 if (dst.is(src)) { |
| 4593 __ SmiUntag(src, dst); | 4473 __ SmiUntag(src, dst); |
| 4594 __ Xor(src, src, Operand(0x80000000)); | 4474 __ Xor(src, src, Operand(0x80000000)); |
| 4595 } | 4475 } |
| 4596 if (CpuFeatures::IsSupported(FPU)) { | 4476 __ mtc1(src, dbl_scratch); |
| 4597 CpuFeatureScope scope(masm(), FPU); | 4477 __ cvt_d_w(dbl_scratch, dbl_scratch); |
| 4598 __ mtc1(src, dbl_scratch); | |
| 4599 __ cvt_d_w(dbl_scratch, dbl_scratch); | |
| 4600 } else { | |
| 4601 FloatingPointHelper::Destination dest = | |
| 4602 FloatingPointHelper::kCoreRegisters; | |
| 4603 FloatingPointHelper::ConvertIntToDouble(masm(), src, dest, f0, | |
| 4604 sfpd_lo, sfpd_hi, | |
| 4605 scratch0(), f2); | |
| 4606 } | |
| 4607 } else { | 4478 } else { |
| 4608 if (CpuFeatures::IsSupported(FPU)) { | 4479 __ mtc1(src, dbl_scratch); |
| 4609 CpuFeatureScope scope(masm(), FPU); | 4480 __ Cvt_d_uw(dbl_scratch, dbl_scratch, f22); |
| 4610 __ mtc1(src, dbl_scratch); | |
| 4611 __ Cvt_d_uw(dbl_scratch, dbl_scratch, f22); | |
| 4612 } else { | |
| 4613 Label no_leading_zero, convert_done; | |
| 4614 __ And(at, src, Operand(0x80000000)); | |
| 4615 __ Branch(&no_leading_zero, ne, at, Operand(zero_reg)); | |
| 4616 | |
| 4617 // Integer has one leading zeros. | |
| 4618 GenerateUInt2Double(masm(), src, sfpd_hi, sfpd_lo, t0, 1); | |
| 4619 __ Branch(&convert_done); | |
| 4620 | |
| 4621 __ bind(&no_leading_zero); | |
| 4622 GenerateUInt2Double(masm(), src, sfpd_hi, sfpd_lo, t0, 0); | |
| 4623 __ bind(&convert_done); | |
| 4624 } | |
| 4625 } | 4481 } |
| 4626 | 4482 |
| 4627 if (FLAG_inline_new) { | 4483 if (FLAG_inline_new) { |
| 4628 __ LoadRoot(scratch0(), Heap::kHeapNumberMapRootIndex); | 4484 __ LoadRoot(scratch0(), Heap::kHeapNumberMapRootIndex); |
| 4629 __ AllocateHeapNumber(t1, a3, t0, scratch0(), &slow, DONT_TAG_RESULT); | 4485 __ AllocateHeapNumber(t1, a3, t0, scratch0(), &slow, DONT_TAG_RESULT); |
| 4630 __ Move(dst, t1); | 4486 __ Move(dst, t1); |
| 4631 __ Branch(&done); | 4487 __ Branch(&done); |
| 4632 } | 4488 } |
| 4633 | 4489 |
| 4634 // Slow case: Call the runtime system to do the number allocation. | 4490 // Slow case: Call the runtime system to do the number allocation. |
| 4635 __ bind(&slow); | 4491 __ bind(&slow); |
| 4636 | 4492 |
| 4637 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 4493 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
| 4638 // register is stored, as this register is in the pointer map, but contains an | 4494 // register is stored, as this register is in the pointer map, but contains an |
| 4639 // integer value. | 4495 // integer value. |
| 4640 __ StoreToSafepointRegisterSlot(zero_reg, dst); | 4496 __ StoreToSafepointRegisterSlot(zero_reg, dst); |
| 4641 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4497 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
| 4642 __ Move(dst, v0); | 4498 __ Move(dst, v0); |
| 4643 __ Subu(dst, dst, kHeapObjectTag); | 4499 __ Subu(dst, dst, kHeapObjectTag); |
| 4644 | 4500 |
| 4645 // Done. Put the value in dbl_scratch into the value of the allocated heap | 4501 // Done. Put the value in dbl_scratch into the value of the allocated heap |
| 4646 // number. | 4502 // number. |
| 4647 __ bind(&done); | 4503 __ bind(&done); |
| 4648 if (CpuFeatures::IsSupported(FPU)) { | 4504 __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset)); |
| 4649 CpuFeatureScope scope(masm(), FPU); | |
| 4650 __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset)); | |
| 4651 } else { | |
| 4652 __ sw(sfpd_lo, MemOperand(dst, HeapNumber::kMantissaOffset)); | |
| 4653 __ sw(sfpd_hi, MemOperand(dst, HeapNumber::kExponentOffset)); | |
| 4654 } | |
| 4655 __ Addu(dst, dst, kHeapObjectTag); | 4505 __ Addu(dst, dst, kHeapObjectTag); |
| 4656 __ StoreToSafepointRegisterSlot(dst, dst); | 4506 __ StoreToSafepointRegisterSlot(dst, dst); |
| 4657 } | 4507 } |
| 4658 | 4508 |
| 4659 | 4509 |
| 4660 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 4510 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
| 4661 class DeferredNumberTagD: public LDeferredCode { | 4511 class DeferredNumberTagD: public LDeferredCode { |
| 4662 public: | 4512 public: |
| 4663 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4513 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 4664 : LDeferredCode(codegen), instr_(instr) { } | 4514 : LDeferredCode(codegen), instr_(instr) { } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4677 bool convert_hole = false; | 4527 bool convert_hole = false; |
| 4678 HValue* change_input = instr->hydrogen()->value(); | 4528 HValue* change_input = instr->hydrogen()->value(); |
| 4679 if (change_input->IsLoadKeyed()) { | 4529 if (change_input->IsLoadKeyed()) { |
| 4680 HLoadKeyed* load = HLoadKeyed::cast(change_input); | 4530 HLoadKeyed* load = HLoadKeyed::cast(change_input); |
| 4681 convert_hole = load->UsesMustHandleHole(); | 4531 convert_hole = load->UsesMustHandleHole(); |
| 4682 } | 4532 } |
| 4683 | 4533 |
| 4684 Label no_special_nan_handling; | 4534 Label no_special_nan_handling; |
| 4685 Label done; | 4535 Label done; |
| 4686 if (convert_hole) { | 4536 if (convert_hole) { |
| 4687 if (CpuFeatures::IsSupported(FPU)) { | 4537 DoubleRegister input_reg = ToDoubleRegister(instr->value()); |
| 4688 CpuFeatureScope scope(masm(), FPU); | 4538 __ BranchF(&no_special_nan_handling, NULL, eq, input_reg, input_reg); |
| 4689 DoubleRegister input_reg = ToDoubleRegister(instr->value()); | 4539 __ Move(reg, scratch0(), input_reg); |
| 4690 __ BranchF(&no_special_nan_handling, NULL, eq, input_reg, input_reg); | 4540 Label canonicalize; |
| 4691 __ Move(reg, scratch0(), input_reg); | 4541 __ Branch(&canonicalize, ne, scratch0(), Operand(kHoleNanUpper32)); |
| 4692 Label canonicalize; | 4542 __ li(reg, factory()->the_hole_value()); |
| 4693 __ Branch(&canonicalize, ne, scratch0(), Operand(kHoleNanUpper32)); | 4543 __ Branch(&done); |
| 4694 __ li(reg, factory()->the_hole_value()); | 4544 __ bind(&canonicalize); |
| 4695 __ Branch(&done); | 4545 __ Move(input_reg, |
| 4696 __ bind(&canonicalize); | 4546 FixedDoubleArray::canonical_not_the_hole_nan_as_double()); |
| 4697 __ Move(input_reg, | |
| 4698 FixedDoubleArray::canonical_not_the_hole_nan_as_double()); | |
| 4699 } else { | |
| 4700 Label not_hole; | |
| 4701 __ Branch(¬_hole, ne, sfpd_hi, Operand(kHoleNanUpper32)); | |
| 4702 __ li(reg, factory()->the_hole_value()); | |
| 4703 __ Branch(&done); | |
| 4704 __ bind(¬_hole); | |
| 4705 __ And(scratch, sfpd_hi, Operand(0x7ff00000)); | |
| 4706 __ Branch(&no_special_nan_handling, ne, scratch, Operand(0x7ff00000)); | |
| 4707 Label special_nan_handling; | |
| 4708 __ And(at, sfpd_hi, Operand(0x000FFFFF)); | |
| 4709 __ Branch(&special_nan_handling, ne, at, Operand(zero_reg)); | |
| 4710 __ Branch(&no_special_nan_handling, eq, sfpd_lo, Operand(zero_reg)); | |
| 4711 __ bind(&special_nan_handling); | |
| 4712 double canonical_nan = | |
| 4713 FixedDoubleArray::canonical_not_the_hole_nan_as_double(); | |
| 4714 uint64_t casted_nan = BitCast<uint64_t>(canonical_nan); | |
| 4715 __ li(sfpd_lo, | |
| 4716 Operand(static_cast<uint32_t>(casted_nan & 0xFFFFFFFF))); | |
| 4717 __ li(sfpd_hi, | |
| 4718 Operand(static_cast<uint32_t>(casted_nan >> 32))); | |
| 4719 } | |
| 4720 } | 4547 } |
| 4721 | 4548 |
| 4722 __ bind(&no_special_nan_handling); | 4549 __ bind(&no_special_nan_handling); |
| 4723 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4550 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
| 4724 if (FLAG_inline_new) { | 4551 if (FLAG_inline_new) { |
| 4725 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 4552 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 4726 // We want the untagged address first for performance | 4553 // We want the untagged address first for performance |
| 4727 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), | 4554 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), |
| 4728 DONT_TAG_RESULT); | 4555 DONT_TAG_RESULT); |
| 4729 } else { | 4556 } else { |
| 4730 __ Branch(deferred->entry()); | 4557 __ Branch(deferred->entry()); |
| 4731 } | 4558 } |
| 4732 __ bind(deferred->exit()); | 4559 __ bind(deferred->exit()); |
| 4733 if (CpuFeatures::IsSupported(FPU)) { | 4560 __ sdc1(input_reg, MemOperand(reg, HeapNumber::kValueOffset)); |
| 4734 CpuFeatureScope scope(masm(), FPU); | |
| 4735 __ sdc1(input_reg, MemOperand(reg, HeapNumber::kValueOffset)); | |
| 4736 } else { | |
| 4737 __ sw(sfpd_lo, MemOperand(reg, HeapNumber::kValueOffset)); | |
| 4738 __ sw(sfpd_hi, MemOperand(reg, HeapNumber::kValueOffset + kPointerSize)); | |
| 4739 } | |
| 4740 // Now that we have finished with the object's real address tag it | 4561 // Now that we have finished with the object's real address tag it |
| 4741 __ Addu(reg, reg, kHeapObjectTag); | 4562 __ Addu(reg, reg, kHeapObjectTag); |
| 4742 __ bind(&done); | 4563 __ bind(&done); |
| 4743 } | 4564 } |
| 4744 | 4565 |
| 4745 | 4566 |
| 4746 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4567 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 4747 // TODO(3095996): Get rid of this. For now, we need to make the | 4568 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4748 // result register contain a valid pointer because it is already | 4569 // result register contain a valid pointer because it is already |
| 4749 // contained in the register pointer map. | 4570 // contained in the register pointer map. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 4779 } | 4600 } |
| 4780 | 4601 |
| 4781 | 4602 |
| 4782 void LCodeGen::EmitNumberUntagD(Register input_reg, | 4603 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 4783 DoubleRegister result_reg, | 4604 DoubleRegister result_reg, |
| 4784 bool deoptimize_on_undefined, | 4605 bool deoptimize_on_undefined, |
| 4785 bool deoptimize_on_minus_zero, | 4606 bool deoptimize_on_minus_zero, |
| 4786 LEnvironment* env, | 4607 LEnvironment* env, |
| 4787 NumberUntagDMode mode) { | 4608 NumberUntagDMode mode) { |
| 4788 Register scratch = scratch0(); | 4609 Register scratch = scratch0(); |
| 4789 CpuFeatureScope scope(masm(), FPU); | |
| 4790 | 4610 |
| 4791 Label load_smi, heap_number, done; | 4611 Label load_smi, heap_number, done; |
| 4792 | 4612 |
| 4793 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { | 4613 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 4794 // Smi check. | 4614 // Smi check. |
| 4795 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); | 4615 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); |
| 4796 | 4616 |
| 4797 // Heap number map check. | 4617 // Heap number map check. |
| 4798 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4618 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4799 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 4619 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4856 | 4676 |
| 4857 Label done; | 4677 Label done; |
| 4858 | 4678 |
| 4859 // The input is a tagged HeapObject. | 4679 // The input is a tagged HeapObject. |
| 4860 // Heap number map check. | 4680 // Heap number map check. |
| 4861 __ lw(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4681 __ lw(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4862 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 4682 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 4863 // This 'at' value and scratch1 map value are used for tests in both clauses | 4683 // This 'at' value and scratch1 map value are used for tests in both clauses |
| 4864 // of the if. | 4684 // of the if. |
| 4865 | 4685 |
| 4866 CpuFeatureScope scope(masm(), FPU); | |
| 4867 if (instr->truncating()) { | 4686 if (instr->truncating()) { |
| 4868 Register scratch3 = ToRegister(instr->temp2()); | 4687 Register scratch3 = ToRegister(instr->temp2()); |
| 4869 FPURegister single_scratch = double_scratch.low(); | 4688 FPURegister single_scratch = double_scratch.low(); |
| 4870 ASSERT(!scratch3.is(input_reg) && | 4689 ASSERT(!scratch3.is(input_reg) && |
| 4871 !scratch3.is(scratch1) && | 4690 !scratch3.is(scratch1) && |
| 4872 !scratch3.is(scratch2)); | 4691 !scratch3.is(scratch2)); |
| 4873 // Performs a truncating conversion of a floating point number as used by | 4692 // Performs a truncating conversion of a floating point number as used by |
| 4874 // the JS bitwise operations. | 4693 // the JS bitwise operations. |
| 4875 Label heap_number; | 4694 Label heap_number; |
| 4876 __ Branch(&heap_number, eq, scratch1, Operand(at)); // HeapNumber map? | 4695 __ Branch(&heap_number, eq, scratch1, Operand(at)); // HeapNumber map? |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5112 __ CompareMapAndBranch( | 4931 __ CompareMapAndBranch( |
| 5113 map_reg, map, &success, eq, &success, REQUIRE_EXACT_MAP); | 4932 map_reg, map, &success, eq, &success, REQUIRE_EXACT_MAP); |
| 5114 } | 4933 } |
| 5115 Handle<Map> map = map_set->last(); | 4934 Handle<Map> map = map_set->last(); |
| 5116 DoCheckMapCommon(map_reg, map, REQUIRE_EXACT_MAP, instr->environment()); | 4935 DoCheckMapCommon(map_reg, map, REQUIRE_EXACT_MAP, instr->environment()); |
| 5117 __ bind(&success); | 4936 __ bind(&success); |
| 5118 } | 4937 } |
| 5119 | 4938 |
| 5120 | 4939 |
| 5121 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 4940 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
| 5122 CpuFeatureScope vfp_scope(masm(), FPU); | |
| 5123 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); | 4941 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); |
| 5124 Register result_reg = ToRegister(instr->result()); | 4942 Register result_reg = ToRegister(instr->result()); |
| 5125 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); | 4943 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); |
| 5126 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); | 4944 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); |
| 5127 } | 4945 } |
| 5128 | 4946 |
| 5129 | 4947 |
| 5130 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { | 4948 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
| 5131 CpuFeatureScope vfp_scope(masm(), FPU); | |
| 5132 Register unclamped_reg = ToRegister(instr->unclamped()); | 4949 Register unclamped_reg = ToRegister(instr->unclamped()); |
| 5133 Register result_reg = ToRegister(instr->result()); | 4950 Register result_reg = ToRegister(instr->result()); |
| 5134 __ ClampUint8(result_reg, unclamped_reg); | 4951 __ ClampUint8(result_reg, unclamped_reg); |
| 5135 } | 4952 } |
| 5136 | 4953 |
| 5137 | 4954 |
| 5138 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { | 4955 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
| 5139 CpuFeatureScope vfp_scope(masm(), FPU); | |
| 5140 Register scratch = scratch0(); | 4956 Register scratch = scratch0(); |
| 5141 Register input_reg = ToRegister(instr->unclamped()); | 4957 Register input_reg = ToRegister(instr->unclamped()); |
| 5142 Register result_reg = ToRegister(instr->result()); | 4958 Register result_reg = ToRegister(instr->result()); |
| 5143 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); | 4959 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); |
| 5144 Label is_smi, done, heap_number; | 4960 Label is_smi, done, heap_number; |
| 5145 | 4961 |
| 5146 // Both smi and heap number cases are handled. | 4962 // Both smi and heap number cases are handled. |
| 5147 __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi); | 4963 __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi); |
| 5148 | 4964 |
| 5149 // Check for heap number | 4965 // Check for heap number |
| (...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5906 __ Subu(scratch, result, scratch); | 5722 __ Subu(scratch, result, scratch); |
| 5907 __ lw(result, FieldMemOperand(scratch, | 5723 __ lw(result, FieldMemOperand(scratch, |
| 5908 FixedArray::kHeaderSize - kPointerSize)); | 5724 FixedArray::kHeaderSize - kPointerSize)); |
| 5909 __ bind(&done); | 5725 __ bind(&done); |
| 5910 } | 5726 } |
| 5911 | 5727 |
| 5912 | 5728 |
| 5913 #undef __ | 5729 #undef __ |
| 5914 | 5730 |
| 5915 } } // namespace v8::internal | 5731 } } // namespace v8::internal |
| OLD | NEW |