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.

428 lines
10 KiB

  1. .file "ldexp.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. // 4/04/00 Unwind support added
  30. // 5/22/00 rewritten to not take swa and be a little faster
  31. // 8/15/00 Bundle added after call to __libm_error_support to properly
  32. // set [the previously overwritten] GR_Parameter_RESULT.
  33. //12/07/00 Removed code that prevented call to __libm_error_support.
  34. // Stored r33 instead of f9 as Parameter 2 for call to
  35. // __libm_error_support.
  36. //
  37. // API
  38. //==============================================================
  39. // double = ldexp (double x, int n)
  40. // input floating point f8 and integer r33
  41. // output floating point f8
  42. //
  43. // returns x* 2**n computed by exponent
  44. // manipulation rather than by actually performing an
  45. // exponentiation or a multiplication.
  46. //
  47. // Overview of operation
  48. //==============================================================
  49. //
  50. // ldexp:
  51. // p7 is set if x is nan, inf, zero; go to x_nan_inf_zero
  52. // sign extend r33
  53. // norm_f8 = fnorm(f8)
  54. // get exponent of norm_f8
  55. // add to r33 to get new exponent
  56. // p6, new_exponent > 103fe => overflow
  57. // p7, new_exponent > fbcd => underflow
  58. // setf new_exponent, merge significand, normalize, return
  59. ldexp_float_int_f9 = f10
  60. ldexp_int_f9 = f11
  61. ldexp_max_exp = f12
  62. ldexp_neg_max_exp = f13
  63. ldexp_new_f9 = f14
  64. LDEXP_BIG = f32
  65. LDEXP_NORM_F8 = f33
  66. LDEXP_FFFF = f34
  67. LDEXP_BIG_SIGN = f35
  68. LDEXP_13FFE = f36
  69. LDEXP_INV_BIG_SIGN = f37
  70. // general registers used
  71. // r32 has ar.pfs
  72. // r33 has input integer
  73. ldexp_GR_signexp = r34
  74. ldexp_GR_13FFE = r35
  75. ldexp_GR_new_exponent = r36
  76. ldexp_GE_FBCD = r37
  77. ldexp_GR_17ones = r38
  78. GR_SAVE_B0 = r39
  79. GR_SAVE_GP = r40
  80. GR_SAVE_PFS = r41
  81. ldexp_GR_exponent = r42
  82. ldexp_GR_103FE = r43
  83. ldexp_GR_FFFF = r44
  84. GR_Parameter_X = r45
  85. GR_Parameter_Y = r46
  86. GR_Parameter_RESULT = r47
  87. ldexp_GR_tag = r48
  88. .global ldexp
  89. // ===============================================================
  90. // LDEXP
  91. // ===============================================================
  92. .text
  93. .proc ldexp
  94. .align 32
  95. // Be sure to sign extend r33 because the
  96. // integer comes in as 32-bits
  97. ldexp:
  98. // x NAN, INF, ZERO, +-
  99. { .mfi
  100. alloc r32=ar.pfs,1,12,4,0
  101. fclass.m.unc p7,p0 = f8, 0xe7 //@qnan | @snan | @inf | @zero
  102. sxt4 r33 = r33
  103. }
  104. ;;
  105. { .mfi
  106. nop.m 999
  107. fnorm LDEXP_NORM_F8 = f8
  108. nop.i 999
  109. }
  110. { .mbb
  111. nop.m 999
  112. (p7) br.cond.spnt LDEXP_X_NAN_INF_ZERO
  113. nop.b 999
  114. }
  115. ;;
  116. // LDEXP_BIG gets a big number, enough to overflow an frcpa
  117. // but not take an architecturally mandated swa.
  118. // We construct this constant rather than load it.
  119. { .mlx
  120. mov ldexp_GR_17ones = 0x1FFFF
  121. movl ldexp_GR_FFFF = 0xffffffffffffffff
  122. }
  123. { .mfi
  124. addl ldexp_GR_13FFE = 0x13ffe, r0
  125. nop.f 999
  126. nop.i 999
  127. }
  128. ;;
  129. { .mmb
  130. setf.exp LDEXP_13FFE = ldexp_GR_13FFE
  131. setf.sig LDEXP_FFFF = ldexp_GR_FFFF
  132. nop.b 999
  133. }
  134. ;;
  135. { .mfi
  136. nop.m 999
  137. fmerge.se LDEXP_BIG = LDEXP_13FFE, LDEXP_FFFF
  138. nop.i 999
  139. }
  140. // Put the absolute normalized exponent in ldexp_GR_new_exponent
  141. // Assuming that the input int is in r33.
  142. // ldexp_GR_new_exponent gets the input int + the exponent of the input double
  143. { .mfi
  144. getf.exp ldexp_GR_signexp = LDEXP_NORM_F8
  145. nop.f 999
  146. nop.i 999
  147. }
  148. ;;
  149. { .mii
  150. nop.m 999
  151. nop.i 999
  152. and ldexp_GR_exponent = ldexp_GR_signexp, ldexp_GR_17ones
  153. }
  154. ;;
  155. // HUGE
  156. // Put big number in ldexp_GR_103FE
  157. // If ldexp_GR_new_exponent is bigger than ldexp_GR_103FE
  158. // Return a big number of the same sign
  159. // double: largest double exponent is 7fe (double-biased)
  160. // 103fe (register-biased)
  161. // f11 gets the big value in f9 with the f8 sign
  162. // For single,
  163. // single: largest single exponent is fe (single-biased)
  164. // fe - 7f + ffff = 1007e
  165. { .mii
  166. add ldexp_GR_new_exponent = ldexp_GR_exponent, r33
  167. addl ldexp_GR_103FE = 0x103fe, r0
  168. nop.i 999
  169. }
  170. ;;
  171. { .mfi
  172. setf.exp f12 = ldexp_GR_new_exponent
  173. nop.f 999
  174. cmp.gt.unc p6,p0 = ldexp_GR_new_exponent, ldexp_GR_103FE
  175. }
  176. ;;
  177. { .mfb
  178. nop.m 999
  179. (p6) fmerge.s LDEXP_BIG_SIGN = f8, LDEXP_BIG
  180. nop.b 999
  181. }
  182. ;;
  183. { .mfi
  184. nop.m 999
  185. (p6) fma.d f12 = LDEXP_BIG_SIGN, LDEXP_BIG, f0
  186. (p6) mov ldexp_GR_tag = 146
  187. }
  188. { .mib
  189. nop.m 999
  190. nop.i 999
  191. (p6) br.spnt LDEXP_HUGE
  192. }
  193. ;;
  194. // TINY
  195. // Put a small number in ldexp_GE_FBCD
  196. // If ldexp_GR_new_exponent is less than ldexp_GE_FBCD
  197. // Return a small number of the same sign
  198. // double:
  199. // 0xfbcd is -1074 unbiased, which is the exponent
  200. // of the smallest double denormal
  201. // single
  202. // 0xff6a is -149 unbiased which is the exponent
  203. // of the smallest single denormal
  204. //
  205. // Take the large value in f9 and put in f10 with
  206. // the sign of f8. Then take reciprocal in f11
  207. { .mfi
  208. addl ldexp_GE_FBCD = 0xfbcd, r0
  209. nop.f 999
  210. nop.i 999
  211. }
  212. ;;
  213. { .mfi
  214. nop.m 999
  215. nop.f 999
  216. cmp.lt.unc p7,p0 = ldexp_GR_new_exponent, ldexp_GE_FBCD
  217. }
  218. ;;
  219. { .mfi
  220. nop.m 999
  221. (p7) fmerge.s LDEXP_BIG_SIGN = f8, LDEXP_BIG
  222. nop.i 999
  223. }
  224. ;;
  225. { .mfi
  226. nop.m 999
  227. (p7) frcpa.s1 LDEXP_INV_BIG_SIGN,p10 = f1,LDEXP_BIG_SIGN
  228. nop.i 999
  229. }
  230. ;;
  231. { .mfi
  232. nop.m 999
  233. (p7) fnorm.d f12 = LDEXP_INV_BIG_SIGN
  234. (p7) mov ldexp_GR_tag = 147
  235. }
  236. { .mib
  237. nop.m 999
  238. nop.i 999
  239. (p7) br.spnt LDEXP_TINY
  240. }
  241. ;;
  242. // CALCULATION
  243. // Put exponent of answer in f12
  244. // f10 has the normalized f8
  245. // f13 = exp(f12) sig(f10)
  246. // f14 = sign(f8) expsig(f13)
  247. { .mfi
  248. nop.m 999
  249. fmerge.se f13 = f12,LDEXP_NORM_F8
  250. nop.i 999
  251. }
  252. ;;
  253. { .mfi
  254. nop.m 999
  255. fmerge.s f14 = f8,f13
  256. nop.i 999
  257. }
  258. ;;
  259. { .mfb
  260. nop.m 999
  261. fnorm.d f8 = f14
  262. br.ret.sptk b0
  263. }
  264. ;;
  265. LDEXP_N_NAN_INF:
  266. // Is n a NAN?
  267. { .mfi
  268. nop.m 999
  269. (p0) fclass.m.unc p6,p0 = f9, 0xc3 //@snan | @qnan
  270. nop.i 999
  271. }
  272. ;;
  273. { .mfi
  274. nop.m 999
  275. (p6) fma.d f8 = f8,f9,f0
  276. nop.i 999
  277. }
  278. // Is n +INF?
  279. { .mfi
  280. nop.m 999
  281. (p0) fclass.m.unc p7,p0 = f9, 0x21 //@inf | @pos
  282. nop.i 999
  283. }
  284. ;;
  285. { .mfi
  286. nop.m 999
  287. (p7) fma.d f8 = f8,f9,f0
  288. nop.i 999
  289. }
  290. // Is n -inf?
  291. { .mfi
  292. nop.m 999
  293. fclass.m.unc p8,p9 = f9, 0x22 //@inf | @neg
  294. nop.i 999
  295. }
  296. ;;
  297. { .mfb
  298. nop.m 999
  299. (p8) frcpa f8,p6 = f8,f9
  300. br.ret.sptk b0
  301. }
  302. ;;
  303. LDEXP_X_NAN_INF_ZERO:
  304. { .mfb
  305. nop.m 999
  306. fnorm.d f8 = f8 // quietize
  307. br.ret.sptk b0
  308. }
  309. ;;
  310. .endp ldexp
  311. .proc __libm_error_region
  312. __libm_error_region:
  313. LDEXP_HUGE:
  314. LDEXP_TINY:
  315. .prologue
  316. { .mfi
  317. add GR_Parameter_Y=-32,sp // Parameter 2 value
  318. nop.f 0
  319. .save ar.pfs,GR_SAVE_PFS
  320. mov GR_SAVE_PFS=ar.pfs // Save ar.pfs
  321. }
  322. { .mfi
  323. .fframe 64
  324. add sp=-64,sp // Create new stack
  325. nop.f 0
  326. mov GR_SAVE_GP=gp // Save gp
  327. };;
  328. { .mmi
  329. st8 [GR_Parameter_Y] = r33,16 // STORE Parameter 2 on stack
  330. add GR_Parameter_X = 16,sp // Parameter 1 address
  331. .save b0, GR_SAVE_B0
  332. mov GR_SAVE_B0=b0 // Save b0
  333. };;
  334. .body
  335. { .mib
  336. stfd [GR_Parameter_X] = f8 // STORE Parameter 1 on stack
  337. add GR_Parameter_RESULT = 0,GR_Parameter_Y // Parameter 3 address
  338. nop.b 0
  339. }
  340. { .mib
  341. stfd [GR_Parameter_Y] = f12 // STORE Parameter 3 on stack
  342. add GR_Parameter_Y = -16,GR_Parameter_Y
  343. br.call.sptk b0=__libm_error_support# // Call error handling function
  344. };;
  345. { .mmi
  346. nop.m 0
  347. nop.m 0
  348. add GR_Parameter_RESULT = 48,sp
  349. };;
  350. { .mmi
  351. ldfd f8 = [GR_Parameter_RESULT] // Get return result off stack
  352. .restore
  353. add sp = 64,sp // Restore stack pointer
  354. mov b0 = GR_SAVE_B0 // Restore return address
  355. };;
  356. { .mib
  357. mov gp = GR_SAVE_GP // Restore gp
  358. mov ar.pfs = GR_SAVE_PFS // Restore ar.pfs
  359. br.ret.sptk b0 // Return
  360. };;
  361. .endp __libm_error_region
  362. .type __libm_error_support#,@function
  363. .global __libm_error_support#