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 | |