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. include mdef.inc
  34. include struct.inc
  35.  
  36.         modstart        fprem386
  37.  
  38.         xdefp   __fprem_
  39.  
  40. ;
  41. ;                     EDX:EAX    ECX:EBX
  42. ;       void fprem( double x, double modulus, int *quot, double *rem )
  43. ;
  44.         defpe   __fprem_
  45.         push    EBP             ; save BP
  46.         mov     EBP,ESP         ; get access to parms
  47.         push    EDX             ; save registers
  48.         push    ECX             ; ...
  49.         push    EBX             ; ...
  50.         push    EAX             ; ...
  51.         mov     EAX,8[EBP]      ; get argument x
  52.         mov     EDX,12[EBP]     ; ...
  53.         mov     EBX,16[EBP]     ; get modulus
  54.         mov     ECX,20[EBP]     ; ...
  55.         or      ECX,ECX         ; if modulus is zero
  56.         _if     e               ; then
  57.           sub   EAX,EAX         ; - set result to 0
  58.           mov   EBX,24[EBP]     ; - quot = 0
  59.           mov   [EBX],EAX       ; - ...
  60.           mov   EBX,28[EBP]     ; - remainder = 0
  61.           mov   [EBX],EAX       ; - ...
  62.           mov   4[EBX],EAX      ; - ...
  63.           pop   EAX             ; - restore registers
  64.           pop   EBX             ; - ...
  65.           pop   ECX             ; - ...
  66.           pop   EDX             ; - ...
  67.           pop   EBP             ; - restore EBP
  68.           ret                   ; - return
  69.         _endif                  ; endif
  70.         push    ESI             ; save ESI
  71.         push    EDI             ; save EDI
  72.         push    EDX             ; save sign of operand
  73.         push    ECX             ; save high part of modulus
  74.  
  75.         mov     ESI,EDX         ; get most sig word of op1
  76.         mov     EDI,ECX         ; get most sig word of op2
  77.         and     ESI,7FF00000h   ; isolate exponent
  78.         and     EDI,7FF00000h   ; isolate exponent of modulus
  79.         and     EDX,000FFFFFh   ; isolate mantissa of op1
  80.         and     ECX,000FFFFFh   ; isolate mantissa of modulus
  81.         or      EDX,00100000h   ; set implied 1 bit
  82.         or      ECX,00100000h   ; ...
  83.         sub     ESI,EDI         ; calculate difference in exponents
  84.         _if     ge              ; if operand >= modulus
  85.           sub   EDI,EDI         ; - set quotient to 0
  86.           _loop                 ; - loop
  87.             _guess              ; - - guess
  88.               cmp    ECX,EDX    ; - - - The purpose of this guess is to
  89.               _quif  ne         ; - - - determine if the divisor will subtract
  90.               cmp  EBX,EAX      ; - - -
  91.               je   try          ; - - -
  92.             _endguess           ; - - endguess
  93.             _if   c             ; - - if the carry is set (ie the modulus will
  94.                                 ; - - - definitely subtract from the dividend
  95.                                 ; - - - without a borrow
  96. try:
  97.               sub  EAX,EBX      ; - - - subtract divisor from dividend
  98.               sbb  EDX,ECX      ; - - - . . .
  99.               stc               ; - - - set carry to indicate that modulus was
  100.                                 ; - - - successfully subtracted from dividend
  101.             _endif              ; - - endif
  102. didnt_go:   _rcl  EDI,1         ; - - rotate 1 (if carry set) into quotient word
  103.             sub   ESI,00100000h ; - - adjust difference in exponents
  104.             jl    _done         ; - - quit if done
  105.             _shl  EAX,1         ; - - shift dividend left
  106.             _rcl  EDX,1         ; - - . . .
  107.             cmp   EDX,00200000h
  108.             jae   try
  109.  
  110. ; If bit 5 of dividend is set here, we didnt subtract the modulus from the
  111. ; dividend (recall that the divisor has a 1 in the msb -- if we subtracted
  112. ; it from the dividend without a borrow, the dividend would not have a one
  113. ; in its msb to be shifted into bit 5 tested for in the condition above. If
  114. ; we are rotating a bit into bit 5, the dividend is now big enough that we
  115. ; can be sure of subtracting out the divisor without a borrow, as we have
  116. ; shifted it left one digit.
  117.  
  118.             cmp   EDX,00100000h
  119.           _until  b             ; - until
  120.  
  121.           cmc                   ; - flip the carry bit
  122.           jmp   short didnt_go  ; - continue
  123. _done:    sub   ESI,ESI         ; - set SI to 0
  124. ;         normalize the remainder in AL:BX:CX:DX
  125.           _guess                ; - guess: number is zero
  126.             or    EAX,EAX       ; - - quit if not zero
  127.             _quif ne            ; - - ...
  128.             or    EDX,EDX       ; - - ...
  129.             _quif ne            ; - - ...
  130.           _admit                ; - admit: not zero
  131.             _loop               ; - - loop
  132.               test  EDX,00200000h; - - - quit if number is normalized
  133.               _quif ne          ; - - - . . .
  134.               _rcl  EAX,1       ; - - - shift result left
  135.               _rcl  EDX,1
  136.               sub   ESI,00100000h; - - - decrement exponent
  137.             _endloop            ; - - endloop
  138.             shr   EDX,1         ; - - put in correct position
  139.             rcr   EAX,1         ; - - . . .
  140.             add   ESI,00100000h ; - - increment exponent
  141.             pop   ECX           ; - - get high part of modulus
  142.             push  ECX           ; - - save it again
  143.             and   ECX,7FF00000h ; - - isolate exponent of modulus
  144.             add   ESI,ECX       ; - - adjust exponent of result
  145.           _endguess             ; - endguess
  146.         _else                   ; else
  147.           add   ESI,EDI         ; - restore exponent
  148.           sub   EDI,EDI         ; - set quotient to 0
  149.         _endif                  ; endif
  150.         and     EDX,000FFFFFh   ; keep just the fraction
  151.         add     EDX,ESI         ; update high order word
  152.         pop     ECX             ; restore high part of modulus
  153.         pop     ESI             ; restore sign
  154.         and     ESI,080000000h  ; isolate sign bit
  155.         or      EDX,EDX         ; test high word of remainder
  156.         _if     ne              ; if remainder is non-zero
  157.           or    EDX,ESI         ; - make remainder same sign as original opnd
  158.         _endif                  ; endif
  159.         xor     ESI,ECX         ; calc sign of quotient
  160.         _if     s               ; if quotient should be negative
  161.           neg   EDI             ; - negate quotient
  162.         _endif                  ; endif
  163.         mov     ESI,24[EBP]     ; get address of quotient
  164.         mov     [ESI],EDI       ; store quotient
  165.         mov     ESI,28[EBP]     ; get address of remainder
  166.         mov     [ESI],EAX       ; store remainder
  167.         mov     4[ESI],EDX      ; ...
  168.         pop     EDI             ; restore EDI
  169.         pop     ESI             ; restore ESI
  170.         pop     EAX             ; restore registers
  171.         pop     EBX             ; ...
  172.         pop     ECX             ; ...
  173.         pop     EDX             ; ...
  174.         pop     EBP             ; restore EBP
  175.         ret                     ; return
  176.         endproc __fprem_
  177.  
  178.  
  179.         endmod
  180.         end
  181.