home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR13 / OS2ASM.ZIP / FLOAT.ASM < prev    next >
Assembly Source File  |  1991-08-10  |  21KB  |  1,079 lines

  1. ;_float.asm    Mar 11 1991   Modified by: Phil Hinger */
  2. ;$Header$
  3. ;Copyright (C) 1984-1988 by Walter Bright
  4. ;All Rights Reserved, written by Walter Bright
  5. ;Floating point package
  6.  
  7. include macros.asm
  8.  
  9. include flthead.asm
  10.     .8087
  11.  
  12.     ifdef _MT
  13.     if LCODE
  14.     c_extrn    _FEEXCEPT,far
  15.     c_extrn    _FEROUND,far
  16.     else
  17.     c_extrn    _FEEXCEPT,near
  18.     c_extrn    _FEROUND,near
  19.     endif
  20.     endif
  21.  
  22.     begdata
  23.     c_extrn _8087,word        ;8087 flag word
  24.  
  25.     ifndef _MT
  26.     extrn    __fe_cur_env:word
  27.     endif
  28.  
  29.     enddata
  30.  
  31.     begcode    double
  32.  
  33.     ;Note:    0=int    2=unsigned    3=long    4=float    5=double
  34.  
  35.     public        __FSUB@
  36.     c_public    _FADD@,_FMUL@,_FDIV@,_FNEG@,_FTST@
  37.     c_public    _FTST0@,_FTST0EXC@
  38.     c_public    _FCMP@,_FCMPEXC@
  39.     c_public    _INTFLT@,_UNSFLT@,_LNGFLT@,_FLTINT@,_FLTUNS@,_FLTLNG@,_FLTUNLNG@
  40.  
  41.     if LCODE
  42.     c_extrn        _DBLINT@,far,_INTDBL@,far,_DBLUNS@,far,_UNSDBL@,far
  43.     c_extrn        _DBLLNG@,far,_LNGDBL@,far,_DBLULNG@,far,_ULNGDBL@,far
  44.     c_extrn        _DBLFLT@,far
  45.     else
  46.     c_extrn        _DBLINT@,near,_INTDBL@,near,_DBLUNS@,near,_UNSDBL@,near
  47.     c_extrn        _DBLLNG@,near,_LNGDBL@,near,_DBLULNG@,near,_ULNGDBL@,near
  48.     c_extrn        _DBLFLT@,near
  49.     endif
  50.  
  51.     extrn         fget_dtype:near, fround:near, fright_justify:near
  52.     extrn         fleft_justify:near, fnorm:near, funnorm:near
  53.     extrn         fget_dtype:near
  54.  
  55.       public           fget_dtype_pair
  56.  
  57.  
  58. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  59. ; Short real:
  60. ;    s | exponent| significand|
  61. ;    31|30      23|22        0|
  62.  
  63. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  64. ; get index of a pair of float
  65. ;    index = (case(b)*dtype_base + case(c)) * 2
  66. ; input:
  67. ;    [EDX] = b
  68. ;    [EAX] = c
  69. ; Output:
  70. ;    SI = index
  71. ;
  72. fget_dtype_pair proc near
  73.     clr    ESI                ;set to default
  74.     mov    EDI,EDX
  75.     test    EDI,shortexp
  76.     jz    fget_dtype_pair1
  77.  
  78.     and    EDI,shortexp                   ;mask exponent
  79.     _ifs     EDI ne short_infinity, fget_dtype_pair2  ;b is not NaN or infinite
  80.     mov    EDI,EDX
  81.     test    EDI,fqnan_bit                ;bit must be set to be
  82.     jz    fget_dtype_pair3            ;a quit NaN
  83.     mov    SI,dtype_qnan*4                ;b is a quite NaN
  84.     jmps    fget_dtype_pair2
  85.  
  86. fget_dtype_pair3:
  87.     and    EDI,shorthid-1                ;Mantissa must be zero
  88.     jz    fget_dtype_pair4            ;otherwise
  89.     mov    SI,dtype_snan*4                ;b is a signaling NaN
  90.     jmps    fget_dtype_pair2
  91.  
  92. fget_dtype_pair4:                    ;b is infinite
  93.     mov    SI,dtype_infinite*4
  94.     jmps    fget_dtype_pair2
  95.  
  96. fget_dtype_pair1:
  97.     test    EDX,shorthid-1
  98.     jnz    fget_dtype_pair2
  99.     mov    SI,dtype_zero*4                ;b is zero
  100.  
  101. fget_dtype_pair2:
  102.     test    EAX,shortexp
  103.     jz    fget_dtype_pair5
  104.  
  105.     mov    EDI,EAX
  106.     and    EDI,shortexp                   ;mask exponent
  107.     _ifs    EDI ne short_infinity, fget_dtype_pair6  ;c is not NaN or infinite
  108.     mov    EDI,EAX
  109.     test    EDI,fqnan_bit                ;bit must be set to be
  110.     jz    fget_dtype_pair7            ;a quit NaN
  111.     add    SI,dtype_qnan * dtype_base*4        ;c is a quite NaN
  112.     ret
  113.  
  114. fget_dtype_pair7:
  115.     and    EDI,shorthid-1                 ;Mantissa must be zero to be infinite
  116.     jz    fget_dtype_pair8            ;otherwise
  117.     add    SI,dtype_snan * dtype_base*4        ;c is a signaling NaN
  118.     ret
  119.  
  120. fget_dtype_pair8:                    ;c is infinite
  121.     add    SI,dtype_infinite * dtype_base*4
  122.     ret
  123.  
  124. fget_dtype_pair5:
  125.     test    EAX,shorthid-1
  126.     jnz    fget_dtype_pair6
  127.     add    SI,dtype_zero * dtype_base*4        ;c is zero
  128.  
  129. fget_dtype_pair6:
  130.     ret
  131. fget_dtype_pair endp
  132.  
  133. CCeq    equ    40h
  134. CClt    equ    81h
  135. CCgt    equ    00h
  136. CCinv    equ    45h
  137.  
  138.  
  139. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  140. ; Test and see if [EAX] is 0
  141.  
  142.     _align
  143. func    _FTST@
  144.     push    EAX
  145.     shl    EAX,1         ;dump sign bit
  146.     tst    EAX
  147.     pop    EAX
  148.     ret
  149. c_endp    _FTST@
  150.  
  151. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  152. ; Float compare against 0, setting sign bits appropriately
  153. ;    a = b ? 0
  154. ; Input:
  155. ;    [EAX] = b
  156. ; Output:
  157. ;    [EAX] = b
  158. ; _FTST0EXC@ is same as _FTST0@, but set invalid exception flag if
  159. ; the operand is a NAN.
  160.  
  161.     _align
  162. func    _FTST0EXC@
  163.     stc
  164.     jmp    short DT9
  165. c_endp    _FTST0EXC@
  166.  
  167.     _align
  168. func    _FTST0@
  169. if 1
  170.     clc
  171. DT9:    push    ESI
  172.     sbb    ESI,ESI              ;SI==-1 if raise exception
  173.     push    EDI
  174.     push    EAX
  175.  
  176.     ;Test if b is a special value
  177.     mov    EDI,EAX
  178.     and    EDI,shortexp
  179.     jz    DT1               ;c is 0 or subnormal
  180.     _ifs    EDI e shortexp, DT2        ;c is nan or infinity
  181.  
  182.     ;Do a straightforward comparison
  183.  
  184. DT3:    test    EAX,sgn_mask
  185.     jz    DTeq
  186.     cmp    EAX,0
  187.     mov    AH,CCgt
  188.     jg    DTret
  189.     mov    AH,CClt
  190. DTret:    ;or    AX,AX            ;OF (overflow flag) is already clear
  191.     sahf
  192.     _pop    <EAX,EDI,ESI>
  193.     ret
  194.  
  195.  
  196. DTeq:    mov    AH,CCeq
  197.     jmp    DTret
  198.  
  199.  
  200. DT1:    test    EAX,7fffffh
  201.     jnz    DT3            ;subnormal
  202.     jmp    DTeq            ;b is 0
  203.  
  204. DT2:    test    EAX,7fffffh
  205.     jz    DT3            ;b is infinity
  206.  
  207.     ;b is a NAN
  208.     mov    AH,CCinv
  209.     and    SI,FE_INVALID
  210.     or    __fe_cur_env.status,SI
  211.     jmp    DTret
  212.  
  213.  
  214. else
  215.     push    EAX
  216.     tst    EAX
  217.     js    TST01
  218.     neg    EAX
  219.     sbb    EAX,EAX
  220.     neg    EAX
  221.     pop    EAX
  222.     ret
  223.  
  224. TST01:
  225.     shl    EAX,1
  226.     neg    EAX             ;C=1 if b!=0
  227.     sbb    EAX,EAX              ;if (b==0) DX=0 else DX=-1
  228.     pop    EAX
  229.     ret
  230. endif
  231. c_endp    _FTST0@
  232.  
  233. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  234. ; Float compare
  235. ;    a = b ? c
  236. ; Input:
  237. ;    EAX = b
  238. ;    EDX = c
  239. ; Output:
  240. ;    no registers changed
  241. ;    Condition codes set same as 8087 would
  242. ;    (but also set SF and OF so that pre-3.0 code will link which
  243. ;    used signed jmps after FCMP)
  244. ;
  245. ; _FCMPEXC@ is same as _FCMP@, but set invalid exception flag if
  246. ; either of the operands are NAN.
  247.  
  248. if 1
  249.     _align
  250. func    _FCMPEXC@
  251.     stc
  252.     jmp    short DC9
  253. c_endp    _FCMPEXC@
  254.  
  255.     _align
  256. func    _FCMP@
  257.     clc
  258. DC9:
  259.     push    ESI
  260.     sbb    ESI,ESI              ;SI==-1 if raise exception
  261.     push    EDI
  262.     push    EDX
  263.     push    EAX
  264.  
  265.  
  266.     ;Test if c is a special value
  267.     mov    EDI,EDX
  268.     and    EDI,shortexp
  269.     jz    DC1            ;c is 0 or subnormal
  270.     _ifs     EDI e shortexp, DC2    ;c is nan or infinity
  271.  
  272.     ;Test if b is a special value
  273. DC3:    mov    EDI,EAX
  274.     and    EDI,shortexp
  275.     jz    DC4            ;b is 0 or subnormal
  276.     _ifs    EDI e shortexp, DC5    ;b is nan or infinity
  277.  
  278.     ;Do a straightforward comparison
  279. DC6:    mov    EDI,EDX
  280.     xor    EDI,EAX
  281.     js    DC8            ;signs are different
  282.     _ifs    EAX ne EDX, DC7
  283.  
  284.  
  285. DCeq:    mov    AH,CCeq
  286. DCret:    or    AX,AX            ;clear OF (overflow flag)
  287.     sahf
  288.     pop    EAX
  289.     pop    EDX
  290.     pop    EDI
  291.     pop    ESI
  292.     ret
  293.  
  294.  
  295. DC7:
  296.     mov    AH,CCgt
  297.     ja    DC10
  298.     mov    AH,CClt
  299. DC10:    test    EDX,sgn
  300.     jns    DCret
  301.     xor    AH,CCgt XOR CClt
  302.     jmp    DCret
  303.  
  304. DC8:    test    EDX,sgn
  305.     mov    AH,CClt
  306.     jns    DCret
  307.     mov    AH,CCgt
  308.     jmp    DCret
  309.  
  310. DC1:    test    EDX,7fffffh
  311.     jnz    DC3            ;subnormal
  312.     ;c is +0 or -0
  313.     and    EDX,sgn_mask        ;no -0 bugs
  314.     jmp    DC3            ;c is 0
  315.  
  316. DC2:    test    EDX,7fffffh
  317.     jz    DC3            ;c is infinity
  318.     jmp    short DCinv        ;c is a nan
  319.  
  320. DC4:    test    EAX,7fffffh
  321.     jnz    DC6            ;b is subnormal
  322.     ;c is +0 or -0
  323.     and    EAX,sgn_mask         ;no -0 bugs
  324.     jmp    DC6            ;b is 0
  325.  
  326. DC5:    test    EAX,7fffffh
  327.     jz    DC6            ;b is infinity
  328. ;    jmp    DCinv            ;b is a nan
  329.  
  330. DCinv:    mov    AH,CCinv
  331.     and    SI,FE_INVALID
  332.     or    __fe_cur_env.status,SI
  333.     jmp    DCret
  334. c_endp    _FCMP@
  335.  
  336.  
  337. else
  338. func    _FCMP@
  339.     push    EDI
  340.     push    EDX
  341.     push    ECX
  342.  
  343.     ;test if c is 0
  344.     mov    EDI,EDX
  345.     shl    EDI,1            ;dump sign bit
  346.     tst    EDI
  347.     jnz    C3            ;no
  348.     and    EDX,7fffffffh;        ;no -0 bugs
  349. C3:
  350.     mov    EDI,EAX
  351.     shl    EDI,1            ;dump sign bit
  352.     tst    EDI
  353.     jnz    C2            ;no
  354.     and    EAX,7fffffffh        ;convert -0 to 0
  355. C2:
  356.     mov    EDI,EAX
  357.     xor    EDI,EDX
  358.     js    C52            ;signs are different
  359.     mov    EDI,1            ;1 for positive compares
  360.     tst    ECX
  361.     jns    C51
  362.     neg    EDI            ;-1 for negative compares
  363. C51:    _ifs     EAX a EDX, C7          ;compare MSW
  364.     neg    EDI
  365. C7:    tst    EDI
  366. L21:    pop    ECX
  367.     pop    EDX
  368.     pop    EDI
  369.     ret
  370.  
  371. C52:    cmp    EAX,EDX
  372.     jmp    L21
  373. c_endp    _FCMP@
  374. endif
  375.  
  376. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  377. ;  floating add/subtract.
  378. ;    a = b +(-) c
  379. ; Input:
  380. ;    [EDX] = b
  381. ;    [EAX] = c
  382. ; Output:
  383. ;    a = [EAX]
  384. ;    SI,DI = preserved
  385. ; Stack offsets
  386.  
  387.  
  388.     padnn     =    24    ;so nn == dd == mm == 50
  389.     sign     =    padnn+8
  390.     signc     =    sign+4
  391.     subtract =    signc+4
  392.     exp     =    subtract+4
  393.     orgsign     =    exp+2
  394.     nn     =    orgsign+4
  395.     b     =    nn+P
  396.  
  397. __FSUB@:
  398.     push    EBP
  399.     sub    ESP,nn         ;make room for nn variables
  400.     mov    EBP,ESP
  401.     _ifs     __8087 e 0, A6         ;if no 8087
  402.     push    EAX            ;push b
  403.     fld    dword ptr -4[EBP]    ;load b into 8087
  404.     _push    EDX            ;push c
  405.     fsub    dword ptr -8[EBP]    ;sub c
  406.     jmps    fltret
  407.  
  408. A6:
  409.     mov    dword ptr orgsign[EBP],sgn ;need to flip sign back on  NaNs
  410.     xor    EDX,sgn            ;flip sign for subtraction
  411.     jmps    A1
  412.  
  413.     _align
  414. func    _FADD@
  415.     push    EBP
  416.     sub    ESP,nn            ;make room for nn variables
  417.     mov    EBP,ESP
  418.     mov    dword ptr orgsign[EBP],0  ;need for NaN
  419.     _ifs     __8087 e 0, A1          ;if no 8087
  420.     _push    EAX            ;push b
  421.     fld    dword ptr -4[EBP]     ;load b into 8087
  422.     _push    EDX            ;push c
  423.     fadd    dword ptr -8[EBP]     ;add c
  424.  
  425. fltret:
  426.     ;Check for floating point error
  427.     fstsw    -2[EBP]
  428.     fwait
  429.     mov    AX,-2[EBP]
  430.     and    AX,FE_ALL_EXCEPT
  431.     jnz    fltret5            ;jmp if error
  432. fltret4:
  433.     
  434.     fstp    dword ptr -8[EBP]
  435.     fwait
  436.     pop    EAX
  437.     pop    EDX            ;pop result
  438.     add    ESP,nn             ;subtract c off also
  439.     pop    EBP
  440.     ret
  441.  
  442. fltret5:
  443.     or    __fe_cur_env.status,AX
  444.     jmp    fltret4
  445.  
  446.  
  447. A1:
  448.     push    EDI
  449.     push    ESI
  450.     call    fget_dtype_pair
  451.     jmp    dword ptr cs:Daddindex[ESI]
  452.  
  453.     _align
  454. Daddindex    label    word
  455.     dd    ANormalAdd            ;other + other
  456.     dd    AFirstIsAnswer        ;other + zero
  457.     dd    ASecondIsAnswer        ;other + infinite
  458.     dd    ASecondAsQNaN        ;other + SNaN
  459.     dd    ASecondQNaN        ;other + QNaN
  460.  
  461.     dd    ASecondIsAnswer        ;zero + other
  462.     dd    Azeros            ;zero + zero
  463.     dd    ASecondIsAnswer        ;zero + infinite
  464.     dd    ASecondAsQNaN        ;zero + SNaN
  465.     dd    ASecondQNaN        ;zero + QNaN
  466.  
  467.     dd    AFirstIsAnswer        ;infinite + other
  468.     dd    AFirstIsAnswer        ;infinite + zero
  469.     dd    AInfiniteInfinite    ;infinite + infinite
  470.     dd    ASecondAsQNaN        ;infinite + SNaN
  471.     dd    ASecondQNaN        ;infinite + QNaN
  472.  
  473.     dd    AFirstAsQNaN        ;SNaN + other
  474.     dd    AFirstAsQNaN        ;SNaN + zero
  475.     dd    AFirstAsQNaN        ;SNaN + infinite
  476.     dd    ALargestSNaNasQNaN    ;SNaN + SNaN
  477.     dd    ASecondAsQNaN        ;SNaN + QNaN
  478.  
  479.     dd    AFirstQNaN        ;QNaN + other
  480.     dd    AFirstQNaN        ;QNaN + zero
  481.     dd    AFirstQNaN        ;QNaN + infinite
  482.     dd    AFirstAsQNaN        ;QNaN + SNaN
  483.     dd    ALargestQNaN        ;QNaN + QNaN
  484.  
  485. ANormalAdd:
  486.  
  487.     mov    signc[EBP],EAX        ;Save sign
  488.     mov    EDI,EDX
  489.     mov    sign[EBP],EDI
  490.     xor    EDI,EAX            ;if sign(b) != sign(c), then subtraction
  491.     mov    subtract[EBP],EDI    ;flag for subtraction
  492.  
  493.     call    funnorm            ;unpack second operand (c)
  494.     mov    exp[EBP],SI        ;save exponent of c
  495.     xchg    EAX,EDX            ;exchange regs
  496.     call    funnorm            ;unpack first operand (b)
  497.     sub    SI,exp[EBP]        ;SI = exp(b) - exp(c)
  498.     jle    A2            ;exp(b) > exp(c)
  499.     add    exp[EBP],SI        ;exponent is b
  500.     xchg    EAX,EDX
  501.     neg    SI
  502.     mov    EDI,signc[EBP]
  503.     mov    sign[EBP],EDI        ;reset sign
  504. A2:
  505.     call    fright_justify
  506.     test    dword ptr subtract[EBP],sgn ;subtracting? (test bit 15)
  507.     je    A3            ;no
  508.  
  509.     sub    EAX,EDX
  510.  
  511.     jnc    A4             ;no borrow
  512.     xor    dword ptr sign[EBP],sgn  ;toggle sign of result
  513.     neg    EAX             ;SI must be 0 for this to work
  514.  
  515. A4:
  516.     test    EAX,0c0000000h         ;if bit 8 or 7 are set then
  517.     jnz    A5             ;do normal round
  518.     tst    EAX             ;is result zero
  519.     je    Azeros1             ;yes
  520.  
  521.     mov    EDI,sign[EBP]
  522.     mov    SI,exp[EBP]         ;exponent of result
  523.     call    fnorm             ;normalize and pack
  524.     jmp    ADone
  525.  
  526. A3:
  527.     add    EAX,EDX
  528.     jnc    A5
  529.     rcr    EAX,1
  530.     inc    word ptr exp[EBP]     ;bump exponent
  531.  
  532. A5:
  533.     mov    EDI,sign[EBP]
  534.     mov    SI,exp[EBP]         ;exponent of result
  535.     call    fround             ;round and normalize
  536.     jmp    ADone
  537.  
  538.  
  539. Azeros:
  540.     mov    EDI,EAX
  541.     xor    EDI,EDX
  542.     test    EDI,sgn             ;are signs the same
  543.     jne    Azeros1
  544.     jmp    ADone             ;yes
  545.  
  546. Azeros1:
  547.     clr    EAX
  548.     _ifs     __fe_cur_env.round e FE_DOWNWARD,Azeros2
  549.     jmp    AFirstIsAnswer
  550. Azeros2:
  551.     mov    EAX,sgn             ;set sign to -
  552.     jmps    AFirstIsAnswer
  553.     
  554. AInfiniteInfinite:
  555.     mov    EDI,EAX
  556.     xor    EDI,EDX
  557.     test    EDI,sgn            ;are signs the same
  558.     je    AFirstIsAnswer        ;yes
  559.  
  560.                     ;Default invalid operation
  561.     mov    EAX,short_qnan OR 10000h
  562.     or    __fe_cur_env.status,FE_INVALID
  563.     jmps    ADone
  564.  
  565.  
  566. ASecondAsQNaN:
  567.     or    EDX,fqnan_bit
  568.     or    __fe_cur_env.status,FE_INVALID
  569.     jmps    ASecondQNaN
  570.  
  571.  
  572. ALargestSNaNasQNaN:
  573.     or    EAX,fqnan_bit
  574.     or    EDX,fqnan_bit
  575.     or    __fe_cur_env.status,FE_INVALID
  576.  
  577. ALargestQNaN:
  578.     mov    ESI,EAX
  579.     and    ESI,sgn_mask
  580.     mov    EDI,EDX
  581.     and    EDI,sgn_mask
  582.     _ifs    ESI ae EDI, AFirstIsAnswer
  583.  
  584. ASecondQNaN:
  585.     
  586.     xor    EDX,orgsign[EBP]     ;reset orginal sign
  587. ASecondIsAnswer:
  588.     mov    EAX,EDX
  589.     jmps    ADone
  590.  
  591. AFirstAsQNaN:
  592.     or    EAX,fqnan_bit
  593.     or    __fe_cur_env.status,FE_INVALID
  594.  
  595. AFirstQNaN:
  596.  
  597. AFirstIsAnswer:
  598.  
  599. ADone:
  600.     pop    ESI
  601.     pop    EDI
  602.     add    ESP,nn
  603.     pop    EBP
  604.     ret
  605. c_endp    _FADD@
  606. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  607. ; Floating divide.
  608. ;    a = b / c
  609. ; Input:
  610. ;     [EDX] = b
  611. ;     [EDX] = c
  612. ; Output:
  613. ;    a = [EAX]
  614. ;    ESI,EDI preserved
  615. ; Stack offsets:
  616.  
  617.     paddd    =    22        ;so nn == cxdd == mm == 50
  618.     resp    =    paddd+16    ;pointer to result
  619.     sign    =    resp+4        ;sign of result
  620.     exp    =    sign+4        ;exponent of result
  621.     count    =    exp+2        ;loop counter
  622.     cxdd    =    count+2        ;amount of local variables
  623.  
  624. func    _FDIV@
  625.     push    EBP
  626.     sub    ESP,cxdd
  627.     mov    EBP,ESP
  628.  
  629.     _ifs     __8087 e 0, D7          ;if no 8087
  630.     push    EAX            ;push b
  631.     fld    dword ptr -4[EBP]    ;load b into 8087
  632.     push    EDX            ;push c
  633.     fdiv    dword ptr -8[EBP]     ;div c
  634.     jmp    fltret
  635.  
  636. D7:    push    ESI
  637.     push    EDI
  638.  
  639.     mov    sign[EBP],EAX        ;transfer sig(b) to 0[EBP]
  640.     xor    sign[EBP],EDX
  641.     and    dword ptr sign[EBP],sgn
  642.     call    fget_dtype_pair
  643.     jmp    dword ptr cs:Dindex[ESI]
  644.  
  645.     _align
  646. Dindex    label    word
  647.     dd    DNormalDivide        ;other / other
  648.     dd    DDivideByZero        ;other / zero
  649.     dd    DSignedZero        ;other / infinite
  650.     dd    DSecondAsQNaN        ;other / SNaN
  651.     dd    DSecondQNaN        ;other / QNaN
  652.  
  653.     dd    DSignedZero        ;zero / other
  654.     dd    DDefaultQNaN        ;zero / zero
  655.     dd    DSignedZero        ;zero / infinite
  656.     dd    DSecondAsQNaN        ;zero / SNaN
  657.     dd    DSecondQNaN        ;zero / QNaN
  658.  
  659.     dd    DSignedInfinite        ;infinite / other
  660.     dd    DSignedInfinite        ;infinite / zero
  661.     dd    DDefaultQNaN        ;infinite / infinite
  662.     dd    DSecondAsQNaN        ;infinite / SNaN
  663.     dd    DSecondQNaN        ;infinite / QNaN
  664.  
  665.     dd    DFirstAsQNaN        ;SNaN / other
  666.     dd    DFirstAsQNaN        ;SNaN / zero
  667.     dd    DFirstAsQNaN        ;SNaN / infinite
  668.     dd    DLargestSNaNasQNaN    ;SNaN / SNaN
  669.     dd    DSecondAsQNaN        ;SNaN / QNaN
  670.  
  671.     dd    DFirstQNaN        ;QNaN / other
  672.     dd    DFirstQNaN        ;QNaN / zero
  673.     dd    DFirstQNaN        ;QNaN / infinite
  674.     dd    DFirstAsQNaN        ;QNaN / SNaN
  675.     dd    DLargestQNaN        ;QNaN / QNaN
  676.  
  677.  
  678. DNormalDivide:
  679.     ;unpack c
  680.     mov    EDI,EDX
  681.     and    EDI,shortexp        ;mask off exponent bits
  682.     and    EDX,shorthid-1        ;remove exponent from mantissa
  683.     tst    EDI            ;is exponent zero
  684.     jnz    D12
  685.                     ;special case when exponent is zero
  686.     xchg    EAX,EDX            ;may need to do a lot of shifting
  687.     call    fleft_justify        ;msb must be block to left
  688.     xchg    EAX,EDX
  689.     mov    DI,SI            ;save exponent
  690.     jmps    D13
  691. D12:
  692.     or    EDX,shorthid
  693.     shr    EDI,16+7        ;right justify exponent
  694. D13:
  695.     
  696.     ;unpack b
  697.     mov    ESI,EAX
  698.     and    ESI,shortexp        ;mask off exponent bits
  699.     and    EAX,shorthid-1
  700.     tst    ESI            ;is exponent zero
  701.     jnz    D14
  702.                     ;special case when exponent is zero
  703.     call    fleft_justify        ;msb must be block to left
  704.     jmps    D15
  705. D14:
  706.     or    EAX,shorthid        ;or in hidden bit
  707.     shr    ESI,16+7        ;right justify exponent
  708. D15:
  709.     sub    SI,DI            ;exp(result) = exp(b) - exp(c)
  710.     add    SI,shortbias        ;so bias is retained after subtraction
  711.     mov    exp[EBP],SI        ;exponent of result
  712.  
  713.     shl    EDX,1            ;Make sure there is not an overflow
  714.     dec    SI
  715.     mov    ECX,EDX
  716.     mov    EDX,EAX
  717.     clr    EAX            ;arange regestors for divide
  718.     div    ECX
  719.     tst    EDX
  720.     je    D16
  721.     or    EAX,1            ;set Sticky bit if remainder
  722. D16:
  723.     mov    SI,exp[EBP]
  724.     mov    EDI,sign[EBP]
  725.     call    fround            ;round and normalize result
  726.     jmp    DDone
  727.  
  728.  
  729.  
  730. DDivideByZero:
  731.     or    __fe_cur_env.status,FE_DIVBYZERO
  732.  
  733. DSignedInfinite:
  734.     mov    EAX,sign[EBP]
  735.     or    EAX,short_infinity
  736.     jmps    DDone
  737.  
  738. DSignedZero:
  739.     mov    EAX,sign[EBP]
  740.     jmps    DDone
  741.  
  742. DSecondAsQNaN:
  743.     or    EDX,fqnan_bit
  744.     or    __fe_cur_env.status,FE_INVALID
  745.  
  746. DSecondQNaN:
  747.     xchg    EAX,EDX
  748.     jmps    DDone
  749.  
  750.     _align
  751. DDefaultQNaN:
  752.     mov    EAX,short_qnan OR 10000h
  753.     or    EAX,sign[EBP]
  754.     or    __fe_cur_env.status,FE_INVALID
  755.     jmps    DDone
  756.  
  757.  
  758. DLargestSNaNasQNaN:
  759.     or    EAX,fqnan_bit
  760.     or    EDX,fqnan_bit
  761.     or    __fe_cur_env.status,FE_INVALID
  762.  
  763. DLargestQNaN:
  764.     mov    ESI,EAX
  765.     and    ESI,sgn_mask
  766.     mov    EDI,EDX
  767.     and    EDI,sgn_mask
  768.     _ifs    ESI ae EDI, DFirstQNaN
  769.     jmps    DSecondQNaN
  770.  
  771. DFirstAsQNaN:
  772.     or    EAX,fqnan_bit
  773.     or    __fe_cur_env.status,FE_INVALID
  774. DFirstQNaN:
  775.  
  776. DDone:
  777.     pop    EDI
  778.     pop    ESI
  779.     add    ESP,cxdd
  780.     pop    EBP
  781.     ret
  782. c_endp    _FDIV@
  783.  
  784. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  785. ; Floating Multiply
  786. ;    a = b * c
  787. ; Input:
  788. ;    [EAX] = b
  789. ;    [EDX] = c
  790. ; Output:
  791. ;    a = [EDX]
  792. ;    ESI,EDI preserved
  793. ; Stack offsets:
  794.  
  795.     padmm    =    30        ;so nn == cxdd == mm == 50
  796.     resp    =    padmm+8        ;pointer to result
  797.     sign    =    resp+4        ;sign of result
  798.     exp    =    sign+4        ;exponent of result
  799.     count    =    exp+2        ;loop counter
  800.     mm        =    count+2        ;amount of local variables
  801.  
  802. func    _FMUL@
  803.     push    EBP
  804.     sub    ESP,mm
  805.     mov    EBP,ESP
  806.  
  807.     _ifs     __8087 e 0, M1          ;if no 8087
  808.     push    EAX            ;push b
  809.     fld    dword ptr -4[EBP]    ;load b into 8087
  810.     push    EDX            ;push c
  811.     fmul    dword ptr -8[EBP]    ;mul c
  812.     jmp    fltret
  813.  
  814. M1:    push    ESI
  815.     push    EDI
  816.  
  817.     mov    sign[EBP],EAX        ;transfer sig(b) to 0[EBP]
  818.     xor    sign[EBP],EDX
  819.     and    dword ptr sign[EBP],sgn
  820.     call    fget_dtype_pair
  821.     jmp    dword ptr cs:Mindex[ESI]
  822.  
  823. Mindex    label    dword
  824.     dd    MNormalMultiply        ;other * other
  825.     dd    MSignedZero        ;other * zero
  826.     dd    MSignedInfinite        ;other * infinite
  827.     dd    MSecondAsQNaN        ;other * SNaN
  828.     dd    MSecondQNaN        ;other * QNaN
  829.  
  830.     dd    MSignedZero        ;zero * other
  831.     dd    MSignedZero        ;zero * zero
  832.     dd    MDefaultQNaN        ;zero * infinite
  833.     dd    MSecondAsQNaN        ;zero * SNaN
  834.     dd    MSecondQNaN        ;zero * QNaN
  835.  
  836.     dd    MSignedInfinite        ;infinite * other
  837.     dd    MDefaultQNaN        ;infinite * zero
  838.     dd    MSignedInfinite        ;infinite * infinite
  839.     dd    MSecondAsQNaN        ;infinite * SNaN
  840.     dd    MSecondQNaN        ;infinite * QNaN
  841.  
  842.     dd    MFirstAsQNaN        ;SNaN * other
  843.     dd    MFirstAsQNaN        ;SNaN * zero
  844.     dd    MFirstAsQNaN        ;SNaN * infinite
  845.     dd    MLargestSNaNasQNaN    ;SNaN * SNaN
  846.     dd    MSecondAsQNaN        ;SNaN * QNaN
  847.  
  848.     dd    MFirstQNaN        ;QNaN * other
  849.     dd    MFirstQNaN        ;QNaN * zero
  850.     dd    MFirstQNaN        ;QNaN * infinite
  851.     dd    MFirstAsQNaN        ;QNaN * SNaN
  852.     dd    MLargestQNaN        ;QNaN * QNaN
  853.  
  854.  
  855. MNormalMultiply:
  856.     call    funnorm        ;unpack second operand (c)
  857.     mov    exp[EBP],SI    ;save exponent of c
  858.     xchg    EAX,EDX        ;may need to do a lot of shifting
  859.     call    funnorm        ;unpack second operand (b)
  860.     sub    ESI,shortbias - 1;so bias is retained after add
  861.     add    SI,exp[EBP]
  862.  
  863.     shr    EDX,1        ;Make sure there is not an overflow
  864.     inc    SI
  865.     MUL    EDX
  866.     test    EDX,0c0000000h     ;Make sure one of the two high order
  867.     jne    M4        ;bits are set
  868.     shld    EDX,EAX,1    ;in this case the third will alway be set
  869.     shl    EAX,1
  870.     dec    SI
  871. M4:
  872.     tst    EAX        ;check for sticky bits
  873.     je    M5
  874.     or    EDX,1
  875. M5:
  876.     mov    EAX,EDX
  877.     mov    EDI,sign[EBP]
  878.     call    fround        ;round and normalize result
  879.     jmp    MDone
  880.  
  881. MSignedInfinite:
  882.     mov    EAX,sign[EBP]
  883.     or    EAX,short_infinity
  884.     jmps    MDone
  885.  
  886. MSignedZero:
  887.     mov    EAX,sign[EBP]
  888.     jmps    MDone
  889.  
  890. MSecondAsQNaN:
  891.     or    EDX,fqnan_bit
  892.     or    __fe_cur_env.status,FE_INVALID
  893.  
  894. MSecondQNaN:
  895.     xchg    EAX,EDX
  896.     jmps    MDone
  897.  
  898. MDefaultQNaN:
  899.     mov    EAX,short_qnan
  900.     or    EAX,sign[EBP]
  901.     or    __fe_cur_env.status,FE_INVALID
  902.     jmps    MDone
  903.  
  904.  
  905. MLargestSNaNasQNaN:
  906.     or    EAX,fqnan_bit
  907.     or    EDX,fqnan_bit
  908.     or    __fe_cur_env.status,FE_INVALID
  909.  
  910. MLargestQNaN:
  911.     mov    ESI,EAX
  912.     and    ESI,sgn_mask
  913.     mov    EDI,EDX
  914.     and    EDI,sgn_mask
  915.     _ifs    ESI a EDI,   MFirstQNaN
  916.     jmps    MSecondQNaN
  917.  
  918. MFirstAsQNaN:
  919.     or    EAX,fqnan_bit
  920.     or    __fe_cur_env.status,FE_INVALID
  921. MFirstQNaN:
  922.  
  923. MDone:
  924.     pop    EDI
  925.     pop    ESI
  926.     add    ESP,mm
  927.     pop    EBP
  928.     ret
  929. c_endp    _FMUL@
  930. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  931. ;
  932. func    _FNEG@
  933.     xor    EAX,sgn
  934.     ret
  935. c_endp    _FNEG@
  936.  
  937. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  938. ; Convert int to float
  939.  
  940. func    _INTFLT@
  941.     _push    <EBX,ECX,EDX>
  942.     callm    _INTDBL@
  943. CX1:    callm    _DBLFLT@
  944. CX2:    _pop    <EDX,ECX,EBX>
  945.     ret
  946. c_endp    _INTFLT@
  947. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  948. ; Convert float to unsigned.
  949.  
  950.  
  951.     _align
  952. func    _FLTUNS@
  953.     push    EDX
  954.     mov    DX,15
  955.     test    EAX,sgn
  956.     jz    fltIntgl
  957.  
  958.     or    __fe_cur_env.status,FE_INVALID
  959.     ret
  960. c_endp    _FLTUNS@
  961.  
  962. ; Convert float to int.
  963.  
  964. func    _FLTINT@
  965.     push    EDX
  966.     mov    DX,14
  967.     test    EAX,sgn
  968.     je    fltIntgl
  969.  
  970.     inc    DX
  971.     jmps    fltIntgl
  972. c_endp    _FLTINT@
  973.  
  974.  
  975. ; Convert float to unsigned long.
  976.  
  977. func    _FLTUNLNG@
  978.     push    EDX
  979.     mov    DX,31
  980.     test    EAX,sgn
  981.     jz    fltIntgl
  982.  
  983.     or    __fe_cur_env.status,FE_INVALID
  984.     ret
  985. c_endp    _FLTUNLNG@
  986.  
  987. ; Convert float to long
  988.  
  989. func    _FLTLNG@
  990.     push    EDX
  991.     mov    DX,30
  992.     test    EAX,sgn
  993.     jz    fltIntgl
  994.  
  995.     inc    DX
  996.  
  997. fltIntgl:
  998.     _push    <EBX,ECX,ESI,EDI>
  999.     call    fget_dtype
  1000.     shl    ESI,2
  1001.     jmp    dword ptr cs:fltIntglIndex[ESI]
  1002.  
  1003. fltIntglIndex label      word
  1004.     dd    fltIntglNormal          ;other
  1005.     dd    fltIntglZero          ;zero
  1006.     dd    fltIntglInvalid          ;infinite
  1007.     dd    fltIntglInvalid          ;SNaN
  1008.     dd    fltIntglInvalid          ;QNaN
  1009.  
  1010. fltIntglNormal:
  1011.     call    funnorm            ;unpack double
  1012.     clr    EBX
  1013.     sub    SI,shortbias        ;un-bias the exponent
  1014.     js    fltIntgl4        ;for neg exponents, the result is 0
  1015.     _ifs    SI a DX, fltIntglInvalid
  1016.     mov    ECX,31
  1017.     sub    CX,SI
  1018.     jcxz    fltIntgl2
  1019.  
  1020.     _align
  1021. fltIntgl3:
  1022.     shr    EAX,1
  1023.     rcr    BH,1            ;keep stick bit
  1024.     adc    BL,0            ;keep gaurd bit
  1025.     loop    fltIntgl3
  1026.  
  1027. fltIntgl2:
  1028.     tst    BX
  1029.     je    fltIntgl6
  1030.     or    __fe_cur_env.status,FE_INEXACT    ;no longer exact
  1031. fltIntgl6:
  1032.     test    EDI,sgn            ;is result negative?
  1033.     jns    fltIntglDone        ;no
  1034.     neg    EAX            ;yes
  1035.     jmps    fltIntglDone
  1036.  
  1037. fltIntgl4:
  1038.     mov    BL,1        ;save stick bits
  1039.     cmp    SI,-1        ;is guard bit needed
  1040.     je    fltIntgl5
  1041.     or    BH,80h        ;make guard bit into sticky bit
  1042. fltIntgl5:
  1043.     clr    EAX
  1044.     jmps    fltIntgl2
  1045. fltIntglInexact:
  1046.     or    __fe_cur_env.status,FE_INEXACT    ;no longer exact
  1047. fltIntglZero:
  1048.     clr    EAX         ;result is 0
  1049.     jmps   fltIntglDone
  1050.  
  1051. fltIntglInvalid:
  1052.     or    __fe_cur_env.status,FE_INVALID
  1053.  
  1054. fltIntglDone:
  1055.     _pop    <EDI,ESI,ECX,EBX,EDX>
  1056.     ret
  1057. c_endp    _FLTLNG@
  1058.  
  1059. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1060. ; Convert unsigned to float
  1061.  
  1062. func    _UNSFLT@
  1063.     _push    <EBX,ECX,EDX>
  1064.     callm    _UNSDBL@
  1065.     jmp    CX1
  1066. c_endp    _UNSFLT@
  1067.  
  1068. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1069. ; Convert long to float
  1070.  
  1071. __LNGFLT@:
  1072.     _push    <EBX,ECX,EDX>
  1073.     callm    _LNGDBL@
  1074.     jmp    CX1
  1075.     endcode double
  1076.  
  1077.     end
  1078.  
  1079.