Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: src/mips/lithium-codegen-mips.cc

Issue 14113011: MIPS: Remove soft-float support. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/mips/full-codegen-mips.cc ('k') | src/mips/lithium-gap-resolver-mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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(&not_heap_number, ne, map, Operand(at)); 1905 __ Branch(&not_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(&not_heap_number); 1910 __ bind(&not_heap_number);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
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
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
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(&not_hole, ne, sfpd_hi, Operand(kHoleNanUpper32));
4702 __ li(reg, factory()->the_hole_value());
4703 __ Branch(&done);
4704 __ bind(&not_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
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
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
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
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
OLDNEW
« no previous file with comments | « src/mips/full-codegen-mips.cc ('k') | src/mips/lithium-gap-resolver-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698