Leaked source code of windows server 2003
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.

363 lines
7.9 KiB

  1. .file "ldexp.s"
  2. // Copyright (c) 2000, 2001, Intel Corporation
  3. // All rights reserved.
  4. //
  5. // Contributed 2/2/2000 by John Harrison, Ted Kubaska, Bob Norin, Shane Story,
  6. // and Ping Tak Peter Tang of the Computational Software Lab, Intel Corporation.
  7. //
  8. // WARRANTY DISCLAIMER
  9. //
  10. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  11. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  12. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  13. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
  14. // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  15. // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  16. // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  17. // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  18. // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
  19. // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  20. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  21. //
  22. // Intel Corporation is the author of this code, and requests that all
  23. // problem reports or change requests be submitted to it directly at
  24. // http://developer.intel.com/opensource.
  25. //
  26. // History
  27. //==============================================================
  28. // 2/02/00 Initial version
  29. // 1/26/01 ldex pcompletely reworked and now standalone version
  30. //
  31. // API
  32. //==============================================================
  33. // double = ldexp (double x, int n)
  34. // input floating point f8 and int n (r33)
  35. // output floating point f8
  36. //
  37. // Returns x* 2**n using an fma and detects overflow
  38. // and underflow.
  39. //
  40. //
  41. FR_Big = f6
  42. FR_NBig = f7
  43. FR_Floating_X = f8
  44. FR_Result = f8
  45. FR_Result2 = f9
  46. FR_Result3 = f11
  47. FR_Norm_X = f12
  48. FR_Two_N = f14
  49. FR_Two_to_Big = f15
  50. GR_N_Biased = r15
  51. GR_Big = r16
  52. GR_NBig = r17
  53. GR_Scratch = r18
  54. GR_Scratch1 = r19
  55. GR_Bias = r20
  56. GR_N_as_int = r21
  57. GR_SAVE_B0 = r32
  58. GR_SAVE_GP = r33
  59. GR_SAVE_PFS = r34
  60. GR_Parameter_X = r35
  61. GR_Parameter_Y = r36
  62. GR_Parameter_RESULT = r37
  63. GR_Tag = r38
  64. .align 32
  65. .global ldexp
  66. .section .text
  67. .proc ldexp
  68. .align 32
  69. ldexp:
  70. //
  71. // Is x NAN, INF, ZERO, +-?
  72. // Build the exponent Bias
  73. //
  74. { .mfi
  75. alloc r32=ar.pfs,1,2,4,0
  76. fclass.m.unc p7,p0 = FR_Floating_X, 0xe7 //@snan | @qnan | @inf | @zero
  77. addl GR_Bias = 0x0FFFF,r0
  78. }
  79. //
  80. // Sign extend input
  81. // Is N zero?
  82. // Normalize x
  83. //
  84. { .mfi
  85. cmp.eq.unc p6,p0 = r33,r0
  86. fnorm.s1 FR_Norm_X = FR_Floating_X
  87. sxt4 GR_N_as_int = r33
  88. }
  89. ;;
  90. //
  91. // Normalize x
  92. // Branch and return special values.
  93. // Create -35000
  94. // Create 35000
  95. //
  96. { .mfi
  97. addl GR_Big = 35000,r0
  98. nop.f 0
  99. add GR_N_Biased = GR_Bias,GR_N_as_int
  100. }
  101. { .mfb
  102. addl GR_NBig = -35000,r0
  103. (p7) fma.d.s0 FR_Result = FR_Floating_X,f1, f0
  104. (p7) br.ret.spnt b0
  105. };;
  106. //
  107. // Build the exponent Bias
  108. // Return x when N = 0
  109. //
  110. { .mfi
  111. setf.exp FR_Two_N = GR_N_Biased
  112. nop.f 0
  113. addl GR_Scratch1 = 0x063BF,r0
  114. }
  115. { .mfb
  116. addl GR_Scratch = 0x019C3F,r0
  117. (p6) fma.d.s0 FR_Result = FR_Floating_X,f1, f0
  118. (p6) br.ret.spnt b0
  119. };;
  120. //
  121. // Create 2*big
  122. // Create 2**-big
  123. // Is N > 35000
  124. // Is N < -35000
  125. // Raise Denormal operand flag with compare
  126. // Main path, create 2**N
  127. //
  128. { .mfi
  129. setf.exp FR_NBig = GR_Scratch1
  130. nop.f 0
  131. cmp.ge.unc p6, p0 = GR_N_as_int, GR_Big
  132. }
  133. { .mfi
  134. setf.exp FR_Big = GR_Scratch
  135. fcmp.ge.s0 p0,p11 = FR_Floating_X,f0
  136. cmp.le.unc p8, p0 = GR_N_as_int, GR_NBig
  137. };;
  138. //
  139. // Adjust 2**N if N was very small or very large
  140. //
  141. { .mfi
  142. nop.m 0
  143. (p6) fma.s1 FR_Two_N = FR_Big,f1,f0
  144. nop.i 0
  145. }
  146. { .mlx
  147. nop.m 999
  148. movl GR_Scratch = 0x00000000000303FF
  149. };;
  150. { .mfi
  151. nop.m 0
  152. (p8) fma.s1 FR_Two_N = FR_NBig,f1,f0
  153. nop.i 0
  154. }
  155. { .mlx
  156. nop.m 999
  157. movl GR_Scratch1= 0x00000000000103FF
  158. };;
  159. // Set up necessary status fields
  160. //
  161. // S0 user supplied status
  162. // S2 user supplied status + WRE + TD (Overflows)
  163. // S3 user supplied status + FZ + TD (Underflows)
  164. //
  165. { .mfi
  166. nop.m 999
  167. fsetc.s3 0x7F,0x41
  168. nop.i 999
  169. }
  170. { .mfi
  171. nop.m 999
  172. fsetc.s2 0x7F,0x42
  173. nop.i 999
  174. };;
  175. //
  176. // Do final operation
  177. //
  178. { .mfi
  179. setf.exp FR_NBig = GR_Scratch
  180. fma.d.s0 FR_Result = FR_Two_N,FR_Norm_X,f0
  181. nop.i 999
  182. }
  183. { .mfi
  184. nop.m 999
  185. fma.d.s3 FR_Result3 = FR_Two_N,FR_Norm_X,f0
  186. nop.i 999
  187. };;
  188. { .mfi
  189. setf.exp FR_Big = GR_Scratch1
  190. fma.d.s2 FR_Result2 = FR_Two_N,FR_Norm_X,f0
  191. nop.i 999
  192. };;
  193. //
  194. // Check for overflow or underflow.
  195. // Restore s3
  196. // Restore s2
  197. //
  198. { .mfi
  199. nop.m 0
  200. fsetc.s3 0x7F,0x40
  201. nop.i 999
  202. }
  203. { .mfi
  204. nop.m 0
  205. fsetc.s2 0x7F,0x40
  206. nop.i 999
  207. };;
  208. //
  209. // Is the result zero?
  210. //
  211. { .mfi
  212. nop.m 999
  213. fclass.m.unc p6, p0 = FR_Result3, 0x007
  214. nop.i 999
  215. }
  216. { .mfi
  217. addl GR_Tag = 146, r0
  218. fcmp.ge.unc.s1 p7, p8 = FR_Result2 , FR_Big
  219. nop.i 0
  220. };;
  221. //
  222. // Detect masked underflow - Tiny + Inexact Only
  223. //
  224. { .mfi
  225. nop.m 999
  226. (p6) fcmp.neq.unc.s1 p6, p0 = FR_Result , FR_Result2
  227. nop.i 999
  228. };;
  229. //
  230. // Is result bigger the allowed range?
  231. // Branch out for underflow
  232. //
  233. { .mfb
  234. (p6) addl GR_Tag = 147, r0
  235. (p8) fcmp.le.unc.s1 p9, p10 = FR_Result2 , FR_NBig
  236. (p6) br.cond.spnt LDEXP_UNDERFLOW
  237. };;
  238. //
  239. // Branch out for overflow
  240. //
  241. { .mbb
  242. nop.m 0
  243. (p7) br.cond.spnt LDEXP_OVERFLOW
  244. (p9) br.cond.spnt LDEXP_OVERFLOW
  245. };;
  246. //
  247. // Return from main path.
  248. //
  249. { .mfb
  250. nop.m 999
  251. nop.f 0
  252. br.ret.sptk b0;;
  253. }
  254. .endp ldexp
  255. .proc __libm_error_region
  256. __libm_error_region:
  257. LDEXP_OVERFLOW:
  258. LDEXP_UNDERFLOW:
  259. //
  260. // Get stack address of N
  261. //
  262. .prologue
  263. { .mfi
  264. add GR_Parameter_Y=-32,sp
  265. nop.f 0
  266. .save ar.pfs,GR_SAVE_PFS
  267. mov GR_SAVE_PFS=ar.pfs
  268. }
  269. //
  270. // Adjust sp
  271. //
  272. { .mfi
  273. .fframe 64
  274. add sp=-64,sp
  275. nop.f 0
  276. mov GR_SAVE_GP=gp
  277. };;
  278. //
  279. // Store N on stack in correct position
  280. // Locate the address of x on stack
  281. //
  282. { .mmi
  283. st8 [GR_Parameter_Y] = GR_N_as_int,16
  284. add GR_Parameter_X = 16,sp
  285. .save b0, GR_SAVE_B0
  286. mov GR_SAVE_B0=b0
  287. };;
  288. //
  289. // Store x on the stack.
  290. // Get address for result on stack.
  291. //
  292. .body
  293. { .mib
  294. stfd [GR_Parameter_X] = FR_Norm_X
  295. add GR_Parameter_RESULT = 0,GR_Parameter_Y
  296. nop.b 0
  297. }
  298. { .mib
  299. stfd [GR_Parameter_Y] = FR_Result
  300. add GR_Parameter_Y = -16,GR_Parameter_Y
  301. br.call.sptk b0=__libm_error_support#
  302. };;
  303. //
  304. // Get location of result on stack
  305. //
  306. { .mmi
  307. nop.m 0
  308. nop.m 0
  309. add GR_Parameter_RESULT = 48,sp
  310. };;
  311. //
  312. // Get the new result
  313. //
  314. { .mmi
  315. ldfd FR_Result = [GR_Parameter_RESULT]
  316. .restore
  317. add sp = 64,sp
  318. mov b0 = GR_SAVE_B0
  319. };;
  320. //
  321. // Restore gp, ar.pfs and return
  322. //
  323. { .mib
  324. mov gp = GR_SAVE_GP
  325. mov ar.pfs = GR_SAVE_PFS
  326. br.ret.sptk b0
  327. };;
  328. .endp __libm_error_region
  329. .type __libm_error_support#,@function
  330. .global __libm_error_support#