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