| 1 | /* |
| 2 | Copyright (c) 2005-2019 Intel Corporation |
| 3 | |
| 4 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | you may not use this file except in compliance with the License. |
| 6 | You may obtain a copy of the License at |
| 7 | |
| 8 | http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | |
| 10 | Unless required by applicable law or agreed to in writing, software |
| 11 | distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | See the License for the specific language governing permissions and |
| 14 | limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #ifndef __TBB_machine_gcc_ia32_common_H |
| 18 | #define __TBB_machine_gcc_ia32_common_H |
| 19 | |
| 20 | #ifndef __TBB_Log2 |
| 21 | //TODO: Add a higher-level function, e.g. tbb::internal::log2(), into tbb_stddef.h, which |
| 22 | //uses __TBB_Log2 and contains the assert and remove the assert from here and all other |
| 23 | //platform-specific headers. |
| 24 | template <typename T> |
| 25 | static inline intptr_t __TBB_machine_lg( T x ) { |
| 26 | __TBB_ASSERT(x>0, "The logarithm of a non-positive value is undefined." ); |
| 27 | uintptr_t j, i = x; |
| 28 | __asm__("bsr %1,%0" : "=r" (j) : "r" (i)); |
| 29 | return j; |
| 30 | } |
| 31 | #define __TBB_Log2(V) __TBB_machine_lg(V) |
| 32 | #endif /* !__TBB_Log2 */ |
| 33 | |
| 34 | #ifndef __TBB_Pause |
| 35 | //TODO: check if raising a ratio of pause instructions to loop control instructions |
| 36 | //(via e.g. loop unrolling) gives any benefit for HT. E.g, the current implementation |
| 37 | //does about 2 CPU-consuming instructions for every pause instruction. Perhaps for |
| 38 | //high pause counts it should use an unrolled loop to raise the ratio, and thus free |
| 39 | //up more integer cycles for the other hyperthread. On the other hand, if the loop is |
| 40 | //unrolled too far, it won't fit in the core's loop cache, and thus take away |
| 41 | //instruction decode slots from the other hyperthread. |
| 42 | |
| 43 | //TODO: check if use of gcc __builtin_ia32_pause intrinsic gives a "some how" better performing code |
| 44 | static inline void __TBB_machine_pause( int32_t delay ) { |
| 45 | for (int32_t i = 0; i < delay; i++) { |
| 46 | __asm__ __volatile__("pause;" ); |
| 47 | } |
| 48 | return; |
| 49 | } |
| 50 | #define __TBB_Pause(V) __TBB_machine_pause(V) |
| 51 | #endif /* !__TBB_Pause */ |
| 52 | |
| 53 | namespace tbb { namespace internal { typedef uint64_t machine_tsc_t; } } |
| 54 | static inline tbb::internal::machine_tsc_t __TBB_machine_time_stamp() { |
| 55 | #if __INTEL_COMPILER |
| 56 | return _rdtsc(); |
| 57 | #else |
| 58 | tbb::internal::uint32_t hi, lo; |
| 59 | __asm__ __volatile__("rdtsc" : "=d" (hi), "=a" (lo)); |
| 60 | return (tbb::internal::machine_tsc_t( hi ) << 32) | lo; |
| 61 | #endif |
| 62 | } |
| 63 | #define __TBB_time_stamp() __TBB_machine_time_stamp() |
| 64 | |
| 65 | // API to retrieve/update FPU control setting |
| 66 | #ifndef __TBB_CPU_CTL_ENV_PRESENT |
| 67 | #define __TBB_CPU_CTL_ENV_PRESENT 1 |
| 68 | namespace tbb { |
| 69 | namespace internal { |
| 70 | class cpu_ctl_env { |
| 71 | private: |
| 72 | int mxcsr; |
| 73 | short x87cw; |
| 74 | static const int MXCSR_CONTROL_MASK = ~0x3f; /* all except last six status bits */ |
| 75 | public: |
| 76 | bool operator!=( const cpu_ctl_env& ctl ) const { return mxcsr != ctl.mxcsr || x87cw != ctl.x87cw; } |
| 77 | void get_env() { |
| 78 | #if __TBB_ICC_12_0_INL_ASM_FSTCW_BROKEN |
| 79 | cpu_ctl_env loc_ctl; |
| 80 | __asm__ __volatile__ ( |
| 81 | "stmxcsr %0\n\t" |
| 82 | "fstcw %1" |
| 83 | : "=m" (loc_ctl.mxcsr), "=m" (loc_ctl.x87cw) |
| 84 | ); |
| 85 | *this = loc_ctl; |
| 86 | #else |
| 87 | __asm__ __volatile__ ( |
| 88 | "stmxcsr %0\n\t" |
| 89 | "fstcw %1" |
| 90 | : "=m" (mxcsr), "=m" (x87cw) |
| 91 | ); |
| 92 | #endif |
| 93 | mxcsr &= MXCSR_CONTROL_MASK; |
| 94 | } |
| 95 | void set_env() const { |
| 96 | __asm__ __volatile__ ( |
| 97 | "ldmxcsr %0\n\t" |
| 98 | "fldcw %1" |
| 99 | : : "m" (mxcsr), "m" (x87cw) |
| 100 | ); |
| 101 | } |
| 102 | }; |
| 103 | } // namespace internal |
| 104 | } // namespace tbb |
| 105 | #endif /* !__TBB_CPU_CTL_ENV_PRESENT */ |
| 106 | |
| 107 | #include "gcc_itsx.h" |
| 108 | |
| 109 | #endif /* __TBB_machine_gcc_ia32_common_H */ |
| 110 | |