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. include mdef.inc
  35. include struct.inc
  36.  
  37. .8087
  38.         modstart        div386
  39.  
  40.         xref            __8087  ; indicate that NDP instructions are present
  41.  
  42.         datasegment
  43.         extrn   __real87 : byte         ; 8087.asm
  44.         extrn   __chipbug: byte
  45.         enddata
  46.  
  47.         xref    F8DivZero       ; Fstatus
  48.         xref    F8OverFlow      ; Fstatus
  49.         xref    F8UnderFlow     ; Fstatus
  50.         xref    __fdiv_m64
  51.  
  52.         xdefp   __FDD
  53.  
  54. ;  double __FDD( double , double )
  55. sign    equ     -12
  56. den     equ     sign-8
  57. quot    equ     den-12
  58. lo      equ     0
  59. hi      equ     4
  60.  
  61.         defpe   __FDD
  62.         or      EBX,EBX                 ; if low word of divisor is 0
  63.         _if     e                       ; then
  64.           _shl  ECX,1                   ; - shift sign of divisor into carry
  65.           _if   e                       ; - if divisor is zero
  66.             jmp   F8DivZero             ; - - handle divide by zero
  67.           _endif                        ; - endif
  68.           rcr   ECX,1                   ; - restore sign of divisor
  69.         _endif                          ; endif
  70.         or      EAX,EAX                 ; check dividend for zero
  71.         _if     e                       ; if so then
  72.           _shl  EDX,1                   ; - save sign of dividend
  73.           _if   e                       ; - if dividend is 0
  74.             ret                         ; - - return
  75.           _endif                        ; - endif
  76.           rcr   EDX,1                   ; - restore sign of dividend
  77.         _endif                          ; endif
  78.  
  79.         cmp     byte ptr __real87,0     ; if no 80x87 is present
  80.         je      short __FDDemu          ; then emulate
  81.  
  82. __FDD87:
  83.         push    EDX                     ; push operand 1
  84.         push    EAX                     ; . . .
  85.         fld     qword ptr [ESP]         ; load operand 1
  86.         push    ECX                     ; push operand 2
  87.         push    EBX                     ; . . .
  88.         test    byte ptr __chipbug,1    ; have we got a bad divider?
  89.         _if     ne                      ; then
  90.           call  __fdiv_m64              ; - call support rtn for divide
  91.         _else                           ; else
  92.           fdiv  qword ptr [ESP]         ; - divide operand 1 by operand 2
  93.           add   ESP,8                   ; - clean up stack
  94.         _endif                          ; endif
  95.         fstp    qword ptr [ESP]         ; store result
  96.         fwait                           ; wait
  97.         pop     EAX                     ; load result into DX:AX
  98.         pop     EDX                     ; . . .
  99.         cmp     EDX,80000000H           ; is it a negative zero?
  100.         _if     e                       ; if it is then
  101.           sub   EDX,EDX                 ; - make it positive 0.0
  102.           mov   EAX,EDX                 ; - ...
  103.         _endif                          ; endif
  104.         ret                             ; return
  105.  
  106. __FDDemu:
  107.         push    EBP                     ; save EBP
  108.         mov     EBP,ESP                 ; get access to stack
  109.         push    EDI                     ; save EDI
  110.         push    ESI                     ; and ESI
  111.  
  112.         mov     EDI,EDX                 ; get high part of op1
  113.         mov     ESI,ECX                 ; get high part of op2
  114.         sar     EDI,20          ; shift exponent to bottom, duplicating sign
  115.         sar     ECX,20          ; shift exponent to bottom, duplicating sign
  116.         and     EDI,0800007FFh          ; isolate signs and exponent
  117.         and     ECX,0800007FFh          ; ...
  118.         rol     EDI,16                  ; rotate signs to bottom
  119.         rol     ECX,16                  ; ...
  120.         add     DI,CX                   ; calc sign of result
  121.         rol     EDI,16                  ; rotate signs to top
  122.         rol     ECX,16                  ; ...
  123.         and     EDX,000FFFFFh           ; isolate fraction
  124.         and     ESI,000FFFFFh           ; isolate fraction
  125.         or      DI,DI                   ; if op1 is not a denormal
  126.         _if     ne                      ; then
  127.           or    EDX,00100000h           ; - turn on implied 1 bit
  128.         _else                           ; else (denormal)
  129.           _loop                         ; - loop (normalize it)
  130.             _shl  EAX,1                 ; - - shift fraction left
  131.             _rcl  EDX,1                 ; - - . . .
  132.             dec   DI                    ; - - decrement exponent
  133.             test  EDX,00100000h         ; - - until implied 1 bit is on
  134.           _until  ne                    ; - until implied 1 bit is on
  135.         _endif                          ; endif
  136.         or      CX,CX                   ; if op2 is not a denormal
  137.         _if     ne                      ; then
  138.           or    ESI,00100000h           ; - turn on implied 1 bit
  139.         _else                           ; else (denormal)
  140.           _loop                         ; - loop (normalize it)
  141.             _shl  EBX,1                 ; - - shift fraction left
  142.             _rcl  ESI,1                 ; - - . . .
  143.             dec   CX                    ; - - decrement exponent
  144.             test  ESI,00100000h         ; - - until implied 1 bit is on
  145.           _until  ne                    ; - until implied 1 bit is on
  146.         _endif                          ; endif
  147.  
  148.         sub     DI,CX                   ; calculate exponent of result
  149.         add     DI,03ffh                ; add in removed bias
  150.         _guess                          ; guess: overflow
  151.           _quif s                       ; - quit if exponent is negative
  152.           cmp   DI,07FFh                ; - quit if not overflow
  153.           _quif b                       ; - . . .
  154.           mov   EAX,ECX                 ; - put sign into EAX
  155.           pop   ESI                     ; - restore ESI
  156.           pop   EDI                     ; - restore EDI
  157.           pop   EBP                     ; - restore EBP
  158.           jmp   F8OverFlow              ; - handle overflow
  159.         _endguess                       ; endguess
  160.         cmp     DI,-52                  ; if exponent is too small
  161.         _if     l                       ; then underflow
  162.           pop   ESI                     ; - restore ESI
  163.           pop   EDI                     ; - restore EDI
  164.           pop   EBP                     ; - restore EBP
  165.           jmp   F8UnderFlow             ; - handle underflow
  166.         _endif                          ; endif
  167.  
  168.         push    EDI                     ; save sign and exponent
  169.         mov     CL,11                   ; shift fractions to top of registers
  170.         shld    EDX,EAX,CL              ; ...
  171.         shld    EAX,EBP,CL              ; ...
  172.         and     EAX,0FFFFF800h          ; ...
  173.         shld    ESI,EBX,CL              ; ...
  174.         shld    EBX,EBP,CL              ; ...
  175.         and     EBX,0FFFFF800h          ; ...
  176.         push    ESI                     ; save divisor
  177.         push    EBX                     ; ...
  178.         mov     ECX,ESI                 ; get top part of divisor
  179.         mov     EDI,EDX                 ; get dividend
  180.         mov     ESI,EAX                 ; ...
  181.         sub     EAX,EAX                 ; assume top bit is 0
  182.         cmp     ECX,EDX                 ; check high parts
  183.         _if     be                      ; if hi(divisor) <= hi(dividend)
  184.           sub   EDX,ECX                 ; - subtract divisor from dividend
  185.           inc   EAX                     ; - set quotient to 1
  186.         _endif                          ; endif
  187.         push    EAX                     ; save high word of quotient
  188.         mov     EAX,ESI                 ; get low part of dividend
  189.         div     ECX                     ; estimate next word of quotient
  190.         push    EAX                     ; save estimate of quotient (quot+4[EBP])
  191.         xchg    EAX,EBX                 ; save quot., get low word of divisor
  192.         mul     EBX                     ; calc. estimate * lo(divisor)
  193.         xchg    EAX,ECX                 ; ...
  194.         xchg    EBX,EDX                 ; save partial product
  195.         mul     EDX                     ; calc. estimate * hi(divisor)
  196.         add     EAX,EBX                 ; add to partial product
  197.         adc     EDX,0                   ; ...
  198.         mov     EBX,den+lo[EBP]         ; get low word of divisor
  199.         test    byte ptr quot+8[EBP],1  ; if high word of quot is 1
  200.         _if     ne                      ; then
  201.           add   EAX,EBX                 ; - add in divisor
  202.           adc   EDX,den+hi[EBP]         ; - ...
  203.         _endif                          ; endif
  204. ; subtract estimate * divisor from dividend
  205.         neg     ECX                     ; 0 - ECX
  206.         sbb     ESI,EAX                 ; ...
  207.         sbb     EDI,EDX                 ; ...
  208.         _if     ne                      ; if high word not 0 (quotient too big)
  209.           _loop                         ; - loop (find correct quotient)
  210.             sub   dword ptr quot+4[EBP],1; - - decrement quotient
  211.             sbb   dword ptr quot+8[EBP],0; - - ...
  212.             add   ECX,EBX               ; - - add divisor back to dividend
  213.             adc   ESI,den+hi[EBP]       ; - - ...
  214.             adc   EDI,0                 ; - - ...
  215.           _until  e                     ; - until done
  216.         _endif                          ; endif
  217.         mov     EDI,ESI                 ; get new dividend
  218.         mov     ESI,ECX                 ; ...
  219.         mov     ECX,den+hi[EBP]         ; get divisor
  220.         cmp     ECX,EDI                 ; check high parts      13-aug-90
  221.         _if     be                      ; if hi(divisor) <= hi(dividend)
  222.           sub   EDI,ECX                 ; - subtract divisor from dividend
  223.           add   dword ptr quot+4[EBP],1 ; - increment quotient
  224.           adc   dword ptr quot+8[EBP],0 ; - ...
  225.         _endif                          ; endif
  226.         mov     EDX,EDI                 ; get dividend into EDX:EAX
  227.         mov     EAX,ESI                 ; ...
  228.         div     ECX                     ; estimate next word of quotient
  229.         push    EAX                     ; save estimate of quotient (-4[EBP])
  230.         or      EAX,EAX                 ; if quotient non-zero
  231.         _if     ne                      ; then
  232.           xchg  EAX,EBX                 ; - save quot., get low word of divisor
  233.           mul   EBX                     ; - calc. estimate * lo(divisor)
  234.           xchg  EAX,ECX                 ; - ...
  235.           xchg  EBX,EDX                 ; - save partial product
  236.           mul   EDX                     ; - calc. estimate * hi(divisor)
  237.           add   EAX,EBX                 ; - add to partial product
  238.           adc   EDX,0                   ; - ...
  239. ;   - subtract estimate * divisor from dividend
  240.           neg   ECX                     ; - 0 - ECX
  241.           sbb   ESI,EAX                 ; - ...
  242.           sbb   EDI,EDX                 ; - ...
  243.           _if   ne                      ; - if high word not 0 (quotient too big)
  244.             _loop                       ; - - loop (find correct quotient)
  245.               sub   dword ptr quot+0[EBP],1; - - - decrement quotient
  246.               sbb   dword ptr quot+4[EBP],0; - - - ...
  247.               sbb   dword ptr quot+8[EBP],0; - - - ...
  248.               add   ECX,den+lo[EBP]     ; - - - add divisor back to dividend
  249.               adc   ESI,den+hi[EBP]     ; - - - ...
  250.               adc   EDI,0               ; - - - ...
  251.             _until  e                   ; - - until done
  252.           _endif                        ; - endif
  253.         _endif                          ; endif
  254.         pop     EAX                     ; get quotient
  255.         pop     EDX                     ; ...
  256.         pop     EBX                     ; get high bit
  257.         add     ESP,8                   ; remove divisor
  258.         pop     EDI                     ; restore sign and exponent
  259.         dec     DI                      ; decrement exponent
  260.         shr     EBX,1                   ; if non-zero
  261.         _if     c                       ; then
  262.           rcr   EDX,1                   ; - shift answer right
  263.           rcr   EAX,1                   ; - ...
  264.           inc   EDI                     ; - increment exponent
  265.         _endif                          ; endif
  266.         sub     ESI,ESI                 ; get zero for zero fill
  267.         mov     CL,11                   ; shift result over
  268.         shrd    EAX,EDX,CL              ; ...
  269.         rcr     ESI,1                   ; save carry
  270.         shrd    EDX,ESI,CL              ; ...
  271.  
  272.         or      EDX,0FFF00000h          ; turn top bits all on
  273.         _shl    ESI,1                   ; get guard bit
  274.         adc     EAX,0                   ; round up
  275.         adc     EDX,0                   ; ...
  276.         adc     EDI,0                   ; increment exponent if required
  277.         or      DI,DI                   ; if exponent <= 0
  278.         _if     le                      ; then (denormal result)
  279.           _if   e                       ; - if exponent = 0
  280.             mov   CL,1                  ; - - set shift count to 1
  281.           _else                         ; - else
  282.             neg   DI                    ; - - negate to get shift count
  283.             mov   CX,DI                 ; - - ...
  284.           _endif                        ; - endif
  285.           and     EDX,001FFFFFh         ; - isolate fraction
  286.           sub     EBX,EBX               ; - for zero fill
  287.           shrd    EAX,EDX,CL            ; - align the fraction
  288.           shrd    EDX,EBX,CL            ; - ...
  289.           sub     DI,DI                 ; - set exponent to 0
  290.         _endif                          ; endif
  291.  
  292.         and     EDX,000FFFFFh           ; isolate fraction
  293.         mov     ESI,EDI                 ; get copy of sign
  294.         ror     EDI,11                  ; get exponent
  295.         _shl    ESI,1                   ; get sign
  296.         rcr     EDI,1                   ; put it in
  297.         and     EDI,0FFF00000h          ; isolate sign and exponent
  298.         or      EDX,EDI                 ; place it in result
  299.  
  300.         pop     ESI                     ; restore registers
  301.         pop     EDI                     ; ...
  302.         pop     EBP                     ; ...
  303.         ret                             ; return
  304.         endproc __FDD
  305.  
  306.         endmod
  307.         end
  308.