Subversion Repositories Kolibri OS

Rev

Rev 554 | Blame | Compare with Previous | 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. ; static char sccs_id[] = "@(#)patch32.asm      1.12  12/21/94  14:53:51";
  34. ;
  35. ; This code is being published by Intel to users of the Pentium(tm)
  36. ; processor.  Recipients are authorized to copy, modify, compile, use and
  37. ; distribute the code.
  38. ;
  39. ; Intel makes no warranty of any kind with regard to this code, including
  40. ; but not limited to, implied warranties or merchantability and fitness for
  41. ; a particular purpose. Intel assumes no responsibility for any errors that
  42. ; may appear in this code.
  43. ;
  44. ; No patent licenses are granted, express or implied.
  45. ;
  46. ;
  47. include mdef.inc
  48.  
  49. .386
  50. .387
  51.  
  52. DENOM           EQU     0
  53. NUMER           EQU     12
  54. PREV_CW         EQU     28      ; 24 + 4 (return size)
  55. PATCH_CW        EQU     32      ; 28 + 4 (return size)
  56.  
  57. DENOM_SAVE      EQU     32
  58.  
  59. MAIN_DENOM      EQU     4
  60. MAIN_NUMER      EQU     16
  61.  
  62. SPILL_SIZE      EQU     12
  63. MEM_OPERAND     EQU     8
  64. STACK_SIZE      EQU     44
  65. SPILL_MEM_OPERAND       EQU     20
  66.  
  67. ONESMASK        EQU     0e000000h
  68.  
  69. SINGLE_NAN      EQU     07f800000h
  70. DOUBLE_NAN      EQU     07ff00000h
  71.  
  72. ILLEGAL_OPC     EQU     6
  73.  
  74. f_stsw  macro   where
  75.         fstsw   where
  76. endm
  77.  
  78. fdivr_st        MACRO   reg_index, reg_index_minus1
  79.         fstp    tbyte ptr [esp+DENOM]
  80. IF      reg_index_minus1 GE 1
  81.         fxch    st(reg_index_minus1)
  82. ENDIF
  83.         fstp    tbyte ptr [esp+NUMER]
  84.         call    fdiv_main_routine
  85. IF      reg_index_minus1 GE 1
  86.         fxch    st(reg_index_minus1)
  87. ENDIF
  88.         fld     tbyte ptr [esp+NUMER]
  89.         fxch    st(reg_index)
  90.         add     esp, STACK_SIZE
  91. ENDM
  92.  
  93. fdivr_sti       MACRO   reg_index, reg_index_minus1
  94.         fstp    tbyte ptr [esp+NUMER]
  95. IF      reg_index_minus1 GE 1
  96.         fxch    st(reg_index_minus1)
  97. ENDIF
  98.         fstp    tbyte ptr [esp+DENOM]
  99.         call    fdiv_main_routine
  100. IF      reg_index_minus1 GE 1
  101.         fxch    st(reg_index_minus1)
  102. ENDIF
  103.         fld     tbyte ptr [esp+NUMER]
  104.         add     esp, STACK_SIZE
  105. ENDM
  106.  
  107. fdivrp_sti      MACRO   reg_index, reg_index_minus1
  108.         fstp    tbyte ptr [esp+NUMER]
  109. IF      reg_index_minus1 GE 1
  110.         fxch    st(reg_index_minus1)
  111. ENDIF
  112.         fstp    tbyte ptr [esp+DENOM]
  113.         call    fdiv_main_routine
  114. IF      reg_index_minus1 GE 1
  115.         fxch    st(reg_index_minus1)
  116. ENDIF
  117.         add     esp, STACK_SIZE
  118. ENDM
  119.  
  120. fdiv_st         MACRO   reg_index, reg_index_minus1
  121.         fstp    tbyte ptr [esp+NUMER]
  122. IF      reg_index_minus1 GE 1
  123.         fxch    st(reg_index_minus1)
  124. ENDIF
  125.         fld     st
  126.         fstp    tbyte ptr [esp+DENOM]
  127.         fstp    tbyte ptr [esp+DENOM_SAVE]      ; save original denom,
  128.         call    fdiv_main_routine
  129. IF      reg_index_minus1 GE 1
  130.         fxch    st(reg_index_minus1)
  131. ENDIF
  132.         fld     tbyte ptr [esp+DENOM_SAVE]
  133.         fxch    st(reg_index)
  134.         add     esp, STACK_SIZE
  135. ENDM
  136.  
  137. fdiv_sti        MACRO   reg_index, reg_index_minus1
  138.         fxch    st(reg_index)
  139.         fstp    tbyte ptr [esp+NUMER]
  140. IF      reg_index_minus1 GE 1
  141.         fxch    st(reg_index_minus1)
  142. ENDIF
  143.         fld     st
  144.         fstp    tbyte ptr [esp+DENOM]
  145.         fstp    tbyte ptr [esp+DENOM_SAVE]      ; save original denom,
  146.         call    fdiv_main_routine
  147. IF      reg_index_minus1 GE 1
  148.         fxch    st(reg_index_minus1)
  149. ENDIF
  150.         fld     tbyte ptr [esp+DENOM_SAVE]
  151.         add     esp, STACK_SIZE
  152. ENDM
  153.  
  154. fdivp_sti       MACRO   reg_index, reg_index_minus1
  155.         fstp    tbyte ptr [esp+DENOM]
  156. IF      reg_index_minus1 GE 1
  157.         fxch    st(reg_index_minus1)
  158. ENDIF
  159.         fstp    tbyte ptr [esp+NUMER]
  160.         call    fdiv_main_routine
  161. IF      reg_index_minus1 GE 1
  162.         fxch    st(reg_index_minus1)
  163. ENDIF
  164.         add     esp, STACK_SIZE
  165. ENDM
  166.  
  167. _TEXT  SEGMENT DWORD USE32 PUBLIC 'CODE'
  168. _TEXT  ENDS
  169.  
  170. _DATA  SEGMENT DWORD USE32 PUBLIC 'DATA'
  171. _DATA  ENDS
  172.  
  173. CONST SEGMENT DWORD USE32 PUBLIC 'DATA'
  174. CONST ENDS
  175.  
  176. _BSS   SEGMENT DWORD USE32 PUBLIC 'BSS'
  177. _BSS   ENDS
  178.  
  179. DGROUP  GROUP CONST,_DATA,_BSS
  180.  
  181.  
  182. _DATA  SEGMENT DWORD USE32 PUBLIC 'DATA'
  183.  
  184. fdiv_risc_table DB      0, 1, 0, 0, 4, 0, 0, 7, 0, 0, 10, 0, 0, 13, 0, 0
  185. fdiv_scale_1    DD      03f700000h              ;0.9375
  186. fdiv_scale_2    DD      03f880000h              ;1.0625
  187. one_shl_63      DD      05f000000h
  188.  
  189.  
  190. dispatch_table DD       offset label0
  191.         DD      offset label1
  192.         DD      offset label2
  193.         DD      offset label3
  194.         DD      offset label4
  195.         DD      offset label5
  196.         DD      offset label6
  197.         DD      offset label7
  198.         DD      offset label8
  199.         DD      offset label9
  200.         DD      offset label10
  201.         DD      offset label11
  202.         DD      offset label12
  203.         DD      offset label13
  204.         DD      offset label14
  205.         DD      offset label15
  206.         DD      offset label16
  207.         DD      offset label17
  208.         DD      offset label18
  209.         DD      offset label19
  210.         DD      offset label20
  211.         DD      offset label21
  212.         DD      offset label22
  213.         DD      offset label23
  214.         DD      offset label24
  215.         DD      offset label25
  216.         DD      offset label26
  217.         DD      offset label27
  218.         DD      offset label28
  219.         DD      offset label29
  220.         DD      offset label30
  221.         DD      offset label31
  222.         DD      offset label32
  223.         DD      offset label33
  224.         DD      offset label34
  225.         DD      offset label35
  226.         DD      offset label36
  227.         DD      offset label37
  228.         DD      offset label38
  229.         DD      offset label39
  230.         DD      offset label40
  231.         DD      offset label41
  232.         DD      offset label42
  233.         DD      offset label43
  234.         DD      offset label44
  235.         DD      offset label45
  236.         DD      offset label46
  237.         DD      offset label47
  238.         DD      offset label48
  239.         DD      offset label49
  240.         DD      offset label50
  241.         DD      offset label51
  242.         DD      offset label52
  243.         DD      offset label53
  244.         DD      offset label54
  245.         DD      offset label55
  246.         DD      offset label56
  247.         DD      offset label57
  248.         DD      offset label58
  249.         DD      offset label59
  250.         DD      offset label60
  251.         DD      offset label61
  252.         DD      offset label62
  253.         DD      offset label63
  254.  
  255. _DATA   ENDS
  256.  
  257.  
  258. _TEXT  SEGMENT   DWORD USE32 PUBLIC 'CODE'
  259.  
  260.  
  261.         assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:nothing
  262.  
  263. ;
  264. ;  PRELIMINARY VERSION for register-register divides.
  265. ;
  266.  
  267.  
  268.                                         ; In this implementation the
  269.                                         ; fdiv_main_routine is called,
  270.                                         ; therefore all the stack frame
  271.                                         ; locations are adjusted for the
  272.                                         ; return pointer.
  273.  
  274. fdiv_main_routine PROC  NEAR
  275.  
  276.         fld     tbyte ptr [esp+MAIN_NUMER]      ; load the numerator
  277.         fld     tbyte ptr [esp+MAIN_DENOM]      ; load the denominator
  278. retry:
  279.  
  280. ;  The following three lines test for denormals and zeros.
  281. ;  A denormal or zero has a 0 in the explicit digit to the left of the
  282. ;  binary point.  Since that bit is the high bit of the word, adding
  283. ;  it to itself will produce a carry if and only if the number is not
  284. ;  denormal or zero.
  285. ;
  286.         mov     eax, [esp+MAIN_DENOM+4] ; get mantissa bits 32-64
  287.         add     eax,eax                 ; shift the one's bit onto carry
  288.         jnc     denormal                ; if no carry, we're denormal
  289.  
  290. ;  The following three lines test the three bits after the four bit
  291. ;  pattern (1,4,7,a,d).  If these three bits are not all one, then
  292. ;  the denominator cannot expose the flaw.  This condition is tested by
  293. ;  inverting the bits and testing that all are equal to zero afterward.
  294.  
  295.         xor     eax, ONESMASK           ; invert the bits that must be ones
  296.         test    eax, ONESMASK           ; and make sure they are all ones
  297.         jz      scale_if_needed         ; if all are one scale numbers
  298.         fdivp   st(1), st               ; use of hardware is OK.
  299.         ret
  300.  
  301. ;
  302. ;  Now we test the four bits for one of the five patterns.
  303. ;
  304. scale_if_needed:
  305.         shr     eax, 28                 ; keep first 4 bits after point
  306.         cmp     byte ptr fdiv_risc_table[eax], 0        ; check for (1,4,7,a,d)
  307.         jnz     divide_scaled           ; are in potential problem area
  308.         fdivp   st(1), st               ; use of hardware is OK.
  309.         ret
  310.  
  311. divide_scaled:
  312.         mov     eax, [esp + MAIN_DENOM+8]       ; test denominator exponent
  313.         and     eax, 07fffh             ; if pseudodenormal ensure that only
  314.         jz      invalid_denom           ; invalid exception flag is set
  315.         cmp     eax, 07fffh             ; if NaN or infinity  ensure that only
  316.         je      invalid_denom           ; invalid exception flag is set
  317. ;
  318. ;  The following six lines turn off exceptions and set the
  319. ;  precision control to 80 bits.  The former is necessary to
  320. ;  force any traps to be taken at the divide instead of the scaling
  321. ;  code.  The latter is necessary in order to get full precision for
  322. ;  codes with incoming 32 and 64 bit precision settings.  If
  323. ;  it can be guaranteed that before reaching this point, the underflow
  324. ;  exception is masked and the precision control is at 80 bits, these
  325. ;  six lines can be omitted.
  326. ;
  327.         fnstcw  [esp+PREV_CW]           ; save caller's control word
  328.         mov     eax, [esp+PREV_CW]
  329.         or      eax, 033fh              ; mask exceptions, pc=80
  330.         and     eax, 0f3ffh             ; set rounding mode to nearest
  331.         mov     [esp+PATCH_CW], eax
  332.         fldcw   [esp+PATCH_CW]          ; mask exceptions & pc=80
  333.  
  334. ;  The following lines check the numerator exponent before scaling.
  335. ;  This in order to prevent undeflow when scaling the numerator,
  336. ;  which will cause a denormal exception flag to be set when the
  337. ;  actual divide is preformed. This flag would not have been set
  338. ;  normally. If there is a risk of underflow, the scale factor is
  339. ;  17/16 instead of 15/16.
  340. ;
  341.         mov     eax, [esp+MAIN_NUMER+8] ; test numerator exponent
  342.         and     eax, 07fffh
  343.         cmp     eax, 00001h
  344.         je      small_numer
  345.  
  346.         fmul    fdiv_scale_1            ; scale denominator by 15/16
  347.         fxch
  348.         fmul    fdiv_scale_1            ; scale numerator by 15/16
  349.         fxch
  350.  
  351. ;
  352. ;  The next line restores the users control word.  If the incoming
  353. ;  control word had the underflow exception masked and precision
  354. ;  control set to 80 bits, this line can be omitted.
  355. ;
  356.  
  357.         fldcw   [esp+PREV_CW]           ; restore caller's control word
  358.         fdivp   st(1), st               ; use of hardware is OK.
  359.         ret
  360.  
  361. small_numer:
  362.         fmul    fdiv_scale_2            ; scale denominator by 17/16
  363.         fxch
  364.         fmul    fdiv_scale_2            ; scale numerator by 17/16
  365.         fxch
  366.  
  367. ;
  368. ;  The next line restores the users control word.  If the incoming
  369. ;  control word had the underflow exception masked and precision
  370. ;  control set to 80 bits, this line can be omitted.
  371. ;
  372.  
  373.         fldcw   [esp+PREV_CW]           ; restore caller's control word
  374.         fdivp   st(1), st               ; use of hardware is OK.
  375.         ret
  376.  
  377. denormal:
  378.         mov     eax, [esp+MAIN_DENOM]   ; test for whole mantissa == 0
  379.         or      eax, [esp+MAIN_DENOM+4] ; test for whole mantissa == 0
  380.         jnz     denormal_divide_scaled  ; denominator is not zero
  381. invalid_denom:                          ; zero or invalid denominator
  382.         fdivp   st(1), st               ; use of hardware is OK.
  383.         ret
  384.  
  385. denormal_divide_scaled:
  386.         mov     eax, [esp + MAIN_DENOM + 8]     ; get exponent
  387.         and     eax, 07fffh             ; check for zero exponent
  388.         jnz     invalid_denom           ;
  389. ;
  390. ;  The following six lines turn off exceptions and set the
  391. ;  precision control to 80 bits.  The former is necessary to
  392. ;  force any traps to be taken at the divide instead of the scaling
  393. ;  code.  The latter is necessary in order to get full precision for
  394. ;  codes with incoming 32 and 64 bit precision settings.  If
  395. ;  it can be guaranteed that before reaching this point, the underflow
  396. ;  exception is masked and the precision control is at 80 bits, these
  397. ;  five lines can be omitted.
  398. ;
  399.  
  400.         fnstcw  [esp+PREV_CW]           ; save caller's control word
  401.         mov     eax, [esp+PREV_CW]
  402.         or      eax, 033fh              ; mask exceptions, pc=80
  403.         and     eax, 0f3ffh             ; set rounding mode to nearest
  404.         mov     [esp+PATCH_CW], eax
  405.         fldcw   [esp+PATCH_CW]          ; mask exceptions & pc=80
  406.  
  407.         mov     eax, [esp + MAIN_NUMER +8]      ; test numerator exponent
  408.         and     eax, 07fffh             ; check for denormal numerator
  409.         je      denormal_numer
  410.         cmp     eax, 07fffh             ; NaN or infinity
  411.         je      invalid_numer
  412.         mov     eax, [esp + MAIN_NUMER + 4]     ; get bits 32..63 of mantissa
  413.         add     eax, eax                ; shift the first bit into carry
  414.         jnc     invalid_numer           ; if there is no carry, we have an
  415.                                         ; invalid numer
  416.         jmp     numer_ok
  417.  
  418. denormal_numer:
  419.         mov     eax, [esp + MAIN_NUMER + 4]     ; get bits 32..63 of mantissa
  420.         add     eax, eax                ; shift the first bit into carry
  421.         jc      invalid_numer           ; if there is a carry, we have an
  422.                                         ; invalid numer
  423.  
  424. numer_ok:
  425.         fxch
  426.         fstp    st                      ; pop numerator
  427.         fld     st                      ; make copy of denominator
  428.         fmul    dword ptr[one_shl_63]   ; make denominator not denormal
  429.         fstp    tbyte ptr [esp+MAIN_DENOM]      ; save modified denominator
  430.         fld     tbyte ptr [esp+MAIN_NUMER]      ; load numerator
  431.         fxch                            ; restore proper order
  432.         fwait
  433.  
  434. ;  The next line restores the users control word.  If the incoming
  435. ;  control word had the underflow exception masked and precision
  436. ;  control set to 80 bits, this line can be omitted.
  437. ;
  438.  
  439.         fldcw   [esp+PREV_CW]           ; restore caller's control word
  440.         jmp     retry                   ; start the whole thing over
  441.  
  442. invalid_numer:
  443. ;
  444. ;  The next line restores the users control word.  If the incoming
  445. ;  control word had the underflow exception masked and precision
  446. ;  control set to 80 bits, this line can be omitted.
  447. ;
  448.         fldcw   [esp + PREV_CW]
  449.         fdivp   st(1), st               ; use of hardware is OK.
  450.         ret
  451.  
  452. fdiv_main_routine       ENDP
  453.  
  454.         public  __fdiv_fpr
  455.         defpe   __fdiv_fpr
  456.  
  457.         sub     esp, STACK_SIZE
  458.         jmp     dword ptr dispatch_table[eax*4]
  459.  
  460.  
  461. label0:
  462.         fdiv    st,st(0)                ; D8 F0         FDIV    ST,ST(0)
  463.         add     esp, STACK_SIZE
  464.         ret
  465. label1:
  466.         add     esp, STACK_SIZE
  467.         int     ILLEGAL_OPC
  468. label2:
  469.         fdivr   st,st(0)                ; D8 F8         FDIVR   ST,ST(0)
  470.         add     esp, STACK_SIZE
  471.         ret
  472. label3:
  473.         add     esp, STACK_SIZE
  474.         int     ILLEGAL_OPC
  475. label4:
  476.         fdiv    st(0),st                ; DC F8/D8 F0   FDIV    ST(0),ST
  477.         add     esp, STACK_SIZE
  478.         ret
  479. label5:
  480.         fdivp   st(0),st                ; DE F8         FDIVP   ST(0),ST
  481.         add     esp, STACK_SIZE
  482.         ret
  483. label6:
  484.         fdivr   st(0),st                ; DC F0/DE F0   FDIVR   ST(0),ST
  485.         add     esp, STACK_SIZE
  486.         ret
  487. label7:
  488.         fdivrp  st(0),st                ; DE F0         FDIVRP  ST(0),ST
  489.         add     esp, STACK_SIZE
  490.         ret
  491. label8:
  492.         fdiv_st 1, 0
  493.         ret
  494. label9:
  495.         add     esp, STACK_SIZE
  496.         int     ILLEGAL_OPC
  497. label10:
  498.         fdivr_st 1, 0
  499.         ret
  500. label11:
  501.         add     esp, STACK_SIZE
  502.         int     ILLEGAL_OPC
  503. label12:
  504.         fdiv_sti 1, 0
  505.         ret
  506. label13:
  507.         fdivp_sti 1, 0
  508.         ret
  509. label14:
  510.         fdivr_sti 1, 0
  511.         ret
  512. label15:
  513.         fdivrp_sti 1, 0
  514.         ret
  515. label16:
  516.         fdiv_st 2, 1
  517.         ret
  518. label17:
  519.         add     esp, STACK_SIZE
  520.         int     ILLEGAL_OPC
  521. label18:
  522.         fdivr_st 2, 1
  523.         ret
  524. label19:
  525.         add     esp, STACK_SIZE
  526.         int     ILLEGAL_OPC
  527. label20:
  528.         fdiv_sti 2, 1
  529.         ret
  530. label21:
  531.         fdivp_sti 2, 1
  532.         ret
  533. label22:
  534.         fdivr_sti 2, 1
  535.         ret
  536. label23:
  537.         fdivrp_sti 2, 1
  538.         ret
  539. label24:
  540.         fdiv_st 3, 2
  541.         ret
  542. label25:
  543.         add     esp, STACK_SIZE
  544.         int     ILLEGAL_OPC
  545. label26:
  546.         fdivr_st 3, 2
  547.         ret
  548. label27:
  549.         add     esp, STACK_SIZE
  550.         int     ILLEGAL_OPC
  551. label28:
  552.         fdiv_sti 3, 2
  553.         ret
  554. label29:
  555.         fdivp_sti 3, 2
  556.         ret
  557. label30:
  558.         fdivr_sti 3, 2
  559.         ret
  560. label31:
  561.         fdivrp_sti 3, 2
  562.         ret
  563. label32:
  564.         fdiv_st 4, 3
  565.         ret
  566. label33:
  567.         add     esp, STACK_SIZE
  568.         int     ILLEGAL_OPC
  569. label34:
  570.         fdivr_st 4, 3
  571.         ret
  572. label35:
  573.         add     esp, STACK_SIZE
  574.         int     ILLEGAL_OPC
  575. label36:
  576.         fdiv_sti 4, 3
  577.         ret
  578. label37:
  579.         fdivp_sti 4, 3
  580.         ret
  581. label38:
  582.         fdivr_sti 4, 3
  583.         ret
  584. label39:
  585.         fdivrp_sti 4, 3
  586.         ret
  587. label40:
  588.         fdiv_st 5, 4
  589.         ret
  590. label41:
  591.         add     esp, STACK_SIZE
  592.         int     ILLEGAL_OPC
  593. label42:
  594.         fdivr_st 5, 4
  595.         ret
  596. label43:
  597.         add     esp, STACK_SIZE
  598.         int     ILLEGAL_OPC
  599. label44:
  600.         fdiv_sti 5, 4
  601.         ret
  602. label45:
  603.         fdivp_sti 5, 4
  604.         ret
  605. label46:
  606.         fdivr_sti 5, 4
  607.         ret
  608. label47:
  609.         fdivrp_sti 5, 4
  610.         ret
  611. label48:
  612.         fdiv_st 6, 5
  613.         ret
  614. label49:
  615.         add     esp, STACK_SIZE
  616.         int     ILLEGAL_OPC
  617. label50:
  618.         fdivr_st 6, 5
  619.         ret
  620. label51:
  621.         add     esp, STACK_SIZE
  622.         int     ILLEGAL_OPC
  623. label52:
  624.         fdiv_sti 6, 5
  625.         ret
  626. label53:
  627.         fdivp_sti 6, 5
  628.         ret
  629. label54:
  630.         fdivr_sti 6, 5
  631.         ret
  632. label55:
  633.         fdivrp_sti 6, 5
  634.         ret
  635. label56:
  636.         fdiv_st 7, 6
  637.         ret
  638. label57:
  639.         add     esp, STACK_SIZE
  640.         int     ILLEGAL_OPC
  641. label58:
  642.         fdivr_st 7, 6
  643.         ret
  644. label59:
  645.         add     esp, STACK_SIZE
  646.         int     ILLEGAL_OPC
  647. label60:
  648.         fdiv_sti 7, 6
  649.         ret
  650. label61:
  651.         fdivp_sti 7, 6
  652.         ret
  653. label62:
  654.         fdivr_sti 7, 6
  655.         ret
  656. label63:
  657.         fdivrp_sti 7, 6
  658.         ret
  659. __fdiv_fpr      ENDP
  660.  
  661.  
  662. __fdivp_sti_st    PROC    NEAR
  663.                                 ; for calling from mem routines
  664.         sub     esp, STACK_SIZE
  665.         fdivp_sti 1, 0
  666.         ret
  667. __fdivp_sti_st    ENDP
  668.  
  669. __fdivrp_sti_st   PROC    NEAR
  670.                                 ; for calling from mem routines
  671.         sub     esp, STACK_SIZE
  672.         fdivrp_sti 1, 0
  673.         ret
  674. __fdivrp_sti_st   ENDP
  675.  
  676.         public  __fdiv_chk
  677.         defpe __fdiv_chk
  678.                                 ; for calling from mem routines
  679.         sub     esp, STACK_SIZE
  680.         fdivrp_sti 1, 0
  681.         ret
  682. __fdiv_chk   ENDP
  683.  
  684. ;
  685. ;  PRELIMINARY VERSIONS of the routines for register-memory
  686. ;  divide instructions
  687. ;
  688.  
  689. ;;; FDIV_M32 - FDIV m32real FIX
  690. ;;
  691. ;;      Input : Value of the m32real in the top of STACK
  692. ;;
  693. ;;      Output: Result of FDIV in ST
  694.  
  695.         PUBLIC  __fdiv_m32
  696.         defpe   __fdiv_m32
  697.  
  698.         push    eax                             ; save eax
  699.         mov     eax, [esp + MEM_OPERAND]        ; check for
  700.         and     eax, SINGLE_NAN                 ; NaN
  701.         cmp     eax, SINGLE_NAN                 ;
  702.         je      memory_divide_m32               ;
  703.  
  704.         f_stsw  ax                              ; get status word
  705.         and     eax, 3800h                      ; get top of stack
  706.         je      spill_fpstack                   ; is FP stack full?
  707.         fld     dword ptr[esp + MEM_OPERAND]    ; load m32real in ST
  708.         call    __fdivp_sti_st                    ; do actual divide
  709.         pop     eax
  710.         ret     4
  711. spill_fpstack:
  712.         fxch
  713.         sub     esp, SPILL_SIZE                 ; make temp space
  714.         fstp    tbyte ptr[esp ]                 ; save user's ST(1)
  715.         fld     dword ptr[esp + SPILL_MEM_OPERAND] ; load m32 real
  716.         call    __fdivp_sti_st                    ; do actual divide
  717.         fld     tbyte ptr[esp]                  ; restore user's ST(1)
  718.                                                 ;esp is adjusted by fdivrp fn
  719.         fxch
  720.         add     esp, SPILL_SIZE
  721.         pop     eax
  722.         ret     4
  723. memory_divide_m32:
  724.         fdiv    dword ptr[esp + MEM_OPERAND]    ; do actual divide
  725.         pop     eax
  726.         ret     4
  727.  
  728. __fdiv_m32        ENDP
  729.  
  730.  
  731. ;;; FDIV_M64 - FDIV m64real FIX
  732. ;;
  733. ;;      Input : Value of the m64real in the top of STACK
  734. ;;
  735. ;;      Output: Result of FDIV in ST
  736.  
  737.         PUBLIC  __fdiv_m64
  738.         defpe   __fdiv_m64
  739.  
  740.         push    eax                             ; save eax
  741.         mov     eax, [esp + MEM_OPERAND + 4]    ; check for
  742.         and     eax, DOUBLE_NAN                 ; NaN
  743.         cmp     eax, DOUBLE_NAN                 ;
  744.         je      memory_divide_m64               ;
  745.  
  746.         f_stsw  ax                              ; get status word
  747.         and     eax, 3800h                      ; get top of stack
  748.         je      spill_fpstack_m64               ; is FP stack full?
  749.         fld     qword ptr[esp + MEM_OPERAND]    ; load m64real in ST
  750.         call    __fdivp_sti_st                    ; do actual divide
  751.         pop     eax
  752.         ret     8
  753. spill_fpstack_m64:
  754.         fxch
  755.         sub     esp, SPILL_SIZE                 ; make temp space
  756.         fstp    tbyte ptr[esp]                  ; save user's ST(1)
  757.         fld     qword ptr[esp + SPILL_MEM_OPERAND] ; load m64real
  758.         call    __fdivp_sti_st                    ; do actual divide
  759.         fld     tbyte ptr[esp]                  ; restore user's ST(1)
  760.                                                 ;esp is adjusted by fdivrp fn
  761.         fxch
  762.         add     esp, SPILL_SIZE
  763.         pop     eax
  764.         ret     8
  765.  
  766. memory_divide_m64:
  767.         fdiv    qword ptr[esp + MEM_OPERAND]    ; do actual divide
  768.         pop     eax
  769.         ret     8
  770.  
  771. __fdiv_m64        ENDP
  772.  
  773.  
  774.  
  775. ;;; FDIVR_M32 - FDIVR m32real FIX
  776. ;;
  777. ;;      Input : Value of the m32real in the top of STACK
  778. ;;
  779. ;;      Output: Result of FDIVR in ST
  780.  
  781.         PUBLIC  __fdiv_m32r
  782.         defpe   __fdiv_m32r
  783.         push    eax                             ; save eax
  784.         mov     eax, [esp + MEM_OPERAND]        ; check for
  785.         and     eax, SINGLE_NAN                 ; NaN
  786.         cmp     eax, SINGLE_NAN                 ;
  787.         je      memory_divide_m32r              ;
  788.  
  789.         f_stsw  ax                              ; get status word
  790.         and     eax, 3800h                      ; get top of stack
  791.         je      spill_fpstack_m32r              ; is FP stack full?
  792.         fld     dword ptr[esp + MEM_OPERAND]    ; load m32real in ST
  793.         call    __fdivrp_sti_st                   ; do actual divide
  794.         pop     eax
  795.         ret     4
  796. spill_fpstack_m32r:
  797.         fxch
  798.         sub     esp, SPILL_SIZE                 ; make temp space
  799.         fstp    tbyte ptr[esp ]                 ; save user's ST(1)
  800.         fld     dword ptr[esp + SPILL_MEM_OPERAND] ; load m32 real
  801.         call    __fdivrp_sti_st                   ; do actual divide
  802.         fld     tbyte ptr[esp]                  ; restore user's ST(1)
  803.                                                 ;esp is adjusted by fdivp fn
  804.         fxch
  805.         add     esp, SPILL_SIZE
  806.         pop     eax
  807.         ret     4
  808. memory_divide_m32r:
  809.         fdivr   dword ptr[esp + MEM_OPERAND]    ; do actual divide
  810.         pop     eax
  811.         ret     4
  812.  
  813. __fdiv_m32r     ENDP
  814.  
  815.  
  816. ;;; FDIVR_M64 - FDIVR m64real FIX
  817. ;;
  818. ;;      Input : Value of the m64real in the top of STACK
  819. ;;
  820. ;;      Output: Result of FDIVR in ST
  821.  
  822.         PUBLIC  __fdiv_m64r
  823.         defpe   __fdiv_m64r
  824.         push    eax                             ; save eax
  825.         mov     eax, [esp + MEM_OPERAND + 4]    ; check for
  826.         and     eax, DOUBLE_NAN                 ; NaN
  827.         cmp     eax, DOUBLE_NAN                 ;
  828.         je      memory_divide_m64r              ;
  829.  
  830.         f_stsw  ax                              ; get status word
  831.         and     eax, 3800h                      ; get top of stack
  832.         je      spill_fpstack_m64r              ; is FP stack full?
  833.         fld     qword ptr[esp + MEM_OPERAND]    ; load m64real in ST
  834.         call    __fdivrp_sti_st                   ; do actual divide
  835.         pop     eax
  836.         ret     8
  837. spill_fpstack_m64r:
  838.         fxch
  839.         sub     esp, SPILL_SIZE                 ; make temp space
  840.         fstp    tbyte ptr[esp ]                 ; save user's ST(1)
  841.         fld     qword ptr[esp + SPILL_MEM_OPERAND] ; load m64real
  842.         call    __fdivrp_sti_st                   ; do actual divide
  843.         fld     tbyte ptr[esp]                  ; restore user's ST(1)
  844.                                                 ;esp is adjusted by fdivp fn
  845.         fxch
  846.         add     esp, SPILL_SIZE
  847.         pop     eax
  848.         ret     8
  849. memory_divide_m64r:
  850.         fdivr   qword ptr[esp + MEM_OPERAND]    ; do actual divide
  851.         pop     eax
  852.         ret     8
  853.  
  854.  
  855. __fdiv_m64r       ENDP
  856.  
  857. comment ~******************************************************************
  858. ;;; FDIV_M16I - FDIV m16int FIX
  859. ;;
  860. ;;      Input : Value of the m16int in the top of STACK
  861. ;;
  862. ;;      Output: Result of FDIV in ST
  863.  
  864.         PUBLIC  FDIV_M16I
  865. FDIV_M16I       PROC    NEAR
  866.         push    eax                             ; save eax
  867.         f_stsw  ax                              ; get status word
  868.         and     eax, 3800h                      ; get top of stack
  869.         je      spill_fpstack_m16i              ; is FP stack full?
  870.         fild    word ptr[esp + MEM_OPERAND]     ; load m16int in ST
  871.         call    __fdivp_sti_st                    ; do actual divide
  872.         pop     eax
  873.         ret
  874. spill_fpstack_m16i:
  875.         fxch
  876.         sub     esp, SPILL_SIZE                 ; make temp space
  877.         fstp    tbyte ptr[esp ]                 ; save user's ST(1)
  878.         fild    word ptr[esp + SPILL_MEM_OPERAND] ; load m16int
  879.         call    __fdivp_sti_st                    ; do actual divide
  880.         fld     tbyte ptr[esp]                  ; restore user's ST(1)
  881.                                                 ;esp is adjusted by fdivrp fn
  882.         fxch
  883.         add     esp, SPILL_SIZE
  884.         pop     eax
  885.         ret
  886.  
  887. FDIV_M16I       ENDP
  888.  
  889. ;;; FDIV_M32I - FDIV m16int FIX
  890. ;;
  891. ;;      Input : Value of the m16int in the top of STACK
  892. ;;
  893. ;;      Output: Result of FDIV in ST
  894.  
  895.         PUBLIC  FDIV_M32I
  896. FDIV_M32I       PROC    NEAR
  897.         push    eax                             ; save eax
  898.         f_stsw  ax                              ; get status word
  899.         and     eax, 3800h                      ; get top of stack
  900.         je      spill_fpstack_m32i              ; is FP stack full?
  901.         fild    dword ptr[esp + MEM_OPERAND]    ; load m32int in ST
  902.         call    __fdivp_sti_st                    ; do actual divide
  903.         pop     eax
  904.         ret
  905. spill_fpstack_m32i:
  906.         fxch
  907.         sub     esp, SPILL_SIZE                 ; make temp space
  908.         fstp    tbyte ptr[esp ]                 ; save user's ST(1)
  909.         fild    dword ptr[esp + SPILL_MEM_OPERAND] ; load m32int
  910.         call    __fdivp_sti_st                    ; do actual divide
  911.         fld     tbyte ptr[esp]                  ; restore user's ST(1)
  912.                                                 ;esp is adjusted by fdivrp fn
  913.         fxch
  914.         add     esp, SPILL_SIZE
  915.         pop     eax
  916.         ret
  917.  
  918.  
  919. FDIV_M32I       ENDP
  920.  
  921.  
  922. ;;; FDIVR_M16I - FDIVR m16int FIX
  923. ;;
  924. ;;      Input : Value of the m16int in the top of STACK
  925. ;;
  926. ;;      Output: Result of FDIVR in ST
  927.  
  928.         PUBLIC  FDIVR_M16I
  929. FDIVR_M16I      PROC    NEAR
  930.         push    eax                             ; save eax
  931.         f_stsw  ax                              ; get status word
  932.         and     eax, 3800h                      ; get top of stack
  933.         je      spill_fpstack_m16ir             ; is FP stack full?
  934.         fild    word ptr[esp + MEM_OPERAND]     ; load m16int in ST
  935.         call    __fdivrp_sti_st                   ; do actual divide
  936.         pop     eax
  937.         ret
  938. spill_fpstack_m16ir:
  939.         fxch
  940.         sub     esp, SPILL_SIZE                 ; make temp space
  941.         fstp    tbyte ptr[esp ]                 ; save user's ST(1)
  942.         fild    word ptr[esp + SPILL_MEM_OPERAND] ; load m16int
  943.         call    __fdivrp_sti_st                   ; do actual divide
  944.         fld     tbyte ptr[esp]                  ; restore user's ST(1)
  945.                                                 ;esp is adjusted by fdivp fn
  946.         fxch
  947.         add     esp, SPILL_SIZE
  948.         pop     eax
  949.         ret
  950.  
  951.  
  952. FDIVR_M16I      ENDP
  953.  
  954.  
  955. ;;; FDIVR_M32I - FDIVR m32int FIX
  956. ;;
  957. ;;      Input : Value of the m32int in the top of STACK
  958. ;;
  959. ;;      Output: Result of FDIVR in ST
  960.  
  961.         PUBLIC  FDIVR_M32I
  962. FDIVR_M32I      PROC    NEAR
  963.         push    eax                             ; save eax
  964.         f_stsw  ax                              ; get status word
  965.         and     eax, 3800h                      ; get top of stack
  966.         je      spill_fpstack_m32ir             ; is FP stack full?
  967.         fild    dword ptr[esp + MEM_OPERAND]    ; load m32int in ST
  968.         call    __fdivrp_sti_st                   ; do actual divide
  969.         pop     eax
  970.         ret
  971. spill_fpstack_m32ir:
  972.         fxch
  973.         sub     esp, SPILL_SIZE                 ; make temp space
  974.         fstp    tbyte ptr[esp ]                 ; save user's ST(1)
  975.         fild    dword ptr[esp + SPILL_MEM_OPERAND] ; load m32int
  976.         call    __fdivrp_sti_st                   ; do actual divide
  977.         fld     tbyte ptr[esp]                  ; restore user's ST(1)
  978.                                                 ;esp is adjusted by fdivp fn
  979.         fxch
  980.         add     esp, SPILL_SIZE
  981.         pop     eax
  982.         ret
  983.  
  984. FDIVR_M32I      ENDP
  985. **********************************************************************~
  986.  
  987.  
  988.  
  989. _TEXT  ENDS
  990.  
  991.         end
  992.