Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

531 lines
11 KiB

  1. page ,132
  2. title 87cdisp - C transcendental function dispatcher
  3. ;***
  4. ;87cdisp.asm - C transcendental function dispatcher (80x87/emulator version)
  5. ;
  6. ; Copyright (c) 1987-2001, Microsoft Corporation. All rights reserved.
  7. ;
  8. ;Purpose:
  9. ; Common dispatch code and error handling for C transcendental functions
  10. ;
  11. ;Revision History:
  12. ; 07-04-84 GFW initial version
  13. ; 12-21-84 GFW correctly point to name in matherr struct
  14. ; 05-12-85 GFW return HUGE correctly signed on ERANGE errors
  15. ; fill 2nd operand for matherr structure correctly
  16. ; 07-05-85 GFW check for possible overflow on PLOSS errors
  17. ; in this case OVERFLOW overrides PLOSS
  18. ; 07-08-85 GFW added FWAIT in useHUGE
  19. ; 11-20-85 GFW faster RANGE checking
  20. ; 09-30-86 JMB internationalized error message handling
  21. ; 03-09-87 BCM changed writestr to _wrt2err (extern)
  22. ; 04-14-87 BCM log(0.0) and log10(0.0) sets errno to ERANGE
  23. ; for MS C 5.0 (ANSI compatible); errno is still
  24. ; set to EDOM for IBM C 2.0 (System V compatible).
  25. ; 04-28-87 BCM Added _cintrindisp1 and _cintrindisp2
  26. ; for C "intrinsic" versions of pow, log, log10, exp,
  27. ; cos, sin, tan, acos, asin, atan, atan2,
  28. ; cosh, sinh, tanh, sqrt, ... for MS C 5.0
  29. ; 08-04-87 BCM Removed "externP write" declaration.
  30. ; 08-17-87 BCM Changed _wrt2err from near to model-dependent
  31. ; except for IMBC20; this is because of QC core lib
  32. ; 10-12-87 BCM OS/2 support C library changes
  33. ; 11-24-87 BCM added _loadds under ifdef DLL
  34. ; 01-18-88 BCM eliminated IBMC20; ifos2,noos2 ==> ifmt, nomt
  35. ; 02-10-88 WAJ MTHREAD libraries now lock stderr when printing errors
  36. ; 04-25-88 WAJ _cpower is on the stack for MTHREAD so must be set to 1
  37. ; 07-11-88 WAJ address of matherr structure was incorrect in MTHREAD case
  38. ; 08-24-88 WAJ 386 version.
  39. ; 11-20-89 WAJ 386 MTHREAD is no longer _pascal.
  40. ; 08-17-90 WAJ Now uses _stdcall.
  41. ; 10-15-90 WAJ Fixed intrinsic/2 argument problems.
  42. ; 05-17-91 WAJ Added _STDCALL ifdefs.
  43. ; 08-27-91 JCR ANSI naming
  44. ; 09-15-91 GDP Added _cwrt2err. _NMSG_WRITE is no longer _pascal
  45. ; 11-15-91 GDP Removed error message display stuff
  46. ; moved exception structure to stack frame, even for
  47. ; single thread code (allow recursive calls of
  48. ; transcendentals through matherr)
  49. ; call _87except after fsave
  50. ; put Localfac on the stack for multi thread
  51. ; 02-10-92 GDP changed error handling avoid polluting the fp status word
  52. ; 03-15-92 GDP extensive changes in error detection scheme
  53. ; 10-27-92 SKS Re-arranged some code to make this work with MASM 6.10
  54. ; 11-06-92 GDP merged changes from the fp tree on \\vangogh: removed
  55. ; saveflag, added __fastflag, new range error checking
  56. ; 09-06-94 CFW Replace MTHREAD with _MT.
  57. ; 04-06-01 PML CHECKOVER should check overflow, not underflow (vs7#132450)
  58. ;*******************************************************************************
  59. .xlist
  60. include cruntime.inc
  61. include mrt386.inc
  62. include os2supp.inc
  63. include elem87.inc
  64. .list
  65. EDOM = 33 ; math error numbers
  66. ERANGE = 34
  67. EDOMAIN = 120 ; internal error number for DOMAIN
  68. ESING = 121 ; internal error number for SING
  69. ETLOSS = 122 ; internal error number for TLOSS
  70. .data
  71. comm _matherr_flag:dword
  72. extrn __fastflag:dword
  73. .const
  74. staticQ DblMax, 07fefffffffffffffR
  75. staticQ DblMin, 00010000000000000R
  76. staticQ IeeeAdjO, 0c098000000000000R
  77. staticQ IeeeAdjU, 04098000000000000R
  78. staticQ _infinity, 07ff0000000000000R
  79. staticQ _zero, 00000000000000000R
  80. ifndef _MT
  81. .data?
  82. staticQ LocalFac, ?
  83. intrinflag db ?
  84. else ;_MT
  85. MTStackFrame struc
  86. MTS_LocalFac dq ?
  87. MTS_cdispflags db ?
  88. MTStackFrame ends
  89. MTSFISize equ ((size MTStackFrame) + ISIZE - 1) and (not (ISIZE-1))
  90. LocalFac equ <MTSF.MTS_LocalFac>
  91. cdispflags equ <MTSF.MTS_cdispflags>
  92. INTRINFLAG = 01h
  93. TWOARGFLAG = 02h
  94. endif ;_MT
  95. ; error value action table
  96. ;labelW retvaltab
  97. ; DNCPTR codeOFFSET useretval
  98. page
  99. CODESEG
  100. extrn _trandisp1:near
  101. extrn _trandisp2:near
  102. extrn _87except:proc
  103. ;----------------------------------------------------------
  104. ;
  105. ; intrinsic versions: TRANSCENDENTAL DISPATCH ROUTINES
  106. ;
  107. ;----------------------------------------------------------
  108. ;
  109. ; _cintrindisp1 - Intrinsic Dispatch for 1 arg DP transcendental
  110. ; _cintrindisp2 - Intrinsic Dispatch for 2 arg DP transcendental
  111. ;
  112. ; rdx - function dispatch table address
  113. ;
  114. ;----------------------------------------------------------
  115. _cintrindisp2 proc uses RBXONLY
  116. local DLSF[DSFISize]:IWORD
  117. ifmt <local MTSF[MTSFISize]:IWORD>
  118. fstcw [DSF.savCntrl]
  119. fwait
  120. ; store the args in case they are needed by matherr.
  121. ; Generally avoid storing since this may generate
  122. ; various exceptions (overflow, underflow, inexact, invalid)
  123. ; Args will not be available to an exception handler and
  124. ; users should not use /Oi if interested in IEEE conformance
  125. cmp [_matherr_flag], 0
  126. JSE save2arg
  127. lab resume2
  128. ;ifmt <mov [_cpower], 1> ; set _cpower to C semantics
  129. ; DISABLED this feature since pow(0,0)
  130. ; will return 1 in C (NCEG spec) which
  131. ; is the same as in FORTRAN --GDP
  132. call _trandisp2
  133. ifmt <or [cdispflags], (INTRINFLAG OR TWOARGFLAG)>
  134. nomt <mov [intrinflag], 1>
  135. call cintrinexit
  136. ret
  137. lab save2arg
  138. fxch
  139. fst [DSF.arg1]
  140. fxch
  141. fst [DSF.arg2]
  142. jmp resume2
  143. _cintrindisp2 endp
  144. _cintrindisp1 proc uses RBXONLY
  145. local DLSF[DSFISize]:IWORD
  146. ifmt <local MTSF[MTSFISize]:IWORD>
  147. fstcw [DSF.savCntrl]
  148. cmp [_matherr_flag], 0
  149. JSE save1arg
  150. lab resume1
  151. call _trandisp1
  152. ifmt <or [cdispflags],INTRINFLAG>
  153. ifmt <and [cdispflags],(NOT TWOARGFLAG)>
  154. nomt <mov [intrinflag], 1>
  155. call cintrinexit
  156. ret
  157. lab save1arg
  158. fst [DSF.arg1]
  159. jmp resume1
  160. _cintrindisp1 endp
  161. ;*******************************************************************************
  162. ;*
  163. ;* TRANSCENDENTAL DISPATCH ROUTINES
  164. ;*
  165. ;*******************************************************************************
  166. ;*
  167. ;* _ctrandisp1 - Dispatch for 1 arg DP transcendental
  168. ;* _ctrandisp2 - Dispatch for 2 arg DP transcendental
  169. ;*
  170. ;* edx - function dispatch table address
  171. ;*
  172. ;*******************************************************************************
  173. ;*
  174. ;* Two arg standard dispatch.
  175. ;*
  176. _ctrandisp2 proc uses ebx, parm1:qword, parm2:qword
  177. local DLSF[DSFISize]:IWORD
  178. ifmt <local MTSF[MTSFISize]:IWORD>
  179. push dword ptr [parm1+4] ; load arg1
  180. push dword ptr [parm1]
  181. call _fload
  182. ifndef _STDCALL
  183. add esp, 8
  184. endif
  185. push dword ptr [parm2+4] ; load arg2
  186. push dword ptr [parm2]
  187. call _fload
  188. ifndef _STDCALL
  189. add esp, 8
  190. endif
  191. fstcw [DSF.savCntrl]
  192. ifmt <or [cdispflags], TWOARGFLAG>
  193. ifmt <mov [_cpower], 1> ; set _cpower to C semantics
  194. call _trandisp2
  195. call ctranexit
  196. ifdef _STDCALL
  197. ret 16
  198. else
  199. ret
  200. endif
  201. ;*
  202. ;* Check for overflow and errors.
  203. ;*
  204. ctranexit::
  205. ifmt <and [cdispflags], (NOT INTRINFLAG)>
  206. nomt <mov [intrinflag], 0>
  207. cintrinexit::
  208. cmp __fastflag, 0
  209. JSNZ restoreCW
  210. fst qword ptr [LocalFac] ; cast result to double precision
  211. ;
  212. ; PROBLEM: Since the intrinsics may be given an argument anywhere
  213. ; in the long double range, functions that are not normally
  214. ; expected to overflow (like sqrt) may generate IEEE exceptions
  215. ; at this point. We can cure this by making the checkrange test
  216. ; standard.
  217. ;
  218. mov al, [DSF.ErrorType] ; check for errors
  219. or al, al
  220. JE checkinexact
  221. cmp al, CHECKOVER
  222. JE checkoverflow
  223. cmp al, CHECKRANGE
  224. JSE checkrng
  225. or al, al
  226. JSE restoreCW
  227. CBI
  228. mov [DSF.typ], rax ; set exception type
  229. jmp haveerror
  230. lab checkinexact
  231. ; This will be the most common path because of
  232. ; the nature of transcendentals. If inexact is
  233. ; unmasked in user's cw and active, raise it
  234. mov ax, [DSF.savCntrl]
  235. and ax, 20h
  236. JSNZ restoreCW ; inexact exception masked
  237. fstsw ax
  238. and ax, 20h
  239. JSZ restoreCW
  240. mov [DSF.typ], INEXACT
  241. jmp haveerror
  242. lab restoreCW
  243. lab restoreCW2
  244. fldcw [DSF.savCntrl] ; load old control word
  245. fwait
  246. retn
  247. lab checkrng
  248. mov ax, word ptr [LocalFac+6] ; get exponent part
  249. and ax, 07ff0h
  250. or ax, ax
  251. JSE haveunderflow
  252. cmp ax, 07ff0h
  253. JSE haveoverflow
  254. jmp checkinexact ; assume possibly inexact result
  255. lab checkoverflow
  256. mov ax, word ptr [LocalFac+6] ; get exponent part
  257. and ax, 07ff0h
  258. cmp ax, 07ff0h
  259. JSE haveoverflow
  260. jmp checkinexact ; assume possibly inexact result
  261. lab haveunderflow
  262. mov [DSF.typ], UNDERFLOW
  263. fld IeeeAdjU
  264. fxch
  265. fscale
  266. fstp st(1)
  267. fld st(0)
  268. fabs
  269. fcomp [DblMin]
  270. fstsw ax
  271. sahf
  272. JSAE haveerror
  273. fmul [_zero]
  274. jmp short haveerror
  275. lab haveoverflow
  276. mov [DSF.typ], OVERFLOW
  277. fld IeeeAdjO
  278. fxch
  279. fscale
  280. fstp st(1)
  281. fld st(0)
  282. fabs
  283. fcomp [DblMax]
  284. fstsw ax
  285. sahf
  286. JSBE haveerror
  287. fmul [_infinity]
  288. lab haveerror
  289. ; fill error structure and call matherr
  290. push rsi ; save si
  291. push rdi
  292. mov rbx, [DSF.Function] ; get function jmp table address
  293. inc rbx
  294. mov [DSF.nam], rbx ; save name address
  295. ifmt <test cdispflags, INTRINFLAG>
  296. nomt <cmp [intrinflag], 0>
  297. JSNE aftercopy
  298. ;
  299. ; copy function args (for matherr structure)
  300. ;
  301. cld
  302. lea esi, [parm1]
  303. lea edi, [DSF.arg1]
  304. movsd
  305. movsd
  306. cmp [rbx-1].fnumarg, 1 ; check for 2nd parameter
  307. JSE aftercopy
  308. lea esi, [parm2]
  309. lea edi, [DSF.arg2]
  310. movsd
  311. movsd
  312. lab aftercopy
  313. lab useretval
  314. fstp [DSF.retval] ; store return value
  315. ;
  316. ; If intrinsic calling convention, an 'fsave' is required
  317. ; before matherr starts doing any fp operations.
  318. ; (This needs to be documented.)
  319. lea rax, [DSF.typ]
  320. lea rbx, [DSF.savCntrl]
  321. push rbx
  322. push rax
  323. mov rbx, [DSF.function]
  324. mov al, [rbx].fnumber
  325. CBI
  326. push rax
  327. call _87except ; _fpexcept(&exception, &savedcw)
  328. ifndef _STDCALL
  329. add esp, 12 ; clear arguments if _cdecl.
  330. endif
  331. lab movretval
  332. pop rdi ; restore di
  333. pop rsi ; restore si
  334. fld [DSF.retval] ; this assumes that the user
  335. ; does not want to return a
  336. ; signaling NaN
  337. jmp restoreCW ; restore CW and return
  338. _ctrandisp2 endp
  339. ;*
  340. ;* One arg standard dispatch.
  341. ;*
  342. _ctrandisp1 proc uses ebx, parm1:qword
  343. local DLSF[DSFISize]:IWORD
  344. ifmt <local MTSF[MTSFISize]:IWORD>
  345. push dword ptr [parm1+4] ; load arg1
  346. push dword ptr [parm1]
  347. call _fload
  348. ifndef _STDCALL
  349. add esp, 8
  350. endif
  351. fstcw [DSF.savCntrl]
  352. ifmt <and [cdispflags],(NOT TWOARGFLAG)>
  353. call _trandisp1
  354. call ctranexit
  355. ifdef _STDCALL
  356. ret 8
  357. else
  358. ret
  359. endif
  360. _ctrandisp1 endp
  361. ;
  362. ; Load arg in the fp stack without raising an exception if the argument
  363. ; is a signaling NaN
  364. ;
  365. _fload proc uses ebx, parm:qword
  366. local tmp:tbyte
  367. mov ax, word ptr [parm+6] ; get exponent field
  368. mov bx, ax ; save it
  369. and ax, 07ff0h
  370. cmp ax, 07ff0h ; check for special exponent
  371. JSNE fpload
  372. ; have special argument (NaN or INF)
  373. or bx, 07fffh ; preserve sign, set max long double exp
  374. mov word ptr [tmp+8], bx
  375. ; convert to long double
  376. mov eax, dword ptr [parm+4]
  377. mov ebx, dword ptr [parm]
  378. shld eax, ebx, 11
  379. ; the MSB of the significand is
  380. ; already 1 because of the exponent value
  381. mov dword ptr [tmp+4], eax
  382. mov dword ptr [tmp], ebx
  383. fld tmp
  384. jmp short return
  385. lab fpload
  386. fld parm
  387. lab return
  388. ifdef _STDCALL
  389. ret 8
  390. else
  391. ret
  392. endif
  393. _fload endp
  394. end