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. ;========================================================================
  34. ;==     Name:           I8D                                            ==
  35. ;==     Operation:      Signed 8 byte divide                           ==
  36. ;==     Inputs:         EDX;EAX  Dividend                              ==
  37. ;==                     ECX;EBX  Divisor                               ==
  38. ;==     Outputs:        EDX;EAX  Quotient                              ==
  39. ;==                     ECX;EBX  Remainder (same sign as dividend)     ==
  40. ;==     Volatile:       none                                           ==
  41. ;==                                     same sign as dividend for      ==
  42. ;==                                     consistency with 8086 idiv     ==
  43. ;==                                     and so (a/b)*b + a%b == a      ==
  44. ;==                                     to get a 64-bit version for 386==
  45. ;========================================================================
  46. include mdef.inc
  47. include struct.inc
  48.  
  49.         modstart        i8d
  50.  
  51.         xdefp   __I8D
  52.  
  53.         defpe   __I8D
  54.         or      edx,edx         ; check sign of dividend
  55.         js      divneg          ; handle case where dividend < 0
  56.         or      ecx,ecx         ; check sign of divisor
  57.         js      notU8D          ; easy case if it is also positive
  58.  
  59.         ; dividend >= 0, divisor >= 0
  60.         docall  __U8D           ; - ...
  61.         ret                     ; - ...
  62.  
  63.         ; dividend >= 0, divisor < 0
  64. notU8D: neg     ecx             ; take positive value of divisor
  65.         neg     ebx             ; ...
  66.         sbb     ecx,0           ; ...
  67.         docall  __U8D           ; do unsigned division
  68.         neg     edx             ; negate quotient
  69.         neg     eax             ; ...
  70.         sbb     edx,0           ; ...
  71.         ret                     ; and return
  72.  
  73. divneg:                         ; dividend is negative
  74.         neg     edx             ; take absolute value of dividend
  75.         neg     eax             ; ...
  76.         sbb     edx,0           ; ...
  77.         or      ecx,ecx         ; check sign of divisor
  78.         jns     negres          ; negative result if divisor > 0
  79.  
  80.         ; dividend < 0, divisor < 0
  81.         neg     ecx             ; negate divisor too
  82.         neg     ebx             ; ...
  83.         sbb     ecx,0           ; ...
  84.         docall  __U8D           ; and do unsigned division
  85.         neg     ecx             ; negate remainder
  86.         neg     ebx             ; ...
  87.         sbb     ecx,0           ; ...
  88.         ret                     ; and return
  89.  
  90.         ; dividend < 0, divisor >= 0
  91. negres: docall  __U8D           ; do unsigned division
  92.         neg     ecx             ; negate remainder
  93.         neg     ebx             ; ...
  94.         sbb     ecx,0           ; ...
  95.         neg     edx             ; negate quotient
  96.         neg     eax             ; ...
  97.         sbb     edx,0           ; ...
  98.         ret                     ; and return
  99.  
  100.         endproc __I8D
  101.  
  102. ;========================================================================
  103. ;==     Name:           U8D                                            ==
  104. ;==     Operation:      Unsigned 8 byte divide                         ==
  105. ;==     Inputs:         EDX;EAX  Dividend                              ==
  106. ;==                     ECX;EBX  Divisor                               ==
  107. ;==     Outputs:        EDX;EAX  Quotient                              ==
  108. ;==                     ECX;EBX  Remainder                             ==
  109. ;==     Volatile:       none                                           ==
  110. ;========================================================================
  111.  
  112.         xdefp   __U8D
  113.  
  114.         defpe   __U8D
  115.         or      ecx,ecx         ; check for easy case
  116.         jne     noteasy         ; easy if divisor is 16 bit
  117.         dec     ebx             ; decrement divisor
  118.         _if     ne              ; if not dividing by 1
  119.           inc   ebx             ; - put divisor back
  120.           cmp   ebx,edx         ; - if quotient will be >= 64K
  121.           _if   be              ; - then
  122. ;
  123. ;       12-aug-88, added thanks to Eric Christensen from Fox Software
  124. ;       divisor < 64K, dividend >= 64K, quotient will be >= 64K
  125. ;
  126. ;       *note* this sequence is used in ltoa's #pragmas; any bug fixes
  127. ;              should be reflected in ltoa's code bursts
  128. ;
  129.             mov   ecx,eax       ; - - save low word of dividend
  130.             mov   eax,edx       ; - - get high word of dividend
  131.             sub   edx,edx       ; - - zero high part
  132.             div   ebx           ; - - divide bx into high part of dividend
  133.             xchg  eax,ecx       ; - - swap high part of quot,low word of dvdnd
  134.           _endif                ; - endif
  135.           div   ebx             ; - calculate low part
  136.           mov   ebx,edx         ; - get remainder
  137.           mov   edx,ecx         ; - get high part of quotient
  138.           sub   ecx,ecx         ; - zero high part of remainder
  139.         _endif                  ; endif
  140.         ret                     ; return
  141.  
  142.  
  143. noteasy:                        ; have to work to do division
  144. ;
  145. ;       check for divisor > dividend
  146. ;
  147.         _guess                  ; guess: divisor > dividend
  148.           cmp   ecx,edx         ; - quit if divisor <= dividend
  149.           _quif b               ; - . . .
  150.           _if   e               ; - if high parts are the same
  151.             cmp   ebx,eax       ; - - compare the lower order words
  152.             _if   be            ; - - if divisor <= dividend
  153.               sub   eax,ebx     ; - - - calulate remainder
  154.               mov   ebx,eax     ; - - - ...
  155.               sub   ecx,ecx     ; - - - ...
  156.               sub   edx,edx     ; - - - quotient = 1
  157.               mov   eax,1       ; - - - ...
  158.               ret               ; - - - return
  159.             _endif              ; - - endif
  160.           _endif                ; - endif
  161.           sub   ecx,ecx         ; - set divisor = 0 (this will be quotient)
  162.           sub   ebx,ebx         ; - ...
  163.           xchg  eax,ebx         ; - return remainder = dividend
  164.           xchg  edx,ecx         ; - and quotient = 0
  165.           ret                   ; - return
  166.         _endguess               ; endguess
  167.         push    ebp              ; save work registers
  168.         push    esi              ; ...
  169.         push    edi              ; ...
  170.         sub     esi,esi           ; zero quotient
  171.         mov     edi,esi           ; ...
  172.         mov     ebp,esi           ; and shift count
  173. moveup:                         ; loop until divisor > dividend
  174.           _shl    ebx,1         ; - divisor *= 2
  175.           _rcl    ecx,1         ; - ...
  176.           jc      backup        ; - know its bigger if carry out
  177.           inc     ebp           ; - increment shift count
  178.           cmp     ecx,edx       ; - check if its bigger yet
  179.           jb      moveup        ; - no, keep going
  180.           ja      divlup        ; - if below, know we're done
  181.           cmp     ebx,eax       ; - check low parts (high parts equal)
  182.           jbe     moveup        ; until divisor > dividend
  183. divlup:                         ; division loop
  184.         clc                     ; clear carry for rotate below
  185.         _loop                   ; loop
  186.           _loop                 ; - loop
  187.             _rcl  esi,1         ; - - shift bit into quotient
  188.             _rcl  edi,1         ; - - . . .
  189.             dec   ebp           ; - - quif( -- shift < 0 ) NB carry not changed
  190.             js    donediv       ; - - ...
  191. backup:                         ; - - entry to remove last shift
  192.             rcr   ecx,1         ; - - divisor /= 2 (NB also used by 'backup')
  193.             rcr   ebx,1         ; - - ...
  194.             sub   eax,ebx       ; - - dividend -= divisor
  195.             sbb   edx,ecx       ; - - c=1 iff it won't go
  196.             cmc                 ; - - c=1 iff it will go
  197.           _until  nc            ; - until it won't go
  198.           _loop                 ; - loop
  199.             _shl  esi,1         ; - - shift 0 into quotient
  200.             _rcl  edi,1         ; - - . . .
  201.             dec   ebp           ; - - going to add, check if done
  202.             js    toomuch       ; - - if done, we subtracted to much
  203.             shr   ecx,1         ; - - divisor /= 2
  204.             rcr   ebx,1         ; - - ...
  205.             add   eax,ebx       ; - - dividend += divisor
  206.             adc   edx,ecx       ; - - c = 1 iff bit of quotient should be 1
  207.           _until  c             ; - until divisor will go into dividend
  208.         _endloop                ; endloop
  209. toomuch:                        ; we subtracted too much
  210.         add     eax,ebx         ; dividend += divisor
  211.         adc     edx,ecx         ; ...
  212. donediv:                        ; now quotient in di;si, remainder in dx;ax
  213.         mov     ebx,eax         ; move remainder to cx;bx
  214.         mov     ecx,edx         ; ...
  215.         mov     eax,esi         ; move quotient to dx;ax
  216.         mov     edx,edi         ; ...
  217.         pop     edi             ; restore registers
  218.         pop     esi             ; ...
  219.         pop     ebp             ; ...
  220.         ret                     ; and return
  221.         endproc __U8D
  222.  
  223.         endmod
  224.         end
  225.