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.

427 lines
10 KiB

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