OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 double dm_val = 0.0; | 1002 double dm_val = 0.0; |
1003 // Read the bits from the unsigned integer vfp_register[] array | 1003 // Read the bits from the unsigned integer vfp_register[] array |
1004 // into the double precision floating point value and return it. | 1004 // into the double precision floating point value and return it. |
1005 char buffer[2 * sizeof(vfp_register[0])]; | 1005 char buffer[2 * sizeof(vfp_register[0])]; |
1006 memcpy(buffer, &vfp_register[2 * dreg], 2 * sizeof(vfp_register[0])); | 1006 memcpy(buffer, &vfp_register[2 * dreg], 2 * sizeof(vfp_register[0])); |
1007 memcpy(&dm_val, buffer, 2 * sizeof(vfp_register[0])); | 1007 memcpy(&dm_val, buffer, 2 * sizeof(vfp_register[0])); |
1008 return(dm_val); | 1008 return(dm_val); |
1009 } | 1009 } |
1010 | 1010 |
1011 | 1011 |
1012 // For use in calls that take two double values, constructed from r0, r1, r2 | 1012 // For use in calls that take two double values, constructed either |
1013 // and r3. | 1013 // from r0-r3 or d0 and d1. |
1014 void Simulator::GetFpArgs(double* x, double* y) { | 1014 void Simulator::GetFpArgs(double* x, double* y) { |
1015 // We use a char buffer to get around the strict-aliasing rules which | 1015 if (FLAG_hardfloat) { |
1016 // otherwise allow the compiler to optimize away the copy. | 1016 *x = vfp_register[0]; |
1017 char buffer[2 * sizeof(registers_[0])]; | 1017 *y = vfp_register[1]; |
1018 // Registers 0 and 1 -> x. | 1018 } else { |
1019 memcpy(buffer, registers_, sizeof(buffer)); | 1019 // We use a char buffer to get around the strict-aliasing rules which |
1020 memcpy(x, buffer, sizeof(buffer)); | 1020 // otherwise allow the compiler to optimize away the copy. |
1021 // Registers 2 and 3 -> y. | 1021 char buffer[2 * sizeof(registers_[0])]; |
1022 memcpy(buffer, registers_ + 2, sizeof(buffer)); | 1022 // Registers 0 and 1 -> x. |
1023 memcpy(y, buffer, sizeof(buffer)); | 1023 memcpy(buffer, registers_, sizeof(buffer)); |
| 1024 memcpy(x, buffer, sizeof(buffer)); |
| 1025 // Registers 2 and 3 -> y. |
| 1026 memcpy(buffer, registers_ + 2, sizeof(buffer)); |
| 1027 memcpy(y, buffer, sizeof(buffer)); |
| 1028 } |
| 1029 } |
| 1030 |
| 1031 // For use in calls that take one double value, constructed either |
| 1032 // from r0 and r1 or d0. |
| 1033 void Simulator::GetFpArgs(double* x) { |
| 1034 if (FLAG_hardfloat) { |
| 1035 *x = vfp_register[0]; |
| 1036 } else { |
| 1037 // We use a char buffer to get around the strict-aliasing rules which |
| 1038 // otherwise allow the compiler to optimize away the copy. |
| 1039 char buffer[2 * sizeof(registers_[0])]; |
| 1040 // Registers 0 and 1 -> x. |
| 1041 memcpy(buffer, registers_, sizeof(buffer)); |
| 1042 memcpy(x, buffer, sizeof(buffer)); |
| 1043 } |
1024 } | 1044 } |
1025 | 1045 |
1026 | 1046 |
1027 void Simulator::SetFpResult(const double& result) { | 1047 // For use in calls that take two double values, constructed either |
1028 char buffer[2 * sizeof(registers_[0])]; | 1048 // from r0-r3 or d0 and d1. |
1029 memcpy(buffer, &result, sizeof(buffer)); | 1049 void Simulator::GetFpArgs(double* x, int32_t* y) { |
1030 // result -> registers 0 and 1. | 1050 if (FLAG_hardfloat) { |
1031 memcpy(registers_, buffer, sizeof(buffer)); | 1051 *x = vfp_register[0]; |
| 1052 *y = registers_[1]; |
| 1053 } else { |
| 1054 // We use a char buffer to get around the strict-aliasing rules which |
| 1055 // otherwise allow the compiler to optimize away the copy. |
| 1056 char buffer[2 * sizeof(registers_[0])]; |
| 1057 // Registers 0 and 1 -> x. |
| 1058 memcpy(buffer, registers_, sizeof(buffer)); |
| 1059 memcpy(x, buffer, sizeof(buffer)); |
| 1060 // Registers 2 and 3 -> y. |
| 1061 memcpy(buffer, registers_ + 2, sizeof(buffer)); |
| 1062 memcpy(y, buffer, sizeof(buffer)); |
| 1063 } |
1032 } | 1064 } |
1033 | 1065 |
1034 | 1066 |
| 1067 // The return value is either in r0/r1 or d0. |
| 1068 void Simulator::SetFpResult(const double& result) { |
| 1069 if (FLAG_hardfloat) { |
| 1070 char buffer[2 * sizeof(vfp_register[0])]; |
| 1071 memcpy(buffer, &result, sizeof(buffer)); |
| 1072 // Copy result to d0. |
| 1073 memcpy(vfp_register, buffer, sizeof(buffer)); |
| 1074 } else { |
| 1075 char buffer[2 * sizeof(registers_[0])]; |
| 1076 memcpy(buffer, &result, sizeof(buffer)); |
| 1077 // Copy result to r0 and r1. |
| 1078 memcpy(registers_, buffer, sizeof(buffer)); |
| 1079 } |
| 1080 } |
| 1081 |
| 1082 |
1035 void Simulator::TrashCallerSaveRegisters() { | 1083 void Simulator::TrashCallerSaveRegisters() { |
1036 // We don't trash the registers with the return value. | 1084 // We don't trash the registers with the return value. |
1037 registers_[2] = 0x50Bad4U; | 1085 registers_[2] = 0x50Bad4U; |
1038 registers_[3] = 0x50Bad4U; | 1086 registers_[3] = 0x50Bad4U; |
1039 registers_[12] = 0x50Bad4U; | 1087 registers_[12] = 0x50Bad4U; |
1040 } | 1088 } |
1041 | 1089 |
1042 // Some Operating Systems allow unaligned access on ARMv7 targets. We | 1090 // Some Operating Systems allow unaligned access on ARMv7 targets. We |
1043 // assume that unaligned accesses are not allowed unless the v8 build system | 1091 // assume that unaligned accesses are not allowed unless the v8 build system |
1044 // defines the CAN_USE_UNALIGNED_ACCESSES macro to be non-zero. | 1092 // defines the CAN_USE_UNALIGNED_ACCESSES macro to be non-zero. |
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1678 (get_register(sp) | 1726 (get_register(sp) |
1679 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; | 1727 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; |
1680 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 1728 Redirection* redirection = Redirection::FromSwiInstruction(instr); |
1681 int32_t arg0 = get_register(r0); | 1729 int32_t arg0 = get_register(r0); |
1682 int32_t arg1 = get_register(r1); | 1730 int32_t arg1 = get_register(r1); |
1683 int32_t arg2 = get_register(r2); | 1731 int32_t arg2 = get_register(r2); |
1684 int32_t arg3 = get_register(r3); | 1732 int32_t arg3 = get_register(r3); |
1685 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); | 1733 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); |
1686 int32_t arg4 = stack_pointer[0]; | 1734 int32_t arg4 = stack_pointer[0]; |
1687 int32_t arg5 = stack_pointer[1]; | 1735 int32_t arg5 = stack_pointer[1]; |
| 1736 bool fp_call = |
| 1737 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) || |
| 1738 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) || |
| 1739 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) || |
| 1740 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); |
| 1741 if (FLAG_hardfloat) { |
| 1742 // With the hard floating point calling convention, double |
| 1743 // arguments are passed in VFP registers. Fetch the arguments |
| 1744 // from there and call the builtin using soft floating point |
| 1745 // convention. |
| 1746 switch (redirection->type()) { |
| 1747 case ExternalReference::BUILTIN_FP_FP_CALL: |
| 1748 case ExternalReference::BUILTIN_COMPARE_CALL: |
| 1749 arg0 = vfp_register[0]; |
| 1750 arg1 = vfp_register[1]; |
| 1751 arg2 = vfp_register[2]; |
| 1752 arg3 = vfp_register[3]; |
| 1753 break; |
| 1754 case ExternalReference::BUILTIN_FP_CALL: |
| 1755 arg0 = vfp_register[0]; |
| 1756 arg1 = vfp_register[1]; |
| 1757 break; |
| 1758 case ExternalReference::BUILTIN_FP_INT_CALL: |
| 1759 arg0 = vfp_register[0]; |
| 1760 arg1 = vfp_register[1]; |
| 1761 arg2 = get_register(0); |
| 1762 break; |
| 1763 default: |
| 1764 break; |
| 1765 } |
| 1766 } |
1688 // This is dodgy but it works because the C entry stubs are never moved. | 1767 // This is dodgy but it works because the C entry stubs are never moved. |
1689 // See comment in codegen-arm.cc and bug 1242173. | 1768 // See comment in codegen-arm.cc and bug 1242173. |
1690 int32_t saved_lr = get_register(lr); | 1769 int32_t saved_lr = get_register(lr); |
1691 intptr_t external = | 1770 intptr_t external = |
1692 reinterpret_cast<intptr_t>(redirection->external_function()); | 1771 reinterpret_cast<intptr_t>(redirection->external_function()); |
1693 if (redirection->type() == ExternalReference::FP_RETURN_CALL) { | 1772 if (fp_call) { |
1694 SimulatorRuntimeFPCall target = | 1773 SimulatorRuntimeFPCall target = |
1695 reinterpret_cast<SimulatorRuntimeFPCall>(external); | 1774 reinterpret_cast<SimulatorRuntimeFPCall>(external); |
1696 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1775 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
1697 double x, y; | 1776 double dval0, dval1; |
1698 GetFpArgs(&x, &y); | 1777 int32_t ival; |
1699 PrintF("Call to host function at %p with args %f, %f", | 1778 switch (redirection->type()) { |
1700 FUNCTION_ADDR(target), x, y); | 1779 case ExternalReference::BUILTIN_FP_FP_CALL: |
| 1780 case ExternalReference::BUILTIN_COMPARE_CALL: |
| 1781 GetFpArgs(&dval0, &dval1); |
| 1782 PrintF("Call to host function at %p with args %f, %f", |
| 1783 FUNCTION_ADDR(target), dval0, dval1); |
| 1784 break; |
| 1785 case ExternalReference::BUILTIN_FP_CALL: |
| 1786 GetFpArgs(&dval0); |
| 1787 PrintF("Call to host function at %p with arg %f", |
| 1788 FUNCTION_ADDR(target), dval1); |
| 1789 break; |
| 1790 case ExternalReference::BUILTIN_FP_INT_CALL: |
| 1791 GetFpArgs(&dval0, &ival); |
| 1792 PrintF("Call to host function at %p with args %f, %d", |
| 1793 FUNCTION_ADDR(target), dval0, ival); |
| 1794 break; |
| 1795 default: |
| 1796 UNREACHABLE(); |
| 1797 break; |
| 1798 } |
1701 if (!stack_aligned) { | 1799 if (!stack_aligned) { |
1702 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1800 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
1703 } | 1801 } |
1704 PrintF("\n"); | 1802 PrintF("\n"); |
1705 } | 1803 } |
1706 CHECK(stack_aligned); | 1804 CHECK(stack_aligned); |
1707 double result = target(arg0, arg1, arg2, arg3); | 1805 double result = target(arg0, arg1, arg2, arg3); |
1708 SetFpResult(result); | 1806 if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) { |
| 1807 SetFpResult(result); |
| 1808 } |
1709 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { | 1809 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { |
1710 SimulatorRuntimeDirectApiCall target = | 1810 SimulatorRuntimeDirectApiCall target = |
1711 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); | 1811 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); |
1712 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1812 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
1713 PrintF("Call to host function at %p args %08x", | 1813 PrintF("Call to host function at %p args %08x", |
1714 FUNCTION_ADDR(target), arg0); | 1814 FUNCTION_ADDR(target), arg0); |
1715 if (!stack_aligned) { | 1815 if (!stack_aligned) { |
1716 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1816 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
1717 } | 1817 } |
1718 PrintF("\n"); | 1818 PrintF("\n"); |
(...skipping 1586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3305 uintptr_t address = *stack_slot; | 3405 uintptr_t address = *stack_slot; |
3306 set_register(sp, current_sp + sizeof(uintptr_t)); | 3406 set_register(sp, current_sp + sizeof(uintptr_t)); |
3307 return address; | 3407 return address; |
3308 } | 3408 } |
3309 | 3409 |
3310 } } // namespace v8::internal | 3410 } } // namespace v8::internal |
3311 | 3411 |
3312 #endif // USE_SIMULATOR | 3412 #endif // USE_SIMULATOR |
3313 | 3413 |
3314 #endif // V8_TARGET_ARCH_ARM | 3414 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |