xfloat.h

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C头文件 代码 · 共 545 行 · 第 1/2 页

H
545
字号
/****************************************************************************
*
*                            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:  C/C++ run-time library floating-point definitions.
*
****************************************************************************/


#ifndef _XFLOAT_H_INCLUDED
#define _XFLOAT_H_INCLUDED

#include <stddef.h>     // for wchar_t
#include <float.h>      // for LDBL_DIG

#ifndef _WMRTLINK
    #define _WMRTLINK   // This SUCKS!
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if (defined(__386__) || defined(M_I86)) && defined(__WATCOMC__)
 #define _LONG_DOUBLE_
#endif

typedef struct {                // This layout matches Intel 8087
  #ifdef _LONG_DOUBLE_
    unsigned long low_word;     // - low word of fraction
    unsigned long high_word;    // - high word of fraction
    unsigned short exponent;    // - exponent and sign
  #else                         // use this for all other 32-bit RISC
    union {
        double          value;  // - double value
        unsigned long   word[2];// - so we can access bits
    };
  #endif
} long_double;

typedef struct {                // Layout of IEEE 754 double (FD)
    union {
        double          value;  // - double value
        unsigned long   word[2];// - so we can access bits
    };
} float_double;

typedef struct {                // Layout of IEEE 754 single (FS)
    union {
        float           value;  // - double value
        unsigned long   word;   // - so we can access bits
    };
} float_single;

/* NB: The following values *must* match FP_ macros in math.h! */
enum    ld_classification {
    __ZERO      = 0,
    __DENORMAL  = 1,
    __NONZERO   = 2,
    __NAN       = 3,
    __INFINITY  = 4
};

enum    ldcvt_flags {
    E_FMT       = 0x0001,       // 'E' format
    F_FMT       = 0x0002,       // 'F' format
    G_FMT       = 0x0004,       // 'G' format
    F_CVT       = 0x0008,       // __cvt routine format rules
    F_DOT       = 0x0010,       // always put '.' in result
    LONG_DOUBLE = 0x0020,       // number is true long double
    NO_TRUNC    = 0x0040,       // always provide ndigits in buffer
    IN_CAPS     = 0x0080,       // 'inf'/'nan' is uppercased
};

typedef struct cvt_info {
      int       ndigits;        // INPUT: number of digits
      int       scale;          // INPUT: FORTRAN scale factor
      int       flags;          // INPUT: flags (see ldcvt_flags)
      int       expchar;        // INPUT: exponent character to use
      int       expwidth;       // INPUT/OUTPUT: number of exponent digits
      int       sign;           // OUTPUT: 0 => +ve; otherwise -ve
      int       decimal_place;  // OUTPUT: position of '.'
      int       n1;             // OUTPUT: number of leading characters
      int       nz1;            // OUTPUT: followed by this many '0's
      int       n2;             // OUTPUT: followed by these characters
      int       nz2;            // OUTPUT: followed by this many '0's
} CVT_INFO;

_WMRTLINK extern void __LDcvt(
                         long_double *pld,      // pointer to long_double
                         CVT_INFO  *cvt,        // conversion info
                         char      *buf );      // buffer
#if defined( __WATCOMC__ )
_WMRTLINK extern int __Strtold(
                        const char *bufptr,
                        long_double *pld,
                        char **endptr );
#endif
extern  int     __LDClass( long_double * );
extern  void    __ZBuf2LD(char _WCNEAR *, long_double _WCNEAR *);
extern  void    _LDScale10x(long_double _WCNEAR *,int);
_WMRTLINK extern void  __cnvd2ld( double _WCNEAR *src, long_double _WCNEAR *dst );
_WMRTLINK extern void  __cnvs2d( char *buf, double *value );
_WMRTLINK extern int   __cnvd2f( double *src, float *tgt );
#ifdef _LONG_DOUBLE_
extern  void    __iLDFD(long_double _WCNEAR *, double _WCNEAR *);
extern  void    __iLDFS(long_double _WCNEAR *, float _WCNEAR *);
extern  void    __iFDLD(double _WCNEAR *,long_double _WCNEAR *);
extern  void    __iFSLD(float _WCNEAR *,long_double _WCNEAR *);
extern  long    __LDI4(long_double _WCNEAR *);
extern  void    __I4LD(long,long_double _WCNEAR *);
extern  void    __U4LD(unsigned long,long_double _WCNEAR *);
//The 64bit types change depending on what's being built.
//(u)int64* (un)signed_64* don't seem suitable, and we use void* instead.
extern  void    __I8LD(void _WCNEAR *, long_double _WCNEAR *);
extern  void    __U8LD(void _WCNEAR *, long_double _WCNEAR *);
extern void __FLDA(long_double _WCNEAR *,long_double _WCNEAR *,long_double _WCNEAR *);
extern void __FLDS(long_double _WCNEAR *,long_double _WCNEAR *,long_double _WCNEAR *);
extern void __FLDM(long_double _WCNEAR *,long_double _WCNEAR *,long_double _WCNEAR *);
extern void __FLDD(long_double _WCNEAR *,long_double _WCNEAR *,long_double _WCNEAR *);
extern int  __FLDC(long_double _WCNEAR *,long_double _WCNEAR *);
#endif

#ifdef __WATCOMC__
#if defined(__386__)
 #pragma aux    __ZBuf2LD       "*"  parm caller [eax] [edx];
 #if defined(__FPI__)
  extern unsigned __Get87CW(void);
  extern void __Set87CW(unsigned short);
  #pragma aux   __Get87CW = \
                "push 0"\
        float   "fstcw [esp]"\
        float   "fwait"\
                "pop eax"\
                value [eax];
  #pragma aux   __Set87CW = \
                "push eax"\
        float   "fldcw [esp]"\
                "pop eax"\
                parm caller [eax];
  #pragma aux   __FLDA = \
        float   "fld tbyte ptr [eax]"\
        float   "fld tbyte ptr [edx]"\
        float   "fadd"\
        float   "fstp tbyte ptr [ebx]"\
                parm caller [eax] [edx] [ebx];
  #pragma aux   __FLDS = \
        float   "fld tbyte ptr [eax]"\
        float   "fld tbyte ptr [edx]"\
        float   "fsub"\
        float   "fstp tbyte ptr [ebx]"\
                parm caller [eax] [edx] [ebx];
  #pragma aux   __FLDM = \
        float   "fld tbyte ptr [eax]"\
        float   "fld tbyte ptr [edx]"\
        float   "fmul"\
        float   "fstp tbyte ptr [ebx]"\
                parm caller [eax] [edx] [ebx];
  #pragma aux   __FLDD = \
        float   "fld tbyte ptr [eax]"\
        float   "fld tbyte ptr [edx]"\
        float   "fdiv"\
        float   "fstp tbyte ptr [ebx]"\
                parm caller [eax] [edx] [ebx];
  #pragma aux   __FLDC = \
                /* ST(1) */\
        float   "fld tbyte ptr [edx]"\
                /* ST(0) */\
        float   "fld tbyte ptr [eax]"\
                /* compare ST(0) with ST(1) */\
        float   "fcompp"\
        float   "fstsw  ax"\
                "sahf"\
                "sbb  edx,edx"\
                "shl  edx,1"\
                "shl  ah,2"\
                "cmc"\
                "adc  edx,0"\
                /* edx will be -1,0,+1 if [eax] <, ==, > [edx] */\
                parm caller [eax] [edx] value [edx];
  #pragma aux   __LDI4 = \
        float   "fld tbyte ptr [eax]"\
                "push  eax"\
                "push  eax"\
        float   "fstcw [esp]"\
        float   "fwait"\
                "pop eax"\
                "push eax"\
                "or ah,0x0c"\
                "push eax"\
        float   "fldcw [esp]"\
                "pop eax"\
        float   "fistp dword ptr 4[esp]"\
        float   "fldcw [esp]"\
                "pop   eax"\
                "pop   eax"\
                parm caller [eax] value [eax];
  #pragma aux   __I4LD = \
                "push  eax"\
        float   "fild  dword ptr [esp]"\
                "pop   eax"\
        float   "fstp tbyte ptr [edx]"\
                parm caller [eax] [edx];
  #pragma aux   __U4LD = \
                "push  0"\
                "push  eax"\
        float   "fild  qword ptr [esp]"\
                "pop   eax"\
                "pop   eax"\
        float   "fstp tbyte ptr [edx]"\
                parm caller [eax] [edx];
  #pragma aux   __I8LD = \
        float   "fild  qword ptr [eax]"\
        float   "fstp  tbyte ptr [edx]"\
                parm caller [eax] [edx];
  #pragma aux   __U8LD = \
                "push  [eax]"\
                "push  [eax+4]"\
                "and   [esp+4],0x7fffffff"\
        float   "fild  qword ptr [esp]"\
                "push  [eax+4]"\
                "and   [esp],0x80000000"\
                "push  0"\
        float   "fild  qword ptr [esp]"\
        float   "fchs"\
        float   "faddp st(1),st"\
        float   "fstp  qword ptr [edx]"\
                "lea   esp,[esp+16]"\
                parm caller [eax] [edx];
  #pragma aux   __iFDLD = \
        float   "fld  qword ptr [eax]"\
        float   "fstp tbyte ptr [edx]"\
                parm caller [eax] [edx];
  #pragma aux   __iFSLD = \
        float   "fld  dword ptr [eax]"\
        float   "fstp tbyte ptr [edx]"\
                parm caller [eax] [edx];
  #pragma aux   __iLDFD = \
        float   "fld  tbyte ptr [eax]"\
        float   "fstp qword ptr [edx]"\
                parm caller [eax] [edx];
  #pragma aux   __iLDFS = \
        float   "fld  tbyte ptr [eax]"\
        float   "fstp dword ptr [edx]"\
                parm caller [eax] [edx];
 #else  // floating-point calls
  #pragma aux   __FLDA  "*"  parm caller [eax] [edx] [ebx];
  #pragma aux   __FLDS  "*"  parm caller [eax] [edx] [ebx];
  #pragma aux   __FLDM  "*"  parm caller [eax] [edx] [ebx];
  #pragma aux   __FLDD  "*"  parm caller [eax] [edx] [ebx];
  #pragma aux   __LDI4  "*"  parm caller [eax] value [eax];

⌨️ 快捷键说明

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