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 957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
968 | 968 |
969 ReturnType value = 0; | 969 ReturnType value = 0; |
970 char buffer[register_size * sizeof(vfp_registers_[0])]; | 970 char buffer[register_size * sizeof(vfp_registers_[0])]; |
971 OS::MemCopy(buffer, &vfp_registers_[register_size * reg_index], | 971 OS::MemCopy(buffer, &vfp_registers_[register_size * reg_index], |
972 register_size * sizeof(vfp_registers_[0])); | 972 register_size * sizeof(vfp_registers_[0])); |
973 OS::MemCopy(&value, buffer, register_size * sizeof(vfp_registers_[0])); | 973 OS::MemCopy(&value, buffer, register_size * sizeof(vfp_registers_[0])); |
974 return value; | 974 return value; |
975 } | 975 } |
976 | 976 |
977 | 977 |
978 // Runtime FP routines take up to two double arguments and zero | 978 // For use in calls that take two double values, constructed either |
979 // or one integer arguments. All are constructed here, | |
980 // from r0-r3 or d0 and d1. | 979 // from r0-r3 or d0 and d1. |
981 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { | 980 void Simulator::GetFpArgs(double* x, double* y) { |
982 if (use_eabi_hardfloat()) { | 981 if (use_eabi_hardfloat()) { |
983 *x = vfp_registers_[0]; | 982 *x = vfp_registers_[0]; |
984 *y = vfp_registers_[1]; | 983 *y = vfp_registers_[1]; |
985 *z = registers_[1]; | |
986 } else { | 984 } else { |
987 // We use a char buffer to get around the strict-aliasing rules which | 985 // We use a char buffer to get around the strict-aliasing rules which |
988 // otherwise allow the compiler to optimize away the copy. | 986 // otherwise allow the compiler to optimize away the copy. |
989 char buffer[sizeof(*x)]; | 987 char buffer[sizeof(*x)]; |
990 // Registers 0 and 1 -> x. | 988 // Registers 0 and 1 -> x. |
991 OS::MemCopy(buffer, registers_, sizeof(*x)); | 989 OS::MemCopy(buffer, registers_, sizeof(*x)); |
992 OS::MemCopy(x, buffer, sizeof(*x)); | 990 OS::MemCopy(x, buffer, sizeof(*x)); |
993 // Registers 2 and 3 -> y. | 991 // Registers 2 and 3 -> y. |
994 OS::MemCopy(buffer, registers_ + 2, sizeof(*y)); | 992 OS::MemCopy(buffer, registers_ + 2, sizeof(*y)); |
995 OS::MemCopy(y, buffer, sizeof(*y)); | 993 OS::MemCopy(y, buffer, sizeof(*y)); |
996 // Register 2 -> z. | |
997 OS::MemCopy(buffer, registers_ + 2, sizeof(*z)); | |
998 OS::MemCopy(z, buffer, sizeof(*z)); | |
999 } | 994 } |
1000 } | 995 } |
1001 | 996 |
| 997 // For use in calls that take one double value, constructed either |
| 998 // from r0 and r1 or d0. |
| 999 void Simulator::GetFpArgs(double* x) { |
| 1000 if (use_eabi_hardfloat()) { |
| 1001 *x = vfp_registers_[0]; |
| 1002 } else { |
| 1003 // We use a char buffer to get around the strict-aliasing rules which |
| 1004 // otherwise allow the compiler to optimize away the copy. |
| 1005 char buffer[sizeof(*x)]; |
| 1006 // Registers 0 and 1 -> x. |
| 1007 OS::MemCopy(buffer, registers_, sizeof(*x)); |
| 1008 OS::MemCopy(x, buffer, sizeof(*x)); |
| 1009 } |
| 1010 } |
| 1011 |
| 1012 |
| 1013 // For use in calls that take one double value constructed either |
| 1014 // from r0 and r1 or d0 and one integer value. |
| 1015 void Simulator::GetFpArgs(double* x, int32_t* y) { |
| 1016 if (use_eabi_hardfloat()) { |
| 1017 *x = vfp_registers_[0]; |
| 1018 *y = registers_[1]; |
| 1019 } else { |
| 1020 // We use a char buffer to get around the strict-aliasing rules which |
| 1021 // otherwise allow the compiler to optimize away the copy. |
| 1022 char buffer[sizeof(*x)]; |
| 1023 // Registers 0 and 1 -> x. |
| 1024 OS::MemCopy(buffer, registers_, sizeof(*x)); |
| 1025 OS::MemCopy(x, buffer, sizeof(*x)); |
| 1026 // Register 2 -> y. |
| 1027 OS::MemCopy(buffer, registers_ + 2, sizeof(*y)); |
| 1028 OS::MemCopy(y, buffer, sizeof(*y)); |
| 1029 } |
| 1030 } |
| 1031 |
1002 | 1032 |
1003 // The return value is either in r0/r1 or d0. | 1033 // The return value is either in r0/r1 or d0. |
1004 void Simulator::SetFpResult(const double& result) { | 1034 void Simulator::SetFpResult(const double& result) { |
1005 if (use_eabi_hardfloat()) { | 1035 if (use_eabi_hardfloat()) { |
1006 char buffer[2 * sizeof(vfp_registers_[0])]; | 1036 char buffer[2 * sizeof(vfp_registers_[0])]; |
1007 OS::MemCopy(buffer, &result, sizeof(buffer)); | 1037 OS::MemCopy(buffer, &result, sizeof(buffer)); |
1008 // Copy result to d0. | 1038 // Copy result to d0. |
1009 OS::MemCopy(vfp_registers_, buffer, sizeof(buffer)); | 1039 OS::MemCopy(vfp_registers_, buffer, sizeof(buffer)); |
1010 } else { | 1040 } else { |
1011 char buffer[2 * sizeof(registers_[0])]; | 1041 char buffer[2 * sizeof(registers_[0])]; |
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1611 // uses the ObjectPair which is essentially two 32-bit values stuffed into a | 1641 // uses the ObjectPair which is essentially two 32-bit values stuffed into a |
1612 // 64-bit value. With the code below we assume that all runtime calls return | 1642 // 64-bit value. With the code below we assume that all runtime calls return |
1613 // 64 bits of result. If they don't, the r1 result register contains a bogus | 1643 // 64 bits of result. If they don't, the r1 result register contains a bogus |
1614 // value, which is fine because it is caller-saved. | 1644 // value, which is fine because it is caller-saved. |
1615 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 1645 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, |
1616 int32_t arg1, | 1646 int32_t arg1, |
1617 int32_t arg2, | 1647 int32_t arg2, |
1618 int32_t arg3, | 1648 int32_t arg3, |
1619 int32_t arg4, | 1649 int32_t arg4, |
1620 int32_t arg5); | 1650 int32_t arg5); |
1621 | 1651 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, |
1622 // These prototypes handle the four types of FP calls. | 1652 int32_t arg1, |
1623 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1); | 1653 int32_t arg2, |
1624 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1); | 1654 int32_t arg3); |
1625 typedef double (*SimulatorRuntimeFPCall)(double darg0); | |
1626 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0); | |
1627 | 1655 |
1628 // This signature supports direct call in to API function native callback | 1656 // This signature supports direct call in to API function native callback |
1629 // (refer to InvocationCallback in v8.h). | 1657 // (refer to InvocationCallback in v8.h). |
1630 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0); | 1658 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0); |
1631 | 1659 |
1632 // This signature supports direct call to accessor getter callback. | 1660 // This signature supports direct call to accessor getter callback. |
1633 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, | 1661 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, |
1634 int32_t arg1); | 1662 int32_t arg1); |
1635 | 1663 |
1636 // Software interrupt instructions are used by the simulator to call into the | 1664 // Software interrupt instructions are used by the simulator to call into the |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1682 default: | 1710 default: |
1683 break; | 1711 break; |
1684 } | 1712 } |
1685 } | 1713 } |
1686 // This is dodgy but it works because the C entry stubs are never moved. | 1714 // This is dodgy but it works because the C entry stubs are never moved. |
1687 // See comment in codegen-arm.cc and bug 1242173. | 1715 // See comment in codegen-arm.cc and bug 1242173. |
1688 int32_t saved_lr = get_register(lr); | 1716 int32_t saved_lr = get_register(lr); |
1689 intptr_t external = | 1717 intptr_t external = |
1690 reinterpret_cast<intptr_t>(redirection->external_function()); | 1718 reinterpret_cast<intptr_t>(redirection->external_function()); |
1691 if (fp_call) { | 1719 if (fp_call) { |
1692 double dval0, dval1; // one or two double parameters | |
1693 int32_t ival; // zero or one integer parameters | |
1694 int64_t iresult = 0; // integer return value | |
1695 double dresult = 0; // double return value | |
1696 GetFpArgs(&dval0, &dval1, &ival); | |
1697 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1720 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
1698 SimulatorRuntimeCall generic_target = | 1721 SimulatorRuntimeFPCall target = |
1699 reinterpret_cast<SimulatorRuntimeCall>(external); | 1722 reinterpret_cast<SimulatorRuntimeFPCall>(external); |
| 1723 double dval0, dval1; |
| 1724 int32_t ival; |
1700 switch (redirection->type()) { | 1725 switch (redirection->type()) { |
1701 case ExternalReference::BUILTIN_FP_FP_CALL: | 1726 case ExternalReference::BUILTIN_FP_FP_CALL: |
1702 case ExternalReference::BUILTIN_COMPARE_CALL: | 1727 case ExternalReference::BUILTIN_COMPARE_CALL: |
| 1728 GetFpArgs(&dval0, &dval1); |
1703 PrintF("Call to host function at %p with args %f, %f", | 1729 PrintF("Call to host function at %p with args %f, %f", |
1704 FUNCTION_ADDR(generic_target), dval0, dval1); | 1730 FUNCTION_ADDR(target), dval0, dval1); |
1705 break; | 1731 break; |
1706 case ExternalReference::BUILTIN_FP_CALL: | 1732 case ExternalReference::BUILTIN_FP_CALL: |
| 1733 GetFpArgs(&dval0); |
1707 PrintF("Call to host function at %p with arg %f", | 1734 PrintF("Call to host function at %p with arg %f", |
1708 FUNCTION_ADDR(generic_target), dval0); | 1735 FUNCTION_ADDR(target), dval0); |
1709 break; | 1736 break; |
1710 case ExternalReference::BUILTIN_FP_INT_CALL: | 1737 case ExternalReference::BUILTIN_FP_INT_CALL: |
| 1738 GetFpArgs(&dval0, &ival); |
1711 PrintF("Call to host function at %p with args %f, %d", | 1739 PrintF("Call to host function at %p with args %f, %d", |
1712 FUNCTION_ADDR(generic_target), dval0, ival); | 1740 FUNCTION_ADDR(target), dval0, ival); |
1713 break; | 1741 break; |
1714 default: | 1742 default: |
1715 UNREACHABLE(); | 1743 UNREACHABLE(); |
1716 break; | 1744 break; |
1717 } | 1745 } |
1718 if (!stack_aligned) { | 1746 if (!stack_aligned) { |
1719 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1747 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
1720 } | 1748 } |
1721 PrintF("\n"); | 1749 PrintF("\n"); |
1722 } | 1750 } |
1723 CHECK(stack_aligned); | 1751 CHECK(stack_aligned); |
1724 switch (redirection->type()) { | 1752 if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) { |
1725 case ExternalReference::BUILTIN_COMPARE_CALL: { | |
1726 SimulatorRuntimeCompareCall target = | |
1727 reinterpret_cast<SimulatorRuntimeCompareCall>(external); | |
1728 iresult = target(dval0, dval1); | |
1729 set_register(r0, static_cast<int32_t>(iresult)); | |
1730 set_register(r1, static_cast<int32_t>(iresult >> 32)); | |
1731 break; | |
1732 } | |
1733 case ExternalReference::BUILTIN_FP_FP_CALL: { | |
1734 SimulatorRuntimeFPFPCall target = | |
1735 reinterpret_cast<SimulatorRuntimeFPFPCall>(external); | |
1736 dresult = target(dval0, dval1); | |
1737 SetFpResult(dresult); | |
1738 break; | |
1739 } | |
1740 case ExternalReference::BUILTIN_FP_CALL: { | |
1741 SimulatorRuntimeFPCall target = | 1753 SimulatorRuntimeFPCall target = |
1742 reinterpret_cast<SimulatorRuntimeFPCall>(external); | 1754 reinterpret_cast<SimulatorRuntimeFPCall>(external); |
1743 dresult = target(dval0); | 1755 double result = target(arg0, arg1, arg2, arg3); |
1744 SetFpResult(dresult); | 1756 SetFpResult(result); |
1745 break; | 1757 } else { |
1746 } | 1758 SimulatorRuntimeCall target = |
1747 case ExternalReference::BUILTIN_FP_INT_CALL: { | 1759 reinterpret_cast<SimulatorRuntimeCall>(external); |
1748 SimulatorRuntimeFPIntCall target = | 1760 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); |
1749 reinterpret_cast<SimulatorRuntimeFPIntCall>(external); | 1761 int32_t lo_res = static_cast<int32_t>(result); |
1750 dresult = target(dval0, ival); | 1762 int32_t hi_res = static_cast<int32_t>(result >> 32); |
1751 SetFpResult(dresult); | 1763 if (::v8::internal::FLAG_trace_sim) { |
1752 break; | 1764 PrintF("Returned %08x\n", lo_res); |
1753 } | |
1754 default: | |
1755 UNREACHABLE(); | |
1756 break; | |
1757 } | |
1758 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | |
1759 switch (redirection->type()) { | |
1760 case ExternalReference::BUILTIN_COMPARE_CALL: | |
1761 PrintF("Returned %08x\n", static_cast<int32_t>(iresult)); | |
1762 break; | |
1763 case ExternalReference::BUILTIN_FP_FP_CALL: | |
1764 case ExternalReference::BUILTIN_FP_CALL: | |
1765 case ExternalReference::BUILTIN_FP_INT_CALL: | |
1766 PrintF("Returned %f\n", dresult); | |
1767 break; | |
1768 default: | |
1769 UNREACHABLE(); | |
1770 break; | |
1771 } | 1765 } |
| 1766 set_register(r0, lo_res); |
| 1767 set_register(r1, hi_res); |
1772 } | 1768 } |
1773 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { | 1769 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { |
1774 SimulatorRuntimeDirectApiCall target = | 1770 SimulatorRuntimeDirectApiCall target = |
1775 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); | 1771 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); |
1776 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1772 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
1777 PrintF("Call to host function at %p args %08x", | 1773 PrintF("Call to host function at %p args %08x", |
1778 FUNCTION_ADDR(target), arg0); | 1774 FUNCTION_ADDR(target), arg0); |
1779 if (!stack_aligned) { | 1775 if (!stack_aligned) { |
1780 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1776 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
1781 } | 1777 } |
(...skipping 1707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3489 uintptr_t address = *stack_slot; | 3485 uintptr_t address = *stack_slot; |
3490 set_register(sp, current_sp + sizeof(uintptr_t)); | 3486 set_register(sp, current_sp + sizeof(uintptr_t)); |
3491 return address; | 3487 return address; |
3492 } | 3488 } |
3493 | 3489 |
3494 } } // namespace v8::internal | 3490 } } // namespace v8::internal |
3495 | 3491 |
3496 #endif // USE_SIMULATOR | 3492 #endif // USE_SIMULATOR |
3497 | 3493 |
3498 #endif // V8_TARGET_ARCH_ARM | 3494 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |