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.

311 lines
8.2 KiB

  1. .file "logb.s"
  2. // Copyright (c) 2000, 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. // 2/16/00 Modified to conform to C9X
  30. // 3/16/00 Improved speed
  31. // 4/04/00 Unwind support added
  32. // 5/30/00 Fixed bug when x double-extended denormal
  33. // 8/15/00 Bundle added after call to __libm_error_support to properly
  34. // set [the previously overwritten] GR_Parameter_RESULT.
  35. //
  36. // API
  37. //==============================================================
  38. // double _logb( double x);
  39. //
  40. // Overview of operation
  41. //==============================================================
  42. // The logb function extracts the exponent of x as an integer in
  43. // floating-point format.
  44. // logb computes log2 of x as a double
  45. //
  46. // logb is similar to ilogb but differs in the following ways:
  47. // +-inf
  48. // ilogb: returns INT_MAX
  49. // logb: returns +inf
  50. // Nan returns FP_LOGBNAN (which is either INT_MAX or INT_MIN)
  51. // ilogb: returns INT_MAX (7fffffff)
  52. // logb: returns QNAN (quietized SNAN)
  53. // 0 returns FP_ILOGB0 (which is either INT_MIN or -INT_MAX)
  54. // ilogb: returns -INT_MAX (80000001)
  55. // logb: returns -inf, raises the divide-by-zero exception,
  56. // and calls libm_error_support to set domain error
  57. //
  58. // Registers used
  59. //==============================================================
  60. // general registers used:
  61. // ar.pfs r32
  62. // r33 -> r37
  63. // r38 -> r41 used as parameters to error path
  64. //
  65. // predicate registers used:
  66. // p6, p7, p8
  67. // floating-point registers used:
  68. // f9, f10, f11
  69. // f8, input
  70. GR_SAVE_B0 = r34
  71. GR_SAVE_GP = r35
  72. GR_SAVE_PFS = r32
  73. GR_Parameter_X = r38
  74. GR_Parameter_Y = r39
  75. GR_Parameter_RESULT = r40
  76. .align 32
  77. .global _logb#
  78. .section .text
  79. .proc _logb#
  80. .align 32
  81. _logb:
  82. // qnan snan inf norm unorm 0 -+
  83. // 0 0 0 0 1 0 11
  84. // 0 b
  85. { .mfi
  86. alloc r32=ar.pfs,1,5,4,0
  87. (p0) fclass.m.unc p8,p0 = f8, 0x0b
  88. nop.i 999
  89. }
  90. // X NORMAL
  91. // r37 = exp(f8) - - 0xffff
  92. // sig(f8) = r37
  93. // f8 = convert_to_fp (sig))
  94. { .mfi
  95. (p0) getf.exp r35 = f8
  96. (p0) fnorm f10=f8
  97. nop.i 999 ;;
  98. }
  99. // qnan snan inf norm unorm 0 -+
  100. // 1 1 1 0 0 0 11
  101. // e 3
  102. { .mmf
  103. (p0) mov r33 = 0xffff
  104. (p0) mov r34 = 0x1ffff
  105. (p0) fclass.m.unc p6,p0 = f8, 0xe3 ;;
  106. }
  107. { .mfb
  108. (p0) and r36 = r35, r34
  109. (p0) fclass.m.unc p7,p0 = f8, 0x07
  110. (p8) br.cond.spnt LOGB_DENORM ;;
  111. }
  112. { .mib
  113. (p0) sub r37 = r36, r33
  114. nop.i 999
  115. (p6) br.cond.spnt LOGB_NAN_INF ;;
  116. }
  117. { .mib
  118. (p0) setf.sig f9 = r37
  119. nop.i 999
  120. (p7) br.cond.spnt LOGB_ZERO ;;
  121. }
  122. { .mfi
  123. nop.m 999
  124. (p0) fcvt.xf f10 = f9
  125. nop.i 999 ;;
  126. }
  127. { .mfb
  128. nop.m 999
  129. (p0) fnorm.d f8 = f10
  130. (p0) br.ret.sptk b0 ;;
  131. }
  132. LOGB_DENORM:
  133. // Form signexp of 2^64 in case need to scale denormal
  134. // Check to see if double-extended denormal
  135. { .mfi
  136. (p0) mov r38 = 0x1003f
  137. (p0) fclass.m.unc p8,p0 = f10, 0x0b
  138. nop.i 999 ;;
  139. }
  140. // Form 2^64 in case need to scale denormal
  141. { .mfi
  142. (p0) setf.exp f11 = r38
  143. nop.f 999
  144. nop.i 999 ;;
  145. }
  146. // If double-extended denormal add 64 to exponent bias for scaling
  147. // If double-extended denormal form x * 2^64 which is normal
  148. { .mfi
  149. (p8) add r33 = 64, r33
  150. (p8) fmpy f10 = f10, f11
  151. nop.i 999 ;;
  152. }
  153. // Logic is the same as normal path but use normalized input
  154. { .mmi
  155. (p0) getf.exp r35 = f10 ;;
  156. nop.m 999
  157. nop.i 999 ;;
  158. }
  159. { .mmi
  160. (p0) and r36 = r35, r34 ;;
  161. (p0) sub r37 = r36, r33
  162. nop.i 999 ;;
  163. }
  164. { .mmi
  165. (p0) setf.sig f9 = r37
  166. nop.m 999
  167. nop.i 999 ;;
  168. }
  169. { .mfi
  170. nop.m 999
  171. (p0) fcvt.xf f10 = f9
  172. nop.i 999 ;;
  173. }
  174. { .mfb
  175. nop.m 999
  176. (p0) fnorm.d f8 = f10
  177. (p0) br.ret.sptk b0 ;;
  178. }
  179. LOGB_NAN_INF:
  180. // X NAN or INFINITY, return f8 * f8
  181. { .mfb
  182. nop.m 999
  183. (p0) fma.d f8= f8,f8,f0
  184. (p0) br.ret.sptk b0 ;;
  185. }
  186. .endp _logb#
  187. // Stack operations when calling error support.
  188. // (1) (2) (3) (call) (4)
  189. // sp -> + psp -> + psp -> + sp -> +
  190. // | | | |
  191. // | | <- GR_Y R3 ->| <- GR_RESULT | -> f8
  192. // | | | |
  193. // | <-GR_Y Y2->| Y2 ->| <- GR_Y |
  194. // | | | |
  195. // | | <- GR_X X1 ->| |
  196. // | | | |
  197. // sp-64 -> + sp -> + sp -> + +
  198. // save ar.pfs save b0 restore gp
  199. // save gp restore ar.pfs
  200. .proc __libm_error_region
  201. __libm_error_region:
  202. LOGB_ZERO:
  203. .prologue
  204. // f9 = |f8|
  205. // f10 = -f9 = -|f8|
  206. // f9 = 1.0/f10 = -1.0/-|f8|
  207. { .mfi
  208. mov r41 = 151 // Error code
  209. (p0) fmerge.s f9 = f0,f8
  210. nop.i 999
  211. }
  212. ;;
  213. { .mfi
  214. nop.m 999
  215. fmerge.ns f10 = f0,f9
  216. nop.i 999
  217. }
  218. ;;
  219. // (1)
  220. { .mfi
  221. add GR_Parameter_Y=-32,sp // Parameter 2 value
  222. frcpa f9,p6 = f1,f10
  223. .save ar.pfs,GR_SAVE_PFS
  224. mov GR_SAVE_PFS=ar.pfs // Save ar.pfs
  225. }
  226. { .mfi
  227. .fframe 64
  228. add sp=-64,sp // Create new stack
  229. nop.f 0
  230. mov GR_SAVE_GP=gp // Save gp
  231. };;
  232. // (2)
  233. { .mmi
  234. stfd [GR_Parameter_Y] = f0,16 // STORE Parameter 2 on stack
  235. add GR_Parameter_X = 16,sp // Parameter 1 address
  236. .save b0, GR_SAVE_B0
  237. mov GR_SAVE_B0=b0 // Save b0
  238. };;
  239. .body
  240. // (3)
  241. { .mib
  242. stfd [GR_Parameter_X] = f8 // STORE Parameter 1 on stack
  243. add GR_Parameter_RESULT = 0,GR_Parameter_Y // Parameter 3 address
  244. nop.b 0
  245. }
  246. { .mib
  247. stfd [GR_Parameter_Y] = f9 // Store Parameter 3 on stack
  248. add GR_Parameter_Y = -16,GR_Parameter_Y
  249. br.call.sptk b0=__libm_error_support# // Call error handling function
  250. };;
  251. { .mmi
  252. nop.m 0
  253. nop.m 0
  254. add GR_Parameter_RESULT = 48,sp
  255. };;
  256. // (4)
  257. { .mmi
  258. ldfd f8 = [GR_Parameter_RESULT] // Get return result off stack
  259. .restore
  260. add sp = 64,sp // Restore stack pointer
  261. mov b0 = GR_SAVE_B0 // Restore return address
  262. };;
  263. { .mib
  264. mov gp = GR_SAVE_GP // Restore gp
  265. mov ar.pfs = GR_SAVE_PFS // Restore ar.pfs
  266. br.ret.sptk b0
  267. };;
  268. .endp __libm_error_region
  269. .type __libm_error_support#,@function
  270. .global __libm_error_support#