| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 | 95 |
| 96 __ BranchEqual(T2, fp_sp_dist, &stack_ok); | 96 __ BranchEqual(T2, fp_sp_dist, &stack_ok); |
| 97 __ break_(0); | 97 __ break_(0); |
| 98 | 98 |
| 99 __ Bind(&stack_ok); | 99 __ Bind(&stack_ok); |
| 100 } | 100 } |
| 101 #endif | 101 #endif |
| 102 // This sequence is patched by a debugger breakpoint. There is no need for | 102 // This sequence is patched by a debugger breakpoint. There is no need for |
| 103 // extra NOP instructions here because the sequence patched in for a | 103 // extra NOP instructions here because the sequence patched in for a |
| 104 // breakpoint is shorter than the sequence here. | 104 // breakpoint is shorter than the sequence here. |
| 105 __ LeaveDartFrame(); | 105 __ LeaveDartFrameAndReturn(); |
| 106 __ Ret(); | |
| 107 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 106 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| 108 Isolate::kNoDeoptId, | 107 Isolate::kNoDeoptId, |
| 109 token_pos()); | 108 token_pos()); |
| 110 } | 109 } |
| 111 | 110 |
| 112 | 111 |
| 113 bool IfThenElseInstr::IsSupported() { | 112 bool IfThenElseInstr::IsSupported() { |
| 114 return false; | 113 return false; |
| 115 } | 114 } |
| 116 | 115 |
| (...skipping 1123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1240 | 1239 |
| 1241 LoadValueCid(compiler, value_cid_reg, value_reg); | 1240 LoadValueCid(compiler, value_cid_reg, value_reg); |
| 1242 | 1241 |
| 1243 __ lw(TMP1, field_cid_operand); | 1242 __ lw(TMP1, field_cid_operand); |
| 1244 __ beq(value_cid_reg, TMP1, &ok); | 1243 __ beq(value_cid_reg, TMP1, &ok); |
| 1245 __ lw(TMP1, field_nullability_operand); | 1244 __ lw(TMP1, field_nullability_operand); |
| 1246 __ subu(CMPRES, value_cid_reg, TMP1); | 1245 __ subu(CMPRES, value_cid_reg, TMP1); |
| 1247 } else if (value_cid == kNullCid) { | 1246 } else if (value_cid == kNullCid) { |
| 1248 // TODO(regis): TMP1 may conflict. Revisit. | 1247 // TODO(regis): TMP1 may conflict. Revisit. |
| 1249 __ lw(TMP1, field_nullability_operand); | 1248 __ lw(TMP1, field_nullability_operand); |
| 1250 __ LoadImmediate(TMP2, value_cid); | 1249 __ LoadImmediate(CMPRES, value_cid); |
| 1251 __ subu(CMPRES, TMP1, TMP2); | 1250 __ subu(CMPRES, TMP1, CMPRES); |
| 1252 } else { | 1251 } else { |
| 1253 // TODO(regis): TMP1 may conflict. Revisit. | 1252 // TODO(regis): TMP1 may conflict. Revisit. |
| 1254 __ lw(TMP1, field_cid_operand); | 1253 __ lw(TMP1, field_cid_operand); |
| 1255 __ LoadImmediate(TMP2, value_cid); | 1254 __ LoadImmediate(CMPRES, value_cid); |
| 1256 __ subu(CMPRES, TMP1, TMP2); | 1255 __ subu(CMPRES, TMP1, CMPRES); |
| 1257 } | 1256 } |
| 1258 __ beq(CMPRES, ZR, &ok); | 1257 __ beq(CMPRES, ZR, &ok); |
| 1259 | 1258 |
| 1260 __ lw(TMP1, field_cid_operand); | 1259 __ lw(TMP1, field_cid_operand); |
| 1261 __ BranchNotEqual(TMP1, kIllegalCid, fail); | 1260 __ BranchNotEqual(TMP1, kIllegalCid, fail); |
| 1262 | 1261 |
| 1263 if (value_cid == kDynamicCid) { | 1262 if (value_cid == kDynamicCid) { |
| 1264 __ sw(value_cid_reg, field_cid_operand); | 1263 __ sw(value_cid_reg, field_cid_operand); |
| 1265 __ sw(value_cid_reg, field_nullability_operand); | 1264 __ sw(value_cid_reg, field_nullability_operand); |
| 1266 } else { | 1265 } else { |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1495 const intptr_t len = type_arguments().Length(); | 1494 const intptr_t len = type_arguments().Length(); |
| 1496 if (type_arguments().IsRawInstantiatedRaw(len)) { | 1495 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 1497 __ BranchEqual(instantiator_reg, | 1496 __ BranchEqual(instantiator_reg, |
| 1498 reinterpret_cast<intptr_t>(Object::null()), | 1497 reinterpret_cast<intptr_t>(Object::null()), |
| 1499 &type_arguments_instantiated); | 1498 &type_arguments_instantiated); |
| 1500 } | 1499 } |
| 1501 // Instantiate non-null type arguments. | 1500 // Instantiate non-null type arguments. |
| 1502 // A runtime call to instantiate the type arguments is required. | 1501 // A runtime call to instantiate the type arguments is required. |
| 1503 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 1502 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| 1504 __ LoadObject(TMP1, Object::ZoneHandle()); | 1503 __ LoadObject(TMP1, Object::ZoneHandle()); |
| 1505 __ LoadObject(TMP2, type_arguments()); | |
| 1506 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Make room for the result. | 1504 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Make room for the result. |
| 1507 __ sw(TMP2, Address(SP, 1 * kWordSize)); | 1505 __ LoadObject(TMP1, type_arguments()); |
| 1506 __ sw(TMP1, Address(SP, 1 * kWordSize)); |
| 1508 // Push instantiator type arguments. | 1507 // Push instantiator type arguments. |
| 1509 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); | 1508 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); |
| 1510 | 1509 |
| 1511 compiler->GenerateCallRuntime(token_pos(), | 1510 compiler->GenerateCallRuntime(token_pos(), |
| 1512 deopt_id(), | 1511 deopt_id(), |
| 1513 kInstantiateTypeArgumentsRuntimeEntry, | 1512 kInstantiateTypeArgumentsRuntimeEntry, |
| 1514 locs()); | 1513 locs()); |
| 1515 // Pop instantiated type arguments. | 1514 // Pop instantiated type arguments. |
| 1516 __ lw(result_reg, Address(SP, 2 * kWordSize)); | 1515 __ lw(result_reg, Address(SP, 2 * kWordSize)); |
| 1517 // Drop instantiator and uninstantiated type arguments. | 1516 // Drop instantiator and uninstantiated type arguments. |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1671 | 1670 |
| 1672 ASSERT(!exception_var().is_captured()); | 1671 ASSERT(!exception_var().is_captured()); |
| 1673 ASSERT(!stacktrace_var().is_captured()); | 1672 ASSERT(!stacktrace_var().is_captured()); |
| 1674 | 1673 |
| 1675 __ sw(kExceptionObjectReg, | 1674 __ sw(kExceptionObjectReg, |
| 1676 Address(FP, exception_var().index() * kWordSize)); | 1675 Address(FP, exception_var().index() * kWordSize)); |
| 1677 __ sw(kStackTraceObjectReg, | 1676 __ sw(kStackTraceObjectReg, |
| 1678 Address(FP, stacktrace_var().index() * kWordSize)); | 1677 Address(FP, stacktrace_var().index() * kWordSize)); |
| 1679 | 1678 |
| 1680 Label next; | 1679 Label next; |
| 1681 __ mov(TMP1, RA); // Save return adress. | 1680 __ mov(T0, RA); // Save return adress. |
| 1682 // Restore the pool pointer. | 1681 // Restore the pool pointer. |
| 1683 __ bal(&next); // Branch and link to next instruction to get PC in RA. | 1682 __ bal(&next); // Branch and link to next instruction to get PC in RA. |
| 1684 __ delay_slot()->mov(TMP2, RA); // Save PC of the following mov. | 1683 __ delay_slot()->mov(T1, RA); // Save PC of the following mov. |
| 1685 | 1684 |
| 1686 // Calculate offset of pool pointer from the PC. | 1685 // Calculate offset of pool pointer from the PC. |
| 1687 const intptr_t object_pool_pc_dist = | 1686 const intptr_t object_pool_pc_dist = |
| 1688 Instructions::HeaderSize() - Instructions::object_pool_offset() + | 1687 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 1689 compiler->assembler()->CodeSize(); | 1688 compiler->assembler()->CodeSize(); |
| 1690 | 1689 |
| 1691 __ Bind(&next); | 1690 __ Bind(&next); |
| 1692 __ mov(RA, TMP1); // Restore return address. | 1691 __ mov(RA, T0); // Restore return address. |
| 1693 __ lw(PP, Address(TMP2, -object_pool_pc_dist)); | 1692 __ lw(PP, Address(T1, -object_pool_pc_dist)); |
| 1694 } | 1693 } |
| 1695 | 1694 |
| 1696 | 1695 |
| 1697 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const { | 1696 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const { |
| 1698 const intptr_t kNumInputs = 0; | 1697 const intptr_t kNumInputs = 0; |
| 1699 const intptr_t kNumTemps = 0; | 1698 const intptr_t kNumTemps = 0; |
| 1700 LocationSummary* summary = | 1699 LocationSummary* summary = |
| 1701 new LocationSummary(kNumInputs, | 1700 new LocationSummary(kNumInputs, |
| 1702 kNumTemps, | 1701 kNumTemps, |
| 1703 LocationSummary::kCallOnSlowPath); | 1702 LocationSummary::kCallOnSlowPath); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1751 const intptr_t kNumInputs = 2; | 1750 const intptr_t kNumInputs = 2; |
| 1752 if (op_kind() == Token::kTRUNCDIV) { | 1751 if (op_kind() == Token::kTRUNCDIV) { |
| 1753 UNIMPLEMENTED(); | 1752 UNIMPLEMENTED(); |
| 1754 return NULL; | 1753 return NULL; |
| 1755 } else { | 1754 } else { |
| 1756 const intptr_t kNumTemps = 0; | 1755 const intptr_t kNumTemps = 0; |
| 1757 LocationSummary* summary = | 1756 LocationSummary* summary = |
| 1758 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1757 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1759 summary->set_in(0, Location::RequiresRegister()); | 1758 summary->set_in(0, Location::RequiresRegister()); |
| 1760 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 1759 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 1760 if (op_kind() == Token::kADD) { |
| 1761 // Need an extra temp for the overflow detection code. |
| 1762 summary->set_temp(0, Location::RequiresRegister()); |
| 1763 } |
| 1761 // We make use of 3-operand instructions by not requiring result register | 1764 // We make use of 3-operand instructions by not requiring result register |
| 1762 // to be identical to first input register as on Intel. | 1765 // to be identical to first input register as on Intel. |
| 1763 summary->set_out(Location::RequiresRegister()); | 1766 summary->set_out(Location::RequiresRegister()); |
| 1764 return summary; | 1767 return summary; |
| 1765 } | 1768 } |
| 1766 } | 1769 } |
| 1767 | 1770 |
| 1768 | 1771 |
| 1769 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1772 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1770 __ TraceSimMsg("BinarySmiOpInstr"); | 1773 __ TraceSimMsg("BinarySmiOpInstr"); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1792 } else { | 1795 } else { |
| 1793 __ SubImmediateDetectOverflow(result, left, imm, CMPRES); | 1796 __ SubImmediateDetectOverflow(result, left, imm, CMPRES); |
| 1794 __ bltz(CMPRES, deopt); | 1797 __ bltz(CMPRES, deopt); |
| 1795 } | 1798 } |
| 1796 break; | 1799 break; |
| 1797 } | 1800 } |
| 1798 case Token::kADD: { | 1801 case Token::kADD: { |
| 1799 if (deopt == NULL) { | 1802 if (deopt == NULL) { |
| 1800 __ AddImmediate(result, left, imm); | 1803 __ AddImmediate(result, left, imm); |
| 1801 } else { | 1804 } else { |
| 1802 __ AddImmediateDetectOverflow(result, left, imm, CMPRES); | 1805 Register temp = locs()->temp(0).reg(); |
| 1806 __ AddImmediateDetectOverflow(result, left, imm, CMPRES, temp); |
| 1803 __ bltz(CMPRES, deopt); | 1807 __ bltz(CMPRES, deopt); |
| 1804 } | 1808 } |
| 1805 break; | 1809 break; |
| 1806 } | 1810 } |
| 1807 case Token::kMUL: { | 1811 case Token::kMUL: { |
| 1808 // Keep left value tagged and untag right value. | 1812 // Keep left value tagged and untag right value. |
| 1809 const intptr_t value = Smi::Cast(constant).Value(); | 1813 const intptr_t value = Smi::Cast(constant).Value(); |
| 1810 if (deopt == NULL) { | 1814 if (deopt == NULL) { |
| 1811 if (value == 2) { | 1815 if (value == 2) { |
| 1812 __ sll(result, left, 1); | 1816 __ sll(result, left, 1); |
| 1813 } else { | 1817 } else { |
| 1814 __ LoadImmediate(TMP1, value); | 1818 __ LoadImmediate(TMP1, value); |
| 1815 __ mult(left, TMP1); | 1819 __ mult(left, TMP1); |
| 1816 __ mflo(result); | 1820 __ mflo(result); |
| 1817 } | 1821 } |
| 1818 } else { | 1822 } else { |
| 1819 if (value == 2) { | 1823 if (value == 2) { |
| 1820 __ sra(TMP1, left, 31); // TMP1 = sign of left. | 1824 __ sra(TMP1, left, 31); // TMP1 = sign of left. |
| 1821 __ sll(result, left, 1); | 1825 __ sll(result, left, 1); |
| 1822 } else { | 1826 } else { |
| 1823 __ LoadImmediate(TMP1, value); | 1827 __ LoadImmediate(TMP1, value); |
| 1824 __ mult(left, TMP1); | 1828 __ mult(left, TMP1); |
| 1825 __ mflo(result); | 1829 __ mflo(result); |
| 1826 __ mfhi(TMP1); | 1830 __ mfhi(TMP1); |
| 1827 } | 1831 } |
| 1828 __ sra(TMP2, result, 31); | 1832 __ sra(CMPRES, result, 31); |
| 1829 __ bne(TMP1, TMP2, deopt); | 1833 __ bne(TMP1, CMPRES, deopt); |
| 1830 } | 1834 } |
| 1831 break; | 1835 break; |
| 1832 } | 1836 } |
| 1833 case Token::kTRUNCDIV: { | 1837 case Token::kTRUNCDIV: { |
| 1834 UNIMPLEMENTED(); | 1838 UNIMPLEMENTED(); |
| 1835 break; | 1839 break; |
| 1836 } | 1840 } |
| 1837 case Token::kBIT_AND: { | 1841 case Token::kBIT_AND: { |
| 1838 // No overflow check. | 1842 // No overflow check. |
| 1839 if (Utils::IsUint(kImmBits, imm)) { | 1843 if (Utils::IsUint(kImmBits, imm)) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1875 } | 1879 } |
| 1876 return; | 1880 return; |
| 1877 } | 1881 } |
| 1878 | 1882 |
| 1879 Register right = locs()->in(1).reg(); | 1883 Register right = locs()->in(1).reg(); |
| 1880 switch (op_kind()) { | 1884 switch (op_kind()) { |
| 1881 case Token::kADD: { | 1885 case Token::kADD: { |
| 1882 if (deopt == NULL) { | 1886 if (deopt == NULL) { |
| 1883 __ addu(result, left, right); | 1887 __ addu(result, left, right); |
| 1884 } else { | 1888 } else { |
| 1885 __ AdduDetectOverflow(result, left, right, CMPRES); | 1889 Register temp = locs()->temp(0).reg(); |
| 1890 __ AdduDetectOverflow(result, left, right, CMPRES, temp); |
| 1886 __ bltz(CMPRES, deopt); | 1891 __ bltz(CMPRES, deopt); |
| 1887 } | 1892 } |
| 1888 break; | 1893 break; |
| 1889 } | 1894 } |
| 1890 case Token::kSUB: { | 1895 case Token::kSUB: { |
| 1891 if (deopt == NULL) { | 1896 if (deopt == NULL) { |
| 1892 __ subu(result, left, right); | 1897 __ subu(result, left, right); |
| 1893 } else { | 1898 } else { |
| 1894 __ SubuDetectOverflow(result, left, right, CMPRES); | 1899 __ SubuDetectOverflow(result, left, right, CMPRES); |
| 1895 __ bltz(CMPRES, deopt); | 1900 __ bltz(CMPRES, deopt); |
| (...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2808 &label, | 2813 &label, |
| 2809 PcDescriptors::kOther, | 2814 PcDescriptors::kOther, |
| 2810 locs()); | 2815 locs()); |
| 2811 __ Drop(2); // Discard type arguments and receiver. | 2816 __ Drop(2); // Discard type arguments and receiver. |
| 2812 } | 2817 } |
| 2813 | 2818 |
| 2814 } // namespace dart | 2819 } // namespace dart |
| 2815 | 2820 |
| 2816 #endif // defined TARGET_ARCH_MIPS | 2821 #endif // defined TARGET_ARCH_MIPS |
| 2817 | 2822 |
| OLD | NEW |