1 ; z_Windows_NT-586_asm.asm: - microtasking routines specifically
2 ; written for IA-32 architecture and Intel(R) 64 running Windows* OS
5 ;//===----------------------------------------------------------------------===//
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
11 ;//===----------------------------------------------------------------------===//
14 TITLE z_Windows_NT-586_asm.asm
16 ; ============================= IA-32 architecture ==========================
24 _TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
26 _DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
28 CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
30 _BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
32 $$SYMBOLS SEGMENT BYTE USE32 'DEBSYM'
34 $$TYPES SEGMENT BYTE USE32 'DEBTYP'
36 _TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
38 FLAT GROUP _DATA, CONST, _BSS
39 ASSUME CS: FLAT, DS: FLAT, SS: FLAT
43 ;------------------------------------------------------------------------
44 ; FUNCTION ___kmp_x86_pause
47 ; __kmp_x86_pause( void )
48 PUBLIC ___kmp_x86_pause
53 ___kmp_x86_pause PROC NEAR
62 ;------------------------------------------------------------------------
63 ; FUNCTION ___kmp_x86_cpuid
66 ; __kmp_x86_cpuid( int mode, int mode2, struct kmp_cpuid *p );
67 PUBLIC ___kmp_x86_cpuid
78 ___kmp_x86_cpuid PROC NEAR
88 mov eax, DWORD PTR _mode$[ebp]
89 mov ecx, DWORD PTR _mode2$[ebp]
90 cpuid ; Query the CPUID for the current processor
92 mov edi, DWORD PTR _p$[ebp]
93 mov DWORD PTR _eax$[ edi ], eax
94 mov DWORD PTR _ebx$[ edi ], ebx
95 mov DWORD PTR _ecx$[ edi ], ecx
96 mov DWORD PTR _edx$[ edi ], edx
107 ___kmp_x86_cpuid ENDP
110 ;------------------------------------------------------------------------
111 ; FUNCTION ___kmp_test_then_add32
114 ; __kmp_test_then_add32( volatile kmp_int32 *p, kmp_int32 d );
115 PUBLIC ___kmp_test_then_add32
120 ___kmp_test_then_add32 PROC NEAR
122 mov eax, DWORD PTR _d$[esp]
123 mov ecx, DWORD PTR _p$[esp]
124 lock xadd DWORD PTR [ecx], eax
127 ___kmp_test_then_add32 ENDP
130 ;------------------------------------------------------------------------
131 ; FUNCTION ___kmp_compare_and_store8
134 ; __kmp_compare_and_store8( volatile kmp_int8 *p, kmp_int8 cv, kmp_int8 sv );
135 PUBLIC ___kmp_compare_and_store8
142 ___kmp_compare_and_store8 PROC NEAR
144 mov ecx, DWORD PTR _p$[esp]
145 mov al, BYTE PTR _cv$[esp]
146 mov dl, BYTE PTR _sv$[esp]
147 lock cmpxchg BYTE PTR [ecx], dl
148 sete al ; if al == [ecx] set al = 1 else set al = 0
149 and eax, 1 ; sign extend previous instruction
152 ___kmp_compare_and_store8 ENDP
155 ;------------------------------------------------------------------------
156 ; FUNCTION ___kmp_compare_and_store16
159 ; __kmp_compare_and_store16( volatile kmp_int16 *p, kmp_int16 cv, kmp_int16 sv );
160 PUBLIC ___kmp_compare_and_store16
167 ___kmp_compare_and_store16 PROC NEAR
169 mov ecx, DWORD PTR _p$[esp]
170 mov ax, WORD PTR _cv$[esp]
171 mov dx, WORD PTR _sv$[esp]
172 lock cmpxchg WORD PTR [ecx], dx
173 sete al ; if ax == [ecx] set al = 1 else set al = 0
174 and eax, 1 ; sign extend previous instruction
177 ___kmp_compare_and_store16 ENDP
180 ;------------------------------------------------------------------------
181 ; FUNCTION ___kmp_compare_and_store32
184 ; __kmp_compare_and_store32( volatile kmp_int32 *p, kmp_int32 cv, kmp_int32 sv );
185 PUBLIC ___kmp_compare_and_store32
192 ___kmp_compare_and_store32 PROC NEAR
194 mov ecx, DWORD PTR _p$[esp]
195 mov eax, DWORD PTR _cv$[esp]
196 mov edx, DWORD PTR _sv$[esp]
197 lock cmpxchg DWORD PTR [ecx], edx
198 sete al ; if eax == [ecx] set al = 1 else set al = 0
199 and eax, 1 ; sign extend previous instruction
202 ___kmp_compare_and_store32 ENDP
205 ;------------------------------------------------------------------------
206 ; FUNCTION ___kmp_compare_and_store64
209 ; __kmp_compare_and_store64( volatile kmp_int64 *p, kmp_int64 cv, kmp_int64 sv );
210 PUBLIC ___kmp_compare_and_store64
219 ___kmp_compare_and_store64 PROC NEAR
225 mov edi, DWORD PTR _p$[ebp]
226 mov eax, DWORD PTR _cv_low$[ebp]
227 mov edx, DWORD PTR _cv_high$[ebp]
228 mov ebx, DWORD PTR _sv_low$[ebp]
229 mov ecx, DWORD PTR _sv_high$[ebp]
230 lock cmpxchg8b QWORD PTR [edi]
231 sete al ; if edx:eax == [edi] set al = 1 else set al = 0
232 and eax, 1 ; sign extend previous instruction
239 ___kmp_compare_and_store64 ENDP
242 ;------------------------------------------------------------------------
243 ; FUNCTION ___kmp_xchg_fixed8
246 ; __kmp_xchg_fixed8( volatile kmp_int8 *p, kmp_int8 d );
247 PUBLIC ___kmp_xchg_fixed8
253 ___kmp_xchg_fixed8 PROC NEAR
255 mov ecx, DWORD PTR _p$[esp]
256 mov al, BYTE PTR _d$[esp]
257 lock xchg BYTE PTR [ecx], al
260 ___kmp_xchg_fixed8 ENDP
263 ;------------------------------------------------------------------------
264 ; FUNCTION ___kmp_xchg_fixed16
267 ; __kmp_xchg_fixed16( volatile kmp_int16 *p, kmp_int16 d );
268 PUBLIC ___kmp_xchg_fixed16
274 ___kmp_xchg_fixed16 PROC NEAR
276 mov ecx, DWORD PTR _p$[esp]
277 mov ax, WORD PTR _d$[esp]
278 lock xchg WORD PTR [ecx], ax
281 ___kmp_xchg_fixed16 ENDP
284 ;------------------------------------------------------------------------
285 ; FUNCTION ___kmp_xchg_fixed32
288 ; __kmp_xchg_fixed32( volatile kmp_int32 *p, kmp_int32 d );
289 PUBLIC ___kmp_xchg_fixed32
295 ___kmp_xchg_fixed32 PROC NEAR
297 mov ecx, DWORD PTR _p$[esp]
298 mov eax, DWORD PTR _d$[esp]
299 lock xchg DWORD PTR [ecx], eax
302 ___kmp_xchg_fixed32 ENDP
306 ;------------------------------------------------------------------------
307 ; FUNCTION ___kmp_xchg_real32
310 ; __kmp_xchg_real32( volatile kmp_real32 *p, kmp_real32 d );
311 PUBLIC ___kmp_xchg_real32
318 ___kmp_xchg_real32 PROC NEAR
324 mov esi, DWORD PTR _p$[ebp]
328 fst DWORD PTR _old_value$[ebp]
329 ;; store into old_value
331 mov eax, DWORD PTR _d$[ebp]
333 lock xchg DWORD PTR [esi], eax
335 fld DWORD PTR _old_value$[ebp]
342 ___kmp_xchg_real32 ENDP
346 ;------------------------------------------------------------------------
347 ; FUNCTION ___kmp_compare_and_store_ret8
350 ; __kmp_compare_and_store_ret8( volatile kmp_int8 *p, kmp_int8 cv, kmp_int8 sv );
351 PUBLIC ___kmp_compare_and_store_ret8
358 ___kmp_compare_and_store_ret8 PROC NEAR
360 mov ecx, DWORD PTR _p$[esp]
361 mov al, BYTE PTR _cv$[esp]
362 mov dl, BYTE PTR _sv$[esp]
363 lock cmpxchg BYTE PTR [ecx], dl
366 ___kmp_compare_and_store_ret8 ENDP
369 ;------------------------------------------------------------------------
370 ; FUNCTION ___kmp_compare_and_store_ret16
373 ; __kmp_compare_and_store_ret16( volatile kmp_int16 *p, kmp_int16 cv, kmp_int16 sv );
374 PUBLIC ___kmp_compare_and_store_ret16
381 ___kmp_compare_and_store_ret16 PROC NEAR
383 mov ecx, DWORD PTR _p$[esp]
384 mov ax, WORD PTR _cv$[esp]
385 mov dx, WORD PTR _sv$[esp]
386 lock cmpxchg WORD PTR [ecx], dx
389 ___kmp_compare_and_store_ret16 ENDP
392 ;------------------------------------------------------------------------
393 ; FUNCTION ___kmp_compare_and_store_ret32
396 ; __kmp_compare_and_store_ret32( volatile kmp_int32 *p, kmp_int32 cv, kmp_int32 sv );
397 PUBLIC ___kmp_compare_and_store_ret32
404 ___kmp_compare_and_store_ret32 PROC NEAR
406 mov ecx, DWORD PTR _p$[esp]
407 mov eax, DWORD PTR _cv$[esp]
408 mov edx, DWORD PTR _sv$[esp]
409 lock cmpxchg DWORD PTR [ecx], edx
412 ___kmp_compare_and_store_ret32 ENDP
415 ;------------------------------------------------------------------------
416 ; FUNCTION ___kmp_compare_and_store_ret64
419 ; __kmp_compare_and_store_ret64( volatile kmp_int64 *p, kmp_int64 cv, kmp_int64 sv );
420 PUBLIC ___kmp_compare_and_store_ret64
429 ___kmp_compare_and_store_ret64 PROC NEAR
435 mov edi, DWORD PTR _p$[ebp]
436 mov eax, DWORD PTR _cv_low$[ebp]
437 mov edx, DWORD PTR _cv_high$[ebp]
438 mov ebx, DWORD PTR _sv_low$[ebp]
439 mov ecx, DWORD PTR _sv_high$[ebp]
440 lock cmpxchg8b QWORD PTR [edi]
447 ___kmp_compare_and_store_ret64 ENDP
450 ;------------------------------------------------------------------------
451 ; FUNCTION ___kmp_load_x87_fpu_control_word
454 ; __kmp_load_x87_fpu_control_word( kmp_int16 *p );
458 PUBLIC ___kmp_load_x87_fpu_control_word
463 ___kmp_load_x87_fpu_control_word PROC NEAR
465 mov eax, DWORD PTR _p$[esp]
469 ___kmp_load_x87_fpu_control_word ENDP
472 ;------------------------------------------------------------------------
473 ; FUNCTION ___kmp_store_x87_fpu_control_word
476 ; __kmp_store_x87_fpu_control_word( kmp_int16 *p );
480 PUBLIC ___kmp_store_x87_fpu_control_word
485 ___kmp_store_x87_fpu_control_word PROC NEAR
487 mov eax, DWORD PTR _p$[esp]
491 ___kmp_store_x87_fpu_control_word ENDP
494 ;------------------------------------------------------------------------
495 ; FUNCTION ___kmp_clear_x87_fpu_status_word
498 ; __kmp_clear_x87_fpu_status_word();
499 PUBLIC ___kmp_clear_x87_fpu_status_word
503 ___kmp_clear_x87_fpu_status_word PROC NEAR
508 ___kmp_clear_x87_fpu_status_word ENDP
512 ;------------------------------------------------------------------------
513 ; FUNCTION ___kmp_invoke_microtask
515 ; typedef void (*microtask_t)( int *gtid, int *tid, ... );
518 ; __kmp_invoke_microtask( microtask_t pkfn,
520 ; int argc, void *p_argv[] )
521 PUBLIC ___kmp_invoke_microtask
537 ___kmp_invoke_microtask PROC NEAR
541 sub esp, 16 ; 00000010H
546 mov eax, DWORD PTR _exit_frame$[ebp]
547 mov DWORD PTR [eax], ebp
550 mov eax, DWORD PTR _argc$[ebp]
551 mov DWORD PTR _i$[ebp], eax
553 ;; ------------------------------------------------------------
554 lea edx, DWORD PTR [eax*4+8]
555 mov ecx, esp ; Save current SP into ECX
556 mov eax,edx ; Save the size of the args in eax
557 sub ecx,edx ; esp-((#args+2)*4) -> ecx -- without mods, stack ptr would be this
558 mov edx,ecx ; Save to edx
559 and ecx,-128 ; Mask off 7 bits
560 sub edx,ecx ; Amount to subtract from esp
561 sub esp,edx ; Prepare stack ptr-- Now it will be aligned on 128-byte boundary at the call
563 add edx,eax ; Calculate total size of the stack decrement.
564 mov DWORD PTR _stk_adj$[ebp], edx
565 ;; ------------------------------------------------------------
569 mov ecx, DWORD PTR _i$[ebp]
571 mov DWORD PTR _i$[ebp], ecx
573 cmp DWORD PTR _i$[ebp], 0
576 mov edx, DWORD PTR _i$[ebp]
577 mov eax, DWORD PTR _argv$[ebp]
578 mov ecx, DWORD PTR [eax+edx*4-4]
579 mov DWORD PTR _vptr$[ebp], ecx
581 mov eax, DWORD PTR _vptr$[ebp]
588 lea edx, DWORD PTR _tid$[ebp]
589 mov DWORD PTR _vptr$[ebp], edx
591 lea eax, DWORD PTR _gtid$[ebp]
592 mov DWORD PTR _qptr$[ebp], eax
594 mov eax, DWORD PTR _vptr$[ebp]
598 mov eax, DWORD PTR _qptr$[ebp]
602 call DWORD PTR _pkfn$[ebp]
604 add esp, DWORD PTR _stk_adj$[ebp]
614 ___kmp_invoke_microtask ENDP
619 ; ==================================== Intel(R) 64 ===================================
623 ;------------------------------------------------------------------------
624 ; FUNCTION __kmp_x86_cpuid
627 ; __kmp_x86_cpuid( int mode, int mode2, struct kmp_cpuid *p );
633 PUBLIC __kmp_x86_cpuid
637 __kmp_x86_cpuid PROC FRAME ;NEAR
643 push rbx ; callee-save register
647 mov r10, r8 ; p parameter
648 mov eax, ecx ; mode parameter
649 mov ecx, edx ; mode2 parameter
650 cpuid ; Query the CPUID for the current processor
652 mov DWORD PTR 0[ r10 ], eax ; store results into buffer
653 mov DWORD PTR 4[ r10 ], ebx
654 mov DWORD PTR 8[ r10 ], ecx
655 mov DWORD PTR 12[ r10 ], edx
657 pop rbx ; callee-save register
666 ;------------------------------------------------------------------------
667 ; FUNCTION __kmp_test_then_add32
670 ; __kmp_test_then_add32( volatile kmp_int32 *p, kmp_int32 d );
677 PUBLIC __kmp_test_then_add32
680 __kmp_test_then_add32 PROC ;NEAR
683 lock xadd DWORD PTR [rcx], eax
686 __kmp_test_then_add32 ENDP
690 ;------------------------------------------------------------------------
691 ; FUNCTION __kmp_test_then_add64
694 ; __kmp_test_then_add64( volatile kmp_int64 *p, kmp_int64 d );
701 PUBLIC __kmp_test_then_add64
704 __kmp_test_then_add64 PROC ;NEAR
707 lock xadd QWORD PTR [rcx], rax
710 __kmp_test_then_add64 ENDP
714 ;------------------------------------------------------------------------
715 ; FUNCTION __kmp_compare_and_store8
718 ; __kmp_compare_and_store8( volatile kmp_int8 *p, kmp_int8 cv, kmp_int8 sv );
725 PUBLIC __kmp_compare_and_store8
729 __kmp_compare_and_store8 PROC ;NEAR
733 lock cmpxchg BYTE PTR [rcx], dl
734 sete al ; if al == [rcx] set al = 1 else set al = 0
735 and rax, 1 ; sign extend previous instruction
738 __kmp_compare_and_store8 ENDP
742 ;------------------------------------------------------------------------
743 ; FUNCTION __kmp_compare_and_store16
746 ; __kmp_compare_and_store16( volatile kmp_int16 *p, kmp_int16 cv, kmp_int16 sv );
753 PUBLIC __kmp_compare_and_store16
757 __kmp_compare_and_store16 PROC ;NEAR
761 lock cmpxchg WORD PTR [rcx], dx
762 sete al ; if ax == [rcx] set al = 1 else set al = 0
763 and rax, 1 ; sign extend previous instruction
766 __kmp_compare_and_store16 ENDP
770 ;------------------------------------------------------------------------
771 ; FUNCTION __kmp_compare_and_store32
774 ; __kmp_compare_and_store32( volatile kmp_int32 *p, kmp_int32 cv, kmp_int32 sv );
781 PUBLIC __kmp_compare_and_store32
785 __kmp_compare_and_store32 PROC ;NEAR
789 lock cmpxchg DWORD PTR [rcx], edx
790 sete al ; if eax == [rcx] set al = 1 else set al = 0
791 and rax, 1 ; sign extend previous instruction
794 __kmp_compare_and_store32 ENDP
798 ;------------------------------------------------------------------------
799 ; FUNCTION __kmp_compare_and_store64
802 ; __kmp_compare_and_store64( volatile kmp_int64 *p, kmp_int64 cv, kmp_int64 sv );
809 PUBLIC __kmp_compare_and_store64
813 __kmp_compare_and_store64 PROC ;NEAR
817 lock cmpxchg QWORD PTR [rcx], rdx
818 sete al ; if rax == [rcx] set al = 1 else set al = 0
819 and rax, 1 ; sign extend previous instruction
822 __kmp_compare_and_store64 ENDP
826 ;------------------------------------------------------------------------
827 ; FUNCTION ___kmp_xchg_fixed8
830 ; __kmp_xchg_fixed8( volatile kmp_int8 *p, kmp_int8 d );
837 PUBLIC __kmp_xchg_fixed8
841 __kmp_xchg_fixed8 PROC ;NEAR
844 lock xchg BYTE PTR [rcx], al
847 __kmp_xchg_fixed8 ENDP
851 ;------------------------------------------------------------------------
852 ; FUNCTION ___kmp_xchg_fixed16
855 ; __kmp_xchg_fixed16( volatile kmp_int16 *p, kmp_int16 d );
862 PUBLIC __kmp_xchg_fixed16
866 __kmp_xchg_fixed16 PROC ;NEAR
869 lock xchg WORD PTR [rcx], ax
872 __kmp_xchg_fixed16 ENDP
876 ;------------------------------------------------------------------------
877 ; FUNCTION ___kmp_xchg_fixed32
880 ; __kmp_xchg_fixed32( volatile kmp_int32 *p, kmp_int32 d );
887 PUBLIC __kmp_xchg_fixed32
890 __kmp_xchg_fixed32 PROC ;NEAR
893 lock xchg DWORD PTR [rcx], eax
896 __kmp_xchg_fixed32 ENDP
900 ;------------------------------------------------------------------------
901 ; FUNCTION ___kmp_xchg_fixed64
904 ; __kmp_xchg_fixed64( volatile kmp_int64 *p, kmp_int64 d );
911 PUBLIC __kmp_xchg_fixed64
914 __kmp_xchg_fixed64 PROC ;NEAR
917 lock xchg QWORD PTR [rcx], rax
920 __kmp_xchg_fixed64 ENDP
924 ;------------------------------------------------------------------------
925 ; FUNCTION __kmp_compare_and_store_ret8
928 ; __kmp_compare_and_store_ret8( volatile kmp_int8 *p, kmp_int8 cv, kmp_int8 sv );
935 PUBLIC __kmp_compare_and_store_ret8
939 __kmp_compare_and_store_ret8 PROC ;NEAR
942 lock cmpxchg BYTE PTR [rcx], dl
943 ; Compare AL with [rcx]. If equal set
944 ; ZF and exchange DL with [rcx]. Else, clear
945 ; ZF and load [rcx] into AL.
948 __kmp_compare_and_store_ret8 ENDP
952 ;------------------------------------------------------------------------
953 ; FUNCTION __kmp_compare_and_store_ret16
956 ; __kmp_compare_and_store_ret16( volatile kmp_int16 *p, kmp_int16 cv, kmp_int16 sv );
963 PUBLIC __kmp_compare_and_store_ret16
967 __kmp_compare_and_store_ret16 PROC ;NEAR
971 lock cmpxchg WORD PTR [rcx], dx
974 __kmp_compare_and_store_ret16 ENDP
978 ;------------------------------------------------------------------------
979 ; FUNCTION __kmp_compare_and_store_ret32
982 ; __kmp_compare_and_store_ret32( volatile kmp_int32 *p, kmp_int32 cv, kmp_int32 sv );
989 PUBLIC __kmp_compare_and_store_ret32
993 __kmp_compare_and_store_ret32 PROC ;NEAR
997 lock cmpxchg DWORD PTR [rcx], edx
1000 __kmp_compare_and_store_ret32 ENDP
1004 ;------------------------------------------------------------------------
1005 ; FUNCTION __kmp_compare_and_store_ret64
1008 ; __kmp_compare_and_store_ret64( volatile kmp_int64 *p, kmp_int64 cv, kmp_int64 sv );
1015 PUBLIC __kmp_compare_and_store_ret64
1019 __kmp_compare_and_store_ret64 PROC ;NEAR
1023 lock cmpxchg QWORD PTR [rcx], rdx
1026 __kmp_compare_and_store_ret64 ENDP
1030 ;------------------------------------------------------------------------
1031 ; FUNCTION __kmp_compare_and_store_loop8
1034 ; __kmp_compare_and_store_loop8( volatile kmp_int8 *p, kmp_int8 cv, kmp_int8 sv );
1041 PUBLIC __kmp_compare_and_store_loop8
1045 __kmp_compare_and_store_loop8 PROC ;NEAR
1049 lock cmpxchg BYTE PTR [rcx], dl
1050 ; Compare AL with [rcx]. If equal set
1051 ; ZF and exchange DL with [rcx]. Else, clear
1052 ; ZF and load [rcx] into AL.
1053 jz SHORT $__kmp_success
1058 jmp SHORT $__kmp_loop
1063 __kmp_compare_and_store_loop8 ENDP
1067 ;------------------------------------------------------------------------
1068 ; FUNCTION __kmp_xchg_real32
1071 ; __kmp_xchg_real32( volatile kmp_real32 *p, kmp_real32 d );
1075 ; d: xmm1 (lower 4 bytes)
1077 ; return: xmm0 (lower 4 bytes)
1078 PUBLIC __kmp_xchg_real32
1081 __kmp_xchg_real32 PROC ;NEAR
1083 movd eax, xmm1 ; load d
1085 lock xchg DWORD PTR [rcx], eax
1087 movd xmm0, eax ; load old value into return register
1090 __kmp_xchg_real32 ENDP
1094 ;------------------------------------------------------------------------
1095 ; FUNCTION __kmp_xchg_real64
1098 ; __kmp_xchg_real64( volatile kmp_real64 *p, kmp_real64 d );
1102 ; d: xmm1 (lower 8 bytes)
1104 ; return: xmm0 (lower 8 bytes)
1105 PUBLIC __kmp_xchg_real64
1108 __kmp_xchg_real64 PROC ;NEAR
1110 movd rax, xmm1 ; load "d"
1112 lock xchg QWORD PTR [rcx], rax
1114 movd xmm0, rax ; load old value into return register
1117 __kmp_xchg_real64 ENDP
1120 ;------------------------------------------------------------------------
1121 ; FUNCTION __kmp_load_x87_fpu_control_word
1124 ; __kmp_load_x87_fpu_control_word( kmp_int16 *p );
1128 PUBLIC __kmp_load_x87_fpu_control_word
1131 __kmp_load_x87_fpu_control_word PROC ;NEAR
1133 fldcw WORD PTR [rcx]
1136 __kmp_load_x87_fpu_control_word ENDP
1140 ;------------------------------------------------------------------------
1141 ; FUNCTION __kmp_store_x87_fpu_control_word
1144 ; __kmp_store_x87_fpu_control_word( kmp_int16 *p );
1148 PUBLIC __kmp_store_x87_fpu_control_word
1151 __kmp_store_x87_fpu_control_word PROC ;NEAR
1153 fstcw WORD PTR [rcx]
1156 __kmp_store_x87_fpu_control_word ENDP
1160 ;------------------------------------------------------------------------
1161 ; FUNCTION __kmp_clear_x87_fpu_status_word
1164 ; __kmp_clear_x87_fpu_status_word()
1165 PUBLIC __kmp_clear_x87_fpu_status_word
1168 __kmp_clear_x87_fpu_status_word PROC ;NEAR
1173 __kmp_clear_x87_fpu_status_word ENDP
1177 ;------------------------------------------------------------------------
1178 ; FUNCTION __kmp_invoke_microtask
1180 ; typedef void (*microtask_t)( int *gtid, int *tid, ... );
1183 ; __kmp_invoke_microtask( microtask_t pkfn,
1184 ; int gtid, int tid,
1185 ; int argc, void *p_argv[] ) {
1187 ; (*pkfn) ( >id, &tid, argv[0], ... );
1192 ; just before call to pkfn must have rsp 128-byte aligned for compiler
1199 ; [st]: p_argv 48[rbp]
1202 ; rax: used all over the place
1203 ; rdx: used all over the place
1204 ; rcx: used as argument counter for push parms loop
1205 ; r10: used to hold pkfn function pointer argument
1207 ; return: eax (always 1/TRUE)
1217 PUBLIC __kmp_invoke_microtask
1221 __kmp_invoke_microtask PROC FRAME ;NEAR
1222 mov QWORD PTR 16[rsp], rdx ; home gtid parameter
1223 mov QWORD PTR 24[rsp], r8 ; home tid parameter
1224 push rbp ; save base pointer
1226 sub rsp, 0 ; no fixed allocation necessary - end prolog
1228 lea rbp, QWORD PTR [rsp] ; establish the base pointer
1232 mov rax, QWORD PTR $_exit_frame[rbp]
1233 mov QWORD PTR [rax], rbp
1235 mov r10, rcx ; save pkfn pointer for later
1237 ;; ------------------------------------------------------------
1238 mov rax, r9 ; rax <= argc
1240 jge SHORT $_kmp_invoke_stack_align
1241 mov rax, 2 ; set 4 homes if less than 2 parms
1242 $_kmp_invoke_stack_align:
1243 lea rdx, QWORD PTR [rax*8+16] ; rax <= (argc + 2) * 8
1244 mov rax, rsp ; Save current SP into rax
1245 sub rax, rdx ; rsp - ((argc+2)*8) -> rax
1246 ; without align, rsp would be this
1247 and rax, -128 ; Mask off 7 bits (128-byte align)
1248 add rax, rdx ; add space for push's in a loop below
1249 mov rsp, rax ; Prepare the stack ptr
1250 ; Now it will align to 128-byte at the call
1251 ;; ------------------------------------------------------------
1252 ; setup pkfn parameter stack
1253 mov rax, r9 ; rax <= argc
1254 shl rax, 3 ; rax <= argc*8
1255 mov rdx, QWORD PTR $_p_argv[rbp] ; rdx <= p_argv
1256 add rdx, rax ; rdx <= &p_argv[argc]
1257 mov rcx, r9 ; rcx <= argc
1258 jecxz SHORT $_kmp_invoke_pass_parms ; nothing to push if argc=0
1259 cmp ecx, 1 ; if argc=1 branch ahead
1260 je SHORT $_kmp_invoke_one_parm
1261 sub ecx, 2 ; if argc=2 branch ahead, subtract two from
1262 je SHORT $_kmp_invoke_two_parms
1264 $_kmp_invoke_push_parms: ; push last - 5th parms to pkfn on stack
1265 sub rdx, 8 ; decrement p_argv pointer to previous parm
1266 mov r8, QWORD PTR [rdx] ; r8 <= p_argv[rcx-1]
1267 push r8 ; push p_argv[rcx-1] onto stack (reverse order)
1269 jecxz SHORT $_kmp_invoke_two_parms
1270 jmp SHORT $_kmp_invoke_push_parms
1272 $_kmp_invoke_two_parms:
1273 sub rdx, 8 ; put 4th parm to pkfn in r9
1274 mov r9, QWORD PTR [rdx] ; r9 <= p_argv[1]
1276 $_kmp_invoke_one_parm:
1277 sub rdx, 8 ; put 3rd parm to pkfn in r8
1278 mov r8, QWORD PTR [rdx] ; r8 <= p_argv[0]
1280 $_kmp_invoke_pass_parms: ; put 1st & 2nd parms to pkfn in registers
1281 lea rdx, QWORD PTR $_tid[rbp] ; rdx <= &tid (2nd parm to pkfn)
1282 lea rcx, QWORD PTR $_gtid[rbp] ; rcx <= >id (1st parm to pkfn)
1283 sub rsp, 32 ; add stack space for first four parms
1284 mov rax, r10 ; rax <= pkfn
1285 call rax ; call (*pkfn)()
1286 mov rax, 1 ; move 1 into return register;
1288 lea rsp, QWORD PTR [rbp] ; restore stack pointer
1290 ; add rsp, 0 ; no fixed allocation necessary - start epilog
1291 pop rbp ; restore frame pointer
1293 __kmp_invoke_microtask ENDP