emuOperALib.s
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:34k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* Copyright 1991-2001 Wind River Systems, Inc. */
  2. /*
  3. modification history
  4. --------------------
  5. 01c,14jul99,tdl  added FUNC / FUNC_LABEL
  6. 01b,24oct96,yp   stuck in a # in USSC mailing addr so cpp will work
  7. 01a,24jan95,hdn  original US Software version.
  8. */
  9. #* * * * * * * * * *
  10. #       Filename:   EMUOPER.ASM
  11. #
  12. #       Copyright (C) 1990,1991 By
  13. #       # United States Software Corporation
  14. #       # 14215 N.W. Science Park Drive
  15. #       # Portland, Oregon 97229
  16. #
  17. #       This software is furnished under a license and may be used
  18. #       and copied only in accordance with the terms of such license
  19. #       and with the inclusion of the above copyright notice.
  20. #       This software or any other copies thereof may not be provided
  21. #       or otherwise made available to any other person.  No title to
  22. #       and ownership of the software is hereby transferred.
  23. #
  24. #       The information in this software is subject to change without
  25. #       notice and should not be construed as a commitment by United
  26. #       States Software Corporation.
  27. #
  28. #       Version:        V3.09  01/19/95 GOFAST  WRS GNU version of GF-PROT
  29. #       Released:       1 March 1991
  30. #
  31. #* * * * * * * * * *
  32. #define _ASMLANGUAGE
  33. #include "vxWorks.h"
  34. #include "asm.h"
  35. .data
  36. .globl  FUNC(copyright_wind_river)
  37. .long   FUNC(copyright_wind_river)
  38. .include "emuIncALib.s"
  39. .text
  40. #        extrn   roundi:near,rounde:near,chkarg:near
  41. #        extrn   retnan:near,tnormal:near,renorm:near,getqn:near
  42. #        extrn   mul10:near,shiftr:near,exproc:near,exprop:near
  43. #        extrn   exret:near
  44. #DGROUP  GROUP   hwseg
  45. #CGROUP  GROUP   emuseg
  46. #hwseg   segment RW para public 'DATA'
  47. #        assume  ds:DGROUP, es:DGROUP, ss:DGROUP
  48. #        extrn   h_ctrl:word,h_stat:word,s_iptr:dword,s_memp:dword
  49. #hwseg   ends
  50. #emuseg  segment public USE32 'CODE'
  51. #        assume  cs:CGROUP
  52. __lib:
  53. #        subttl  Convert To Internal Floating-Point Format
  54. #        page
  55. # convert 16-bit or 32-bit integer to extended floating-point
  56. # input:        *eax = signed integer
  57. # output:       EP in ecx:edx:eax
  58. .globl witoep,wiep
  59. witoep:
  60. movswl (%eax),%edx
  61. jmp wiep2
  62. .globl sitoep
  63. sitoep:
  64. movl (%eax),%edx #pick up number
  65. wiep2: #SAVEII
  66. movl %esi,s_iptr
  67. movl %eax,s_memp
  68. wiep: movl $31,%ecx #initial sign -> cx
  69. xorl %eax,%eax
  70. orl %edx,%edx #weed out zero
  71. jz liep20
  72. jns siep5 #if negative, set sign, negate
  73. orl $0x80000000,%ecx
  74. negl %edx
  75. siep5: bsrl %edx,%esi
  76. subl %esi,%ecx
  77. shll %cl,%edx
  78. negw %cx
  79. addw $tBIAS+31,%cx
  80. ret
  81. # convert 64-bit integer to extended floating-point
  82. # input:        *eax = signed integer
  83. # output:       EP in ecx:edx:eax
  84. .globl litoep
  85. litoep:
  86. #SAVEII
  87. movl %esi,s_iptr
  88. movl %eax,s_memp
  89. movl 4(%eax),%edx #pick up number
  90. movl (%eax),%eax
  91. movl %eax,%ecx #jump if all zero
  92. orl %edx,%ecx
  93. jz liep20
  94. movl $tBIAS+63,%ecx #initial exponent -> cx
  95. orl %edx,%edx #if negative, set sign, negate
  96. jns liep5
  97. orl $0x80000000,%ecx
  98. notl %edx
  99. negl %eax
  100. sbbl $-1,%edx
  101. js liep7
  102. liep5: decl %ecx #shift left until high bit = 1
  103. addl %eax,%eax
  104. adcl %edx,%edx
  105. jns liep5
  106. liep7: ret
  107. liep20: movl $0x00010000,%ecx #zero
  108. ret
  109. # convert 10-byte packed decimal integer to extended floating-point
  110. # input:        *eax = signed integer
  111. # output:       EP in ecx:edx:eax
  112. .globl pdtoep
  113. pdtoep:
  114. movl $9,%ecx #set up loop counter and pointer
  115. lea 9(%eax),%edi
  116. xorl %edx,%edx #initialize mantissa
  117. xorl %eax,%eax
  118. pdep3: call mul10 #multiply mantissa by 10
  119. decl %edi #pick up next 2-digit
  120. movb (%edi),%bl
  121. pushl %ebx #add low digit to mantissa
  122. shrb $4,%bl
  123. andl $0x0f,%ebx
  124. addl %ebx,%eax
  125. adcl $0,%edx
  126. call mul10 #again multiply mantissa by 10
  127. popl %ebx #add high digit to mantissa
  128. andl $0x0f,%ebx
  129. addl %ebx,%eax
  130. adcl $0,%edx
  131. loop pdep3 #loop for all digits
  132. movl %eax,%ecx #jump if all zero
  133. orl %edx,%ecx
  134. jz pdep20
  135. movl $tBIAS+63,%ecx #initial exponent -> cx
  136. pdep5: decl %ecx #shift left until high bit = 1
  137. addl %eax,%eax
  138. adcl %edx,%edx
  139. jns pdep5
  140. pdep7: movb 9(%edi),%bl #set the sign bit
  141. andb $0x80,%bl
  142. shll $24,%ebx
  143. orl %ebx,%ecx
  144. ret
  145. pdep20: movl $0x00010000,%ecx #zero
  146. jmp pdep7
  147. # convert single-precision to extended floating-point
  148. # input:        *eax = single-precision
  149. # output:       EP in ecx:edx:eax
  150. .globl fptoep
  151. fptoep:
  152. #SAVEII
  153. movl %esi,s_iptr
  154. movl %eax,s_memp
  155. movl (%eax),%edx #pick up number
  156. movl %edx,%ecx #sign, exponent to ecx
  157. sarl $23,%ecx
  158. andl $0x800000ff,%ecx
  159. shll $9,%edx #mantissa -> edx:eax
  160. xorl %eax,%eax
  161. cmpb $0,%cl #go handle zero and denormal
  162. jz fpep20
  163. cmpb $-1,%cl #go handle INF and NaN
  164. jz dpep30
  165. rcrl $1,%edx
  166. fpep7: addw $tBIAS-sBIAS,%cx #adjust bias
  167. ret
  168. fpep20: shrl $1,%edx #this is either zero or denormal
  169. jz dpep29 #   zero if mantissa = 0
  170. orb $denorm,h_stat
  171. call exprop
  172. incl %ecx
  173. fpep21: decw %cx
  174. addl %edx,%edx
  175. jns fpep21
  176. jmp fpep7
  177. # convert double-precision to extended floating-point
  178. # input:        eax -> double-precision
  179. # output:       EP in ecx:edx:eax
  180. .globl dptoep
  181. dptoep:
  182. #SAVEII
  183. movl %esi,s_iptr
  184. movl %eax,s_memp
  185. movl 4(%eax),%edx #pick up number
  186. movl (%eax),%eax
  187. movl %edx,%ecx #sign, exponent to ecx
  188. sarl $20,%ecx
  189. andl $0x800007ff,%ecx
  190. shldl $12,%eax,%edx #mantissa -> edx:eax
  191. shll $11,%eax
  192. orw %cx,%cx
  193. jz dpep20
  194. cmpw $0x7ff,%cx
  195. jz dpep30
  196. rcrl $1,%edx
  197. dpep7: addw $tBIAS-lBIAS,%cx #adjust exponent bias
  198. dpep9: ret
  199. dpep30: orl $0x00027fff,%ecx #this is INF or NaN
  200. movl %edx,%ebx #   INF if mantissa 800..00
  201. shrdl $1,%ecx,%edx
  202. orl %eax,%ebx
  203. jz dpep9
  204. nanret: btl $30,%edx
  205. jc dpep32
  206. orw $invop,h_stat
  207. call exproc
  208. btsl $30,%edx
  209. dpep32: xorl %ebx,%ebx
  210. ret
  211. dpep20: shrl $1,%edx #this is either zero or denormal
  212. movl %edx,%ebx #   zero if mantissa = 0
  213. orl %eax,%ebx
  214. jz dpep29
  215. orb $denorm,h_stat
  216. call exprop
  217. incl %ecx
  218. dpep21: decw %cx
  219. addl %eax,%eax
  220. adcl %edx,%edx
  221. jns dpep21
  222. jmp dpep7
  223. dpep29: btsl $16,%ecx #zero
  224. ret
  225. # convert extended floating-point number to internal formal
  226. # input:        EP in *ss:eax
  227. # output:       EP in ecx:edx:eax
  228. .globl eptoep
  229. eptoep:
  230. movl 4(%eax),%edx #pick up the number
  231. movzwl 8(%eax),%ecx
  232. movl (%eax),%eax
  233. addw %cx,%cx
  234. rcrl $1,%ecx
  235. jz epe11 #tags: 10 = INF, denormal, illegal
  236. cmpw $0x7fff,%cx #      01 = zero
  237. jz epe6
  238. orl %edx,%edx
  239. jns epe6
  240. movl %edx,%ebx
  241. orl %eax,%ebx
  242. jz epe6
  243. ret
  244. epe6: btsl $17,%ecx #illegal etc
  245. ret
  246. epe11: movl %edx,%ebx #this is zero or denormal
  247. orl %eax,%ebx
  248. jnz epe6
  249. btsl $16,%ecx
  250. ret
  251. #        subttl  Convert From Internal Floating-Point Format
  252. #        page
  253. # convert extended floating-point to 16 or 32 bit integer
  254. # input:        EP in ecx:edx:eax
  255. # output:       eax = signed integer
  256. .globl eptowi
  257. eptowi:
  258. movl $15,%ebx #integer size
  259. jmp epsi1
  260. .globl eptosi
  261. eptosi:
  262. movl $31,%ebx #integer size
  263. epsi1: testl $0x00020000,%ecx #weed out specials
  264. jnz epsi20
  265. epsi3: subw $tBIAS,%cx #subtract the bias
  266. cmpw %bx,%cx #if exponent too large, return INF
  267. jge epsi32
  268. subw $63,%cx #here shift right
  269. negw %cx
  270. call shiftr
  271. call roundi #IEEE rounding
  272. adcl $0,%eax
  273. orl %ecx,%ecx #if negative take 2s complement
  274. jns epsi11
  275. negl %eax
  276. epsi11: ret #return
  277. epsi20: rorl $8,%ecx #check for stack underflow
  278. cmpb $3,%ch
  279. roll $8,%ecx
  280. jz epsi80
  281. orw %cx,%cx #specials, but denormals go back
  282. jz epsi3
  283. jmp epsi30
  284. epsi32: jg epsi30 #overflow
  285. addl %edx,%edx
  286. orl %eax,%edx
  287. jz epsi34
  288. epsi30: orb $invop,h_stat #either +INF or -INF
  289. call exproc
  290. epsi34: movl $1,%eax
  291. movb %bl,%cl
  292. shll %cl,%eax
  293. ret
  294. epsi80: orb $stacku,h_stat #stack underflow
  295. call exproc
  296. jmp epsi34
  297. # convert extended floating-point to 64-bit integer
  298. # input:        EP in ecx:edx:eax
  299. # output:       edx:eax = signed integer
  300. .globl eptoli
  301. eptoli:
  302. testl $0x00020000,%ecx #weed out specials
  303. jnz epli20
  304. epli3: subw $tBIAS,%cx #subtract the bias
  305. cmpw $63,%cx #if exponent too large, return INF
  306. je epli32
  307. jg epli30
  308. subw $63,%cx #here shift right
  309. negw %cx
  310. call shiftr
  311. call roundi #do IEEE rounding
  312. adcl $0,%eax
  313. adcl $0,%edx
  314. orl %ecx,%ecx #if negative take 2s complement
  315. jns epli11
  316. notl %edx
  317. negl %eax
  318. sbbl $-1,%edx
  319. epli11: ret #return
  320. epli20: shldl $16,%ecx,%ebx #check for stack underflow
  321. cmpb $3,%bl
  322. jz epli80
  323. orw %cx,%cx #specials, but denormals go back
  324. jz epli3
  325. jmp epli30
  326. epli32: addl %edx,%edx #treat 0x80000000 as special case
  327. orl %eax,%edx
  328. jz epli34
  329. epli30: orb $invop,h_stat #either +INF or -INF
  330. call exproc
  331. epli34: movl $0x80000000,%edx
  332. xorl %eax,%eax
  333. jmp epli11
  334. epli80: orb $stacku,h_stat #stack underflow
  335. call exproc
  336. jmp epli34
  337. # convert EP to 10-byte packed-decimal integer
  338. # input:        EP in ecx:edx:eax
  339. #               edi pointer to result area
  340. # output:       signed integer in result area
  341. .globl eptopd
  342. eppd20: shldl $16,%ecx,%ebx #check for stack underflow
  343. cmpb $3,%bl
  344. jz eppd80
  345. orw %cx,%cx #specials, but denormals go back
  346. jz eppd3
  347. eppd30: orb $invop,h_stat #either +INF or -INF
  348. call exproc
  349. eppd34: movl $0xffff8000,%eax
  350. movl %eax,6(%edi)
  351. movl $6,%ecx
  352. repz
  353. stosb
  354. ret
  355. eppd80: orb $stacku,h_stat #stack underflow
  356. call exproc
  357. jmp eppd34
  358. eppd33: subl $9,%edi #number too big
  359. jmp eppd30
  360. eptopd:
  361. movl %ecx,6(%edi) #store the sign
  362. btl $17,%ecx #weed out specials
  363. jc eppd20
  364. eppd3: subw $tBIAS+63,%cx #subtract the bias
  365. jge eppd30
  366. negw %cx
  367. call shiftr
  368. call roundi #do IEEE rounding
  369. adcl $0,%eax
  370. adcl $0,%edx
  371. movl %edx,%esi #get the digits by dividing with 10
  372. movl $9,%ecx
  373. pushl %ebp
  374. movl $10,%ebp
  375. eppd11: xchgl %esi,%eax
  376. xorl %edx,%edx
  377. divl %ebp
  378. xchgl %esi,%eax
  379. divl %ebp
  380. movb %dl,%bl
  381. xchgl %esi,%eax
  382. xorl %edx,%edx
  383. divl %ebp
  384. xchgl %esi,%eax
  385. divl %ebp
  386. shlb $4,%dl
  387. orb %bl,%dl
  388. movb %dl,(%edi)
  389. incl %edi
  390. loop eppd11
  391. popl %ebp
  392. orl %eax,%eax
  393. jnz eppd33
  394. ret
  395. # convert extended floating-point to single-precision floating-point
  396. # input:        EP in ecx:edx:eax
  397. # output:       eax = floating-point
  398. .globl eptofp
  399. epfp2: shldl $16,%ecx,%ebx #check for stack underflow
  400. cmpb $3,%bl
  401. jz epfp38
  402. btsl $16,%ecx #check zero, denormal
  403. jc epfp9
  404. orw %cx,%cx
  405. jz epfp3
  406. orl %edx,%edx
  407. jns epfp36
  408. jmp epfp30
  409. eptofp:
  410. testl $0x00030000,%ecx #jump if special value
  411. jnz epfp2
  412. epfp3: addw $sBIAS-tBIAS,%cx #adjust the bias
  413. cmpw $0,%cx #weed out underflow and overflow
  414. jle epfp20
  415. cmpw $0x0ff,%cx
  416. jnc epfp32
  417. epfp6: addl %edx,%edx #shift left to delete hidden bit
  418. epfp7: movl %edx,%ebx #set rounding bits
  419. shll $23,%ebx
  420. addl $-1,%eax
  421. adcl %ebx,%ebx
  422. jz epfp71
  423. movb $0x80,%bl
  424. epfp71: rcrb $1,%bl
  425. epfp8: shldl $9,%ecx,%eax #combine sign, exponent, mantissa
  426. movb %cl,%al
  427. shldl $23,%edx,%eax
  428. orb %cl,%cl #set underflow if necessary
  429. jnz epfp11
  430. testb $underf,h_ctrl
  431. jz epfp13
  432. orb %bl,%bl
  433. jz epfp11
  434. epfp13: orb $underf,h_stat
  435. call exproc
  436. epfp11: call roundi #IEEE rounding
  437. adcl $0,%eax
  438. ret
  439. epfp9: addl %ecx,%ecx #return signed zero
  440. rcrl $1,%eax
  441. ret
  442. epfp20: negw %cx #underflow, we return zero or denormal
  443. jz epfp7
  444. cmpw $25,%cx
  445. jc epfp23
  446. movw $25,%cx
  447. epfp23: xorl %ebx,%ebx
  448. shrdl %cl,%edx,%ebx
  449. shrl %cl,%edx
  450. xorw %cx,%cx
  451. orl %ebx,%ebx
  452. jz epfp7
  453. orb $1,%dl
  454. jmp epfp7
  455. epfp30: btcl $31,%edx #this is NaN or INF
  456. orl %edx,%eax
  457. jnz epfp34
  458. movw $2*sBIAS+1,%cx
  459. jmp epfp7
  460. epfp32: orb $overf,h_stat #this is overflow
  461. call exproc
  462. movw $2*sBIAS,%cx
  463. movl $-1,%edx
  464. jmp epfp7
  465. epfp38: call getqn
  466. orb $stacku,h_stat
  467. jmp epfp39
  468. epfp36: call getqn #this is NaN
  469. jmp epfp37
  470. epfp34: btl $30,%edx
  471. jc epfp35
  472. epfp37: orb $invop,h_stat
  473. epfp39: call exproc
  474. btsl $30,%edx
  475. epfp35: movw $2*sBIAS+1,%cx
  476. addl %edx,%edx
  477. xorl %ebx,%ebx
  478. jmp epfp8
  479. # convert extended floating-point to double-precision floating-point
  480. # input:        EP in ecx:edx:eax
  481. # output:       edx:eax = double-precision
  482. .globl eptodp
  483. epdp32: orb $overf,h_stat #this is overflow
  484. call exproc
  485. movw $0x7fe,%cx
  486. movl $-1,%edx
  487. movl %edx,%eax
  488. jmp epdp6
  489. epdp2: shldl $16,%ecx,%ebx #check for stack underflow
  490. cmpb $3,%bl
  491. jz epdp38
  492. btsl $16,%ecx #check zero, denormal
  493. jc epdp3
  494. orw %cx,%cx
  495. jz epdp4
  496. orl %edx,%edx
  497. jns epdp36
  498. jmp epdp30
  499. epdp3: movl %ecx,%edx #return zero
  500. andl $0x80000000,%edx
  501. ret
  502. eptodp:
  503. testl $0x00030000,%ecx #jump if special value
  504. jnz epdp2
  505. epdp4: addw $lBIAS-tBIAS,%cx #adjust the bias
  506. jle epdp20 #   weed out underflow and overflow
  507. cmpw $0x07ff,%cx
  508. jnc epdp32
  509. epdp6: addl %eax,%eax #shift left mantissa to delete hidden bit
  510. adcl %edx,%edx
  511. xorl %ebx,%ebx #discarded bits into ebx
  512. shrdl $12,%eax,%ebx
  513. shrdl $12,%edx,%eax #shift right everything 12 bits
  514. shrdl $11,%ecx,%edx
  515. btl $31,%ecx
  516. rcrl $1,%edx
  517. epdp8: orl %ebx,%ebx #exact = no rounding
  518. jz epdp19
  519. testb $0x0c,h_ctrl+1 #quick round
  520. jnz epdp14
  521. btl $0,%eax
  522. adcl $-1,%ebx
  523. jns epdp17
  524. epdp18: #PREEX   precis+rup
  525. orw $precis+rup,h_stat
  526. testb $precis,h_ctrl
  527. jnz LL1
  528. orw $0x8080,h_stat
  529. movl $exret,-4(%ebp)
  530. LL1:
  531. addl $1,%eax
  532. adcl $0,%edx
  533. ret
  534. epdp17: #PREEXS  precis
  535. orb $precis,h_stat
  536. testb $precis,h_ctrl
  537. jnz LL2
  538. orw $0x8080,h_stat
  539. movl $exret,-4(%ebp)
  540. LL2:
  541. epdp19: andb $0x0fd,h_stat+1
  542. ret
  543. epdp14: roll $8,%ebx #IEEE rounding
  544. cmpl $0x0ff,%ebx
  545. jna epdp11
  546. orb $0x40,%bl
  547. epdp11: call roundi
  548. adcl $0,%eax
  549. adcl $0,%edx
  550. ret
  551. epdp20: negw %cx #this is zero or denormal
  552. jz epdp7
  553. cmpw $53,%cx
  554. jc epdp21
  555. movw $53,%cx
  556. epdp21: shrl $1,%edx
  557. rcrl $1,%eax
  558. jnc epdp22
  559. orl $1,%eax
  560. epdp22: decw %cx
  561. jnz epdp21
  562. epdp7: xorl %ebx,%ebx #discarded bits into ebx
  563. shrdl $12,%eax,%ebx
  564. shrdl $12,%edx,%eax #shift right everything 12 bits
  565. shrdl $11,%ecx,%edx
  566. btl $31,%ecx
  567. rcrl $1,%edx
  568. testb $underf,h_ctrl #set underflow if necessary
  569. jz epdp13
  570. orl %ebx,%ebx
  571. jz epdp19
  572. epdp13: orb $underf,h_stat
  573. call exproc
  574. jmp epdp8
  575. epdp30: movl %edx,%ebx #this is INF or NaN
  576. addl %ebx,%ebx
  577. orl %eax,%ebx
  578. jnz epdp34
  579. movw $0x7ff,%cx
  580. jmp epdp6
  581. epdp38: call getqn
  582. orb $stacku,h_stat
  583. jmp epdp39
  584. epdp36: call getqn #this is NaN
  585. jmp epdp37
  586. epdp34: btl $30,%edx
  587. jc epdp35
  588. epdp37: orb $invop,h_stat
  589. epdp39: call exproc
  590. btsl $30,%edx
  591. epdp35: movw $2*lBIAS+1,%cx
  592. andw $0xf800,%ax
  593. jmp epdp6
  594. # round extended floating-point to whole floating-point
  595. # input:        EP in ecx:edx:eax
  596. # output:       EP in ecx:edx:eax no decimals
  597. .globl eptown
  598. epwn2: call chkarg #check for stack underflow, NaN
  599. jc epwn82
  600. btl $16,%ecx #check zero, denormal
  601. jc epwn82
  602. orw %cx,%cx
  603. jz epwn85
  604. cmpw $1,%cx
  605. jz epwn43
  606. orl %edx,%edx
  607. jns stdnan
  608. epwn82: ret #INF
  609. epwn85: orw $denorm+precis,h_stat
  610. call exproc
  611. epwn43: orb $1,%bl
  612. epwn40: movb $0,%bl #here answer is 0 or 1 or -1
  613. jnz epwn41
  614. shldl $8,%edx,%ebx
  615. addl %edx,%edx
  616. epwn41: orl %eax,%edx
  617. jz epwn42
  618. orb $0x40,%bl
  619. epwn42: xorl %edx,%edx
  620. xorl %eax,%eax
  621. andl $0x80000000,%ecx
  622. movw $0x3fff,%cx
  623. call roundi
  624. jc epwn16
  625. addl $0xc001,%ecx
  626. ret
  627. eptown:
  628. testl $0x00030000,%ecx #jump if special value
  629. jnz epwn2
  630. epwn3: movl %ecx,%esi #number of bits to clear
  631. movw $tBIAS+63,%si
  632. subw %cx,%si
  633. jle epwn8
  634. cmpw $64,%si #over not needed
  635. jnc epwn40
  636. xchgl %esi,%ecx
  637. xorl %ebx,%ebx
  638. cmpb $32,%cl #clear decimal bits
  639. jc epwn21
  640. xchgl %ebx,%eax
  641. xchgl %eax,%edx
  642. jz epwn22
  643. cmpl %ebx,%edx
  644. rcrl $1,%ebx
  645. epwn21: shrdl %cl,%eax,%ebx
  646. shrdl %cl,%edx,%eax
  647. shrl %cl,%edx
  648. epwn22: roll $8,%ebx
  649. cmpl $0x100,%ebx
  650. jc epwn23
  651. orb $0x20,%bl
  652. epwn23: call roundi
  653. adcl $0,%eax
  654. adcl $0,%edx
  655. cmpb $32,%cl
  656. jc epwn24
  657. xchgl %eax,%edx
  658. shrl $1,%eax
  659. adcl $0,%esi
  660. epwn24: shldl %cl,%eax,%edx
  661. adcl $0,%esi
  662. shll %cl,%eax
  663. xchgl %esi,%ecx
  664. epwn16: btsl $31,%edx #set high mantissa bit
  665. epwn8: ret
  666. # extract exponent and mantissa from extended floating-point
  667. # input:        EP in ecx:edx:eax
  668. # output:       mantissa as EP in ecx:edx:eax
  669. #               [edi] exponent as EP
  670. .globl xtract
  671. xtr2: btl $16,%ecx #check zero, denormal
  672. jc xtr80
  673. orw %cx,%cx
  674. jz xtr23
  675. orl %edx,%edx
  676. jns xtr92
  677. jmp xtr90
  678. xtr23: call tnormal #normalize
  679. jmp xtr3
  680. xtract:
  681. movl %ecx,%ebx #save original sign
  682. andl $0x80000000,%ebx
  683. testl $0x00030000,%ecx #jump if special value
  684. jnz xtr2
  685. xtr3: pushl %edx #save the argument
  686. pushl %eax
  687. movswl %cx,%edx #convert real exponent to EP floating-point
  688. subl $tBIAS,%edx
  689. call wiep
  690. orw %cx,%cx
  691. jnz xtr7
  692. orl %ebx,%ecx
  693. xtr7: #PUTEP   
  694. movl %eax,(%edi)
  695. movl %edx,4(%edi)
  696. movl %ecx,8(%edi)
  697. popl %eax #restore original argument
  698. popl %edx
  699. movl $0x3fff,%ecx #make exponent 1
  700. orl %ebx,%ecx
  701. ret
  702. xtr80: orb $zerod,h_stat #argument was 0, store -INF
  703. call exproc
  704. movl %eax,(%edi)
  705. movl $0x80000000,4(%edi)
  706. movl $0x80007fff,8(%edi)
  707. ret
  708. xtr92: call getqn #invalid
  709. jmp xtr97
  710. xtr90: movl %edx,%ebx #either NaN or INF
  711. addl %ebx,%ebx
  712. orl %eax,%ebx
  713. jnz xtr95
  714. movl %eax,(%edi) #argument was INF, store INF
  715. movl $0x7fff,8(%edi)
  716. movl $0x80000000,%edx
  717. movl %edx,4(%edi)
  718. ret
  719. xtr95: btl $30,%edx #NaN, make into quiet
  720. jc xtr96
  721. xtr97: orb $invop,h_stat
  722. call exproc
  723. btsl $30,%edx
  724. xtr96: #PUTEP   
  725. movl %eax,(%edi)
  726. movl %edx,4(%edi)
  727. movl %ecx,8(%edi)
  728. ret
  729. # add integer to exponent or EP
  730. # input:        integer EP in ecx:edx:eax
  731. #               [edi] EP
  732. # output:       EP scaled in ecx:edx:eax
  733. .globl scale
  734. scaw: call retnan #remove NaNs and invalids
  735. movb $0,%bl
  736. movl %ecx,%esi #set denormal exception if either
  737. addl %esi,%esi #   argument denormal
  738. cmpl $0x00040000,%esi
  739. jz sca24
  740. movl 8(%edi),%esi
  741. addl %esi,%esi
  742. cmpl $0x00040000,%esi
  743. jnz sca26
  744. movb $1,8(%edi)
  745. sca24: orb $denorm,h_stat
  746. call exproc
  747. sca26: testb $0x01,10(%edi) #cases x = 0
  748. jz sca28
  749. cmpl $0x00027fff,%ecx
  750. jz stdnan
  751. scazer: xorl %edx,%edx #return zero 
  752. xorl %eax,%eax
  753. movl $0x00010000,%ecx
  754. jmp sca17
  755. sca28: cmpw $0x7fff,8(%edi) #cases x = INF
  756. jnz sca30
  757. cmpl $0x80027fff,%ecx
  758. jz stdnan
  759. #GETEP                   #return x
  760. movl (%edi),%eax
  761. movl 4(%edi),%edx
  762. movl 8(%edi),%ecx
  763. ret
  764. sca30: cmpl $0x80027fff,%ecx #cases n = INF
  765. jz scazer
  766. cmpl $0x00027fff,%ecx
  767. jz sca17
  768. jmp sca4
  769. sca40: movl $-2,%ebx #this is special cases for integer
  770. jmp sca9
  771. sca44: xorl %ebx,%ebx
  772. jmp sca9
  773. scale:
  774. andb $0x0fd,h_stat+1
  775. shldl $16,%ecx,%ebx #weed out special arguments
  776. orb 10(%edi),%bl
  777. jnz scaw
  778. sca4: movl %ecx,%esi #save the sign
  779. subw $tBIAS+15,%cx #calculate shift count
  780. ja sca40
  781. negw %cx
  782. cmpw $16,%cx
  783. jnc sca44
  784. addb $16,%cl
  785. shrl %cl,%edx #integer -> bx
  786. movl %edx,%ebx
  787. sca9: #GETEP                   #load the EP
  788. movl (%edi),%eax
  789. movl 4(%edi),%edx
  790. movl 8(%edi),%ecx
  791. andl $0xffff,%ebx #we need 32-bit integers
  792. andl $0xffff,%ecx
  793. sarl $31,%esi #make twos complement of integer
  794. xorl %esi,%ebx
  795. subl %esi,%ebx
  796. addl %ebx,%ecx #add integer to exponent
  797. jle sca70
  798. cmpl $0x7fff,%ecx
  799. jge sca74
  800. orl %edx,%edx #also check for denormal
  801. jns sca78
  802. movb $0,%bl #no extra bits here
  803. sca17: roll $16,%ecx #put sign in place
  804. movb 11(%edi),%ch
  805. roll $16,%ecx
  806. ret
  807. sca70: cmpl $0xffff8000,%ecx #renormalization needed
  808. jge sca71
  809. movw $0x8000,%cx
  810. sca71: clc
  811. jmp sca78
  812. sca74: stc
  813. sca78: movb $0,%bl
  814. call renorm
  815. jmp sca17
  816. itsstu: orb $stacku,h_stat
  817. jmp nan3
  818. itsnan: btl $30,%edx
  819. jc nan9
  820. stdnan: orb $invop,h_stat
  821. nan3: call getqn
  822. call exproc
  823. btsl $30,%edx
  824. nan9: xorl %ebx,%ebx
  825. ret
  826. #        subttl  CCALL Arithmetic Operations
  827. #        page
  828. # examine an EP operand
  829. # input:        ecx:edx:eax
  830. # output:       condition bits in al
  831. .globl epexam
  832. epexam:
  833. xorl %ebx,%ebx #first set sign bit
  834. shldl $2,%ecx,%ebx
  835. testl $0x00030000,%ecx #check for specials
  836. jnz exa10
  837. exa8: orb $4,%bl #regular bit
  838. exa9: movb %bl,%al #return bits
  839. ret
  840. exa10: btl $16,%ecx #check for zero, NaN, unsupported
  841. jc exa12
  842. orw %cx,%cx
  843. jz exa14
  844. orl %edx,%edx
  845. jns exa9
  846. exa20: orb $0x01,%bl #INF or NaN
  847. addl %edx,%edx
  848. orl %eax,%edx
  849. jnz exa9
  850. jmp exa8
  851. exa14: orb $0x4,%bl #denormal case
  852. exa12: orb $0x40,%bl #zero case
  853. jmp exa9
  854. # compare two EP operands
  855. # input:        cx:edx:eax
  856. #               in epcomu quiet NaN will not cause exception
  857. # output:       ST - input -> condition bits in al
  858. .globl epcomp, epcomu, xcmp
  859. epcomu:
  860. movb $1,%bl #unordered entry
  861. jmp cmp1
  862. epcomp:
  863. movb $0,%bl #Intel entry
  864. cmp1: movl 8(%edi),%esi #sign, exponent of B
  865. shldl $16,%ecx,%ebx #weed out special arguments
  866. orb 10(%edi),%bl
  867. jnz cmpw
  868. cmp7: movl %ecx,%ebx #set bit in bh if both negative
  869. andl %esi,%ebx
  870. shrl $23,%ebx
  871. subl (%edi),%eax #compare hook line and sinker
  872. sbbl 4(%edi),%edx
  873. sbbl %esi,%ecx
  874. jz cmp10
  875. setnl %al
  876. cmp8: xorb %bh,%al #if both negative, complement answer
  877. cmp9: andb $0x0b8,h_stat+1
  878. orb %al,h_stat+1
  879. ret
  880. cmp10: orl %eax,%edx #possibly equal
  881. movb $1,%al
  882. jnz cmp8
  883. cmpeq: movb $0x40,%al
  884. jmp cmp9
  885. cmpw: andb $0x0b8,h_stat+1
  886. orb $0x45,h_stat+1
  887. call retnan
  888. xcmp: shldl $16,%ecx,%ebx #two zeroes are equal regardless of sign
  889. andb 10(%edi),%bl
  890. testb $1,%bl
  891. jnz cmpeq
  892. movl %ecx,%ebx #set denormal exception if either
  893. addl %ebx,%ebx #   argument denormal
  894. cmpl $0x00040000,%ebx
  895. jz cmpw2
  896. movl %esi,%ebx
  897. addl %ebx,%ebx
  898. cmpl $0x00040000,%ebx
  899. jnz cmpw4
  900. cmpw2: orb $denorm,h_stat
  901. testb $denorm,h_ctrl
  902. jnz cmpw4
  903. orw $0x8080,h_stat
  904. movl $exret,-4(%ebp)
  905. cmpw4: orw %cx,%cx #adjust exponent of pseudo-denormal
  906. jnz cmpw5
  907. orl %edx,%edx
  908. jns cmpw5
  909. incl %ecx
  910. cmpw5: orw %si,%si
  911. jnz cmpw6
  912. testb $0x80,7(%edi)
  913. jz cmpw6
  914. incl %esi
  915. cmpw6: andl $0x8000ffff,%ecx
  916. andl $0x8000ffff,%esi
  917. jmp cmp7
  918. # add/subtract from registers to stack
  919. # input:        ecx:edx:eax = EP number
  920. # result:       registers = ST + number
  921. .globl epadd,epadd1,epsub,epsubr
  922. epsub:
  923. shldl $16,%ecx,%ebx #weed out special arguments
  924. orb 10(%edi),%bl
  925. jnz sub2
  926. movl 8(%edi),%esi
  927. xorl $0x80000000,%esi
  928. jmp epadd2
  929. sub2: call retnan #handle special arguments
  930. xorb $0x80,11(%edi)
  931. jmp addw
  932. epsubr:
  933. shldl $16,%ecx,%ebx #weed out special arguments
  934. orb 10(%edi),%bl
  935. jnz subr2
  936. xorl $0x80000000,%ecx
  937. jmp epadd1
  938. subr2: call retnan #handle special arguments
  939. xorl $0x80000000,%ecx
  940. addw: testb $0x02,%bl #zero is handled normally
  941. jz epadd1
  942. call retnan #first remove NaNs and invalids
  943. cmpw $0x7fff,%cx #weed out A = INF
  944. jnz addw3
  945. cmpw %cx,8(%edi)
  946. jnz addrta
  947. movl %ecx,%esi
  948. xorl 8(%edi),%esi
  949. jns addrta
  950. jmp stdnan
  951. addrtb: #GETEP                   #return B or A as such
  952. movl (%edi),%eax
  953. movl 4(%edi),%edx
  954. movl 8(%edi),%ecx
  955. addrta: movb $0,%bl
  956. ret
  957. addw3: cmpw $0x7fff,8(%edi) #weed out B = INF
  958. jz addrtb
  959. call tnormal #normalize arguments
  960. xchgl %eax,(%edi)
  961. xchgl %edx,4(%edi)
  962. xchgl %ecx,8(%edi)
  963. call tnormal
  964. jmp epadd1
  965. epadd:
  966. shldl $16,%ecx,%ebx #weed out special arguments
  967. orb 10(%edi),%bl
  968. jnz addw
  969. epadd1: movl 8(%edi),%esi #the other exponent
  970. epadd2: cmpw %si,%cx #if exponent of A > exponent of B,
  971. jl add7 #   we swap arguments
  972. movl $0,%ebx
  973. je add34
  974. xchgl %eax,(%edi)
  975. xchgl %edx,4(%edi)
  976. xchgl %ecx,%esi
  977. add7: subw %si,%cx
  978. negw %cx
  979. call shiftr #shift mantissa right by cl
  980. movw %si,%cx #load the exponent
  981. add34: andl $0x8000ffff,%ecx #clear special bits
  982. xorl %ecx,%esi #go subtract if different signs
  983. js add20
  984. addl (%edi),%eax #add mantissas
  985. adcl 4(%edi),%edx
  986. jnc add15
  987. rcrl $1,%edx
  988. rcrl $1,%eax
  989. rcrb $1,%bl
  990. incl %ecx
  991. cmpw $0x7fff,%cx
  992. je add19
  993. add15: orw %cx,%cx #renormalize if needed
  994. jle add28
  995. ret
  996. add20: sbbl (%edi),%eax #subtract mantissas
  997. sbbl 4(%edi),%edx
  998. jnc add24
  999. xorl $0x80000000,%ecx
  1000. notl %edx
  1001. notl %eax
  1002. negb %bl
  1003. sbbl $-1,%eax
  1004. sbbl $-1,%edx
  1005. add24: jns add25 #weed out not-normal, possible all-zero
  1006. orw %cx,%cx
  1007. jle add19
  1008. ret
  1009. add25: je add27 #here needs normalizing, or is zero             
  1010. add26: decw %cx
  1011. addb %bl,%bl
  1012. adcl %eax,%eax
  1013. adcl %edx,%edx
  1014. jns add26
  1015. orw %cx,%cx
  1016. jle add19
  1017. ret
  1018. add28: orl %edx,%edx #this may be 0+0
  1019. jnz add19
  1020. movb %bl,%dl
  1021. orl %eax,%edx
  1022. jnz add22
  1023. btsl $16,%ecx
  1024. ret
  1025. add27: orb %bl,%dl #here may be all zero
  1026. orl %eax,%edx
  1027. jz addzer
  1028. add22: xorl %edx,%edx
  1029. add19: call renorm #normalize
  1030. ret
  1031. addzer: movl $0x00010000,%ecx #result went all the way to zero
  1032. movb h_ctrl+1,%bh
  1033. andb $0x0c,%bh
  1034. cmpb $0x04,%bh
  1035. jnz add18
  1036. btsl $31,%ecx
  1037. add18: ret
  1038. # multiply registers to stack
  1039. # input:        cx:edx:eax = EP number
  1040. # result:       registers = ST * number
  1041. .globl epmul,epmul1
  1042. mulzer: shrl $16,%ecx
  1043. movb $1,%cl
  1044. shll $16,%ecx
  1045. xorl %edx,%edx
  1046. jmp mulin2
  1047. mulinf: orl $0x00027fff,%ecx #return INF
  1048. movl $0x80000000,%edx
  1049. mulin2: xorl %eax,%eax
  1050. xorb %bl,%bl
  1051. jmp mul21
  1052. mulw: call retnan #weed out NaN arguments
  1053. movl %ecx,%esi #weed out special cases
  1054. addl 8(%edi),%esi
  1055. btrl $31,%esi
  1056. cmpl $0x37fff,%esi
  1057. jz stdnan
  1058. testb $1,%bl
  1059. jnz mulzer
  1060. cmpw $0x7fff,%si
  1061. jnc mulinf
  1062. call tnormal #normalize arguments if needed
  1063. xchgl %eax,(%edi)
  1064. xchgl %edx,4(%edi)
  1065. xchgl %ecx,8(%edi)
  1066. call tnormal
  1067. jmp epmul1
  1068. epmul:
  1069. shldl $16,%ecx,%ebx #weed out special arguments
  1070. orb 10(%edi),%bl
  1071. jnz mulw
  1072. epmul1: pushl %ebp #save exponent, sign, FP stack pointer
  1073. pushl %ecx
  1074. movl %eax,%esi #save A0123
  1075. movl %edx,%ecx
  1076. mull (%edi) # A23 * B23
  1077. xchgl %eax,%esi
  1078. movl %edx,%ebx
  1079. mull 4(%edi) # A23 * B01
  1080. addl %eax,%ebx
  1081. adcl $0,%edx
  1082. movl %edx,%ebp
  1083. movl (%edi),%eax # A01 * B23
  1084. mull %ecx
  1085. addl %eax,%ebx
  1086. adcl %edx,%ebp
  1087. movl $0,%eax
  1088. adcl $0,%eax
  1089. xchgl %ecx,%eax
  1090. mull 4(%edi) # A01 * B01
  1091. addl %ebp,%eax
  1092. adcl %ecx,%edx
  1093. popl %ecx #exponent
  1094. js mul42 #possibly normalize
  1095. addl %ebx,%ebx
  1096. adcl %eax,%eax
  1097. adcl %edx,%edx
  1098. decl %ecx
  1099. mul42: addl $-1,%esi #set rounding bits
  1100. adcl %ebx,%ebx
  1101. jz mul43
  1102. movb $0x80,%bl
  1103. mul43: rcrb $1,%bl
  1104. popl %ebp #restore base pointer
  1105. subw $tBIAS-2,%cx #calculate new exponent
  1106. addw 8(%edi),%cx
  1107. jo mul44
  1108. decw %cx
  1109. jle mul45
  1110. mul21: roll $8,%ecx #put in sign
  1111. xorb 11(%edi),%cl
  1112. rorl $8,%ecx
  1113. ret #return
  1114. mul44: stc #here re-normalize
  1115. jmp mul46
  1116. mul45: clc
  1117. mul46: call renorm
  1118. jmp mul21
  1119. # divide registers to stack
  1120. # input:        cx:edx:eax = EP number
  1121. # result:       registers = ST / number
  1122. .globl epdiv,epdivr,epdiv1
  1123. divw61: orb $zerod,h_stat
  1124. call exproc
  1125. jmp mulinf
  1126. divw: call retnan #weed out NaN arguments
  1127. cmpw $0x7fff,%cx #weed out A = INF
  1128. jnz divw3
  1129. cmpw %cx,8(%edi)
  1130. jz stdnan
  1131. jmp mulinf
  1132. divw3: cmpw $0x7fff,8(%edi) #weed out B = INF
  1133. jz mulzer
  1134. btl $16,%ecx #if A = 0 and B = 0 return NaN
  1135. jnc divw7
  1136. testb $1,10(%edi)
  1137. jnz stdnan
  1138. jmp mulzer
  1139. divw7: testb $1,10(%edi) #if B = 0 "zero divide"
  1140. jnz divw61
  1141. call tnormal #normalize arguments
  1142. xchgl %eax,(%edi)
  1143. xchgl %edx,4(%edi)
  1144. xchgl %ecx,8(%edi)
  1145. call tnormal
  1146. xchgl %eax,(%edi)
  1147. xchgl %edx,4(%edi)
  1148. xchgl %ecx,8(%edi)
  1149. jmp epdiv1
  1150. epdivr:
  1151. xchgl (%edi),%eax
  1152. xchgl 4(%edi),%edx
  1153. xchgl 8(%edi),%ecx
  1154. epdiv:
  1155. shldl $16,%ecx,%ebx #weed out special arguments
  1156. orb 10(%edi),%bl
  1157. jnz divw
  1158. epdiv1: pushl %ebp #save exponent, sign
  1159. pushl %ecx
  1160. movl $1,%ebp #first bit = 0
  1161. cmpl 4(%edi),%edx #jump if x < y
  1162. jc div50
  1163. subl 0(%edi),%eax #get first bit
  1164. sbbl 4(%edi),%edx
  1165. jnc div49
  1166. movl %eax,%edx #prevent overflow
  1167. xorl %eax,%eax
  1168. movl %eax,%ecx
  1169. jmp div31
  1170. div49: decl %ebp #first bit = 1
  1171. div50: divl 4(%edi) # q = A0123 / B01 -> ebx
  1172. movl %eax,%ecx #     r -> esi
  1173. movl %edx,%esi
  1174. mull 0(%edi) # x * B23 -> edx:eax
  1175. xchgl %edx,%esi #subtract that from qA23
  1176. negl %eax
  1177. sbbl %esi,%edx
  1178. jnc div41
  1179. div31: decl %ecx
  1180. addl 0(%edi),%eax
  1181. adcl 4(%edi),%edx
  1182. jnc div31
  1183. div41: cmpl 4(%edi),%edx #prevent overflow
  1184. jnz div51
  1185. movl %eax,%esi
  1186. xorl %eax,%eax
  1187. movl %eax,%ebx
  1188. subl 0(%edi),%esi
  1189. jmp div32
  1190. div51: divl 4(%edi) # x = A0123 / B01 -> bx
  1191. movl %eax,%ebx
  1192. movl %edx,%esi
  1193. mull 0(%edi) #then q * B23 -> edx:eax
  1194. negl %eax #subtract that from qA23
  1195. sbbl %edx,%esi
  1196. jnc div42
  1197. div32: decl %ebx
  1198. addl 0(%edi),%eax
  1199. adcl 4(%edi),%esi
  1200. jnc div32
  1201. div42: movl %esi,%edx #set rounding bit, first bit flag
  1202. orl %eax,%edx
  1203. xchgl %ebx,%edx
  1204. jz div54
  1205. movb $0x80,%bl
  1206. addl %eax,%eax
  1207. adcl %esi,%esi
  1208. jc div43
  1209. subl 0(%edi),%eax
  1210. sbbl 4(%edi),%esi
  1211. cmc
  1212. div43: rcrb $1,%bl
  1213. div54: movl %edx,%eax #load result to edx:eax
  1214. movl %ecx,%edx
  1215. popl %ecx #restore registers
  1216. cmpl $1,%ebp #handle first bit
  1217. jnc div57
  1218. rcrl $1,%edx
  1219. rcrl $1,%eax
  1220. rcrb $1,%bl
  1221. incw %cx
  1222. div57: popl %ebp
  1223. subw 8(%edi),%cx #calculate new exponent
  1224. addw $tBIAS-0,%cx
  1225. jo div23
  1226. decw %cx
  1227. jle div24
  1228. div21: roll $8,%ecx #put in sign
  1229. xorb 11(%edi),%cl
  1230. rorl $8,%ecx
  1231. ret
  1232. div23: stc #renormalize if needed
  1233. jmp div26
  1234. div24: clc
  1235. div26: call renorm
  1236. jmp div21
  1237. # partial remainder, Intel version
  1238. # input:        cx:edx:eax = EP number
  1239. # result:       registers = ST % number
  1240. .globl eprem
  1241. res88: cmpw $-1,%cx #here exponent of A < exponent of B
  1242. jnz rem83 #   return A unless A > B/2
  1243. pushl %eax #   in which case return A-B
  1244. pushl %edx
  1245. shll $1,(%edi)
  1246. rcll $1,4(%edi)
  1247. btrl $31,%edx
  1248. jmp res17
  1249. rem87: btl $16,%ebx #branch if IEEE remainder
  1250. jc res88
  1251. rem83: jmp rem16
  1252. remw: andb $0x0fb,h_stat+1 #clear C2
  1253. call retnan #remove NaNs and invalids
  1254. andb $0x0b8,h_stat+1 #clear condition codes
  1255. btl $16,%ecx #if B = 0 or A = INF return NaN
  1256. jc stdnan
  1257. cmpw $0x7fff,%si
  1258. jz stdnan
  1259. call tnormal #normalize arguments
  1260. xchgl %eax,(%edi)
  1261. xchgl %edx,4(%edi)
  1262. xchgl %ecx,%esi
  1263. cmpw $0x7fff,%si
  1264. jz rem17
  1265. btl $16,%ecx
  1266. jc rem19
  1267. call tnormal
  1268. jmp rem3
  1269. eprem:
  1270. movl 8(%edi),%esi
  1271. shldl $16,%ecx,%ebx #weed out special arguments
  1272. orb 10(%edi),%bl
  1273. jnz remw
  1274. andb $0x0b8,h_stat+1 #clear condition codes
  1275. xchgl (%edi),%eax #swap registers
  1276. xchgl 4(%edi),%edx
  1277. xchgl %esi,%ecx
  1278. rem3: movb $0,%bl #initialize quotient
  1279. subw %si,%cx #get the shift count
  1280. js rem87
  1281. cmpw $64,%cx #maximum shift count 64
  1282. jl rem4
  1283. addw %cx,%si
  1284. orb $32,%cl
  1285. andw $63,%cx
  1286. subw %cx,%si
  1287. orb $0x04,h_stat+1
  1288. rem4: movw %si,8(%edi)
  1289. pushl %ebp #save registers
  1290. movl (%edi),%ebp
  1291. movl 4(%edi),%esi
  1292. rem5: subl %ebp,%eax #divide using shift-subtract
  1293. sbbl %esi,%edx
  1294. jnc rem9
  1295. addl %ebp,%eax
  1296. adcl %esi,%edx
  1297. rem9: cmc
  1298. rem11: adcb %bl,%bl
  1299. decb %cl
  1300. js rem15
  1301. addl %eax,%eax
  1302. adcl %edx,%edx
  1303. jnc rem5
  1304. subl %ebp,%eax
  1305. sbbl %esi,%edx
  1306. jmp rem11
  1307. rem15: popl %ebp #restore registers
  1308. testb $0x04,h_stat+1 #if C2 is set (incomplete)
  1309. jnz rem16 #   leave Q zero
  1310. testl $0x10000,%ebx #branch if IEEE remainder
  1311. jnz res18
  1312. rem41: andl $7,%ebx #massage quotient for the required form
  1313. rorw $1,%bx #   bits are discontinuous and reversed
  1314. shrb $4,%bh
  1315. rorw $1,%bx
  1316. shrb $2,%bh
  1317. shlb $7,%bl
  1318. shll $1,%ebx
  1319. orb %bh,h_stat+1
  1320. rem16: movw 8(%edi),%cx #normalize
  1321. rem17: xorb %bl,%bl
  1322. call renorm
  1323. rem19: ret
  1324. res18: pushl %eax #save remainder
  1325. pushl %edx
  1326. res17: addl %eax,%eax #if next quotent bit would be 0, we are
  1327. adcl %edx,%edx #   done
  1328. setc %bh
  1329. subl (%edi),%eax
  1330. sbbl 4(%edi),%edx
  1331. sbbb $0,%bh
  1332. jc res42
  1333. movl %ebx,%esi #next bit is one, if all the rest are 0,
  1334. andl $1,%esi #   and Q is even, we are likewise done
  1335. orl %edx,%esi
  1336. orl %eax,%esi
  1337. jz res42
  1338. incl %ebx #here we round up the quotient
  1339. popl %edx
  1340. popl %eax
  1341. subl (%edi),%eax
  1342. sbbl 4(%edi),%edx
  1343. notl %edx
  1344. negl %eax
  1345. sbbl $-1,%edx
  1346. btcl $31,%ecx
  1347. jmp rem41
  1348. res42: popl %edx
  1349. popl %eax
  1350. jmp rem41
  1351. # square-root
  1352. # input:        ecx:edx:eax = EP number
  1353. # result:       ST = sqrt(number)
  1354. .globl epsqrt
  1355. sqr89: ret
  1356. sqrw: xorl %ebx,%ebx
  1357. btl $16,%ecx #zero returns as such
  1358. jc sqr89
  1359. orw %cx,%cx #check for unsupported
  1360. jz sqrw5
  1361. orl %edx,%edx
  1362. jns stdnan
  1363. cmpw $0x7fff,%cx #check for NaN
  1364. jnz sqrw5
  1365. movl %edx,%ebx
  1366. addl %ebx,%ebx
  1367. orl %eax,%ebx
  1368. jnz nanret
  1369. sqrw5: orl %ecx,%ecx #negative is illegal
  1370. js stdnan
  1371. cmpw $0x7fff,%cx #+INF returns as such
  1372. jz sqr89
  1373. call tnormal #normalize
  1374. movl %ecx,8(%edi)
  1375. jmp sqr2
  1376. epsqrt:
  1377. testl $0x80030000,%ecx #jump if special value
  1378. jnz sqrw
  1379. sqr2:
  1380. pushl %ebp #save registers
  1381. pushl %edi
  1382. xorl %ebx,%ebx #save x, possibly shifted right by 1
  1383. movl %eax,%esi
  1384. andb $1,%cl
  1385. shrdl %cl,%esi,%ebx
  1386. shrdl %cl,%edx,%esi
  1387. pushl %esi
  1388. pushl %ebx
  1389. incl %ecx #load high 30 or 31 bits -> esi:edi
  1390. shrdl %cl,%edx,%eax
  1391. shrl %cl,%edx
  1392. movl %edx,%esi
  1393. movl %eax,%edi
  1394. testb $1,%cl #get first estimate with a*x+b
  1395. movl $0x4d12cfe4,%ebx
  1396. jz sqr3
  1397. movl $0x6cff9300,%ebx
  1398. sqr3: shldl $17,%esi,%eax
  1399. mulw %bx
  1400. shrl $16,%ebx
  1401. addw %dx,%bx
  1402. movl %esi,%eax #16-bit iteration y = (x/y + y)/2
  1403. shldl $16,%esi,%edx
  1404. divw %bx
  1405. shrw $1,%bx
  1406. addw %ax,%bx
  1407. sbbw $0,%bx
  1408. shll $16,%ebx
  1409. movl %esi,%edx #32-bit iteration y = (x/y + y)/2
  1410. movl %edi,%eax
  1411. divl %ebx
  1412. shrl $1,%ebx
  1413. addl %eax,%ebx
  1414. sbbl $0,%ebx
  1415. movl %esi,%edx #64-bit iteration y = (x/y + y)/2
  1416. movl %edi,%eax
  1417. divl %ebx
  1418. movl %eax,%ecx
  1419. xorl %eax,%eax
  1420. divl %ebx
  1421. xorl %edx,%edx
  1422. shrl $1,%ebx
  1423. rcrl $1,%edx
  1424. addl %edx,%eax
  1425. adcl %ebx,%ecx
  1426. movl %eax,%ebx #mantissa of y -> ecx:ebx
  1427. mull %eax #calculate y^2 -> (none):si:edi:ebp
  1428. movl %eax,%ebp
  1429. movl %edx,%edi
  1430. movl %ecx,%eax
  1431. mull %eax
  1432. movl %eax,%esi
  1433. movl %ebx,%eax
  1434. mull %ecx
  1435. addl %eax,%edi
  1436. adcl %edx,%esi
  1437. addl %eax,%edi
  1438. adcl %edx,%esi
  1439. movl %ebx,%eax #mantissa of y -> ecx:eax
  1440. popl %ebx #now y^2 - x into si:edi:ebp
  1441. subl %ebx,%edi
  1442. popl %ebx
  1443. sbbl %ebx,%esi
  1444. js sqr37
  1445. jz sqr35
  1446. sqr31: subl $1,%eax #try out next smallest y 
  1447. sbbl $0,%ecx
  1448. stc #new residue = old - 2y + 1
  1449. sbbl %eax,%ebp
  1450. sbbl %ecx,%edi
  1451. sbbl $0,%esi
  1452. subl %eax,%ebp
  1453. sbbl %ecx,%edi
  1454. sbbl $0,%esi
  1455. jns sqr31 #more if we are still above real sqrt(x)
  1456. cmc
  1457. sqr32: sbbb %bl,%bl #1/2 bit here, never exactly half
  1458. orb $0x40,%bl
  1459. sqr33: movl %ecx,%edx
  1460. popl %edi #restore registers
  1461. popl %ebp
  1462. movl 8(%edi),%ecx #calculate new exponent
  1463. shrw $1,%cx
  1464. adcw $0x1fff,%cx
  1465. ret
  1466. sqr37: stc #try next largest x
  1467. adcl %eax,%ebp
  1468. adcl %ecx,%edi
  1469. adcl $0,%esi
  1470. addl %eax,%ebp
  1471. adcl %ecx,%edi
  1472. adcl $0,%esi
  1473. jns sqr32 #quit if differential > 0
  1474. addl $1,%eax
  1475. adcl $0,%ecx
  1476. jmp sqr37
  1477. sqr35: movl %edi,%ebx #see if we have an exact answer
  1478. orl %ebp,%ebx
  1479. jz sqr33
  1480. jmp sqr31
  1481. #__lib   endp
  1482. #emuseg  ends
  1483. #        end