10b57cec5SDimitry Andric /* 20b57cec5SDimitry Andric * z_Windows_NT-586_util.cpp -- platform specific routines. 30b57cec5SDimitry Andric */ 40b57cec5SDimitry Andric 50b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 80b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 90b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "kmp.h" 140b57cec5SDimitry Andric 15fe6060f1SDimitry Andric #if (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64) 160b57cec5SDimitry Andric /* Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to 170b57cec5SDimitry Andric use compare_and_store for these routines */ 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric kmp_int8 __kmp_test_then_or8(volatile kmp_int8 *p, kmp_int8 d) { 200b57cec5SDimitry Andric kmp_int8 old_value, new_value; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric old_value = TCR_1(*p); 230b57cec5SDimitry Andric new_value = old_value | d; 240b57cec5SDimitry Andric 25fe6060f1SDimitry Andric while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) { 260b57cec5SDimitry Andric KMP_CPU_PAUSE(); 270b57cec5SDimitry Andric old_value = TCR_1(*p); 280b57cec5SDimitry Andric new_value = old_value | d; 290b57cec5SDimitry Andric } 300b57cec5SDimitry Andric return old_value; 310b57cec5SDimitry Andric } 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric kmp_int8 __kmp_test_then_and8(volatile kmp_int8 *p, kmp_int8 d) { 340b57cec5SDimitry Andric kmp_int8 old_value, new_value; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric old_value = TCR_1(*p); 370b57cec5SDimitry Andric new_value = old_value & d; 380b57cec5SDimitry Andric 39fe6060f1SDimitry Andric while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) { 400b57cec5SDimitry Andric KMP_CPU_PAUSE(); 410b57cec5SDimitry Andric old_value = TCR_1(*p); 420b57cec5SDimitry Andric new_value = old_value & d; 430b57cec5SDimitry Andric } 440b57cec5SDimitry Andric return old_value; 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric kmp_uint32 __kmp_test_then_or32(volatile kmp_uint32 *p, kmp_uint32 d) { 480b57cec5SDimitry Andric kmp_uint32 old_value, new_value; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric old_value = TCR_4(*p); 510b57cec5SDimitry Andric new_value = old_value | d; 520b57cec5SDimitry Andric 53fe6060f1SDimitry Andric while (!KMP_COMPARE_AND_STORE_REL32((volatile kmp_int32 *)p, old_value, 540b57cec5SDimitry Andric new_value)) { 550b57cec5SDimitry Andric KMP_CPU_PAUSE(); 560b57cec5SDimitry Andric old_value = TCR_4(*p); 570b57cec5SDimitry Andric new_value = old_value | d; 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric return old_value; 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric kmp_uint32 __kmp_test_then_and32(volatile kmp_uint32 *p, kmp_uint32 d) { 630b57cec5SDimitry Andric kmp_uint32 old_value, new_value; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric old_value = TCR_4(*p); 660b57cec5SDimitry Andric new_value = old_value & d; 670b57cec5SDimitry Andric 68fe6060f1SDimitry Andric while (!KMP_COMPARE_AND_STORE_REL32((volatile kmp_int32 *)p, old_value, 690b57cec5SDimitry Andric new_value)) { 700b57cec5SDimitry Andric KMP_CPU_PAUSE(); 710b57cec5SDimitry Andric old_value = TCR_4(*p); 720b57cec5SDimitry Andric new_value = old_value & d; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric return old_value; 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 77fe6060f1SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 780b57cec5SDimitry Andric kmp_int8 __kmp_test_then_add8(volatile kmp_int8 *p, kmp_int8 d) { 790b57cec5SDimitry Andric kmp_int64 old_value, new_value; 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric old_value = TCR_1(*p); 820b57cec5SDimitry Andric new_value = old_value + d; 830b57cec5SDimitry Andric while (!__kmp_compare_and_store8(p, old_value, new_value)) { 840b57cec5SDimitry Andric KMP_CPU_PAUSE(); 850b57cec5SDimitry Andric old_value = TCR_1(*p); 860b57cec5SDimitry Andric new_value = old_value + d; 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric return old_value; 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric #if KMP_ARCH_X86 920b57cec5SDimitry Andric kmp_int64 __kmp_test_then_add64(volatile kmp_int64 *p, kmp_int64 d) { 930b57cec5SDimitry Andric kmp_int64 old_value, new_value; 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric old_value = TCR_8(*p); 960b57cec5SDimitry Andric new_value = old_value + d; 970b57cec5SDimitry Andric while (!__kmp_compare_and_store64(p, old_value, new_value)) { 980b57cec5SDimitry Andric KMP_CPU_PAUSE(); 990b57cec5SDimitry Andric old_value = TCR_8(*p); 1000b57cec5SDimitry Andric new_value = old_value + d; 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric return old_value; 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 */ 105fe6060f1SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric kmp_uint64 __kmp_test_then_or64(volatile kmp_uint64 *p, kmp_uint64 d) { 1080b57cec5SDimitry Andric kmp_uint64 old_value, new_value; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric old_value = TCR_8(*p); 1110b57cec5SDimitry Andric new_value = old_value | d; 112fe6060f1SDimitry Andric while (!KMP_COMPARE_AND_STORE_REL64((volatile kmp_int64 *)p, old_value, 1130b57cec5SDimitry Andric new_value)) { 1140b57cec5SDimitry Andric KMP_CPU_PAUSE(); 1150b57cec5SDimitry Andric old_value = TCR_8(*p); 1160b57cec5SDimitry Andric new_value = old_value | d; 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric return old_value; 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric kmp_uint64 __kmp_test_then_and64(volatile kmp_uint64 *p, kmp_uint64 d) { 1230b57cec5SDimitry Andric kmp_uint64 old_value, new_value; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric old_value = TCR_8(*p); 1260b57cec5SDimitry Andric new_value = old_value & d; 127fe6060f1SDimitry Andric while (!KMP_COMPARE_AND_STORE_REL64((volatile kmp_int64 *)p, old_value, 1280b57cec5SDimitry Andric new_value)) { 1290b57cec5SDimitry Andric KMP_CPU_PAUSE(); 1300b57cec5SDimitry Andric old_value = TCR_8(*p); 1310b57cec5SDimitry Andric new_value = old_value & d; 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric return old_value; 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 137fe6060f1SDimitry Andric #if KMP_ARCH_AARCH64 138fe6060f1SDimitry Andric int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc, 139fe6060f1SDimitry Andric void *p_argv[] 140fe6060f1SDimitry Andric #if OMPT_SUPPORT 141fe6060f1SDimitry Andric , 142fe6060f1SDimitry Andric void **exit_frame_ptr 143fe6060f1SDimitry Andric #endif 144fe6060f1SDimitry Andric ) { 145fe6060f1SDimitry Andric #if OMPT_SUPPORT 146fe6060f1SDimitry Andric *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0); 147fe6060f1SDimitry Andric #endif 148fe6060f1SDimitry Andric 149fe6060f1SDimitry Andric switch (argc) { 150fe6060f1SDimitry Andric case 0: 151fe6060f1SDimitry Andric (*pkfn)(>id, &tid); 152fe6060f1SDimitry Andric break; 153fe6060f1SDimitry Andric case 1: 154fe6060f1SDimitry Andric (*pkfn)(>id, &tid, p_argv[0]); 155fe6060f1SDimitry Andric break; 156fe6060f1SDimitry Andric case 2: 157fe6060f1SDimitry Andric (*pkfn)(>id, &tid, p_argv[0], p_argv[1]); 158fe6060f1SDimitry Andric break; 159fe6060f1SDimitry Andric case 3: 160fe6060f1SDimitry Andric (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2]); 161fe6060f1SDimitry Andric break; 162fe6060f1SDimitry Andric case 4: 163fe6060f1SDimitry Andric (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3]); 164fe6060f1SDimitry Andric break; 165fe6060f1SDimitry Andric case 5: 166fe6060f1SDimitry Andric (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4]); 167fe6060f1SDimitry Andric break; 168fe6060f1SDimitry Andric default: { 169fe6060f1SDimitry Andric // p_argv[6] and onwards must be passed on the stack since 8 registers are 170fe6060f1SDimitry Andric // already used. 171fe6060f1SDimitry Andric size_t len = (argc - 6) * sizeof(void *); 172fe6060f1SDimitry Andric void *argbuf = alloca(len); 173fe6060f1SDimitry Andric memcpy(argbuf, &p_argv[6], len); 174fe6060f1SDimitry Andric } 175fe6060f1SDimitry Andric [[fallthrough]]; 176fe6060f1SDimitry Andric case 6: 177fe6060f1SDimitry Andric (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], 178fe6060f1SDimitry Andric p_argv[5]); 179fe6060f1SDimitry Andric break; 180fe6060f1SDimitry Andric } 181fe6060f1SDimitry Andric 182fe6060f1SDimitry Andric #if OMPT_SUPPORT 183fe6060f1SDimitry Andric *exit_frame_ptr = 0; 184fe6060f1SDimitry Andric #endif 185fe6060f1SDimitry Andric 186fe6060f1SDimitry Andric return 1; 187fe6060f1SDimitry Andric } 188fe6060f1SDimitry Andric #endif 189fe6060f1SDimitry Andric 190fe6060f1SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 */ 191