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