Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
548 | serge | 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: C/C++ run-time library floating-point definitions. |
||
28 | * |
||
29 | ****************************************************************************/ |
||
30 | |||
31 | |||
32 | #ifndef _XFLOAT_H_INCLUDED |
||
33 | #define _XFLOAT_H_INCLUDED |
||
34 | |||
35 | #include |
||
36 | #include |
||
37 | |||
38 | #ifdef __cplusplus |
||
39 | extern "C" { |
||
40 | #endif |
||
41 | |||
42 | #if (defined(__386__) || defined(M_I86)) && defined(__WATCOMC__) |
||
43 | #define _LONG_DOUBLE_ |
||
44 | #endif |
||
45 | |||
46 | typedef struct { // This layout matches Intel 8087 |
||
47 | #ifdef _LONG_DOUBLE_ |
||
48 | unsigned long low_word; // - low word of fraction |
||
49 | unsigned long high_word; // - high word of fraction |
||
50 | unsigned short exponent; // - exponent and sign |
||
51 | #else // use this for all other 32-bit RISC |
||
52 | union { |
||
53 | double value; // - double value |
||
54 | unsigned long word[2];// - so we can access bits |
||
55 | }; |
||
56 | #endif |
||
57 | } long_double; |
||
58 | |||
59 | typedef struct { // Layout of IEEE 754 double (FD) |
||
60 | union { |
||
61 | double value; // - double value |
||
62 | unsigned long word[2];// - so we can access bits |
||
63 | }; |
||
64 | } float_double; |
||
65 | |||
66 | typedef struct { // Layout of IEEE 754 single (FS) |
||
67 | union { |
||
68 | float value; // - double value |
||
69 | unsigned long word; // - so we can access bits |
||
70 | }; |
||
71 | } float_single; |
||
72 | |||
73 | /* NB: The following values *must* match FP_ macros in math.h! */ |
||
74 | enum ld_classification { |
||
75 | __ZERO = 0, |
||
76 | __DENORMAL = 1, |
||
77 | __NONZERO = 2, |
||
78 | __NAN = 3, |
||
79 | __INFINITY = 4 |
||
80 | }; |
||
81 | |||
82 | enum ldcvt_flags { |
||
83 | E_FMT = 0x0001, // 'E' format |
||
84 | F_FMT = 0x0002, // 'F' format |
||
85 | G_FMT = 0x0004, // 'G' format |
||
86 | F_CVT = 0x0008, // __cvt routine format rules |
||
87 | F_DOT = 0x0010, // always put '.' in result |
||
88 | LONG_DOUBLE = 0x0020, // number is true long double |
||
89 | NO_TRUNC = 0x0040, // always provide ndigits in buffer |
||
90 | IN_CAPS = 0x0080, // 'inf'/'nan' is uppercased |
||
91 | }; |
||
92 | |||
93 | typedef struct cvt_info { |
||
94 | int ndigits; // INPUT: number of digits |
||
95 | int scale; // INPUT: FORTRAN scale factor |
||
96 | int flags; // INPUT: flags (see ldcvt_flags) |
||
97 | int expchar; // INPUT: exponent character to use |
||
98 | int expwidth; // INPUT/OUTPUT: number of exponent digits |
||
99 | int sign; // OUTPUT: 0 => +ve; otherwise -ve |
||
100 | int decimal_place; // OUTPUT: position of '.' |
||
101 | int n1; // OUTPUT: number of leading characters |
||
102 | int nz1; // OUTPUT: followed by this many '0's |
||
103 | int n2; // OUTPUT: followed by these characters |
||
104 | int nz2; // OUTPUT: followed by this many '0's |
||
105 | } CVT_INFO; |
||
106 | |||
107 | _WMRTLINK extern void __LDcvt( |
||
108 | long_double *pld, // pointer to long_double |
||
109 | CVT_INFO *cvt, // conversion info |
||
110 | char *buf ); // buffer |
||
111 | #if defined( __WATCOMC__ ) |
||
112 | _WMRTLINK extern int __Strtold( |
||
113 | const char *bufptr, |
||
114 | long_double *pld, |
||
115 | char **endptr ); |
||
116 | #endif |
||
117 | extern int __LDClass( long_double * ); |
||
118 | extern void __ZBuf2LD(char _WCNEAR *, long_double _WCNEAR *); |
||
119 | extern void _LDScale10x(long_double _WCNEAR *,int); |
||
120 | _WMRTLINK extern void __cnvd2ld( double _WCNEAR *src, long_double _WCNEAR *dst ); |
||
121 | _WMRTLINK extern void __cnvs2d( char *buf, double *value ); |
||
122 | _WMRTLINK extern int __cnvd2f( double *src, float *tgt ); |
||
123 | #ifdef _LONG_DOUBLE_ |
||
124 | extern void __iLDFD(long_double _WCNEAR *, double _WCNEAR *); |
||
125 | extern void __iLDFS(long_double _WCNEAR *, float _WCNEAR *); |
||
126 | extern void __iFDLD(double _WCNEAR *,long_double _WCNEAR *); |
||
127 | extern void __iFSLD(float _WCNEAR *,long_double _WCNEAR *); |
||
128 | extern long __LDI4(long_double _WCNEAR *); |
||
129 | extern void __I4LD(long,long_double _WCNEAR *); |
||
130 | extern void __U4LD(unsigned long,long_double _WCNEAR *); |
||
131 | extern void __FLDA(long_double _WCNEAR *,long_double _WCNEAR *,long_double _WCNEAR *); |
||
132 | extern void __FLDS(long_double _WCNEAR *,long_double _WCNEAR *,long_double _WCNEAR *); |
||
133 | extern void __FLDM(long_double _WCNEAR *,long_double _WCNEAR *,long_double _WCNEAR *); |
||
134 | extern void __FLDD(long_double _WCNEAR *,long_double _WCNEAR *,long_double _WCNEAR *); |
||
135 | extern int __FLDC(long_double _WCNEAR *,long_double _WCNEAR *); |
||
136 | #endif |
||
137 | |||
138 | #ifdef __WATCOMC__ |
||
139 | #if defined(__386__) |
||
140 | #pragma aux __ZBuf2LD "*" parm caller [eax] [edx]; |
||
141 | #if defined(__FPI__) |
||
142 | extern unsigned __Get87CW(void); |
||
143 | extern void __Set87CW(unsigned short); |
||
144 | #pragma aux __Get87CW = \ |
||
145 | "push 0"\ |
||
146 | float "fstcw [esp]"\ |
||
147 | float "fwait"\ |
||
148 | "pop eax"\ |
||
149 | value [eax]; |
||
150 | #pragma aux __Set87CW = \ |
||
151 | "push eax"\ |
||
152 | float "fldcw [esp]"\ |
||
153 | "pop eax"\ |
||
154 | parm caller [eax]; |
||
155 | #pragma aux __FLDA = \ |
||
156 | float "fld tbyte ptr [eax]"\ |
||
157 | float "fld tbyte ptr [edx]"\ |
||
158 | float "fadd"\ |
||
159 | float "fstp tbyte ptr [ebx]"\ |
||
160 | parm caller [eax] [edx] [ebx]; |
||
161 | #pragma aux __FLDS = \ |
||
162 | float "fld tbyte ptr [eax]"\ |
||
163 | float "fld tbyte ptr [edx]"\ |
||
164 | float "fsub"\ |
||
165 | float "fstp tbyte ptr [ebx]"\ |
||
166 | parm caller [eax] [edx] [ebx]; |
||
167 | #pragma aux __FLDM = \ |
||
168 | float "fld tbyte ptr [eax]"\ |
||
169 | float "fld tbyte ptr [edx]"\ |
||
170 | float "fmul"\ |
||
171 | float "fstp tbyte ptr [ebx]"\ |
||
172 | parm caller [eax] [edx] [ebx]; |
||
173 | #pragma aux __FLDD = \ |
||
174 | float "fld tbyte ptr [eax]"\ |
||
175 | float "fld tbyte ptr [edx]"\ |
||
176 | float "fdiv"\ |
||
177 | float "fstp tbyte ptr [ebx]"\ |
||
178 | parm caller [eax] [edx] [ebx]; |
||
179 | #pragma aux __FLDC = \ |
||
180 | /* ST(1) */\ |
||
181 | float "fld tbyte ptr [edx]"\ |
||
182 | /* ST(0) */\ |
||
183 | float "fld tbyte ptr [eax]"\ |
||
184 | /* compare ST(0) with ST(1) */\ |
||
185 | float "fcompp"\ |
||
186 | float "fstsw ax"\ |
||
187 | "sahf"\ |
||
188 | "sbb edx,edx"\ |
||
189 | "shl edx,1"\ |
||
190 | "shl ah,2"\ |
||
191 | "cmc"\ |
||
192 | "adc edx,0"\ |
||
193 | /* edx will be -1,0,+1 if [eax] <, ==, > [edx] */\ |
||
194 | parm caller [eax] [edx] value [edx]; |
||
195 | #pragma aux __LDI4 = \ |
||
196 | float "fld tbyte ptr [eax]"\ |
||
197 | "push eax"\ |
||
198 | "push eax"\ |
||
199 | float "fstcw [esp]"\ |
||
200 | float "fwait"\ |
||
201 | "pop eax"\ |
||
202 | "push eax"\ |
||
203 | "or ah,0x0c"\ |
||
204 | "push eax"\ |
||
205 | float "fldcw [esp]"\ |
||
206 | "pop eax"\ |
||
207 | float "fistp dword ptr 4[esp]"\ |
||
208 | float "fldcw [esp]"\ |
||
209 | "pop eax"\ |
||
210 | "pop eax"\ |
||
211 | parm caller [eax] value [eax]; |
||
212 | #pragma aux __I4LD = \ |
||
213 | "push eax"\ |
||
214 | float "fild dword ptr [esp]"\ |
||
215 | "pop eax"\ |
||
216 | float "fstp tbyte ptr [edx]"\ |
||
217 | parm caller [eax] [edx]; |
||
218 | #pragma aux __U4LD = \ |
||
219 | "push 0"\ |
||
220 | "push eax"\ |
||
221 | float "fild qword ptr [esp]"\ |
||
222 | "pop eax"\ |
||
223 | "pop eax"\ |
||
224 | float "fstp tbyte ptr [edx]"\ |
||
225 | parm caller [eax] [edx]; |
||
226 | #pragma aux __iFDLD = \ |
||
227 | float "fld qword ptr [eax]"\ |
||
228 | float "fstp tbyte ptr [edx]"\ |
||
229 | parm caller [eax] [edx]; |
||
230 | #pragma aux __iFSLD = \ |
||
231 | float "fld dword ptr [eax]"\ |
||
232 | float "fstp tbyte ptr [edx]"\ |
||
233 | parm caller [eax] [edx]; |
||
234 | #pragma aux __iLDFD = \ |
||
235 | float "fld tbyte ptr [eax]"\ |
||
236 | float "fstp qword ptr [edx]"\ |
||
237 | parm caller [eax] [edx]; |
||
238 | #pragma aux __iLDFS = \ |
||
239 | float "fld tbyte ptr [eax]"\ |
||
240 | float "fstp dword ptr [edx]"\ |
||
241 | parm caller [eax] [edx]; |
||
242 | #else // floating-point calls |
||
243 | #pragma aux __FLDA "*" parm caller [eax] [edx] [ebx]; |
||
244 | #pragma aux __FLDS "*" parm caller [eax] [edx] [ebx]; |
||
245 | #pragma aux __FLDM "*" parm caller [eax] [edx] [ebx]; |
||
246 | #pragma aux __FLDD "*" parm caller [eax] [edx] [ebx]; |
||
247 | #pragma aux __LDI4 "*" parm caller [eax] value [eax]; |
||
248 | #pragma aux __I4LD "*" parm caller [eax] [edx]; |
||
249 | #pragma aux __U4LD "*" parm caller [eax] [edx]; |
||
250 | #pragma aux __iFDLD "*" parm caller [eax] [edx]; |
||
251 | #pragma aux __iFSLD "*" parm caller [eax] [edx]; |
||
252 | #pragma aux __iLDFD "*" parm caller [eax] [edx]; |
||
253 | #pragma aux __iLDFS "*" parm caller [eax] [edx]; |
||
254 | #pragma aux __FLDC "*" parm caller [eax] [edx] value [eax]; |
||
255 | #endif |
||
256 | #elif defined(M_I86) // 16-bit pragmas |
||
257 | #pragma aux __ZBuf2LD "*" parm caller [ax] [dx]; |
||
258 | #if defined(__FPI__) |
||
259 | extern unsigned __Get87CW(void); |
||
260 | extern void __Set87CW(unsigned short); |
||
261 | #pragma aux __Get87CW = \ |
||
262 | "push ax"\ |
||
263 | "push bp"\ |
||
264 | "mov bp,sp"\ |
||
265 | float "fstcw 2[bp]"\ |
||
266 | float "fwait"\ |
||
267 | "pop bp"\ |
||
268 | "pop ax"\ |
||
269 | value [ax]; |
||
270 | #pragma aux __Set87CW = \ |
||
271 | "push ax"\ |
||
272 | "push bp"\ |
||
273 | "mov bp,sp"\ |
||
274 | float "fldcw 2[bp]"\ |
||
275 | "pop bp"\ |
||
276 | "pop ax"\ |
||
277 | parm caller [ax]; |
||
278 | #pragma aux __FLDA = \ |
||
279 | "push bp"\ |
||
280 | "mov bp,ax"\ |
||
281 | float "fld tbyte ptr [bp]"\ |
||
282 | "mov bp,dx"\ |
||
283 | float "fld tbyte ptr [bp]"\ |
||
284 | float "fadd"\ |
||
285 | "mov bp,bx"\ |
||
286 | float "fstp tbyte ptr [bp]"\ |
||
287 | "pop bp"\ |
||
288 | parm caller [ax] [dx] [bx]; |
||
289 | #pragma aux __FLDS = \ |
||
290 | "push bp"\ |
||
291 | "mov bp,ax"\ |
||
292 | float "fld tbyte ptr [bp]"\ |
||
293 | "mov bp,dx"\ |
||
294 | float "fld tbyte ptr [bp]"\ |
||
295 | float "fsub"\ |
||
296 | "mov bp,bx"\ |
||
297 | float "fstp tbyte ptr [bp]"\ |
||
298 | "pop bp"\ |
||
299 | parm caller [ax] [dx] [bx]; |
||
300 | #pragma aux __FLDM = \ |
||
301 | "push bp"\ |
||
302 | "mov bp,ax"\ |
||
303 | float "fld tbyte ptr [bp]"\ |
||
304 | "mov bp,dx"\ |
||
305 | float "fld tbyte ptr [bp]"\ |
||
306 | float "fmul"\ |
||
307 | "mov bp,bx"\ |
||
308 | float "fstp tbyte ptr [bp]"\ |
||
309 | "pop bp"\ |
||
310 | parm caller [ax] [dx] [bx]; |
||
311 | #pragma aux __FLDD = \ |
||
312 | "push bp"\ |
||
313 | "mov bp,ax"\ |
||
314 | float "fld tbyte ptr [bp]"\ |
||
315 | "mov bp,dx"\ |
||
316 | float "fld tbyte ptr [bp]"\ |
||
317 | float "fdiv"\ |
||
318 | "mov bp,bx"\ |
||
319 | float "fstp tbyte ptr [bp]"\ |
||
320 | "pop bp"\ |
||
321 | parm caller [ax] [dx] [bx]; |
||
322 | #pragma aux __FLDC = \ |
||
323 | "push bp"\ |
||
324 | "mov bp,dx"\ |
||
325 | /* ST(1) */\ |
||
326 | float "fld tbyte ptr [bp]"\ |
||
327 | "mov bp,ax"\ |
||
328 | /* ST(0) */\ |
||
329 | float "fld tbyte ptr [bp]"\ |
||
330 | /* compare ST(0) with ST(1) */\ |
||
331 | float "fcompp"\ |
||
332 | "push ax"\ |
||
333 | "mov bp,sp"\ |
||
334 | float "fstsw 0[bp]"\ |
||
335 | float "fwait"\ |
||
336 | "pop ax"\ |
||
337 | "sahf"\ |
||
338 | "sbb dx,dx"\ |
||
339 | "shl dx,1"\ |
||
340 | "shl ah,1"\ |
||
341 | "shl ah,1"\ |
||
342 | "cmc"\ |
||
343 | "adc dx,0"\ |
||
344 | "pop bp"\ |
||
345 | parm caller [ax] [dx] value [dx]; |
||
346 | #pragma aux __LDI4 = \ |
||
347 | "push bp"\ |
||
348 | "mov bp,ax"\ |
||
349 | float "fld tbyte ptr [bp]"\ |
||
350 | "push dx"\ |
||
351 | "push ax"\ |
||
352 | "push ax"\ |
||
353 | "mov bp,sp"\ |
||
354 | float "fstcw [bp]"\ |
||
355 | float "fwait"\ |
||
356 | "pop ax"\ |
||
357 | "push ax"\ |
||
358 | "or ah,0x0c"\ |
||
359 | "mov 2[bp],ax"\ |
||
360 | float "fldcw 2[bp]"\ |
||
361 | float "fistp dword ptr 2[bp]"\ |
||
362 | float "fldcw [bp]"\ |
||
363 | "pop ax"\ |
||
364 | "pop ax"\ |
||
365 | "pop dx"\ |
||
366 | "pop bp"\ |
||
367 | parm caller [ax] value [dx ax]; |
||
368 | #pragma aux __I4LD = \ |
||
369 | "push bp"\ |
||
370 | "push dx"\ |
||
371 | "push ax"\ |
||
372 | "mov bp,sp"\ |
||
373 | float "fild dword ptr [bp]"\ |
||
374 | "pop ax"\ |
||
375 | "pop dx"\ |
||
376 | "mov bp,bx"\ |
||
377 | float "fstp tbyte ptr [bp]"\ |
||
378 | "pop bp"\ |
||
379 | parm caller [dx ax] [bx]; |
||
380 | #pragma aux __U4LD = \ |
||
381 | "push bp"\ |
||
382 | "push ax"\ |
||
383 | "push ax"\ |
||
384 | "push dx"\ |
||
385 | "push ax"\ |
||
386 | "mov bp,sp"\ |
||
387 | "sub ax,ax"\ |
||
388 | "mov 4[bp],ax"\ |
||
389 | "mov 6[bp],ax"\ |
||
390 | float "fild qword ptr 2[bp]"\ |
||
391 | "pop ax"\ |
||
392 | "pop dx"\ |
||
393 | "pop ax"\ |
||
394 | "pop ax"\ |
||
395 | "mov bp,bx"\ |
||
396 | float "fstp tbyte ptr [bp]"\ |
||
397 | "pop bp"\ |
||
398 | parm caller [dx ax] [bx]; |
||
399 | #pragma aux __iFDLD = \ |
||
400 | "push bp"\ |
||
401 | "mov bp,ax"\ |
||
402 | float "fld qword ptr [bp]"\ |
||
403 | "mov bp,dx"\ |
||
404 | float "fstp tbyte ptr [bp]"\ |
||
405 | "pop bp"\ |
||
406 | parm caller [ax] [dx]; |
||
407 | #pragma aux __iFSLD = \ |
||
408 | "push bp"\ |
||
409 | "mov bp,ax"\ |
||
410 | float "fld dword ptr [bp]"\ |
||
411 | "mov bp,dx"\ |
||
412 | float "fstp tbyte ptr [bp]"\ |
||
413 | "pop bp"\ |
||
414 | parm caller [ax] [dx]; |
||
415 | #pragma aux __iLDFD = \ |
||
416 | "push bp"\ |
||
417 | "mov bp,ax"\ |
||
418 | float "fld tbyte ptr [bp]"\ |
||
419 | "mov bp,dx"\ |
||
420 | float "fstp qword ptr [bp]"\ |
||
421 | "pop bp"\ |
||
422 | parm caller [ax] [dx]; |
||
423 | #pragma aux __iLDFS = \ |
||
424 | "push bp"\ |
||
425 | "mov bp,ax"\ |
||
426 | float "fld tbyte ptr [bp]"\ |
||
427 | "mov bp,dx"\ |
||
428 | float "fstp dword ptr [bp]"\ |
||
429 | "pop bp"\ |
||
430 | parm caller [ax] [dx]; |
||
431 | #else // floating-point calls |
||
432 | #pragma aux __FLDA "*" parm caller [ax] [dx] [bx]; |
||
433 | #pragma aux __FLDS "*" parm caller [ax] [dx] [bx]; |
||
434 | #pragma aux __FLDM "*" parm caller [ax] [dx] [bx]; |
||
435 | #pragma aux __FLDD "*" parm caller [ax] [dx] [bx]; |
||
436 | #pragma aux __LDI4 "*" parm caller [ax] value [dx ax]; |
||
437 | #pragma aux __I4LD "*" parm caller [dx ax] [bx]; |
||
438 | #pragma aux __U4LD "*" parm caller [dx ax] [bx]; |
||
439 | #pragma aux __iFDLD "*" parm caller [ax] [dx]; |
||
440 | #pragma aux __iFSLD "*" parm caller [ax] [dx]; |
||
441 | #pragma aux __iLDFD "*" parm caller [ax] [dx]; |
||
442 | #pragma aux __iLDFS "*" parm caller [ax] [dx]; |
||
443 | #pragma aux __FLDC "*" parm caller [ax] [dx] value [ax]; |
||
444 | #endif |
||
445 | #endif |
||
446 | #endif |
||
447 | |||
448 | #ifdef _LONG_DOUBLE_ |
||
449 | // macros to allow old source code names to still work |
||
450 | #define __FDLD __iFDLD |
||
451 | #define __FSLD __iFSLD |
||
452 | #define __LDFD __iLDFD |
||
453 | #define __LDFS __iLDFS |
||
454 | #endif |
||
455 | |||
456 | // define number of significant digits for long double numbers (80-bit) |
||
457 | // it will be defined in float.h as soon as OW support long double |
||
458 | // used in mathlib/c/ldcvt.c |
||
459 | |||
460 | #ifdef _LONG_DOUBLE_ |
||
461 | #if LDBL_DIG == 15 |
||
462 | #undef LDBL_DIG |
||
463 | #define LDBL_DIG 19 |
||
464 | #else |
||
465 | #error LDBL_DIG has changed from 15 |
||
466 | #endif |
||
467 | #endif |
||
468 | |||
469 | // floating point conversion buffer length definition |
||
470 | // used by various floating point conversion routines |
||
471 | // used in clib/startup/c/cvtbuf.c and lib_misc/h/thread.h |
||
472 | // it must be equal maximum FP precision ( LDBL_DIG ) |
||
473 | |||
474 | #define __FPCVT_BUFFERLEN 19 |
||
475 | |||
476 | #ifdef __cplusplus |
||
477 | }; |
||
478 | #endif |
||
479 | #endif,> |