fp.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,429 行 · 第 1/3 页
C
1,429 行
/****************************************************************************
*
* 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!
*
****************************************************************************/
/* This module contains floating point functions that conform to the Java 1.3
* standard. This standard is close to the IEEE754 standard but there are
* some differences.
*/
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include "mp.h"
#include "fp.h"
#define FALSE 0
#define TRUE 1
#define SET_CW_ROUND_TO_NEAREST \
"push 0000037FH" \
"fldcw dword ptr [esp]" \
"add esp,4"
#define SET_CW_ROUND_TO_ZERO \
"push 00000F7FH" \
"fldcw dword ptr [esp]" \
"add esp,4"
void c_dadd( void *dst, void *src1, void *src2 );
void c_dsub( void *dst, void *src1, void *src2 );
#ifndef C_IMPL
void _dadd( void *, void *, void * );
#pragma aux _dadd = \
SET_CW_ROUND_TO_NEAREST \
"fld qword ptr [edx]" \
"fld qword ptr [ebx]" \
"fadd" \
"fstp qword ptr [eax]" \
parm caller [eax] [edx] [ebx] \
modify exact [];
void dadd( void *dst, void *src1, void *src2 ) {
uint64 f1, f2;
int e1, e2;
int diff;
parseDouble( *(double*)src1, &f1, &e1 );
parseDouble( *(double*)src2, &f2, &e2 );
diff = abs( (e1 - e2) );
if( diff > 11 && diff <= 53 ) {
/* the FPU will round twice during this operation so use the c version
* of this function instead */
c_dadd( dst, src1, src2 );
} else {
_dadd( dst, src1, src2 );
}
}
void _dsub( void *, void *, void * );
#pragma aux _dsub = \
SET_CW_ROUND_TO_NEAREST \
"fld qword ptr [edx]" \
"fsub qword ptr [ebx]" \
"fstp qword ptr [eax]" \
parm caller [eax] [edx] [ebx] \
modify exact [];
void dsub( void *dst, void *src1, void *src2 ) {
uint64 f1, f2;
int e1, e2;
int diff;
parseDouble( *(double*)src1, &f1, &e1 );
parseDouble( *(double*)src2, &f2, &e2 );
diff = abs( (e1 - e2) );
if( diff > 11 && diff <= 53 ) {
/* the FPU will round twice during this operation so use the c version
* of this function instead */
c_dsub( dst, src1, src2 );
} else {
_dsub( dst, src1, src2 );
}
}
void _dmul( void *, void *, void * );
#pragma aux _dmul = \
SET_CW_ROUND_TO_NEAREST \
"fld qword ptr [edx]" \
"fmul qword ptr [ebx]" \
"fstp qword ptr [eax]" \
parm caller [eax] [edx] [ebx] \
modify exact [];
void dmul( void *dst, void *src1, void *src2 ) {
_dmul( dst, src1, src2 );
}
void _ddiv( void *, void *, void * );
#pragma aux _ddiv = \
SET_CW_ROUND_TO_NEAREST \
"fld qword ptr [edx]" \
"fdiv qword ptr [ebx]" \
"fstp qword ptr [eax]" \
parm caller [eax] [edx] [ebx] \
modify exact [];
void ddiv( void *dst, void *src1, void *src2 ) {
_ddiv( dst, src1, src2 );
}
void _drem( void *, void *, void * );
#pragma aux _drem = \
SET_CW_ROUND_TO_NEAREST \
"fld qword ptr [ebx]" \
"fld qword ptr [edx]" \
"mov ecx,eax" \
"remloop:" \
"fprem" \
"fstsw ax" \
"test ax,0400H" \
"jne remloop" \
"mov eax,ecx" \
"fstp qword ptr [eax]" \
"fstp qword ptr [ebx]" \
parm caller [eax] [edx] [ebx] \
modify exact [ecx];
void drem( void *dst, void *src1, void *src2 ) {
_drem( dst, src1, src2 );
}
void _dneg( void *, void * );
#pragma aux _dneg = \
"fld qword ptr [edx]" \
"fchs" \
"fstp qword ptr [eax]" \
parm caller [eax] [edx] \
modify exact [];
void dneg( void *dst, void *src ) {
_dneg( dst, src );
}
void _fadd( void *, void *, void * );
#pragma aux _fadd = \
SET_CW_ROUND_TO_NEAREST \
"fld dword ptr [edx]" \
"fadd dword ptr [ebx]" \
"fstp dword ptr [eax]" \
parm caller [eax] [edx] [ebx] \
modify exact [];
void fadd( void *dst, void *src1, void *src2 ) {
_fadd( dst, src1, src2 );
}
void _fsub( void *, void *, void * );
#pragma aux _fsub = \
SET_CW_ROUND_TO_NEAREST \
"fld dword ptr [edx]" \
"fsub dword ptr [ebx]" \
"fstp dword ptr [eax]" \
parm caller [eax] [edx] [ebx] \
modify exact [];
void fsub( void *dst, void *src1, void *src2 ) {
_fsub( dst, src1, src2 );
}
void _fmul( void *, void *, void * );
#pragma aux _fmul = \
SET_CW_ROUND_TO_NEAREST \
"fld dword ptr [edx]" \
"fld dword ptr [ebx]" \
"fmul" \
"fstp dword ptr [eax]" \
parm caller [eax] [edx] [ebx] \
modify exact [];
void fmul( void *dst, void *src1, void *src2 ) {
_fmul( dst, src1, src2 );
}
void _fdiv( void *, void *, void * );
#pragma aux _fdiv = \
SET_CW_ROUND_TO_NEAREST \
"fld dword ptr [edx]" \
"fld dword ptr [ebx]" \
"fdiv" \
"fstp dword ptr [eax]" \
parm caller [eax] [edx] [ebx] \
modify exact [];
void fdiv( void *dst, void *src1, void *src2 ) {
_fdiv( dst, src1, src2 );
}
void _frem( void *, void *, void * );
#pragma aux _frem = \
SET_CW_ROUND_TO_NEAREST \
"fld dword ptr [ebx]" \
"fld dword ptr [edx]" \
"mov ecx,eax" \
"remloop:" \
"fprem" \
"fstsw ax" \
"test ax,0400H" \
"jne remloop" \
"mov eax,ecx" \
"fstp dword ptr [eax]" \
"fstp dword ptr [ebx]" \
parm caller [eax] [edx] [ebx] \
modify exact [ecx];
void frem( void *dst, void *src1, void *src2 ) {
_frem( dst, src1, src2 );
}
void _fneg( void *, void * );
#pragma aux _fneg = \
"fld dword ptr [edx]" \
"fchs" \
"fstp dword ptr [eax]" \
parm caller [eax] [edx] \
modify exact [];
void fneg( void *dst, void *src ) {
_fneg( dst, src );
}
void _eadd( void *, void *, void * );
#pragma aux _eadd = \
SET_CW_ROUND_TO_NEAREST \
"fld tbyte ptr [edx]" \
"fld tbyte ptr [ebx]" \
"fadd" \
"fstp tbyte ptr [eax]" \
parm caller [eax] [edx] [ebx] \
modify exact [];
void eadd( void *dst, void *src1, void *src2 ) {
_eadd( dst, src1, src2 );
}
void _esub( void *, void *, void * );
#pragma aux _esub = \
SET_CW_ROUND_TO_NEAREST \
"fld tbyte ptr [edx]" \
"fld tbyte ptr [edx]" \
"fsub" \
"fstp tbyte ptr [eax]" \
parm caller [eax] [edx] [ebx] \
modify exact [];
void esub( void *dst, void *src1, void *src2 ) {
_esub( dst, src1, src2 );
}
void _emul( void *, void *, void * );
#pragma aux _emul = \
SET_CW_ROUND_TO_NEAREST \
"finit" \
"fld tbyte ptr [edx]" \
"fld tbyte ptr [ebx]" \
"fmul" \
"fstp tbyte ptr [eax]" \
parm caller [eax] [edx] [ebx] \
modify exact [];
void emul( void *dst, void *src1, void *src2 ) {
_emul( dst, src1, src2 );
}
void _ediv( void *, void *, void * );
#pragma aux _ediv = \
SET_CW_ROUND_TO_NEAREST \
"fld tbyte ptr [edx]" \
"fld tbyte ptr [ebx]" \
"fdiv" \
"fstp tbyte ptr [eax]" \
parm caller [eax] [edx] [ebx] \
modify exact [];
void ediv( void *dst, void *src1, void *src2 ) {
_ediv( dst, src1, src2 );
}
void _erem( void *, void *, void * );
#pragma aux _erem = \
SET_CW_ROUND_TO_NEAREST \
"fld tbyte ptr [ebx]" \
"fld tbyte ptr [edx]" \
"mov ecx,eax" \
"remloop:" \
"fprem" \
"fstsw ax" \
"test ax,0400H" \
"jne remloop" \
"mov eax,ecx" \
"fstp tbyte ptr [eax]" \
"fstp tbyte ptr [ebx]" \
parm caller [eax] [edx] [ebx] \
modify exact [ecx];
void erem( void *dst, void *src1, void *src2 ) {
_erem( dst, src1, src2 );
}
void _eneg( void *, void * );
#pragma aux _eneg = \
"fld tbyte ptr [edx]" \
"fchs" \
"fstp tbyte ptr [eax]" \
parm caller [eax] [edx] \
modify exact [];
void eneg( void *dst, void *src ) {
_eneg( dst, src );
}
/****** conversion functions **********/
void _f2d( void *, void * );
#pragma aux _f2d = \
SET_CW_ROUND_TO_NEAREST \
"fld dword ptr [edx]" \
"fstp qword ptr [eax]" \
parm caller [eax] [edx] \
modify exact [ebx];
void f2d( void *dst, void *src ) {
_f2d( dst, src );
}
void _d2f( void *, void * );
#pragma aux _d2f = \
SET_CW_ROUND_TO_NEAREST \
"fld qword ptr [edx]" \
"fstp dword ptr [eax]" \
parm caller [eax] [edx] \
modify exact [ebx];
void d2f( void *dst, void *src ) {
_d2f( dst, src );
}
void _e2d( void *, void * );
#pragma aux _e2d = \
SET_CW_ROUND_TO_NEAREST \
"fld tbyte ptr [edx]" \
"fstp qword ptr [eax]" \
parm caller [eax] [edx] \
modify exact [];
void e2d( void *dst, void *src ) {
_e2d( dst, src );
}
void _d2e( void *, void * );
#pragma aux _d2e = \
SET_CW_ROUND_TO_NEAREST \
"fld qword ptr [edx]" \
"fstp tbyte ptr [eax]" \
parm caller [eax] [edx] \
modify exact [];
void d2e( void *dst, void *src ) {
_d2e( dst, src );
}
void _e2f( void *, void * );
#pragma aux _e2f = \
SET_CW_ROUND_TO_NEAREST \
"fld tbyte ptr [edx]" \
"fstp dword ptr [eax]" \
parm caller [eax] [edx] \
modify exact [];
void e2f( void *dst, void *src ) {
_e2f( dst, src );
}
void _f2e( void *, void * );
#pragma aux _f2e = \
SET_CW_ROUND_TO_NEAREST \
"fld dword ptr [edx]" \
"fstp tbyte ptr [eax]" \
parm caller [eax] [edx] \
modify exact [];
void f2e( void *dst, void *src ) {
_f2e( dst, src );
}
void _f2i( void *, void * );
#pragma aux _f2i = \
SET_CW_ROUND_TO_ZERO \
"fld dword ptr [edx]" \
"mov ebx,eax" \
"push 07FFFFFFFH" \
"fild dword ptr [esp]" \
"add esp,4" \
"fcomp" \
"fstsw ax" \
"test ax,0400H" \
"jnz nan" \
"test ax,0100H" \
"jnz large" \
"mov eax,ebx" \
"fist dword ptr [eax]" \
"jmp done" \
"nan:" \
"mov eax,ebx" \
"mov dword ptr [eax],0000H" \
"jmp done" \
"large:" \
"mov eax,ebx" \
"mov dword ptr [eax],7FFFFFFFH" \
"done:" \
"fstp dword ptr [edx]" \
parm caller [eax] [edx] \
modify exact [];
void f2i( void *dst, void *src ) {
_f2i( dst, src );
}
void _i2f( void *, void * );
#pragma aux _i2f = \
SET_CW_ROUND_TO_NEAREST \
"fild dword ptr [edx]" \
"fstp dword ptr [eax]" \
parm caller [eax] [edx] \
modify exact [];
void i2f( void *dst, void *src ) {
_i2f( dst, src );
}
void _f2l( void *, void * );
#pragma aux _f2l = \
SET_CW_ROUND_TO_ZERO \
"fld dword ptr [edx]" \
"mov ebx,eax" \
"push 07FFFFFFFH" \
"push 0FFFFFFFFH" \
"fild qword ptr [esp]" \
"add esp,8" \
"fcomp" \
"fstsw ax" \
"test ax,0400H" \
"jnz nan" \
"test ax,0100H" \
"jnz large" \
"mov eax,ebx" \
"fistp qword ptr [eax]" \
"jmp done" \
"nan:" \
"mov eax,ebx" \
"mov dword ptr [eax],0000H" \
"mov dword ptr +4[eax],0000H" \
"fstp dword ptr [edx]" \
"jmp done" \
"large:" \
"mov eax,ebx" \
"mov dword ptr [eax],0FFFFFFFFH" \
"mov dword ptr +4[eax],07FFFFFFFH" \
"fstp dword ptr [edx]" \
"done:" \
parm caller [eax] [edx] \
modify exact [];
void f2l( void *dst, void *src ) {
_f2l( dst, src );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?