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 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 double dm_val = 0.0; | 905 double dm_val = 0.0; |
906 // Read the bits from the unsigned integer register_[] array | 906 // Read the bits from the unsigned integer register_[] array |
907 // into the double precision floating point value and return it. | 907 // into the double precision floating point value and return it. |
908 char buffer[2 * sizeof(vfp_registers_[0])]; | 908 char buffer[2 * sizeof(vfp_registers_[0])]; |
909 OS::MemCopy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); | 909 OS::MemCopy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); |
910 OS::MemCopy(&dm_val, buffer, 2 * sizeof(registers_[0])); | 910 OS::MemCopy(&dm_val, buffer, 2 * sizeof(registers_[0])); |
911 return(dm_val); | 911 return(dm_val); |
912 } | 912 } |
913 | 913 |
914 | 914 |
| 915 void Simulator::set_register_pair_from_double(int reg, double* value) { |
| 916 ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0)); |
| 917 memcpy(registers_ + reg, value, sizeof(*value)); |
| 918 } |
| 919 |
| 920 |
915 void Simulator::set_dw_register(int dreg, const int* dbl) { | 921 void Simulator::set_dw_register(int dreg, const int* dbl) { |
916 ASSERT((dreg >= 0) && (dreg < num_d_registers)); | 922 ASSERT((dreg >= 0) && (dreg < num_d_registers)); |
917 registers_[dreg] = dbl[0]; | 923 registers_[dreg] = dbl[0]; |
918 registers_[dreg + 1] = dbl[1]; | 924 registers_[dreg + 1] = dbl[1]; |
919 } | 925 } |
920 | 926 |
921 | 927 |
922 void Simulator::get_d_register(int dreg, uint64_t* value) { | 928 void Simulator::get_d_register(int dreg, uint64_t* value) { |
923 ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); | 929 ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); |
924 memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value)); | 930 memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value)); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1019 | 1025 |
1020 ReturnType value = 0; | 1026 ReturnType value = 0; |
1021 char buffer[register_size * sizeof(vfp_registers_[0])]; | 1027 char buffer[register_size * sizeof(vfp_registers_[0])]; |
1022 OS::MemCopy(buffer, &vfp_registers_[register_size * reg_index], | 1028 OS::MemCopy(buffer, &vfp_registers_[register_size * reg_index], |
1023 register_size * sizeof(vfp_registers_[0])); | 1029 register_size * sizeof(vfp_registers_[0])); |
1024 OS::MemCopy(&value, buffer, register_size * sizeof(vfp_registers_[0])); | 1030 OS::MemCopy(&value, buffer, register_size * sizeof(vfp_registers_[0])); |
1025 return value; | 1031 return value; |
1026 } | 1032 } |
1027 | 1033 |
1028 | 1034 |
1029 // Runtime FP routines take up to two double arguments and zero | 1035 // Runtime FP routines take: |
1030 // or one integer arguments. All are consructed here. | 1036 // - two double arguments |
1031 // from r0-r3 or d0 and d1. | 1037 // - one double argument and zero or one integer arguments. |
| 1038 // All are consructed here from r0-r3 or d0, d1 and r0. |
1032 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { | 1039 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { |
1033 if (use_eabi_hardfloat()) { | 1040 if (use_eabi_hardfloat()) { |
1034 *x = vfp_registers_[0]; | 1041 *x = get_double_from_d_register(0); |
1035 *y = vfp_registers_[1]; | 1042 *y = get_double_from_d_register(1); |
1036 *z = registers_[1]; | 1043 *z = get_register(0); |
1037 } else { | 1044 } else { |
1038 // We use a char buffer to get around the strict-aliasing rules which | |
1039 // otherwise allow the compiler to optimize away the copy. | |
1040 char buffer[sizeof(*x)]; | |
1041 // Registers 0 and 1 -> x. | 1045 // Registers 0 and 1 -> x. |
1042 OS::MemCopy(buffer, registers_, sizeof(*x)); | 1046 *x = get_double_from_register_pair(0); |
1043 OS::MemCopy(x, buffer, sizeof(*x)); | |
1044 // Register 2 and 3 -> y. | 1047 // Register 2 and 3 -> y. |
1045 OS::MemCopy(buffer, registers_ + 2, sizeof(*y)); | 1048 *y = get_double_from_register_pair(2); |
1046 OS::MemCopy(y, buffer, sizeof(*y)); | |
1047 // Register 2 -> z | 1049 // Register 2 -> z |
1048 memcpy(buffer, registers_ + 2, sizeof(*z)); | 1050 *z = get_register(2); |
1049 memcpy(z, buffer, sizeof(*z)); | |
1050 } | 1051 } |
1051 } | 1052 } |
1052 | 1053 |
1053 | 1054 |
1054 // The return value is either in r0/r1 or d0. | 1055 // The return value is either in r0/r1 or d0. |
1055 void Simulator::SetFpResult(const double& result) { | 1056 void Simulator::SetFpResult(const double& result) { |
1056 if (use_eabi_hardfloat()) { | 1057 if (use_eabi_hardfloat()) { |
1057 char buffer[2 * sizeof(vfp_registers_[0])]; | 1058 char buffer[2 * sizeof(vfp_registers_[0])]; |
1058 OS::MemCopy(buffer, &result, sizeof(buffer)); | 1059 OS::MemCopy(buffer, &result, sizeof(buffer)); |
1059 // Copy result to d0. | 1060 // Copy result to d0. |
(...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1711 int32_t arg2 = get_register(r2); | 1712 int32_t arg2 = get_register(r2); |
1712 int32_t arg3 = get_register(r3); | 1713 int32_t arg3 = get_register(r3); |
1713 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); | 1714 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); |
1714 int32_t arg4 = stack_pointer[0]; | 1715 int32_t arg4 = stack_pointer[0]; |
1715 int32_t arg5 = stack_pointer[1]; | 1716 int32_t arg5 = stack_pointer[1]; |
1716 bool fp_call = | 1717 bool fp_call = |
1717 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) || | 1718 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) || |
1718 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) || | 1719 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) || |
1719 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) || | 1720 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) || |
1720 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); | 1721 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); |
1721 if (use_eabi_hardfloat()) { | |
1722 // With the hard floating point calling convention, double | |
1723 // arguments are passed in VFP registers. Fetch the arguments | |
1724 // from there and call the builtin using soft floating point | |
1725 // convention. | |
1726 switch (redirection->type()) { | |
1727 case ExternalReference::BUILTIN_FP_FP_CALL: | |
1728 case ExternalReference::BUILTIN_COMPARE_CALL: | |
1729 arg0 = vfp_registers_[0]; | |
1730 arg1 = vfp_registers_[1]; | |
1731 arg2 = vfp_registers_[2]; | |
1732 arg3 = vfp_registers_[3]; | |
1733 break; | |
1734 case ExternalReference::BUILTIN_FP_CALL: | |
1735 arg0 = vfp_registers_[0]; | |
1736 arg1 = vfp_registers_[1]; | |
1737 break; | |
1738 case ExternalReference::BUILTIN_FP_INT_CALL: | |
1739 arg0 = vfp_registers_[0]; | |
1740 arg1 = vfp_registers_[1]; | |
1741 arg2 = get_register(0); | |
1742 break; | |
1743 default: | |
1744 break; | |
1745 } | |
1746 } | |
1747 // This is dodgy but it works because the C entry stubs are never moved. | 1722 // This is dodgy but it works because the C entry stubs are never moved. |
1748 // See comment in codegen-arm.cc and bug 1242173. | 1723 // See comment in codegen-arm.cc and bug 1242173. |
1749 int32_t saved_lr = get_register(lr); | 1724 int32_t saved_lr = get_register(lr); |
1750 intptr_t external = | 1725 intptr_t external = |
1751 reinterpret_cast<intptr_t>(redirection->external_function()); | 1726 reinterpret_cast<intptr_t>(redirection->external_function()); |
1752 if (fp_call) { | 1727 if (fp_call) { |
1753 double dval0, dval1; // one or two double parameters | 1728 double dval0, dval1; // one or two double parameters |
1754 int32_t ival; // zero or one integer parameters | 1729 int32_t ival; // zero or one integer parameters |
1755 int64_t iresult = 0; // integer return value | 1730 int64_t iresult = 0; // integer return value |
1756 double dresult = 0; // double return value | 1731 double dresult = 0; // double return value |
(...skipping 2052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3809 | 3784 |
3810 // Pop stack passed arguments. | 3785 // Pop stack passed arguments. |
3811 CHECK_EQ(entry_stack, get_register(sp)); | 3786 CHECK_EQ(entry_stack, get_register(sp)); |
3812 set_register(sp, original_stack); | 3787 set_register(sp, original_stack); |
3813 | 3788 |
3814 int32_t result = get_register(r0); | 3789 int32_t result = get_register(r0); |
3815 return result; | 3790 return result; |
3816 } | 3791 } |
3817 | 3792 |
3818 | 3793 |
3819 double Simulator::CallFP(byte* entry, double d0, double d1) { | 3794 void Simulator::CallFP(byte* entry, double d0, double d1) { |
3820 if (use_eabi_hardfloat()) { | 3795 if (use_eabi_hardfloat()) { |
3821 set_d_register_from_double(0, d0); | 3796 set_d_register_from_double(0, d0); |
3822 set_d_register_from_double(1, d1); | 3797 set_d_register_from_double(1, d1); |
3823 } else { | 3798 } else { |
3824 int buffer[2]; | 3799 set_register_pair_from_double(0, &d0); |
3825 ASSERT(sizeof(buffer[0]) * 2 == sizeof(d0)); | 3800 set_register_pair_from_double(2, &d1); |
3826 OS::MemCopy(buffer, &d0, sizeof(d0)); | |
3827 set_dw_register(0, buffer); | |
3828 OS::MemCopy(buffer, &d1, sizeof(d1)); | |
3829 set_dw_register(2, buffer); | |
3830 } | 3801 } |
3831 CallInternal(entry); | 3802 CallInternal(entry); |
| 3803 } |
| 3804 |
| 3805 |
| 3806 int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) { |
| 3807 CallFP(entry, d0, d1); |
| 3808 int32_t result = get_register(r0); |
| 3809 return result; |
| 3810 } |
| 3811 |
| 3812 |
| 3813 double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) { |
| 3814 CallFP(entry, d0, d1); |
3832 if (use_eabi_hardfloat()) { | 3815 if (use_eabi_hardfloat()) { |
3833 return get_double_from_d_register(0); | 3816 return get_double_from_d_register(0); |
3834 } else { | 3817 } else { |
3835 return get_double_from_register_pair(0); | 3818 return get_double_from_register_pair(0); |
3836 } | 3819 } |
3837 } | 3820 } |
3838 | 3821 |
3839 | 3822 |
3840 uintptr_t Simulator::PushAddress(uintptr_t address) { | 3823 uintptr_t Simulator::PushAddress(uintptr_t address) { |
3841 int new_sp = get_register(sp) - sizeof(uintptr_t); | 3824 int new_sp = get_register(sp) - sizeof(uintptr_t); |
(...skipping 10 matching lines...) Expand all Loading... |
3852 uintptr_t address = *stack_slot; | 3835 uintptr_t address = *stack_slot; |
3853 set_register(sp, current_sp + sizeof(uintptr_t)); | 3836 set_register(sp, current_sp + sizeof(uintptr_t)); |
3854 return address; | 3837 return address; |
3855 } | 3838 } |
3856 | 3839 |
3857 } } // namespace v8::internal | 3840 } } // namespace v8::internal |
3858 | 3841 |
3859 #endif // USE_SIMULATOR | 3842 #endif // USE_SIMULATOR |
3860 | 3843 |
3861 #endif // V8_TARGET_ARCH_ARM | 3844 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |