xref: /reactos/sdk/lib/crt/math/libm_sse2/fmod.asm (revision 1734f297)
1;
2; MIT License
3; -----------
4;
5; Copyright (c) 2002-2019 Advanced Micro Devices, Inc.
6;
7; Permission is hereby granted, free of charge, to any person obtaining a copy
8; of this Software and associated documentaon files (the "Software"), to deal
9; in the Software without restriction, including without limitation the rights
10; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11; copies of the Software, and to permit persons to whom the Software is
12; furnished to do so, subject to the following conditions:
13;
14; The above copyright notice and this permission notice shall be included in
15; all copies or substantial portions of the Software.
16;
17; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23; THE SOFTWARE.
24;
25; $Workfile: fmod.asm $
26; $Revision: 4 $
27;     $Date: 9/15/04 16:43 $
28;
29;
30; This is an optimized version of fmod.
31;
32; Define _CRTBLD_C9X to make it compliant with C90 and on.
33;
34; If building the OS CRTL (_NTSUBSET_ defined), abort.
35
36;		.ERRDEF _NTSUBSET_, "x87 code cannot be used in kernel mode"
37
38DOMAIN		EQU	1			; _DOMAIN
39EDOM		EQU	33			; EDOM
40FPCODEFMOD	EQU	22			; _FpCodeFmod
41INVALID		EQU	8			; AMD_F_INVALID
42
43FPIND		EQU	0fff8000000000000h	; indefinite
44FPSNAN		EQU	07ff7ffffffffffffh	; SNAN
45FPQNAN		EQU	07fffffffffffffffh	; QNAN
46
47X87SW		RECORD	X87SW_B: 1,
48			X87SW_C3: 1,
49			X87SW_TOP: 3,
50			X87SW_C: 3,
51			X87SW_ES: 1,
52			X87SW_SF: 1,
53			X87SW_PE: 1,
54			X87SW_E: 5
55
56X87XAM		EQU	MASK X87SW_C3 OR MASK X87SW_C AND NOT (1 SHL (X87SW_C + 1))
57X87XAM_INF	EQU	5 SHL X87SW_C
58X87XAM_NAN	EQU	1 SHL X87SW_C
59X87XAM_BAD	EQU	MASK X87SW_E AND NOT 2
60
61		EXTRN	_handle_error: PROC	; float _handle_error (char *fname, int opcode, unsigned long long value, int type, int flags, int error, double arg1, double arg2, int nargs)
62
63		.const
64
65@fmodz		DB	"fmod", 0
66
67		.CODE
68
69; double fmod [double, double] ----------------------------------
70
71PUBLIC fmod
72fmod		PROC	FRAME
73
74		sub	rsp, 40 + 32
75
76		.ALLOCSTACK 40 + 32
77		.ENDPROLOG
78
79		movsd	QWORD PTR 24 [rsp + 32], xmm1	; Y
80		movsd	QWORD PTR 16 [rsp + 32], xmm0	; X
81
82		DB	0ddh, 44h, 24h, 38h	; fld	QWORD PTR 24 [rsp + 32]
83		DB	0ddh, 44h, 24h, 30h	; fld	QWORD PTR 16 [rsp + 32]
84
85		DB	0d9h, 0e5h		; fxam (X)
86		DB	09bh, 0ddh, 07ch, 024h, 010h ; fstsw 16 [rsp]
87
88		movzx	ecx, WORD PTR 16 [rsp]
89		and	ecx, X87XAM
90
91		fnclex			; clear exception flags
92						; in preparation for fprem
93
94@again:
95		DB	0d9h, 0f8h		; fprem
96
97		DB	09bh, 0dfh, 0e0h 	; fstsw	ax
98		test	ax, 4 SHL X87SW_C
99		jnz	@again	; do it again in case of partial result
100
101		DB	0ddh, 01ch, 024h	; fstp	QWORD PTR [rsp]
102		movlpd	xmm0, QWORD PTR [rsp]		; result
103
104		DB	0d9h, 0e5h		; fxam (Y)
105		DB	09bh, 0ddh, 07ch, 024h, 008h ; fstsw 8 [rsp]
106
107		movzx	edx, WORD PTR 8 [rsp]
108		and	edx, X87XAM
109
110		DB	0ddh, 0d8h		; fstp	st(0)
111
112		cmp	edx, X87XAM_NAN		; fmod (x, NAN) = QNAN
113		je	@error
114
115		cmp	ecx, X87XAM_NAN		; fmod (NAN, y) = QNAN
116		je	@error
117
118		and	eax, X87XAM_BAD
119		jnz	@raise			; handle error
120
121		IFNDEF	_CRTBLD_C9X		; Not C90
122		cmp	edx, X87XAM_INF		; fmod (x, infinity) = ???
123		je	@raise
124		ELSE				; C90
125						; fmod (x, infinity) = x (as x87 already does)
126		ENDIF
127
128@exit:
129		add	rsp, 40 + 32
130		ret
131
132		ALIGN	16
133
134@raise:
135		mov	eax, INVALID		; raise exception
136		mov	r8, FPIND
137		jmp	@fail
138
139@error:
140		xor	eax, eax		; no exception
141		movd	r8, xmm0
142		jmp	@fail
143
144@fail:
145		lea	rcx, [@fmodz]		; fname
146		mov	edx, FPCODEFMOD		; opcode
147;		mov	r8, INDEF		; value
148		mov	r9d, DOMAIN		; type
149		mov	DWORD PTR  0 [rsp + 32], eax ; flags
150		mov	DWORD PTR  8 [rsp + 32], EDOM ; error
151		mov	DWORD PTR 32 [rsp + 32], 2 ; nargs
152		call	_handle_error		; (char *fname, int opcode, unsigned long long value, int type, int flags, int error, double arg1, double arg2, int nargs)
153
154		DB	09bh, 0dbh, 0e2h	; fclex
155		jmp	@exit
156
157fmod		ENDP
158
159; ---------------------------------------------------------------
160
161		END
162