chipd32.asm

来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 992 行 · 第 1/3 页

ASM
992
字号
;*****************************************************************************
;*
;*                            Open Watcom Project
;*
;*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
;*
;*  ========================================================================
;*
;*    This file contains Original Code and/or Modifications of Original
;*    Code as defined in and that are subject to the Sybase Open Watcom
;*    Public License version 1.0 (the 'License'). You may not use this file
;*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
;*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
;*    provided with the Original Code and Modifications, and is also
;*    available at www.sybase.com/developer/opensource.
;*
;*    The Original Code and all software distributed under the License are
;*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
;*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
;*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
;*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
;*    NON-INFRINGEMENT. Please see the License for the specific language
;*    governing rights and limitations under the License.
;*
;*  ========================================================================
;*
;* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
;*               DESCRIBE IT HERE!
;*
;*****************************************************************************


; static char sccs_id[] = "@(#)patch32.asm      1.12  12/21/94  14:53:51";
;
; This code is being published by Intel to users of the Pentium(tm)
; processor.  Recipients are authorized to copy, modify, compile, use and
; distribute the code.
;
; Intel makes no warranty of any kind with regard to this code, including
; but not limited to, implied warranties or merchantability and fitness for
; a particular purpose. Intel assumes no responsibility for any errors that
; may appear in this code.
;
; No patent licenses are granted, express or implied.
;
;
include mdef.inc

.386
.387

DENOM           EQU     0
NUMER           EQU     12
PREV_CW         EQU     28      ; 24 + 4 (return size)
PATCH_CW        EQU     32      ; 28 + 4 (return size)

DENOM_SAVE      EQU     32

MAIN_DENOM      EQU     4
MAIN_NUMER      EQU     16

SPILL_SIZE      EQU     12
MEM_OPERAND     EQU     8
STACK_SIZE      EQU     44
SPILL_MEM_OPERAND       EQU     20

ONESMASK        EQU     0e000000h

SINGLE_NAN      EQU     07f800000h
DOUBLE_NAN      EQU     07ff00000h

ILLEGAL_OPC     EQU     6

f_stsw  macro   where
        fstsw   where
endm

fdivr_st        MACRO   reg_index, reg_index_minus1
        fstp    tbyte ptr [esp+DENOM]
IF      reg_index_minus1 GE 1
        fxch    st(reg_index_minus1)
ENDIF
        fstp    tbyte ptr [esp+NUMER]
        call    fdiv_main_routine
IF      reg_index_minus1 GE 1
        fxch    st(reg_index_minus1)
ENDIF
        fld     tbyte ptr [esp+NUMER]
        fxch    st(reg_index)
        add     esp, STACK_SIZE
ENDM

fdivr_sti       MACRO   reg_index, reg_index_minus1
        fstp    tbyte ptr [esp+NUMER]
IF      reg_index_minus1 GE 1
        fxch    st(reg_index_minus1)
ENDIF
        fstp    tbyte ptr [esp+DENOM]
        call    fdiv_main_routine
IF      reg_index_minus1 GE 1
        fxch    st(reg_index_minus1)
ENDIF
        fld     tbyte ptr [esp+NUMER]
        add     esp, STACK_SIZE
ENDM

fdivrp_sti      MACRO   reg_index, reg_index_minus1
        fstp    tbyte ptr [esp+NUMER]
IF      reg_index_minus1 GE 1
        fxch    st(reg_index_minus1)
ENDIF
        fstp    tbyte ptr [esp+DENOM]
        call    fdiv_main_routine
IF      reg_index_minus1 GE 1
        fxch    st(reg_index_minus1)
ENDIF
        add     esp, STACK_SIZE
ENDM

fdiv_st         MACRO   reg_index, reg_index_minus1
        fstp    tbyte ptr [esp+NUMER]
IF      reg_index_minus1 GE 1
        fxch    st(reg_index_minus1)
ENDIF
        fld     st
        fstp    tbyte ptr [esp+DENOM]
        fstp    tbyte ptr [esp+DENOM_SAVE]      ; save original denom,
        call    fdiv_main_routine
IF      reg_index_minus1 GE 1
        fxch    st(reg_index_minus1)
ENDIF
        fld     tbyte ptr [esp+DENOM_SAVE]
        fxch    st(reg_index)
        add     esp, STACK_SIZE
ENDM

fdiv_sti        MACRO   reg_index, reg_index_minus1
        fxch    st(reg_index)
        fstp    tbyte ptr [esp+NUMER]
IF      reg_index_minus1 GE 1
        fxch    st(reg_index_minus1)
ENDIF
        fld     st
        fstp    tbyte ptr [esp+DENOM]
        fstp    tbyte ptr [esp+DENOM_SAVE]      ; save original denom,
        call    fdiv_main_routine
IF      reg_index_minus1 GE 1
        fxch    st(reg_index_minus1)
ENDIF
        fld     tbyte ptr [esp+DENOM_SAVE]
        add     esp, STACK_SIZE
ENDM

fdivp_sti       MACRO   reg_index, reg_index_minus1
        fstp    tbyte ptr [esp+DENOM]
IF      reg_index_minus1 GE 1
        fxch    st(reg_index_minus1)
ENDIF
        fstp    tbyte ptr [esp+NUMER]
        call    fdiv_main_routine
IF      reg_index_minus1 GE 1
        fxch    st(reg_index_minus1)
ENDIF
        add     esp, STACK_SIZE
ENDM

_TEXT  SEGMENT DWORD USE32 PUBLIC 'CODE'
_TEXT  ENDS

DATA32  SEGMENT DWORD USE32 PUBLIC 'DATA'
DATA32  ENDS

CONST32 SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST32 ENDS

BSS32   SEGMENT DWORD USE32 PUBLIC 'BSS'
BSS32   ENDS

DGROUP  GROUP CONST32, BSS32, DATA32


DATA32  SEGMENT DWORD USE32 PUBLIC 'DATA'

fdiv_risc_table DB      0, 1, 0, 0, 4, 0, 0, 7, 0, 0, 10, 0, 0, 13, 0, 0
fdiv_scale_1    DD      03f700000h              ;0.9375
fdiv_scale_2    DD      03f880000h              ;1.0625
one_shl_63      DD      05f000000h


dispatch_table DD       offset label0
        DD      offset label1
        DD      offset label2
        DD      offset label3
        DD      offset label4
        DD      offset label5
        DD      offset label6
        DD      offset label7
        DD      offset label8
        DD      offset label9
        DD      offset label10
        DD      offset label11
        DD      offset label12
        DD      offset label13
        DD      offset label14
        DD      offset label15
        DD      offset label16
        DD      offset label17
        DD      offset label18
        DD      offset label19
        DD      offset label20
        DD      offset label21
        DD      offset label22
        DD      offset label23
        DD      offset label24
        DD      offset label25
        DD      offset label26
        DD      offset label27
        DD      offset label28
        DD      offset label29
        DD      offset label30
        DD      offset label31
        DD      offset label32
        DD      offset label33
        DD      offset label34
        DD      offset label35
        DD      offset label36
        DD      offset label37
        DD      offset label38
        DD      offset label39
        DD      offset label40
        DD      offset label41
        DD      offset label42
        DD      offset label43
        DD      offset label44
        DD      offset label45
        DD      offset label46
        DD      offset label47
        DD      offset label48
        DD      offset label49
        DD      offset label50
        DD      offset label51
        DD      offset label52
        DD      offset label53
        DD      offset label54
        DD      offset label55
        DD      offset label56
        DD      offset label57
        DD      offset label58
        DD      offset label59
        DD      offset label60
        DD      offset label61
        DD      offset label62
        DD      offset label63

DATA32  ENDS


_TEXT  SEGMENT   DWORD USE32 PUBLIC 'CODE'


        assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:nothing

;
;  PRELIMINARY VERSION for register-register divides.
;


                                        ; In this implementation the
                                        ; fdiv_main_routine is called,
                                        ; therefore all the stack frame
                                        ; locations are adjusted for the
                                        ; return pointer.

fdiv_main_routine PROC  NEAR

        fld     tbyte ptr [esp+MAIN_NUMER]      ; load the numerator
        fld     tbyte ptr [esp+MAIN_DENOM]      ; load the denominator
retry:

;  The following three lines test for denormals and zeros.
;  A denormal or zero has a 0 in the explicit digit to the left of the
;  binary point.  Since that bit is the high bit of the word, adding
;  it to itself will produce a carry if and only if the number is not
;  denormal or zero.
;
        mov     eax, [esp+MAIN_DENOM+4] ; get mantissa bits 32-64
        add     eax,eax                 ; shift the one's bit onto carry
        jnc     denormal                ; if no carry, we're denormal

;  The following three lines test the three bits after the four bit
;  pattern (1,4,7,a,d).  If these three bits are not all one, then
;  the denominator cannot expose the flaw.  This condition is tested by
;  inverting the bits and testing that all are equal to zero afterward.

        xor     eax, ONESMASK           ; invert the bits that must be ones
        test    eax, ONESMASK           ; and make sure they are all ones
        jz      scale_if_needed         ; if all are one scale numbers
        fdivp   st(1), st               ; use of hardware is OK.
        ret

;
;  Now we test the four bits for one of the five patterns.
;
scale_if_needed:
        shr     eax, 28                 ; keep first 4 bits after point
        cmp     byte ptr fdiv_risc_table[eax], 0        ; check for (1,4,7,a,d)
        jnz     divide_scaled           ; are in potential problem area
        fdivp   st(1), st               ; use of hardware is OK.
        ret

divide_scaled:
        mov     eax, [esp + MAIN_DENOM+8]       ; test denominator exponent
        and     eax, 07fffh             ; if pseudodenormal ensure that only
        jz      invalid_denom           ; invalid exception flag is set
        cmp     eax, 07fffh             ; if NaN or infinity  ensure that only
        je      invalid_denom           ; invalid exception flag is set
;
;  The following six lines turn off exceptions and set the
;  precision control to 80 bits.  The former is necessary to
;  force any traps to be taken at the divide instead of the scaling
;  code.  The latter is necessary in order to get full precision for
;  codes with incoming 32 and 64 bit precision settings.  If
;  it can be guaranteed that before reaching this point, the underflow
;  exception is masked and the precision control is at 80 bits, these
;  six lines can be omitted.
;
        fnstcw  [esp+PREV_CW]           ; save caller's control word
        mov     eax, [esp+PREV_CW]
        or      eax, 033fh              ; mask exceptions, pc=80
        and     eax, 0f3ffh             ; set rounding mode to nearest
        mov     [esp+PATCH_CW], eax

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?