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