fp_util.S 35 KB

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