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 ;// The LLVM Compiler Infrastructure
9 ;// This file is dual licensed under the MIT and the University of Illinois Open
10 ;// Source Licenses. See LICENSE.txt for details.
12 ;//===----------------------------------------------------------------------===//
15 TITLE z_Windows_NT-586_asm.asm
17 ; ============================= IA-32 architecture ==========================
25 _TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
27 _DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
29 CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
31 _BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
33 $$SYMBOLS SEGMENT BYTE USE32 'DEBSYM'
35 $$TYPES SEGMENT BYTE USE32 'DEBTYP'
37 _TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
39 FLAT GROUP _DATA, CONST, _BSS
40 ASSUME CS: FLAT, DS: FLAT, SS: FLAT
44 ;------------------------------------------------------------------------
45 ; FUNCTION ___kmp_x86_pause
48 ; __kmp_x86_pause( void )
49 PUBLIC ___kmp_x86_pause
54 ___kmp_x86_pause PROC NEAR
63 ;------------------------------------------------------------------------
64 ; FUNCTION ___kmp_x86_cpuid
67 ; __kmp_x86_cpuid( int mode, int mode2, struct kmp_cpuid *p );
68 PUBLIC ___kmp_x86_cpuid
79 ___kmp_x86_cpuid PROC NEAR
89 mov eax, DWORD PTR _mode$[ebp]
90 mov ecx, DWORD PTR _mode2$[ebp]
91 cpuid ; Query the CPUID for the current processor
93 mov edi, DWORD PTR _p$[ebp]
94 mov DWORD PTR _eax$[ edi ], eax
95 mov DWORD PTR _ebx$[ edi ], ebx
96 mov DWORD PTR _ecx$[ edi ], ecx
97 mov DWORD PTR _edx$[ edi ], edx
108 ___kmp_x86_cpuid ENDP
111 ;------------------------------------------------------------------------
112 ; FUNCTION ___kmp_test_then_add32
115 ; __kmp_test_then_add32( volatile kmp_int32 *p, kmp_int32 d );
116 PUBLIC ___kmp_test_then_add32
121 ___kmp_test_then_add32 PROC NEAR
123 mov eax, DWORD PTR _d$[esp]
124 mov ecx, DWORD PTR _p$[esp]
125 lock xadd DWORD PTR [ecx], eax
128 ___kmp_test_then_add32 ENDP
131 ;------------------------------------------------------------------------
132 ; FUNCTION ___kmp_compare_and_store8
135 ; __kmp_compare_and_store8( volatile kmp_int8 *p, kmp_int8 cv, kmp_int8 sv );
136 PUBLIC ___kmp_compare_and_store8
143 ___kmp_compare_and_store8 PROC NEAR
145 mov ecx, DWORD PTR _p$[esp]
146 mov al, BYTE PTR _cv$[esp]
147 mov dl, BYTE PTR _sv$[esp]
148 lock cmpxchg BYTE PTR [ecx], dl
149 sete al ; if al == [ecx] set al = 1 else set al = 0
150 and eax, 1 ; sign extend previous instruction
153 ___kmp_compare_and_store8 ENDP
156 ;------------------------------------------------------------------------
157 ; FUNCTION ___kmp_compare_and_store16
160 ; __kmp_compare_and_store16( volatile kmp_int16 *p, kmp_int16 cv, kmp_int16 sv );
161 PUBLIC ___kmp_compare_and_store16
168 ___kmp_compare_and_store16 PROC NEAR
170 mov ecx, DWORD PTR _p$[esp]
171 mov ax, WORD PTR _cv$[esp]
172 mov dx, WORD PTR _sv$[esp]
173 lock cmpxchg WORD PTR [ecx], dx
174 sete al ; if ax == [ecx] set al = 1 else set al = 0
175 and eax, 1 ; sign extend previous instruction
178 ___kmp_compare_and_store16 ENDP
181 ;------------------------------------------------------------------------
182 ; FUNCTION ___kmp_compare_and_store32
185 ; __kmp_compare_and_store32( volatile kmp_int32 *p, kmp_int32 cv, kmp_int32 sv );
186 PUBLIC ___kmp_compare_and_store32
193 ___kmp_compare_and_store32 PROC NEAR
195 mov ecx, DWORD PTR _p$[esp]
196 mov eax, DWORD PTR _cv$[esp]
197 mov edx, DWORD PTR _sv$[esp]
198 lock cmpxchg DWORD PTR [ecx], edx
199 sete al ; if eax == [ecx] set al = 1 else set al = 0
200 and eax, 1 ; sign extend previous instruction
203 ___kmp_compare_and_store32 ENDP
206 ;------------------------------------------------------------------------
207 ; FUNCTION ___kmp_compare_and_store64
210 ; __kmp_compare_and_store64( volatile kmp_int64 *p, kmp_int64 cv, kmp_int64 sv );
211 PUBLIC ___kmp_compare_and_store64
220 ___kmp_compare_and_store64 PROC NEAR
226 mov edi, DWORD PTR _p$[ebp]
227 mov eax, DWORD PTR _cv_low$[ebp]
228 mov edx, DWORD PTR _cv_high$[ebp]
229 mov ebx, DWORD PTR _sv_low$[ebp]
230 mov ecx, DWORD PTR _sv_high$[ebp]
231 lock cmpxchg8b QWORD PTR [edi]
232 sete al ; if edx:eax == [edi] set al = 1 else set al = 0
233 and eax, 1 ; sign extend previous instruction
240 ___kmp_compare_and_store64 ENDP
243 ;------------------------------------------------------------------------
244 ; FUNCTION ___kmp_xchg_fixed8
247 ; __kmp_xchg_fixed8( volatile kmp_int8 *p, kmp_int8 d );
248 PUBLIC ___kmp_xchg_fixed8
254 ___kmp_xchg_fixed8 PROC NEAR
256 mov ecx, DWORD PTR _p$[esp]
257 mov al, BYTE PTR _d$[esp]
258 lock xchg BYTE PTR [ecx], al
261 ___kmp_xchg_fixed8 ENDP
264 ;------------------------------------------------------------------------
265 ; FUNCTION ___kmp_xchg_fixed16
268 ; __kmp_xchg_fixed16( volatile kmp_int16 *p, kmp_int16 d );
269 PUBLIC ___kmp_xchg_fixed16
275 ___kmp_xchg_fixed16 PROC NEAR
277 mov ecx, DWORD PTR _p$[esp]
278 mov ax, WORD PTR _d$[esp]
279 lock xchg WORD PTR [ecx], ax
282 ___kmp_xchg_fixed16 ENDP
285 ;------------------------------------------------------------------------
286 ; FUNCTION ___kmp_xchg_fixed32
289 ; __kmp_xchg_fixed32( volatile kmp_int32 *p, kmp_int32 d );
290 PUBLIC ___kmp_xchg_fixed32
296 ___kmp_xchg_fixed32 PROC NEAR
298 mov ecx, DWORD PTR _p$[esp]
299 mov eax, DWORD PTR _d$[esp]
300 lock xchg DWORD PTR [ecx], eax
303 ___kmp_xchg_fixed32 ENDP
307 ;------------------------------------------------------------------------
308 ; FUNCTION ___kmp_xchg_real32
311 ; __kmp_xchg_real32( volatile kmp_real32 *p, kmp_real32 d );
312 PUBLIC ___kmp_xchg_real32
319 ___kmp_xchg_real32 PROC NEAR
325 mov esi, DWORD PTR _p$[ebp]
329 fst DWORD PTR _old_value$[ebp]
330 ;; store into old_value
332 mov eax, DWORD PTR _d$[ebp]
334 lock xchg DWORD PTR [esi], eax
336 fld DWORD PTR _old_value$[ebp]
343 ___kmp_xchg_real32 ENDP
347 ;------------------------------------------------------------------------
348 ; FUNCTION ___kmp_compare_and_store_ret8
351 ; __kmp_compare_and_store_ret8( volatile kmp_int8 *p, kmp_int8 cv, kmp_int8 sv );
352 PUBLIC ___kmp_compare_and_store_ret8
359 ___kmp_compare_and_store_ret8 PROC NEAR
361 mov ecx, DWORD PTR _p$[esp]
362 mov al, BYTE PTR _cv$[esp]
363 mov dl, BYTE PTR _sv$[esp]
364 lock cmpxchg BYTE PTR [ecx], dl
367 ___kmp_compare_and_store_ret8 ENDP
370 ;------------------------------------------------------------------------
371 ; FUNCTION ___kmp_compare_and_store_ret16
374 ; __kmp_compare_and_store_ret16( volatile kmp_int16 *p, kmp_int16 cv, kmp_int16 sv );
375 PUBLIC ___kmp_compare_and_store_ret16
382 ___kmp_compare_and_store_ret16 PROC NEAR
384 mov ecx, DWORD PTR _p$[esp]
385 mov ax, WORD PTR _cv$[esp]
386 mov dx, WORD PTR _sv$[esp]
387 lock cmpxchg WORD PTR [ecx], dx
390 ___kmp_compare_and_store_ret16 ENDP
393 ;------------------------------------------------------------------------
394 ; FUNCTION ___kmp_compare_and_store_ret32
397 ; __kmp_compare_and_store_ret32( volatile kmp_int32 *p, kmp_int32 cv, kmp_int32 sv );
398 PUBLIC ___kmp_compare_and_store_ret32
405 ___kmp_compare_and_store_ret32 PROC NEAR
407 mov ecx, DWORD PTR _p$[esp]
408 mov eax, DWORD PTR _cv$[esp]
409 mov edx, DWORD PTR _sv$[esp]
410 lock cmpxchg DWORD PTR [ecx], edx
413 ___kmp_compare_and_store_ret32 ENDP
416 ;------------------------------------------------------------------------
417 ; FUNCTION ___kmp_compare_and_store_ret64
420 ; __kmp_compare_and_store_ret64( volatile kmp_int64 *p, kmp_int64 cv, kmp_int64 sv );
421 PUBLIC ___kmp_compare_and_store_ret64
430 ___kmp_compare_and_store_ret64 PROC NEAR
436 mov edi, DWORD PTR _p$[ebp]
437 mov eax, DWORD PTR _cv_low$[ebp]
438 mov edx, DWORD PTR _cv_high$[ebp]
439 mov ebx, DWORD PTR _sv_low$[ebp]
440 mov ecx, DWORD PTR _sv_high$[ebp]
441 lock cmpxchg8b QWORD PTR [edi]
448 ___kmp_compare_and_store_ret64 ENDP
451 ;------------------------------------------------------------------------
452 ; FUNCTION ___kmp_load_x87_fpu_control_word
455 ; __kmp_load_x87_fpu_control_word( kmp_int16 *p );
459 PUBLIC ___kmp_load_x87_fpu_control_word
464 ___kmp_load_x87_fpu_control_word PROC NEAR
466 mov eax, DWORD PTR _p$[esp]
470 ___kmp_load_x87_fpu_control_word ENDP
473 ;------------------------------------------------------------------------
474 ; FUNCTION ___kmp_store_x87_fpu_control_word
477 ; __kmp_store_x87_fpu_control_word( kmp_int16 *p );
481 PUBLIC ___kmp_store_x87_fpu_control_word
486 ___kmp_store_x87_fpu_control_word PROC NEAR
488 mov eax, DWORD PTR _p$[esp]
492 ___kmp_store_x87_fpu_control_word ENDP
495 ;------------------------------------------------------------------------
496 ; FUNCTION ___kmp_clear_x87_fpu_status_word
499 ; __kmp_clear_x87_fpu_status_word();
500 PUBLIC ___kmp_clear_x87_fpu_status_word
504 ___kmp_clear_x87_fpu_status_word PROC NEAR
509 ___kmp_clear_x87_fpu_status_word ENDP
513 ;------------------------------------------------------------------------
514 ; FUNCTION ___kmp_invoke_microtask
516 ; typedef void (*microtask_t)( int *gtid, int *tid, ... );
519 ; __kmp_invoke_microtask( microtask_t pkfn,
521 ; int argc, void *p_argv[] )
522 PUBLIC ___kmp_invoke_microtask
538 ___kmp_invoke_microtask PROC NEAR
542 sub esp, 16 ; 00000010H
547 mov eax, DWORD PTR _exit_frame$[ebp]
548 mov DWORD PTR [eax], ebp
551 mov eax, DWORD PTR _argc$[ebp]
552 mov DWORD PTR _i$[ebp], eax
554 ;; ------------------------------------------------------------
555 lea edx, DWORD PTR [eax*4+8]
556 mov ecx, esp ; Save current SP into ECX
557 mov eax,edx ; Save the size of the args in eax
558 sub ecx,edx ; esp-((#args+2)*4) -> ecx -- without mods, stack ptr would be this
559 mov edx,ecx ; Save to edx
560 and ecx,-128 ; Mask off 7 bits
561 sub edx,ecx ; Amount to subtract from esp
562 sub esp,edx ; Prepare stack ptr-- Now it will be aligned on 128-byte boundary at the call
564 add edx,eax ; Calculate total size of the stack decrement.
565 mov DWORD PTR _stk_adj$[ebp], edx
566 ;; ------------------------------------------------------------
570 mov ecx, DWORD PTR _i$[ebp]
572 mov DWORD PTR _i$[ebp], ecx
574 cmp DWORD PTR _i$[ebp], 0
577 mov edx, DWORD PTR _i$[ebp]
578 mov eax, DWORD PTR _argv$[ebp]
579 mov ecx, DWORD PTR [eax+edx*4-4]
580 mov DWORD PTR _vptr$[ebp], ecx
582 mov eax, DWORD PTR _vptr$[ebp]
589 lea edx, DWORD PTR _tid$[ebp]
590 mov DWORD PTR _vptr$[ebp], edx
592 lea eax, DWORD PTR _gtid$[ebp]
593 mov DWORD PTR _qptr$[ebp], eax
595 mov eax, DWORD PTR _vptr$[ebp]
599 mov eax, DWORD PTR _qptr$[ebp]
603 call DWORD PTR _pkfn$[ebp]
605 add esp, DWORD PTR _stk_adj$[ebp]
615 ___kmp_invoke_microtask ENDP
620 ; ==================================== Intel(R) 64 ===================================
624 ;------------------------------------------------------------------------
625 ; FUNCTION __kmp_x86_cpuid
628 ; __kmp_x86_cpuid( int mode, int mode2, struct kmp_cpuid *p );
634 PUBLIC __kmp_x86_cpuid
638 __kmp_x86_cpuid PROC FRAME ;NEAR
644 push rbx ; callee-save register
648 mov r10, r8 ; p parameter
649 mov eax, ecx ; mode parameter
650 mov ecx, edx ; mode2 parameter
651 cpuid ; Query the CPUID for the current processor
653 mov DWORD PTR 0[ r10 ], eax ; store results into buffer
654 mov DWORD PTR 4[ r10 ], ebx
655 mov DWORD PTR 8[ r10 ], ecx
656 mov DWORD PTR 12[ r10 ], edx
658 pop rbx ; callee-save register
667 ;------------------------------------------------------------------------
668 ; FUNCTION __kmp_test_then_add32
671 ; __kmp_test_then_add32( volatile kmp_int32 *p, kmp_int32 d );
678 PUBLIC __kmp_test_then_add32
681 __kmp_test_then_add32 PROC ;NEAR
684 lock xadd DWORD PTR [rcx], eax
687 __kmp_test_then_add32 ENDP
691 ;------------------------------------------------------------------------
692 ; FUNCTION __kmp_test_then_add64
695 ; __kmp_test_then_add64( volatile kmp_int64 *p, kmp_int64 d );
702 PUBLIC __kmp_test_then_add64
705 __kmp_test_then_add64 PROC ;NEAR
708 lock xadd QWORD PTR [rcx], rax
711 __kmp_test_then_add64 ENDP
715 ;------------------------------------------------------------------------
716 ; FUNCTION __kmp_compare_and_store8
719 ; __kmp_compare_and_store8( volatile kmp_int8 *p, kmp_int8 cv, kmp_int8 sv );
726 PUBLIC __kmp_compare_and_store8
730 __kmp_compare_and_store8 PROC ;NEAR
734 lock cmpxchg BYTE PTR [rcx], dl
735 sete al ; if al == [rcx] set al = 1 else set al = 0
736 and rax, 1 ; sign extend previous instruction
739 __kmp_compare_and_store8 ENDP
743 ;------------------------------------------------------------------------
744 ; FUNCTION __kmp_compare_and_store16
747 ; __kmp_compare_and_store16( volatile kmp_int16 *p, kmp_int16 cv, kmp_int16 sv );
754 PUBLIC __kmp_compare_and_store16
758 __kmp_compare_and_store16 PROC ;NEAR
762 lock cmpxchg WORD PTR [rcx], dx
763 sete al ; if ax == [rcx] set al = 1 else set al = 0
764 and rax, 1 ; sign extend previous instruction
767 __kmp_compare_and_store16 ENDP
771 ;------------------------------------------------------------------------
772 ; FUNCTION __kmp_compare_and_store32
775 ; __kmp_compare_and_store32( volatile kmp_int32 *p, kmp_int32 cv, kmp_int32 sv );
782 PUBLIC __kmp_compare_and_store32
786 __kmp_compare_and_store32 PROC ;NEAR
790 lock cmpxchg DWORD PTR [rcx], edx
791 sete al ; if eax == [rcx] set al = 1 else set al = 0
792 and rax, 1 ; sign extend previous instruction
795 __kmp_compare_and_store32 ENDP
799 ;------------------------------------------------------------------------
800 ; FUNCTION __kmp_compare_and_store64
803 ; __kmp_compare_and_store64( volatile kmp_int64 *p, kmp_int64 cv, kmp_int64 sv );
810 PUBLIC __kmp_compare_and_store64
814 __kmp_compare_and_store64 PROC ;NEAR
818 lock cmpxchg QWORD PTR [rcx], rdx
819 sete al ; if rax == [rcx] set al = 1 else set al = 0
820 and rax, 1 ; sign extend previous instruction
823 __kmp_compare_and_store64 ENDP
827 ;------------------------------------------------------------------------
828 ; FUNCTION ___kmp_xchg_fixed8
831 ; __kmp_xchg_fixed8( volatile kmp_int8 *p, kmp_int8 d );
838 PUBLIC __kmp_xchg_fixed8
842 __kmp_xchg_fixed8 PROC ;NEAR
845 lock xchg BYTE PTR [rcx], al
848 __kmp_xchg_fixed8 ENDP
852 ;------------------------------------------------------------------------
853 ; FUNCTION ___kmp_xchg_fixed16
856 ; __kmp_xchg_fixed16( volatile kmp_int16 *p, kmp_int16 d );
863 PUBLIC __kmp_xchg_fixed16
867 __kmp_xchg_fixed16 PROC ;NEAR
870 lock xchg WORD PTR [rcx], ax
873 __kmp_xchg_fixed16 ENDP
877 ;------------------------------------------------------------------------
878 ; FUNCTION ___kmp_xchg_fixed32
881 ; __kmp_xchg_fixed32( volatile kmp_int32 *p, kmp_int32 d );
888 PUBLIC __kmp_xchg_fixed32
891 __kmp_xchg_fixed32 PROC ;NEAR
894 lock xchg DWORD PTR [rcx], eax
897 __kmp_xchg_fixed32 ENDP
901 ;------------------------------------------------------------------------
902 ; FUNCTION ___kmp_xchg_fixed64
905 ; __kmp_xchg_fixed64( volatile kmp_int64 *p, kmp_int64 d );
912 PUBLIC __kmp_xchg_fixed64
915 __kmp_xchg_fixed64 PROC ;NEAR
918 lock xchg QWORD PTR [rcx], rax
921 __kmp_xchg_fixed64 ENDP
925 ;------------------------------------------------------------------------
926 ; FUNCTION __kmp_compare_and_store_ret8
929 ; __kmp_compare_and_store_ret8( volatile kmp_int8 *p, kmp_int8 cv, kmp_int8 sv );
936 PUBLIC __kmp_compare_and_store_ret8
940 __kmp_compare_and_store_ret8 PROC ;NEAR
943 lock cmpxchg BYTE PTR [rcx], dl
944 ; Compare AL with [rcx]. If equal set
945 ; ZF and exchange DL with [rcx]. Else, clear
946 ; ZF and load [rcx] into AL.
949 __kmp_compare_and_store_ret8 ENDP
953 ;------------------------------------------------------------------------
954 ; FUNCTION __kmp_compare_and_store_ret16
957 ; __kmp_compare_and_store_ret16( volatile kmp_int16 *p, kmp_int16 cv, kmp_int16 sv );
964 PUBLIC __kmp_compare_and_store_ret16
968 __kmp_compare_and_store_ret16 PROC ;NEAR
972 lock cmpxchg WORD PTR [rcx], dx
975 __kmp_compare_and_store_ret16 ENDP
979 ;------------------------------------------------------------------------
980 ; FUNCTION __kmp_compare_and_store_ret32
983 ; __kmp_compare_and_store_ret32( volatile kmp_int32 *p, kmp_int32 cv, kmp_int32 sv );
990 PUBLIC __kmp_compare_and_store_ret32
994 __kmp_compare_and_store_ret32 PROC ;NEAR
998 lock cmpxchg DWORD PTR [rcx], edx
1001 __kmp_compare_and_store_ret32 ENDP
1005 ;------------------------------------------------------------------------
1006 ; FUNCTION __kmp_compare_and_store_ret64
1009 ; __kmp_compare_and_store_ret64( volatile kmp_int64 *p, kmp_int64 cv, kmp_int64 sv );
1016 PUBLIC __kmp_compare_and_store_ret64
1020 __kmp_compare_and_store_ret64 PROC ;NEAR
1024 lock cmpxchg QWORD PTR [rcx], rdx
1027 __kmp_compare_and_store_ret64 ENDP
1031 ;------------------------------------------------------------------------
1032 ; FUNCTION __kmp_compare_and_store_loop8
1035 ; __kmp_compare_and_store_loop8( volatile kmp_int8 *p, kmp_int8 cv, kmp_int8 sv );
1042 PUBLIC __kmp_compare_and_store_loop8
1046 __kmp_compare_and_store_loop8 PROC ;NEAR
1050 lock cmpxchg BYTE PTR [rcx], dl
1051 ; Compare AL with [rcx]. If equal set
1052 ; ZF and exchange DL with [rcx]. Else, clear
1053 ; ZF and load [rcx] into AL.
1054 jz SHORT $__kmp_success
1059 jmp SHORT $__kmp_loop
1064 __kmp_compare_and_store_loop8 ENDP
1068 ;------------------------------------------------------------------------
1069 ; FUNCTION __kmp_xchg_real32
1072 ; __kmp_xchg_real32( volatile kmp_real32 *p, kmp_real32 d );
1076 ; d: xmm1 (lower 4 bytes)
1078 ; return: xmm0 (lower 4 bytes)
1079 PUBLIC __kmp_xchg_real32
1082 __kmp_xchg_real32 PROC ;NEAR
1084 movd eax, xmm1 ; load d
1086 lock xchg DWORD PTR [rcx], eax
1088 movd xmm0, eax ; load old value into return register
1091 __kmp_xchg_real32 ENDP
1095 ;------------------------------------------------------------------------
1096 ; FUNCTION __kmp_xchg_real64
1099 ; __kmp_xchg_real64( volatile kmp_real64 *p, kmp_real64 d );
1103 ; d: xmm1 (lower 8 bytes)
1105 ; return: xmm0 (lower 8 bytes)
1106 PUBLIC __kmp_xchg_real64
1109 __kmp_xchg_real64 PROC ;NEAR
1111 movd rax, xmm1 ; load "d"
1113 lock xchg QWORD PTR [rcx], rax
1115 movd xmm0, rax ; load old value into return register
1118 __kmp_xchg_real64 ENDP
1121 ;------------------------------------------------------------------------
1122 ; FUNCTION __kmp_load_x87_fpu_control_word
1125 ; __kmp_load_x87_fpu_control_word( kmp_int16 *p );
1129 PUBLIC __kmp_load_x87_fpu_control_word
1132 __kmp_load_x87_fpu_control_word PROC ;NEAR
1134 fldcw WORD PTR [rcx]
1137 __kmp_load_x87_fpu_control_word ENDP
1141 ;------------------------------------------------------------------------
1142 ; FUNCTION __kmp_store_x87_fpu_control_word
1145 ; __kmp_store_x87_fpu_control_word( kmp_int16 *p );
1149 PUBLIC __kmp_store_x87_fpu_control_word
1152 __kmp_store_x87_fpu_control_word PROC ;NEAR
1154 fstcw WORD PTR [rcx]
1157 __kmp_store_x87_fpu_control_word ENDP
1161 ;------------------------------------------------------------------------
1162 ; FUNCTION __kmp_clear_x87_fpu_status_word
1165 ; __kmp_clear_x87_fpu_status_word()
1166 PUBLIC __kmp_clear_x87_fpu_status_word
1169 __kmp_clear_x87_fpu_status_word PROC ;NEAR
1174 __kmp_clear_x87_fpu_status_word ENDP
1178 ;------------------------------------------------------------------------
1179 ; FUNCTION __kmp_invoke_microtask
1181 ; typedef void (*microtask_t)( int *gtid, int *tid, ... );
1184 ; __kmp_invoke_microtask( microtask_t pkfn,
1185 ; int gtid, int tid,
1186 ; int argc, void *p_argv[] ) {
1188 ; (*pkfn) ( >id, &tid, argv[0], ... );
1193 ; just before call to pkfn must have rsp 128-byte aligned for compiler
1200 ; [st]: p_argv 48[rbp]
1203 ; rax: used all over the place
1204 ; rdx: used all over the place
1205 ; rcx: used as argument counter for push parms loop
1206 ; r10: used to hold pkfn function pointer argument
1208 ; return: eax (always 1/TRUE)
1218 PUBLIC __kmp_invoke_microtask
1222 __kmp_invoke_microtask PROC FRAME ;NEAR
1223 mov QWORD PTR 16[rsp], rdx ; home gtid parameter
1224 mov QWORD PTR 24[rsp], r8 ; home tid parameter
1225 push rbp ; save base pointer
1227 sub rsp, 0 ; no fixed allocation necessary - end prolog
1229 lea rbp, QWORD PTR [rsp] ; establish the base pointer
1233 mov rax, QWORD PTR $_exit_frame[rbp]
1234 mov QWORD PTR [rax], rbp
1236 mov r10, rcx ; save pkfn pointer for later
1238 ;; ------------------------------------------------------------
1239 mov rax, r9 ; rax <= argc
1241 jge SHORT $_kmp_invoke_stack_align
1242 mov rax, 2 ; set 4 homes if less than 2 parms
1243 $_kmp_invoke_stack_align:
1244 lea rdx, QWORD PTR [rax*8+16] ; rax <= (argc + 2) * 8
1245 mov rax, rsp ; Save current SP into rax
1246 sub rax, rdx ; rsp - ((argc+2)*8) -> rax
1247 ; without align, rsp would be this
1248 and rax, -128 ; Mask off 7 bits (128-byte align)
1249 add rax, rdx ; add space for push's in a loop below
1250 mov rsp, rax ; Prepare the stack ptr
1251 ; Now it will align to 128-byte at the call
1252 ;; ------------------------------------------------------------
1253 ; setup pkfn parameter stack
1254 mov rax, r9 ; rax <= argc
1255 shl rax, 3 ; rax <= argc*8
1256 mov rdx, QWORD PTR $_p_argv[rbp] ; rdx <= p_argv
1257 add rdx, rax ; rdx <= &p_argv[argc]
1258 mov rcx, r9 ; rcx <= argc
1259 jecxz SHORT $_kmp_invoke_pass_parms ; nothing to push if argc=0
1260 cmp ecx, 1 ; if argc=1 branch ahead
1261 je SHORT $_kmp_invoke_one_parm
1262 sub ecx, 2 ; if argc=2 branch ahead, subtract two from
1263 je SHORT $_kmp_invoke_two_parms
1265 $_kmp_invoke_push_parms: ; push last - 5th parms to pkfn on stack
1266 sub rdx, 8 ; decrement p_argv pointer to previous parm
1267 mov r8, QWORD PTR [rdx] ; r8 <= p_argv[rcx-1]
1268 push r8 ; push p_argv[rcx-1] onto stack (reverse order)
1270 jecxz SHORT $_kmp_invoke_two_parms
1271 jmp SHORT $_kmp_invoke_push_parms
1273 $_kmp_invoke_two_parms:
1274 sub rdx, 8 ; put 4th parm to pkfn in r9
1275 mov r9, QWORD PTR [rdx] ; r9 <= p_argv[1]
1277 $_kmp_invoke_one_parm:
1278 sub rdx, 8 ; put 3rd parm to pkfn in r8
1279 mov r8, QWORD PTR [rdx] ; r8 <= p_argv[0]
1281 $_kmp_invoke_pass_parms: ; put 1st & 2nd parms to pkfn in registers
1282 lea rdx, QWORD PTR $_tid[rbp] ; rdx <= &tid (2nd parm to pkfn)
1283 lea rcx, QWORD PTR $_gtid[rbp] ; rcx <= >id (1st parm to pkfn)
1284 sub rsp, 32 ; add stack space for first four parms
1285 mov rax, r10 ; rax <= pkfn
1286 call rax ; call (*pkfn)()
1287 mov rax, 1 ; move 1 into return register;
1289 lea rsp, QWORD PTR [rbp] ; restore stack pointer
1291 ; add rsp, 0 ; no fixed allocation necessary - start epilog
1292 pop rbp ; restore frame pointer
1294 __kmp_invoke_microtask ENDP