home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mntlib32.zoo / _addsubs.cpp < prev    next >
Text File  |  1993-06-17  |  7KB  |  274 lines

  1. |
  2. | single floating point add/subtract routine
  3. |
  4. #ifndef    __M68881__
  5.     .text
  6.     .even
  7.     .globl    __subsf3, ___subsf3
  8.     .globl    __addsf3, ___addsf3
  9. # ifndef sfp004
  10. |
  11. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  12. | Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
  13. |
  14. | Revision 1.3.5 michal 05-93 (ntomczak@vm.ucs.ualberta.ca)
  15. |   + ensure that x - x always returns +0, says IEEE,
  16. |     unless x is Inf or NaN - then return NaN
  17. |   + code smoothing
  18. |
  19. | patched by Olaf Flebbe (flebbe@tat.physik.uni-tuebingen.de)
  20. |
  21. | Revision 1.3.4 olaf 11-92 :
  22. |  + added support for NaN and infinities
  23. |    > paranoia now dont complains about unbalanced range any more
  24. |  -- still lacks trap handling for exceptions
  25. |  -- dont know the external representation of quiet and signaling NaN
  26. |     I decided 0x7fffffff to be a quiet NaN
  27. |     the rest should be signaling (but isnt)
  28. |
  29. | Revision 1.3.3 olaf 11-92 :
  30. |  + changed to get rid of rounding bits. a sticky register (d3) is
  31. |    sufficient.
  32. |
  33. | Revision 1.3.2 olaf 10-92 :
  34. |  + increased comparson by one again. (Dont understand, but it works)
  35. |  + corrected negation of rounding bits and mantissa
  36. |     >enquire now detects correct IEEE precision
  37. |     >paranoia now qualifies add/sub as correctly rounded
  38. |
  39. | Revision 1.3.1 olaf 10-92 :
  40. |  + increased comparison of exponents by one.
  41. |  + initialized sticky byte
  42. |  + corrected handling of rounding bits
  43. |  + corrected swapping of register halves
  44. |     >paranoia now detects only one (obscure) SERIOUS DEFECT.
  45. |     ** Patches need _normsf Rev 1.4.1 (or higher) **
  46. |
  47. | Revision 1.3, kub 01-90 :
  48. | added support for denormalized numbers
  49. |
  50. | Revision 1.2, kub 01-90 :
  51. | replace far shifts by swaps to gain speed (more optimization is of course
  52. | possible by doing shifts all in one intruction, but what about the rounding
  53. | bits)
  54. |
  55. | Revision 1.1, kub 12-89 :
  56. | Created single float version for 68000
  57. |
  58. | Revision 1.0:
  59. | original 8088 code from P.S.Housel for double floats
  60.  
  61. __subsf3:
  62. ___subsf3:
  63.     eorb    #0x80,sp@(8)    | reverse sign of v
  64. __addsf3:
  65. ___addsf3:
  66.     lea    sp@(4),a0    | pointer to u and v parameter
  67.     moveml    d2-d5,sp@-    | save registers
  68.     moveml    a0@,d4/d5    | d4 = v, d5 = u
  69.  
  70.     movel    #0x7fffff,d3
  71.     movel    d5,d0        | d0 = u.exp
  72.     movel    d5,d2        | d2.h = u.sign
  73.     swap    d0
  74.     movew    d0,d2        | d2 = u.sign
  75.     andl    d3,d5        | remove exponent from u.mantissa
  76.  
  77.     movel    d4,d1        | d1 = v.exp
  78.     andl    d3,d4        | remove exponent from v.mantissa
  79.     swap    d1
  80.     eorw    d1,d2        | d2 = u.sign ^ v.sign (in bit 15)
  81.     clrb    d2        | we will use the lowest byte as a flag
  82.     moveq    #15,d3
  83.     bclr    d3,d1        | kill sign bit u.exp
  84.     bclr    d3,d0        | kill sign bit u.exp
  85.     btst    d3,d2        | same sign for u and v?
  86.     bne    0f
  87.     cmpl    d0,d1        | different signs - maybe x - x ?
  88.     seq    d2        | set 'cancellation' flag
  89. 0:
  90.     lsrw    #7,d0        | keep here exponents only
  91.     lsrw    #7,d1
  92. |
  93. | Now perform testing of NaN and infinities
  94. |
  95.     moveq    #-1,d3
  96.     cmpb    d3,d0
  97.     beq    0f
  98.     cmpb    d3,d1
  99.     bne    nospec
  100.     bra    1f
  101. |
  102. |    u is special
  103. |
  104. 0:    tstb    d2        
  105.     bne    retnan        | cancellation of specials -> NaN
  106.     tstl    d5
  107.     bne    retnan        | arith with Nan gives always NaN
  108.  
  109.     addqw    #4,a0        | here is an infinity
  110.     cmpb    d3,d1
  111.     bne    0f        | skip check for NaN if v not special
  112. |
  113. |    v is special
  114. |
  115. 1:    tstl    d4
  116.     bne    retnan
  117. 0:    movel    a0@,d0
  118.     bra    return
  119. |
  120. | return a quiet NaN
  121. |
  122. retnan: moveql    #-1,d0
  123.     lsrl    #1,d0        | 0x7fffffff -> d0
  124.     bra    return
  125. |
  126. | Ok, no inifinty or NaN involved..
  127. |
  128. nospec:    tstb    d2
  129.     beq    0f
  130.     moveq    #0,d0        | x - x hence we always return +0
  131. return:    moveml    sp@+,d2-d5
  132.     rts
  133.  
  134. 0:    moveq    #23,d3
  135.     bset    d3,d5        | restore implied leading "1"
  136.     tstw    d0        | check for zero exponent - no leading "1"
  137.     bne    1f
  138.     bclr    d3,d5        | remove it
  139.     addqw    #1,d0        | "normalize" exponent
  140. 1:
  141.     bset    d3,d4        | restore implied leading "1"
  142.     tstw    d1        | check for zero exponent - no leading "1"
  143.     bne    1f
  144.     bclr    d3,d4        | remove it
  145.     addqw    #1,d1        | "normalize" exponent
  146. 1:
  147.     moveq    #0,d3        | (put initial zero rounding bits in d3)
  148.     negw    d1        | d1 = u.exp - v.exp
  149.     addw    d0,d1
  150.     beq    5f        | exponents are equal - no shifting neccessary
  151.     bgt    1f        | not equal but no exchange neccessary
  152.     exg    d4,d5        | exchange u and v
  153.     subw    d1,d0        | d0 = u.exp - (u.exp - v.exp) = v.exp
  154.     negw    d1
  155.     tstw    d2        | d2.h = u.sign ^ (u.sign ^ v.sign) = v.sign
  156.     bpl    1f
  157.     bchg    #31,d2
  158. 1:
  159.     cmpw    #26,d1        | is u so much bigger that v is not
  160.     bge    7f        | significant ?
  161. |
  162. | shift mantissa left two digits, to allow cancellation of
  163. | most significant digit, while gaining an additional digit for
  164. | rounding.
  165. |
  166.     moveql    #1,d3
  167. 2:    addl    d5,d5
  168.     subqw    #1,d0        | decrement exponent
  169.     subqw    #1,d1        | done shifting altogether ?
  170.     dbeq    d3,2b        | loop if still can shift u.mant more
  171.     moveq    #0,d3
  172.  
  173.     cmpw    #16,d1        | see if fast rotate possible
  174.     blt    4f
  175.     orw    d4,d3        | set rounding bits
  176.     clrw    d4
  177.     swap    d4
  178.     subqw    #8,d1
  179.     subqw    #8,d1
  180.         bra     4f
  181.  
  182. 0:    moveb   d4,d2
  183.     andb    #1,d2
  184.     orb    d2,d3
  185.     lsrl    #1,d4        | shift v.mant right the rest of the way
  186. 4:    dbra    d1,0b        | loop
  187.  
  188. 5:
  189.     tstw    d2        | are the signs equal ?
  190.     bpl    6f        | yes, no negate necessary
  191.  
  192.  
  193.     tstw    d3        | negate rounding bits and v.mant
  194.     beq    9f
  195.     addql    #1,d4
  196. 9:    negl    d4
  197.  
  198. 6:
  199.     addl    d4,d5        | u.mant = u.mant + v.mant
  200.     bcs    7f        | needn not negate
  201.     tstw    d2        | opposite signs ?
  202.     bpl    7f        | do not need to negate result
  203.  
  204.     negl    d5
  205.     notl    d2        | switch sign
  206. 7:
  207.     movel    d5,d4        | move result for normalization
  208.     clrl    d1
  209.     tstl    d3
  210.     beq    8f
  211.     moveql    #-1,d1
  212. 8:    swap    d2        | put sign into d2 (exponent is in d0)
  213.     jmp    norm_sf        | leave registers on stack for norm_sf
  214.  
  215. # else    sfp004
  216.  
  217. | single precision floating point stuff for Atari-gcc using the SFP004
  218. | developed with gas
  219. |
  220. |  single floating point add/subtract routine
  221. |
  222. | M. Ritzert (mjr at dmzrzu71)
  223. |
  224. | 4.10.1990
  225. |
  226. | no NAN checking implemented since the 68881 treats this situation "correct",
  227. | i.e. according to IEEE
  228.  
  229. | addresses of the 68881 data port. This choice is fastest when much data is
  230. | transferred between the two processors.
  231.  
  232. comm =     -6
  233. resp =    -16
  234. zahl =      0
  235.  
  236. | waiting loop ...
  237. |
  238. | wait:
  239. | ww:    cmpiw    #0x8900,a0@(resp)
  240. |     beq    ww
  241. | is coded directly by
  242. |    .long    0x0c688900, 0xfff067f8
  243.  
  244. __subsf3:
  245. ___subsf3:
  246.     lea    0xfffffa50:w,a0
  247.     movew    #0x4400,a0@(comm)    | load first argument to fp0
  248.     cmpiw    #0x8900,a0@(resp)    | check
  249.     movel    a7@(4),a0@
  250.     movew    #0x4428,a0@(comm)
  251.     .long    0x0c688900, 0xfff067f8
  252.     movel    a7@(8),a0@
  253.     movew    #0x6400,a0@(comm)    | result to d0
  254.     .long    0x0c688900, 0xfff067f8
  255.     movel    a0@,d0
  256.      rts
  257.  
  258. __addsf3:
  259. ___addsf3:
  260.     lea    0xfffffa50:w,a0
  261.     movew    #0x4400,a0@(comm)        | load fp0
  262.     cmpiw    #0x8900,a0@(resp)        | got it?
  263.     movel    a7@(4),a0@            | take a from stack to FPU
  264.     movew    #0x4422,a0@(comm)        | add second arg to fp0
  265.     .long    0x0c688900, 0xfff067f8
  266.     movel    a7@(8),a0@            | move b from stack to FPU
  267.     movew    #0x6400,a0@(comm)        | result to d0
  268.     .long    0x0c688900, 0xfff067f8
  269.     movel    a0@,d0                | download result
  270.      rts
  271.  
  272. # endif    sfp004
  273. #endif    __M68881__
  274.