fp_util.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:36k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * fp_util.S
  3.  *
  4.  * Copyright Roman Zippel, 1997.  All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, and the entire permission notice in its entirety,
  11.  *    including the disclaimer of warranties.
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in the
  14.  *    documentation and/or other materials provided with the distribution.
  15.  * 3. The name of the author may not be used to endorse or promote
  16.  *    products derived from this software without specific prior
  17.  *    written permission.
  18.  *
  19.  * ALTERNATIVELY, this product may be distributed under the terms of
  20.  * the GNU General Public License, in which case the provisions of the GPL are
  21.  * required INSTEAD OF the above restrictions.  (This clause is
  22.  * necessary due to a potential bad interaction between the GPL and
  23.  * the restrictions contained in a BSD-style copyright.)
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  26.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  27.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  28.  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  29.  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  30.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  31.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  33.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  35.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  36.  */
  37. #include <linux/config.h>
  38. #include "fp_emu.h"
  39. /*
  40.  * Here are lots of conversion and normalization functions mainly
  41.  * used by fp_scan.S
  42.  * Note that these functions are optimized for "normal" numbers,
  43.  * these are handled first and exit as fast as possible, this is
  44.  * especially important for fp_normalize_ext/fp_conv_ext2ext, as
  45.  * it's called very often.
  46.  * The register usage is optimized for fp_scan.S and which register
  47.  * is currently at that time unused, be careful if you want change
  48.  * something here. %d0 and %d1 is always usable, sometimes %d2 (or
  49.  * only the lower half) most function have to return the %a0
  50.  * unmodified, so that the caller can immediatly reuse it.
  51.  */
  52. .globl fp_ill, fp_end
  53. | exits from fp_scan:
  54. | illegal instruction
  55. fp_ill:
  56. printf ,"fp_illegaln"
  57. rts
  58. | completed instruction
  59. fp_end:
  60. tst.l (TASK_MM-8,%a2)
  61. jmi 1f
  62. tst.l (TASK_MM-4,%a2)
  63. jmi 1f
  64. tst.l (TASK_MM,%a2)
  65. jpl 2f
  66. 1: printf ,"oops:%p,%p,%pn",3,%a2@(TASK_MM-8),%a2@(TASK_MM-4),%a2@(TASK_MM)
  67. 2: clr.l %d0
  68. rts
  69. .globl fp_conv_long2ext, fp_conv_single2ext
  70. .globl fp_conv_double2ext, fp_conv_ext2ext
  71. .globl fp_normalize_ext, fp_normalize_double
  72. .globl fp_normalize_single, fp_normalize_single_fast
  73. .globl fp_conv_ext2double, fp_conv_ext2single
  74. .globl fp_conv_ext2long, fp_conv_ext2short
  75. .globl fp_conv_ext2byte
  76. .globl fp_finalrounding_single, fp_finalrounding_single_fast
  77. .globl fp_finalrounding_double
  78. .globl fp_finalrounding, fp_finaltest, fp_final
  79. /*
  80.  * First several conversion functions from a source operand
  81.  * into the extended format. Note, that only fp_conv_ext2ext
  82.  * normalizes the number and is always called after the other
  83.  * conversion functions, which only move the information into
  84.  * fp_ext structure.
  85.  */
  86. | fp_conv_long2ext:
  87. |
  88. | args: %d0 = source (32-bit long)
  89. | %a0 = destination (ptr to struct fp_ext)
  90. fp_conv_long2ext:
  91. printf PCONV,"l2e: %p -> %p(",2,%d0,%a0
  92. clr.l %d1 | sign defaults to zero
  93. tst.l %d0
  94. jeq fp_l2e_zero | is source zero?
  95. jpl 1f | positive?
  96. moveq #1,%d1
  97. neg.l %d0
  98. 1: swap %d1
  99. move.w #0x3fff+31,%d1
  100. move.l %d1,(%a0)+ | set sign / exp
  101. move.l %d0,(%a0)+ | set mantissa
  102. clr.l (%a0)
  103. subq.l #8,%a0 | restore %a0
  104. printx PCONV,%a0@
  105. printf PCONV,")n"
  106. rts
  107. | source is zero
  108. fp_l2e_zero:
  109. clr.l (%a0)+
  110. clr.l (%a0)+
  111. clr.l (%a0)
  112. subq.l #8,%a0
  113. printx PCONV,%a0@
  114. printf PCONV,")n"
  115. rts
  116. | fp_conv_single2ext
  117. | args: %d0 = source (single-precision fp value)
  118. | %a0 = dest (struct fp_ext *)
  119. fp_conv_single2ext:
  120. printf PCONV,"s2e: %p -> %p(",2,%d0,%a0
  121. move.l %d0,%d1
  122. lsl.l #8,%d0 | shift mantissa
  123. lsr.l #8,%d1 | exponent / sign
  124. lsr.l #7,%d1
  125. lsr.w #8,%d1
  126. jeq fp_s2e_small | zero / denormal?
  127. cmp.w #0xff,%d1 | NaN / Inf?
  128. jeq fp_s2e_large
  129. bset #31,%d0 | set explizit bit
  130. add.w #0x3fff-0x7f,%d1 | re-bias the exponent.
  131. 9: move.l %d1,(%a0)+ | fp_ext.sign, fp_ext.exp
  132. move.l %d0,(%a0)+ | high lword of fp_ext.mant
  133. clr.l (%a0) | low lword = 0
  134. subq.l #8,%a0
  135. printx PCONV,%a0@
  136. printf PCONV,")n"
  137. rts
  138. | zeros and denormalized
  139. fp_s2e_small:
  140. | exponent is zero, so explizit bit is already zero too
  141. tst.l %d0
  142. jeq 9b
  143. move.w #0x4000-0x7f,%d1
  144. jra 9b
  145. | infinities and NAN
  146. fp_s2e_large:
  147. bclr #31,%d0 | clear explizit bit
  148. move.w #0x7fff,%d1
  149. jra 9b
  150. fp_conv_double2ext:
  151. #ifdef FPU_EMU_DEBUG
  152. getuser.l %a1@(0),%d0,fp_err_ua2,%a1
  153. getuser.l %a1@(4),%d1,fp_err_ua2,%a1
  154. printf PCONV,"d2e: %p%p -> %p(",3,%d0,%d1,%a0
  155. #endif
  156. getuser.l (%a1)+,%d0,fp_err_ua2,%a1
  157. move.l %d0,%d1
  158. lsl.l #8,%d0 | shift high mantissa
  159. lsl.l #3,%d0
  160. lsr.l #8,%d1 | exponent / sign
  161. lsr.l #7,%d1
  162. lsr.w #5,%d1
  163. jeq fp_d2e_small | zero / denormal?
  164. cmp.w #0x7ff,%d1 | NaN / Inf?
  165. jeq fp_d2e_large
  166. bset #31,%d0 | set explizit bit
  167. add.w #0x3fff-0x3ff,%d1 | re-bias the exponent.
  168. 9: move.l %d1,(%a0)+ | fp_ext.sign, fp_ext.exp
  169. move.l %d0,(%a0)+
  170. getuser.l (%a1)+,%d0,fp_err_ua2,%a1
  171. move.l %d0,%d1
  172. lsl.l #8,%d0
  173. lsl.l #3,%d0
  174. move.l %d0,(%a0)
  175. moveq #21,%d0
  176. lsr.l %d0,%d1
  177. or.l %d1,-(%a0)
  178. subq.l #4,%a0
  179. printx PCONV,%a0@
  180. printf PCONV,")n"
  181. rts
  182. | zeros and denormalized
  183. fp_d2e_small:
  184. | exponent is zero, so explizit bit is already zero too
  185. tst.l %d0
  186. jeq 9b
  187. move.w #0x4000-0x3ff,%d1
  188. jra 9b
  189. | infinities and NAN
  190. fp_d2e_large:
  191. bclr #31,%d0 | clear explizit bit
  192. move.w #0x7fff,%d1
  193. jra 9b
  194. | fp_conv_ext2ext:
  195. | originally used to get longdouble from userspace, now it's
  196. | called before arithmetic operations to make sure the number
  197. | is normalized [maybe rename it?].
  198. | args: %a0 = dest (struct fp_ext *)
  199. | returns 0 in %d0 for a NaN, otherwise 1
  200. fp_conv_ext2ext:
  201. printf PCONV,"e2e: %p(",1,%a0
  202. printx PCONV,%a0@
  203. printf PCONV,"), "
  204. move.l (%a0)+,%d0
  205. cmp.w #0x7fff,%d0 | Inf / NaN?
  206. jeq fp_e2e_large
  207. move.l (%a0),%d0
  208. jpl fp_e2e_small | zero / denorm?
  209. | The high bit is set, so normalization is irrelevant.
  210. fp_e2e_checkround:
  211. subq.l #4,%a0
  212. #ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
  213. move.b (%a0),%d0
  214. jne fp_e2e_round
  215. #endif
  216. printf PCONV,"%p(",1,%a0
  217. printx PCONV,%a0@
  218. printf PCONV,")n"
  219. moveq #1,%d0
  220. rts
  221. #ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
  222. fp_e2e_round:
  223. fp_set_sr FPSR_EXC_INEX2
  224. clr.b (%a0)
  225. move.w (FPD_RND,FPDATA),%d2
  226. jne fp_e2e_roundother | %d2 == 0, round to nearest
  227. tst.b %d0 | test guard bit
  228. jpl 9f | zero is closer
  229. btst #0,(11,%a0) | test lsb bit
  230. jne fp_e2e_doroundup | round to infinity
  231. lsl.b #1,%d0 | check low bits
  232. jeq 9f | round to zero
  233. fp_e2e_doroundup:
  234. addq.l #1,(8,%a0)
  235. jcc 9f
  236. addq.l #1,(4,%a0)
  237. jcc 9f
  238. move.w #0x8000,(4,%a0)
  239. addq.w #1,(2,%a0)
  240. 9: printf PNORM,"%p(",1,%a0
  241. printx PNORM,%a0@
  242. printf PNORM,")n"
  243. rts
  244. fp_e2e_roundother:
  245. subq.w #2,%d2
  246. jcs 9b | %d2 < 2, round to zero
  247. jhi 1f | %d2 > 2, round to +infinity
  248. tst.b (1,%a0) | to -inf
  249. jne fp_e2e_doroundup | negative, round to infinity
  250. jra 9b | positive, round to zero
  251. 1: tst.b (1,%a0) | to +inf
  252. jeq fp_e2e_doroundup | positive, round to infinity
  253. jra 9b | negative, round to zero
  254. #endif
  255. | zeros and subnormals:
  256. | try to normalize these anyway.
  257. fp_e2e_small:
  258. jne fp_e2e_small1 | high lword zero?
  259. move.l (4,%a0),%d0
  260. jne fp_e2e_small2
  261. #ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
  262. clr.l %d0
  263. move.b (-4,%a0),%d0
  264. jne fp_e2e_small3
  265. #endif
  266. | Genuine zero.
  267. clr.w -(%a0)
  268. subq.l #2,%a0
  269. printf PNORM,"%p(",1,%a0
  270. printx PNORM,%a0@
  271. printf PNORM,")n"
  272. moveq #1,%d0
  273. rts
  274. | definitely subnormal, need to shift all 64 bits
  275. fp_e2e_small1:
  276. bfffo %d0{#0,#32},%d1
  277. move.w -(%a0),%d2
  278. sub.w %d1,%d2
  279. jcc 1f
  280. | Pathologically small, denormalize.
  281. add.w %d2,%d1
  282. clr.w %d2
  283. 1: move.w %d2,(%a0)+
  284. move.w %d1,%d2
  285. jeq fp_e2e_checkround
  286. | fancy 64-bit double-shift begins here
  287. lsl.l %d2,%d0
  288. move.l %d0,(%a0)+
  289. move.l (%a0),%d0
  290. move.l %d0,%d1
  291. lsl.l %d2,%d0
  292. move.l %d0,(%a0)
  293. neg.w %d2
  294. and.w #0x1f,%d2
  295. lsr.l %d2,%d1
  296. or.l %d1,-(%a0)
  297. #ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
  298. fp_e2e_extra1:
  299. clr.l %d0
  300. move.b (-4,%a0),%d0
  301. neg.w %d2
  302. add.w #24,%d2
  303. jcc 1f
  304. clr.b (-4,%a0)
  305. lsl.l %d2,%d0
  306. or.l %d0,(4,%a0)
  307. jra fp_e2e_checkround
  308. 1: addq.w #8,%d2
  309. lsl.l %d2,%d0
  310. move.b %d0,(-4,%a0)
  311. lsr.l #8,%d0
  312. or.l %d0,(4,%a0)
  313. #endif
  314. jra fp_e2e_checkround
  315. | pathologically small subnormal
  316. fp_e2e_small2:
  317. bfffo %d0{#0,#32},%d1
  318. add.w #32,%d1
  319. move.w -(%a0),%d2
  320. sub.w %d1,%d2
  321. jcc 1f
  322. | Beyond pathologically small, denormalize.
  323. add.w %d2,%d1
  324. clr.w %d2
  325. 1: move.w %d2,(%a0)+
  326. ext.l %d1
  327. jeq fp_e2e_checkround
  328. clr.l (4,%a0)
  329. sub.w #32,%d2
  330. jcs 1f
  331. lsl.l %d1,%d0 | lower lword needs only to be shifted
  332. move.l %d0,(%a0) | into the higher lword
  333. #ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
  334. clr.l %d0
  335. move.b (-4,%a0),%d0
  336. clr.b (-4,%a0)
  337. neg.w %d1
  338. add.w #32,%d1
  339. bfins %d0,(%a0){%d1,#8}
  340. #endif
  341. jra fp_e2e_checkround
  342. 1: neg.w %d1 | lower lword is splitted between
  343. bfins %d0,(%a0){%d1,#32} | higher and lower lword
  344. #ifndef CONFIG_M68KFPU_EMU_EXTRAPREC
  345. jra fp_e2e_checkround
  346. #else
  347. move.w %d1,%d2
  348. jra fp_e2e_extra1
  349. | These are extremely small numbers, that will mostly end up as zero
  350. | anyway, so this is only important for correct rounding.
  351. fp_e2e_small3:
  352. bfffo %d0{#24,#8},%d1
  353. add.w #40,%d1
  354. move.w -(%a0),%d2
  355. sub.w %d1,%d2
  356. jcc 1f
  357. | Pathologically small, denormalize.
  358. add.w %d2,%d1
  359. clr.w %d2
  360. 1: move.w %d2,(%a0)+
  361. ext.l %d1
  362. jeq fp_e2e_checkround
  363. cmp.w #8,%d1
  364. jcs 2f
  365. 1: clr.b (-4,%a0)
  366. sub.w #64,%d1
  367. jcs 1f
  368. add.w #24,%d1
  369. lsl.l %d1,%d0
  370. move.l %d0,(%a0)
  371. jra fp_e2e_checkround
  372. 1: neg.w %d1
  373. bfins %d0,(%a0){%d1,#8}
  374. jra fp_e2e_checkround
  375. 2: lsl.l %d1,%d0
  376. move.b %d0,(-4,%a0)
  377. lsr.l #8,%d0
  378. move.b %d0,(7,%a0)
  379. jra fp_e2e_checkround
  380. #endif
  381. 1: move.l %d0,%d1 | lower lword is splitted between
  382. lsl.l %d2,%d0 | higher and lower lword
  383. move.l %d0,(%a0)
  384. move.l %d1,%d0
  385. neg.w %d2
  386. add.w #32,%d2
  387. lsr.l %d2,%d0
  388. move.l %d0,-(%a0)
  389. jra fp_e2e_checkround
  390. | Infinities and NaNs
  391. fp_e2e_large:
  392. move.l (%a0)+,%d0
  393. jne 3f
  394. 1: tst.l (%a0)
  395. jne 4f
  396. moveq #1,%d0
  397. 2: subq.l #8,%a0
  398. printf PCONV,"%p(",1,%a0
  399. printx PCONV,%a0@
  400. printf PCONV,")n"
  401. rts
  402. | we have maybe a NaN, shift off the highest bit
  403. 3: lsl.l #1,%d0
  404. jeq 1b
  405. | we have a NaN, clear the return value
  406. 4: clrl %d0
  407. jra 2b
  408. /*
  409.  * Normalization functions.  Call these on the output of general
  410.  * FP operators, and before any conversion into the destination
  411.  * formats. fp_normalize_ext has always to be called first, the
  412.  * following conversion functions expect an already normalized
  413.  * number.
  414.  */
  415. | fp_normalize_ext:
  416. | normalize an extended in extended (unpacked) format, basically
  417. | it does the same as fp_conv_ext2ext, additionally it also does
  418. | the necessary postprocessing checks.
  419. | args: %a0 (struct fp_ext *)
  420. | NOTE: it does _not_ modify %a0/%a1 and the upper word of %d2
  421. fp_normalize_ext:
  422. printf PNORM,"ne: %p(",1,%a0
  423. printx PNORM,%a0@
  424. printf PNORM,"), "
  425. move.l (%a0)+,%d0
  426. cmp.w #0x7fff,%d0 | Inf / NaN?
  427. jeq fp_ne_large
  428. move.l (%a0),%d0
  429. jpl fp_ne_small | zero / denorm?
  430. | The high bit is set, so normalization is irrelevant.
  431. fp_ne_checkround:
  432. subq.l #4,%a0
  433. #ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
  434. move.b (%a0),%d0
  435. jne fp_ne_round
  436. #endif
  437. printf PNORM,"%p(",1,%a0
  438. printx PNORM,%a0@
  439. printf PNORM,")n"
  440. rts
  441. #ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
  442. fp_ne_round:
  443. fp_set_sr FPSR_EXC_INEX2
  444. clr.b (%a0)
  445. move.w (FPD_RND,FPDATA),%d2
  446. jne fp_ne_roundother | %d2 == 0, round to nearest
  447. tst.b %d0 | test guard bit
  448. jpl 9f | zero is closer
  449. btst #0,(11,%a0) | test lsb bit
  450. jne fp_ne_doroundup | round to infinity
  451. lsl.b #1,%d0 | check low bits
  452. jeq 9f | round to zero
  453. fp_ne_doroundup:
  454. addq.l #1,(8,%a0)
  455. jcc 9f
  456. addq.l #1,(4,%a0)
  457. jcc 9f
  458. addq.w #1,(2,%a0)
  459. move.w #0x8000,(4,%a0)
  460. 9: printf PNORM,"%p(",1,%a0
  461. printx PNORM,%a0@
  462. printf PNORM,")n"
  463. rts
  464. fp_ne_roundother:
  465. subq.w #2,%d2
  466. jcs 9b | %d2 < 2, round to zero
  467. jhi 1f | %d2 > 2, round to +infinity
  468. tst.b (1,%a0) | to -inf
  469. jne fp_ne_doroundup | negative, round to infinity
  470. jra 9b | positive, round to zero
  471. 1: tst.b (1,%a0) | to +inf
  472. jeq fp_ne_doroundup | positive, round to infinity
  473. jra 9b | negative, round to zero
  474. #endif
  475. | Zeros and subnormal numbers
  476. | These are probably merely subnormal, rather than "denormalized"
  477. |  numbers, so we will try to make them normal again.
  478. fp_ne_small:
  479. jne fp_ne_small1 | high lword zero?
  480. move.l (4,%a0),%d0
  481. jne fp_ne_small2
  482. #ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
  483. clr.l %d0
  484. move.b (-4,%a0),%d0
  485. jne fp_ne_small3
  486. #endif
  487. | Genuine zero.
  488. clr.w -(%a0)
  489. subq.l #2,%a0
  490. printf PNORM,"%p(",1,%a0
  491. printx PNORM,%a0@
  492. printf PNORM,")n"
  493. rts
  494. | Subnormal.
  495. fp_ne_small1:
  496. bfffo %d0{#0,#32},%d1
  497. move.w -(%a0),%d2
  498. sub.w %d1,%d2
  499. jcc 1f
  500. | Pathologically small, denormalize.
  501. add.w %d2,%d1
  502. clr.w %d2
  503. fp_set_sr FPSR_EXC_UNFL
  504. 1: move.w %d2,(%a0)+
  505. move.w %d1,%d2
  506. jeq fp_ne_checkround
  507. | This is exactly the same 64-bit double shift as seen above.
  508. lsl.l %d2,%d0
  509. move.l %d0,(%a0)+
  510. move.l (%a0),%d0
  511. move.l %d0,%d1
  512. lsl.l %d2,%d0
  513. move.l %d0,(%a0)
  514. neg.w %d2
  515. and.w #0x1f,%d2
  516. lsr.l %d2,%d1
  517. or.l %d1,-(%a0)
  518. #ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
  519. fp_ne_extra1:
  520. clr.l %d0
  521. move.b (-4,%a0),%d0
  522. neg.w %d2
  523. add.w #24,%d2
  524. jcc 1f
  525. clr.b (-4,%a0)
  526. lsl.l %d2,%d0
  527. or.l %d0,(4,%a0)
  528. jra fp_ne_checkround
  529. 1: addq.w #8,%d2
  530. lsl.l %d2,%d0
  531. move.b %d0,(-4,%a0)
  532. lsr.l #8,%d0
  533. or.l %d0,(4,%a0)
  534. #endif
  535. jra fp_ne_checkround
  536. | May or may not be subnormal, if so, only 32 bits to shift.
  537. fp_ne_small2:
  538. bfffo %d0{#0,#32},%d1
  539. add.w #32,%d1
  540. move.w -(%a0),%d2
  541. sub.w %d1,%d2
  542. jcc 1f
  543. | Beyond pathologically small, denormalize.
  544. add.w %d2,%d1
  545. clr.w %d2
  546. fp_set_sr FPSR_EXC_UNFL
  547. 1: move.w %d2,(%a0)+
  548. ext.l %d1
  549. jeq fp_ne_checkround
  550. clr.l (4,%a0)
  551. sub.w #32,%d1
  552. jcs 1f
  553. lsl.l %d1,%d0 | lower lword needs only to be shifted
  554. move.l %d0,(%a0) | into the higher lword
  555. #ifdef CONFIG_M68KFPU_EMU_EXTRAPREC
  556. clr.l %d0
  557. move.b (-4,%a0),%d0
  558. clr.b (-4,%a0)
  559. neg.w %d1
  560. add.w #32,%d1
  561. bfins %d0,(%a0){%d1,#8}
  562. #endif
  563. jra fp_ne_checkround
  564. 1: neg.w %d1 | lower lword is splitted between
  565. bfins %d0,(%a0){%d1,#32} | higher and lower lword
  566. #ifndef CONFIG_M68KFPU_EMU_EXTRAPREC
  567. jra fp_ne_checkround
  568. #else
  569. move.w %d1,%d2
  570. jra fp_ne_extra1
  571. | These are extremely small numbers, that will mostly end up as zero
  572. | anyway, so this is only important for correct rounding.
  573. fp_ne_small3:
  574. bfffo %d0{#24,#8},%d1
  575. add.w #40,%d1
  576. move.w -(%a0),%d2
  577. sub.w %d1,%d2
  578. jcc 1f
  579. | Pathologically small, denormalize.
  580. add.w %d2,%d1
  581. clr.w %d2
  582. 1: move.w %d2,(%a0)+
  583. ext.l %d1
  584. jeq fp_ne_checkround
  585. cmp.w #8,%d1
  586. jcs 2f
  587. 1: clr.b (-4,%a0)
  588. sub.w #64,%d1
  589. jcs 1f
  590. add.w #24,%d1
  591. lsl.l %d1,%d0
  592. move.l %d0,(%a0)
  593. jra fp_ne_checkround
  594. 1: neg.w %d1
  595. bfins %d0,(%a0){%d1,#8}
  596. jra fp_ne_checkround
  597. 2: lsl.l %d1,%d0
  598. move.b %d0,(-4,%a0)
  599. lsr.l #8,%d0
  600. move.b %d0,(7,%a0)
  601. jra fp_ne_checkround
  602. #endif
  603. | Infinities and NaNs, again, same as above.
  604. fp_ne_large:
  605. move.l (%a0)+,%d0
  606. jne 3f
  607. 1: tst.l (%a0)
  608. jne 4f
  609. 2: subq.l #8,%a0
  610. printf PNORM,"%p(",1,%a0
  611. printx PNORM,%a0@
  612. printf PNORM,")n"
  613. rts
  614. | we have maybe a NaN, shift off the highest bit
  615. 3: move.l %d0,%d1
  616. lsl.l #1,%d1
  617. jne 4f
  618. clr.l (-4,%a0)
  619. jra 1b
  620. | we have a NaN, test if it is signaling
  621. 4: bset #30,%d0
  622. jne 2b
  623. fp_set_sr FPSR_EXC_SNAN
  624. move.l %d0,(-4,%a0)
  625. jra 2b
  626. | these next two do rounding as per the IEEE standard.
  627. | values for the rounding modes appear to be:
  628. | 0: Round to nearest
  629. | 1: Round to zero
  630. | 2: Round to -Infinity
  631. | 3: Round to +Infinity
  632. | both functions expect that fp_normalize was already
  633. | called (and extended argument is already normalized
  634. | as far as possible), these are used if there is different
  635. | rounding precision is selected and before converting
  636. | into single/double
  637. | fp_normalize_double:
  638. | normalize an extended with double (52-bit) precision
  639. | args:  %a0 (struct fp_ext *)
  640. fp_normalize_double:
  641. printf PNORM,"nd: %p(",1,%a0
  642. printx PNORM,%a0@
  643. printf PNORM,"), "
  644. move.l (%a0)+,%d2
  645. tst.w %d2
  646. jeq fp_nd_zero | zero / denormalized
  647. cmp.w #0x7fff,%d2
  648. jeq fp_nd_huge | NaN / infinitive.
  649. sub.w #0x4000-0x3ff,%d2 | will the exponent fit?
  650. jcs fp_nd_small | too small.
  651. cmp.w #0x7fe,%d2
  652. jcc fp_nd_large | too big.
  653. addq.l #4,%a0
  654. move.l (%a0),%d0 | low lword of mantissa
  655. | now, round off the low 11 bits.
  656. fp_nd_round:
  657. moveq #21,%d1
  658. lsl.l %d1,%d0 | keep 11 low bits.
  659. jne fp_nd_checkround | Are they non-zero?
  660. | nothing to do here
  661. 9: subq.l #8,%a0
  662. printf PNORM,"%p(",1,%a0
  663. printx PNORM,%a0@
  664. printf PNORM,")n"
  665. rts
  666. | Be careful with the X bit! It contains the lsb
  667. | from the shift above, it is needed for round to nearest.
  668. fp_nd_checkround:
  669. fp_set_sr FPSR_EXC_INEX2 | INEX2 bit
  670. and.w #0xf800,(2,%a0) | clear bits 0-10
  671. move.w (FPD_RND,FPDATA),%d2 | rounding mode
  672. jne 2f | %d2 == 0, round to nearest
  673. tst.l %d0 | test guard bit
  674. jpl 9b | zero is closer
  675. | here we test the X bit by adding it to %d2
  676. clr.w %d2 | first set z bit, addx only clears it
  677. addx.w %d2,%d2 | test lsb bit
  678. | IEEE754-specified "round to even" behaviour.  If the guard
  679. | bit is set, then the number is odd, so rounding works like
  680. | in grade-school arithmetic (i.e. 1.5 rounds to 2.0)
  681. | Otherwise, an equal distance rounds towards zero, so as not
  682. | to produce an odd number.  This is strange, but it is what
  683. | the standard says.
  684. jne fp_nd_doroundup | round to infinity
  685. lsl.l #1,%d0 | check low bits
  686. jeq 9b | round to zero
  687. fp_nd_doroundup:
  688. | round (the mantissa, that is) towards infinity
  689. add.l #0x800,(%a0)
  690. jcc 9b | no overflow, good.
  691. addq.l #1,-(%a0) | extend to high lword
  692. jcc 1f | no overflow, good.
  693. | Yow! we have managed to overflow the mantissa.  Since this
  694. | only happens when %d1 was 0xfffff800, it is now zero, so
  695. | reset the high bit, and increment the exponent.
  696. move.w #0x8000,(%a0)
  697. addq.w #1,-(%a0)
  698. cmp.w #0x43ff,(%a0)+ | exponent now overflown?
  699. jeq fp_nd_large | yes, so make it infinity.
  700. 1: subq.l #4,%a0
  701. printf PNORM,"%p(",1,%a0
  702. printx PNORM,%a0@
  703. printf PNORM,")n"
  704. rts
  705. 2: subq.w #2,%d2
  706. jcs 9b | %d2 < 2, round to zero
  707. jhi 3f | %d2 > 2, round to +infinity
  708. | Round to +Inf or -Inf.  High word of %d2 contains the
  709. | sign of the number, by the way.
  710. swap %d2 | to -inf
  711. tst.b %d2
  712. jne fp_nd_doroundup | negative, round to infinity
  713. jra 9b | positive, round to zero
  714. 3: swap %d2 | to +inf
  715. tst.b %d2
  716. jeq fp_nd_doroundup | positive, round to infinity
  717. jra 9b | negative, round to zero
  718. | Exponent underflow.  Try to make a denormal, and set it to
  719. | the smallest possible fraction if this fails.
  720. fp_nd_small:
  721. fp_set_sr FPSR_EXC_UNFL | set UNFL bit
  722. move.w #0x3c01,(-2,%a0) | 2**-1022
  723. neg.w %d2 | degree of underflow
  724. cmp.w #32,%d2 | single or double shift?
  725. jcc 1f
  726. | Again, another 64-bit double shift.
  727. move.l (%a0),%d0
  728. move.l %d0,%d1
  729. lsr.l %d2,%d0
  730. move.l %d0,(%a0)+
  731. move.l (%a0),%d0
  732. lsr.l %d2,%d0
  733. neg.w %d2
  734. add.w #32,%d2
  735. lsl.l %d2,%d1
  736. or.l %d1,%d0
  737. move.l (%a0),%d1
  738. move.l %d0,(%a0)
  739. | Check to see if we shifted off any significant bits
  740. lsl.l %d2,%d1
  741. jeq fp_nd_round | Nope, round.
  742. bset #0,%d0 | Yes, so set the "sticky bit".
  743. jra fp_nd_round | Now, round.
  744. | Another 64-bit single shift and store
  745. 1: sub.w #32,%d2
  746. cmp.w #32,%d2 | Do we really need to shift?
  747. jcc 2f | No, the number is too small.
  748. move.l (%a0),%d0
  749. clr.l (%a0)+
  750. move.l %d0,%d1
  751. lsr.l %d2,%d0
  752. neg.w %d2
  753. add.w #32,%d2
  754. | Again, check to see if we shifted off any significant bits.
  755. tst.l (%a0)
  756. jeq 1f
  757. bset #0,%d0 | Sticky bit.
  758. 1: move.l %d0,(%a0)
  759. lsl.l %d2,%d1
  760. jeq fp_nd_round
  761. bset #0,%d0
  762. jra fp_nd_round
  763. | Sorry, the number is just too small.
  764. 2: clr.l (%a0)+
  765. clr.l (%a0)
  766. moveq #1,%d0 | Smallest possible fraction,
  767. jra fp_nd_round | round as desired.
  768. | zero and denormalized
  769. fp_nd_zero:
  770. tst.l (%a0)+
  771. jne 1f
  772. tst.l (%a0)
  773. jne 1f
  774. subq.l #8,%a0
  775. printf PNORM,"%p(",1,%a0
  776. printx PNORM,%a0@
  777. printf PNORM,")n"
  778. rts | zero.  nothing to do.
  779. | These are not merely subnormal numbers, but true denormals,
  780. | i.e. pathologically small (exponent is 2**-16383) numbers.
  781. | It is clearly impossible for even a normal extended number
  782. | with that exponent to fit into double precision, so just
  783. | write these ones off as "too darn small".
  784. 1: fp_set_sr FPSR_EXC_UNFL | Set UNFL bit
  785. clr.l (%a0)
  786. clr.l -(%a0)
  787. move.w #0x3c01,-(%a0) | i.e. 2**-1022
  788. addq.l #6,%a0
  789. moveq #1,%d0
  790. jra fp_nd_round | round.
  791. | Exponent overflow.  Just call it infinity.
  792. fp_nd_large:
  793. move.w #0x7ff,%d0
  794. and.w (6,%a0),%d0
  795. jeq 1f
  796. fp_set_sr FPSR_EXC_INEX2
  797. 1: fp_set_sr FPSR_EXC_OVFL
  798. move.w (FPD_RND,FPDATA),%d2
  799. jne 3f | %d2 = 0 round to nearest
  800. 1: move.w #0x7fff,(-2,%a0)
  801. clr.l (%a0)+
  802. clr.l (%a0)
  803. 2: subq.l #8,%a0
  804. printf PNORM,"%p(",1,%a0
  805. printx PNORM,%a0@
  806. printf PNORM,")n"
  807. rts
  808. 3: subq.w #2,%d2
  809. jcs 5f | %d2 < 2, round to zero
  810. jhi 4f | %d2 > 2, round to +infinity
  811. tst.b (-3,%a0) | to -inf
  812. jne 1b
  813. jra 5f
  814. 4: tst.b (-3,%a0) | to +inf
  815. jeq 1b
  816. 5: move.w #0x43fe,(-2,%a0)
  817. moveq #-1,%d0
  818. move.l %d0,(%a0)+
  819. move.w #0xf800,%d0
  820. move.l %d0,(%a0)
  821. jra 2b
  822. | Infinities or NaNs
  823. fp_nd_huge:
  824. subq.l #4,%a0
  825. printf PNORM,"%p(",1,%a0
  826. printx PNORM,%a0@
  827. printf PNORM,")n"
  828. rts
  829. | fp_normalize_single:
  830. | normalize an extended with single (23-bit) precision
  831. | args:  %a0 (struct fp_ext *)
  832. fp_normalize_single:
  833. printf PNORM,"ns: %p(",1,%a0
  834. printx PNORM,%a0@
  835. printf PNORM,") "
  836. addq.l #2,%a0
  837. move.w (%a0)+,%d2
  838. jeq fp_ns_zero | zero / denormalized
  839. cmp.w #0x7fff,%d2
  840. jeq fp_ns_huge | NaN / infinitive.
  841. sub.w #0x4000-0x7f,%d2 | will the exponent fit?
  842. jcs fp_ns_small | too small.
  843. cmp.w #0xfe,%d2
  844. jcc fp_ns_large | too big.
  845. move.l (%a0)+,%d0 | get high lword of mantissa
  846. fp_ns_round:
  847. tst.l (%a0) | check the low lword
  848. jeq 1f
  849. | Set a sticky bit if it is non-zero.  This should only
  850. | affect the rounding in what would otherwise be equal-
  851. | distance situations, which is what we want it to do.
  852. bset #0,%d0
  853. 1: clr.l (%a0) | zap it from memory.
  854. | now, round off the low 8 bits of the hi lword.
  855. tst.b %d0 | 8 low bits.
  856. jne fp_ns_checkround | Are they non-zero?
  857. | nothing to do here
  858. subq.l #8,%a0
  859. printf PNORM,"%p(",1,%a0
  860. printx PNORM,%a0@
  861. printf PNORM,")n"
  862. rts
  863. fp_ns_checkround:
  864. fp_set_sr FPSR_EXC_INEX2 | INEX2 bit
  865. clr.b -(%a0) | clear low byte of high lword
  866. subq.l #3,%a0
  867. move.w (FPD_RND,FPDATA),%d2 | rounding mode
  868. jne 2f | %d2 == 0, round to nearest
  869. tst.b %d0 | test guard bit
  870. jpl 9f | zero is closer
  871. btst #8,%d0 | test lsb bit
  872. | round to even behaviour, see above.
  873. jne fp_ns_doroundup | round to infinity
  874. lsl.b #1,%d0 | check low bits
  875. jeq 9f | round to zero
  876. fp_ns_doroundup:
  877. | round (the mantissa, that is) towards infinity
  878. add.l #0x100,(%a0)
  879. jcc 9f | no overflow, good.
  880. | Overflow.  This means that the %d1 was 0xffffff00, so it
  881. | is now zero.  We will set the mantissa to reflect this, and
  882. | increment the exponent (checking for overflow there too)
  883. move.w #0x8000,(%a0)
  884. addq.w #1,-(%a0)
  885. cmp.w #0x407f,(%a0)+ | exponent now overflown?
  886. jeq fp_ns_large | yes, so make it infinity.
  887. 9: subq.l #4,%a0
  888. printf PNORM,"%p(",1,%a0
  889. printx PNORM,%a0@
  890. printf PNORM,")n"
  891. rts
  892. | check nondefault rounding modes
  893. 2: subq.w #2,%d2
  894. jcs 9b | %d2 < 2, round to zero
  895. jhi 3f | %d2 > 2, round to +infinity
  896. tst.b (-3,%a0) | to -inf
  897. jne fp_ns_doroundup | negative, round to infinity
  898. jra 9b | positive, round to zero
  899. 3: tst.b (-3,%a0) | to +inf
  900. jeq fp_ns_doroundup | positive, round to infinity
  901. jra 9b | negative, round to zero
  902. | Exponent underflow.  Try to make a denormal, and set it to
  903. | the smallest possible fraction if this fails.
  904. fp_ns_small:
  905. fp_set_sr FPSR_EXC_UNFL | set UNFL bit
  906. move.w #0x3f81,(-2,%a0) | 2**-126
  907. neg.w %d2 | degree of underflow
  908. cmp.w #32,%d2 | single or double shift?
  909. jcc 2f
  910. | a 32-bit shift.
  911. move.l (%a0),%d0
  912. move.l %d0,%d1
  913. lsr.l %d2,%d0
  914. move.l %d0,(%a0)+
  915. | Check to see if we shifted off any significant bits.
  916. neg.w %d2
  917. add.w #32,%d2
  918. lsl.l %d2,%d1
  919. jeq 1f
  920. bset #0,%d0 | Sticky bit.
  921. | Check the lower lword
  922. 1: tst.l (%a0)
  923. jeq fp_ns_round
  924. clr (%a0)
  925. bset #0,%d0 | Sticky bit.
  926. jra fp_ns_round
  927. | Sorry, the number is just too small.
  928. 2: clr.l (%a0)+
  929. clr.l (%a0)
  930. moveq #1,%d0 | Smallest possible fraction,
  931. jra fp_ns_round | round as desired.
  932. | Exponent overflow.  Just call it infinity.
  933. fp_ns_large:
  934. tst.b (3,%a0)
  935. jeq 1f
  936. fp_set_sr FPSR_EXC_INEX2
  937. 1: fp_set_sr FPSR_EXC_OVFL
  938. move.w (FPD_RND,FPDATA),%d2
  939. jne 3f | %d2 = 0 round to nearest
  940. 1: move.w #0x7fff,(-2,%a0)
  941. clr.l (%a0)+
  942. clr.l (%a0)
  943. 2: subq.l #8,%a0
  944. printf PNORM,"%p(",1,%a0
  945. printx PNORM,%a0@
  946. printf PNORM,")n"
  947. rts
  948. 3: subq.w #2,%d2
  949. jcs 5f | %d2 < 2, round to zero
  950. jhi 4f | %d2 > 2, round to +infinity
  951. tst.b (-3,%a0) | to -inf
  952. jne 1b
  953. jra 5f
  954. 4: tst.b (-3,%a0) | to +inf
  955. jeq 1b
  956. 5: move.w #0x407e,(-2,%a0)
  957. move.l #0xffffff00,(%a0)+
  958. clr.l (%a0)
  959. jra 2b
  960. | zero and denormalized
  961. fp_ns_zero:
  962. tst.l (%a0)+
  963. jne 1f
  964. tst.l (%a0)
  965. jne 1f
  966. subq.l #8,%a0
  967. printf PNORM,"%p(",1,%a0
  968. printx PNORM,%a0@
  969. printf PNORM,")n"
  970. rts | zero.  nothing to do.
  971. | These are not merely subnormal numbers, but true denormals,
  972. | i.e. pathologically small (exponent is 2**-16383) numbers.
  973. | It is clearly impossible for even a normal extended number
  974. | with that exponent to fit into single precision, so just
  975. | write these ones off as "too darn small".
  976. 1: fp_set_sr FPSR_EXC_UNFL | Set UNFL bit
  977. clr.l (%a0)
  978. clr.l -(%a0)
  979. move.w #0x3f81,-(%a0) | i.e. 2**-126
  980. addq.l #6,%a0
  981. moveq #1,%d0
  982. jra fp_ns_round | round.
  983. | Infinities or NaNs
  984. fp_ns_huge:
  985. subq.l #4,%a0
  986. printf PNORM,"%p(",1,%a0
  987. printx PNORM,%a0@
  988. printf PNORM,")n"
  989. rts
  990. | fp_normalize_single_fast:
  991. | normalize an extended with single (23-bit) precision
  992. | this is only used by fsgldiv/fsgdlmul, where the
  993. | operand is not completly normalized.
  994. | args:  %a0 (struct fp_ext *)
  995. fp_normalize_single_fast:
  996. printf PNORM,"nsf: %p(",1,%a0
  997. printx PNORM,%a0@
  998. printf PNORM,") "
  999. addq.l #2,%a0
  1000. move.w (%a0)+,%d2
  1001. cmp.w #0x7fff,%d2
  1002. jeq fp_nsf_huge | NaN / infinitive.
  1003. move.l (%a0)+,%d0 | get high lword of mantissa
  1004. fp_nsf_round:
  1005. tst.l (%a0) | check the low lword
  1006. jeq 1f
  1007. | Set a sticky bit if it is non-zero.  This should only
  1008. | affect the rounding in what would otherwise be equal-
  1009. | distance situations, which is what we want it to do.
  1010. bset #0,%d0
  1011. 1: clr.l (%a0) | zap it from memory.
  1012. | now, round off the low 8 bits of the hi lword.
  1013. tst.b %d0 | 8 low bits.
  1014. jne fp_nsf_checkround | Are they non-zero?
  1015. | nothing to do here
  1016. subq.l #8,%a0
  1017. printf PNORM,"%p(",1,%a0
  1018. printx PNORM,%a0@
  1019. printf PNORM,")n"
  1020. rts
  1021. fp_nsf_checkround:
  1022. fp_set_sr FPSR_EXC_INEX2 | INEX2 bit
  1023. clr.b -(%a0) | clear low byte of high lword
  1024. subq.l #3,%a0
  1025. move.w (FPD_RND,FPDATA),%d2 | rounding mode
  1026. jne 2f | %d2 == 0, round to nearest
  1027. tst.b %d0 | test guard bit
  1028. jpl 9f | zero is closer
  1029. btst #8,%d0 | test lsb bit
  1030. | round to even behaviour, see above.
  1031. jne fp_nsf_doroundup | round to infinity
  1032. lsl.b #1,%d0 | check low bits
  1033. jeq 9f | round to zero
  1034. fp_nsf_doroundup:
  1035. | round (the mantissa, that is) towards infinity
  1036. add.l #0x100,(%a0)
  1037. jcc 9f | no overflow, good.
  1038. | Overflow.  This means that the %d1 was 0xffffff00, so it
  1039. | is now zero.  We will set the mantissa to reflect this, and
  1040. | increment the exponent (checking for overflow there too)
  1041. move.w #0x8000,(%a0)
  1042. addq.w #1,-(%a0)
  1043. cmp.w #0x407f,(%a0)+ | exponent now overflown?
  1044. jeq fp_nsf_large | yes, so make it infinity.
  1045. 9: subq.l #4,%a0
  1046. printf PNORM,"%p(",1,%a0
  1047. printx PNORM,%a0@
  1048. printf PNORM,")n"
  1049. rts
  1050. | check nondefault rounding modes
  1051. 2: subq.w #2,%d2
  1052. jcs 9b | %d2 < 2, round to zero
  1053. jhi 3f | %d2 > 2, round to +infinity
  1054. tst.b (-3,%a0) | to -inf
  1055. jne fp_nsf_doroundup | negative, round to infinity
  1056. jra 9b | positive, round to zero
  1057. 3: tst.b (-3,%a0) | to +inf
  1058. jeq fp_nsf_doroundup | positive, round to infinity
  1059. jra 9b | negative, round to zero
  1060. | Exponent overflow.  Just call it infinity.
  1061. fp_nsf_large:
  1062. tst.b (3,%a0)
  1063. jeq 1f
  1064. fp_set_sr FPSR_EXC_INEX2
  1065. 1: fp_set_sr FPSR_EXC_OVFL
  1066. move.w (FPD_RND,FPDATA),%d2
  1067. jne 3f | %d2 = 0 round to nearest
  1068. 1: move.w #0x7fff,(-2,%a0)
  1069. clr.l (%a0)+
  1070. clr.l (%a0)
  1071. 2: subq.l #8,%a0
  1072. printf PNORM,"%p(",1,%a0
  1073. printx PNORM,%a0@
  1074. printf PNORM,")n"
  1075. rts
  1076. 3: subq.w #2,%d2
  1077. jcs 5f | %d2 < 2, round to zero
  1078. jhi 4f | %d2 > 2, round to +infinity
  1079. tst.b (-3,%a0) | to -inf
  1080. jne 1b
  1081. jra 5f
  1082. 4: tst.b (-3,%a0) | to +inf
  1083. jeq 1b
  1084. 5: move.w #0x407e,(-2,%a0)
  1085. move.l #0xffffff00,(%a0)+
  1086. clr.l (%a0)
  1087. jra 2b
  1088. | Infinities or NaNs
  1089. fp_nsf_huge:
  1090. subq.l #4,%a0
  1091. printf PNORM,"%p(",1,%a0
  1092. printx PNORM,%a0@
  1093. printf PNORM,")n"
  1094. rts
  1095. | conv_ext2int (macro):
  1096. | Generates a subroutine that converts an extended value to an
  1097. | integer of a given size, again, with the appropriate type of
  1098. | rounding.
  1099. | Macro arguments:
  1100. | s: size, as given in an assembly instruction.
  1101. | b: number of bits in that size.
  1102. | Subroutine arguments:
  1103. | %a0: source (struct fp_ext *)
  1104. | Returns the integer in %d0 (like it should)
  1105. .macro conv_ext2int s,b
  1106. .set inf,(1<<(b-1))-1 | i.e. MAXINT
  1107. printf PCONV,"e2i%d: %p(",2,#b,%a0
  1108. printx PCONV,%a0@
  1109. printf PCONV,") "
  1110. addq.l #2,%a0
  1111. move.w (%a0)+,%d2 | exponent
  1112. jeq fp_e2i_zerob | zero / denorm (== 0, here)
  1113. cmp.w #0x7fff,%d2
  1114. jeq fp_e2i_hugeb | Inf / NaN
  1115. sub.w #0x3ffe,%d2
  1116. jcs fp_e2i_smallb
  1117. cmp.w #b,%d2
  1118. jhi fp_e2i_largeb
  1119. move.l (%a0),%d0
  1120. move.l %d0,%d1
  1121. lsl.l %d2,%d1
  1122. jne fp_e2i_roundb
  1123. tst.l (4,%a0)
  1124. jne fp_e2i_roundb
  1125. neg.w %d2
  1126. add.w #32,%d2
  1127. lsr.l %d2,%d0
  1128. 9: tst.w (-4,%a0)
  1129. jne 1f
  1130. tst.s %d0
  1131. jmi fp_e2i_largeb
  1132. printf PCONV,"-> %pn",1,%d0
  1133. rts
  1134. 1: neg.s %d0
  1135. jeq 1f
  1136. jpl fp_e2i_largeb
  1137. 1: printf PCONV,"-> %pn",1,%d0
  1138. rts
  1139. fp_e2i_roundb:
  1140. fp_set_sr FPSR_EXC_INEX2 | INEX2 bit
  1141. neg.w %d2
  1142. add.w #32,%d2
  1143. .if b>16
  1144. jeq 5f
  1145. .endif
  1146. lsr.l %d2,%d0
  1147. move.w (FPD_RND,FPDATA),%d2 | rounding mode
  1148. jne 2f | %d2 == 0, round to nearest
  1149. tst.l %d1 | test guard bit
  1150. jpl 9b | zero is closer
  1151. btst %d2,%d0 | test lsb bit (%d2 still 0)
  1152. jne fp_e2i_doroundupb
  1153. lsl.l #1,%d1 | check low bits
  1154. jne fp_e2i_doroundupb
  1155. tst.l (4,%a0)
  1156. jeq 9b
  1157. fp_e2i_doroundupb:
  1158. addq.l #1,%d0
  1159. jra 9b
  1160. | check nondefault rounding modes
  1161. 2: subq.w #2,%d2
  1162. jcs 9b | %d2 < 2, round to zero
  1163. jhi 3f | %d2 > 2, round to +infinity
  1164. tst.w (-4,%a0) | to -inf
  1165. jne fp_e2i_doroundupb | negative, round to infinity
  1166. jra 9b | positive, round to zero
  1167. 3: tst.w (-4,%a0) | to +inf
  1168. jeq fp_e2i_doroundupb | positive, round to infinity
  1169. jra 9b | negative, round to zero
  1170. | we are only want -2**127 get correctly rounded here,
  1171. | since the guard bit is in the lower lword.
  1172. | everything else ends up anyway as overflow.
  1173. .if b>16
  1174. 5: move.w (FPD_RND,FPDATA),%d2 | rounding mode
  1175. jne 2b | %d2 == 0, round to nearest
  1176. move.l (4,%a0),%d1 | test guard bit
  1177. jpl 9b | zero is closer
  1178. lsl.l #1,%d1 | check low bits
  1179. jne fp_e2i_doroundupb
  1180. jra 9b
  1181. .endif
  1182. fp_e2i_zerob:
  1183. clr.l %d0
  1184. tst.l (%a0)+
  1185. jne 1f
  1186. tst.l (%a0)
  1187. jeq 3f
  1188. 1: subq.l #4,%a0
  1189. fp_clr_sr FPSR_EXC_UNFL | fp_normalize_ext has set this bit
  1190. fp_e2i_smallb:
  1191. fp_set_sr FPSR_EXC_INEX2
  1192. clr.l %d0
  1193. move.w (FPD_RND,FPDATA),%d2 | rounding mode
  1194. subq.w #2,%d2
  1195. jcs 3f | %d2 < 2, round to nearest/zero
  1196. jhi 2f | %d2 > 2, round to +infinity
  1197. tst.w (-4,%a0) | to -inf
  1198. jeq 3f
  1199. subq.s #1,%d0
  1200. jra 3f
  1201. 2: tst.w (-4,%a0) | to +inf
  1202. jne 3f
  1203. addq.s #1,%d0
  1204. 3: printf PCONV,"-> %pn",1,%d0
  1205. rts
  1206. fp_e2i_largeb:
  1207. fp_set_sr FPSR_EXC_OPERR
  1208. move.s #inf,%d0
  1209. tst.w (-4,%a0)
  1210. jeq 1f
  1211. addq.s #1,%d0
  1212. 1: printf PCONV,"-> %pn",1,%d0
  1213. rts
  1214. fp_e2i_hugeb:
  1215. move.s (%a0),%d0
  1216. tst.l (%a0)
  1217. jne 1f
  1218. tst.l (%a0)
  1219. jeq fp_e2i_largeb
  1220. | fp_normalize_ext has set this bit already
  1221. | and made the number nonsignaling
  1222. 1: fp_tst_sr FPSR_EXC_SNAN
  1223. jne 1f
  1224. fp_set_sr FPSR_EXC_OPERR
  1225. 1: printf PCONV,"-> %pn",1,%d0
  1226. rts
  1227. .endm
  1228. fp_conv_ext2long:
  1229. conv_ext2int l,32
  1230. fp_conv_ext2short:
  1231. conv_ext2int w,16
  1232. fp_conv_ext2byte:
  1233. conv_ext2int b,8
  1234. fp_conv_ext2double:
  1235. jsr fp_normalize_double
  1236. printf PCONV,"e2d: %p(",1,%a0
  1237. printx PCONV,%a0@
  1238. printf PCONV,"), "
  1239. move.l (%a0)+,%d2
  1240. cmp.w #0x7fff,%d2
  1241. jne 1f
  1242. move.w #0x7ff,%d2
  1243. move.l (%a0)+,%d0
  1244. jra 2f
  1245. 1: sub.w #0x3fff-0x3ff,%d2
  1246. move.l (%a0)+,%d0
  1247. jmi 2f
  1248. clr.w %d2
  1249. 2: lsl.w #5,%d2
  1250. lsl.l #7,%d2
  1251. lsl.l #8,%d2
  1252. move.l %d0,%d1
  1253. lsl.l #1,%d0
  1254. lsr.l #4,%d0
  1255. lsr.l #8,%d0
  1256. or.l %d2,%d0
  1257. putuser.l %d0,(%a1)+,fp_err_ua2,%a1
  1258. moveq #21,%d0
  1259. lsl.l %d0,%d1
  1260. move.l (%a0),%d0
  1261. lsr.l #4,%d0
  1262. lsr.l #7,%d0
  1263. or.l %d1,%d0
  1264. putuser.l %d0,(%a1),fp_err_ua2,%a1
  1265. #ifdef FPU_EMU_DEBUG
  1266. getuser.l %a1@(-4),%d0,fp_err_ua2,%a1
  1267. getuser.l %a1@(0),%d1,fp_err_ua2,%a1
  1268. printf PCONV,"%p(%08x%08x)n",3,%a1,%d0,%d1
  1269. #endif
  1270. rts
  1271. fp_conv_ext2single:
  1272. jsr fp_normalize_single
  1273. printf PCONV,"e2s: %p(",1,%a0
  1274. printx PCONV,%a0@
  1275. printf PCONV,"), "
  1276. move.l (%a0)+,%d1
  1277. cmp.w #0x7fff,%d1
  1278. jne 1f
  1279. move.w #0xff,%d1
  1280. move.l (%a0)+,%d0
  1281. jra 2f
  1282. 1: sub.w #0x3fff-0x7f,%d1
  1283. move.l (%a0)+,%d0
  1284. jmi 2f
  1285. clr.w %d1
  1286. 2: lsl.w #8,%d1
  1287. lsl.l #7,%d1
  1288. lsl.l #8,%d1
  1289. bclr #31,%d0
  1290. lsr.l #8,%d0
  1291. or.l %d1,%d0
  1292. printf PCONV,"%08xn",1,%d0
  1293. rts
  1294. | special return addresses for instr that
  1295. | encode the rounding precision in the opcode
  1296. | (e.g. fsmove,fdmove)
  1297. fp_finalrounding_single:
  1298. addq.l #8,%sp
  1299. jsr fp_normalize_ext
  1300. jsr fp_normalize_single
  1301. jra fp_finaltest
  1302. fp_finalrounding_single_fast:
  1303. addq.l #8,%sp 
  1304. jsr fp_normalize_ext
  1305. jsr fp_normalize_single_fast
  1306. jra fp_finaltest
  1307. fp_finalrounding_double:
  1308. addq.l #8,%sp
  1309. jsr fp_normalize_ext
  1310. jsr fp_normalize_double
  1311. jra fp_finaltest
  1312. | fp_finaltest:
  1313. | set the emulated status register based on the outcome of an
  1314. | emulated instruction.
  1315. fp_finalrounding:
  1316. addq.l #8,%sp
  1317. | printf ,"f: %pn",1,%a0
  1318. jsr fp_normalize_ext
  1319. move.w (FPD_PREC,FPDATA),%d0
  1320. subq.w #1,%d0
  1321. jcs fp_finaltest
  1322. jne 1f
  1323. jsr fp_normalize_single
  1324. jra 2f
  1325. 1: jsr fp_normalize_double
  1326. 2:| printf ,"f: %pn",1,%a0
  1327. fp_finaltest:
  1328. | First, we do some of the obvious tests for the exception
  1329. | status byte and condition code bytes of fp_sr here, so that
  1330. | they do not have to be handled individually by every
  1331. | emulated instruction.
  1332. clr.l %d0
  1333. addq.l #1,%a0
  1334. tst.b (%a0)+ | sign
  1335. jeq 1f
  1336. bset #FPSR_CC_NEG-24,%d0 | N bit
  1337. 1: cmp.w #0x7fff,(%a0)+ | exponent
  1338. jeq 2f
  1339. | test for zero
  1340. moveq #FPSR_CC_Z-24,%d1
  1341. tst.l (%a0)+
  1342. jne 9f
  1343. tst.l (%a0)
  1344. jne 9f
  1345. jra 8f
  1346. | infinitiv and NAN
  1347. 2: moveq #FPSR_CC_NAN-24,%d1
  1348. move.l (%a0)+,%d2
  1349. lsl.l #1,%d2 | ignore high bit
  1350. jne 8f
  1351. tst.l (%a0)
  1352. jne 8f
  1353. moveq #FPSR_CC_INF-24,%d1
  1354. 8: bset %d1,%d0
  1355. 9: move.b %d0,(FPD_FPSR+0,FPDATA) | set condition test result
  1356. | move instructions enter here
  1357. | Here, we test things in the exception status byte, and set
  1358. | other things in the accrued exception byte accordingly.
  1359. | Emulated instructions can set various things in the former,
  1360. | as defined in fp_emu.h.
  1361. fp_final:
  1362. move.l (FPD_FPSR,FPDATA),%d0
  1363. #if 0
  1364. btst #FPSR_EXC_SNAN,%d0 | EXC_SNAN
  1365. jne 1f
  1366. btst #FPSR_EXC_OPERR,%d0 | EXC_OPERR
  1367. jeq 2f
  1368. 1: bset #FPSR_AEXC_IOP,%d0 | set IOP bit
  1369. 2: btst #FPSR_EXC_OVFL,%d0 | EXC_OVFL
  1370. jeq 1f
  1371. bset #FPSR_AEXC_OVFL,%d0 | set OVFL bit
  1372. 1: btst #FPSR_EXC_UNFL,%d0 | EXC_UNFL
  1373. jeq 1f
  1374. btst #FPSR_EXC_INEX2,%d0 | EXC_INEX2
  1375. jeq 1f
  1376. bset #FPSR_AEXC_UNFL,%d0 | set UNFL bit
  1377. 1: btst #FPSR_EXC_DZ,%d0 | EXC_INEX1
  1378. jeq 1f
  1379. bset #FPSR_AEXC_DZ,%d0 | set DZ bit
  1380. 1: btst #FPSR_EXC_OVFL,%d0 | EXC_OVFL
  1381. jne 1f
  1382. btst #FPSR_EXC_INEX2,%d0 | EXC_INEX2
  1383. jne 1f
  1384. btst #FPSR_EXC_INEX1,%d0 | EXC_INEX1
  1385. jeq 2f
  1386. 1: bset #FPSR_AEXC_INEX,%d0 | set INEX bit
  1387. 2: move.l %d0,(FPD_FPSR,FPDATA)
  1388. #else
  1389. | same as above, greatly optimized, but untested (yet)
  1390. move.l %d0,%d2
  1391. lsr.l #5,%d0
  1392. move.l %d0,%d1
  1393. lsr.l #4,%d1
  1394. or.l %d0,%d1
  1395. and.b #0x08,%d1
  1396. move.l %d2,%d0
  1397. lsr.l #6,%d0
  1398. or.l %d1,%d0
  1399. move.l %d2,%d1
  1400. lsr.l #4,%d1
  1401. or.b #0xdf,%d1
  1402. and.b %d1,%d0
  1403. move.l %d2,%d1
  1404. lsr.l #7,%d1
  1405. and.b #0x80,%d1
  1406. or.b %d1,%d0
  1407. and.b #0xf8,%d0
  1408. or.b %d0,%d2
  1409. move.l %d2,(FPD_FPSR,FPDATA)
  1410. #endif
  1411. move.b (FPD_FPSR+2,FPDATA),%d0
  1412. and.b (FPD_FPCR+2,FPDATA),%d0
  1413. jeq 1f
  1414. printf ,"send signal!!!n"
  1415. 1: jra fp_end