home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mntlib25.zoo / _normdf.cpp < prev    next >
C/C++ Source or Header  |  1992-12-12  |  5KB  |  204 lines

  1. | mjr: not needed _normdf for -__M68881__ or the sfp004
  2. | however, _infinitydf is retained
  3.  
  4. |#######################################################################
  5.  
  6. | double floating point normalization routine
  7. |
  8. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  9. | Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
  10. | patched by Olaf Flebbe (flebbe@tat.physik.uni-tuebingen.de)
  11. |
  12. | Revision 1.6.1 olaf 10-92:
  13. |  + corrected rounding in tie case: round up, not down.
  14. |    (needed for enquire 4.3)
  15. |
  16. | Revision 1.6, kub 04-90 :
  17. | more robust handling exponent and sign handling for 32 bit integers. There
  18. | are now overflow tests for 32 bit exponents, and bit 31 of the sign flag
  19. | is or ed to bit 15 for later checks (i.e. both bits 31 and 15 are now sign
  20. | bits). Take care, the upper 16 bits of rounding info are ignored for 32 bit
  21. | integers !
  22. |
  23. | Revision 1.5, ++jrb 03-90:
  24. | change __normdf interface to expect ints instead of shorts. easier
  25. | to interface to 32 bit int code. this file is now pre-processed,
  26. | with __MSHORT__ defined when ints are 16 bits.
  27. |
  28. | Revision 1.4, kub 03-90 :
  29. | export ___normdf entry to C language. Rename the internal entry to a name
  30. | not accessible from C to prevent crashes
  31. |
  32. | Revision 1.3, kub 01-90 :
  33. | added support for denormalized numbers
  34. |
  35. | Revision 1.2, kub 01-90 :
  36. | replace far shifts by swaps to gain speed
  37. |
  38. | Revision 1.1, kub 12-89 :
  39. | Ported over to 68k assembler
  40. |
  41. | Revision 1.0:
  42. | original 8088 code from P.S.Housel
  43.  
  44.     .text
  45.     .even
  46.     .globl    __infinitydf
  47.  
  48. #if !defined (__M68881__) && !defined (sfp004)
  49.     .globl    ___normdf
  50.     .globl    norm_df
  51. #include "errbase.h"
  52. # ifdef    ERROR_CHECK
  53. LC0:
  54.     .ascii "normdf: OVERFLOW\12\15\0"
  55.     .even
  56. # endif    ERROR_CHECK
  57.  
  58.     | C entry, for procs dealing with the internal representation :
  59.     | double __normdf(long long mant, int exp, int sign, int rbits);
  60. ___normdf:
  61.     lea    sp@(4),a0    | parameter pointer
  62.     moveml    d2-d7,sp@-    | save working registers
  63.     moveml    a0@+,d4-d5    | get mantissa
  64.  
  65. # ifdef __MSHORT__
  66.     movew    a0@+,d0        | get exponent
  67.     movew    a0@+,d2        | get sign
  68.     movew    a0@+,d1        | rounding information
  69. # else
  70.     movel    a0@+,d0        | get exponent
  71.     movel    a0@+,d2        | get sign
  72.     bpl    0f        | or bit 31 to bit 15 for later tests
  73.     orw    #0x8000,d2
  74. 0:    movel    a0@+,d1        | rounding information
  75.  
  76.     cmpl    #0x7fff,d0    | test exponent
  77.     bgt    oflow
  78.     cmpl    #-0x8000,d0
  79.     blt    retz
  80. # endif
  81.  
  82.     | internal entry for floating point package, saves time
  83.     | d0=u.exp, d2=u.sign, d1=rounding bits, d4/d5=mantissa
  84.     | registers d2-d7 must be saved on the stack !
  85. norm_df:
  86.     movel    d4,d3        | rounding and u.mant == 0 ?
  87.     orl    d5,d3
  88.     bne    1f
  89.     tstb    d1
  90.     beq    retz
  91. 1:
  92.     movel    d4,d3
  93.     andl    #0xfffff000,d3    | fast shift, 16 bits ?
  94.     bne    2f
  95.     cmpw    #9,d0        | shift is going to far; do normal shift
  96.     ble    2f        |  (minimize shifts here : 10l = 16l + 6r)
  97.     swap    d4        | yes, swap register halfs
  98.     swap    d5
  99.     movew    d5,d4
  100.     moveb    d1,d5        | some doubt about this one !
  101.     lslw    #8,d5
  102.     clrw    d1
  103.     subw    #16,d0        | account for swap
  104.     bra    1b
  105. 2:
  106.     clrb    d2        | sticky byte
  107.     movel    #0xffe00000,d6
  108. 3:    tstw    d0        | divide (shift)
  109.     ble    0f        |  denormalized number
  110.     movel    d4,d3
  111.     andl    d6,d3        |  or until no bits above 53
  112.     beq    4f
  113. 0:    addw    #1,d0        | increment exponent
  114.     lsrl    #1,d4
  115.     roxrl    #1,d5
  116.     orb    d1,d2        | set sticky
  117.     roxrb    #1,d1        | shift into rounding bits
  118.     bra    3b
  119. 4:
  120.     andb    #1,d2
  121.     orb    d2,d1        | make least sig bit sticky
  122.     movel    #0xfff00000,d6
  123. 5:    movel    d4,d3        | multiply (shift) until
  124.     andl    d6,d3        | one in implied position
  125.     bne    6f
  126.     subw    #1,d0        | decrement exponent
  127.     beq    6f        |  too small. store as denormalized number
  128.     addb    d1,d1        | some doubt about this one *
  129.     addxl    d5,d5
  130.     addxl    d4,d4
  131.     bra    5b
  132. 6:
  133.     tstb    d1        | check rounding bits
  134.     bge    8f        | round down - no action neccessary
  135.     negb    d1
  136.     bvc    7f        | round up
  137.         movew   d5,d1           | tie case - round to even 
  138.                                 | dont need rounding bits any more
  139.         andw    #1,d1           | check if even
  140.         beq     8f              | mantissa is even - no action necessary
  141.                                 | fall through
  142. 7:
  143.     clrl    d1        | zero rounding bits
  144.     addl    #1,d5
  145.     addxl    d1,d4
  146.     tstw    d0
  147.     bne    0f        | renormalize if number was denormalized
  148.     addw    #1,d0        | correct exponent for denormalized numbers
  149.     bra    2b
  150. 0:    movel    d4,d3        | check for rounding overflow
  151.     andl    #0xffe00000,d3
  152.     bne    2b        | go back and renormalize
  153. 8:
  154.     movel    d4,d3        | check if normalization caused an underflow
  155.     orl    d5,d3
  156.     beq    retz
  157.     cmpw    #0,d0        | check for exponent overflow or underflow
  158.     blt    retz
  159.     cmpw    #2047,d0
  160.     bge    oflow
  161.  
  162.     lslw    #4,d0        | re-position exponent
  163.     andw    #0x8000,d2    | sign bit
  164.     orw    d2,d0
  165.     swap    d0        | map to upper word
  166.     clrw    d0
  167.     andl    #0x0fffff,d4    | top mantissa bits
  168.     orl    d0,d4        | insert exponent and sign
  169.     movel    d4,d0
  170.     movel    d5,d1
  171.     moveml    sp@+,d2-d7
  172.     rts
  173.  
  174. retz:
  175.     moveq    #ERANGE,d0
  176.     Emove    d0,Errno
  177.     clrl    d0        | return zero value
  178.     clrl    d1
  179.     moveml    sp@+,d2-d7
  180.     rts
  181.  
  182. oflow:
  183. #ifdef    ERROR_CHECK
  184.     pea    pc@(LC0)
  185.     pea    Stderr
  186.     jbsr    _fprintf    |
  187.     addql    #8,a7        |
  188.     moveq    #ERANGE,d0
  189.     Emove    d0,Errno
  190. #endif    ERROR_CHECK
  191.  
  192.     moveml    pc@(__infinitydf),d0-d1 | return infinity value
  193.     andw    #0x8000,d2    | get sign bit of argument
  194.     swap    d2
  195.     clrw    d2
  196.     orl    d2,d0
  197.     moveml    sp@+,d2-d7    | should really cause trap ?!? (mjr: why?)
  198.     rts
  199.  
  200. #endif __M68881__
  201.  
  202. __infinitydf:            | +infinity as proposed by IEEE
  203.     .long    0x7ff00000,0x00000000
  204.