home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / mint / mntlib16.lzh / MNTLIB16 / NORMDF.CPP < prev    next >
Text File  |  1993-08-03  |  5KB  |  181 lines

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