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