1 | /* |
2 | * z_Windows_NT-586_util.cpp -- platform specific routines. |
3 | */ |
4 | |
5 | //===----------------------------------------------------------------------===// |
6 | // |
7 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
8 | // See https://llvm.org/LICENSE.txt for license information. |
9 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "kmp.h" |
14 | |
15 | #if (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_ARM) |
16 | /* Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to |
17 | use compare_and_store for these routines */ |
18 | |
19 | kmp_int8 __kmp_test_then_or8(volatile kmp_int8 *p, kmp_int8 d) { |
20 | kmp_int8 old_value, new_value; |
21 | |
22 | old_value = TCR_1(*p); |
23 | new_value = old_value | d; |
24 | |
25 | while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) { |
26 | KMP_CPU_PAUSE(); |
27 | old_value = TCR_1(*p); |
28 | new_value = old_value | d; |
29 | } |
30 | return old_value; |
31 | } |
32 | |
33 | kmp_int8 __kmp_test_then_and8(volatile kmp_int8 *p, kmp_int8 d) { |
34 | kmp_int8 old_value, new_value; |
35 | |
36 | old_value = TCR_1(*p); |
37 | new_value = old_value & d; |
38 | |
39 | while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) { |
40 | KMP_CPU_PAUSE(); |
41 | old_value = TCR_1(*p); |
42 | new_value = old_value & d; |
43 | } |
44 | return old_value; |
45 | } |
46 | |
47 | kmp_uint32 __kmp_test_then_or32(volatile kmp_uint32 *p, kmp_uint32 d) { |
48 | kmp_uint32 old_value, new_value; |
49 | |
50 | old_value = TCR_4(*p); |
51 | new_value = old_value | d; |
52 | |
53 | while (!KMP_COMPARE_AND_STORE_REL32((volatile kmp_int32 *)p, old_value, |
54 | new_value)) { |
55 | KMP_CPU_PAUSE(); |
56 | old_value = TCR_4(*p); |
57 | new_value = old_value | d; |
58 | } |
59 | return old_value; |
60 | } |
61 | |
62 | kmp_uint32 __kmp_test_then_and32(volatile kmp_uint32 *p, kmp_uint32 d) { |
63 | kmp_uint32 old_value, new_value; |
64 | |
65 | old_value = TCR_4(*p); |
66 | new_value = old_value & d; |
67 | |
68 | while (!KMP_COMPARE_AND_STORE_REL32((volatile kmp_int32 *)p, old_value, |
69 | new_value)) { |
70 | KMP_CPU_PAUSE(); |
71 | old_value = TCR_4(*p); |
72 | new_value = old_value & d; |
73 | } |
74 | return old_value; |
75 | } |
76 | |
77 | #if KMP_ARCH_X86 || KMP_ARCH_X86_64 |
78 | kmp_int8 __kmp_test_then_add8(volatile kmp_int8 *p, kmp_int8 d) { |
79 | kmp_int64 old_value, new_value; |
80 | |
81 | old_value = TCR_1(*p); |
82 | new_value = old_value + d; |
83 | while (!__kmp_compare_and_store8(p, old_value, new_value)) { |
84 | KMP_CPU_PAUSE(); |
85 | old_value = TCR_1(*p); |
86 | new_value = old_value + d; |
87 | } |
88 | return old_value; |
89 | } |
90 | |
91 | #if KMP_ARCH_X86 |
92 | kmp_int64 __kmp_test_then_add64(volatile kmp_int64 *p, kmp_int64 d) { |
93 | kmp_int64 old_value, new_value; |
94 | |
95 | old_value = TCR_8(*p); |
96 | new_value = old_value + d; |
97 | while (!__kmp_compare_and_store64(p, old_value, new_value)) { |
98 | KMP_CPU_PAUSE(); |
99 | old_value = TCR_8(*p); |
100 | new_value = old_value + d; |
101 | } |
102 | return old_value; |
103 | } |
104 | #endif /* KMP_ARCH_X86 */ |
105 | #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ |
106 | |
107 | kmp_uint64 __kmp_test_then_or64(volatile kmp_uint64 *p, kmp_uint64 d) { |
108 | kmp_uint64 old_value, new_value; |
109 | |
110 | old_value = TCR_8(*p); |
111 | new_value = old_value | d; |
112 | while (!KMP_COMPARE_AND_STORE_REL64((volatile kmp_int64 *)p, old_value, |
113 | new_value)) { |
114 | KMP_CPU_PAUSE(); |
115 | old_value = TCR_8(*p); |
116 | new_value = old_value | d; |
117 | } |
118 | |
119 | return old_value; |
120 | } |
121 | |
122 | kmp_uint64 __kmp_test_then_and64(volatile kmp_uint64 *p, kmp_uint64 d) { |
123 | kmp_uint64 old_value, new_value; |
124 | |
125 | old_value = TCR_8(*p); |
126 | new_value = old_value & d; |
127 | while (!KMP_COMPARE_AND_STORE_REL64((volatile kmp_int64 *)p, old_value, |
128 | new_value)) { |
129 | KMP_CPU_PAUSE(); |
130 | old_value = TCR_8(*p); |
131 | new_value = old_value & d; |
132 | } |
133 | |
134 | return old_value; |
135 | } |
136 | |
137 | #if KMP_ARCH_AARCH64 && KMP_COMPILER_MSVC |
138 | // For !KMP_COMPILER_MSVC, this function is provided in assembly form |
139 | // by z_Linux_asm.S. |
140 | int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc, |
141 | void *p_argv[] |
142 | #if OMPT_SUPPORT |
143 | , |
144 | void **exit_frame_ptr |
145 | #endif |
146 | ) { |
147 | #if OMPT_SUPPORT |
148 | *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0); |
149 | #endif |
150 | |
151 | switch (argc) { |
152 | case 0: |
153 | (*pkfn)(>id, &tid); |
154 | break; |
155 | case 1: |
156 | (*pkfn)(>id, &tid, p_argv[0]); |
157 | break; |
158 | case 2: |
159 | (*pkfn)(>id, &tid, p_argv[0], p_argv[1]); |
160 | break; |
161 | case 3: |
162 | (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2]); |
163 | break; |
164 | case 4: |
165 | (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3]); |
166 | break; |
167 | case 5: |
168 | (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4]); |
169 | break; |
170 | default: { |
171 | // p_argv[6] and onwards must be passed on the stack since 8 registers are |
172 | // already used. |
173 | size_t len = (argc - 6) * sizeof(void *); |
174 | void *argbuf = alloca(len); |
175 | memcpy(argbuf, &p_argv[6], len); |
176 | } |
177 | [[fallthrough]]; |
178 | case 6: |
179 | (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], |
180 | p_argv[5]); |
181 | break; |
182 | } |
183 | |
184 | #if OMPT_SUPPORT |
185 | *exit_frame_ptr = 0; |
186 | #endif |
187 | |
188 | return 1; |
189 | } |
190 | #endif |
191 | |
192 | #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_ARM */ |
193 | |