Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. ;*****************************************************************************
  2. ;*
  3. ;*                            Open Watcom Project
  4. ;*
  5. ;*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
  6. ;*
  7. ;*  ========================================================================
  8. ;*
  9. ;*    This file contains Original Code and/or Modifications of Original
  10. ;*    Code as defined in and that are subject to the Sybase Open Watcom
  11. ;*    Public License version 1.0 (the 'License'). You may not use this file
  12. ;*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
  13. ;*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
  14. ;*    provided with the Original Code and Modifications, and is also
  15. ;*    available at www.sybase.com/developer/opensource.
  16. ;*
  17. ;*    The Original Code and all software distributed under the License are
  18. ;*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  19. ;*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
  20. ;*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
  21. ;*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
  22. ;*    NON-INFRINGEMENT. Please see the License for the specific language
  23. ;*    governing rights and limitations under the License.
  24. ;*
  25. ;*  ========================================================================
  26. ;*
  27. ;* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
  28. ;*               DESCRIBE IT HERE!
  29. ;*
  30. ;*****************************************************************************
  31.  
  32.  
  33. ;       double modf( double value, double *iptr );
  34. ;
  35. ; Description:
  36. ;   The modf function breaks the argument value into integral and
  37. ;   fractional parts, each of which has the same sign as the argument.
  38. ;   It stores the integral part as a double in the object pointed to
  39. ;   by iptr.
  40. ;
  41. ; Returns:
  42. ;   The modf function returns the signed fractional part of value.
  43. ;
  44. ;  18-oct-86    ...             Fraction in Modf not computed right
  45. ;                               significant digits
  46. ;
  47. include mdef.inc
  48. include struct.inc
  49.  
  50.         modstart        amodf386
  51.  
  52.         xdefp   __ModF
  53.         xdefp   __ZBuf2F
  54.  
  55. ;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
  56. ;[]
  57. ;[] __ModF
  58. ;[]
  59. ;[]     void __ModF( double near *AX, double near *DX );
  60. ;[]     Input:  EAX         - pointer to double precision float
  61. ;[]             EDX         - place to store integral part
  62. ;[]     Output: [EAX]       - fractional part of value.
  63. ;[]             [EDX]       - integral part of value
  64. ;[]
  65. ;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
  66.  
  67.         defpe   __ModF
  68.         push    EBP             ; save BP
  69.         push    ESI             ; save SI
  70.         push    EDI             ; save DI
  71.         push    ECX             ; save CX
  72.         push    EBX             ; save BX
  73.         mov     ESI,EDX         ; get address for ipart
  74.         mov     EBP,EAX         ; get address of float
  75.         mov     EAX,0[EBP]      ; get float
  76.         mov     EDX,4[EBP]      ; . . .
  77.         xchg    ESI,EBP         ; flip pointers
  78.         mov     0[EBP],EAX      ; store integral part of value
  79.         mov     4[EBP],EDX      ; . . .
  80.         _guess                  ; guess: fraction is zero
  81.           mov   ECX,EDX         ; - get exponent
  82.           and   ECX,7FF00000h   ; - get exponent part of R into DI
  83.           je    short done      ; - set integer part to 0 if exponent = 0
  84.           cmp ECX,(3FFh+52) shl 20; - check for exponent > 52
  85.           _quif b               ; - quit if fraction not zero
  86.           xchg  EBP,ESI         ; - get address of fractional part
  87. done:     sub   EAX,EAX         ; - set fraction(or integer) to 0
  88.           mov   4[EBP],EAX      ; - . . .
  89.           mov   0[EBP],EAX      ; - . . .
  90.           pop   EBX             ; - restore BX
  91.           pop   ECX             ; - restore CX
  92.           pop   EDI             ; - restore DI
  93.           pop   ESI             ; - restore SI
  94.           pop   EBP             ; - restore BP
  95.           ret                   ; - return
  96.         _endguess               ; endguess
  97.         mov     EDI,ECX         ; save exponent
  98.         shr     ECX,20          ; move exponent to bottom
  99.         sub     CX,03FFh        ; remove bias
  100.         jb      done            ; quit if number < 1.0
  101.         push    EDX             ; save sign
  102.         sub     EAX,EAX         ; initialize mask to 0
  103.         mov     EDX,0FFF00000h  ; ...
  104.         cmp     CL,20           ; if exponent > 20
  105.         _if     a               ; then
  106.           sar   EDX,21          ; - set ESI to all ones
  107.           rcr   EAX,1           ; - set high bit of EBX
  108.           sub   CL,21           ; - get shift count for second part
  109.           sar   EAX,CL          ; - create rest of mask
  110.         _else                   ; else
  111.           sar   EDX,CL          ; - create mask in high part only
  112.         _endif                  ; endif
  113.         and     4[EBP],EDX      ; mask off the remaining fraction bits
  114.         and     0[EBP],EAX      ; . . .
  115.         not     EDX             ; complement the mask to get fractional part
  116.         not     EAX             ; . . .
  117.         mov     EBP,ESI         ; get address of fractional part
  118.         and     EDX,4[EBP]      ; get fraction bits
  119.         and     EAX,0[EBP]      ; . . .
  120.         call    Norm            ; normalize the fraction
  121.         pop     ESI             ; restore sign
  122.         or      EDX,EDX         ; if fraction is not 0
  123.         _if     ne              ; then
  124.           and   ESI,80000000h   ; - isolate sign
  125.           or    EDX,ESI         ; - set sign in fractional part
  126.         _endif                  ; endif
  127.         mov     4[EBP],EDX      ; store fractional part
  128.         mov     0[EBP],EAX      ; . . .
  129.         pop     EBX             ; restore BX
  130.         pop     ECX             ; restore CX
  131.         pop     EDI             ; restore DI
  132.         pop     ESI             ; restore SI
  133.         pop     EBP             ; restore BP
  134.         ret                     ; return
  135.         endproc __ModF
  136.  
  137.  
  138. ;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
  139. ;<>                                                                   <>
  140. ;<>   __ZBuf2F - convert buffer of significant digits into floating   <>
  141. ;<>             void __ZBuf2F( char near *buf, double near *value )   <>
  142. ;<>                                                                   <>
  143. ;<>   input:  EAX - address of buffer of significant digits           <>
  144. ;<>           EDX - place to store value                              <>
  145. ;<>   output: [EDX]        - floating point number                    <>
  146. ;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
  147.  
  148.         defpe   __ZBuf2F
  149.         push    EBP             ; save BP
  150.         push    ESI             ; save SI
  151.         push    EDI             ; save DI
  152.         push    ECX             ; save CX
  153.         push    EBX             ; save BX
  154.         push    EDX             ; save pointer to result
  155.         mov     ESI,EAX         ; get address of buffer
  156.         sub     EDX,EDX         ; set 54-bit integer to 0
  157.         sub     ECX,ECX         ; . . .
  158.         sub     EAX,EAX         ; zero out EAX
  159.         _loop                   ; loop (convert digits into 54-bit int)
  160.           mov   AL,[ESI]        ; - get next digit
  161.           cmp   AL,0            ; - quit if at end of buffer
  162.           _quif e               ; - . . .
  163.  
  164. ;[]  multiply current value in EDX:ECX by 10
  165.  
  166.           mov   EDI,EDX         ; - save current value
  167.           mov   EBX,ECX         ; - ...
  168.           _shl  ECX,1           ; - multiply number by 4
  169.           _rcl  EDX,1           ; -   by shifting left 2 places
  170.           _shl  ECX,1           ; - . . .
  171.           _rcl  EDX,1           ; - . . .
  172.           add   ECX,EBX         ; - add original value
  173.           adc   EDX,EDI         ; -  (this will make it times 5)
  174.           _shl  ECX,1           ; - shift left to make it times 10
  175.           _rcl  EDX,1           ; - . . .
  176.           and   AL,0Fh          ; - isolate binary digit
  177.           add   ECX,EAX         ; - add in current digit
  178.           adc   EDX,0           ; - . . .
  179.           inc   ESI             ; - point to next digit in buffer
  180.         _endloop                ; endloop
  181.         mov     EAX,ECX         ; get low order word into EAX
  182.  
  183. ;[] Turn the integer in EDX:EAX into a real number
  184.  
  185.         mov     EDI,(3FFh+52) shl 20; set exponent
  186.         call    Norm            ; convert the 52 bit integer to a float
  187.         pop     EBP             ; restore pointer to result
  188.         mov     4[EBP],EDX      ; store result
  189.         mov     0[EBP],EAX      ; . . .
  190.         pop     EBX             ; restore BX
  191.         pop     ECX             ; restore CX
  192.         pop     EDI             ; restore DI
  193.         pop     ESI             ; restore SI
  194.         pop     EBP             ; restore BP
  195.         ret                     ; return to caller
  196.         endproc __ZBuf2F
  197.  
  198.  
  199. ;[] Norm normalizes an unsigned real in EDX:EAX
  200. ;[] expects the exponent to be in EDI.  The real returned is in 'packed'
  201. ;[] format
  202. ;[]     ESI is destroyed
  203.  
  204. Norm    proc    near            ; normalize floating point number
  205.         sub     ESI,ESI         ; clear out SI
  206.         or      ESI,EAX         ; see if the integer is zero
  207.         or      ESI,EDX         ; . . .
  208.         je      short Z_52ret   ; if integer is zero, return to caller
  209.         test    EDX,0FFF00000h  ; see if we have to shift forward or backward
  210.         _if     e               ; if (we haven't shifted msb into bit 53)
  211.           _loop                 ; - loop
  212.             sub   EDI,00100000h ; - - exp <-- exp - 1
  213.             _shl  EAX,1         ; - - shift integer left by 1 bit
  214.             _rcl  EDX,1         ; - - . . .
  215.             test  EDX,0FFF00000h;
  216.           _until ne             ; - until( msb is shifted into bit 53 )
  217.         _else                   ; else (we must shift to the right)
  218.           test  EDX,0FFE00000h  ; -
  219.           je    short done1     ; - if msb is bit 53, we are done
  220.           _loop                 ; - loop
  221.             add   EDI,00100000h ; - - exp <-- exp + 1
  222.             shr   EDX,1         ; - - shift integer right by 1 bit
  223.             rcr   EAX,1         ; - - . . .
  224.             rcr   ESI,1         ; - - save lsb
  225.             test  EDX,0FFE00000h; -
  226.           _until e              ; - until( msb is bit 53 )
  227.           _rcl  ESI,1           ; - get lsb
  228.           adc   EAX,0           ; - and use it to round off the number
  229.           adc   EDX,0           ; - . . .
  230.         _endif                  ; endif
  231. done1:  and     EDX,000FFFFFh   ; clear out implied bit
  232.         or      EDX,EDI         ; put in exponent
  233. Z_52ret:ret                     ; return
  234.         endproc Norm
  235.  
  236.         endmod
  237.         end
  238.