~ubuntu-branches/debian/lenny/fpc/lenny

« back to all changes in this revision

Viewing changes to fpcsrc/rtl/inc/softfpu.pp

  • Committer: Bazaar Package Importer
  • Author(s): Mazen Neifer, Torsten Werner, Mazen Neifer
  • Date: 2008-05-17 17:12:11 UTC
  • mfrom: (3.1.9 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080517171211-9qi33xhd9evfa0kg
Tags: 2.2.0-dfsg1-9
[ Torsten Werner ]
* Add Mazen Neifer to Uploaders field.

[ Mazen Neifer ]
* Moved FPC sources into a version dependent directory from /usr/share/fpcsrc
  to /usr/share/fpcsrc/${FPCVERSION}. This allow installing more than on FPC
  release.
* Fixed far call issue in compiler preventing building huge binearies.
  (closes: #477743)
* Updated building dependencies, recomennded and suggested packages.
* Moved fppkg to fp-utils as it is just a helper tool and is not required by
  compiler.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
{*
 
2
===============================================================================
 
3
The original notice of the softfloat package is shown below. The conversion
 
4
to pascal was done by Carl Eric Codere in 2002 (ccodere@ieee.org).
 
5
===============================================================================
 
6
 
 
7
This C source file is part of the SoftFloat IEC/IEEE Floating-Point
 
8
Arithmetic Package, Release 2a.
 
9
 
 
10
Written by John R. Hauser.  This work was made possible in part by the
 
11
International Computer Science Institute, located at Suite 600, 1947 Center
 
12
Street, Berkeley, California 94704.  Funding was partially provided by the
 
13
National Science Foundation under grant MIP-9311980.  The original version
 
14
of this code was written as part of a project to build a fixed-point vector
 
15
processor in collaboration with the University of California at Berkeley,
 
16
overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
 
17
is available through the Web page
 
18
`http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'.
 
19
 
 
20
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
 
21
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
 
22
TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
 
23
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
 
24
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
 
25
 
 
26
Derivative works are acceptable, even for commercial purposes, so long as
 
27
(1) they include prominent notice that the work is derivative, and (2) they
 
28
include prominent notice akin to these four paragraphs for those parts of
 
29
this code that are retained.
 
30
 
 
31
===============================================================================
 
32
 
 
33
The float80 and float128 part is translated from the softfloat package
 
34
by Florian Klaempfl and contained the following copyright notice
 
35
 
 
36
The code might contain some duplicate stuff because the floatx80/float128 port was
 
37
done based on the 64 bit enabled softfloat code.
 
38
 
 
39
===============================================================================
 
40
 
 
41
This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
 
42
Package, Release 2b.
 
43
 
 
44
Written by John R. Hauser.  This work was made possible in part by the
 
45
International Computer Science Institute, located at Suite 600, 1947 Center
 
46
Street, Berkeley, California 94704.  Funding was partially provided by the
 
47
National Science Foundation under grant MIP-9311980.  The original version
 
48
of this code was written as part of a project to build a fixed-point vector
 
49
processor in collaboration with the University of California at Berkeley,
 
50
overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
 
51
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
 
52
arithmetic/SoftFloat.html'.
 
53
 
 
54
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
 
55
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
 
56
RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
 
57
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
 
58
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
 
59
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
 
60
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
 
61
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
 
62
 
 
63
Derivative works are acceptable, even for commercial purposes, so long as
 
64
(1) the source code for the derivative work includes prominent notice that
 
65
the work is derivative, and (2) the source code includes prominent notice with
 
66
these four paragraphs for those parts of this code that are retained.
 
67
 
 
68
 
 
69
===============================================================================
 
70
*}
 
71
 
 
72
{ $define FPC_SOFTFLOAT_FLOATX80}
 
73
{ $define FPC_SOFTFLOAT_FLOAT128}
 
74
 
 
75
{ the softfpu unit can be also embedded directly into the system unit }
 
76
 
 
77
{$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
 
78
 
 
79
{$mode objfpc}
 
80
unit softfpu;
 
81
 
 
82
{ Overflow checking must be disabled,
 
83
  since some operations expect overflow!
 
84
}
 
85
{$Q-}
 
86
{$goto on}
 
87
 
 
88
interface
 
89
{$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
 
90
 
 
91
{$if not(defined(fpc_softfpu_implementation))}
 
92
{
 
93
-------------------------------------------------------------------------------
 
94
Software IEC/IEEE floating-point types.
 
95
-------------------------------------------------------------------------------
 
96
}
 
97
TYPE
 
98
  float32 = longword;
 
99
  { we use here a record in the function header because
 
100
    the record allows bitwise conversion to single }
 
101
  float32rec = record
 
102
    float32 : float32;
 
103
  end;
 
104
 
 
105
  flag = byte;
 
106
  uint8 = byte;
 
107
  int8 = shortint;
 
108
  uint16 = word;
 
109
  int16 = smallint;
 
110
  uint32 = longword;
 
111
  int32 = longint;
 
112
 
 
113
  bits8 = byte;
 
114
  sbits8 = shortint;
 
115
  bits16 = word;
 
116
  sbits16 = smallint;
 
117
  sbits32 = longint;
 
118
  bits32 = longword;
 
119
{$ifndef fpc}
 
120
  qword = int64;
 
121
{$endif}
 
122
  { now part of the system unit
 
123
  uint64 = qword;
 
124
  }
 
125
  bits64 = qword;
 
126
  sbits64 = int64;
 
127
 
 
128
{$ifdef ENDIAN_LITTLE}
 
129
  float64 = packed record
 
130
    low: bits32;
 
131
    high: bits32;
 
132
  end;
 
133
 
 
134
 
 
135
  int64rec = packed record
 
136
    low: bits32;
 
137
    high: bits32;
 
138
  end;
 
139
 
 
140
  floatx80 = packed record
 
141
    low : qword;
 
142
    high : word;
 
143
  end;
 
144
 
 
145
  float128 = packed record
 
146
    low : qword;
 
147
    high : qword;
 
148
  end;
 
149
{$else}
 
150
 float64 = packed record
 
151
   high,low : bits32;
 
152
 end;
 
153
 
 
154
 int64rec = packed record
 
155
   high,low : bits32;
 
156
 end;
 
157
 
 
158
  floatx80 = packed record
 
159
    high : word;
 
160
    low : qword;
 
161
  end;
 
162
 
 
163
  float128 = packed record
 
164
    high : qword;
 
165
    low : qword;
 
166
  end;
 
167
{$endif}
 
168
 
 
169
{*
 
170
-------------------------------------------------------------------------------
 
171
Returns 1 if the double-precision floating-point value `a' is less than
 
172
the corresponding value `b', and 0 otherwise.  The comparison is performed
 
173
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
174
-------------------------------------------------------------------------------
 
175
*}
 
176
Function float64_lt(a: float64;b: float64): flag; compilerproc;
 
177
{*
 
178
-------------------------------------------------------------------------------
 
179
Returns 1 if the double-precision floating-point value `a' is less than
 
180
or equal to the corresponding value `b', and 0 otherwise.  The comparison
 
181
is performed according to the IEC/IEEE Standard for Binary Floating-Point
 
182
Arithmetic.
 
183
-------------------------------------------------------------------------------
 
184
*}
 
185
Function float64_le(a: float64;b: float64): flag; compilerproc;
 
186
{*
 
187
-------------------------------------------------------------------------------
 
188
Returns 1 if the double-precision floating-point value `a' is equal to
 
189
the corresponding value `b', and 0 otherwise.  The comparison is performed
 
190
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
191
-------------------------------------------------------------------------------
 
192
*}
 
193
Function float64_eq(a: float64;b: float64): flag; compilerproc;
 
194
{*
 
195
-------------------------------------------------------------------------------
 
196
Returns the square root of the double-precision floating-point value `a'.
 
197
The operation is performed according to the IEC/IEEE Standard for Binary
 
198
Floating-Point Arithmetic.
 
199
-------------------------------------------------------------------------------
 
200
*}
 
201
Procedure float64_sqrt( a: float64; var out: float64 ); compilerproc;
 
202
{*
 
203
-------------------------------------------------------------------------------
 
204
Returns the remainder of the double-precision floating-point value `a'
 
205
with respect to the corresponding value `b'.  The operation is performed
 
206
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
207
-------------------------------------------------------------------------------
 
208
*}
 
209
Function float64_rem(a: float64; b : float64) : float64; compilerproc;
 
210
{*
 
211
-------------------------------------------------------------------------------
 
212
Returns the result of dividing the double-precision floating-point value `a'
 
213
by the corresponding value `b'.  The operation is performed according to the
 
214
IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
215
-------------------------------------------------------------------------------
 
216
*}
 
217
Function float64_div(a: float64; b : float64) : float64; compilerproc;
 
218
{*
 
219
-------------------------------------------------------------------------------
 
220
Returns the result of multiplying the double-precision floating-point values
 
221
`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
 
222
for Binary Floating-Point Arithmetic.
 
223
-------------------------------------------------------------------------------
 
224
*}
 
225
Function float64_mul( a: float64; b:float64) : float64; compilerproc;
 
226
{*
 
227
-------------------------------------------------------------------------------
 
228
Returns the result of subtracting the double-precision floating-point values
 
229
`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
 
230
for Binary Floating-Point Arithmetic.
 
231
-------------------------------------------------------------------------------
 
232
*}
 
233
Function float64_sub(a: float64; b : float64) : float64; compilerproc;
 
234
{*
 
235
-------------------------------------------------------------------------------
 
236
Returns the result of adding the double-precision floating-point values `a'
 
237
and `b'.  The operation is performed according to the IEC/IEEE Standard for
 
238
Binary Floating-Point Arithmetic.
 
239
-------------------------------------------------------------------------------
 
240
*}
 
241
Function float64_add( a: float64; b : float64) : float64; compilerproc;
 
242
{*
 
243
-------------------------------------------------------------------------------
 
244
Rounds the double-precision floating-point value `a' to an integer,
 
245
and returns the result as a double-precision floating-point value.  The
 
246
operation is performed according to the IEC/IEEE Standard for Binary
 
247
Floating-Point Arithmetic.
 
248
-------------------------------------------------------------------------------
 
249
*}
 
250
Function float64_round_to_int(a: float64) : float64; compilerproc;
 
251
{*
 
252
-------------------------------------------------------------------------------
 
253
Returns the result of converting the double-precision floating-point value
 
254
`a' to the single-precision floating-point format.  The conversion is
 
255
performed according to the IEC/IEEE Standard for Binary Floating-Point
 
256
Arithmetic.
 
257
-------------------------------------------------------------------------------
 
258
*}
 
259
Function float64_to_float32(a: float64) : float32rec; compilerproc;
 
260
{*
 
261
-------------------------------------------------------------------------------
 
262
Returns the result of converting the double-precision floating-point value
 
263
`a' to the 32-bit two's complement integer format.  The conversion is
 
264
performed according to the IEC/IEEE Standard for Binary Floating-Point
 
265
Arithmetic, except that the conversion is always rounded toward zero.
 
266
If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
 
267
the conversion overflows, the largest integer with the same sign as `a' is
 
268
returned.
 
269
-------------------------------------------------------------------------------
 
270
*}
 
271
Function float64_to_int32_round_to_zero(a: float64 ): int32; compilerproc;
 
272
{*
 
273
-------------------------------------------------------------------------------
 
274
Returns the result of converting the double-precision floating-point value
 
275
`a' to the 32-bit two's complement integer format.  The conversion is
 
276
performed according to the IEC/IEEE Standard for Binary Floating-Point
 
277
Arithmetic---which means in particular that the conversion is rounded
 
278
according to the current rounding mode.  If `a' is a NaN, the largest
 
279
positive integer is returned.  Otherwise, if the conversion overflows, the
 
280
largest integer with the same sign as `a' is returned.
 
281
-------------------------------------------------------------------------------
 
282
*}
 
283
Function float64_to_int32(a: float64): int32; compilerproc;
 
284
{*
 
285
-------------------------------------------------------------------------------
 
286
Returns 1 if the single-precision floating-point value `a' is less than
 
287
the corresponding value `b', and 0 otherwise.  The comparison is performed
 
288
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
289
-------------------------------------------------------------------------------
 
290
*}
 
291
Function float32_lt( a:float32rec ; b : float32rec): flag; compilerproc;
 
292
{*
 
293
-------------------------------------------------------------------------------
 
294
Returns 1 if the single-precision floating-point value `a' is less than
 
295
or equal to the corresponding value `b', and 0 otherwise.  The comparison
 
296
is performed according to the IEC/IEEE Standard for Binary Floating-Point
 
297
Arithmetic.
 
298
-------------------------------------------------------------------------------
 
299
*}
 
300
Function float32_le( a: float32rec; b : float32rec ):flag; compilerproc;
 
301
{*
 
302
-------------------------------------------------------------------------------
 
303
Returns 1 if the single-precision floating-point value `a' is equal to
 
304
the corresponding value `b', and 0 otherwise.  The comparison is performed
 
305
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
306
-------------------------------------------------------------------------------
 
307
*}
 
308
Function float32_eq( a:float32rec; b:float32rec): flag; compilerproc;
 
309
{*
 
310
-------------------------------------------------------------------------------
 
311
Returns the square root of the single-precision floating-point value `a'.
 
312
The operation is performed according to the IEC/IEEE Standard for Binary
 
313
Floating-Point Arithmetic.
 
314
-------------------------------------------------------------------------------
 
315
*}
 
316
Function float32_sqrt(a: float32rec ): float32rec; compilerproc;
 
317
{*
 
318
-------------------------------------------------------------------------------
 
319
Returns the remainder of the single-precision floating-point value `a'
 
320
with respect to the corresponding value `b'.  The operation is performed
 
321
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
322
-------------------------------------------------------------------------------
 
323
*}
 
324
Function float32_rem(a: float32rec; b: float32rec ):float32rec; compilerproc;
 
325
{*
 
326
-------------------------------------------------------------------------------
 
327
Returns the result of dividing the single-precision floating-point value `a'
 
328
by the corresponding value `b'.  The operation is performed according to the
 
329
IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
330
-------------------------------------------------------------------------------
 
331
*}
 
332
Function float32_div(a: float32rec;b: float32rec ): float32rec; compilerproc;
 
333
{*
 
334
-------------------------------------------------------------------------------
 
335
Returns the result of multiplying the single-precision floating-point values
 
336
`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
 
337
for Binary Floating-Point Arithmetic.
 
338
-------------------------------------------------------------------------------
 
339
*}
 
340
Function float32_mul(a: float32rec; b: float32rec ) : float32rec; compilerproc;
 
341
{*
 
342
-------------------------------------------------------------------------------
 
343
Returns the result of subtracting the single-precision floating-point values
 
344
`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
 
345
for Binary Floating-Point Arithmetic.
 
346
-------------------------------------------------------------------------------
 
347
*}
 
348
Function float32_sub( a: float32rec ; b:float32rec ): float32rec; compilerproc;
 
349
{*
 
350
-------------------------------------------------------------------------------
 
351
Returns the result of adding the single-precision floating-point values `a'
 
352
and `b'.  The operation is performed according to the IEC/IEEE Standard for
 
353
Binary Floating-Point Arithmetic.
 
354
-------------------------------------------------------------------------------
 
355
*}
 
356
Function float32_add( a: float32rec; b:float32rec ): float32rec; compilerproc;
 
357
{*
 
358
-------------------------------------------------------------------------------
 
359
Rounds the single-precision floating-point value `a' to an integer,
 
360
and returns the result as a single-precision floating-point value.  The
 
361
operation is performed according to the IEC/IEEE Standard for Binary
 
362
Floating-Point Arithmetic.
 
363
-------------------------------------------------------------------------------
 
364
*}
 
365
Function float32_round_to_int( a: float32rec): float32rec; compilerproc;
 
366
{*
 
367
-------------------------------------------------------------------------------
 
368
Returns the result of converting the single-precision floating-point value
 
369
`a' to the double-precision floating-point format.  The conversion is
 
370
performed according to the IEC/IEEE Standard for Binary Floating-Point
 
371
Arithmetic.
 
372
-------------------------------------------------------------------------------
 
373
*}
 
374
Function float32_to_float64( a : float32rec) : Float64; compilerproc;
 
375
{*
 
376
-------------------------------------------------------------------------------
 
377
Returns the result of converting the single-precision floating-point value
 
378
`a' to the 32-bit two's complement integer format.  The conversion is
 
379
performed according to the IEC/IEEE Standard for Binary Floating-Point
 
380
Arithmetic, except that the conversion is always rounded toward zero.
 
381
If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
 
382
the conversion overflows, the largest integer with the same sign as `a' is
 
383
returned.
 
384
-------------------------------------------------------------------------------
 
385
*}
 
386
Function float32_to_int32_round_to_zero( a: Float32rec ): int32; compilerproc;
 
387
{*
 
388
-------------------------------------------------------------------------------
 
389
Returns the result of converting the single-precision floating-point value
 
390
`a' to the 32-bit two's complement integer format.  The conversion is
 
391
performed according to the IEC/IEEE Standard for Binary Floating-Point
 
392
Arithmetic---which means in particular that the conversion is rounded
 
393
according to the current rounding mode.  If `a' is a NaN, the largest
 
394
positive integer is returned.  Otherwise, if the conversion overflows, the
 
395
largest integer with the same sign as `a' is returned.
 
396
-------------------------------------------------------------------------------
 
397
*}
 
398
Function float32_to_int32( a : float32rec) : int32; compilerproc;
 
399
{*
 
400
-------------------------------------------------------------------------------
 
401
Returns the result of converting the 32-bit two's complement integer `a' to
 
402
the double-precision floating-point format.  The conversion is performed
 
403
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
404
-------------------------------------------------------------------------------
 
405
*}
 
406
Function int32_to_float64( a: int32) : float64; compilerproc;
 
407
{*
 
408
-------------------------------------------------------------------------------
 
409
Returns the result of converting the 32-bit two's complement integer `a' to
 
410
the single-precision floating-point format.  The conversion is performed
 
411
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
412
-------------------------------------------------------------------------------
 
413
*}
 
414
Function int32_to_float32( a: int32): float32rec; compilerproc;
 
415
 
 
416
{*----------------------------------------------------------------------------
 
417
| Returns the result of converting the 64-bit two's complement integer `a'
 
418
| to the double-precision floating-point format.  The conversion is performed
 
419
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
420
*----------------------------------------------------------------------------*}
 
421
Function int64_to_float64( a: int64 ): float64; compilerproc;
 
422
 
 
423
{*----------------------------------------------------------------------------
 
424
| Returns the result of converting the 64-bit two's complement integer `a'
 
425
| to the single-precision floating-point format.  The conversion is performed
 
426
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
427
*----------------------------------------------------------------------------*}
 
428
Function int64_to_float32( a: int64 ): float32rec; compilerproc;
 
429
 
 
430
 
 
431
CONST
 
432
{-------------------------------------------------------------------------------
 
433
Software IEC/IEEE floating-point underflow tininess-detection mode.
 
434
-------------------------------------------------------------------------------
 
435
*}
 
436
    float_tininess_after_rounding  = 0;
 
437
    float_tininess_before_rounding = 1;
 
438
 
 
439
{*
 
440
-------------------------------------------------------------------------------
 
441
Software IEC/IEEE floating-point rounding mode.
 
442
-------------------------------------------------------------------------------
 
443
*}
 
444
{
 
445
Round to nearest.
 
446
This is the default mode. It should be used unless there is a specific
 
447
need for one of the others. In this mode results are rounded to the
 
448
nearest representable value. If the result is midway between two
 
449
representable values, the even representable is chosen. Even here
 
450
means the lowest-order bit is zero. This rounding mode prevents
 
451
statistical bias and guarantees numeric stability: round-off errors
 
452
in a lengthy calculation will remain smaller than half of FLT_EPSILON.
 
453
 
 
454
Round toward plus Infinity.
 
455
All results are rounded to the smallest representable value which is
 
456
greater than the result.
 
457
 
 
458
Round toward minus Infinity.
 
459
All results are rounded to the largest representable value which is
 
460
less than the result.
 
461
 
 
462
Round toward zero.
 
463
All results are rounded to the largest representable value whose
 
464
magnitude is less than that of the result. In other words, if the
 
465
result is negative it is rounded up; if it is positive, it is
 
466
rounded down.
 
467
}
 
468
    float_round_nearest_even = 0;
 
469
    float_round_down         = 1;
 
470
    float_round_up           = 2;
 
471
    float_round_to_zero      = 3;
 
472
 
 
473
{*
 
474
-------------------------------------------------------------------------------
 
475
Floating-point rounding mode and exception flags.
 
476
-------------------------------------------------------------------------------
 
477
*}
 
478
const
 
479
 float_rounding_mode : Byte = float_round_nearest_even;
 
480
 
 
481
{*
 
482
-------------------------------------------------------------------------------
 
483
Underflow tininess-detection mode, statically initialized to default value.
 
484
(The declaration in `softfloat.h' must match the `int8' type here.)
 
485
-------------------------------------------------------------------------------
 
486
*}
 
487
 
 
488
const float_detect_tininess: int8 = float_tininess_after_rounding;
 
489
 
 
490
{$endif  not(defined(fpc_softfpu_implementation))}
 
491
 
 
492
{$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
 
493
implementation
 
494
{$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
 
495
 
 
496
 
 
497
{$if not(defined(fpc_softfpu_interface))}
 
498
(*****************************************************************************)
 
499
(*----------------------------------------------------------------------------*)
 
500
(* Primitive arithmetic functions, including multi-word arithmetic, and       *)
 
501
(* division and square root approximations.  (Can be specialized to target if *)
 
502
(* desired.)                                                                  *)
 
503
(* ---------------------------------------------------------------------------*)
 
504
(*****************************************************************************)
 
505
 
 
506
 
 
507
{*----------------------------------------------------------------------------
 
508
| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
 
509
| and 7, and returns the properly rounded 32-bit integer corresponding to the
 
510
| input.  If `zSign' is 1, the input is negated before being converted to an
 
511
| integer.  Bit 63 of `absZ' must be zero.  Ordinarily, the fixed-point input
 
512
| is simply rounded to an integer, with the inexact exception raised if the
 
513
| input cannot be represented exactly as an integer.  However, if the fixed-
 
514
| point input is too large, the invalid exception is raised and the largest
 
515
| positive or negative integer is returned.
 
516
*----------------------------------------------------------------------------*}
 
517
 
 
518
function roundAndPackInt32( zSign: flag; absZ : bits64): int32;
 
519
var
 
520
    roundingMode: int8;
 
521
    roundNearestEven: flag;
 
522
    roundIncrement, roundBits: int8;
 
523
    z: int32;
 
524
begin
 
525
    roundingMode := float_rounding_mode;
 
526
    roundNearestEven := ord( roundingMode = float_round_nearest_even );
 
527
    roundIncrement := $40;
 
528
    if ( roundNearestEven=0 ) then
 
529
    begin
 
530
        if ( roundingMode = float_round_to_zero ) then
 
531
        begin
 
532
            roundIncrement := 0;
 
533
        end
 
534
        else begin
 
535
            roundIncrement := $7F;
 
536
            if ( zSign<>0 ) then
 
537
            begin
 
538
                if ( roundingMode = float_round_up ) then
 
539
                  roundIncrement := 0;
 
540
            end
 
541
            else begin
 
542
                if ( roundingMode = float_round_down ) then
 
543
                  roundIncrement := 0;
 
544
            end;
 
545
        end;
 
546
    end;
 
547
    roundBits := absZ and $7F;
 
548
    absZ := ( absZ + roundIncrement ) shr 7;
 
549
    absZ := absZ and not( ord( ( roundBits xor  $40 ) = 0 ) and roundNearestEven );
 
550
    z := absZ;
 
551
    if ( zSign<>0 ) then
 
552
      z := - z;
 
553
    if ( ( absZ shr 32 ) or ( z and ( ord( z < 0 ) xor  zSign ) ) )<>0 then
 
554
    begin
 
555
        float_raise( float_flag_invalid );
 
556
        if zSign<>0 then
 
557
          result:=sbits32($80000000)
 
558
        else
 
559
          result:=$7FFFFFFF;
 
560
        exit;
 
561
    end;
 
562
    if ( roundBits<>0 ) then
 
563
      softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
564
    result:=z;
 
565
end;
 
566
 
 
567
{*----------------------------------------------------------------------------
 
568
| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
 
569
| `absZ1', with binary point between bits 63 and 64 (between the input words),
 
570
| and returns the properly rounded 64-bit integer corresponding to the input.
 
571
| If `zSign' is 1, the input is negated before being converted to an integer.
 
572
| Ordinarily, the fixed-point input is simply rounded to an integer, with
 
573
| the inexact exception raised if the input cannot be represented exactly as
 
574
| an integer.  However, if the fixed-point input is too large, the invalid
 
575
| exception is raised and the largest positive or negative integer is
 
576
| returned.
 
577
*----------------------------------------------------------------------------*}
 
578
 
 
579
function roundAndPackInt64( zSign: flag; absZ0: bits64; absZ1 : bits64): int64;
 
580
var
 
581
    roundingMode: int8;
 
582
    roundNearestEven, increment: flag;
 
583
    z: int64;
 
584
label
 
585
    overflow;
 
586
begin
 
587
    roundingMode := float_rounding_mode;
 
588
    roundNearestEven := ord( roundingMode = float_round_nearest_even );
 
589
    increment := ord( sbits64(absZ1) < 0 );
 
590
    if ( roundNearestEven=0 ) then
 
591
    begin
 
592
        if ( roundingMode = float_round_to_zero ) then
 
593
        begin
 
594
            increment := 0;
 
595
        end
 
596
        else begin
 
597
            if ( zSign<>0 ) then
 
598
            begin
 
599
                increment := ord(( roundingMode = float_round_down ) and (absZ1<>0));
 
600
            end
 
601
            else begin
 
602
                increment := ord(( roundingMode = float_round_up ) and (absZ1<>0));
 
603
            end;
 
604
        end;
 
605
    end;
 
606
    if ( increment<>0 ) then
 
607
    begin
 
608
        inc(absZ0);
 
609
        if ( absZ0 = 0 ) then
 
610
          goto overflow;
 
611
        absZ0 := absZ0 and not( ord( bits64( absZ1 shl 1 ) = 0 ) and roundNearestEven );
 
612
    end;
 
613
    z := absZ0;
 
614
    if ( zSign<>0 ) then
 
615
      z := - z;
 
616
    if ( (z<>0) and (( ord( z < 0 ) xor  zSign )<>0) ) then
 
617
    begin
 
618
 overflow:
 
619
        float_raise( float_flag_invalid );
 
620
        if zSign<>0 then
 
621
          result:=int64($8000000000000000)
 
622
        else
 
623
          result:=int64($7FFFFFFFFFFFFFFF);
 
624
    end;
 
625
    if ( absZ1<>0 ) then
 
626
      softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
627
    result:=z;
 
628
end;
 
629
 
 
630
{*
 
631
-------------------------------------------------------------------------------
 
632
Shifts `a' right by the number of bits given in `count'.  If any nonzero
 
633
bits are shifted off, they are ``jammed'' into the least significant bit of
 
634
the result by setting the least significant bit to 1.  The value of `count'
 
635
can be arbitrarily large; in particular, if `count' is greater than 32, the
 
636
result will be either 0 or 1, depending on whether `a' is zero or nonzero.
 
637
The result is stored in the location pointed to by `zPtr'.
 
638
-------------------------------------------------------------------------------
 
639
*}
 
640
Procedure shift32RightJamming( a: bits32 ; count: int16 ; VAR zPtr :bits32);
 
641
var
 
642
  z: Bits32;
 
643
Begin
 
644
    if ( count = 0 ) then
 
645
        z := a
 
646
   else
 
647
    if ( count < 32 ) then
 
648
    Begin
 
649
        z := ( a shr count ) or bits32( (( a shl ( ( - count ) AND 31 )) ) <> 0);
 
650
    End
 
651
   else
 
652
    Begin
 
653
        z := bits32( a <> 0 );
 
654
    End;
 
655
    zPtr := z;
 
656
End;
 
657
 
 
658
{*----------------------------------------------------------------------------
 
659
| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
 
660
| number of bits given in `count'.  Any bits shifted off are lost.  The value
 
661
| of `count' can be arbitrarily large; in particular, if `count' is greater
 
662
| than 128, the result will be 0.  The result is broken into two 64-bit pieces
 
663
| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
 
664
*----------------------------------------------------------------------------*}
 
665
 
 
666
procedure shift128Right(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; z1Ptr : bits64);
 
667
var
 
668
    z0, z1: bits64;
 
669
    negCount: int8;
 
670
begin
 
671
    negCount := ( - count ) and 63;
 
672
 
 
673
    if ( count = 0 ) then
 
674
    begin
 
675
        z1 := a1;
 
676
        z0 := a0;
 
677
    end
 
678
    else if ( count < 64 ) then
 
679
    begin
 
680
        z1 := ( a0 shl negCount ) or ( a1 shr count );
 
681
        z0 := a0 shr count;
 
682
    end
 
683
    else
 
684
    begin
 
685
          if ( count shl 64 )<>0 then
 
686
          z1 := a0 shr ( count and 63 )
 
687
        else
 
688
          z1 := 0;
 
689
        z0 := 0;
 
690
    end;
 
691
    z1Ptr := z1;
 
692
    z0Ptr := z0;
 
693
end;
 
694
 
 
695
 
 
696
{*
 
697
-------------------------------------------------------------------------------
 
698
Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
 
699
number of bits given in `count'.  Any bits shifted off are lost.  The value
 
700
of `count' can be arbitrarily large; in particular, if `count' is greater
 
701
than 64, the result will be 0.  The result is broken into two 32-bit pieces
 
702
which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
 
703
-------------------------------------------------------------------------------
 
704
*}
 
705
Procedure
 
706
 shift64Right(
 
707
     a0 :bits32; a1: bits32; count:int16; VAR z0Ptr:bits32; VAR z1Ptr:bits32);
 
708
Var
 
709
  z0, z1: bits32;
 
710
  negCount : int8;
 
711
Begin
 
712
    negCount := ( - count ) AND 31;
 
713
 
 
714
    if ( count = 0 ) then
 
715
    Begin
 
716
        z1 := a1;
 
717
        z0 := a0;
 
718
    End
 
719
    else if ( count < 32 ) then
 
720
    Begin
 
721
        z1 := ( a0 shl negCount ) OR ( a1 shr count );
 
722
        z0 := a0 shr count;
 
723
    End
 
724
   else
 
725
    Begin
 
726
        if (count < 64) then
 
727
          z1 := ( a0 shr ( count AND 31 ) )
 
728
        else
 
729
          z1 := 0;
 
730
        z0 := 0;
 
731
    End;
 
732
    z1Ptr := z1;
 
733
    z0Ptr := z0;
 
734
End;
 
735
 
 
736
{*
 
737
-------------------------------------------------------------------------------
 
738
Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
 
739
number of bits given in `count'.  If any nonzero bits are shifted off, they
 
740
are ``jammed'' into the least significant bit of the result by setting the
 
741
least significant bit to 1.  The value of `count' can be arbitrarily large;
 
742
in particular, if `count' is greater than 64, the result will be either 0
 
743
or 1, depending on whether the concatenation of `a0' and `a1' is zero or
 
744
nonzero.  The result is broken into two 32-bit pieces which are stored at
 
745
the locations pointed to by `z0Ptr' and `z1Ptr'.
 
746
-------------------------------------------------------------------------------
 
747
*}
 
748
Procedure
 
749
 shift64RightJamming(
 
750
     a0:bits32; a1: bits32; count:int16; VAR Z0Ptr :bits32;VAR z1Ptr: bits32 );
 
751
VAR
 
752
    z0, z1 : bits32;
 
753
    negCount : int8;
 
754
Begin
 
755
    negCount := ( - count ) AND 31;
 
756
 
 
757
    if ( count = 0 ) then
 
758
    Begin
 
759
        z1 := a1;
 
760
        z0 := a0;
 
761
    End
 
762
   else
 
763
    if ( count < 32 ) then
 
764
    Begin
 
765
        z1 := ( a0 shl negCount ) OR ( a1 shr count ) OR bits32( ( a1 shl negCount ) <> 0 );
 
766
        z0 := a0 shr count;
 
767
    End
 
768
   else
 
769
    Begin
 
770
        if ( count = 32 ) then
 
771
        Begin
 
772
            z1 := a0 OR bits32( a1 <> 0 );
 
773
        End
 
774
       else
 
775
        if ( count < 64 ) Then
 
776
        Begin
 
777
            z1 := ( a0 shr ( count AND 31 ) ) OR bits32( ( ( a0 shl negCount ) OR a1 ) <> 0 );
 
778
        End
 
779
       else
 
780
        Begin
 
781
            z1 := bits32( ( a0 OR a1 ) <> 0 );
 
782
        End;
 
783
        z0 := 0;
 
784
    End;
 
785
    z1Ptr := z1;
 
786
    z0Ptr := z0;
 
787
End;
 
788
 
 
789
 
 
790
{*----------------------------------------------------------------------------
 
791
| Shifts `a' right by the number of bits given in `count'.  If any nonzero
 
792
| bits are shifted off, they are ``jammed'' into the least significant bit of
 
793
| the result by setting the least significant bit to 1.  The value of `count'
 
794
| can be arbitrarily large; in particular, if `count' is greater than 64, the
 
795
| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
 
796
| The result is stored in the location pointed to by `zPtr'.
 
797
*----------------------------------------------------------------------------*}
 
798
 
 
799
procedure shift64RightJamming(a: bits64; count: int16; var zPtr : bits64);
 
800
var
 
801
    z: bits64;
 
802
begin
 
803
    if ( count = 0 ) then
 
804
    begin
 
805
        z := a;
 
806
    end
 
807
    else if ( count < 64 ) then
 
808
    begin
 
809
        z := ( a shr count ) or ord( ( a  shl ( ( - count ) and 63 ) ) <> 0 );
 
810
    end
 
811
    else
 
812
    begin
 
813
        z := ord( a <> 0 );
 
814
    end;
 
815
    zPtr := z;
 
816
end;
 
817
 
 
818
 
 
819
 
 
820
{*
 
821
-------------------------------------------------------------------------------
 
822
Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' right
 
823
by 32 _plus_ the number of bits given in `count'.  The shifted result is
 
824
at most 64 nonzero bits; these are broken into two 32-bit pieces which are
 
825
stored at the locations pointed to by `z0Ptr' and `z1Ptr'.  The bits shifted
 
826
off form a third 32-bit result as follows:  The _last_ bit shifted off is
 
827
the most-significant bit of the extra result, and the other 31 bits of the
 
828
extra result are all zero if and only if _all_but_the_last_ bits shifted off
 
829
were all zero.  This extra result is stored in the location pointed to by
 
830
`z2Ptr'.  The value of `count' can be arbitrarily large.
 
831
    (This routine makes more sense if `a0', `a1', and `a2' are considered
 
832
to form a fixed-point value with binary point between `a1' and `a2'.  This
 
833
fixed-point value is shifted right by the number of bits given in `count',
 
834
and the integer part of the result is returned at the locations pointed to
 
835
by `z0Ptr' and `z1Ptr'.  The fractional part of the result may be slightly
 
836
corrupted as described above, and is returned at the location pointed to by
 
837
`z2Ptr'.)
 
838
-------------------------------------------------------------------------------
 
839
}
 
840
Procedure
 
841
 shift64ExtraRightJamming(
 
842
     a0: bits32;
 
843
     a1: bits32;
 
844
     a2: bits32;
 
845
     count: int16;
 
846
     VAR z0Ptr: bits32;
 
847
     VAR z1Ptr: bits32;
 
848
     VAR z2Ptr: bits32
 
849
 );
 
850
Var
 
851
    z0, z1, z2: bits32;
 
852
    negCount : int8;
 
853
Begin
 
854
    negCount := ( - count ) AND 31;
 
855
 
 
856
    if ( count = 0 ) then
 
857
    Begin
 
858
        z2 := a2;
 
859
        z1 := a1;
 
860
        z0 := a0;
 
861
    End
 
862
   else
 
863
    Begin
 
864
        if ( count < 32 ) Then
 
865
        Begin
 
866
            z2 := a1 shl negCount;
 
867
            z1 := ( a0 shl negCount ) OR ( a1 shr count );
 
868
            z0 := a0 shr count;
 
869
        End
 
870
       else
 
871
        Begin
 
872
            if ( count = 32 ) then
 
873
            Begin
 
874
                z2 := a1;
 
875
                z1 := a0;
 
876
            End
 
877
           else
 
878
            Begin
 
879
                a2 := a2 or a1;
 
880
                if ( count < 64 ) then
 
881
                Begin
 
882
                    z2 := a0 shl negCount;
 
883
                    z1 := a0 shr ( count AND 31 );
 
884
                End
 
885
               else
 
886
                Begin
 
887
                    if count = 64 then
 
888
                       z2 := a0
 
889
                    else
 
890
                       z2 := bits32(a0 <> 0);
 
891
                    z1 := 0;
 
892
                End;
 
893
            End;
 
894
            z0 := 0;
 
895
        End;
 
896
        z2 := z2 or bits32( a2 <> 0 );
 
897
    End;
 
898
    z2Ptr := z2;
 
899
    z1Ptr := z1;
 
900
    z0Ptr := z0;
 
901
End;
 
902
 
 
903
{*
 
904
-------------------------------------------------------------------------------
 
905
Shifts the 64-bit value formed by concatenating `a0' and `a1' left by the
 
906
number of bits given in `count'.  Any bits shifted off are lost.  The value
 
907
of `count' must be less than 32.  The result is broken into two 32-bit
 
908
pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
 
909
-------------------------------------------------------------------------------
 
910
*}
 
911
Procedure
 
912
 shortShift64Left(
 
913
     a0:bits32; a1:bits32; count:int16; VAR z0Ptr:bits32; VAR z1Ptr:bits32 );
 
914
Begin
 
915
 
 
916
    z1Ptr := a1 shl count;
 
917
    if count = 0 then
 
918
      z0Ptr := a0
 
919
    else
 
920
      z0Ptr := ( a0 shl count ) OR ( a1 shr ( ( - count ) AND 31 ) );
 
921
End;
 
922
 
 
923
{*
 
924
-------------------------------------------------------------------------------
 
925
Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' left
 
926
by the number of bits given in `count'.  Any bits shifted off are lost.
 
927
The value of `count' must be less than 32.  The result is broken into three
 
928
32-bit pieces which are stored at the locations pointed to by `z0Ptr',
 
929
`z1Ptr', and `z2Ptr'.
 
930
-------------------------------------------------------------------------------
 
931
*}
 
932
Procedure
 
933
 shortShift96Left(
 
934
     a0: bits32;
 
935
     a1: bits32;
 
936
     a2: bits32;
 
937
     count: int16;
 
938
     VAR z0Ptr: bits32;
 
939
     VAR z1Ptr: bits32;
 
940
     VAR z2Ptr: bits32
 
941
 );
 
942
Var
 
943
    z0, z1, z2: bits32;
 
944
    negCount: int8;
 
945
Begin
 
946
    z2 := a2 shl count;
 
947
    z1 := a1 shl count;
 
948
    z0 := a0 shl count;
 
949
    if ( 0 < count ) then
 
950
    Begin
 
951
        negCount := ( ( - count ) AND 31 );
 
952
        z1 := z1 or (a2 shr negCount);
 
953
        z0 := z0 or (a1 shr negCount);
 
954
    End;
 
955
    z2Ptr := z2;
 
956
    z1Ptr := z1;
 
957
    z0Ptr := z0;
 
958
End;
 
959
 
 
960
{*----------------------------------------------------------------------------
 
961
| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
 
962
| number of bits given in `count'.  Any bits shifted off are lost.  The value
 
963
| of `count' must be less than 64.  The result is broken into two 64-bit
 
964
| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
 
965
*----------------------------------------------------------------------------*}
 
966
 
 
967
procedure shortShift128Left(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; z1Ptr : bits64);inline;
 
968
begin
 
969
    z1Ptr := a1 shl count;
 
970
    if count=0 then
 
971
      z0Ptr:=a0
 
972
    else
 
973
      z0Ptr:=( a0 shl count ) or ( a1 shr ( ( - count ) and 63 ) );
 
974
end;
 
975
 
 
976
{*
 
977
-------------------------------------------------------------------------------
 
978
Adds the 64-bit value formed by concatenating `a0' and `a1' to the 64-bit
 
979
value formed by concatenating `b0' and `b1'.  Addition is modulo 2^64, so
 
980
any carry out is lost.  The result is broken into two 32-bit pieces which
 
981
are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
 
982
-------------------------------------------------------------------------------
 
983
*}
 
984
Procedure
 
985
 add64(
 
986
     a0:bits32; a1:bits32; b0:bits32; b1:bits32; VAR z0Ptr:bits32; VAR z1Ptr:bits32 );
 
987
Var
 
988
    z1: bits32;
 
989
Begin
 
990
    z1 := a1 + b1;
 
991
    z1Ptr := z1;
 
992
    z0Ptr := a0 + b0 + bits32( z1 < a1 );
 
993
End;
 
994
 
 
995
{*
 
996
-------------------------------------------------------------------------------
 
997
Adds the 96-bit value formed by concatenating `a0', `a1', and `a2' to the
 
998
96-bit value formed by concatenating `b0', `b1', and `b2'.  Addition is
 
999
modulo 2^96, so any carry out is lost.  The result is broken into three
 
1000
32-bit pieces which are stored at the locations pointed to by `z0Ptr',
 
1001
`z1Ptr', and `z2Ptr'.
 
1002
-------------------------------------------------------------------------------
 
1003
*}
 
1004
Procedure
 
1005
 add96(
 
1006
     a0: bits32;
 
1007
     a1: bits32;
 
1008
     a2: bits32;
 
1009
     b0: bits32;
 
1010
     b1: bits32;
 
1011
     b2: bits32;
 
1012
     VAR z0Ptr: bits32;
 
1013
     VAR z1Ptr: bits32;
 
1014
     VAR z2Ptr: bits32
 
1015
 );
 
1016
var
 
1017
    z0, z1, z2: bits32;
 
1018
    carry0, carry1: int8;
 
1019
Begin
 
1020
    z2 := a2 + b2;
 
1021
    carry1 := int8( z2 < a2 );
 
1022
    z1 := a1 + b1;
 
1023
    carry0 := int8( z1 < a1 );
 
1024
    z0 := a0 + b0;
 
1025
    z1 := z1 + carry1;
 
1026
    z0 := z0 + bits32( z1 < carry1 );
 
1027
    z0 := z0 + carry0;
 
1028
    z2Ptr := z2;
 
1029
    z1Ptr := z1;
 
1030
    z0Ptr := z0;
 
1031
End;
 
1032
 
 
1033
{*
 
1034
-------------------------------------------------------------------------------
 
1035
Subtracts the 64-bit value formed by concatenating `b0' and `b1' from the
 
1036
64-bit value formed by concatenating `a0' and `a1'.  Subtraction is modulo
 
1037
2^64, so any borrow out (carry out) is lost.  The result is broken into two
 
1038
32-bit pieces which are stored at the locations pointed to by `z0Ptr' and
 
1039
`z1Ptr'.
 
1040
-------------------------------------------------------------------------------
 
1041
*}
 
1042
Procedure
 
1043
 sub64(
 
1044
     a0: bits32; a1 : bits32; b0 :bits32; b1: bits32; VAR z0Ptr:bits32; VAR z1Ptr: bits32 );
 
1045
Begin
 
1046
    z1Ptr := a1 - b1;
 
1047
    z0Ptr := a0 - b0 - bits32( a1 < b1 );
 
1048
End;
 
1049
 
 
1050
{*
 
1051
-------------------------------------------------------------------------------
 
1052
Subtracts the 96-bit value formed by concatenating `b0', `b1', and `b2' from
 
1053
the 96-bit value formed by concatenating `a0', `a1', and `a2'.  Subtraction
 
1054
is modulo 2^96, so any borrow out (carry out) is lost.  The result is broken
 
1055
into three 32-bit pieces which are stored at the locations pointed to by
 
1056
`z0Ptr', `z1Ptr', and `z2Ptr'.
 
1057
-------------------------------------------------------------------------------
 
1058
*}
 
1059
Procedure
 
1060
 sub96(
 
1061
     a0:bits32;
 
1062
     a1:bits32;
 
1063
     a2:bits32;
 
1064
     b0:bits32;
 
1065
     b1:bits32;
 
1066
     b2:bits32;
 
1067
     VAR z0Ptr:bits32;
 
1068
     VAR z1Ptr:bits32;
 
1069
     VAR z2Ptr:bits32
 
1070
 );
 
1071
Var
 
1072
    z0, z1, z2: bits32;
 
1073
    borrow0, borrow1: int8;
 
1074
Begin
 
1075
    z2 := a2 - b2;
 
1076
    borrow1 := int8( a2 < b2 );
 
1077
    z1 := a1 - b1;
 
1078
    borrow0 := int8( a1 < b1 );
 
1079
    z0 := a0 - b0;
 
1080
    z0 := z0 - bits32( z1 < borrow1 );
 
1081
    z1 := z1 - borrow1;
 
1082
    z0 := z0 -borrow0;
 
1083
    z2Ptr := z2;
 
1084
    z1Ptr := z1;
 
1085
    z0Ptr := z0;
 
1086
End;
 
1087
 
 
1088
{*
 
1089
-------------------------------------------------------------------------------
 
1090
Multiplies `a' by `b' to obtain a 64-bit product.  The product is broken
 
1091
into two 32-bit pieces which are stored at the locations pointed to by
 
1092
`z0Ptr' and `z1Ptr'.
 
1093
-------------------------------------------------------------------------------
 
1094
*}
 
1095
Procedure mul32To64( a:bits32; b:bits32; VAR z0Ptr: bits32; VAR z1Ptr
 
1096
:bits32 );
 
1097
Var
 
1098
    aHigh, aLow, bHigh, bLow: bits16;
 
1099
    z0, zMiddleA, zMiddleB, z1: bits32;
 
1100
Begin
 
1101
    aLow := a and $ffff;
 
1102
    aHigh := a shr 16;
 
1103
    bLow := b and $ffff;
 
1104
    bHigh := b shr 16;
 
1105
    z1 := ( bits32( aLow) ) * bLow;
 
1106
    zMiddleA := ( bits32 (aLow) ) * bHigh;
 
1107
    zMiddleB := ( bits32 (aHigh) ) * bLow;
 
1108
    z0 := ( bits32 (aHigh) ) * bHigh;
 
1109
    zMiddleA := zMiddleA + zMiddleB;
 
1110
    z0 := z0 + ( ( bits32 ( zMiddleA < zMiddleB ) ) shl 16 ) + ( zMiddleA shr 16 );
 
1111
    zMiddleA := zmiddleA shl 16;
 
1112
    z1 := z1 + zMiddleA;
 
1113
    z0 := z0 + bits32( z1 < zMiddleA );
 
1114
    z1Ptr := z1;
 
1115
    z0Ptr := z0;
 
1116
End;
 
1117
 
 
1118
{*
 
1119
-------------------------------------------------------------------------------
 
1120
Multiplies the 64-bit value formed by concatenating `a0' and `a1' by `b'
 
1121
to obtain a 96-bit product.  The product is broken into three 32-bit pieces
 
1122
which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
 
1123
`z2Ptr'.
 
1124
-------------------------------------------------------------------------------
 
1125
*}
 
1126
Procedure
 
1127
 mul64By32To96(
 
1128
     a0:bits32;
 
1129
     a1:bits32;
 
1130
     b:bits32;
 
1131
     VAR z0Ptr:bits32;
 
1132
     VAR z1Ptr:bits32;
 
1133
     VAR z2Ptr:bits32
 
1134
 );
 
1135
Var
 
1136
    z0, z1, z2, more1: bits32;
 
1137
Begin
 
1138
    mul32To64( a1, b, z1, z2 );
 
1139
    mul32To64( a0, b, z0, more1 );
 
1140
    add64( z0, more1, 0, z1, z0, z1 );
 
1141
    z2Ptr := z2;
 
1142
    z1Ptr := z1;
 
1143
    z0Ptr := z0;
 
1144
End;
 
1145
 
 
1146
{*
 
1147
-------------------------------------------------------------------------------
 
1148
Multiplies the 64-bit value formed by concatenating `a0' and `a1' to the
 
1149
64-bit value formed by concatenating `b0' and `b1' to obtain a 128-bit
 
1150
product.  The product is broken into four 32-bit pieces which are stored at
 
1151
the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
 
1152
-------------------------------------------------------------------------------
 
1153
*}
 
1154
Procedure
 
1155
 mul64To128(
 
1156
     a0:bits32;
 
1157
     a1:bits32;
 
1158
     b0:bits32;
 
1159
     b1:bits32;
 
1160
     VAR z0Ptr:bits32;
 
1161
     VAR z1Ptr:bits32;
 
1162
     VAR z2Ptr:bits32;
 
1163
     VAR z3Ptr:bits32
 
1164
 );
 
1165
Var
 
1166
    z0, z1, z2, z3: bits32;
 
1167
    more1, more2: bits32;
 
1168
Begin
 
1169
 
 
1170
    mul32To64( a1, b1, z2, z3 );
 
1171
    mul32To64( a1, b0, z1, more2 );
 
1172
    add64( z1, more2, 0, z2, z1, z2 );
 
1173
    mul32To64( a0, b0, z0, more1 );
 
1174
    add64( z0, more1, 0, z1, z0, z1 );
 
1175
    mul32To64( a0, b1, more1, more2 );
 
1176
    add64( more1, more2, 0, z2, more1, z2 );
 
1177
    add64( z0, z1, 0, more1, z0, z1 );
 
1178
    z3Ptr := z3;
 
1179
    z2Ptr := z2;
 
1180
    z1Ptr := z1;
 
1181
    z0Ptr := z0;
 
1182
 
 
1183
End;
 
1184
 
 
1185
{*
 
1186
-------------------------------------------------------------------------------
 
1187
Returns an approximation to the 32-bit integer quotient obtained by dividing
 
1188
`b' into the 64-bit value formed by concatenating `a0' and `a1'.  The
 
1189
divisor `b' must be at least 2^31.  If q is the exact quotient truncated
 
1190
toward zero, the approximation returned lies between q and q + 2 inclusive.
 
1191
If the exact quotient q is larger than 32 bits, the maximum positive 32-bit
 
1192
unsigned integer is returned.
 
1193
-------------------------------------------------------------------------------
 
1194
*}
 
1195
Function estimateDiv64To32( a0:bits32; a1: bits32; b:bits32): bits32;
 
1196
Var
 
1197
    b0, b1: bits32;
 
1198
    rem0, rem1, term0, term1: bits32;
 
1199
    z: bits32;
 
1200
Begin
 
1201
    if ( b <= a0 ) then
 
1202
    Begin
 
1203
       estimateDiv64To32 := $FFFFFFFF;
 
1204
       exit;
 
1205
    End;
 
1206
    b0 := b shr 16;
 
1207
    if ( b0 shl 16 <= a0 ) then
 
1208
       z:= $FFFF0000
 
1209
     else
 
1210
       z:= ( a0 div b0 ) shl 16;
 
1211
    mul32To64( b, z, term0, term1 );
 
1212
    sub64( a0, a1, term0, term1, rem0, rem1 );
 
1213
    while ( ( sbits32 (rem0) ) < 0 ) do
 
1214
    Begin
 
1215
        z := z - $10000;
 
1216
        b1 := b shl 16;
 
1217
        add64( rem0, rem1, b0, b1, rem0, rem1 );
 
1218
    End;
 
1219
    rem0 := ( rem0 shl 16 ) OR ( rem1 shr 16 );
 
1220
    if ( b0 shl 16 <= rem0 ) then
 
1221
      z := z or $FFFF
 
1222
    else
 
1223
      z := z or (rem0 div b0);
 
1224
    estimateDiv64To32 := z;
 
1225
 
 
1226
End;
 
1227
 
 
1228
{*
 
1229
-------------------------------------------------------------------------------
 
1230
Returns an approximation to the square root of the 32-bit significand given
 
1231
by `a'.  Considered as an integer, `a' must be at least 2^31.  If bit 0 of
 
1232
`aExp' (the least significant bit) is 1, the integer returned approximates
 
1233
2^31*sqrt(`a'/2^31), where `a' is considered an integer.  If bit 0 of `aExp'
 
1234
is 0, the integer returned approximates 2^31*sqrt(`a'/2^30).  In either
 
1235
case, the approximation returned lies strictly within +/-2 of the exact
 
1236
value.
 
1237
-------------------------------------------------------------------------------
 
1238
*}
 
1239
Function estimateSqrt32( aExp: int16; a: bits32 ): bits32;
 
1240
    const sqrtOddAdjustments: array[0..15] of bits16 = (
 
1241
        $0004, $0022, $005D, $00B1, $011D, $019F, $0236, $02E0,
 
1242
        $039C, $0468, $0545, $0631, $072B, $0832, $0946, $0A67
 
1243
    );
 
1244
    const sqrtEvenAdjustments: array[0..15] of bits16 = (
 
1245
        $0A2D, $08AF, $075A, $0629, $051A, $0429, $0356, $029E,
 
1246
        $0200, $0179, $0109, $00AF, $0068, $0034, $0012, $0002
 
1247
    );
 
1248
Var
 
1249
    index: int8;
 
1250
    z: bits32;
 
1251
Begin
 
1252
 
 
1253
    index := ( a shr 27 ) AND 15;
 
1254
    if ( aExp AND 1 ) <> 0  then
 
1255
    Begin
 
1256
        z := $4000 + ( a shr 17 ) - sqrtOddAdjustments[ index ];
 
1257
        z := ( ( a div z ) shl 14 ) + ( z shl 15 );
 
1258
        a := a shr 1;
 
1259
    End
 
1260
    else
 
1261
    Begin
 
1262
        z := $8000 + ( a shr 17 ) - sqrtEvenAdjustments[ index ];
 
1263
        z := a div z + z;
 
1264
        if ( $20000 <= z ) then
 
1265
          z := $FFFF8000
 
1266
        else
 
1267
          z := ( z shl 15 );
 
1268
        if ( z <= a ) then
 
1269
        Begin
 
1270
           estimateSqrt32 := bits32 ( ( sbits32 (a )) shr 1 );
 
1271
           exit;
 
1272
        End;
 
1273
    End;
 
1274
    estimateSqrt32 := ( ( estimateDiv64To32( a, 0, z ) ) shr 1 ) + ( z shr 1 );
 
1275
End;
 
1276
 
 
1277
{*
 
1278
-------------------------------------------------------------------------------
 
1279
Returns the number of leading 0 bits before the most-significant 1 bit of
 
1280
`a'.  If `a' is zero, 32 is returned.
 
1281
-------------------------------------------------------------------------------
 
1282
*}
 
1283
Function countLeadingZeros32( a:bits32 ): int8;
 
1284
 
 
1285
    const countLeadingZerosHigh:array[0..255] of int8 = (
 
1286
        8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
 
1287
        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 
1288
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 
1289
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 
1290
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 
1291
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 
1292
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 
1293
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 
1294
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
1295
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
1296
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
1297
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
1298
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
1299
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
1300
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
1301
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 
1302
    );
 
1303
Var
 
1304
    shiftCount: int8;
 
1305
Begin
 
1306
 
 
1307
    shiftCount := 0;
 
1308
    if ( a < $10000 ) then
 
1309
    Begin
 
1310
        shiftCount := shiftcount + 16;
 
1311
        a := a shl 16;
 
1312
    End;
 
1313
    if ( a < $1000000 ) then
 
1314
    Begin
 
1315
        shiftCount := shiftcount + 8;
 
1316
        a := a shl 8;
 
1317
    end;
 
1318
    shiftCount := shiftcount + countLeadingZerosHigh[ a shr 24 ];
 
1319
    countLeadingZeros32:= shiftCount;
 
1320
End;
 
1321
 
 
1322
{*----------------------------------------------------------------------------
 
1323
| Returns the number of leading 0 bits before the most-significant 1 bit of
 
1324
| `a'.  If `a' is zero, 64 is returned.
 
1325
*----------------------------------------------------------------------------*}
 
1326
 
 
1327
function countLeadingZeros64( a : bits64): int8;
 
1328
var
 
1329
 shiftcount : int8;
 
1330
Begin
 
1331
    shiftCount := 0;
 
1332
    if ( a <  (bits64(1)  shl 32 )) then
 
1333
        shiftCount := shiftcount + 32
 
1334
    else
 
1335
        a := a shr 32;
 
1336
    shiftCount := shiftCount + countLeadingZeros32( a );
 
1337
    countLeadingZeros64:= shiftCount;
 
1338
End;
 
1339
 
 
1340
 
 
1341
 
 
1342
{*
 
1343
-------------------------------------------------------------------------------
 
1344
Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is
 
1345
equal to the 64-bit value formed by concatenating `b0' and `b1'.  Otherwise,
 
1346
returns 0.
 
1347
-------------------------------------------------------------------------------
 
1348
*}
 
1349
Function eq64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
 
1350
Begin
 
1351
    eq64 :=  flag( a0 = b0 ) and flag( a1 = b1 );
 
1352
End;
 
1353
 
 
1354
{*
 
1355
-------------------------------------------------------------------------------
 
1356
Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
 
1357
than or equal to the 64-bit value formed by concatenating `b0' and `b1'.
 
1358
Otherwise, returns 0.
 
1359
-------------------------------------------------------------------------------
 
1360
*}
 
1361
Function le64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
 
1362
Begin
 
1363
 
 
1364
    le64:= flag( a0 < b0 ) or flag( ( a0 = b0 ) and ( a1 <= b1 ) );
 
1365
 
 
1366
End;
 
1367
 
 
1368
{*
 
1369
-------------------------------------------------------------------------------
 
1370
Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
 
1371
than the 64-bit value formed by concatenating `b0' and `b1'.  Otherwise,
 
1372
returns 0.
 
1373
-------------------------------------------------------------------------------
 
1374
*}
 
1375
Function lt64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
 
1376
Begin
 
1377
    lt64 := flag( a0 < b0 ) or flag( ( a0 = b0 ) and ( a1 < b1 ) );
 
1378
End;
 
1379
 
 
1380
{*
 
1381
-------------------------------------------------------------------------------
 
1382
Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is not
 
1383
equal to the 64-bit value formed by concatenating `b0' and `b1'.  Otherwise,
 
1384
returns 0.
 
1385
-------------------------------------------------------------------------------
 
1386
*}
 
1387
Function ne64( a0: bits32; a1:bits32 ;b0:bits32; b1:bits32 ): flag;
 
1388
Begin
 
1389
    ne64:= flag( a0 <> b0 ) or flag( a1 <> b1 );
 
1390
End;
 
1391
 
 
1392
(*****************************************************************************)
 
1393
(*                      End Low-Level arithmetic                             *)
 
1394
(*****************************************************************************)
 
1395
 
 
1396
 
 
1397
 
 
1398
{*
 
1399
-------------------------------------------------------------------------------
 
1400
Functions and definitions to determine:  (1) whether tininess for underflow
 
1401
is detected before or after rounding by default, (2) what (if anything)
 
1402
happens when exceptions are raised, (3) how signaling NaNs are distinguished
 
1403
from quiet NaNs, (4) the default generated quiet NaNs, and (4) how NaNs
 
1404
are propagated from function inputs to output.  These details are ENDIAN
 
1405
specific
 
1406
-------------------------------------------------------------------------------
 
1407
*}
 
1408
{$IFDEF ENDIAN_LITTLE}
 
1409
{*
 
1410
-------------------------------------------------------------------------------
 
1411
Internal canonical NaN format.
 
1412
-------------------------------------------------------------------------------
 
1413
*}
 
1414
TYPE
 
1415
 commonNaNT = packed record
 
1416
   sign: flag;
 
1417
   high, low : bits32;
 
1418
 end;
 
1419
{*
 
1420
-------------------------------------------------------------------------------
 
1421
The pattern for a default generated single-precision NaN.
 
1422
-------------------------------------------------------------------------------
 
1423
*}
 
1424
const float32_default_nan = $FFC00000;
 
1425
 
 
1426
{*
 
1427
-------------------------------------------------------------------------------
 
1428
Returns 1 if the single-precision floating-point value `a' is a NaN;
 
1429
otherwise returns 0.
 
1430
-------------------------------------------------------------------------------
 
1431
*}
 
1432
Function float32_is_nan( a : float32 ): flag;
 
1433
Begin
 
1434
 
 
1435
    float32_is_nan:= flag( $FF000000 < bits32 ( a shl 1 ) );
 
1436
 
 
1437
End;
 
1438
 
 
1439
{*
 
1440
-------------------------------------------------------------------------------
 
1441
Returns 1 if the single-precision floating-point value `a' is a signaling
 
1442
NaN; otherwise returns 0.
 
1443
-------------------------------------------------------------------------------
 
1444
*}
 
1445
Function float32_is_signaling_nan( a : float32  ): flag;
 
1446
Begin
 
1447
 
 
1448
    float32_is_signaling_nan := flag
 
1449
      ( ( ( a shr 22 ) and $1FF ) = $1FE ) and( a and $003FFFFF );
 
1450
 
 
1451
End;
 
1452
 
 
1453
{*
 
1454
-------------------------------------------------------------------------------
 
1455
Returns the result of converting the single-precision floating-point NaN
 
1456
`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
 
1457
exception is raised.
 
1458
-------------------------------------------------------------------------------
 
1459
*}
 
1460
Procedure float32ToCommonNaN( a: float32; VAR c:commonNaNT  );
 
1461
var
 
1462
    z : commonNaNT ;
 
1463
Begin
 
1464
    if ( float32_is_signaling_nan( a ) <> 0) then
 
1465
       float_raise( float_flag_invalid );
 
1466
    z.sign := a shr 31;
 
1467
    z.low := 0;
 
1468
    z.high := a shl 9;
 
1469
    c := z;
 
1470
 
 
1471
End;
 
1472
 
 
1473
{*
 
1474
-------------------------------------------------------------------------------
 
1475
Returns the result of converting the canonical NaN `a' to the single-
 
1476
precision floating-point format.
 
1477
-------------------------------------------------------------------------------
 
1478
*}
 
1479
Function commonNaNToFloat32( a : commonNaNT ): float32;
 
1480
Begin
 
1481
    commonNaNToFloat32 := ( ( bits32 (a.sign) ) shl 31 ) or $7FC00000 or ( a.high shr 9 );
 
1482
End;
 
1483
 
 
1484
{*
 
1485
-------------------------------------------------------------------------------
 
1486
Takes two single-precision floating-point values `a' and `b', one of which
 
1487
is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
 
1488
signaling NaN, the invalid exception is raised.
 
1489
-------------------------------------------------------------------------------
 
1490
*}
 
1491
Function propagateFloat32NaN( a : float32 ; b: float32 ): float32;
 
1492
Var
 
1493
    aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
 
1494
label returnLargerSignificand;
 
1495
Begin
 
1496
    aIsNaN := float32_is_nan( a );
 
1497
    aIsSignalingNaN := float32_is_signaling_nan( a );
 
1498
    bIsNaN := float32_is_nan( b );
 
1499
    bIsSignalingNaN := float32_is_signaling_nan( b );
 
1500
    a := a or $00400000;
 
1501
    b := b or $00400000;
 
1502
    if ( aIsSignalingNaN or bIsSignalingNaN ) <> 0 then
 
1503
        float_raise( float_flag_invalid );
 
1504
    if ( aIsSignalingNaN )<> 0  then
 
1505
    Begin
 
1506
        if ( bIsSignalingNaN ) <>  0 then
 
1507
          goto returnLargerSignificand;
 
1508
        if bIsNan <> 0 then
 
1509
          propagateFloat32NaN := b
 
1510
        else
 
1511
          propagateFloat32NaN := a;
 
1512
        exit;
 
1513
    End
 
1514
    else if ( aIsNaN <> 0) then
 
1515
    Begin
 
1516
        if ( bIsSignalingNaN or not bIsNaN )<> 0 then
 
1517
        Begin
 
1518
           propagateFloat32NaN := a;
 
1519
           exit;
 
1520
        End;
 
1521
 returnLargerSignificand:
 
1522
        if ( bits32 ( a shl 1 ) < bits32 ( b shl 1 ) ) then
 
1523
        Begin
 
1524
           propagateFloat32NaN := b;
 
1525
           exit;
 
1526
        End;
 
1527
        if ( bits32 ( b shl 1 ) < bits32 ( a shl 1 ) ) then
 
1528
        Begin
 
1529
           propagateFloat32NaN :=  a;
 
1530
        End;
 
1531
        if a < b then
 
1532
          propagateFloat32NaN := a
 
1533
        else
 
1534
          propagateFloat32NaN := b;
 
1535
        exit;
 
1536
    End
 
1537
    else
 
1538
    Begin
 
1539
        propagateFloat32NaN := b;
 
1540
        exit;
 
1541
    End;
 
1542
 
 
1543
End;
 
1544
 
 
1545
{*
 
1546
-------------------------------------------------------------------------------
 
1547
The pattern for a default generated double-precision NaN.  The `high' and
 
1548
`low' values hold the most- and least-significant bits, respectively.
 
1549
-------------------------------------------------------------------------------
 
1550
*}
 
1551
const
 
1552
    float64_default_nan_high = $FFF80000;
 
1553
    float64_default_nan_low  = $00000000;
 
1554
 
 
1555
{*
 
1556
-------------------------------------------------------------------------------
 
1557
Returns 1 if the double-precision floating-point value `a' is a NaN;
 
1558
otherwise returns 0.
 
1559
-------------------------------------------------------------------------------
 
1560
*}
 
1561
Function float64_is_nan( a : float64 ) : flag;
 
1562
Begin
 
1563
 
 
1564
    float64_is_nan :=
 
1565
           flag( $FFE00000 <= bits32 ( a.high shl 1 ) )
 
1566
        and ( a.low or ( a.high and $000FFFFF ) );
 
1567
 
 
1568
End;
 
1569
 
 
1570
{*
 
1571
-------------------------------------------------------------------------------
 
1572
Returns 1 if the double-precision floating-point value `a' is a signaling
 
1573
NaN; otherwise returns 0.
 
1574
-------------------------------------------------------------------------------
 
1575
*}
 
1576
Function float64_is_signaling_nan( a : float64 ): flag;
 
1577
Begin
 
1578
 
 
1579
    float64_is_signaling_nan :=
 
1580
           flag( ( ( a.high shr 19 ) and $FFF ) = $FFE )
 
1581
        and ( a.low or ( a.high and $0007FFFF ) );
 
1582
End;
 
1583
 
 
1584
{*
 
1585
-------------------------------------------------------------------------------
 
1586
Returns the result of converting the double-precision floating-point NaN
 
1587
`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
 
1588
exception is raised.
 
1589
-------------------------------------------------------------------------------
 
1590
*}
 
1591
Procedure float64ToCommonNaN( a : float64; VAR c:commonNaNT );
 
1592
Var
 
1593
    z : commonNaNT;
 
1594
Begin
 
1595
    if ( float64_is_signaling_nan( a )<>0 ) then
 
1596
        float_raise( float_flag_invalid );
 
1597
    z.sign := a.high shr 31;
 
1598
    shortShift64Left( a.high, a.low, 12, z.high, z.low );
 
1599
    c := z;
 
1600
 
 
1601
End;
 
1602
 
 
1603
{*
 
1604
-------------------------------------------------------------------------------
 
1605
Returns the result of converting the canonical NaN `a' to the double-
 
1606
precision floating-point format.
 
1607
-------------------------------------------------------------------------------
 
1608
*}
 
1609
Procedure commonNaNToFloat64( a : commonNaNT; VAR c: float64  );
 
1610
Var
 
1611
    z: float64;
 
1612
Begin
 
1613
    shift64Right( a.high, a.low, 12, z.high, z.low );
 
1614
    z.high := z.high or ( ( bits32 (a.sign) ) shl 31 ) or $7FF80000;
 
1615
    c := z;
 
1616
End;
 
1617
 
 
1618
{*
 
1619
-------------------------------------------------------------------------------
 
1620
Takes two double-precision floating-point values `a' and `b', one of which
 
1621
is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
 
1622
signaling NaN, the invalid exception is raised.
 
1623
-------------------------------------------------------------------------------
 
1624
*}
 
1625
Procedure propagateFloat64NaN( a: float64; b: float64 ; VAR c: float64 );
 
1626
Var
 
1627
    aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
 
1628
    label returnLargerSignificand;
 
1629
Begin
 
1630
    aIsNaN := float64_is_nan( a );
 
1631
    aIsSignalingNaN := float64_is_signaling_nan( a );
 
1632
    bIsNaN := float64_is_nan( b );
 
1633
    bIsSignalingNaN := float64_is_signaling_nan( b );
 
1634
    a.high := a.high or $00080000;
 
1635
    b.high := b.high or $00080000;
 
1636
    if ( aIsSignalingNaN or bIsSignalingNaN )<> 0 then
 
1637
        float_raise( float_flag_invalid );
 
1638
    if ( aIsSignalingNaN )<>0 then
 
1639
    Begin
 
1640
        if ( bIsSignalingNaN )<>0 then
 
1641
            goto returnLargerSignificand;
 
1642
        if bIsNan <> 0 then
 
1643
           c := b
 
1644
        else
 
1645
           c := a;
 
1646
        exit;
 
1647
    End
 
1648
    else if ( aIsNaN )<> 0 then
 
1649
    Begin
 
1650
        if ( bIsSignalingNaN or not bIsNaN ) <> 0 then
 
1651
        Begin
 
1652
          c := a;
 
1653
           exit;
 
1654
        End;
 
1655
 returnLargerSignificand:
 
1656
        if ( lt64( a.high shl 1, a.low, b.high shl 1, b.low ) ) <> 0 then
 
1657
        Begin
 
1658
           c := b;
 
1659
           exit;
 
1660
        End;
 
1661
        if ( lt64( b.high shl 1, b.low, a.high shl 1, a.low ) ) <> 0 then
 
1662
        Begin
 
1663
           c := a;
 
1664
           exit;
 
1665
        End;
 
1666
        if a.high < b.high then
 
1667
         c := a
 
1668
        else
 
1669
         c := b;
 
1670
        exit;
 
1671
    End
 
1672
    else
 
1673
    Begin
 
1674
        c := b;
 
1675
        exit;
 
1676
    End;
 
1677
End;
 
1678
 
 
1679
{*----------------------------------------------------------------------------
 
1680
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
 
1681
| than the 128-bit value formed by concatenating `b0' and `b1'.  Otherwise,
 
1682
| returns 0.
 
1683
*----------------------------------------------------------------------------*}
 
1684
 
 
1685
function lt128(a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;
 
1686
begin
 
1687
    result := ord(( a0 < b0 ) or ( ( a0 = b0 ) and ( a1 < b1 ) ));
 
1688
end;
 
1689
 
 
1690
{*----------------------------------------------------------------------------
 
1691
| Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
 
1692
| otherwise returns 0.
 
1693
*----------------------------------------------------------------------------*}
 
1694
 
 
1695
function float128_is_nan( a : float128): flag;
 
1696
begin
 
1697
    result:= ord(( int64( $FFFE000000000000 ) <= bits64( a.high shl 1 ) )
 
1698
        and ( (a.low<>0) or (( a.high and int64( $0000FFFFFFFFFFFF ) )<>0 ) ));
 
1699
end;
 
1700
 
 
1701
{*----------------------------------------------------------------------------
 
1702
| Returns 1 if the quadruple-precision floating-point value `a' is a
 
1703
| signaling NaN; otherwise returns 0.
 
1704
*----------------------------------------------------------------------------*}
 
1705
 
 
1706
function float128_is_signaling_nan( a : float128): flag;
 
1707
begin
 
1708
    result:=ord(( ( ( a.high shr 47 ) and $FFFF ) = $FFFE ) and
 
1709
        ( (a.low<>0) or (( a.high and int64( $00007FFFFFFFFFFF ) )<>0) ));
 
1710
end;
 
1711
 
 
1712
{*----------------------------------------------------------------------------
 
1713
| Returns the result of converting the quadruple-precision floating-point NaN
 
1714
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
 
1715
| exception is raised.
 
1716
*----------------------------------------------------------------------------*}
 
1717
 
 
1718
function float128ToCommonNaN( a : float128): commonNaNT;
 
1719
var
 
1720
    z: commonNaNT;
 
1721
    qhigh,qlow : qword;
 
1722
begin
 
1723
    if ( float128_is_signaling_nan( a )<>0)  then
 
1724
      float_raise( float_flag_invalid );
 
1725
    z.sign := a.high shr 63;
 
1726
    shortShift128Left( a.high, a.low, 16, qhigh, qlow );
 
1727
    z.high:=qhigh shr 32;
 
1728
    z.low:=qhigh and $ffffffff;
 
1729
    result:=z;
 
1730
end;
 
1731
 
 
1732
{*----------------------------------------------------------------------------
 
1733
| Returns the result of converting the canonical NaN `a' to the quadruple-
 
1734
| precision floating-point format.
 
1735
*----------------------------------------------------------------------------*}
 
1736
 
 
1737
function commonNaNToFloat128( a : commonNaNT): float128;
 
1738
var
 
1739
    z: float128;
 
1740
begin
 
1741
    shift128Right( a.high, a.low, 16, z.high, z.low );
 
1742
    z.high := z.high or ( ( bits64(a.sign) ) shl 63 ) or int64( $7FFF800000000000 );
 
1743
    result:=z;
 
1744
end;
 
1745
 
 
1746
{*----------------------------------------------------------------------------
 
1747
| Takes two quadruple-precision floating-point values `a' and `b', one of
 
1748
| which is a NaN, and returns the appropriate NaN result.  If either `a' or
 
1749
| `b' is a signaling NaN, the invalid exception is raised.
 
1750
*----------------------------------------------------------------------------*}
 
1751
 
 
1752
function propagateFloat128NaN( a: float128; b : float128): float128;
 
1753
var
 
1754
    aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
 
1755
label
 
1756
    returnLargerSignificand;
 
1757
begin
 
1758
    aIsNaN := float128_is_nan( a );
 
1759
    aIsSignalingNaN := float128_is_signaling_nan( a );
 
1760
    bIsNaN := float128_is_nan( b );
 
1761
    bIsSignalingNaN := float128_is_signaling_nan( b );
 
1762
    a.high := a.high or int64( $0000800000000000 );
 
1763
    b.high := b.high or int64( $0000800000000000 );
 
1764
    if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then
 
1765
       float_raise( float_flag_invalid );
 
1766
    if ( aIsSignalingNaN )<>0 then
 
1767
    begin
 
1768
        if ( bIsSignalingNaN )<>0 then
 
1769
          goto returnLargerSignificand;
 
1770
        if bIsNaN<>0 then
 
1771
          result := b
 
1772
        else
 
1773
          result := a;
 
1774
        exit;
 
1775
    end
 
1776
    else if ( aIsNaN )<>0 then
 
1777
    begin
 
1778
        if ( bIsSignalingNaN or not( bIsNaN) )<>0 then
 
1779
          begin
 
1780
                result := a;
 
1781
                exit;
 
1782
          end;
 
1783
 returnLargerSignificand:
 
1784
        if ( lt128( a.high shl 1, a.low, b.high shl 1, b.low ) )<>0 then
 
1785
          begin
 
1786
                result := b;
 
1787
                exit;
 
1788
          end;
 
1789
        if ( lt128( b.high shl 1, b.low, a.high shl 1, a.low ) )<>0 then
 
1790
          begin
 
1791
                result := a;
 
1792
                exit
 
1793
          end;
 
1794
        if ( a.high < b.high ) then
 
1795
          result := a
 
1796
        else
 
1797
          result := b;
 
1798
        exit;
 
1799
    end
 
1800
    else
 
1801
    result:=b;
 
1802
end;
 
1803
 
 
1804
 
 
1805
{$ELSE}
 
1806
 
 
1807
{ Big endian code }
 
1808
(*----------------------------------------------------------------------------
 
1809
| Internal canonical NaN format.
 
1810
*----------------------------------------------------------------------------*)
 
1811
type
 
1812
 commonNANT = packed record
 
1813
  sign : flag;
 
1814
  high, low : bits32;
 
1815
 end;
 
1816
 
 
1817
(*----------------------------------------------------------------------------
 
1818
| The pattern for a default generated single-precision NaN.
 
1819
*----------------------------------------------------------------------------*)
 
1820
const float32_default_nan = $7FFFFFFF;
 
1821
 
 
1822
(*----------------------------------------------------------------------------
 
1823
| Returns 1 if the single-precision floating-point value `a' is a NaN;
 
1824
| otherwise returns 0.
 
1825
*----------------------------------------------------------------------------*)
 
1826
function float32_is_nan(a:  float32): flag;
 
1827
begin
 
1828
    float32_is_nan := flag( $FF000000 < bits32( a shl 1 ) );
 
1829
end;
 
1830
 
 
1831
(*----------------------------------------------------------------------------
 
1832
| Returns 1 if the single-precision floating-point value `a' is a signaling
 
1833
| NaN; otherwise returns 0.
 
1834
*----------------------------------------------------------------------------*)
 
1835
function float32_is_signaling_nan(a: float32):flag;
 
1836
 begin
 
1837
   float32_is_signaling_nan := flag( ( ( a shr 22 ) and $1FF ) = $1FE ) and flag( boolean((a and $003FFFFF)<>0) );
 
1838
 end;
 
1839
 
 
1840
(*----------------------------------------------------------------------------
 
1841
| Returns the result of converting the single-precision floating-point NaN
 
1842
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
 
1843
| exception is raised.
 
1844
*----------------------------------------------------------------------------*)
 
1845
Procedure float32ToCommonNaN( a: float32; VAR c:commonNaNT  );
 
1846
 var
 
1847
  z: commonNANT;
 
1848
 begin
 
1849
   if float32_is_signaling_nan(a)<>0 then
 
1850
      float_raise(float_flag_invalid);
 
1851
   z.sign := a shr 31;
 
1852
   z.low := 0;
 
1853
   z.high := a shl 9;
 
1854
   c:=z;
 
1855
 end;
 
1856
 
 
1857
(*----------------------------------------------------------------------------
 
1858
| Returns the result of converting the canonical NaN `a' to the single-
 
1859
| precision floating-point format.
 
1860
*----------------------------------------------------------------------------*)
 
1861
function CommonNanToFloat32(a : CommonNaNT): float32;
 
1862
 begin
 
1863
    CommonNanToFloat32:= ( ( bits32( a.sign )) shl 31 ) OR $7FC00000 OR ( a.high shr 9 );
 
1864
 end;
 
1865
 
 
1866
(*----------------------------------------------------------------------------
 
1867
| Takes two single-precision floating-point values `a' and `b', one of which
 
1868
| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
 
1869
| signaling NaN, the invalid exception is raised.
 
1870
*----------------------------------------------------------------------------*)
 
1871
function  propagateFloat32NaN( a: float32 ; b: float32): float32;
 
1872
 var
 
1873
  aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN: flag;
 
1874
 begin
 
1875
    aIsNaN := float32_is_nan( a );
 
1876
    aIsSignalingNaN := float32_is_signaling_nan( a );
 
1877
    bIsNaN := float32_is_nan( b );
 
1878
    bIsSignalingNaN := float32_is_signaling_nan( b );
 
1879
    a := a or $00400000;
 
1880
    b := b or $00400000;
 
1881
    if ( aIsSignalingNaN or bIsSignalingNaN )<>0 then
 
1882
       float_raise( float_flag_invalid );
 
1883
    if bIsSignalingNaN<>0 then
 
1884
        propagateFloat32Nan := b
 
1885
    else if aIsSignalingNan<>0 then
 
1886
        propagateFloat32Nan := a
 
1887
    else if bIsNan<>0 then
 
1888
        propagateFloat32Nan := b
 
1889
    else
 
1890
        propagateFloat32Nan := a;
 
1891
 end;
 
1892
 
 
1893
 
 
1894
(*----------------------------------------------------------------------------
 
1895
| The pattern for a default generated double-precision NaN.  The `high' and
 
1896
| `low' values hold the most- and least-significant bits, respectively.
 
1897
*----------------------------------------------------------------------------*)
 
1898
const
 
1899
    float64_default_nan_high = $7FFFFFFF;
 
1900
    float64_default_nan_low  = $FFFFFFFF;
 
1901
 
 
1902
(*----------------------------------------------------------------------------
 
1903
| Returns 1 if the double-precision floating-point value `a' is a NaN;
 
1904
| otherwise returns 0.
 
1905
*----------------------------------------------------------------------------*)
 
1906
 
 
1907
function float64_is_nan(a: float64): flag;
 
1908
 begin
 
1909
    float64_is_nan := flag (
 
1910
           ( $FFE00000 <= bits32 ( a.high shl 1 ) )
 
1911
        and ( (a.low<>0) or (( a.high and $000FFFFF )<>0) ));
 
1912
 end;
 
1913
 
 
1914
(*----------------------------------------------------------------------------
 
1915
| Returns 1 if the double-precision floating-point value `a' is a signaling
 
1916
| NaN; otherwise returns 0.
 
1917
*----------------------------------------------------------------------------*)
 
1918
function float64_is_signaling_nan( a:float64): flag;
 
1919
 begin
 
1920
    float64_is_signaling_nan := flag(
 
1921
           ( ( ( a.high shr 19 ) and $FFF ) = $FFE )
 
1922
        and ( (a.low<>0) or ( ( a.high and $0007FFFF )<>0) ));
 
1923
 
 
1924
 end;
 
1925
 
 
1926
(*----------------------------------------------------------------------------
 
1927
| Returns the result of converting the double-precision floating-point NaN
 
1928
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
 
1929
| exception is raised.
 
1930
*----------------------------------------------------------------------------*)
 
1931
Procedure float64ToCommonNaN( a : float64; VAR c:commonNaNT );
 
1932
 var
 
1933
   z : commonNaNT;
 
1934
 begin
 
1935
    if ( float64_is_signaling_nan( a )<>0 ) then
 
1936
        float_raise( float_flag_invalid );
 
1937
    z.sign := a.high shr 31;
 
1938
    shortShift64Left( a.high, a.low, 12, z.high, z.low );
 
1939
    c:=z;
 
1940
 end;
 
1941
 
 
1942
(*----------------------------------------------------------------------------
 
1943
| Returns the result of converting the canonical NaN `a' to the double-
 
1944
| precision floating-point format.
 
1945
*----------------------------------------------------------------------------*)
 
1946
Procedure commonNaNToFloat64( a : commonNaNT; VAR c: float64  );
 
1947
 var
 
1948
  z: float64;
 
1949
 begin
 
1950
    shift64Right( a.high, a.low, 12, z.high, z.low );
 
1951
    z.high := z.high or ( ( bits32 (a.sign) ) shl 31 ) or $7FF80000;
 
1952
    c:=z;
 
1953
 end;
 
1954
 
 
1955
(*----------------------------------------------------------------------------
 
1956
| Takes two double-precision floating-point values `a' and `b', one of which
 
1957
| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
 
1958
| signaling NaN, the invalid exception is raised.
 
1959
*----------------------------------------------------------------------------*)
 
1960
Procedure propagateFloat64NaN( a: float64; b: float64 ; VAR c: float64 );
 
1961
var
 
1962
 aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN : flag;
 
1963
 begin
 
1964
    aIsNaN := float64_is_nan( a );
 
1965
    aIsSignalingNaN := float64_is_signaling_nan( a );
 
1966
    bIsNaN := float64_is_nan( b );
 
1967
    bIsSignalingNaN := float64_is_signaling_nan( b );
 
1968
    a.high := a.high or $00080000;
 
1969
    b.high := b.high or $00080000;
 
1970
    if ( (aIsSignalingNaN<>0) or (bIsSignalingNaN<>0) ) then
 
1971
       float_raise( float_flag_invalid );
 
1972
    if bIsSignalingNaN<>0 then
 
1973
        c := b
 
1974
    else if aIsSignalingNan<>0 then
 
1975
        c := a
 
1976
    else if bIsNan<>0 then
 
1977
        c := b
 
1978
    else
 
1979
        c := a;
 
1980
 end;
 
1981
 
 
1982
{$ENDIF}
 
1983
 
 
1984
(****************************************************************************)
 
1985
(*                        END ENDIAN SPECIFIC CODE                          *)
 
1986
(****************************************************************************)
 
1987
 
 
1988
 
 
1989
{*
 
1990
-------------------------------------------------------------------------------
 
1991
Returns the fraction bits of the single-precision floating-point value `a'.
 
1992
-------------------------------------------------------------------------------
 
1993
*}
 
1994
Function ExtractFloat32Frac(a : Float32) : Bits32;
 
1995
 Begin
 
1996
    ExtractFloat32Frac := A AND $007FFFFF;
 
1997
 End;
 
1998
 
 
1999
 
 
2000
{*
 
2001
-------------------------------------------------------------------------------
 
2002
Returns the exponent bits of the single-precision floating-point value `a'.
 
2003
-------------------------------------------------------------------------------
 
2004
*}
 
2005
Function extractFloat32Exp( a: float32 ): Int16;
 
2006
  Begin
 
2007
    extractFloat32Exp := (a shr 23) AND $FF;
 
2008
  End;
 
2009
 
 
2010
{*
 
2011
-------------------------------------------------------------------------------
 
2012
Returns the sign bit of the single-precision floating-point value `a'.
 
2013
-------------------------------------------------------------------------------
 
2014
*}
 
2015
Function extractFloat32Sign( a: float32 ): Flag;
 
2016
  Begin
 
2017
    extractFloat32Sign := a shr 31;
 
2018
  End;
 
2019
 
 
2020
{*
 
2021
-------------------------------------------------------------------------------
 
2022
Normalizes the subnormal single-precision floating-point value represented
 
2023
by the denormalized significand `aSig'.  The normalized exponent and
 
2024
significand are stored at the locations pointed to by `zExpPtr' and
 
2025
`zSigPtr', respectively.
 
2026
-------------------------------------------------------------------------------
 
2027
*}
 
2028
Procedure normalizeFloat32Subnormal( aSig : bits32; VAR zExpPtr: Int16; VAR zSigPtr :bits32);
 
2029
 Var
 
2030
   ShiftCount : BYTE;
 
2031
 Begin
 
2032
 
 
2033
    shiftCount := countLeadingZeros32( aSig ) - 8;
 
2034
    zSigPtr := aSig shl shiftCount;
 
2035
    zExpPtr := 1 - shiftCount;
 
2036
  End;
 
2037
 
 
2038
{*
 
2039
-------------------------------------------------------------------------------
 
2040
Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
 
2041
single-precision floating-point value, returning the result.  After being
 
2042
shifted into the proper positions, the three fields are simply added
 
2043
together to form the result.  This means that any integer portion of `zSig'
 
2044
will be added into the exponent.  Since a properly normalized significand
 
2045
will have an integer portion equal to 1, the `zExp' input should be 1 less
 
2046
than the desired result exponent whenever `zSig' is a complete, normalized
 
2047
significand.
 
2048
-------------------------------------------------------------------------------
 
2049
*}
 
2050
Function packFloat32( zSign: Flag; zExp : Int16; zSig: Bits32 ): Float32;
 
2051
 Begin
 
2052
 
 
2053
    packFloat32 := ( ( bits32( zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 23 )
 
2054
      + zSig;
 
2055
 End;
 
2056
 
 
2057
{*
 
2058
-------------------------------------------------------------------------------
 
2059
Takes an abstract floating-point value having sign `zSign', exponent `zExp',
 
2060
and significand `zSig', and returns the proper single-precision floating-
 
2061
point value corresponding to the abstract input.  Ordinarily, the abstract
 
2062
value is simply rounded and packed into the single-precision format, with
 
2063
the inexact exception raised if the abstract input cannot be represented
 
2064
exactly.  However, if the abstract value is too large, the overflow and
 
2065
inexact exceptions are raised and an infinity or maximal finite value is
 
2066
returned.  If the abstract value is too small, the input value is rounded to
 
2067
a subnormal number, and the underflow and inexact exceptions are raised if
 
2068
the abstract input cannot be represented exactly as a subnormal single-
 
2069
precision floating-point number.
 
2070
    The input significand `zSig' has its binary point between bits 30
 
2071
and 29, which is 7 bits to the left of the usual location.  This shifted
 
2072
significand must be normalized or smaller.  If `zSig' is not normalized,
 
2073
`zExp' must be 0; in that case, the result returned is a subnormal number,
 
2074
and it must not require rounding.  In the usual case that `zSig' is
 
2075
normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
 
2076
The handling of underflow and overflow follows the IEC/IEEE Standard for
 
2077
Binary Floating-Point Arithmetic.
 
2078
-------------------------------------------------------------------------------
 
2079
*}
 
2080
Function roundAndPackFloat32( zSign : Flag; zExp : Int16; zSig : Bits32 ) : float32;
 
2081
 Var
 
2082
   roundingMode : BYTE;
 
2083
   roundNearestEven : Flag;
 
2084
   roundIncrement, roundBits : BYTE;
 
2085
   IsTiny : Flag;
 
2086
 Begin
 
2087
    roundingMode := float_rounding_mode;
 
2088
    if (roundingMode = float_round_nearest_even) then
 
2089
      Begin
 
2090
        roundNearestEven := Flag(TRUE);
 
2091
      end
 
2092
    else
 
2093
       roundNearestEven := Flag(FALSE);
 
2094
    roundIncrement := $40;
 
2095
    if ( Boolean(roundNearestEven)  = FALSE)  then
 
2096
      Begin
 
2097
        if ( roundingMode = float_round_to_zero ) Then
 
2098
          Begin
 
2099
            roundIncrement := 0;
 
2100
          End
 
2101
        else
 
2102
          Begin
 
2103
            roundIncrement := $7F;
 
2104
            if ( zSign <> 0 ) then
 
2105
              Begin
 
2106
                if roundingMode = float_round_up then roundIncrement := 0;
 
2107
              End
 
2108
            else
 
2109
              Begin
 
2110
                if roundingMode = float_round_down then roundIncrement := 0;
 
2111
              End;
 
2112
         End
 
2113
      End;
 
2114
    roundBits := zSig AND $7F;
 
2115
    if ($FD <= bits16 (zExp) ) then
 
2116
     Begin
 
2117
        if (( $FD < zExp ) OR  ( zExp = $FD ) AND ( sbits32 ( zSig + roundIncrement ) < 0 ) ) then
 
2118
          Begin
 
2119
             float_raise( float_flag_overflow OR float_flag_inexact );
 
2120
             roundAndPackFloat32:=packFloat32( zSign, $FF, 0 ) - Flag( roundIncrement = 0 );
 
2121
             exit;
 
2122
          End;
 
2123
        if ( zExp < 0 ) then
 
2124
          Begin
 
2125
            isTiny :=
 
2126
                   flag(( float_detect_tininess = float_tininess_before_rounding )
 
2127
                OR ( zExp < -1 )
 
2128
                OR ( (zSig + roundIncrement) < $80000000 ));
 
2129
            shift32RightJamming( zSig, - zExp, zSig );
 
2130
            zExp := 0;
 
2131
            roundBits := zSig AND $7F;
 
2132
            if ( (isTiny = flag(TRUE)) and (roundBits<>0) ) then
 
2133
               float_raise( float_flag_underflow );
 
2134
          End;
 
2135
    End;
 
2136
    if ( roundBits )<> 0 then
 
2137
       softfloat_exception_flags := float_flag_inexact OR softfloat_exception_flags;
 
2138
    zSig := ( zSig + roundIncrement ) shr 7;
 
2139
    zSig := zSig AND not bits32( bits32( ( roundBits XOR $40 ) = 0 ) and roundNearestEven );
 
2140
    if ( zSig = 0 ) then zExp := 0;
 
2141
    roundAndPackFloat32 := packFloat32( zSign, zExp, zSig );
 
2142
    exit;
 
2143
  End;
 
2144
 
 
2145
{*
 
2146
-------------------------------------------------------------------------------
 
2147
Takes an abstract floating-point value having sign `zSign', exponent `zExp',
 
2148
and significand `zSig', and returns the proper single-precision floating-
 
2149
point value corresponding to the abstract input.  This routine is just like
 
2150
`roundAndPackFloat32' except that `zSig' does not have to be normalized.
 
2151
Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
 
2152
floating-point exponent.
 
2153
-------------------------------------------------------------------------------
 
2154
*}
 
2155
Function normalizeRoundAndPackFloat32( zSign: flag; zExp: int16; zSig:bits32 ): float32;
 
2156
  Var
 
2157
    ShiftCount : int8;
 
2158
  Begin
 
2159
    shiftCount := countLeadingZeros32( zSig ) - 1;
 
2160
    normalizeRoundAndPackFloat32 := roundAndPackFloat32( zSign, zExp - shiftCount, zSig shl shiftCount );
 
2161
  End;
 
2162
 
 
2163
{*
 
2164
-------------------------------------------------------------------------------
 
2165
Returns the most-significant 20 fraction bits of the double-precision
 
2166
floating-point value `a'.
 
2167
-------------------------------------------------------------------------------
 
2168
*}
 
2169
Function extractFloat64Frac0(a: float64): bits32;
 
2170
  Begin
 
2171
    extractFloat64Frac0 := a.high and $000FFFFF;
 
2172
  End;
 
2173
 
 
2174
{*
 
2175
-------------------------------------------------------------------------------
 
2176
Returns the least-significant 32 fraction bits of the double-precision
 
2177
floating-point value `a'.
 
2178
-------------------------------------------------------------------------------
 
2179
*}
 
2180
Function extractFloat64Frac1(a: float64): bits32;
 
2181
  Begin
 
2182
    extractFloat64Frac1 := a.low;
 
2183
  End;
 
2184
 
 
2185
{*
 
2186
-------------------------------------------------------------------------------
 
2187
Returns the exponent bits of the double-precision floating-point value `a'.
 
2188
-------------------------------------------------------------------------------
 
2189
*}
 
2190
Function extractFloat64Exp(a: float64): int16;
 
2191
 Begin
 
2192
    extractFloat64Exp:= ( a.high shr 20 ) AND $7FF;
 
2193
 End;
 
2194
 
 
2195
{*
 
2196
-------------------------------------------------------------------------------
 
2197
Returns the sign bit of the double-precision floating-point value `a'.
 
2198
-------------------------------------------------------------------------------
 
2199
*}
 
2200
Function extractFloat64Sign(a: float64) : flag;
 
2201
 Begin
 
2202
    extractFloat64Sign := a.high shr 31;
 
2203
 End;
 
2204
 
 
2205
{*
 
2206
-------------------------------------------------------------------------------
 
2207
Normalizes the subnormal double-precision floating-point value represented
 
2208
by the denormalized significand formed by the concatenation of `aSig0' and
 
2209
`aSig1'.  The normalized exponent is stored at the location pointed to by
 
2210
`zExpPtr'.  The most significant 21 bits of the normalized significand are
 
2211
stored at the location pointed to by `zSig0Ptr', and the least significant
 
2212
32 bits of the normalized significand are stored at the location pointed to
 
2213
by `zSig1Ptr'.
 
2214
-------------------------------------------------------------------------------
 
2215
*}
 
2216
Procedure normalizeFloat64Subnormal(
 
2217
     aSig0: bits32;
 
2218
     aSig1: bits32;
 
2219
     VAR zExpPtr : Int16;
 
2220
     VAR zSig0Ptr : Bits32;
 
2221
     VAR zSig1Ptr : Bits32
 
2222
 );
 
2223
 Var
 
2224
  ShiftCount : Int8;
 
2225
 Begin
 
2226
    if ( aSig0 = 0 ) then
 
2227
      Begin
 
2228
        shiftCount := countLeadingZeros32( aSig1 ) - 11;
 
2229
        if ( shiftCount < 0 ) then
 
2230
          Begin
 
2231
            zSig0Ptr := aSig1 shr ( - shiftCount );
 
2232
            zSig1Ptr := aSig1 shl ( shiftCount AND 31 );
 
2233
          End
 
2234
        else
 
2235
           Begin
 
2236
            zSig0Ptr := aSig1 shl shiftCount;
 
2237
            zSig1Ptr := 0;
 
2238
           End;
 
2239
        zExpPtr := - shiftCount - 31;
 
2240
      End
 
2241
    else
 
2242
      Begin
 
2243
        shiftCount := countLeadingZeros32( aSig0 ) - 11;
 
2244
        shortShift64Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
 
2245
        zExpPtr := 1 - shiftCount;
 
2246
      End;
 
2247
  End;
 
2248
 
 
2249
{*
 
2250
-------------------------------------------------------------------------------
 
2251
Packs the sign `zSign', the exponent `zExp', and the significand formed by
 
2252
the concatenation of `zSig0' and `zSig1' into a double-precision floating-
 
2253
point value, returning the result.  After being shifted into the proper
 
2254
positions, the three fields `zSign', `zExp', and `zSig0' are simply added
 
2255
together to form the most significant 32 bits of the result.  This means
 
2256
that any integer portion of `zSig0' will be added into the exponent.  Since
 
2257
a properly normalized significand will have an integer portion equal to 1,
 
2258
the `zExp' input should be 1 less than the desired result exponent whenever
 
2259
`zSig0' and `zSig1' concatenated form a complete, normalized significand.
 
2260
-------------------------------------------------------------------------------
 
2261
*}
 
2262
Procedure
 
2263
 packFloat64( zSign: Flag; zExp: Int16; zSig0: Bits32; zSig1 : Bits32; VAR c : float64);
 
2264
 var
 
2265
    z: Float64;
 
2266
 Begin
 
2267
 
 
2268
    z.low := zSig1;
 
2269
    z.high := ( ( bits32 (zSign) ) shl 31 ) + ( ( bits32 (zExp) ) shl 20 ) + zSig0;
 
2270
    c := z;
 
2271
 End;
 
2272
 
 
2273
 
 
2274
{*----------------------------------------------------------------------------
 
2275
| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
 
2276
| double-precision floating-point value, returning the result.  After being
 
2277
| shifted into the proper positions, the three fields are simply added
 
2278
| together to form the result.  This means that any integer portion of `zSig'
 
2279
| will be added into the exponent.  Since a properly normalized significand
 
2280
| will have an integer portion equal to 1, the `zExp' input should be 1 less
 
2281
| than the desired result exponent whenever `zSig' is a complete, normalized
 
2282
| significand.
 
2283
*----------------------------------------------------------------------------*}
 
2284
 
 
2285
function packFloat64( zSign: flag; zExp: int16; zSig : bits64): float64;inline;
 
2286
begin
 
2287
    result := float64(( ( bits64(zSign) ) shl 63 ) + ( ( bits64(zExp) ) shl 52 ) + zSig);
 
2288
end;
 
2289
 
 
2290
{*
 
2291
-------------------------------------------------------------------------------
 
2292
Takes an abstract floating-point value having sign `zSign', exponent `zExp',
 
2293
and extended significand formed by the concatenation of `zSig0', `zSig1',
 
2294
and `zSig2', and returns the proper double-precision floating-point value
 
2295
corresponding to the abstract input.  Ordinarily, the abstract value is
 
2296
simply rounded and packed into the double-precision format, with the inexact
 
2297
exception raised if the abstract input cannot be represented exactly.
 
2298
However, if the abstract value is too large, the overflow and inexact
 
2299
exceptions are raised and an infinity or maximal finite value is returned.
 
2300
If the abstract value is too small, the input value is rounded to a
 
2301
subnormal number, and the underflow and inexact exceptions are raised if the
 
2302
abstract input cannot be represented exactly as a subnormal double-precision
 
2303
floating-point number.
 
2304
    The input significand must be normalized or smaller.  If the input
 
2305
significand is not normalized, `zExp' must be 0; in that case, the result
 
2306
returned is a subnormal number, and it must not require rounding.  In the
 
2307
usual case that the input significand is normalized, `zExp' must be 1 less
 
2308
than the ``true'' floating-point exponent.  The handling of underflow and
 
2309
overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
2310
-------------------------------------------------------------------------------
 
2311
*}
 
2312
Procedure
 
2313
 roundAndPackFloat64(
 
2314
     zSign: Flag; zExp: Int16; zSig0: Bits32; zSig1: Bits32; zSig2: Bits32; Var c: Float64 );
 
2315
 Var
 
2316
   roundingMode : Int8;
 
2317
   roundNearestEven, increment, isTiny : Flag;
 
2318
 Begin
 
2319
 
 
2320
    roundingMode := float_rounding_mode;
 
2321
    roundNearestEven := flag( roundingMode = float_round_nearest_even );
 
2322
    increment := flag( sbits32 (zSig2) < 0 );
 
2323
    if ( roundNearestEven  = flag(FALSE) ) then
 
2324
      Begin
 
2325
        if ( roundingMode = float_round_to_zero ) then
 
2326
            increment := 0
 
2327
        else
 
2328
          Begin
 
2329
            if ( zSign )<> 0 then
 
2330
              Begin
 
2331
                increment := flag( roundingMode = float_round_down ) and zSig2;
 
2332
              End
 
2333
            else
 
2334
              Begin
 
2335
                increment := flag( roundingMode = float_round_up ) and zSig2;
 
2336
              End
 
2337
          End
 
2338
      End;
 
2339
    if ( $7FD <= bits16 (zExp) ) then
 
2340
      Begin
 
2341
        if (( $7FD < zExp )
 
2342
             or (( zExp = $7FD )
 
2343
                  and (eq64( $001FFFFF, $FFFFFFFF, zSig0, zSig1 )<>0)
 
2344
                  and (increment<>0)
 
2345
                )
 
2346
           ) then
 
2347
           Begin
 
2348
            float_raise( float_flag_overflow OR  float_flag_inexact );
 
2349
            if (( roundingMode = float_round_to_zero )
 
2350
                 or ( (zSign<>0) and ( roundingMode = float_round_up ) )
 
2351
                 or ( (zSign = 0) and ( roundingMode = float_round_down ) )
 
2352
               ) then
 
2353
              Begin
 
2354
                packFloat64( zSign, $7FE, $000FFFFF, $FFFFFFFF, c );
 
2355
                exit;
 
2356
              End;
 
2357
            packFloat64( zSign, $7FF, 0, 0, c );
 
2358
            exit;
 
2359
           End;
 
2360
        if ( zExp < 0 ) then
 
2361
           Begin
 
2362
            isTiny :=
 
2363
                   flag( float_detect_tininess = float_tininess_before_rounding )
 
2364
                or flag( zExp < -1 )
 
2365
                or  flag(increment = 0)
 
2366
                or flag(lt64( zSig0, zSig1, $001FFFFF, $FFFFFFFF)<>0);
 
2367
            shift64ExtraRightJamming(
 
2368
                zSig0, zSig1, zSig2, - zExp, zSig0, zSig1, zSig2 );
 
2369
            zExp := 0;
 
2370
            if ( isTiny<>0) and (zSig2<>0 ) then float_raise( float_flag_underflow );
 
2371
            if ( roundNearestEven )<>0 then
 
2372
              Begin
 
2373
                increment := flag( sbits32 (zSig2) < 0 );
 
2374
              End
 
2375
            else
 
2376
              Begin
 
2377
                if ( zSign )<>0 then
 
2378
                  Begin
 
2379
                    increment := flag( roundingMode = float_round_down ) and zSig2;
 
2380
                  End
 
2381
                else
 
2382
                  Begin
 
2383
                    increment := flag( roundingMode = float_round_up ) and zSig2;
 
2384
                  End
 
2385
              End;
 
2386
        End;
 
2387
    End;
 
2388
    if ( zSig2 )<>0 then
 
2389
       softfloat_exception_flags := softfloat_exception_flags OR  float_flag_inexact;
 
2390
    if ( increment )<>0 then
 
2391
      Begin
 
2392
        add64( zSig0, zSig1, 0, 1, zSig0, zSig1 );
 
2393
        zSig1 := zSig1 and not ( bits32(flag( zSig2 + zSig2 = 0 )) and roundNearestEven );
 
2394
      End
 
2395
    else
 
2396
      Begin
 
2397
        if ( ( zSig0 or zSig1 ) = 0 ) then zExp := 0;
 
2398
      End;
 
2399
    packFloat64( zSign, zExp, zSig0, zSig1, c );
 
2400
 End;
 
2401
 
 
2402
{*----------------------------------------------------------------------------
 
2403
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
 
2404
| and significand `zSig', and returns the proper double-precision floating-
 
2405
| point value corresponding to the abstract input.  Ordinarily, the abstract
 
2406
| value is simply rounded and packed into the double-precision format, with
 
2407
| the inexact exception raised if the abstract input cannot be represented
 
2408
| exactly.  However, if the abstract value is too large, the overflow and
 
2409
| inexact exceptions are raised and an infinity or maximal finite value is
 
2410
| returned.  If the abstract value is too small, the input value is rounded
 
2411
| to a subnormal number, and the underflow and inexact exceptions are raised
 
2412
| if the abstract input cannot be represented exactly as a subnormal double-
 
2413
| precision floating-point number.
 
2414
|     The input significand `zSig' has its binary point between bits 62
 
2415
| and 61, which is 10 bits to the left of the usual location.  This shifted
 
2416
| significand must be normalized or smaller.  If `zSig' is not normalized,
 
2417
| `zExp' must be 0; in that case, the result returned is a subnormal number,
 
2418
| and it must not require rounding.  In the usual case that `zSig' is
 
2419
| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
 
2420
| The handling of underflow and overflow follows the IEC/IEEE Standard for
 
2421
| Binary Floating-Point Arithmetic.
 
2422
*----------------------------------------------------------------------------*}
 
2423
 
 
2424
function roundAndPackFloat64( zSign: flag; zExp: int16; zSig : bits64): float64;
 
2425
var
 
2426
    roundingMode: int8;
 
2427
    roundNearestEven: flag;
 
2428
    roundIncrement, roundBits: int16;
 
2429
    isTiny: flag;
 
2430
begin
 
2431
    roundingMode := float_rounding_mode;
 
2432
    roundNearestEven := ord( roundingMode = float_round_nearest_even );
 
2433
    roundIncrement := $200;
 
2434
    if ( roundNearestEven=0 ) then
 
2435
    begin
 
2436
        if ( roundingMode = float_round_to_zero ) then
 
2437
        begin
 
2438
            roundIncrement := 0;
 
2439
        end
 
2440
        else begin
 
2441
            roundIncrement := $3FF;
 
2442
            if ( zSign<>0 ) then
 
2443
            begin
 
2444
                if ( roundingMode = float_round_up ) then
 
2445
                  roundIncrement := 0;
 
2446
            end
 
2447
            else begin
 
2448
                if ( roundingMode = float_round_down ) then
 
2449
                  roundIncrement := 0;
 
2450
            end
 
2451
        end
 
2452
    end;
 
2453
    roundBits := zSig and $3FF;
 
2454
    if ( $7FD <= bits16(zExp) ) then
 
2455
    begin
 
2456
        if (    ( $7FD < zExp )
 
2457
             or (    ( zExp = $7FD )
 
2458
                  and ( sbits64( zSig + roundIncrement ) < 0 ) )
 
2459
           ) then
 
2460
           begin
 
2461
            float_raise( float_flag_overflow or float_flag_inexact );
 
2462
            result := float64(qword(packFloat64( zSign, $7FF, 0 )) - ord( roundIncrement = 0 ));
 
2463
            exit;
 
2464
        end;
 
2465
        if ( zExp < 0 ) then
 
2466
        begin
 
2467
            isTiny := ord(
 
2468
                   ( float_detect_tininess = float_tininess_before_rounding )
 
2469
                or ( zExp < -1 )
 
2470
                or ( (zSig + roundIncrement) < int64( $8000000000000000 ) ) );
 
2471
            shift64RightJamming( zSig, - zExp, zSig );
 
2472
            zExp := 0;
 
2473
            roundBits := zSig and $3FF;
 
2474
            if ( isTiny and roundBits )<>0 then
 
2475
              float_raise( float_flag_underflow );
 
2476
        end
 
2477
    end;
 
2478
    if ( roundBits<>0 ) then
 
2479
      softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
2480
    zSig := ( zSig + roundIncrement ) shr 10;
 
2481
    zSig := zSig and not( ord( ( roundBits xor $200 ) = 0 ) and roundNearestEven );
 
2482
    if ( zSig = 0 ) then
 
2483
      zExp := 0;
 
2484
    result:=packFloat64( zSign, zExp, zSig );
 
2485
end;
 
2486
 
 
2487
{*
 
2488
-------------------------------------------------------------------------------
 
2489
Takes an abstract floating-point value having sign `zSign', exponent `zExp',
 
2490
and significand formed by the concatenation of `zSig0' and `zSig1', and
 
2491
returns the proper double-precision floating-point value corresponding
 
2492
to the abstract input.  This routine is just like `roundAndPackFloat64'
 
2493
except that the input significand has fewer bits and does not have to be
 
2494
normalized.  In all cases, `zExp' must be 1 less than the ``true'' floating-
 
2495
point exponent.
 
2496
-------------------------------------------------------------------------------
 
2497
*}
 
2498
Procedure
 
2499
 normalizeRoundAndPackFloat64(
 
2500
     zSign:flag; zExp:int16; zSig0:bits32; zSig1:bits32; VAR c: float64 );
 
2501
 Var
 
2502
   shiftCount : int8;
 
2503
   zSig2 : bits32;
 
2504
 Begin
 
2505
 
 
2506
    if ( zSig0 = 0 ) then
 
2507
     Begin
 
2508
        zSig0 := zSig1;
 
2509
        zSig1 := 0;
 
2510
        zExp := zExp -32;
 
2511
     End;
 
2512
    shiftCount := countLeadingZeros32( zSig0 ) - 11;
 
2513
    if ( 0 <= shiftCount ) then
 
2514
      Begin
 
2515
        zSig2 := 0;
 
2516
        shortShift64Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
 
2517
      End
 
2518
    else
 
2519
      Begin
 
2520
        shift64ExtraRightJamming
 
2521
          (zSig0, zSig1, 0, - shiftCount, zSig0, zSig1, zSig2 );
 
2522
      End;
 
2523
    zExp := zExp - shiftCount;
 
2524
    roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, c );
 
2525
  End;
 
2526
 
 
2527
{*
 
2528
-------------------------------------------------------------------------------
 
2529
Returns the result of converting the 32-bit two's complement integer `a' to
 
2530
the single-precision floating-point format.  The conversion is performed
 
2531
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
2532
-------------------------------------------------------------------------------
 
2533
*}
 
2534
Function int32_to_float32( a: int32): float32rec; compilerproc;
 
2535
 Var
 
2536
  zSign : Flag;
 
2537
 Begin
 
2538
 
 
2539
    if ( a = 0 ) then
 
2540
      Begin
 
2541
       int32_to_float32.float32 := 0;
 
2542
       exit;
 
2543
      End;
 
2544
    if ( a = sbits32 ($80000000) ) then
 
2545
      Begin
 
2546
       int32_to_float32.float32 := packFloat32( 1, $9E, 0 );
 
2547
       exit;
 
2548
      end;
 
2549
    zSign := flag( a < 0 );
 
2550
    If zSign<>0 then
 
2551
      a := -a;
 
2552
    int32_to_float32.float32:=
 
2553
      normalizeRoundAndPackFloat32( zSign, $9C, a );
 
2554
 End;
 
2555
 
 
2556
 
 
2557
{*
 
2558
-------------------------------------------------------------------------------
 
2559
Returns the result of converting the 32-bit two's complement integer `a' to
 
2560
the double-precision floating-point format.  The conversion is performed
 
2561
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
2562
-------------------------------------------------------------------------------
 
2563
*}
 
2564
Function int32_to_float64( a: int32) : float64;{$ifdef fpc} [public,Alias:'INT32_TO_FLOAT64'];compilerproc;{$endif}
 
2565
  var
 
2566
    zSign : flag;
 
2567
    absA : bits32;
 
2568
    shiftCount : int8;
 
2569
    zSig0, zSig1 : bits32;
 
2570
  Begin
 
2571
 
 
2572
    if ( a = 0 ) then
 
2573
      Begin
 
2574
       packFloat64( 0, 0, 0, 0, result );
 
2575
       exit;
 
2576
      end;
 
2577
    zSign := flag( a < 0 );
 
2578
    if ZSign<>0 then
 
2579
      AbsA := -a
 
2580
    else
 
2581
      AbsA := a;
 
2582
    shiftCount := countLeadingZeros32( absA ) - 11;
 
2583
    if ( 0 <= shiftCount ) then
 
2584
      Begin
 
2585
        zSig0 := absA shl shiftCount;
 
2586
        zSig1 := 0;
 
2587
      End
 
2588
    else
 
2589
      Begin
 
2590
        shift64Right( absA, 0, - shiftCount, zSig0, zSig1 );
 
2591
      End;
 
2592
    packFloat64( zSign, $412 - shiftCount, zSig0, zSig1, result );
 
2593
  End;
 
2594
 
 
2595
{*
 
2596
-------------------------------------------------------------------------------
 
2597
Returns the result of converting the single-precision floating-point value
 
2598
`a' to the 32-bit two's complement integer format.  The conversion is
 
2599
performed according to the IEC/IEEE Standard for Binary Floating-Point
 
2600
Arithmetic---which means in particular that the conversion is rounded
 
2601
according to the current rounding mode.  If `a' is a NaN, the largest
 
2602
positive integer is returned.  Otherwise, if the conversion overflows, the
 
2603
largest integer with the same sign as `a' is returned.
 
2604
-------------------------------------------------------------------------------
 
2605
*}
 
2606
Function float32_to_int32( a : float32rec) : int32;compilerproc;
 
2607
  Var
 
2608
    aSign: flag;
 
2609
    aExp, shiftCount: int16;
 
2610
    aSig, aSigExtra: bits32;
 
2611
    z: int32;
 
2612
    roundingMode: int8;
 
2613
  Begin
 
2614
 
 
2615
    aSig := extractFloat32Frac( a.float32 );
 
2616
    aExp := extractFloat32Exp( a.float32 );
 
2617
    aSign := extractFloat32Sign( a.float32 );
 
2618
    shiftCount := aExp - $96;
 
2619
    if ( 0 <= shiftCount ) then
 
2620
      Begin
 
2621
        if ( $9E <= aExp ) then
 
2622
          Begin
 
2623
            if ( a.float32 <> $CF000000 ) then
 
2624
              Begin
 
2625
                float_raise( float_flag_invalid );
 
2626
                if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
 
2627
                  Begin
 
2628
                    float32_to_int32 := $7FFFFFFF;
 
2629
                    exit;
 
2630
                  End;
 
2631
              End;
 
2632
            float32_to_int32 := sbits32 ($80000000);
 
2633
            exit;
 
2634
          End;
 
2635
        z := ( aSig or $00800000 ) shl shiftCount;
 
2636
        if ( aSign<>0 ) then z := - z;
 
2637
      End
 
2638
    else
 
2639
      Begin
 
2640
        if ( aExp < $7E ) then
 
2641
          Begin
 
2642
            aSigExtra := aExp OR aSig;
 
2643
            z := 0;
 
2644
          End
 
2645
        else
 
2646
         Begin
 
2647
            aSig := aSig OR $00800000;
 
2648
            aSigExtra := aSig shl ( shiftCount and 31 );
 
2649
            z := aSig shr ( - shiftCount );
 
2650
         End;
 
2651
        if ( aSigExtra<>0 ) then
 
2652
          softfloat_exception_flags := softfloat_exception_flags
 
2653
             or float_flag_inexact;
 
2654
        roundingMode := float_rounding_mode;
 
2655
        if ( roundingMode = float_round_nearest_even ) then
 
2656
          Begin
 
2657
            if ( sbits32 (aSigExtra) < 0 ) then
 
2658
              Begin
 
2659
                Inc(z);
 
2660
                if ( bits32 ( aSigExtra shl 1 ) = 0 ) then
 
2661
                  z := z and not 1;
 
2662
              End;
 
2663
              if ( aSign<>0 ) then
 
2664
                z := - z;
 
2665
          End
 
2666
        else
 
2667
          Begin
 
2668
            aSigExtra := flag( aSigExtra <> 0 );
 
2669
            if ( aSign<>0 ) then
 
2670
             Begin
 
2671
                z := z + (flag( roundingMode = float_round_down ) and aSigExtra);
 
2672
                z := - z;
 
2673
             End
 
2674
            else
 
2675
             Begin
 
2676
                z := z + (flag( roundingMode = float_round_up ) and aSigExtra);
 
2677
             End
 
2678
          End;
 
2679
      End;
 
2680
   float32_to_int32 := z;
 
2681
  End;
 
2682
 
 
2683
{*
 
2684
-------------------------------------------------------------------------------
 
2685
Returns the result of converting the single-precision floating-point value
 
2686
`a' to the 32-bit two's complement integer format.  The conversion is
 
2687
performed according to the IEC/IEEE Standard for Binary Floating-Point
 
2688
Arithmetic, except that the conversion is always rounded toward zero.
 
2689
If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
 
2690
the conversion overflows, the largest integer with the same sign as `a' is
 
2691
returned.
 
2692
-------------------------------------------------------------------------------
 
2693
*}
 
2694
Function float32_to_int32_round_to_zero( a: Float32rec ): int32;compilerproc;
 
2695
 Var
 
2696
    aSign : flag;
 
2697
    aExp, shiftCount : int16;
 
2698
    aSig : bits32;
 
2699
    z : int32;
 
2700
 Begin
 
2701
    aSig := extractFloat32Frac( a.float32 );
 
2702
    aExp := extractFloat32Exp( a.float32 );
 
2703
    aSign := extractFloat32Sign( a.float32 );
 
2704
    shiftCount := aExp - $9E;
 
2705
    if ( 0 <= shiftCount ) then
 
2706
      Begin
 
2707
        if ( a.float32 <> $CF000000 ) then
 
2708
          Begin
 
2709
            float_raise( float_flag_invalid );
 
2710
            if ( (aSign=0) or ( ( aExp = $FF ) and (aSig<>0) ) ) then
 
2711
              Begin
 
2712
                float32_to_int32_round_to_zero := $7FFFFFFF;
 
2713
                exit;
 
2714
              end;
 
2715
          End;
 
2716
        float32_to_int32_round_to_zero:= sbits32 ($80000000);
 
2717
        exit;
 
2718
      End
 
2719
    else
 
2720
      if ( aExp <= $7E ) then
 
2721
      Begin
 
2722
        if ( aExp or aSig )<>0 then
 
2723
           softfloat_exception_flags :=
 
2724
             softfloat_exception_flags or float_flag_inexact;
 
2725
        float32_to_int32_round_to_zero := 0;
 
2726
        exit;
 
2727
      End;
 
2728
    aSig := ( aSig or $00800000 ) shl 8;
 
2729
    z := aSig shr ( - shiftCount );
 
2730
    if ( bits32 ( aSig shl ( shiftCount and 31 ) )<> 0 ) then
 
2731
      Begin
 
2732
           softfloat_exception_flags :=
 
2733
             softfloat_exception_flags or float_flag_inexact;
 
2734
      End;
 
2735
    if ( aSign<>0 ) then z := - z;
 
2736
    float32_to_int32_round_to_zero := z;
 
2737
 End;
 
2738
 
 
2739
{*
 
2740
-------------------------------------------------------------------------------
 
2741
Returns the result of converting the single-precision floating-point value
 
2742
`a' to the double-precision floating-point format.  The conversion is
 
2743
performed according to the IEC/IEEE Standard for Binary Floating-Point
 
2744
Arithmetic.
 
2745
-------------------------------------------------------------------------------
 
2746
*}
 
2747
Function float32_to_float64( a : float32rec) : Float64;compilerproc;
 
2748
  Var
 
2749
    aSign : flag;
 
2750
    aExp : int16;
 
2751
    aSig, zSig0, zSig1: bits32;
 
2752
    tmp : CommonNanT;
 
2753
  Begin
 
2754
    aSig := extractFloat32Frac( a.float32 );
 
2755
    aExp := extractFloat32Exp( a.float32 );
 
2756
    aSign := extractFloat32Sign( a.float32 );
 
2757
    if ( aExp = $FF ) then
 
2758
      Begin
 
2759
        if ( aSig<>0 ) then
 
2760
          Begin
 
2761
            float32ToCommonNaN(a.float32, tmp);
 
2762
            commonNaNToFloat64(tmp , result);
 
2763
            exit;
 
2764
          End;
 
2765
          packFloat64( aSign, $7FF, 0, 0, result);
 
2766
          exit;
 
2767
      End;
 
2768
    if ( aExp = 0 ) then
 
2769
      Begin
 
2770
        if ( aSig = 0 ) then
 
2771
          Begin
 
2772
            packFloat64( aSign, 0, 0, 0, result );
 
2773
            exit;
 
2774
          end;
 
2775
        normalizeFloat32Subnormal( aSig, aExp, aSig );
 
2776
        Dec(aExp);
 
2777
      End;
 
2778
    shift64Right( aSig, 0, 3, zSig0, zSig1 );
 
2779
    packFloat64( aSign, aExp + $380, zSig0, zSig1, result );
 
2780
  End;
 
2781
 
 
2782
{*
 
2783
-------------------------------------------------------------------------------
 
2784
Rounds the single-precision floating-point value `a' to an integer,
 
2785
and returns the result as a single-precision floating-point value.  The
 
2786
operation is performed according to the IEC/IEEE Standard for Binary
 
2787
Floating-Point Arithmetic.
 
2788
-------------------------------------------------------------------------------
 
2789
*}
 
2790
Function float32_round_to_int( a: float32rec): float32rec;compilerproc;
 
2791
  Var
 
2792
    aSign: flag;
 
2793
    aExp: int16;
 
2794
    lastBitMask, roundBitsMask: bits32;
 
2795
    roundingMode: int8;
 
2796
    z: float32;
 
2797
  Begin
 
2798
    aExp := extractFloat32Exp( a.float32 );
 
2799
    if ( $96 <= aExp ) then
 
2800
     Begin
 
2801
        if ( ( aExp = $FF ) and (extractFloat32Frac( a.float32 )<>0) ) then
 
2802
          Begin
 
2803
            float32_round_to_int.float32 := propagateFloat32NaN( a.float32, a.float32 );
 
2804
            exit;
 
2805
          End;
 
2806
        float32_round_to_int:=a;
 
2807
        exit;
 
2808
     End;
 
2809
    if ( aExp <= $7E ) then
 
2810
      Begin
 
2811
        if ( bits32 ( a.float32 shl 1 ) = 0 ) then
 
2812
          Begin
 
2813
             float32_round_to_int:=a;
 
2814
             exit;
 
2815
          end;
 
2816
        softfloat_exception_flags
 
2817
          := softfloat_exception_flags OR  float_flag_inexact;
 
2818
        aSign := extractFloat32Sign( a.float32 );
 
2819
 
 
2820
        case ( float_rounding_mode ) of
 
2821
         float_round_nearest_even:
 
2822
            Begin
 
2823
              if ( ( aExp = $7E ) and (extractFloat32Frac( a.float32 )<>0) ) then
 
2824
                Begin
 
2825
                  float32_round_to_int.float32 := packFloat32( aSign, $7F, 0 );
 
2826
                  exit;
 
2827
                End;
 
2828
            End;
 
2829
         float_round_down:
 
2830
            Begin
 
2831
              if aSign <> 0 then
 
2832
                 float32_round_to_int.float32 := $BF800000
 
2833
              else
 
2834
                 float32_round_to_int.float32 := 0;
 
2835
              exit;
 
2836
            End;
 
2837
         float_round_up:
 
2838
            Begin
 
2839
              if aSign <> 0 then
 
2840
                 float32_round_to_int.float32 := $80000000
 
2841
              else
 
2842
                 float32_round_to_int.float32 := $3F800000;
 
2843
              exit;
 
2844
            End;
 
2845
        end;
 
2846
        float32_round_to_int.float32 := packFloat32( aSign, 0, 0 );
 
2847
      End;
 
2848
    lastBitMask := 1;
 
2849
    {_____________________________!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
 
2850
    lastBitMask := lastBitMask shl ($96 - aExp);
 
2851
    roundBitsMask := lastBitMask - 1;
 
2852
    z := a.float32;
 
2853
    roundingMode := float_rounding_mode;
 
2854
    if ( roundingMode = float_round_nearest_even ) then
 
2855
      Begin
 
2856
        z := z + (lastBitMask shr 1);
 
2857
        if ( ( z and roundBitsMask ) = 0 ) then
 
2858
           z := z and not lastBitMask;
 
2859
      End
 
2860
    else if ( roundingMode <> float_round_to_zero ) then
 
2861
      Begin
 
2862
        if ( (extractFloat32Sign( z ) xor flag(roundingMode = float_round_up ))<>0 ) then
 
2863
          Begin
 
2864
            z := z + roundBitsMask;
 
2865
          End;
 
2866
      End;
 
2867
    z := z and not roundBitsMask;
 
2868
    if ( z <> a.float32 ) then
 
2869
      softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
2870
    float32_round_to_int.float32 := z;
 
2871
  End;
 
2872
 
 
2873
{*
 
2874
-------------------------------------------------------------------------------
 
2875
Returns the result of adding the absolute values of the single-precision
 
2876
floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
 
2877
before being returned.  `zSign' is ignored if the result is a NaN.
 
2878
The addition is performed according to the IEC/IEEE Standard for Binary
 
2879
Floating-Point Arithmetic.
 
2880
-------------------------------------------------------------------------------
 
2881
*}
 
2882
Function addFloat32Sigs( a:float32; b: float32; zSign:flag ): float32;
 
2883
  Var
 
2884
    aExp, bExp, zExp: int16;
 
2885
    aSig, bSig, zSig: bits32;
 
2886
    expDiff: int16;
 
2887
    label roundAndPack;
 
2888
  Begin
 
2889
    aSig:=extractFloat32Frac( a );
 
2890
    aExp:=extractFloat32Exp( a );
 
2891
    bSig:=extractFloat32Frac( b );
 
2892
    bExp := extractFloat32Exp( b );
 
2893
    expDiff := aExp - bExp;
 
2894
    aSig := aSig shl 6;
 
2895
    bSig := bSig shl 6;
 
2896
    if ( 0 < expDiff ) then
 
2897
    Begin
 
2898
        if ( aExp = $FF ) then
 
2899
          Begin
 
2900
            if ( aSig <> 0) then
 
2901
              Begin
 
2902
                addFloat32Sigs := propagateFloat32NaN( a, b );
 
2903
                exit;
 
2904
              End;
 
2905
            addFloat32Sigs := a;
 
2906
            exit;
 
2907
          End;
 
2908
        if ( bExp = 0 ) then
 
2909
          Begin
 
2910
             Dec(expDiff);
 
2911
          End
 
2912
        else
 
2913
          Begin
 
2914
            bSig := bSig or $20000000;
 
2915
          End;
 
2916
        shift32RightJamming( bSig, expDiff, bSig );
 
2917
        zExp := aExp;
 
2918
    End
 
2919
    else
 
2920
    If ( expDiff < 0 ) then
 
2921
      Begin
 
2922
        if ( bExp = $FF ) then
 
2923
        Begin
 
2924
            if ( bSig<>0 ) then
 
2925
              Begin
 
2926
                addFloat32Sigs := propagateFloat32NaN( a, b );
 
2927
                exit;
 
2928
              end;
 
2929
 
 
2930
            addFloat32Sigs := packFloat32( zSign, $FF, 0 );
 
2931
            exit;
 
2932
        End;
 
2933
        if ( aExp = 0 ) then
 
2934
          Begin
 
2935
            Inc(expDiff);
 
2936
          End
 
2937
        else
 
2938
          Begin
 
2939
            aSig := aSig OR $20000000;
 
2940
          End;
 
2941
        shift32RightJamming( aSig, - expDiff, aSig );
 
2942
        zExp := bExp;
 
2943
    End
 
2944
    else
 
2945
    Begin
 
2946
        if ( aExp = $FF ) then
 
2947
        Begin
 
2948
            if ( aSig OR  bSig )<> 0 then
 
2949
              Begin
 
2950
                addFloat32Sigs := propagateFloat32NaN( a, b );
 
2951
                exit;
 
2952
              end;
 
2953
            addFloat32Sigs := a;
 
2954
            exit;
 
2955
        End;
 
2956
        if ( aExp = 0 ) then
 
2957
          Begin
 
2958
             addFloat32Sigs := packFloat32( zSign, 0, ( aSig + bSig ) shr 6 );
 
2959
             exit;
 
2960
          end;
 
2961
        zSig := $40000000 + aSig + bSig;
 
2962
        zExp := aExp;
 
2963
        goto roundAndPack;
 
2964
    End;
 
2965
    aSig := aSig OR $20000000;
 
2966
    zSig := ( aSig + bSig ) shl 1;
 
2967
    Dec(zExp);
 
2968
    if ( sbits32 (zSig) < 0 ) then
 
2969
      Begin
 
2970
        zSig := aSig + bSig;
 
2971
        Inc(zExp);
 
2972
      End;
 
2973
 roundAndPack:
 
2974
    addFloat32Sigs := roundAndPackFloat32( zSign, zExp, zSig );
 
2975
 End;
 
2976
 
 
2977
{*
 
2978
-------------------------------------------------------------------------------
 
2979
Returns the result of subtracting the absolute values of the single-
 
2980
precision floating-point values `a' and `b'.  If `zSign' is 1, the
 
2981
difference is negated before being returned.  `zSign' is ignored if the
 
2982
result is a NaN.  The subtraction is performed according to the IEC/IEEE
 
2983
Standard for Binary Floating-Point Arithmetic.
 
2984
-------------------------------------------------------------------------------
 
2985
*}
 
2986
Function subFloat32Sigs( a:float32; b:float32; zSign:flag ): float32;
 
2987
  Var
 
2988
    aExp, bExp, zExp: int16;
 
2989
    aSig, bSig, zSig: bits32;
 
2990
    expDiff : int16;
 
2991
    label aExpBigger;
 
2992
    label bExpBigger;
 
2993
    label aBigger;
 
2994
    label bBigger;
 
2995
    label normalizeRoundAndPack;
 
2996
  Begin
 
2997
    aSig := extractFloat32Frac( a );
 
2998
    aExp := extractFloat32Exp( a );
 
2999
    bSig := extractFloat32Frac( b );
 
3000
    bExp := extractFloat32Exp( b );
 
3001
    expDiff := aExp - bExp;
 
3002
    aSig := aSig shl 7;
 
3003
    bSig := bSig shl 7;
 
3004
    if ( 0 < expDiff ) then goto aExpBigger;
 
3005
    if ( expDiff < 0 ) then goto bExpBigger;
 
3006
    if ( aExp = $FF ) then
 
3007
    Begin
 
3008
        if ( aSig OR  bSig )<> 0 then
 
3009
          Begin
 
3010
           subFloat32Sigs := propagateFloat32NaN( a, b );
 
3011
           exit;
 
3012
          End;
 
3013
        float_raise( float_flag_invalid );
 
3014
        subFloat32Sigs := float32_default_nan;
 
3015
        exit;
 
3016
    End;
 
3017
    if ( aExp = 0 ) then
 
3018
    Begin
 
3019
        aExp := 1;
 
3020
        bExp := 1;
 
3021
    End;
 
3022
    if ( bSig < aSig ) Then goto aBigger;
 
3023
    if ( aSig < bSig ) Then goto bBigger;
 
3024
    subFloat32Sigs := packFloat32( flag(float_rounding_mode = float_round_down), 0, 0 );
 
3025
    exit;
 
3026
 bExpBigger:
 
3027
    if ( bExp = $FF ) then
 
3028
    Begin
 
3029
        if ( bSig<>0 ) then
 
3030
        Begin
 
3031
          subFloat32Sigs := propagateFloat32NaN( a, b );
 
3032
          exit;
 
3033
        End;
 
3034
        subFloat32Sigs := packFloat32( zSign XOR 1, $FF, 0 );
 
3035
        exit;
 
3036
    End;
 
3037
    if ( aExp = 0 ) then
 
3038
      Begin
 
3039
        Inc(expDiff);
 
3040
      End
 
3041
    else
 
3042
      Begin
 
3043
        aSig := aSig OR $40000000;
 
3044
      End;
 
3045
    shift32RightJamming( aSig, - expDiff, aSig );
 
3046
    bSig := bSig OR $40000000;
 
3047
 bBigger:
 
3048
    zSig := bSig - aSig;
 
3049
    zExp := bExp;
 
3050
    zSign := zSign xor 1;
 
3051
    goto normalizeRoundAndPack;
 
3052
 aExpBigger:
 
3053
    if ( aExp = $FF ) then
 
3054
      Begin
 
3055
        if ( aSig <> 0) then
 
3056
          Begin
 
3057
            subFloat32Sigs := propagateFloat32NaN( a, b );
 
3058
            exit;
 
3059
          End;
 
3060
        subFloat32Sigs := a;
 
3061
        exit;
 
3062
      End;
 
3063
    if ( bExp = 0 ) then
 
3064
      Begin
 
3065
        Dec(expDiff);
 
3066
      End
 
3067
    else
 
3068
      Begin
 
3069
        bSig := bSig OR $40000000;
 
3070
      End;
 
3071
    shift32RightJamming( bSig, expDiff, bSig );
 
3072
    aSig := aSig OR $40000000;
 
3073
 aBigger:
 
3074
    zSig := aSig - bSig;
 
3075
    zExp := aExp;
 
3076
 normalizeRoundAndPack:
 
3077
    Dec(zExp);
 
3078
    subFloat32Sigs := normalizeRoundAndPackFloat32( zSign, zExp, zSig );
 
3079
  End;
 
3080
 
 
3081
{*
 
3082
-------------------------------------------------------------------------------
 
3083
Returns the result of adding the single-precision floating-point values `a'
 
3084
and `b'.  The operation is performed according to the IEC/IEEE Standard for
 
3085
Binary Floating-Point Arithmetic.
 
3086
-------------------------------------------------------------------------------
 
3087
*}
 
3088
Function float32_add( a: float32rec; b:float32rec ): float32rec; compilerproc;
 
3089
  Var
 
3090
    aSign, bSign: Flag;
 
3091
  Begin
 
3092
    aSign := extractFloat32Sign( a.float32 );
 
3093
    bSign := extractFloat32Sign( b.float32 );
 
3094
    if ( aSign = bSign ) then
 
3095
      Begin
 
3096
        float32_add.float32 := addFloat32Sigs( a.float32, b.float32, aSign );
 
3097
      End
 
3098
    else
 
3099
      Begin
 
3100
        float32_add.float32 := subFloat32Sigs( a.float32, b.float32, aSign );
 
3101
      End;
 
3102
  End;
 
3103
 
 
3104
{*
 
3105
-------------------------------------------------------------------------------
 
3106
Returns the result of subtracting the single-precision floating-point values
 
3107
`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
 
3108
for Binary Floating-Point Arithmetic.
 
3109
-------------------------------------------------------------------------------
 
3110
*}
 
3111
Function float32_sub( a: float32rec ; b:float32rec ): float32rec;compilerproc;
 
3112
  Var
 
3113
    aSign, bSign: flag;
 
3114
  Begin
 
3115
    aSign := extractFloat32Sign( a.float32 );
 
3116
    bSign := extractFloat32Sign( b.float32 );
 
3117
    if ( aSign = bSign ) then
 
3118
      Begin
 
3119
        float32_sub.float32 := subFloat32Sigs( a.float32, b.float32, aSign );
 
3120
      End
 
3121
    else
 
3122
      Begin
 
3123
        float32_sub.float32 := addFloat32Sigs( a.float32, b.float32, aSign );
 
3124
      End;
 
3125
  End;
 
3126
 
 
3127
{*
 
3128
-------------------------------------------------------------------------------
 
3129
Returns the result of multiplying the single-precision floating-point values
 
3130
`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
 
3131
for Binary Floating-Point Arithmetic.
 
3132
-------------------------------------------------------------------------------
 
3133
*}
 
3134
Function float32_mul(a: float32rec; b: float32rec ) : float32rec; compilerproc;
 
3135
 
 
3136
  Var
 
3137
    aSign, bSign, zSign: flag;
 
3138
    aExp, bExp, zExp : int16;
 
3139
    aSig, bSig, zSig0, zSig1: bits32;
 
3140
  Begin
 
3141
    aSig := extractFloat32Frac( a.float32 );
 
3142
    aExp := extractFloat32Exp( a.float32 );
 
3143
    aSign := extractFloat32Sign( a.float32 );
 
3144
    bSig := extractFloat32Frac( b.float32 );
 
3145
    bExp := extractFloat32Exp( b.float32 );
 
3146
    bSign := extractFloat32Sign( b.float32 );
 
3147
    zSign := aSign xor bSign;
 
3148
    if ( aExp = $FF ) then
 
3149
    Begin
 
3150
        if ( (aSig<>0) OR ( ( bExp = $FF ) AND  (bSig<>0) ) ) then
 
3151
        Begin
 
3152
            float32_mul.float32 := propagateFloat32NaN( a.float32, b.float32 );
 
3153
        End;
 
3154
        if ( ( bExp OR  bSig ) = 0 ) then
 
3155
        Begin
 
3156
            float_raise( float_flag_invalid );
 
3157
            float32_mul.float32 := float32_default_nan;
 
3158
            exit;
 
3159
        End;
 
3160
        float32_mul.float32 := packFloat32( zSign, $FF, 0 );
 
3161
        exit;
 
3162
    End;
 
3163
    if ( bExp = $FF ) then
 
3164
    Begin
 
3165
        if ( bSig <> 0 ) then
 
3166
        Begin
 
3167
           float32_mul.float32 := propagateFloat32NaN( a.float32, b.float32 );
 
3168
           exit;
 
3169
        End;
 
3170
        if ( ( aExp OR  aSig ) = 0 ) then
 
3171
        Begin
 
3172
            float_raise( float_flag_invalid );
 
3173
            float32_mul.float32 := float32_default_nan;
 
3174
            exit;
 
3175
        End;
 
3176
        float32_mul.float32 := packFloat32( zSign, $FF, 0 );
 
3177
        exit;
 
3178
    End;
 
3179
    if ( aExp = 0 ) then
 
3180
    Begin
 
3181
        if ( aSig = 0 ) then
 
3182
        Begin
 
3183
           float32_mul.float32 := packFloat32( zSign, 0, 0 );
 
3184
           exit;
 
3185
        End;
 
3186
        normalizeFloat32Subnormal( aSig, aExp, aSig );
 
3187
    End;
 
3188
    if ( bExp = 0 ) then
 
3189
    Begin
 
3190
        if ( bSig = 0 ) then
 
3191
         Begin
 
3192
           float32_mul.float32 := packFloat32( zSign, 0, 0 );
 
3193
           exit;
 
3194
         End;
 
3195
        normalizeFloat32Subnormal( bSig, bExp, bSig );
 
3196
    End;
 
3197
    zExp := aExp + bExp - $7F;
 
3198
    aSig := ( aSig OR  $00800000 ) shl 7;
 
3199
    bSig := ( bSig OR  $00800000 ) shl 8;
 
3200
    mul32To64( aSig, bSig, zSig0, zSig1 );
 
3201
    zSig0 := zSig0 OR bits32( zSig1 <> 0 );
 
3202
    if ( 0 <= sbits32 ( zSig0 shl 1 ) ) then
 
3203
    Begin
 
3204
        zSig0 := zSig0 shl 1;
 
3205
        Dec(zExp);
 
3206
    End;
 
3207
    float32_mul.float32 := roundAndPackFloat32( zSign, zExp, zSig0 );
 
3208
 End;
 
3209
 
 
3210
{*
 
3211
-------------------------------------------------------------------------------
 
3212
Returns the result of dividing the single-precision floating-point value `a'
 
3213
by the corresponding value `b'.  The operation is performed according to the
 
3214
IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
3215
-------------------------------------------------------------------------------
 
3216
*}
 
3217
Function float32_div(a: float32rec;b: float32rec ): float32rec; compilerproc;
 
3218
  Var
 
3219
    aSign, bSign, zSign: flag;
 
3220
    aExp, bExp, zExp: int16;
 
3221
    aSig, bSig, zSig, rem0, rem1, term0, term1: bits32;
 
3222
  Begin
 
3223
    aSig := extractFloat32Frac( a.float32 );
 
3224
    aExp := extractFloat32Exp( a.float32 );
 
3225
    aSign := extractFloat32Sign( a.float32 );
 
3226
    bSig := extractFloat32Frac( b.float32 );
 
3227
    bExp := extractFloat32Exp( b.float32 );
 
3228
    bSign := extractFloat32Sign( b.float32 );
 
3229
    zSign := aSign xor bSign;
 
3230
    if ( aExp = $FF ) then
 
3231
      Begin
 
3232
        if ( aSig <> 0 ) then
 
3233
        Begin
 
3234
           float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );
 
3235
           exit;
 
3236
        End;
 
3237
        if ( bExp = $FF ) then
 
3238
        Begin
 
3239
            if ( bSig <> 0) then
 
3240
            Begin
 
3241
              float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );
 
3242
            End;
 
3243
            float_raise( float_flag_invalid );
 
3244
            float32_div.float32 := float32_default_nan;
 
3245
            exit;
 
3246
        End;
 
3247
        float32_div.float32 := packFloat32( zSign, $FF, 0 );
 
3248
        exit;
 
3249
      End;
 
3250
    if ( bExp = $FF ) then
 
3251
    Begin
 
3252
        if ( bSig <> 0) then
 
3253
        Begin
 
3254
          float32_div.float32 := propagateFloat32NaN( a.float32, b.float32 );
 
3255
          exit;
 
3256
        End;
 
3257
        float32_div.float32 := packFloat32( zSign, 0, 0 );
 
3258
        exit;
 
3259
    End;
 
3260
    if ( bExp = 0 ) Then
 
3261
    Begin
 
3262
        if ( bSig = 0 ) Then
 
3263
        Begin
 
3264
            if ( ( aExp OR  aSig ) = 0 ) then
 
3265
            Begin
 
3266
                float_raise( float_flag_invalid );
 
3267
                float32_div.float32 := float32_default_nan;
 
3268
                exit;
 
3269
            End;
 
3270
            float_raise( float_flag_divbyzero );
 
3271
            float32_div.float32 := packFloat32( zSign, $FF, 0 );
 
3272
            exit;
 
3273
        End;
 
3274
        normalizeFloat32Subnormal( bSig, bExp, bSig );
 
3275
    End;
 
3276
    if ( aExp = 0 ) Then
 
3277
    Begin
 
3278
        if ( aSig = 0 ) Then
 
3279
        Begin
 
3280
          float32_div.float32 := packFloat32( zSign, 0, 0 );
 
3281
          exit;
 
3282
        End;
 
3283
        normalizeFloat32Subnormal( aSig, aExp, aSig );
 
3284
    End;
 
3285
    zExp := aExp - bExp + $7D;
 
3286
    aSig := ( aSig OR  $00800000 ) shl 7;
 
3287
    bSig := ( bSig OR  $00800000 ) shl 8;
 
3288
    if ( bSig <= ( aSig + aSig ) ) then
 
3289
    Begin
 
3290
        aSig := aSig shr 1;
 
3291
        Inc(zExp);
 
3292
    End;
 
3293
    zSig := estimateDiv64To32( aSig, 0, bSig );
 
3294
    if ( ( zSig and $3F ) <= 2 ) then
 
3295
    Begin
 
3296
        mul32To64( bSig, zSig, term0, term1 );
 
3297
        sub64( aSig, 0, term0, term1, rem0, rem1 );
 
3298
        while ( sbits32 (rem0) < 0 ) do
 
3299
        Begin
 
3300
            Dec(zSig);
 
3301
            add64( rem0, rem1, 0, bSig, rem0, rem1 );
 
3302
        End;
 
3303
        zSig := zSig or bits32( rem1 <> 0 );
 
3304
    End;
 
3305
    float32_div.float32 := roundAndPackFloat32( zSign, zExp, zSig );
 
3306
 
 
3307
  End;
 
3308
 
 
3309
{*
 
3310
-------------------------------------------------------------------------------
 
3311
Returns the remainder of the single-precision floating-point value `a'
 
3312
with respect to the corresponding value `b'.  The operation is performed
 
3313
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
3314
-------------------------------------------------------------------------------
 
3315
*}
 
3316
Function float32_rem(a: float32rec; b: float32rec ):float32rec; compilerproc;
 
3317
  Var
 
3318
    aSign, bSign, zSign: flag;
 
3319
    aExp, bExp, expDiff: int16;
 
3320
    aSig, bSig, q, allZero, alternateASig: bits32;
 
3321
    sigMean: sbits32;
 
3322
  Begin
 
3323
    aSig := extractFloat32Frac( a.float32 );
 
3324
    aExp := extractFloat32Exp( a.float32 );
 
3325
    aSign := extractFloat32Sign( a.float32 );
 
3326
    bSig := extractFloat32Frac( b.float32 );
 
3327
    bExp := extractFloat32Exp( b.float32 );
 
3328
    bSign := extractFloat32Sign( b.float32 );
 
3329
    if ( aExp = $FF ) then
 
3330
    Begin
 
3331
        if ( (aSig<>0) OR ( ( bExp = $FF ) AND  (bSig <>0)) ) then
 
3332
        Begin
 
3333
            float32_rem.float32 := propagateFloat32NaN( a.float32, b.float32 );
 
3334
            exit;
 
3335
        End;
 
3336
        float_raise( float_flag_invalid );
 
3337
        float32_rem.float32 := float32_default_nan;
 
3338
        exit;
 
3339
    End;
 
3340
    if ( bExp = $FF ) then
 
3341
    Begin
 
3342
        if ( bSig <> 0 ) then
 
3343
        Begin
 
3344
          float32_rem.float32 := propagateFloat32NaN( a.float32, b.float32 );
 
3345
          exit;
 
3346
        End;
 
3347
        float32_rem := a;
 
3348
        exit;
 
3349
    End;
 
3350
    if ( bExp = 0 ) then
 
3351
    Begin
 
3352
        if ( bSig = 0 ) then
 
3353
        Begin
 
3354
            float_raise( float_flag_invalid );
 
3355
            float32_rem.float32 := float32_default_nan;
 
3356
            exit;
 
3357
        End;
 
3358
        normalizeFloat32Subnormal( bSig, bExp, bSig );
 
3359
    End;
 
3360
    if ( aExp = 0 ) then
 
3361
    Begin
 
3362
        if ( aSig = 0 ) then
 
3363
        Begin
 
3364
           float32_rem := a;
 
3365
           exit;
 
3366
        End;
 
3367
        normalizeFloat32Subnormal( aSig, aExp, aSig );
 
3368
    End;
 
3369
    expDiff := aExp - bExp;
 
3370
    aSig := ( aSig OR  $00800000 ) shl 8;
 
3371
    bSig := ( bSig OR  $00800000 ) shl 8;
 
3372
    if ( expDiff < 0 ) then
 
3373
    Begin
 
3374
        if ( expDiff < -1 ) then
 
3375
        Begin
 
3376
           float32_rem := a;
 
3377
           exit;
 
3378
        End;
 
3379
        aSig := aSig shr 1;
 
3380
    End;
 
3381
    q := bits32( bSig <= aSig );
 
3382
    if ( q <> 0) then
 
3383
       aSig := aSig - bSig;
 
3384
    expDiff := expDiff - 32;
 
3385
    while ( 0 < expDiff ) do
 
3386
    Begin
 
3387
        q := estimateDiv64To32( aSig, 0, bSig );
 
3388
        if (2 < q) then
 
3389
         q := q - 2
 
3390
        else
 
3391
         q := 0;
 
3392
        aSig := - ( ( bSig shr 2 ) * q );
 
3393
        expDiff := expDiff - 30;
 
3394
    End;
 
3395
    expDiff := expDiff + 32;
 
3396
    if ( 0 < expDiff ) then
 
3397
    Begin
 
3398
        q := estimateDiv64To32( aSig, 0, bSig );
 
3399
        if (2 < q) then
 
3400
         q := q - 2
 
3401
        else
 
3402
         q := 0;
 
3403
        q := q shr (32 - expDiff);
 
3404
        bSig := bSig shr 2;
 
3405
        aSig := ( ( aSig shr 1 ) shl ( expDiff - 1 ) ) - bSig * q;
 
3406
    End
 
3407
    else
 
3408
    Begin
 
3409
        aSig := aSig shr 2;
 
3410
        bSig := bSig shr 2;
 
3411
    End;
 
3412
    Repeat
 
3413
        alternateASig := aSig;
 
3414
        Inc(q);
 
3415
        aSig := aSig - bSig;
 
3416
    Until not ( 0 <= sbits32 (aSig) );
 
3417
    sigMean := aSig + alternateASig;
 
3418
    if ( ( sigMean < 0 ) OR ( ( sigMean = 0 ) AND  (( q and 1 )<>0) ) ) then
 
3419
    Begin
 
3420
        aSig := alternateASig;
 
3421
    End;
 
3422
    zSign := flag( sbits32 (aSig) < 0 );
 
3423
    if ( zSign<>0 ) then
 
3424
      aSig := - aSig;
 
3425
    float32_rem.float32 := normalizeRoundAndPackFloat32( aSign xor zSign, bExp, aSig );
 
3426
  End;
 
3427
 
 
3428
{*
 
3429
-------------------------------------------------------------------------------
 
3430
Returns the square root of the single-precision floating-point value `a'.
 
3431
The operation is performed according to the IEC/IEEE Standard for Binary
 
3432
Floating-Point Arithmetic.
 
3433
-------------------------------------------------------------------------------
 
3434
*}
 
3435
Function float32_sqrt(a: float32rec ): float32rec;compilerproc;
 
3436
Var
 
3437
    aSign : flag;
 
3438
    aExp, zExp : int16;
 
3439
    aSig, zSig, rem0, rem1, term0, term1: bits32;
 
3440
    label roundAndPack;
 
3441
Begin
 
3442
    aSig := extractFloat32Frac( a.float32 );
 
3443
    aExp := extractFloat32Exp( a.float32 );
 
3444
    aSign := extractFloat32Sign( a.float32 );
 
3445
    if ( aExp = $FF ) then
 
3446
    Begin
 
3447
        if ( aSig <> 0) then
 
3448
        Begin
 
3449
           float32_sqrt.float32 := propagateFloat32NaN( a.float32, 0 );
 
3450
           exit;
 
3451
        End;
 
3452
        if ( aSign = 0) then
 
3453
        Begin
 
3454
          float32_sqrt := a;
 
3455
          exit;
 
3456
        End;
 
3457
        float_raise( float_flag_invalid );
 
3458
        float32_sqrt.float32 := float32_default_nan;
 
3459
        exit;
 
3460
    End;
 
3461
    if ( aSign <> 0) then
 
3462
    Begin
 
3463
        if ( ( aExp OR  aSig ) = 0 ) then
 
3464
        Begin
 
3465
           float32_sqrt := a;
 
3466
           exit;
 
3467
        End;
 
3468
        float_raise( float_flag_invalid );
 
3469
        float32_sqrt.float32 := float32_default_nan;
 
3470
        exit;
 
3471
    End;
 
3472
    if ( aExp = 0 ) then
 
3473
    Begin
 
3474
        if ( aSig = 0 ) then
 
3475
        Begin
 
3476
           float32_sqrt.float32 := 0;
 
3477
           exit;
 
3478
        End;
 
3479
        normalizeFloat32Subnormal( aSig, aExp, aSig );
 
3480
    End;
 
3481
    zExp := ( ( aExp - $7F ) shr 1 ) + $7E;
 
3482
    aSig := ( aSig OR  $00800000 ) shl 8;
 
3483
    zSig := estimateSqrt32( aExp, aSig ) + 2;
 
3484
    if ( ( zSig and $7F ) <= 5 ) then
 
3485
    Begin
 
3486
        if ( zSig < 2 ) then
 
3487
        Begin
 
3488
            zSig := $7FFFFFFF;
 
3489
            goto roundAndPack;
 
3490
        End
 
3491
        else
 
3492
        Begin
 
3493
            aSig  := aSig shr (aExp and 1);
 
3494
            mul32To64( zSig, zSig, term0, term1 );
 
3495
            sub64( aSig, 0, term0, term1, rem0, rem1 );
 
3496
            while ( sbits32 (rem0) < 0 ) do
 
3497
            Begin
 
3498
                Dec(zSig);
 
3499
                shortShift64Left( 0, zSig, 1, term0, term1 );
 
3500
                term1 := term1 or 1;
 
3501
                add64( rem0, rem1, term0, term1, rem0, rem1 );
 
3502
            End;
 
3503
            zSig := zSig OR bits32( ( rem0 OR  rem1 ) <> 0 );
 
3504
        End;
 
3505
    End;
 
3506
    shift32RightJamming( zSig, 1, zSig );
 
3507
 roundAndPack:
 
3508
    float32_sqrt.float32 := roundAndPackFloat32( 0, zExp, zSig );
 
3509
End;
 
3510
 
 
3511
{*
 
3512
-------------------------------------------------------------------------------
 
3513
Returns 1 if the single-precision floating-point value `a' is equal to
 
3514
the corresponding value `b', and 0 otherwise.  The comparison is performed
 
3515
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
3516
-------------------------------------------------------------------------------
 
3517
*}
 
3518
Function float32_eq( a:float32rec; b:float32rec): flag; compilerproc;
 
3519
Begin
 
3520
    if ((( extractFloat32Exp( a.float32 ) = $FF ) AND  (extractFloat32Frac( a.float32 )<>0))
 
3521
         OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND  (extractFloat32Frac( b.float32 )<>0) )
 
3522
       ) then
 
3523
    Begin
 
3524
        if ( (float32_is_signaling_nan( a.float32 )<>0) OR (float32_is_signaling_nan( b.float32 )<>0) ) then
 
3525
        Begin
 
3526
            float_raise( float_flag_invalid );
 
3527
        End;
 
3528
        float32_eq := 0;
 
3529
        exit;
 
3530
    End;
 
3531
    float32_eq := flag( a.float32 = b.float32 ) OR flag( bits32 ( ( a.float32 OR  b.float32 ) shl 1 ) = 0 );
 
3532
End;
 
3533
 
 
3534
{*
 
3535
-------------------------------------------------------------------------------
 
3536
Returns 1 if the single-precision floating-point value `a' is less than
 
3537
or equal to the corresponding value `b', and 0 otherwise.  The comparison
 
3538
is performed according to the IEC/IEEE Standard for Binary Floating-Point
 
3539
Arithmetic.
 
3540
-------------------------------------------------------------------------------
 
3541
*}
 
3542
Function float32_le( a: float32rec; b : float32rec ):flag;compilerproc;
 
3543
var
 
3544
    aSign, bSign: flag;
 
3545
Begin
 
3546
 
 
3547
    if (    ( ( extractFloat32Exp( a.float32 ) = $FF ) AND  (extractFloat32Frac( a.float32 )<>0) )
 
3548
         OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND  (extractFloat32Frac( b.float32 )<>0) )
 
3549
       ) then
 
3550
    Begin
 
3551
        float_raise( float_flag_invalid );
 
3552
        float32_le := 0;
 
3553
        exit;
 
3554
    End;
 
3555
    aSign := extractFloat32Sign( a.float32 );
 
3556
    bSign := extractFloat32Sign( b.float32 );
 
3557
    if ( aSign <> bSign ) then
 
3558
    Begin
 
3559
       float32_le :=  aSign OR flag( bits32 ( ( a.float32 OR  b.float32 ) shl 1 ) = 0 );
 
3560
       exit;
 
3561
    End;
 
3562
    float32_le := flag(flag( a.float32 = b.float32 ) OR flag( aSign xor flag( a.float32 < b.float32 ) ));
 
3563
 
 
3564
End;
 
3565
 
 
3566
{*
 
3567
-------------------------------------------------------------------------------
 
3568
Returns 1 if the single-precision floating-point value `a' is less than
 
3569
the corresponding value `b', and 0 otherwise.  The comparison is performed
 
3570
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
3571
-------------------------------------------------------------------------------
 
3572
*}
 
3573
Function float32_lt( a:float32rec ; b : float32rec): flag; compilerproc;
 
3574
var
 
3575
    aSign, bSign: flag;
 
3576
Begin
 
3577
 
 
3578
    if (    ( ( extractFloat32Exp( a.float32 ) = $FF ) AND  (extractFloat32Frac( a.float32 ) <>0))
 
3579
         OR ( ( extractFloat32Exp( b.float32 ) = $FF ) AND  (extractFloat32Frac( b.float32 ) <>0) )
 
3580
       ) then
 
3581
    Begin
 
3582
        float_raise( float_flag_invalid );
 
3583
        float32_lt :=0;
 
3584
        exit;
 
3585
    End;
 
3586
    aSign := extractFloat32Sign( a.float32 );
 
3587
    bSign := extractFloat32Sign( b.float32 );
 
3588
    if ( aSign <> bSign ) then
 
3589
    Begin
 
3590
       float32_lt := aSign AND  flag( bits32 ( ( a.float32 OR  b.float32 ) shl 1 ) <> 0 );
 
3591
       exit;
 
3592
    End;
 
3593
    float32_lt := flag(flag( a.float32 <> b.float32 ) AND  flag( aSign xor flag( a.float32 < b.float32 ) ));
 
3594
 
 
3595
End;
 
3596
 
 
3597
{*
 
3598
-------------------------------------------------------------------------------
 
3599
Returns 1 if the single-precision floating-point value `a' is equal to
 
3600
the corresponding value `b', and 0 otherwise.  The invalid exception is
 
3601
raised if either operand is a NaN.  Otherwise, the comparison is performed
 
3602
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
3603
-------------------------------------------------------------------------------
 
3604
*}
 
3605
Function float32_eq_signaling( a: float32; b: float32) : flag;
 
3606
Begin
 
3607
 
 
3608
    if (    ( ( extractFloat32Exp( a ) = $FF ) AND  (extractFloat32Frac( a ) <> 0))
 
3609
         OR ( ( extractFloat32Exp( b ) = $FF ) AND  (extractFloat32Frac( b ) <> 0))
 
3610
       ) then
 
3611
    Begin
 
3612
        float_raise( float_flag_invalid );
 
3613
        float32_eq_signaling := 0;
 
3614
        exit;
 
3615
    End;
 
3616
    float32_eq_signaling := (flag( a = b ) OR flag( bits32 ( ( a OR  b ) shl 1 ) = 0 ));
 
3617
End;
 
3618
 
 
3619
{*
 
3620
-------------------------------------------------------------------------------
 
3621
Returns 1 if the single-precision floating-point value `a' is less than or
 
3622
equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not
 
3623
cause an exception.  Otherwise, the comparison is performed according to the
 
3624
IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
3625
-------------------------------------------------------------------------------
 
3626
*}
 
3627
Function float32_le_quiet( a: float32 ; b : float32 ): flag;
 
3628
Var
 
3629
    aSign, bSign: flag;
 
3630
    aExp, bExp: int16;
 
3631
Begin
 
3632
    if (    ( ( extractFloat32Exp( a ) = $FF ) AND  (extractFloat32Frac( a )<>0) )
 
3633
         OR ( ( extractFloat32Exp( b ) = $FF ) AND  (extractFloat32Frac( b )<>0) )
 
3634
       ) then
 
3635
    Begin
 
3636
        if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then
 
3637
        Begin
 
3638
            float_raise( float_flag_invalid );
 
3639
        End;
 
3640
        float32_le_quiet := 0;
 
3641
        exit;
 
3642
    End;
 
3643
    aSign := extractFloat32Sign( a );
 
3644
    bSign := extractFloat32Sign( b );
 
3645
    if ( aSign <> bSign ) then
 
3646
    Begin
 
3647
       float32_le_quiet := aSign OR flag( bits32 ( ( a OR  b ) shl 1 ) = 0 );
 
3648
       exit;
 
3649
    End;
 
3650
    float32_le_quiet := flag(flag( a = b ) OR flag( aSign xor flag( a < b ) ));
 
3651
End;
 
3652
 
 
3653
{*
 
3654
-------------------------------------------------------------------------------
 
3655
Returns 1 if the single-precision floating-point value `a' is less than
 
3656
the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
 
3657
exception.  Otherwise, the comparison is performed according to the IEC/IEEE
 
3658
Standard for Binary Floating-Point Arithmetic.
 
3659
-------------------------------------------------------------------------------
 
3660
*}
 
3661
Function float32_lt_quiet( a: float32 ; b: float32 ): flag;
 
3662
Var
 
3663
   aSign, bSign: flag;
 
3664
Begin
 
3665
    if (    ( ( extractFloat32Exp( a ) = $FF ) AND  (extractFloat32Frac( a )<>0) )
 
3666
         OR ( ( extractFloat32Exp( b ) = $FF ) AND  (extractFloat32Frac( b )<>0) )
 
3667
       ) then
 
3668
    Begin
 
3669
        if ( (float32_is_signaling_nan( a )<>0) OR (float32_is_signaling_nan( b )<>0) ) then
 
3670
        Begin
 
3671
            float_raise( float_flag_invalid );
 
3672
        End;
 
3673
        float32_lt_quiet := 0;
 
3674
        exit;
 
3675
    End;
 
3676
    aSign := extractFloat32Sign( a );
 
3677
    bSign := extractFloat32Sign( b );
 
3678
    if ( aSign <> bSign ) then
 
3679
    Begin
 
3680
        float32_lt_quiet := aSign AND  flag( bits32 ( ( a OR  b ) shl 1 ) <> 0 );
 
3681
        exit;
 
3682
    End;
 
3683
    float32_lt_quiet := flag(flag( a <> b ) AND  ( aSign xor flag( a < b ) ));
 
3684
End;
 
3685
 
 
3686
{*
 
3687
-------------------------------------------------------------------------------
 
3688
Returns the result of converting the double-precision floating-point value
 
3689
`a' to the 32-bit two's complement integer format.  The conversion is
 
3690
performed according to the IEC/IEEE Standard for Binary Floating-Point
 
3691
Arithmetic---which means in particular that the conversion is rounded
 
3692
according to the current rounding mode.  If `a' is a NaN, the largest
 
3693
positive integer is returned.  Otherwise, if the conversion overflows, the
 
3694
largest integer with the same sign as `a' is returned.
 
3695
-------------------------------------------------------------------------------
 
3696
*}
 
3697
Function float64_to_int32(a: float64): int32;{$ifdef fpc} [public,Alias:'FLOAT64_TO_INT32'];compilerproc;{$endif}
 
3698
var
 
3699
    aSign: flag;
 
3700
    aExp, shiftCount: int16;
 
3701
    aSig0, aSig1, absZ, aSigExtra: bits32;
 
3702
    z: int32;
 
3703
    roundingMode: int8;
 
3704
    label invalid;
 
3705
Begin
 
3706
    aSig1 := extractFloat64Frac1( a );
 
3707
    aSig0 := extractFloat64Frac0( a );
 
3708
    aExp := extractFloat64Exp( a );
 
3709
    aSign := extractFloat64Sign( a );
 
3710
    shiftCount := aExp - $413;
 
3711
    if ( 0 <= shiftCount ) then
 
3712
    Begin
 
3713
        if ( $41E < aExp ) then
 
3714
        Begin
 
3715
            if ( ( aExp = $7FF ) AND  (( aSig0 OR  aSig1 )<>0) ) then
 
3716
               aSign := 0;
 
3717
            goto invalid;
 
3718
        End;
 
3719
        shortShift64Left(
 
3720
            aSig0 OR  $00100000, aSig1, shiftCount, absZ, aSigExtra );
 
3721
        if ( $80000000 < absZ ) then
 
3722
          goto invalid;
 
3723
    End
 
3724
    else
 
3725
    Begin
 
3726
        aSig1 := flag( aSig1 <> 0 );
 
3727
        if ( aExp < $3FE ) then
 
3728
        Begin
 
3729
            aSigExtra := aExp OR  aSig0 OR  aSig1;
 
3730
            absZ := 0;
 
3731
        End
 
3732
        else
 
3733
        Begin
 
3734
            aSig0 := aSig0 OR $00100000;
 
3735
            aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR  aSig1;
 
3736
            absZ := aSig0 shr ( - shiftCount );
 
3737
        End;
 
3738
    End;
 
3739
    roundingMode := float_rounding_mode;
 
3740
    if ( roundingMode = float_round_nearest_even ) then
 
3741
    Begin
 
3742
        if ( sbits32(aSigExtra) < 0 ) then
 
3743
        Begin
 
3744
            Inc(absZ);
 
3745
            if ( bits32 ( aSigExtra shl 1 ) = 0 ) then
 
3746
               absZ :=  absZ and not 1;
 
3747
        End;
 
3748
        if aSign <> 0 then
 
3749
          z := - absZ
 
3750
        else
 
3751
          z := absZ;
 
3752
    End
 
3753
    else
 
3754
    Begin
 
3755
        aSigExtra := bits32( aSigExtra <> 0 );
 
3756
        if ( aSign <> 0) then
 
3757
        Begin
 
3758
            z := - (   absZ
 
3759
                    + ( int32( roundingMode = float_round_down ) and aSigExtra ) );
 
3760
        End
 
3761
        else
 
3762
        Begin
 
3763
            z := absZ + ( int32( roundingMode = float_round_up ) and aSigExtra );
 
3764
        End
 
3765
    End;
 
3766
    if ( (( aSign xor flag( z < 0 ) )<>0) AND  (z<>0) ) then
 
3767
    Begin
 
3768
 invalid:
 
3769
        float_raise( float_flag_invalid );
 
3770
        if (aSign <> 0 ) then
 
3771
          float64_to_int32 := sbits32 ($80000000)
 
3772
        else
 
3773
          float64_to_int32 :=  $7FFFFFFF;
 
3774
        exit;
 
3775
    End;
 
3776
    if ( aSigExtra <> 0) then
 
3777
       softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
3778
    float64_to_int32 := z;
 
3779
End;
 
3780
 
 
3781
 
 
3782
{*
 
3783
-------------------------------------------------------------------------------
 
3784
Returns the result of converting the double-precision floating-point value
 
3785
`a' to the 32-bit two's complement integer format.  The conversion is
 
3786
performed according to the IEC/IEEE Standard for Binary Floating-Point
 
3787
Arithmetic, except that the conversion is always rounded toward zero.
 
3788
If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
 
3789
the conversion overflows, the largest integer with the same sign as `a' is
 
3790
returned.
 
3791
-------------------------------------------------------------------------------
 
3792
*}
 
3793
Function float64_to_int32_round_to_zero(a: float64 ): int32;
 
3794
{$ifdef fpc} [public,Alias:'FLOAT64_TO_INT32_ROUND_TO_ZERO'];compilerproc;{$endif}
 
3795
Var
 
3796
    aSign: flag;
 
3797
    aExp, shiftCount: int16;
 
3798
    aSig0, aSig1, absZ, aSigExtra: bits32;
 
3799
    z: int32;
 
3800
    label invalid;
 
3801
 Begin
 
3802
    aSig1 := extractFloat64Frac1( a );
 
3803
    aSig0 := extractFloat64Frac0( a );
 
3804
    aExp := extractFloat64Exp( a );
 
3805
    aSign := extractFloat64Sign( a );
 
3806
    shiftCount := aExp - $413;
 
3807
    if ( 0 <= shiftCount ) then
 
3808
    Begin
 
3809
        if ( $41E < aExp ) then
 
3810
        Begin
 
3811
            if ( ( aExp = $7FF ) AND  (( aSig0 OR  aSig1 )<>0) ) then
 
3812
               aSign := 0;
 
3813
            goto invalid;
 
3814
        End;
 
3815
        shortShift64Left(
 
3816
            aSig0 OR  $00100000, aSig1, shiftCount, absZ, aSigExtra );
 
3817
    End
 
3818
    else
 
3819
    Begin
 
3820
        if ( aExp < $3FF ) then
 
3821
        Begin
 
3822
            if ( aExp OR  aSig0 OR  aSig1 )<>0 then
 
3823
            Begin
 
3824
                softfloat_exception_flags :=
 
3825
                  softfloat_exception_flags or float_flag_inexact;
 
3826
            End;
 
3827
            float64_to_int32_round_to_zero := 0;
 
3828
            exit;
 
3829
        End;
 
3830
        aSig0 := aSig0 or $00100000;
 
3831
        aSigExtra := ( aSig0 shl ( shiftCount and 31 ) ) OR  aSig1;
 
3832
        absZ := aSig0 shr ( - shiftCount );
 
3833
    End;
 
3834
    if aSign <> 0 then
 
3835
      z := - absZ
 
3836
    else
 
3837
      z := absZ;
 
3838
    if ( (( aSign xor flag( z < 0 )) <> 0) AND  (z<>0) ) then
 
3839
    Begin
 
3840
 invalid:
 
3841
        float_raise( float_flag_invalid );
 
3842
        if (aSign <> 0) then
 
3843
          float64_to_int32_round_to_zero := sbits32 ($80000000)
 
3844
        else
 
3845
          float64_to_int32_round_to_zero :=  $7FFFFFFF;
 
3846
        exit;
 
3847
    End;
 
3848
    if ( aSigExtra <> 0) then
 
3849
       softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
3850
    float64_to_int32_round_to_zero := z;
 
3851
 End;
 
3852
 
 
3853
{*
 
3854
-------------------------------------------------------------------------------
 
3855
Returns the result of converting the double-precision floating-point value
 
3856
`a' to the single-precision floating-point format.  The conversion is
 
3857
performed according to the IEC/IEEE Standard for Binary Floating-Point
 
3858
Arithmetic.
 
3859
-------------------------------------------------------------------------------
 
3860
*}
 
3861
Function float64_to_float32(a: float64 ): float32rec;compilerproc;
 
3862
Var
 
3863
    aSign: flag;
 
3864
    aExp: int16;
 
3865
    aSig0, aSig1, zSig: bits32;
 
3866
    allZero: bits32;
 
3867
    tmp : CommonNanT;
 
3868
Begin
 
3869
    aSig1 := extractFloat64Frac1( a );
 
3870
    aSig0 := extractFloat64Frac0( a );
 
3871
    aExp := extractFloat64Exp( a );
 
3872
    aSign := extractFloat64Sign( a );
 
3873
    if ( aExp = $7FF ) then
 
3874
    Begin
 
3875
        if ( aSig0 OR  aSig1 ) <> 0 then
 
3876
        Begin
 
3877
            float64ToCommonNaN( a, tmp );
 
3878
            float64_to_float32.float32 := commonNaNToFloat32( tmp );
 
3879
            exit;
 
3880
        End;
 
3881
        float64_to_float32.float32 := packFloat32( aSign, $FF, 0 );
 
3882
        exit;
 
3883
    End;
 
3884
    shift64RightJamming( aSig0, aSig1, 22, allZero, zSig );
 
3885
    if ( aExp <> 0) then
 
3886
      zSig := zSig OR $40000000;
 
3887
    float64_to_float32.float32 := roundAndPackFloat32( aSign, aExp - $381, zSig );
 
3888
End;
 
3889
 
 
3890
{*
 
3891
-------------------------------------------------------------------------------
 
3892
Rounds the double-precision floating-point value `a' to an integer,
 
3893
and returns the result as a double-precision floating-point value.  The
 
3894
operation is performed according to the IEC/IEEE Standard for Binary
 
3895
Floating-Point Arithmetic.
 
3896
-------------------------------------------------------------------------------
 
3897
*}
 
3898
function float64_round_to_int(a: float64) : Float64;{$ifdef fpc} [public,Alias:'FLOAT64_ROUND_TO_INT'];compilerproc;{$endif}
 
3899
 
 
3900
Var
 
3901
    aSign: flag;
 
3902
    aExp: int16;
 
3903
    lastBitMask, roundBitsMask: bits32;
 
3904
    roundingMode: int8;
 
3905
    z: float64;
 
3906
Begin
 
3907
    aExp := extractFloat64Exp( a );
 
3908
    if ( $413 <= aExp ) then
 
3909
    Begin
 
3910
        if ( $433 <= aExp ) then
 
3911
        Begin
 
3912
            if (    ( aExp = $7FF )
 
3913
                 AND
 
3914
            (
 
3915
            ( extractFloat64Frac0( a ) OR  extractFloat64Frac1( a )
 
3916
            ) <>0)
 
3917
            )  then
 
3918
            Begin
 
3919
                propagateFloat64NaN( a, a, result );
 
3920
                exit;
 
3921
            End;
 
3922
            result := a;
 
3923
            exit;
 
3924
        End;
 
3925
        lastBitMask := 1;
 
3926
        lastBitMask := ( lastBitMask shl ( $432 - aExp ) ) shl 1;
 
3927
        roundBitsMask := lastBitMask - 1;
 
3928
        z := a;
 
3929
        roundingMode := float_rounding_mode;
 
3930
        if ( roundingMode = float_round_nearest_even ) then
 
3931
        Begin
 
3932
            if ( lastBitMask <> 0) then
 
3933
            Begin
 
3934
                add64( z.high, z.low, 0, lastBitMask shr 1, z.high, z.low );
 
3935
                if ( ( z.low and roundBitsMask ) = 0 ) then
 
3936
                   z.low := z.low and not lastBitMask;
 
3937
            End
 
3938
            else
 
3939
            Begin
 
3940
                if ( sbits32 (z.low) < 0 ) then
 
3941
                Begin
 
3942
                    Inc(z.high);
 
3943
                    if ( bits32 ( z.low shl 1 ) = 0 ) then
 
3944
                      z.high := z.high and not 1;
 
3945
                End;
 
3946
            End;
 
3947
        End
 
3948
        else if ( roundingMode <> float_round_to_zero ) then
 
3949
        Begin
 
3950
            if (   extractFloat64Sign( z )
 
3951
                 xor flag( roundingMode = float_round_up ) )<> 0 then
 
3952
            Begin
 
3953
                add64( z.high, z.low, 0, roundBitsMask, z.high, z.low );
 
3954
            End;
 
3955
        End;
 
3956
        z.low := z.low and not roundBitsMask;
 
3957
    End
 
3958
    else
 
3959
    Begin
 
3960
        if ( aExp <= $3FE ) then
 
3961
        Begin
 
3962
            if ( ( ( bits32 ( a.high shl 1 ) ) OR  a.low ) = 0 ) then
 
3963
            Begin
 
3964
                result := a;
 
3965
                exit;
 
3966
            End;
 
3967
            softfloat_exception_flags := softfloat_exception_flags or
 
3968
               float_flag_inexact;
 
3969
            aSign := extractFloat64Sign( a );
 
3970
            case ( float_rounding_mode ) of
 
3971
             float_round_nearest_even:
 
3972
               Begin
 
3973
                if (    ( aExp = $3FE )
 
3974
                     AND  ( (extractFloat64Frac0( a ) OR  extractFloat64Frac1( a ) )<>0)
 
3975
                   ) then
 
3976
                Begin
 
3977
                    packFloat64( aSign, $3FF, 0, 0, result );
 
3978
                    exit;
 
3979
                End;
 
3980
 
 
3981
               End;
 
3982
               float_round_down:
 
3983
                Begin
 
3984
                  if aSign<>0 then
 
3985
                   packFloat64( 1, $3FF, 0, 0, result )
 
3986
                  else
 
3987
                   packFloat64( 0, 0, 0, 0, result );
 
3988
                  exit;
 
3989
                End;
 
3990
             float_round_up:
 
3991
                Begin
 
3992
                  if aSign <> 0 then
 
3993
                   packFloat64( 1, 0, 0, 0, result )
 
3994
                  else
 
3995
                   packFloat64( 0, $3FF, 0, 0, result );
 
3996
                  exit;
 
3997
                End;
 
3998
            end;
 
3999
            packFloat64( aSign, 0, 0, 0, result );
 
4000
            exit;
 
4001
        End;
 
4002
        lastBitMask := 1;
 
4003
        lastBitMask := lastBitMask shl ($413 - aExp);
 
4004
        roundBitsMask := lastBitMask - 1;
 
4005
        z.low := 0;
 
4006
        z.high := a.high;
 
4007
        roundingMode := float_rounding_mode;
 
4008
        if ( roundingMode = float_round_nearest_even ) then
 
4009
        Begin
 
4010
            z.high := z.high + lastBitMask shr 1;
 
4011
            if ( ( ( z.high and roundBitsMask ) OR  a.low ) = 0 ) then
 
4012
            Begin
 
4013
                z.high := z.high and not lastBitMask;
 
4014
            End;
 
4015
        End
 
4016
        else if ( roundingMode <> float_round_to_zero ) then
 
4017
        Begin
 
4018
            if (   extractFloat64Sign( z )
 
4019
                 xor flag( roundingMode = float_round_up ) )<> 0 then
 
4020
            Begin
 
4021
                z.high := z.high or bits32( a.low <> 0 );
 
4022
                z.high := z.high + roundBitsMask;
 
4023
            End;
 
4024
        End;
 
4025
        z.high := z.high and not roundBitsMask;
 
4026
    End;
 
4027
    if ( ( z.low <> a.low ) OR ( z.high <> a.high ) ) then
 
4028
    Begin
 
4029
        softfloat_exception_flags :=
 
4030
          softfloat_exception_flags or float_flag_inexact;
 
4031
    End;
 
4032
    result := z;
 
4033
End;
 
4034
 
 
4035
 
 
4036
{*
 
4037
-------------------------------------------------------------------------------
 
4038
Returns the result of adding the absolute values of the double-precision
 
4039
floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
 
4040
before being returned.  `zSign' is ignored if the result is a NaN.
 
4041
The addition is performed according to the IEC/IEEE Standard for Binary
 
4042
Floating-Point Arithmetic.
 
4043
-------------------------------------------------------------------------------
 
4044
*}
 
4045
Procedure addFloat64Sigs( a:float64 ; b: float64 ; zSign:flag; Var out: float64 );
 
4046
Var
 
4047
    aExp, bExp, zExp: int16;
 
4048
    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits32;
 
4049
    expDiff: int16;
 
4050
    label shiftRight1;
 
4051
    label roundAndPack;
 
4052
Begin
 
4053
    aSig1 := extractFloat64Frac1( a );
 
4054
    aSig0 := extractFloat64Frac0( a );
 
4055
    aExp := extractFloat64Exp( a );
 
4056
    bSig1 := extractFloat64Frac1( b );
 
4057
    bSig0 := extractFloat64Frac0( b );
 
4058
    bExp := extractFloat64Exp( b );
 
4059
    expDiff := aExp - bExp;
 
4060
    if ( 0 < expDiff ) then
 
4061
    Begin
 
4062
        if ( aExp = $7FF ) then
 
4063
        Begin
 
4064
            if ( aSig0 OR  aSig1 ) <> 0 then
 
4065
            Begin
 
4066
              propagateFloat64NaN( a, b, out );
 
4067
              exit;
 
4068
            end;
 
4069
            out := a;
 
4070
            exit;
 
4071
        End;
 
4072
        if ( bExp = 0 ) then
 
4073
        Begin
 
4074
            Dec(expDiff);
 
4075
        End
 
4076
        else
 
4077
        Begin
 
4078
            bSig0 := bSig0 or $00100000;
 
4079
        End;
 
4080
        shift64ExtraRightJamming(
 
4081
            bSig0, bSig1, 0, expDiff, bSig0, bSig1, zSig2 );
 
4082
        zExp := aExp;
 
4083
    End
 
4084
    else if ( expDiff < 0 ) then
 
4085
    Begin
 
4086
        if ( bExp = $7FF ) then
 
4087
        Begin
 
4088
            if ( bSig0 OR  bSig1 ) <> 0 then
 
4089
            Begin
 
4090
               propagateFloat64NaN( a, b, out );
 
4091
               exit;
 
4092
            End;
 
4093
            packFloat64( zSign, $7FF, 0, 0, out );
 
4094
        End;
 
4095
        if ( aExp = 0 ) then
 
4096
        Begin
 
4097
            Inc(expDiff);
 
4098
        End
 
4099
        else
 
4100
        Begin
 
4101
            aSig0 := aSig0 or $00100000;
 
4102
        End;
 
4103
        shift64ExtraRightJamming(
 
4104
            aSig0, aSig1, 0, - expDiff, aSig0, aSig1, zSig2 );
 
4105
        zExp := bExp;
 
4106
    End
 
4107
    else
 
4108
    Begin
 
4109
        if ( aExp = $7FF ) then
 
4110
        Begin
 
4111
            if ( aSig0 OR  aSig1 OR  bSig0 OR  bSig1 ) <> 0 then
 
4112
            Begin
 
4113
                propagateFloat64NaN( a, b, out );
 
4114
                exit;
 
4115
            End;
 
4116
            out := a;
 
4117
            exit;
 
4118
        End;
 
4119
        add64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
 
4120
        if ( aExp = 0 ) then
 
4121
        Begin
 
4122
           packFloat64( zSign, 0, zSig0, zSig1, out );
 
4123
           exit;
 
4124
        End;
 
4125
        zSig2 := 0;
 
4126
        zSig0 := zSig0 or $00200000;
 
4127
        zExp := aExp;
 
4128
        goto shiftRight1;
 
4129
    End;
 
4130
    aSig0 := aSig0 or $00100000;
 
4131
    add64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
 
4132
    Dec(zExp);
 
4133
    if ( zSig0 < $00200000 ) then
 
4134
       goto roundAndPack;
 
4135
    Inc(zExp);
 
4136
 shiftRight1:
 
4137
    shift64ExtraRightJamming( zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
 
4138
 roundAndPack:
 
4139
    roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, out );
 
4140
 
 
4141
End;
 
4142
 
 
4143
{*
 
4144
-------------------------------------------------------------------------------
 
4145
Returns the result of subtracting the absolute values of the double-
 
4146
precision floating-point values `a' and `b'.  If `zSign' is 1, the
 
4147
difference is negated before being returned.  `zSign' is ignored if the
 
4148
result is a NaN.  The subtraction is performed according to the IEC/IEEE
 
4149
Standard for Binary Floating-Point Arithmetic.
 
4150
-------------------------------------------------------------------------------
 
4151
*}
 
4152
Procedure subFloat64Sigs( a:float64; b: float64 ; zSign:flag; Var out: float64 );
 
4153
Var
 
4154
    aExp, bExp, zExp: int16;
 
4155
    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1: bits32;
 
4156
    expDiff: int16;
 
4157
    z: float64;
 
4158
    label aExpBigger;
 
4159
    label bExpBigger;
 
4160
    label aBigger;
 
4161
    label bBigger;
 
4162
    label normalizeRoundAndPack;
 
4163
Begin
 
4164
    aSig1 := extractFloat64Frac1( a );
 
4165
    aSig0 := extractFloat64Frac0( a );
 
4166
    aExp := extractFloat64Exp( a );
 
4167
    bSig1 := extractFloat64Frac1( b );
 
4168
    bSig0 := extractFloat64Frac0( b );
 
4169
    bExp := extractFloat64Exp( b );
 
4170
    expDiff := aExp - bExp;
 
4171
    shortShift64Left( aSig0, aSig1, 10, aSig0, aSig1 );
 
4172
    shortShift64Left( bSig0, bSig1, 10, bSig0, bSig1 );
 
4173
    if ( 0 < expDiff ) then goto aExpBigger;
 
4174
    if ( expDiff < 0 ) then goto bExpBigger;
 
4175
    if ( aExp = $7FF ) then
 
4176
    Begin
 
4177
        if ( aSig0 OR  aSig1 OR  bSig0 OR  bSig1 ) <> 0 then
 
4178
        Begin
 
4179
            propagateFloat64NaN( a, b, out );
 
4180
            exit;
 
4181
        End;
 
4182
        float_raise( float_flag_invalid );
 
4183
        z.low := float64_default_nan_low;
 
4184
        z.high := float64_default_nan_high;
 
4185
        out := z;
 
4186
        exit;
 
4187
    End;
 
4188
    if ( aExp = 0 ) then
 
4189
    Begin
 
4190
        aExp := 1;
 
4191
        bExp := 1;
 
4192
    End;
 
4193
    if ( bSig0 < aSig0 ) then goto aBigger;
 
4194
    if ( aSig0 < bSig0 ) then goto bBigger;
 
4195
    if ( bSig1 < aSig1 ) then goto aBigger;
 
4196
    if ( aSig1 < bSig1 ) then goto bBigger;
 
4197
    packFloat64( flag(float_rounding_mode = float_round_down), 0, 0, 0 , out);
 
4198
    exit;
 
4199
 bExpBigger:
 
4200
    if ( bExp = $7FF ) then
 
4201
    Begin
 
4202
        if ( bSig0 OR  bSig1 ) <> 0 then
 
4203
        Begin
 
4204
           propagateFloat64NaN( a, b, out );
 
4205
           exit;
 
4206
        End;
 
4207
        packFloat64( zSign xor 1, $7FF, 0, 0, out );
 
4208
        exit;
 
4209
    End;
 
4210
    if ( aExp = 0 ) then
 
4211
    Begin
 
4212
        Inc(expDiff);
 
4213
    End
 
4214
    else
 
4215
    Begin
 
4216
        aSig0 := aSig0 or $40000000;
 
4217
    End;
 
4218
    shift64RightJamming( aSig0, aSig1, - expDiff, aSig0, aSig1 );
 
4219
    bSig0 := bSig0 or $40000000;
 
4220
 bBigger:
 
4221
    sub64( bSig0, bSig1, aSig0, aSig1, zSig0, zSig1 );
 
4222
    zExp := bExp;
 
4223
    zSign := zSign xor 1;
 
4224
    goto normalizeRoundAndPack;
 
4225
 aExpBigger:
 
4226
    if ( aExp = $7FF ) then
 
4227
    Begin
 
4228
        if ( aSig0 OR  aSig1 ) <> 0 then
 
4229
        Begin
 
4230
           propagateFloat64NaN( a, b, out );
 
4231
           exit;
 
4232
        End;
 
4233
        out :=  a;
 
4234
        exit;
 
4235
    End;
 
4236
    if ( bExp = 0 ) then
 
4237
    Begin
 
4238
        Dec(expDiff);
 
4239
    End
 
4240
    else
 
4241
    Begin
 
4242
        bSig0 := bSig0 or $40000000;
 
4243
    End;
 
4244
    shift64RightJamming( bSig0, bSig1, expDiff, bSig0, bSig1 );
 
4245
    aSig0 := aSig0 or $40000000;
 
4246
 aBigger:
 
4247
    sub64( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1 );
 
4248
    zExp := aExp;
 
4249
 normalizeRoundAndPack:
 
4250
    Dec(zExp);
 
4251
    normalizeRoundAndPackFloat64( zSign, zExp - 10, zSig0, zSig1, out );
 
4252
 
 
4253
End;
 
4254
 
 
4255
{*
 
4256
-------------------------------------------------------------------------------
 
4257
Returns the result of adding the double-precision floating-point values `a'
 
4258
and `b'.  The operation is performed according to the IEC/IEEE Standard for
 
4259
Binary Floating-Point Arithmetic.
 
4260
-------------------------------------------------------------------------------
 
4261
*}
 
4262
Function float64_add( a: float64; b : float64) : Float64;
 
4263
{$ifdef fpc}[public,Alias:'FLOAT64_ADD'];compilerproc;{$endif}
 
4264
Var
 
4265
    aSign, bSign: flag;
 
4266
Begin
 
4267
    aSign := extractFloat64Sign( a );
 
4268
    bSign := extractFloat64Sign( b );
 
4269
    if ( aSign = bSign ) then
 
4270
    Begin
 
4271
         addFloat64Sigs( a, b, aSign, result );
 
4272
    End
 
4273
    else
 
4274
    Begin
 
4275
        subFloat64Sigs( a, b, aSign, result );
 
4276
    End;
 
4277
End;
 
4278
 
 
4279
{*
 
4280
-------------------------------------------------------------------------------
 
4281
Returns the result of subtracting the double-precision floating-point values
 
4282
`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
 
4283
for Binary Floating-Point Arithmetic.
 
4284
-------------------------------------------------------------------------------
 
4285
*}
 
4286
Function float64_sub(a: float64; b : float64) : Float64;
 
4287
{$ifdef fpc}[public,Alias:'FLOAT64_SUB'];compilerproc;{$endif}
 
4288
Var
 
4289
    aSign, bSign: flag;
 
4290
Begin
 
4291
    aSign := extractFloat64Sign( a );
 
4292
    bSign := extractFloat64Sign( b );
 
4293
    if ( aSign = bSign ) then
 
4294
    Begin
 
4295
        subFloat64Sigs( a, b, aSign, result );
 
4296
    End
 
4297
    else
 
4298
    Begin
 
4299
        addFloat64Sigs( a, b, aSign, result );
 
4300
    End;
 
4301
End;
 
4302
 
 
4303
{*
 
4304
-------------------------------------------------------------------------------
 
4305
Returns the result of multiplying the double-precision floating-point values
 
4306
`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
 
4307
for Binary Floating-Point Arithmetic.
 
4308
-------------------------------------------------------------------------------
 
4309
*}
 
4310
Function float64_mul( a: float64; b:float64) : Float64;
 
4311
{$ifdef fpc}[public,Alias:'FLOAT64_MUL'];compilerproc;{$endif}
 
4312
Var
 
4313
    aSign, bSign, zSign: flag;
 
4314
    aExp, bExp, zExp: int16;
 
4315
    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3: bits32;
 
4316
    z: float64;
 
4317
    label invalid;
 
4318
Begin
 
4319
    aSig1 := extractFloat64Frac1( a );
 
4320
    aSig0 := extractFloat64Frac0( a );
 
4321
    aExp := extractFloat64Exp( a );
 
4322
    aSign := extractFloat64Sign( a );
 
4323
    bSig1 := extractFloat64Frac1( b );
 
4324
    bSig0 := extractFloat64Frac0( b );
 
4325
    bExp := extractFloat64Exp( b );
 
4326
    bSign := extractFloat64Sign( b );
 
4327
    zSign := aSign xor bSign;
 
4328
    if ( aExp = $7FF ) then
 
4329
    Begin
 
4330
        if (    (( aSig0 OR  aSig1 ) <>0)
 
4331
             OR ( ( bExp = $7FF ) AND  (( bSig0 OR  bSig1 )<>0) ) ) then
 
4332
        Begin
 
4333
            propagateFloat64NaN( a, b, result );
 
4334
            exit;
 
4335
        End;
 
4336
        if ( ( bExp OR  bSig0 OR  bSig1 ) = 0 ) then goto invalid;
 
4337
        packFloat64( zSign, $7FF, 0, 0, result );
 
4338
        exit;
 
4339
    End;
 
4340
    if ( bExp = $7FF ) then
 
4341
    Begin
 
4342
        if ( bSig0 OR  bSig1 )<> 0 then
 
4343
        Begin
 
4344
          propagateFloat64NaN( a, b, result );
 
4345
          exit;
 
4346
        End;
 
4347
        if ( ( aExp OR  aSig0 OR  aSig1 ) = 0 ) then
 
4348
        Begin
 
4349
 invalid:
 
4350
            float_raise( float_flag_invalid );
 
4351
            z.low := float64_default_nan_low;
 
4352
            z.high := float64_default_nan_high;
 
4353
            result := z;
 
4354
            exit;
 
4355
        End;
 
4356
        packFloat64( zSign, $7FF, 0, 0, result );
 
4357
        exit;
 
4358
    End;
 
4359
    if ( aExp = 0 ) then
 
4360
    Begin
 
4361
        if ( ( aSig0 OR  aSig1 ) = 0 ) then
 
4362
        Begin
 
4363
           packFloat64( zSign, 0, 0, 0, result );
 
4364
           exit;
 
4365
        End;
 
4366
        normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
 
4367
    End;
 
4368
    if ( bExp = 0 ) then
 
4369
    Begin
 
4370
        if ( ( bSig0 OR  bSig1 ) = 0 ) then
 
4371
        Begin
 
4372
          packFloat64( zSign, 0, 0, 0, result );
 
4373
          exit;
 
4374
        End;
 
4375
        normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
 
4376
    End;
 
4377
    zExp := aExp + bExp - $400;
 
4378
    aSig0 := aSig0 or $00100000;
 
4379
    shortShift64Left( bSig0, bSig1, 12, bSig0, bSig1 );
 
4380
    mul64To128( aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3 );
 
4381
    add64( zSig0, zSig1, aSig0, aSig1, zSig0, zSig1 );
 
4382
    zSig2 := zSig2 or flag( zSig3 <> 0 );
 
4383
    if ( $00200000 <= zSig0 ) then
 
4384
    Begin
 
4385
        shift64ExtraRightJamming(
 
4386
            zSig0, zSig1, zSig2, 1, zSig0, zSig1, zSig2 );
 
4387
        Inc(zExp);
 
4388
    End;
 
4389
    roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, result );
 
4390
End;
 
4391
 
 
4392
{*
 
4393
-------------------------------------------------------------------------------
 
4394
Returns the result of dividing the double-precision floating-point value `a'
 
4395
by the corresponding value `b'.  The operation is performed according to the
 
4396
IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
4397
-------------------------------------------------------------------------------
 
4398
*}
 
4399
Function float64_div(a: float64; b : float64) : Float64;
 
4400
{$ifdef fpc}[public,Alias:'FLOAT64_DIV'];compilerproc;{$endif}
 
4401
Var
 
4402
    aSign, bSign, zSign: flag;
 
4403
    aExp, bExp, zExp: int16;
 
4404
    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits32;
 
4405
    rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits32;
 
4406
    z: float64;
 
4407
    label invalid;
 
4408
Begin
 
4409
    aSig1 := extractFloat64Frac1( a );
 
4410
    aSig0 := extractFloat64Frac0( a );
 
4411
    aExp := extractFloat64Exp( a );
 
4412
    aSign := extractFloat64Sign( a );
 
4413
    bSig1 := extractFloat64Frac1( b );
 
4414
    bSig0 := extractFloat64Frac0( b );
 
4415
    bExp := extractFloat64Exp( b );
 
4416
    bSign := extractFloat64Sign( b );
 
4417
    zSign := aSign xor bSign;
 
4418
    if ( aExp = $7FF ) then
 
4419
    Begin
 
4420
        if ( aSig0 OR  aSig1 )<> 0 then
 
4421
        Begin
 
4422
           propagateFloat64NaN( a, b, result );
 
4423
           exit;
 
4424
        end;
 
4425
        if ( bExp = $7FF ) then
 
4426
        Begin
 
4427
            if ( bSig0 OR  bSig1 )<>0 then
 
4428
            Begin
 
4429
               propagateFloat64NaN( a, b, result );
 
4430
               exit;
 
4431
            End;
 
4432
            goto invalid;
 
4433
        End;
 
4434
        packFloat64( zSign, $7FF, 0, 0, result );
 
4435
        exit;
 
4436
    End;
 
4437
    if ( bExp = $7FF ) then
 
4438
    Begin
 
4439
        if ( bSig0 OR  bSig1 )<> 0 then
 
4440
        Begin
 
4441
          propagateFloat64NaN( a, b, result );
 
4442
          exit;
 
4443
        End;
 
4444
        packFloat64( zSign, 0, 0, 0, result );
 
4445
        exit;
 
4446
    End;
 
4447
    if ( bExp = 0 ) then
 
4448
    Begin
 
4449
        if ( ( bSig0 OR  bSig1 ) = 0 ) then
 
4450
        Begin
 
4451
            if ( ( aExp OR  aSig0 OR  aSig1 ) = 0 ) then
 
4452
            Begin
 
4453
 invalid:
 
4454
                float_raise( float_flag_invalid );
 
4455
                z.low := float64_default_nan_low;
 
4456
                z.high := float64_default_nan_high;
 
4457
                result := z;
 
4458
                exit;
 
4459
            End;
 
4460
            float_raise( float_flag_divbyzero );
 
4461
            packFloat64( zSign, $7FF, 0, 0, result );
 
4462
            exit;
 
4463
        End;
 
4464
        normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
 
4465
    End;
 
4466
    if ( aExp = 0 ) then
 
4467
    Begin
 
4468
        if ( ( aSig0 OR  aSig1 ) = 0 ) then
 
4469
        Begin
 
4470
           packFloat64( zSign, 0, 0, 0, result );
 
4471
           exit;
 
4472
        End;
 
4473
        normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
 
4474
    End;
 
4475
    zExp := aExp - bExp + $3FD;
 
4476
    shortShift64Left( aSig0 OR  $00100000, aSig1, 11, aSig0, aSig1 );
 
4477
    shortShift64Left( bSig0 OR  $00100000, bSig1, 11, bSig0, bSig1 );
 
4478
    if ( le64( bSig0, bSig1, aSig0, aSig1 )<>0 ) then
 
4479
    Begin
 
4480
        shift64Right( aSig0, aSig1, 1, aSig0, aSig1 );
 
4481
        Inc(zExp);
 
4482
    End;
 
4483
    zSig0 := estimateDiv64To32( aSig0, aSig1, bSig0 );
 
4484
    mul64By32To96( bSig0, bSig1, zSig0, term0, term1, term2 );
 
4485
    sub96( aSig0, aSig1, 0, term0, term1, term2, rem0, rem1, rem2 );
 
4486
    while ( sbits32 (rem0) < 0 ) do
 
4487
    Begin
 
4488
        Dec(zSig0);
 
4489
        add96( rem0, rem1, rem2, 0, bSig0, bSig1, rem0, rem1, rem2 );
 
4490
    End;
 
4491
    zSig1 := estimateDiv64To32( rem1, rem2, bSig0 );
 
4492
    if ( ( zSig1 and $3FF ) <= 4 ) then
 
4493
    Begin
 
4494
        mul64By32To96( bSig0, bSig1, zSig1, term1, term2, term3 );
 
4495
        sub96( rem1, rem2, 0, term1, term2, term3, rem1, rem2, rem3 );
 
4496
        while ( sbits32 (rem1) < 0 ) do
 
4497
        Begin
 
4498
            Dec(zSig1);
 
4499
            add96( rem1, rem2, rem3, 0, bSig0, bSig1, rem1, rem2, rem3 );
 
4500
        End;
 
4501
        zSig1 := zSig1 or flag( ( rem1 OR  rem2 OR  rem3 ) <> 0 );
 
4502
    End;
 
4503
    shift64ExtraRightJamming( zSig0, zSig1, 0, 11, zSig0, zSig1, zSig2 );
 
4504
    roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2, result );
 
4505
 
 
4506
End;
 
4507
 
 
4508
{*
 
4509
-------------------------------------------------------------------------------
 
4510
Returns the remainder of the double-precision floating-point value `a'
 
4511
with respect to the corresponding value `b'.  The operation is performed
 
4512
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
4513
-------------------------------------------------------------------------------
 
4514
*}
 
4515
Function float64_rem(a: float64; b : float64) : float64;
 
4516
{$ifdef fpc}[public,Alias:'FLOAT64_REM'];compilerproc;{$endif}
 
4517
Var
 
4518
    aSign, bSign, zSign: flag;
 
4519
    aExp, bExp, expDiff: int16;
 
4520
    aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2: bits32;
 
4521
    allZero, alternateASig0, alternateASig1, sigMean1: bits32;
 
4522
    sigMean0: sbits32;
 
4523
    z: float64;
 
4524
    label invalid;
 
4525
Begin
 
4526
    aSig1 := extractFloat64Frac1( a );
 
4527
    aSig0 := extractFloat64Frac0( a );
 
4528
    aExp := extractFloat64Exp( a );
 
4529
    aSign := extractFloat64Sign( a );
 
4530
    bSig1 := extractFloat64Frac1( b );
 
4531
    bSig0 := extractFloat64Frac0( b );
 
4532
    bExp := extractFloat64Exp( b );
 
4533
    bSign := extractFloat64Sign( b );
 
4534
    if ( aExp = $7FF ) then
 
4535
    Begin
 
4536
        if ((( aSig0 OR  aSig1 )<>0)
 
4537
             OR ( ( bExp = $7FF ) AND  (( bSig0 OR  bSig1 )<>0) ) ) then
 
4538
        Begin
 
4539
            propagateFloat64NaN( a, b, result );
 
4540
            exit;
 
4541
        End;
 
4542
        goto invalid;
 
4543
    End;
 
4544
    if ( bExp = $7FF ) then
 
4545
    Begin
 
4546
        if ( bSig0 OR  bSig1 ) <> 0 then
 
4547
        Begin
 
4548
          propagateFloat64NaN( a, b, result );
 
4549
          exit;
 
4550
        End;
 
4551
        result := a;
 
4552
        exit;
 
4553
    End;
 
4554
    if ( bExp = 0 ) then
 
4555
    Begin
 
4556
        if ( ( bSig0 OR  bSig1 ) = 0 ) then
 
4557
        Begin
 
4558
 invalid:
 
4559
            float_raise( float_flag_invalid );
 
4560
            z.low := float64_default_nan_low;
 
4561
            z.high := float64_default_nan_high;
 
4562
            result := z;
 
4563
            exit;
 
4564
        End;
 
4565
        normalizeFloat64Subnormal( bSig0, bSig1, bExp, bSig0, bSig1 );
 
4566
    End;
 
4567
    if ( aExp = 0 ) then
 
4568
    Begin
 
4569
        if ( ( aSig0 OR  aSig1 ) = 0 ) then
 
4570
        Begin
 
4571
           result := a;
 
4572
           exit;
 
4573
        End;
 
4574
        normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
 
4575
    End;
 
4576
    expDiff := aExp - bExp;
 
4577
    if ( expDiff < -1 ) then
 
4578
    Begin
 
4579
       result := a;
 
4580
       exit;
 
4581
    End;
 
4582
    shortShift64Left(
 
4583
        aSig0 OR  $00100000, aSig1, 11 - flag( expDiff < 0 ), aSig0, aSig1 );
 
4584
    shortShift64Left( bSig0 OR  $00100000, bSig1, 11, bSig0, bSig1 );
 
4585
    q := le64( bSig0, bSig1, aSig0, aSig1 );
 
4586
    if ( q )<>0 then
 
4587
       sub64( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
 
4588
    expDiff := expDiff - 32;
 
4589
    while ( 0 < expDiff ) do
 
4590
    Begin
 
4591
        q := estimateDiv64To32( aSig0, aSig1, bSig0 );
 
4592
        if 4 < q then
 
4593
          q:= q - 4
 
4594
        else
 
4595
          q := 0;
 
4596
        mul64By32To96( bSig0, bSig1, q, term0, term1, term2 );
 
4597
        shortShift96Left( term0, term1, term2, 29, term1, term2, allZero );
 
4598
        shortShift64Left( aSig0, aSig1, 29, aSig0, allZero );
 
4599
        sub64( aSig0, 0, term1, term2, aSig0, aSig1 );
 
4600
        expDiff := expDiff - 29;
 
4601
    End;
 
4602
    if ( -32 < expDiff ) then
 
4603
    Begin
 
4604
        q := estimateDiv64To32( aSig0, aSig1, bSig0 );
 
4605
        if 4 < q then
 
4606
          q := q - 4
 
4607
        else
 
4608
          q := 0;
 
4609
        q := q shr (- expDiff);
 
4610
        shift64Right( bSig0, bSig1, 8, bSig0, bSig1 );
 
4611
        expDiff := expDiff + 24;
 
4612
        if ( expDiff < 0 ) then
 
4613
        Begin
 
4614
            shift64Right( aSig0, aSig1, - expDiff, aSig0, aSig1 );
 
4615
        End
 
4616
        else
 
4617
        Begin
 
4618
            shortShift64Left( aSig0, aSig1, expDiff, aSig0, aSig1 );
 
4619
        End;
 
4620
        mul64By32To96( bSig0, bSig1, q, term0, term1, term2 );
 
4621
        sub64( aSig0, aSig1, term1, term2, aSig0, aSig1 );
 
4622
    End
 
4623
    else
 
4624
    Begin
 
4625
        shift64Right( aSig0, aSig1, 8, aSig0, aSig1 );
 
4626
        shift64Right( bSig0, bSig1, 8, bSig0, bSig1 );
 
4627
    End;
 
4628
    Repeat
 
4629
        alternateASig0 := aSig0;
 
4630
        alternateASig1 := aSig1;
 
4631
        Inc(q);
 
4632
        sub64( aSig0, aSig1, bSig0, bSig1, aSig0, aSig1 );
 
4633
    Until not ( 0 <= sbits32 (aSig0) );
 
4634
    add64(
 
4635
        aSig0, aSig1, alternateASig0, alternateASig1, bits32(sigMean0), sigMean1 );
 
4636
    if (    ( sigMean0 < 0 )
 
4637
         OR ( ( ( sigMean0 OR  sigMean1 ) = 0 ) AND  (( q AND 1 )<>0) ) ) then
 
4638
    Begin
 
4639
        aSig0 := alternateASig0;
 
4640
        aSig1 := alternateASig1;
 
4641
    End;
 
4642
    zSign := flag( sbits32 (aSig0) < 0 );
 
4643
    if ( zSign <> 0 ) then
 
4644
       sub64( 0, 0, aSig0, aSig1, aSig0, aSig1 );
 
4645
    normalizeRoundAndPackFloat64( aSign xor zSign, bExp - 4, aSig0, aSig1, result );
 
4646
End;
 
4647
 
 
4648
{*
 
4649
-------------------------------------------------------------------------------
 
4650
Returns the square root of the double-precision floating-point value `a'.
 
4651
The operation is performed according to the IEC/IEEE Standard for Binary
 
4652
Floating-Point Arithmetic.
 
4653
-------------------------------------------------------------------------------
 
4654
*}
 
4655
Procedure float64_sqrt( a: float64; var out: float64 );
 
4656
{$ifdef fpc}[public,Alias:'FLOAT64_SQRT'];compilerproc;{$endif}
 
4657
Var
 
4658
    aSign: flag;
 
4659
    aExp, zExp: int16;
 
4660
    aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0: bits32;
 
4661
    rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits32;
 
4662
    z: float64;
 
4663
    label invalid;
 
4664
Begin
 
4665
    aSig1 := extractFloat64Frac1( a );
 
4666
    aSig0 := extractFloat64Frac0( a );
 
4667
    aExp := extractFloat64Exp( a );
 
4668
    aSign := extractFloat64Sign( a );
 
4669
    if ( aExp = $7FF ) then
 
4670
    Begin
 
4671
        if ( aSig0 OR  aSig1 ) <> 0 then
 
4672
        Begin
 
4673
           propagateFloat64NaN( a, a, out );
 
4674
           exit;
 
4675
        End;
 
4676
        if ( aSign = 0) then
 
4677
        Begin
 
4678
          out := a;
 
4679
          exit;
 
4680
        End;
 
4681
        goto invalid;
 
4682
    End;
 
4683
    if ( aSign <> 0 ) then
 
4684
    Begin
 
4685
        if ( ( aExp OR  aSig0 OR  aSig1 ) = 0 ) then
 
4686
        Begin
 
4687
           out := a;
 
4688
           exit;
 
4689
        End;
 
4690
 invalid:
 
4691
        float_raise( float_flag_invalid );
 
4692
        z.low := float64_default_nan_low;
 
4693
        z.high := float64_default_nan_high;
 
4694
        out := z;
 
4695
        exit;
 
4696
    End;
 
4697
    if ( aExp = 0 ) then
 
4698
    Begin
 
4699
        if ( ( aSig0 OR  aSig1 ) = 0 ) then
 
4700
        Begin
 
4701
           packFloat64( 0, 0, 0, 0, out );
 
4702
           exit;
 
4703
        End;
 
4704
        normalizeFloat64Subnormal( aSig0, aSig1, aExp, aSig0, aSig1 );
 
4705
    End;
 
4706
    zExp := ( ( aExp - $3FF ) shr 1 ) + $3FE;
 
4707
    aSig0 := aSig0 or $00100000;
 
4708
    shortShift64Left( aSig0, aSig1, 11, term0, term1 );
 
4709
    zSig0 := ( estimateSqrt32( aExp, term0 ) shr 1 ) + 1;
 
4710
    if ( zSig0 = 0 ) then
 
4711
       zSig0 := $7FFFFFFF;
 
4712
    doubleZSig0 := zSig0 + zSig0;
 
4713
    shortShift64Left( aSig0, aSig1, 9 - ( aExp and 1 ), aSig0, aSig1 );
 
4714
    mul32To64( zSig0, zSig0, term0, term1 );
 
4715
    sub64( aSig0, aSig1, term0, term1, rem0, rem1 );
 
4716
    while ( sbits32 (rem0) < 0 ) do
 
4717
    Begin
 
4718
        Dec(zSig0);
 
4719
        doubleZSig0 := doubleZSig0 - 2;
 
4720
        add64( rem0, rem1, 0, doubleZSig0 OR  1, rem0, rem1 );
 
4721
    End;
 
4722
    zSig1 := estimateDiv64To32( rem1, 0, doubleZSig0 );
 
4723
    if ( ( zSig1 and $1FF ) <= 5 ) then
 
4724
    Begin
 
4725
        if ( zSig1 = 0 ) then
 
4726
           zSig1 := 1;
 
4727
        mul32To64( doubleZSig0, zSig1, term1, term2 );
 
4728
        sub64( rem1, 0, term1, term2, rem1, rem2 );
 
4729
        mul32To64( zSig1, zSig1, term2, term3 );
 
4730
        sub96( rem1, rem2, 0, 0, term2, term3, rem1, rem2, rem3 );
 
4731
        while ( sbits32 (rem1) < 0 ) do
 
4732
        Begin
 
4733
            Dec(zSig1);
 
4734
            shortShift64Left( 0, zSig1, 1, term2, term3 );
 
4735
            term3 := term3 or 1;
 
4736
            term2 := term2 or doubleZSig0;
 
4737
            add96( rem1, rem2, rem3, 0, term2, term3, rem1, rem2, rem3 );
 
4738
        End;
 
4739
        zSig1 := zSig1 or bits32( ( rem1 OR  rem2 OR  rem3 ) <> 0 );
 
4740
    End;
 
4741
    shift64ExtraRightJamming( zSig0, zSig1, 0, 10, zSig0, zSig1, zSig2 );
 
4742
    roundAndPackFloat64( 0, zExp, zSig0, zSig1, zSig2, out );
 
4743
End;
 
4744
 
 
4745
{*
 
4746
-------------------------------------------------------------------------------
 
4747
Returns 1 if the double-precision floating-point value `a' is equal to
 
4748
the corresponding value `b', and 0 otherwise.  The comparison is performed
 
4749
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
4750
-------------------------------------------------------------------------------
 
4751
*}
 
4752
Function float64_eq(a: float64; b: float64): flag;
 
4753
{$ifdef fpc}[public,Alias:'FLOAT64_EQ'];compilerproc;{$endif}
 
4754
Begin
 
4755
    if
 
4756
         (
 
4757
                ( extractFloat64Exp( a ) = $7FF )
 
4758
            AND
 
4759
                (
 
4760
                    (extractFloat64Frac0( a )  OR  extractFloat64Frac1( a )) <>0
 
4761
                )
 
4762
         )
 
4763
         OR (
 
4764
                ( extractFloat64Exp( b ) = $7FF )
 
4765
           AND  (
 
4766
                    (extractFloat64Frac0( b ) OR  (extractFloat64Frac1( b )) <> 0
 
4767
                )
 
4768
           )
 
4769
       ) then
 
4770
    Begin
 
4771
        if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
 
4772
            float_raise( float_flag_invalid );
 
4773
        float64_eq := 0;
 
4774
        exit;
 
4775
    End;
 
4776
    float64_eq := flag(
 
4777
           ( a.low = b.low )
 
4778
        AND  (    ( a.high = b.high )
 
4779
             OR (    ( a.low = 0 )
 
4780
                  AND  ( bits32 ( ( a.high OR  b.high ) shl 1 ) = 0 ) )
 
4781
           ));
 
4782
End;
 
4783
 
 
4784
{*
 
4785
-------------------------------------------------------------------------------
 
4786
Returns 1 if the double-precision floating-point value `a' is less than
 
4787
or equal to the corresponding value `b', and 0 otherwise.  The comparison
 
4788
is performed according to the IEC/IEEE Standard for Binary Floating-Point
 
4789
Arithmetic.
 
4790
-------------------------------------------------------------------------------
 
4791
*}
 
4792
Function float64_le(a: float64;b: float64): flag;
 
4793
{$ifdef fpc}[public,Alias:'FLOAT64_LE'];compilerproc;{$endif}
 
4794
Var
 
4795
    aSign, bSign: flag;
 
4796
Begin
 
4797
    if
 
4798
         (
 
4799
                ( extractFloat64Exp( a ) = $7FF )
 
4800
            AND
 
4801
                (
 
4802
                    (extractFloat64Frac0( a )  OR  extractFloat64Frac1( a )) <>0
 
4803
                )
 
4804
         )
 
4805
         OR (
 
4806
                ( extractFloat64Exp( b ) = $7FF )
 
4807
           AND  (
 
4808
                    (extractFloat64Frac0( b ) OR  (extractFloat64Frac1( b )) <> 0
 
4809
                )
 
4810
           )
 
4811
       ) then
 
4812
    Begin
 
4813
        float_raise( float_flag_invalid );
 
4814
        float64_le := 0;
 
4815
        exit;
 
4816
    End;
 
4817
    aSign := extractFloat64Sign( a );
 
4818
    bSign := extractFloat64Sign( b );
 
4819
    if ( aSign <> bSign ) then
 
4820
    Begin
 
4821
        float64_le := flag(
 
4822
               (aSign <> 0)
 
4823
            OR (    ( ( bits32 ( ( a.high OR  b.high ) shl 1 ) ) OR  a.low OR  b.low )
 
4824
                 = 0 ));
 
4825
        exit;
 
4826
    End;
 
4827
    if aSign <> 0 then
 
4828
      float64_le := le64( b.high, b.low, a.high, a.low )
 
4829
    else
 
4830
      float64_le := le64( a.high, a.low, b.high, b.low );
 
4831
End;
 
4832
 
 
4833
{*
 
4834
-------------------------------------------------------------------------------
 
4835
Returns 1 if the double-precision floating-point value `a' is less than
 
4836
the corresponding value `b', and 0 otherwise.  The comparison is performed
 
4837
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
4838
-------------------------------------------------------------------------------
 
4839
*}
 
4840
Function float64_lt(a: float64;b: float64): flag;
 
4841
{$ifdef fpc}[public,Alias:'FLOAT64_LT'];compilerproc;{$endif}
 
4842
Var
 
4843
    aSign, bSign: flag;
 
4844
Begin
 
4845
    if
 
4846
         (
 
4847
                ( extractFloat64Exp( a ) = $7FF )
 
4848
            AND
 
4849
                (
 
4850
                    (extractFloat64Frac0( a )  OR  extractFloat64Frac1( a )) <>0
 
4851
                )
 
4852
         )
 
4853
         OR (
 
4854
                ( extractFloat64Exp( b ) = $7FF )
 
4855
           AND  (
 
4856
                    (extractFloat64Frac0( b ) OR  (extractFloat64Frac1( b )) <> 0
 
4857
                )
 
4858
           )
 
4859
       ) then
 
4860
    Begin
 
4861
        float_raise( float_flag_invalid );
 
4862
        float64_lt := 0;
 
4863
        exit;
 
4864
    End;
 
4865
    aSign := extractFloat64Sign( a );
 
4866
    bSign := extractFloat64Sign( b );
 
4867
    if ( aSign <> bSign ) then
 
4868
    Begin
 
4869
        float64_lt := flag(
 
4870
               (aSign <> 0)
 
4871
            AND  (    ( ( bits32 ( ( a.high OR  b.high ) shl 1 ) ) OR  a.low OR  b.low )
 
4872
                 <> 0 ));
 
4873
        exit;
 
4874
    End;
 
4875
    if aSign <> 0 then
 
4876
       float64_lt := lt64( b.high, b.low, a.high, a.low )
 
4877
    else
 
4878
       float64_lt := lt64( a.high, a.low, b.high, b.low );
 
4879
End;
 
4880
 
 
4881
{*
 
4882
-------------------------------------------------------------------------------
 
4883
Returns 1 if the double-precision floating-point value `a' is equal to
 
4884
the corresponding value `b', and 0 otherwise.  The invalid exception is
 
4885
raised if either operand is a NaN.  Otherwise, the comparison is performed
 
4886
according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
4887
-------------------------------------------------------------------------------
 
4888
*}
 
4889
Function float64_eq_signaling( a: float64; b: float64): flag;
 
4890
Begin
 
4891
 
 
4892
    if
 
4893
         (
 
4894
                ( extractFloat64Exp( a ) = $7FF )
 
4895
            AND
 
4896
                (
 
4897
                    (extractFloat64Frac0( a )  OR  extractFloat64Frac1( a )) <>0
 
4898
                )
 
4899
         )
 
4900
         OR (
 
4901
                ( extractFloat64Exp( b ) = $7FF )
 
4902
           AND  (
 
4903
                    (extractFloat64Frac0( b ) OR  (extractFloat64Frac1( b )) <> 0
 
4904
                )
 
4905
           )
 
4906
       ) then
 
4907
    Begin
 
4908
        float_raise( float_flag_invalid );
 
4909
        float64_eq_signaling := 0;
 
4910
        exit;
 
4911
    End;
 
4912
    float64_eq_signaling := flag(
 
4913
           ( a.low = b.low )
 
4914
        AND  (    ( a.high = b.high )
 
4915
             OR (    ( a.low = 0 )
 
4916
                  AND  ( bits32 ( ( a.high OR  b.high ) shl 1 ) = 0 ) )
 
4917
           ));
 
4918
End;
 
4919
 
 
4920
{*
 
4921
-------------------------------------------------------------------------------
 
4922
Returns 1 if the double-precision floating-point value `a' is less than or
 
4923
equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not
 
4924
cause an exception.  Otherwise, the comparison is performed according to the
 
4925
IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
4926
-------------------------------------------------------------------------------
 
4927
*}
 
4928
Function float64_le_quiet(a: float64 ; b: float64 ): flag;
 
4929
Var
 
4930
    aSign, bSign : flag;
 
4931
Begin
 
4932
    if
 
4933
         (
 
4934
                ( extractFloat64Exp( a ) = $7FF )
 
4935
            AND
 
4936
                (
 
4937
                    (extractFloat64Frac0( a )  OR  extractFloat64Frac1( a )) <>0
 
4938
                )
 
4939
         )
 
4940
         OR (
 
4941
                ( extractFloat64Exp( b ) = $7FF )
 
4942
           AND  (
 
4943
                    (extractFloat64Frac0( b ) OR  (extractFloat64Frac1( b )) <> 0
 
4944
                )
 
4945
           )
 
4946
       ) then
 
4947
    Begin
 
4948
        if ( (float64_is_signaling_nan( a )<>0)  OR (float64_is_signaling_nan( b )<>0) ) then
 
4949
            float_raise( float_flag_invalid );
 
4950
        float64_le_quiet := 0;
 
4951
        exit;
 
4952
    End;
 
4953
    aSign := extractFloat64Sign( a );
 
4954
    bSign := extractFloat64Sign( b );
 
4955
    if ( aSign <> bSign ) then
 
4956
    Begin
 
4957
     float64_le_quiet := flag
 
4958
      ((aSign <> 0)
 
4959
            OR (    ( ( bits32 ( ( a.high OR  b.high ) shl 1 ) ) OR  a.low OR  b.low )
 
4960
                 = 0 ));
 
4961
        exit;
 
4962
    End;
 
4963
    if aSign <> 0 then
 
4964
      float64_le_quiet := le64( b.high, b.low, a.high, a.low )
 
4965
    else
 
4966
      float64_le_quiet := le64( a.high, a.low, b.high, b.low );
 
4967
End;
 
4968
 
 
4969
{*
 
4970
-------------------------------------------------------------------------------
 
4971
Returns 1 if the double-precision floating-point value `a' is less than
 
4972
the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
 
4973
exception.  Otherwise, the comparison is performed according to the IEC/IEEE
 
4974
Standard for Binary Floating-Point Arithmetic.
 
4975
-------------------------------------------------------------------------------
 
4976
*}
 
4977
Function float64_lt_quiet(a: float64; b: float64 ): Flag;
 
4978
Var
 
4979
    aSign, bSign: flag;
 
4980
Begin
 
4981
    if
 
4982
         (
 
4983
                ( extractFloat64Exp( a ) = $7FF )
 
4984
            AND
 
4985
                (
 
4986
                    (extractFloat64Frac0( a )  OR  extractFloat64Frac1( a )) <>0
 
4987
                )
 
4988
         )
 
4989
         OR (
 
4990
                ( extractFloat64Exp( b ) = $7FF )
 
4991
           AND  (
 
4992
                    (extractFloat64Frac0( b ) OR  (extractFloat64Frac1( b )) <> 0
 
4993
                )
 
4994
           )
 
4995
       ) then
 
4996
    Begin
 
4997
        if ( (float64_is_signaling_nan( a )<>0) OR (float64_is_signaling_nan( b )<>0) ) then
 
4998
            float_raise( float_flag_invalid );
 
4999
        float64_lt_quiet := 0;
 
5000
        exit;
 
5001
    End;
 
5002
    aSign := extractFloat64Sign( a );
 
5003
    bSign := extractFloat64Sign( b );
 
5004
    if ( aSign <> bSign ) then
 
5005
    Begin
 
5006
      float64_lt_quiet := flag(
 
5007
               (aSign<>0)
 
5008
            AND  (    ( ( bits32 ( ( a.high OR  b.high ) shl 1 ) ) OR  a.low OR  b.low )
 
5009
                 <> 0 ));
 
5010
        exit;
 
5011
    End;
 
5012
    If aSign <> 0 then
 
5013
      float64_lt_quiet :=  lt64( b.high, b.low, a.high, a.low )
 
5014
    else
 
5015
      float64_lt_quiet := lt64( a.high, a.low, b.high, b.low );
 
5016
End;
 
5017
 
 
5018
 
 
5019
{*----------------------------------------------------------------------------
 
5020
| Returns the result of converting the 64-bit two's complement integer `a'
 
5021
| to the single-precision floating-point format.  The conversion is performed
 
5022
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
5023
*----------------------------------------------------------------------------*}
 
5024
function int64_to_float32( a: int64 ): float32rec; compilerproc;
 
5025
var
 
5026
    zSign : flag;
 
5027
    absA : uint64;
 
5028
    shiftCount: int8;
 
5029
    zSig : bits32;
 
5030
    intval : int64rec;
 
5031
Begin
 
5032
    if ( a = 0 ) then
 
5033
      begin
 
5034
       int64_to_float32.float32 := 0;
 
5035
       exit;
 
5036
      end;
 
5037
    if a < 0 then
 
5038
      zSign := flag(TRUE)
 
5039
    else
 
5040
      zSign := flag(FALSE);
 
5041
    if zSign<>0 then
 
5042
       absA := -a
 
5043
    else
 
5044
       absA := a;
 
5045
    shiftCount := countLeadingZeros64( absA ) - 40;
 
5046
    if ( 0 <= shiftCount ) then
 
5047
      begin
 
5048
        int64_to_float32.float32:= packFloat32( zSign, $95 - shiftCount, absA shl shiftCount );
 
5049
      end
 
5050
    else
 
5051
       begin
 
5052
        shiftCount := shiftCount + 7;
 
5053
        if ( shiftCount < 0 ) then
 
5054
          begin
 
5055
            intval.low := int64rec(AbsA).low;
 
5056
            intval.high := int64rec(AbsA).high;
 
5057
            shift64RightJamming( intval.low, intval.high, - shiftCount,
 
5058
               intval.low, intval.high);
 
5059
            int64rec(absA).low := intval.low;
 
5060
            int64rec(absA).high := intval.high;
 
5061
          end
 
5062
        else
 
5063
            absA := absA shl shiftCount;
 
5064
        int64_to_float32.float32:=roundAndPackFloat32( zSign, $9C - shiftCount, absA );
 
5065
      end;
 
5066
End;
 
5067
 
 
5068
 
 
5069
{*----------------------------------------------------------------------------
 
5070
| Returns the result of converting the 64-bit two's complement integer `a'
 
5071
| to the double-precision floating-point format.  The conversion is performed
 
5072
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
5073
*----------------------------------------------------------------------------*}
 
5074
function int64_to_float64( a: int64 ): float64;
 
5075
{$ifdef fpc}[public,Alias:'INT64_TO_FLOAT64'];compilerproc;{$endif}
 
5076
var
 
5077
 zSign : flag;
 
5078
 float_result : float64;
 
5079
 intval : int64rec;
 
5080
 AbsA : bits64;
 
5081
 shiftcount : int8;
 
5082
 zSig0, zSig1 : bits32;
 
5083
Begin
 
5084
    if ( a = 0 ) then
 
5085
      Begin
 
5086
       packFloat64( 0, 0, 0, 0, result );
 
5087
       exit;
 
5088
      end;
 
5089
    zSign := flag( a < 0 );
 
5090
    if ZSign<>0 then
 
5091
      AbsA := -a
 
5092
    else
 
5093
      AbsA := a;
 
5094
    shiftCount := countLeadingZeros64( absA ) - 11;
 
5095
    if ( 0 <= shiftCount ) then
 
5096
      Begin
 
5097
        absA := absA shl shiftcount;
 
5098
        zSig0:=int64rec(absA).high;
 
5099
        zSig1:=int64rec(absA).low;
 
5100
      End
 
5101
    else
 
5102
      Begin
 
5103
        shift64Right( absA, 0, - shiftCount, zSig0, zSig1 );
 
5104
      End;
 
5105
    packFloat64( zSign, $432 - shiftCount, zSig0, zSig1, float_result );
 
5106
    int64_to_float64:= float_result;
 
5107
End;
 
5108
 
 
5109
 
 
5110
{*----------------------------------------------------------------------------
 
5111
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
 
5112
| is equal to the 128-bit value formed by concatenating `b0' and `b1'.
 
5113
| Otherwise, returns 0.
 
5114
*----------------------------------------------------------------------------*}
 
5115
 
 
5116
function eq128( a0: bits64; a1: bits64; b0: bits64; b1 : bits64): flag;inline;
 
5117
begin
 
5118
    result := ord(( a0 = b0 ) and ( a1 = b1 ));
 
5119
end;
 
5120
 
 
5121
{*----------------------------------------------------------------------------
 
5122
| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
 
5123
| value formed by concatenating `b0' and `b1'.  Addition is modulo 2^128, so
 
5124
| any carry out is lost.  The result is broken into two 64-bit pieces which
 
5125
| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
 
5126
*----------------------------------------------------------------------------*}
 
5127
 
 
5128
procedure add128(a0: bits64; a1: bits64; b0: bits64; b1: bits64; var z0Ptr: bits64; var z1Ptr : bits64);inline;
 
5129
var
 
5130
    z1: bits64;
 
5131
begin
 
5132
    z1 := a1 + b1;
 
5133
    z1Ptr := z1;
 
5134
    z0Ptr := a0 + b0 + ord( z1 < a1 );
 
5135
end;
 
5136
 
 
5137
 
 
5138
{*----------------------------------------------------------------------------
 
5139
| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
 
5140
| by 64 _plus_ the number of bits given in `count'.  The shifted result is
 
5141
| at most 128 nonzero bits; these are broken into two 64-bit pieces which are
 
5142
| stored at the locations pointed to by `z0Ptr' and `z1Ptr'.  The bits shifted
 
5143
| off form a third 64-bit result as follows:  The _last_ bit shifted off is
 
5144
| the most-significant bit of the extra result, and the other 63 bits of the
 
5145
| extra result are all zero if and only if _all_but_the_last_ bits shifted off
 
5146
| were all zero.  This extra result is stored in the location pointed to by
 
5147
| `z2Ptr'.  The value of `count' can be arbitrarily large.
 
5148
|     (This routine makes more sense if `a0', `a1', and `a2' are considered
 
5149
| to form a fixed-point value with binary point between `a1' and `a2'.  This
 
5150
| fixed-point value is shifted right by the number of bits given in `count',
 
5151
| and the integer part of the result is returned at the locations pointed to
 
5152
| by `z0Ptr' and `z1Ptr'.  The fractional part of the result may be slightly
 
5153
| corrupted as described above, and is returned at the location pointed to by
 
5154
| `z2Ptr'.)
 
5155
*----------------------------------------------------------------------------*}
 
5156
 
 
5157
procedure shift128ExtraRightJamming(
 
5158
     a0: bits64;
 
5159
     a1: bits64;
 
5160
     a2: bits64;
 
5161
     count: int16;
 
5162
     var z0Ptr: bits64;
 
5163
     var z1Ptr: bits64;
 
5164
     var z2Ptr: bits64);
 
5165
var
 
5166
    z0, z1, z2: bits64;
 
5167
    negCount: int8;
 
5168
begin
 
5169
    negCount := ( - count ) and 63;
 
5170
 
 
5171
    if ( count = 0 ) then
 
5172
    begin
 
5173
        z2 := a2;
 
5174
        z1 := a1;
 
5175
        z0 := a0;
 
5176
    end
 
5177
    else begin
 
5178
        if ( count < 64 ) then
 
5179
        begin
 
5180
            z2 := a1 shr negCount;
 
5181
            z1 := ( a0 shl negCount ) or  ( a1 shr count );
 
5182
            z0 := a0 shr count;
 
5183
        end
 
5184
        else begin
 
5185
            if ( count = 64 ) then
 
5186
            begin
 
5187
                z2 := a1;
 
5188
                z1 := a0;
 
5189
            end
 
5190
            else begin
 
5191
                a2 := a2 or a1;
 
5192
                if ( count < 128 ) then
 
5193
                begin
 
5194
                    z2 := a0 shl negCount;
 
5195
                    z1 := a0 shr ( count and 63 );
 
5196
                end
 
5197
                else begin
 
5198
                          if ( count = 128 ) then
 
5199
                      z2 :=  a0
 
5200
                    else
 
5201
                      z2 := ord( a0 <> 0 );
 
5202
                    z1 := 0;
 
5203
                end;
 
5204
            end;
 
5205
            z0 := 0;
 
5206
        end;
 
5207
        z2 := z2 or ord( a2 <> 0 );
 
5208
    end;
 
5209
    z2Ptr := z2;
 
5210
    z1Ptr := z1;
 
5211
    z0Ptr := z0;
 
5212
 
 
5213
end;
 
5214
 
 
5215
{*----------------------------------------------------------------------------
 
5216
| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
 
5217
| _plus_ the number of bits given in `count'.  The shifted result is at most
 
5218
| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'.  The
 
5219
| bits shifted off form a second 64-bit result as follows:  The _last_ bit
 
5220
| shifted off is the most-significant bit of the extra result, and the other
 
5221
| 63 bits of the extra result are all zero if and only if _all_but_the_last_
 
5222
| bits shifted off were all zero.  This extra result is stored in the location
 
5223
| pointed to by `z1Ptr'.  The value of `count' can be arbitrarily large.
 
5224
|     (This routine makes more sense if `a0' and `a1' are considered to form
 
5225
| a fixed-point value with binary point between `a0' and `a1'.  This fixed-
 
5226
| point value is shifted right by the number of bits given in `count', and
 
5227
| the integer part of the result is returned at the location pointed to by
 
5228
| `z0Ptr'.  The fractional part of the result may be slightly corrupted as
 
5229
| described above, and is returned at the location pointed to by `z1Ptr'.)
 
5230
*----------------------------------------------------------------------------*}
 
5231
 
 
5232
procedure shift64ExtraRightJamming(a0: bits64; a1: bits64; count: int16; var z0Ptr: bits64; var z1Ptr : bits64);
 
5233
var
 
5234
    z0, z1: bits64;
 
5235
    negCount: int8;
 
5236
begin
 
5237
    negCount := ( - count ) and 63;
 
5238
 
 
5239
    if ( count = 0 ) then
 
5240
    begin
 
5241
        z1 := a1;
 
5242
        z0 := a0;
 
5243
    end
 
5244
    else if ( count < 64 ) then
 
5245
    begin
 
5246
        z1 := ( a0 shl negCount ) or ord( a1 <>  0 );
 
5247
        z0 := a0 shr count;
 
5248
    end
 
5249
    else begin
 
5250
        if ( count = 64 ) then
 
5251
        begin
 
5252
            z1 := a0 or ord( a1 <>  0 );
 
5253
        end
 
5254
        else begin
 
5255
            z1 := ord( ( a0 or a1 ) <>  0 );
 
5256
        end;
 
5257
        z0 := 0;
 
5258
    end;
 
5259
    z1Ptr := z1;
 
5260
    z0Ptr := z0;
 
5261
end;
 
5262
 
 
5263
{$ifdef FPC_SOFTFLOAT_FLOATX80}
 
5264
 
 
5265
{*----------------------------------------------------------------------------
 
5266
| Returns the fraction bits of the extended double-precision floating-point
 
5267
| value `a'.
 
5268
*----------------------------------------------------------------------------*}
 
5269
 
 
5270
function extractFloatx80Frac(a : floatx80): bits64;inline;
 
5271
begin
 
5272
    result:=a.low;
 
5273
end;
 
5274
 
 
5275
{*----------------------------------------------------------------------------
 
5276
| Returns the exponent bits of the extended double-precision floating-point
 
5277
| value `a'.
 
5278
*----------------------------------------------------------------------------*}
 
5279
 
 
5280
function extractFloatx80Exp(a : floatx80): int32;inline;
 
5281
begin
 
5282
    result:=a.high and $7FFF;
 
5283
end;
 
5284
 
 
5285
{*----------------------------------------------------------------------------
 
5286
| Returns the sign bit of the extended double-precision floating-point value
 
5287
| `a'.
 
5288
*----------------------------------------------------------------------------*}
 
5289
 
 
5290
function extractFloatx80Sign(a : floatx80): flag;inline;
 
5291
begin
 
5292
    result:=a.high shr 15;
 
5293
end;
 
5294
 
 
5295
{*----------------------------------------------------------------------------
 
5296
| Normalizes the subnormal extended double-precision floating-point value
 
5297
| represented by the denormalized significand `aSig'.  The normalized exponent
 
5298
| and significand are stored at the locations pointed to by `zExpPtr' and
 
5299
| `zSigPtr', respectively.
 
5300
*----------------------------------------------------------------------------*}
 
5301
 
 
5302
procedure normalizeFloatx80Subnormal( aSig: bits64; var zExpPtr: int32; var zSigPtr : bits64);
 
5303
var
 
5304
    shiftCount: int8;
 
5305
begin
 
5306
    shiftCount := countLeadingZeros64( aSig );
 
5307
    zSigPtr := aSig shl shiftCount;
 
5308
    zExpPtr := 1 - shiftCount;
 
5309
end;
 
5310
 
 
5311
{*----------------------------------------------------------------------------
 
5312
| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
 
5313
| extended double-precision floating-point value, returning the result.
 
5314
*----------------------------------------------------------------------------*}
 
5315
 
 
5316
function packFloatx80( zSign: flag; zExp: int32; zSig : bits64): floatx80;
 
5317
var
 
5318
    z: floatx80;
 
5319
begin
 
5320
    z.low := zSig;
 
5321
    z.high := (  bits16(zSign) shl 15 ) + zExp;
 
5322
    result:=z;
 
5323
end;
 
5324
 
 
5325
{*----------------------------------------------------------------------------
 
5326
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
 
5327
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
 
5328
| and returns the proper extended double-precision floating-point value
 
5329
| corresponding to the abstract input.  Ordinarily, the abstract value is
 
5330
| rounded and packed into the extended double-precision format, with the
 
5331
| inexact exception raised if the abstract input cannot be represented
 
5332
| exactly.  However, if the abstract value is too large, the overflow and
 
5333
| inexact exceptions are raised and an infinity or maximal finite value is
 
5334
| returned.  If the abstract value is too small, the input value is rounded to
 
5335
| a subnormal number, and the underflow and inexact exceptions are raised if
 
5336
| the abstract input cannot be represented exactly as a subnormal extended
 
5337
| double-precision floating-point number.
 
5338
|     If `roundingPrecision' is 32 or 64, the result is rounded to the same
 
5339
| number of bits as single or double precision, respectively.  Otherwise, the
 
5340
| result is rounded to the full precision of the extended double-precision
 
5341
| format.
 
5342
|     The input significand must be normalized or smaller.  If the input
 
5343
| significand is not normalized, `zExp' must be 0; in that case, the result
 
5344
| returned is a subnormal number, and it must not require rounding.  The
 
5345
| handling of underflow and overflow follows the IEC/IEEE Standard for Binary
 
5346
| Floating-Point Arithmetic.
 
5347
*----------------------------------------------------------------------------*}
 
5348
 
 
5349
function roundAndPackFloatx80(roundingPrecision: int8; zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): floatx80;
 
5350
var
 
5351
    roundingMode: int8;
 
5352
    roundNearestEven, increment, isTiny: flag;
 
5353
    roundIncrement, roundMask, roundBits: int64;
 
5354
label
 
5355
    precision80;
 
5356
begin
 
5357
    roundingMode := float_rounding_mode;
 
5358
    roundNearestEven := flag( roundingMode = float_round_nearest_even );
 
5359
    if ( roundingPrecision = 80 ) then
 
5360
      goto precision80;
 
5361
    if ( roundingPrecision = 64 ) then
 
5362
    begin
 
5363
        roundIncrement := int64( $0000000000000400 );
 
5364
        roundMask := int64( $00000000000007FF );
 
5365
    end
 
5366
    else if ( roundingPrecision = 32 ) then
 
5367
    begin
 
5368
        roundIncrement := int64( $0000008000000000 );
 
5369
        roundMask := int64( $000000FFFFFFFFFF );
 
5370
    end
 
5371
    else begin
 
5372
        goto precision80;
 
5373
    end;
 
5374
    zSig0 := zSig0 or ord( zSig1 <> 0 );
 
5375
    if ( not (roundNearestEven<>0) ) then
 
5376
    begin
 
5377
        if ( roundingMode = float_round_to_zero ) then
 
5378
        begin
 
5379
            roundIncrement := 0;
 
5380
        end
 
5381
        else begin
 
5382
            roundIncrement := roundMask;
 
5383
            if ( zSign<>0 ) then
 
5384
            begin
 
5385
                if ( roundingMode = float_round_up ) then
 
5386
                  roundIncrement := 0;
 
5387
            end
 
5388
            else begin
 
5389
                if ( roundingMode = float_round_down ) then
 
5390
                  roundIncrement := 0;
 
5391
            end;
 
5392
        end;
 
5393
    end;
 
5394
    roundBits := zSig0 and roundMask;
 
5395
    if ( $7FFD <= (bits32) ( zExp - 1 ) ) begin
 
5396
        if (    ( $7FFE < zExp )
 
5397
             or ( ( zExp = $7FFE ) and ( zSig0 + roundIncrement < zSig0 ) )
 
5398
           ) begin
 
5399
            goto overflow;
 
5400
        end;
 
5401
        if ( zExp <= 0 ) begin
 
5402
            isTiny =
 
5403
                   ( float_detect_tininess = float_tininess_before_rounding )
 
5404
                or ( zExp < 0 )
 
5405
                or ( zSig0 <= zSig0 + roundIncrement );
 
5406
            shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
 
5407
            zExp := 0;
 
5408
            roundBits := zSig0 and roundMask;
 
5409
            if ( isTiny and roundBits ) float_raise( float_flag_underflow );
 
5410
            if ( roundBits ) softfloat_exception_flags |= float_flag_inexact;
 
5411
            zSig0 += roundIncrement;
 
5412
            if ( (sbits64) zSig0 < 0 ) zExp := 1;
 
5413
            roundIncrement := roundMask + 1;
 
5414
            if ( roundNearestEven and ( roundBits shl 1 = roundIncrement ) ) begin
 
5415
                roundMask |= roundIncrement;
 
5416
            end;
 
5417
            zSig0 &= ~ roundMask;
 
5418
            result:=packFloatx80( zSign, zExp, zSig0 );
 
5419
        end;
 
5420
    end;
 
5421
    if ( roundBits ) softfloat_exception_flags |= float_flag_inexact;
 
5422
    zSig0 += roundIncrement;
 
5423
    if ( zSig0 < roundIncrement ) begin
 
5424
        ++zExp;
 
5425
        zSig0 := LIT64( $8000000000000000 );
 
5426
    end;
 
5427
    roundIncrement := roundMask + 1;
 
5428
    if ( roundNearestEven and ( roundBits shl 1 = roundIncrement ) ) begin
 
5429
        roundMask |= roundIncrement;
 
5430
    end;
 
5431
    zSig0 &= ~ roundMask;
 
5432
    if ( zSig0 = 0 ) zExp := 0;
 
5433
    result:=packFloatx80( zSign, zExp, zSig0 );
 
5434
 precision80:
 
5435
    increment := ( (sbits64) zSig1 < 0 );
 
5436
    if ( ! roundNearestEven ) begin
 
5437
        if ( roundingMode = float_round_to_zero ) begin
 
5438
            increment := 0;
 
5439
        end;
 
5440
        else begin
 
5441
            if ( zSign ) begin
 
5442
                increment := ( roundingMode = float_round_down ) and zSig1;
 
5443
            end;
 
5444
            else begin
 
5445
                increment := ( roundingMode = float_round_up ) and zSig1;
 
5446
            end;
 
5447
        end;
 
5448
    end;
 
5449
    if ( $7FFD <= (bits32) ( zExp - 1 ) ) begin
 
5450
        if (    ( $7FFE < zExp )
 
5451
             or (    ( zExp = $7FFE )
 
5452
                  and ( zSig0 = LIT64( $FFFFFFFFFFFFFFFF ) )
 
5453
                  and increment
 
5454
                )
 
5455
           ) begin
 
5456
            roundMask := 0;
 
5457
 overflow:
 
5458
            float_raise( float_flag_overflow or float_flag_inexact );
 
5459
            if (    ( roundingMode = float_round_to_zero )
 
5460
                 or ( zSign and ( roundingMode = float_round_up ) )
 
5461
                 or ( ! zSign and ( roundingMode = float_round_down ) )
 
5462
               ) begin
 
5463
                result:=packFloatx80( zSign, $7FFE, ~ roundMask );
 
5464
            end;
 
5465
            result:=packFloatx80( zSign, $7FFF, LIT64( $8000000000000000 ) );
 
5466
        end;
 
5467
        if ( zExp <= 0 ) begin
 
5468
            isTiny =
 
5469
                   ( float_detect_tininess = float_tininess_before_rounding )
 
5470
                or ( zExp < 0 )
 
5471
                or ! increment
 
5472
                or ( zSig0 < LIT64( $FFFFFFFFFFFFFFFF ) );
 
5473
            shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
 
5474
            zExp := 0;
 
5475
            if ( isTiny and zSig1 ) float_raise( float_flag_underflow );
 
5476
            if ( zSig1 ) softfloat_exception_flags |= float_flag_inexact;
 
5477
            if ( roundNearestEven ) begin
 
5478
                increment := ( (sbits64) zSig1 < 0 );
 
5479
            end;
 
5480
            else begin
 
5481
                if ( zSign ) begin
 
5482
                    increment := ( roundingMode = float_round_down ) and zSig1;
 
5483
                end;
 
5484
                else begin
 
5485
                    increment := ( roundingMode = float_round_up ) and zSig1;
 
5486
                end;
 
5487
            end;
 
5488
            if ( increment ) begin
 
5489
                ++zSig0;
 
5490
                zSig0 &=
 
5491
                    ~ ( ( (bits64) ( zSig1 shl 1 ) = 0 ) and roundNearestEven );
 
5492
                if ( (sbits64) zSig0 < 0 ) zExp := 1;
 
5493
            end;
 
5494
            result:=packFloatx80( zSign, zExp, zSig0 );
 
5495
        end;
 
5496
    end;
 
5497
    if ( zSig1 ) softfloat_exception_flags |= float_flag_inexact;
 
5498
    if ( increment ) begin
 
5499
        ++zSig0;
 
5500
        if ( zSig0 = 0 ) begin
 
5501
            ++zExp;
 
5502
            zSig0 := LIT64( $8000000000000000 );
 
5503
        end;
 
5504
        else begin
 
5505
            zSig0 &= ~ ( ( (bits64) ( zSig1 shl 1 ) = 0 ) and roundNearestEven );
 
5506
        end;
 
5507
    end;
 
5508
    else begin
 
5509
        if ( zSig0 = 0 ) zExp := 0;
 
5510
    end;
 
5511
    result:=packFloatx80( zSign, zExp, zSig0 );
 
5512
 
 
5513
end;
 
5514
 
 
5515
{*----------------------------------------------------------------------------
 
5516
| Takes an abstract floating-point value having sign `zSign', exponent
 
5517
| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
 
5518
| and returns the proper extended double-precision floating-point value
 
5519
| corresponding to the abstract input.  This routine is just like
 
5520
| `roundAndPackFloatx80' except that the input significand does not have to be
 
5521
| normalized.
 
5522
*----------------------------------------------------------------------------*}
 
5523
 
 
5524
function normalizeRoundAndPackFloatx80(roundingPrecision: int8; zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): floatx80;
 
5525
var
 
5526
    shiftCount: int8;
 
5527
begin
 
5528
    if ( zSig0 = 0 ) begin
 
5529
        zSig0 := zSig1;
 
5530
        zSig1 := 0;
 
5531
        zExp -= 64;
 
5532
    end;
 
5533
    shiftCount := countLeadingZeros64( zSig0 );
 
5534
    shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
 
5535
    zExp := eExp - shiftCount;
 
5536
    return
 
5537
        roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 );
 
5538
 
 
5539
end;
 
5540
 
 
5541
{*----------------------------------------------------------------------------
 
5542
| Returns the result of converting the extended double-precision floating-
 
5543
| point value `a' to the 32-bit two's complement integer format.  The
 
5544
| conversion is performed according to the IEC/IEEE Standard for Binary
 
5545
| Floating-Point Arithmetic---which means in particular that the conversion
 
5546
| is rounded according to the current rounding mode.  If `a' is a NaN, the
 
5547
| largest positive integer is returned.  Otherwise, if the conversion
 
5548
| overflows, the largest integer with the same sign as `a' is returned.
 
5549
*----------------------------------------------------------------------------*}
 
5550
 
 
5551
function floatx80_to_int32(a: floatx80): int32;
 
5552
var
 
5553
    aSign: flag;
 
5554
    aExp, shiftCount: int32;
 
5555
    aSig: bits64;
 
5556
begin
 
5557
    aSig := extractFloatx80Frac( a );
 
5558
    aExp := extractFloatx80Exp( a );
 
5559
    aSign := extractFloatx80Sign( a );
 
5560
    if ( ( aExp = $7FFF ) and (bits64) ( aSig shl 1 ) ) aSign := 0;
 
5561
    shiftCount := $4037 - aExp;
 
5562
    if ( shiftCount <= 0 ) shiftCount := 1;
 
5563
    shift64RightJamming( aSig, shiftCount, &aSig );
 
5564
    result := roundAndPackInt32( aSign, aSig );
 
5565
 
 
5566
end;
 
5567
 
 
5568
{*----------------------------------------------------------------------------
 
5569
| Returns the result of converting the extended double-precision floating-
 
5570
| point value `a' to the 32-bit two's complement integer format.  The
 
5571
| conversion is performed according to the IEC/IEEE Standard for Binary
 
5572
| Floating-Point Arithmetic, except that the conversion is always rounded
 
5573
| toward zero.  If `a' is a NaN, the largest positive integer is returned.
 
5574
| Otherwise, if the conversion overflows, the largest integer with the same
 
5575
| sign as `a' is returned.
 
5576
*----------------------------------------------------------------------------*}
 
5577
 
 
5578
function floatx80_to_int32_round_to_zero(a: floatx80): int32;
 
5579
var
 
5580
    aSign: flag;
 
5581
    aExp, shiftCount: int32;
 
5582
    aSig, savedASig: bits64;
 
5583
    z: int32;
 
5584
begin
 
5585
    aSig := extractFloatx80Frac( a );
 
5586
    aExp := extractFloatx80Exp( a );
 
5587
    aSign := extractFloatx80Sign( a );
 
5588
    if ( $401E < aExp ) begin
 
5589
        if ( ( aExp = $7FFF ) and (bits64) ( aSig shl 1 ) ) aSign := 0;
 
5590
        goto invalid;
 
5591
    end;
 
5592
    else if ( aExp < $3FFF ) begin
 
5593
        if ( aExp or aSig ) softfloat_exception_flags or= float_flag_inexact;
 
5594
        result := 0;
 
5595
    end;
 
5596
    shiftCount := $403E - aExp;
 
5597
    savedASig := aSig;
 
5598
    aSig >>= shiftCount;
 
5599
    z := aSig;
 
5600
    if ( aSign ) z := - z;
 
5601
    if ( ( z < 0 ) xor aSign ) begin
 
5602
 invalid:
 
5603
        float_raise( float_flag_invalid );
 
5604
        result := aSign ? (sbits32) $80000000 : $7FFFFFFF;
 
5605
    end;
 
5606
    if ( ( aSig shl shiftCount ) <> savedASig ) begin
 
5607
        softfloat_exception_flags or= float_flag_inexact;
 
5608
    end;
 
5609
    result := z;
 
5610
 
 
5611
end;
 
5612
 
 
5613
{*----------------------------------------------------------------------------
 
5614
| Returns the result of converting the extended double-precision floating-
 
5615
| point value `a' to the 64-bit two's complement integer format.  The
 
5616
| conversion is performed according to the IEC/IEEE Standard for Binary
 
5617
| Floating-Point Arithmetic---which means in particular that the conversion
 
5618
| is rounded according to the current rounding mode.  If `a' is a NaN,
 
5619
| the largest positive integer is returned.  Otherwise, if the conversion
 
5620
| overflows, the largest integer with the same sign as `a' is returned.
 
5621
*----------------------------------------------------------------------------*}
 
5622
 
 
5623
function floatx80_to_int64(a: floatx80): int64;
 
5624
var
 
5625
    aSign: flag;
 
5626
    aExp, shiftCount: int32;
 
5627
    aSig, aSigExtra: bits64;
 
5628
begin
 
5629
 
 
5630
    aSig := extractFloatx80Frac( a );
 
5631
    aExp := extractFloatx80Exp( a );
 
5632
    aSign := extractFloatx80Sign( a );
 
5633
    shiftCount := $403E - aExp;
 
5634
    if ( shiftCount <= 0 ) begin
 
5635
        if ( shiftCount ) begin
 
5636
            float_raise( float_flag_invalid );
 
5637
            if (    ! aSign
 
5638
                 or (    ( aExp = $7FFF )
 
5639
                      and ( aSig <> LIT64( $8000000000000000 ) ) )
 
5640
               ) begin
 
5641
                result := LIT64( $7FFFFFFFFFFFFFFF );
 
5642
            end;
 
5643
            result := (sbits64) LIT64( $8000000000000000 );
 
5644
        end;
 
5645
        aSigExtra := 0;
 
5646
    end;
 
5647
    else begin
 
5648
        shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra );
 
5649
    end;
 
5650
    result := roundAndPackInt64( aSign, aSig, aSigExtra );
 
5651
 
 
5652
end;
 
5653
 
 
5654
{*----------------------------------------------------------------------------
 
5655
| Returns the result of converting the extended double-precision floating-
 
5656
| point value `a' to the 64-bit two's complement integer format.  The
 
5657
| conversion is performed according to the IEC/IEEE Standard for Binary
 
5658
| Floating-Point Arithmetic, except that the conversion is always rounded
 
5659
| toward zero.  If `a' is a NaN, the largest positive integer is returned.
 
5660
| Otherwise, if the conversion overflows, the largest integer with the same
 
5661
| sign as `a' is returned.
 
5662
*----------------------------------------------------------------------------*}
 
5663
 
 
5664
function floatx80_to_int64_round_to_zero(a: floatx80): int64;
 
5665
var
 
5666
    aSign: flag;
 
5667
    aExp, shiftCount: int32;
 
5668
    aSig: bits64;
 
5669
    z: int64;
 
5670
begin
 
5671
    aSig := extractFloatx80Frac( a );
 
5672
    aExp := extractFloatx80Exp( a );
 
5673
    aSign := extractFloatx80Sign( a );
 
5674
    shiftCount := aExp - $403E;
 
5675
    if ( 0 <= shiftCount ) begin
 
5676
        aSig &= LIT64( $7FFFFFFFFFFFFFFF );
 
5677
        if ( ( a.high <> $C03E ) or aSig ) begin
 
5678
            float_raise( float_flag_invalid );
 
5679
            if ( ! aSign or ( ( aExp = $7FFF ) and aSig ) ) begin
 
5680
                result := LIT64( $7FFFFFFFFFFFFFFF );
 
5681
            end;
 
5682
        end;
 
5683
        result := (sbits64) LIT64( $8000000000000000 );
 
5684
    end;
 
5685
    else if ( aExp < $3FFF ) begin
 
5686
        if ( aExp or aSig ) softfloat_exception_flags or= float_flag_inexact;
 
5687
        result := 0;
 
5688
    end;
 
5689
    z := aSig>>( - shiftCount );
 
5690
    if ( (bits64) ( aSig shl ( shiftCount and 63 ) ) ) begin
 
5691
        softfloat_exception_flags or= float_flag_inexact;
 
5692
    end;
 
5693
    if ( aSign ) z := - z;
 
5694
    result := z;
 
5695
 
 
5696
end;
 
5697
 
 
5698
{*----------------------------------------------------------------------------
 
5699
| Returns the result of converting the extended double-precision floating-
 
5700
| point value `a' to the single-precision floating-point format.  The
 
5701
| conversion is performed according to the IEC/IEEE Standard for Binary
 
5702
| Floating-Point Arithmetic.
 
5703
*----------------------------------------------------------------------------*}
 
5704
 
 
5705
function floatx80_to_float32(a: floatx80): float32;
 
5706
var
 
5707
    aSign: flag;
 
5708
    aExp: int32;
 
5709
    aSig: bits64;
 
5710
begin
 
5711
    aSig := extractFloatx80Frac( a );
 
5712
    aExp := extractFloatx80Exp( a );
 
5713
    aSign := extractFloatx80Sign( a );
 
5714
    if ( aExp = $7FFF ) begin
 
5715
        if ( (bits64) ( aSig shl 1 ) ) begin
 
5716
            result := commonNaNToFloat32( floatx80ToCommonNaN( a ) );
 
5717
        end;
 
5718
        result := packFloat32( aSign, $FF, 0 );
 
5719
    end;
 
5720
    shift64RightJamming( aSig, 33, &aSig );
 
5721
    if ( aExp or aSig ) aExp -= $3F81;
 
5722
    result := roundAndPackFloat32( aSign, aExp, aSig );
 
5723
 
 
5724
end;
 
5725
 
 
5726
{*----------------------------------------------------------------------------
 
5727
| Returns the result of converting the extended double-precision floating-
 
5728
| point value `a' to the double-precision floating-point format.  The
 
5729
| conversion is performed according to the IEC/IEEE Standard for Binary
 
5730
| Floating-Point Arithmetic.
 
5731
*----------------------------------------------------------------------------*}
 
5732
 
 
5733
function floatx80_to_float64(a: floatx80): float64;
 
5734
var
 
5735
    aSign: flag;
 
5736
    aExp: int32;
 
5737
    aSig, zSig: bits64;
 
5738
begin
 
5739
    aSig := extractFloatx80Frac( a );
 
5740
    aExp := extractFloatx80Exp( a );
 
5741
    aSign := extractFloatx80Sign( a );
 
5742
    if ( aExp = $7FFF ) begin
 
5743
        if ( (bits64) ( aSig shl 1 ) ) begin
 
5744
            result := commonNaNToFloat64( floatx80ToCommonNaN( a ) );
 
5745
        end;
 
5746
        result := packFloat64( aSign, $7FF, 0 );
 
5747
    end;
 
5748
    shift64RightJamming( aSig, 1, &zSig );
 
5749
    if ( aExp or aSig ) aExp -= $3C01;
 
5750
    result := roundAndPackFloat64( aSign, aExp, zSig );
 
5751
 
 
5752
end;
 
5753
 
 
5754
{$ifdef FPC_SOFTFLOAT_FLOAT128}
 
5755
{*----------------------------------------------------------------------------
 
5756
| Returns the result of converting the extended double-precision floating-
 
5757
| point value `a' to the quadruple-precision floating-point format.  The
 
5758
| conversion is performed according to the IEC/IEEE Standard for Binary
 
5759
| Floating-Point Arithmetic.
 
5760
*----------------------------------------------------------------------------*}
 
5761
 
 
5762
function floatx80_to_float128(a: floatx80): float128;
 
5763
var
 
5764
    aSign: flag;
 
5765
    aExp: int16;
 
5766
    aSig, zSig0, zSig1: bits64;
 
5767
begin
 
5768
    aSig := extractFloatx80Frac( a );
 
5769
    aExp := extractFloatx80Exp( a );
 
5770
    aSign := extractFloatx80Sign( a );
 
5771
    if ( ( aExp = $7FFF ) and (bits64) ( aSig shl 1 ) ) begin
 
5772
        result := commonNaNToFloat128( floatx80ToCommonNaN( a ) );
 
5773
    end;
 
5774
    shift128Right( aSig shl 1, 0, 16, &zSig0, &zSig1 );
 
5775
    result := packFloat128( aSign, aExp, zSig0, zSig1 );
 
5776
 
 
5777
end;
 
5778
 
 
5779
{$endif FPC_SOFTFLOAT_FLOAT128}
 
5780
 
 
5781
{*----------------------------------------------------------------------------
 
5782
| Rounds the extended double-precision floating-point value `a' to an integer,
 
5783
| and Returns the result as an extended quadruple-precision floating-point
 
5784
| value.  The operation is performed according to the IEC/IEEE Standard for
 
5785
| Binary Floating-Point Arithmetic.
 
5786
*----------------------------------------------------------------------------*}
 
5787
 
 
5788
function floatx80_round_to_int(a: floatx80): floatx80;
 
5789
var
 
5790
    aSign: flag;
 
5791
    aExp: int32;
 
5792
    lastBitMask, roundBitsMask: bits64;
 
5793
    roundingMode: int8;
 
5794
    z: floatx80;
 
5795
begin
 
5796
    aExp := extractFloatx80Exp( a );
 
5797
    if ( $403E <= aExp ) begin
 
5798
        if ( ( aExp = $7FFF ) and (bits64) ( extractFloatx80Frac( a ) shl 1 ) ) begin
 
5799
            result := propagateFloatx80NaN( a, a );
 
5800
        end;
 
5801
        result := a;
 
5802
    end;
 
5803
    if ( aExp < $3FFF ) begin
 
5804
        if (    ( aExp = 0 )
 
5805
             and ( (bits64) ( extractFloatx80Frac( a ) shl 1 ) = 0 ) ) begin
 
5806
            result := a;
 
5807
        end;
 
5808
        softfloat_exception_flags or= float_flag_inexact;
 
5809
        aSign := extractFloatx80Sign( a );
 
5810
        switch ( float_rounding_mode ) begin
 
5811
         case float_round_nearest_even:
 
5812
            if ( ( aExp = $3FFE ) and (bits64) ( extractFloatx80Frac( a ) shl 1 )
 
5813
               ) begin
 
5814
                result :=
 
5815
                    packFloatx80( aSign, $3FFF, LIT64( $8000000000000000 ) );
 
5816
            end;
 
5817
            break;
 
5818
         case float_round_down:
 
5819
            result :=
 
5820
                  aSign ?
 
5821
                      packFloatx80( 1, $3FFF, LIT64( $8000000000000000 ) )
 
5822
                : packFloatx80( 0, 0, 0 );
 
5823
         case float_round_up:
 
5824
            result :=
 
5825
                  aSign ? packFloatx80( 1, 0, 0 )
 
5826
                : packFloatx80( 0, $3FFF, LIT64( $8000000000000000 ) );
 
5827
        end;
 
5828
        result := packFloatx80( aSign, 0, 0 );
 
5829
    end;
 
5830
    lastBitMask := 1;
 
5831
    lastBitMask  shl = $403E - aExp;
 
5832
    roundBitsMask := lastBitMask - 1;
 
5833
    z := a;
 
5834
    roundingMode := float_rounding_mode;
 
5835
    if ( roundingMode = float_round_nearest_even ) begin
 
5836
        z.low += lastBitMask>>1;
 
5837
        if ( ( z.low and roundBitsMask ) = 0 ) z.low &= ~ lastBitMask;
 
5838
    end;
 
5839
    else if ( roundingMode <> float_round_to_zero ) begin
 
5840
        if ( extractFloatx80Sign( z ) xor ( roundingMode = float_round_up ) ) begin
 
5841
            z.low += roundBitsMask;
 
5842
        end;
 
5843
    end;
 
5844
    z.low &= ~ roundBitsMask;
 
5845
    if ( z.low = 0 ) begin
 
5846
        ++z.high;
 
5847
        z.low := LIT64( $8000000000000000 );
 
5848
    end;
 
5849
    if ( z.low <> a.low ) softfloat_exception_flags or= float_flag_inexact;
 
5850
    result := z;
 
5851
 
 
5852
end;
 
5853
 
 
5854
{*----------------------------------------------------------------------------
 
5855
| Returns the result of adding the absolute values of the extended double-
 
5856
| precision floating-point values `a' and `b'.  If `zSign' is 1, the sum is
 
5857
| negated before being returned.  `zSign' is ignored if the result is a NaN.
 
5858
| The addition is performed according to the IEC/IEEE Standard for Binary
 
5859
| Floating-Point Arithmetic.
 
5860
*----------------------------------------------------------------------------*}
 
5861
 
 
5862
function addFloatx80Sigs(a: floatx80; b: floatx80; zSign : flag): floatx80;
 
5863
var
 
5864
    aExp, bExp, zExp: int32;
 
5865
    aSig, bSig, zSig0, zSig1: bits64;
 
5866
    expDiff: int32;
 
5867
begin
 
5868
    aSig := extractFloatx80Frac( a );
 
5869
    aExp := extractFloatx80Exp( a );
 
5870
    bSig := extractFloatx80Frac( b );
 
5871
    bExp := extractFloatx80Exp( b );
 
5872
    expDiff := aExp - bExp;
 
5873
    if ( 0 < expDiff ) begin
 
5874
        if ( aExp = $7FFF ) begin
 
5875
            if ( (bits64) ( aSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
 
5876
            result := a;
 
5877
        end;
 
5878
        if ( bExp = 0 ) --expDiff;
 
5879
        shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
 
5880
        zExp := aExp;
 
5881
    end;
 
5882
    else if ( expDiff < 0 ) begin
 
5883
        if ( bExp = $7FFF ) begin
 
5884
            if ( (bits64) ( bSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
 
5885
            result := packFloatx80( zSign, $7FFF, LIT64( $8000000000000000 ) );
 
5886
        end;
 
5887
        if ( aExp = 0 ) ++expDiff;
 
5888
        shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
 
5889
        zExp := bExp;
 
5890
    end;
 
5891
    else begin
 
5892
        if ( aExp = $7FFF ) begin
 
5893
            if ( (bits64) ( ( aSig or bSig ) shl 1 ) ) begin
 
5894
                result := propagateFloatx80NaN( a, b );
 
5895
            end;
 
5896
            result := a;
 
5897
        end;
 
5898
        zSig1 := 0;
 
5899
        zSig0 := aSig + bSig;
 
5900
        if ( aExp = 0 ) begin
 
5901
            normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 );
 
5902
            goto roundAndPack;
 
5903
        end;
 
5904
        zExp := aExp;
 
5905
        goto shiftRight1;
 
5906
    end;
 
5907
    zSig0 := aSig + bSig;
 
5908
    if ( (sbits64) zSig0 < 0 ) goto roundAndPack;
 
5909
 shiftRight1:
 
5910
    shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 );
 
5911
    zSig0 or= LIT64( $8000000000000000 );
 
5912
    ++zExp;
 
5913
 roundAndPack:
 
5914
    result :=
 
5915
        roundAndPackFloatx80(
 
5916
            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
 
5917
 
 
5918
end;
 
5919
 
 
5920
{*----------------------------------------------------------------------------
 
5921
| Returns the result of subtracting the absolute values of the extended
 
5922
| double-precision floating-point values `a' and `b'.  If `zSign' is 1, the
 
5923
| difference is negated before being returned.  `zSign' is ignored if the
 
5924
| result is a NaN.  The subtraction is performed according to the IEC/IEEE
 
5925
| Standard for Binary Floating-Point Arithmetic.
 
5926
*----------------------------------------------------------------------------*}
 
5927
 
 
5928
function subFloatx80Sigs(a: floatx80; b: floatx80; zSign : flag): floatx80;
 
5929
var
 
5930
    aExp, bExp, zExp: int32;
 
5931
    aSig, bSig, zSig0, zSig1: bits64;
 
5932
    expDiff: int32;
 
5933
    z: floatx80;
 
5934
begin
 
5935
    aSig := extractFloatx80Frac( a );
 
5936
    aExp := extractFloatx80Exp( a );
 
5937
    bSig := extractFloatx80Frac( b );
 
5938
    bExp := extractFloatx80Exp( b );
 
5939
    expDiff := aExp - bExp;
 
5940
    if ( 0 < expDiff ) goto aExpBigger;
 
5941
    if ( expDiff < 0 ) goto bExpBigger;
 
5942
    if ( aExp = $7FFF ) begin
 
5943
        if ( (bits64) ( ( aSig or bSig ) shl 1 ) ) begin
 
5944
            result := propagateFloatx80NaN( a, b );
 
5945
        end;
 
5946
        float_raise( float_flag_invalid );
 
5947
        z.low := floatx80_default_nan_low;
 
5948
        z.high := floatx80_default_nan_high;
 
5949
        result := z;
 
5950
    end;
 
5951
    if ( aExp = 0 ) begin
 
5952
        aExp := 1;
 
5953
        bExp := 1;
 
5954
    end;
 
5955
    zSig1 := 0;
 
5956
    if ( bSig < aSig ) goto aBigger;
 
5957
    if ( aSig < bSig ) goto bBigger;
 
5958
    result := packFloatx80( float_rounding_mode = float_round_down, 0, 0 );
 
5959
 bExpBigger:
 
5960
    if ( bExp = $7FFF ) begin
 
5961
        if ( (bits64) ( bSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
 
5962
        result := packFloatx80( zSign xor 1, $7FFF, LIT64( $8000000000000000 ) );
 
5963
    end;
 
5964
    if ( aExp = 0 ) ++expDiff;
 
5965
    shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
 
5966
 bBigger:
 
5967
    sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 );
 
5968
    zExp := bExp;
 
5969
    zSign  xor = 1;
 
5970
    goto normalizeRoundAndPack;
 
5971
 aExpBigger:
 
5972
    if ( aExp = $7FFF ) begin
 
5973
        if ( (bits64) ( aSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
 
5974
        result := a;
 
5975
    end;
 
5976
    if ( bExp = 0 ) --expDiff;
 
5977
    shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
 
5978
 aBigger:
 
5979
    sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 );
 
5980
    zExp := aExp;
 
5981
 normalizeRoundAndPack:
 
5982
    result :=
 
5983
        normalizeRoundAndPackFloatx80(
 
5984
            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
 
5985
 
 
5986
end;
 
5987
 
 
5988
{*----------------------------------------------------------------------------
 
5989
| Returns the result of adding the extended double-precision floating-point
 
5990
| values `a' and `b'.  The operation is performed according to the IEC/IEEE
 
5991
| Standard for Binary Floating-Point Arithmetic.
 
5992
*----------------------------------------------------------------------------*}
 
5993
 
 
5994
function floatx80_add(a: floatx80; b: floatx80): floatx80;
 
5995
var
 
5996
    aSign, bSign: flag;
 
5997
begin
 
5998
    aSign := extractFloatx80Sign( a );
 
5999
    bSign := extractFloatx80Sign( b );
 
6000
    if ( aSign = bSign ) begin
 
6001
        result := addFloatx80Sigs( a, b, aSign );
 
6002
    end;
 
6003
    else begin
 
6004
        result := subFloatx80Sigs( a, b, aSign );
 
6005
    end;
 
6006
 
 
6007
end;
 
6008
 
 
6009
{*----------------------------------------------------------------------------
 
6010
| Returns the result of subtracting the extended double-precision floating-
 
6011
| point values `a' and `b'.  The operation is performed according to the
 
6012
| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
6013
*----------------------------------------------------------------------------*}
 
6014
 
 
6015
function floatx80_sub(a: floatx80; b: floatx80 ): floatx80;
 
6016
var
 
6017
    aSign, bSign: flag;
 
6018
begin
 
6019
    aSign := extractFloatx80Sign( a );
 
6020
    bSign := extractFloatx80Sign( b );
 
6021
    if ( aSign = bSign ) begin
 
6022
        result := subFloatx80Sigs( a, b, aSign );
 
6023
    end;
 
6024
    else begin
 
6025
        result := addFloatx80Sigs( a, b, aSign );
 
6026
    end;
 
6027
 
 
6028
end;
 
6029
 
 
6030
{*----------------------------------------------------------------------------
 
6031
| Returns the result of multiplying the extended double-precision floating-
 
6032
| point values `a' and `b'.  The operation is performed according to the
 
6033
| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
6034
*----------------------------------------------------------------------------*}
 
6035
 
 
6036
function floatx80_mul(a: floatx80; b: floatx80): floatx80;
 
6037
var
 
6038
    aSign, bSign, zSign: flag;
 
6039
    aExp, bExp, zExp: int32;
 
6040
    aSig, bSig, zSig0, zSig1: bits64;
 
6041
    z: floatx80;
 
6042
begin
 
6043
    aSig := extractFloatx80Frac( a );
 
6044
    aExp := extractFloatx80Exp( a );
 
6045
    aSign := extractFloatx80Sign( a );
 
6046
    bSig := extractFloatx80Frac( b );
 
6047
    bExp := extractFloatx80Exp( b );
 
6048
    bSign := extractFloatx80Sign( b );
 
6049
    zSign := aSign xor bSign;
 
6050
    if ( aExp = $7FFF ) begin
 
6051
        if (    (bits64) ( aSig shl 1 )
 
6052
             or ( ( bExp = $7FFF ) and (bits64) ( bSig shl 1 ) ) ) begin
 
6053
            result := propagateFloatx80NaN( a, b );
 
6054
        end;
 
6055
        if ( ( bExp or bSig ) = 0 ) goto invalid;
 
6056
        result := packFloatx80( zSign, $7FFF, LIT64( $8000000000000000 ) );
 
6057
    end;
 
6058
    if ( bExp = $7FFF ) begin
 
6059
        if ( (bits64) ( bSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
 
6060
        if ( ( aExp or aSig ) = 0 ) begin
 
6061
 invalid:
 
6062
            float_raise( float_flag_invalid );
 
6063
            z.low := floatx80_default_nan_low;
 
6064
            z.high := floatx80_default_nan_high;
 
6065
            result := z;
 
6066
        end;
 
6067
        result := packFloatx80( zSign, $7FFF, LIT64( $8000000000000000 ) );
 
6068
    end;
 
6069
    if ( aExp = 0 ) begin
 
6070
        if ( aSig = 0 ) result := packFloatx80( zSign, 0, 0 );
 
6071
        normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
 
6072
    end;
 
6073
    if ( bExp = 0 ) begin
 
6074
        if ( bSig = 0 ) result := packFloatx80( zSign, 0, 0 );
 
6075
        normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
 
6076
    end;
 
6077
    zExp := aExp + bExp - $3FFE;
 
6078
    mul64To128( aSig, bSig, &zSig0, &zSig1 );
 
6079
    if ( 0 < (sbits64) zSig0 ) begin
 
6080
        shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
 
6081
        --zExp;
 
6082
    end;
 
6083
    result :=
 
6084
        roundAndPackFloatx80(
 
6085
            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
 
6086
 
 
6087
end;
 
6088
 
 
6089
{*----------------------------------------------------------------------------
 
6090
| Returns the result of dividing the extended double-precision floating-point
 
6091
| value `a' by the corresponding value `b'.  The operation is performed
 
6092
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
6093
*----------------------------------------------------------------------------*}
 
6094
 
 
6095
function floatx80_div(a: floatx80; b: floatx80 ): floatx80;
 
6096
var
 
6097
    aSign, bSign, zSign: flag;
 
6098
    aExp, bExp, zExp: int32;
 
6099
    aSig, bSig, zSig0, zSig1: bits64;
 
6100
    rem0, rem1, rem2, term0, term1, term2: bits64;
 
6101
    z: floatx80;
 
6102
begin
 
6103
    aSig := extractFloatx80Frac( a );
 
6104
    aExp := extractFloatx80Exp( a );
 
6105
    aSign := extractFloatx80Sign( a );
 
6106
    bSig := extractFloatx80Frac( b );
 
6107
    bExp := extractFloatx80Exp( b );
 
6108
    bSign := extractFloatx80Sign( b );
 
6109
    zSign := aSign xor bSign;
 
6110
    if ( aExp = $7FFF ) begin
 
6111
        if ( (bits64) ( aSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
 
6112
        if ( bExp = $7FFF ) begin
 
6113
            if ( (bits64) ( bSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
 
6114
            goto invalid;
 
6115
        end;
 
6116
        result := packFloatx80( zSign, $7FFF, LIT64( $8000000000000000 ) );
 
6117
    end;
 
6118
    if ( bExp = $7FFF ) begin
 
6119
        if ( (bits64) ( bSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
 
6120
        result := packFloatx80( zSign, 0, 0 );
 
6121
    end;
 
6122
    if ( bExp = 0 ) begin
 
6123
        if ( bSig = 0 ) begin
 
6124
            if ( ( aExp or aSig ) = 0 ) begin
 
6125
 invalid:
 
6126
                float_raise( float_flag_invalid );
 
6127
                z.low := floatx80_default_nan_low;
 
6128
                z.high := floatx80_default_nan_high;
 
6129
                result := z;
 
6130
            end;
 
6131
            float_raise( float_flag_divbyzero );
 
6132
            result := packFloatx80( zSign, $7FFF, LIT64( $8000000000000000 ) );
 
6133
        end;
 
6134
        normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
 
6135
    end;
 
6136
    if ( aExp = 0 ) begin
 
6137
        if ( aSig = 0 ) result := packFloatx80( zSign, 0, 0 );
 
6138
        normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
 
6139
    end;
 
6140
    zExp := aExp - bExp + $3FFE;
 
6141
    rem1 := 0;
 
6142
    if ( bSig <= aSig ) begin
 
6143
        shift128Right( aSig, 0, 1, &aSig, &rem1 );
 
6144
        ++zExp;
 
6145
    end;
 
6146
    zSig0 := estimateDiv128To64( aSig, rem1, bSig );
 
6147
    mul64To128( bSig, zSig0, &term0, &term1 );
 
6148
    sub128( aSig, rem1, term0, term1, &rem0, &rem1 );
 
6149
    while ( (sbits64) rem0 < 0 ) begin
 
6150
        --zSig0;
 
6151
        add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
 
6152
    end;
 
6153
    zSig1 := estimateDiv128To64( rem1, 0, bSig );
 
6154
    if ( (bits64) ( zSig1 shl 1 ) <= 8 ) begin
 
6155
        mul64To128( bSig, zSig1, &term1, &term2 );
 
6156
        sub128( rem1, 0, term1, term2, &rem1, &rem2 );
 
6157
        while ( (sbits64) rem1 < 0 ) begin
 
6158
            --zSig1;
 
6159
            add128( rem1, rem2, 0, bSig, &rem1, &rem2 );
 
6160
        end;
 
6161
        zSig1 or= ( ( rem1 or rem2 ) <> 0 );
 
6162
    end;
 
6163
    result :=
 
6164
        roundAndPackFloatx80(
 
6165
            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
 
6166
 
 
6167
end;
 
6168
 
 
6169
{*----------------------------------------------------------------------------
 
6170
| Returns the remainder of the extended double-precision floating-point value
 
6171
| `a' with respect to the corresponding value `b'.  The operation is performed
 
6172
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
6173
*----------------------------------------------------------------------------*}
 
6174
 
 
6175
function floatx80_rem(a: floatx80; b: floatx80 ): floatx80;
 
6176
var
 
6177
    aSign, bSign, zSign: flag;
 
6178
    aExp, bExp, expDiff: int32;
 
6179
    aSig0, aSig1, bSig: bits64;
 
6180
    q, term0, term1, alternateASig0, alternateASig1: bits64;
 
6181
    z: floatx80;
 
6182
begin
 
6183
    aSig0 := extractFloatx80Frac( a );
 
6184
    aExp := extractFloatx80Exp( a );
 
6185
    aSign := extractFloatx80Sign( a );
 
6186
    bSig := extractFloatx80Frac( b );
 
6187
    bExp := extractFloatx80Exp( b );
 
6188
    bSign := extractFloatx80Sign( b );
 
6189
    if ( aExp = $7FFF ) begin
 
6190
        if (    (bits64) ( aSig0 shl 1 )
 
6191
             or ( ( bExp = $7FFF ) and (bits64) ( bSig shl 1 ) ) ) begin
 
6192
            result := propagateFloatx80NaN( a, b );
 
6193
        end;
 
6194
        goto invalid;
 
6195
    end;
 
6196
    if ( bExp = $7FFF ) begin
 
6197
        if ( (bits64) ( bSig shl 1 ) ) result := propagateFloatx80NaN( a, b );
 
6198
        result := a;
 
6199
    end;
 
6200
    if ( bExp = 0 ) begin
 
6201
        if ( bSig = 0 ) begin
 
6202
 invalid:
 
6203
            float_raise( float_flag_invalid );
 
6204
            z.low := floatx80_default_nan_low;
 
6205
            z.high := floatx80_default_nan_high;
 
6206
            result := z;
 
6207
        end;
 
6208
        normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
 
6209
    end;
 
6210
    if ( aExp = 0 ) begin
 
6211
        if ( (bits64) ( aSig0 shl 1 ) = 0 ) result := a;
 
6212
        normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
 
6213
    end;
 
6214
    bSig or= LIT64( $8000000000000000 );
 
6215
    zSign := aSign;
 
6216
    expDiff := aExp - bExp;
 
6217
    aSig1 := 0;
 
6218
    if ( expDiff < 0 ) begin
 
6219
        if ( expDiff < -1 ) result := a;
 
6220
        shift128Right( aSig0, 0, 1, &aSig0, &aSig1 );
 
6221
        expDiff := 0;
 
6222
    end;
 
6223
    q := ( bSig <= aSig0 );
 
6224
    if ( q ) aSig0 -= bSig;
 
6225
    expDiff -= 64;
 
6226
    while ( 0 < expDiff ) begin
 
6227
        q := estimateDiv128To64( aSig0, aSig1, bSig );
 
6228
        q := ( 2 < q ) ? q - 2 : 0;
 
6229
        mul64To128( bSig, q, &term0, &term1 );
 
6230
        sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
 
6231
        shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
 
6232
        expDiff -= 62;
 
6233
    end;
 
6234
    expDiff += 64;
 
6235
    if ( 0 < expDiff ) begin
 
6236
        q := estimateDiv128To64( aSig0, aSig1, bSig );
 
6237
        q := ( 2 < q ) ? q - 2 : 0;
 
6238
        q >>= 64 - expDiff;
 
6239
        mul64To128( bSig, q shl ( 64 - expDiff ), &term0, &term1 );
 
6240
        sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
 
6241
        shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 );
 
6242
        while ( le128( term0, term1, aSig0, aSig1 ) ) begin
 
6243
            ++q;
 
6244
            sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
 
6245
        end;
 
6246
    end;
 
6247
    else begin
 
6248
        term1 := 0;
 
6249
        term0 := bSig;
 
6250
    end;
 
6251
    sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 );
 
6252
    if (    lt128( alternateASig0, alternateASig1, aSig0, aSig1 )
 
6253
         or (    eq128( alternateASig0, alternateASig1, aSig0, aSig1 )
 
6254
              and ( q and 1 ) )
 
6255
       ) begin
 
6256
        aSig0 := alternateASig0;
 
6257
        aSig1 := alternateASig1;
 
6258
        zSign := ! zSign;
 
6259
    end;
 
6260
    result :=
 
6261
        normalizeRoundAndPackFloatx80(
 
6262
            80, zSign, bExp + expDiff, aSig0, aSig1 );
 
6263
 
 
6264
end;
 
6265
 
 
6266
{*----------------------------------------------------------------------------
 
6267
| Returns the square root of the extended double-precision floating-point
 
6268
| value `a'.  The operation is performed according to the IEC/IEEE Standard
 
6269
| for Binary Floating-Point Arithmetic.
 
6270
*----------------------------------------------------------------------------*}
 
6271
 
 
6272
function floatx80_sqrt(a: floatx80): floatx80;
 
6273
var
 
6274
    aSign: flag;
 
6275
    aExp, zExp: int32;
 
6276
    aSig0, aSig1, zSig0, zSig1, doubleZSig0: bits64;
 
6277
    rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;
 
6278
    z: floatx80;
 
6279
label
 
6280
    invalid;
 
6281
begin
 
6282
    aSig0 := extractFloatx80Frac( a );
 
6283
    aExp := extractFloatx80Exp( a );
 
6284
    aSign := extractFloatx80Sign( a );
 
6285
    if ( aExp = $7FFF ) begin
 
6286
        if ( (bits64) ( aSig0 shl 1 ) ) result := propagateFloatx80NaN( a, a );
 
6287
        if ( ! aSign ) result := a;
 
6288
        goto invalid;
 
6289
    end;
 
6290
    if ( aSign ) begin
 
6291
        if ( ( aExp or aSig0 ) = 0 ) result := a;
 
6292
 invalid:
 
6293
        float_raise( float_flag_invalid );
 
6294
        z.low := floatx80_default_nan_low;
 
6295
        z.high := floatx80_default_nan_high;
 
6296
        result := z;
 
6297
    end;
 
6298
    if ( aExp = 0 ) begin
 
6299
        if ( aSig0 = 0 ) result := packFloatx80( 0, 0, 0 );
 
6300
        normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
 
6301
    end;
 
6302
    zExp := ( ( aExp - $3FFF )>>1 ) + $3FFF;
 
6303
    zSig0 := estimateSqrt32( aExp, aSig0>>32 );
 
6304
    shift128Right( aSig0, 0, 2 + ( aExp and 1 ), &aSig0, &aSig1 );
 
6305
    zSig0 := estimateDiv128To64( aSig0, aSig1, zSig0 shl 32 ) + ( zSig0 shl 30 );
 
6306
    doubleZSig0 := zSig0 shl 1;
 
6307
    mul64To128( zSig0, zSig0, &term0, &term1 );
 
6308
    sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
 
6309
    while ( (sbits64) rem0 < 0 ) begin
 
6310
        --zSig0;
 
6311
        doubleZSig0 -= 2;
 
6312
        add128( rem0, rem1, zSig0>>63, doubleZSig0 or 1, &rem0, &rem1 );
 
6313
    end;
 
6314
    zSig1 := estimateDiv128To64( rem1, 0, doubleZSig0 );
 
6315
    if ( ( zSig1 and LIT64( $3FFFFFFFFFFFFFFF ) ) <= 5 ) begin
 
6316
        if ( zSig1 = 0 ) zSig1 := 1;
 
6317
        mul64To128( doubleZSig0, zSig1, &term1, &term2 );
 
6318
        sub128( rem1, 0, term1, term2, &rem1, &rem2 );
 
6319
        mul64To128( zSig1, zSig1, &term2, &term3 );
 
6320
        sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
 
6321
        while ( (sbits64) rem1 < 0 ) begin
 
6322
            --zSig1;
 
6323
            shortShift128Left( 0, zSig1, 1, &term2, &term3 );
 
6324
            term3 or= 1;
 
6325
            term2 or= doubleZSig0;
 
6326
            add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
 
6327
        end;
 
6328
        zSig1 or= ( ( rem1 or rem2 or rem3 ) <> 0 );
 
6329
    end;
 
6330
    shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 );
 
6331
    zSig0 or= doubleZSig0;
 
6332
    result :=
 
6333
        roundAndPackFloatx80(
 
6334
            floatx80_rounding_precision, 0, zExp, zSig0, zSig1 );
 
6335
 
 
6336
end;
 
6337
 
 
6338
{*----------------------------------------------------------------------------
 
6339
| Returns 1 if the extended double-precision floating-point value `a' is
 
6340
| equal to the corresponding value `b', and 0 otherwise.  The comparison is
 
6341
| performed according to the IEC/IEEE Standard for Binary Floating-Point
 
6342
| Arithmetic.
 
6343
*----------------------------------------------------------------------------*}
 
6344
 
 
6345
function floatx80_eq(a: floatx80; b: floatx80 ): flag;
 
6346
begin
 
6347
    if (    (    ( extractFloatx80Exp( a ) = $7FFF )
 
6348
              and (bits64) ( extractFloatx80Frac( a ) shl 1 ) )
 
6349
         or (    ( extractFloatx80Exp( b ) = $7FFF )
 
6350
              and (bits64) ( extractFloatx80Frac( b ) shl 1 ) )
 
6351
       ) begin
 
6352
        if (    floatx80_is_signaling_nan( a )
 
6353
             or floatx80_is_signaling_nan( b ) ) begin
 
6354
            float_raise( float_flag_invalid );
 
6355
        end;
 
6356
        result := 0;
 
6357
    end;
 
6358
    result :=
 
6359
           ( a.low = b.low )
 
6360
        and (    ( a.high = b.high )
 
6361
             or (    ( a.low = 0 )
 
6362
                  and ( (bits16) ( ( a.high or b.high ) shl 1 ) = 0 ) )
 
6363
           );
 
6364
 
 
6365
end;
 
6366
 
 
6367
{*----------------------------------------------------------------------------
 
6368
| Returns 1 if the extended double-precision floating-point value `a' is
 
6369
| less than or equal to the corresponding value `b', and 0 otherwise.  The
 
6370
| comparison is performed according to the IEC/IEEE Standard for Binary
 
6371
| Floating-Point Arithmetic.
 
6372
*----------------------------------------------------------------------------*}
 
6373
 
 
6374
function floatx80_le(a: floatx80; b: floatx80 ): flag;
 
6375
var
 
6376
    aSign, bSign: flag;
 
6377
begin
 
6378
    if (    (    ( extractFloatx80Exp( a ) = $7FFF )
 
6379
              and (bits64) ( extractFloatx80Frac( a ) shl 1 ) )
 
6380
         or (    ( extractFloatx80Exp( b ) = $7FFF )
 
6381
              and (bits64) ( extractFloatx80Frac( b ) shl 1 ) )
 
6382
       ) begin
 
6383
        float_raise( float_flag_invalid );
 
6384
        result := 0;
 
6385
    end;
 
6386
    aSign := extractFloatx80Sign( a );
 
6387
    bSign := extractFloatx80Sign( b );
 
6388
    if ( aSign <> bSign ) begin
 
6389
        result :=
 
6390
               aSign
 
6391
            or (    ( ( (bits16) ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
 
6392
                 = 0 );
 
6393
    end;
 
6394
    result :=
 
6395
          aSign ? le128( b.high, b.low, a.high, a.low )
 
6396
        : le128( a.high, a.low, b.high, b.low );
 
6397
 
 
6398
end;
 
6399
 
 
6400
{*----------------------------------------------------------------------------
 
6401
| Returns 1 if the extended double-precision floating-point value `a' is
 
6402
| less than the corresponding value `b', and 0 otherwise.  The comparison
 
6403
| is performed according to the IEC/IEEE Standard for Binary Floating-Point
 
6404
| Arithmetic.
 
6405
*----------------------------------------------------------------------------*}
 
6406
 
 
6407
function floatx80_lt(a: floatx80; b: floatx80 ): flag;
 
6408
var
 
6409
    aSign, bSign: flag;
 
6410
begin
 
6411
    if (    (    ( extractFloatx80Exp( a ) = $7FFF )
 
6412
              and (bits64) ( extractFloatx80Frac( a ) shl 1 ) )
 
6413
         or (    ( extractFloatx80Exp( b ) = $7FFF )
 
6414
              and (bits64) ( extractFloatx80Frac( b ) shl 1 ) )
 
6415
       ) begin
 
6416
        float_raise( float_flag_invalid );
 
6417
        result := 0;
 
6418
    end;
 
6419
    aSign := extractFloatx80Sign( a );
 
6420
    bSign := extractFloatx80Sign( b );
 
6421
    if ( aSign <> bSign ) begin
 
6422
        result :=
 
6423
               aSign
 
6424
            and (    ( ( (bits16) ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
 
6425
                 <> 0 );
 
6426
    end;
 
6427
    result :=
 
6428
          aSign ? lt128( b.high, b.low, a.high, a.low )
 
6429
        : lt128( a.high, a.low, b.high, b.low );
 
6430
 
 
6431
end;
 
6432
 
 
6433
{*----------------------------------------------------------------------------
 
6434
| Returns 1 if the extended double-precision floating-point value `a' is equal
 
6435
| to the corresponding value `b', and 0 otherwise.  The invalid exception is
 
6436
| raised if either operand is a NaN.  Otherwise, the comparison is performed
 
6437
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
6438
*----------------------------------------------------------------------------*}
 
6439
 
 
6440
function floatx80_eq_signaling(a: floatx80; b: floatx80 ): flag;
 
6441
begin
 
6442
    if (    (    ( extractFloatx80Exp( a ) = $7FFF )
 
6443
              and (bits64) ( extractFloatx80Frac( a ) shl 1 ) )
 
6444
         or (    ( extractFloatx80Exp( b ) = $7FFF )
 
6445
              and (bits64) ( extractFloatx80Frac( b ) shl 1 ) )
 
6446
       ) begin
 
6447
        float_raise( float_flag_invalid );
 
6448
        result := 0;
 
6449
    end;
 
6450
    result :=
 
6451
           ( a.low = b.low )
 
6452
        and (    ( a.high = b.high )
 
6453
             or (    ( a.low = 0 )
 
6454
                  and ( (bits16) ( ( a.high or b.high ) shl 1 ) = 0 ) )
 
6455
           );
 
6456
 
 
6457
end;
 
6458
 
 
6459
{*----------------------------------------------------------------------------
 
6460
| Returns 1 if the extended double-precision floating-point value `a' is less
 
6461
| than or equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs
 
6462
| do not cause an exception.  Otherwise, the comparison is performed according
 
6463
| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
6464
*----------------------------------------------------------------------------*}
 
6465
 
 
6466
function floatx80_le_quiet(a: floatx80; b: floatx80 ): flag;
 
6467
var
 
6468
    aSign, bSign: flag;
 
6469
begin
 
6470
    if (    (    ( extractFloatx80Exp( a ) = $7FFF )
 
6471
              and (bits64) ( extractFloatx80Frac( a ) shl 1 ) )
 
6472
         or (    ( extractFloatx80Exp( b ) = $7FFF )
 
6473
              and (bits64) ( extractFloatx80Frac( b ) shl 1 ) )
 
6474
       ) begin
 
6475
        if (    floatx80_is_signaling_nan( a )
 
6476
             or floatx80_is_signaling_nan( b ) ) begin
 
6477
            float_raise( float_flag_invalid );
 
6478
        end;
 
6479
        result := 0;
 
6480
    end;
 
6481
    aSign := extractFloatx80Sign( a );
 
6482
    bSign := extractFloatx80Sign( b );
 
6483
    if ( aSign <> bSign ) begin
 
6484
        result :=
 
6485
               aSign
 
6486
            or (    ( ( (bits16) ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
 
6487
                 = 0 );
 
6488
    end;
 
6489
    result :=
 
6490
          aSign ? le128( b.high, b.low, a.high, a.low )
 
6491
        : le128( a.high, a.low, b.high, b.low );
 
6492
 
 
6493
end;
 
6494
 
 
6495
{*----------------------------------------------------------------------------
 
6496
| Returns 1 if the extended double-precision floating-point value `a' is less
 
6497
| than the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause
 
6498
| an exception.  Otherwise, the comparison is performed according to the
 
6499
| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
6500
*----------------------------------------------------------------------------*}
 
6501
 
 
6502
function floatx80_lt_quiet(a: floatx80; b: floatx80 ): flag;
 
6503
var
 
6504
    aSign, bSign: flag;
 
6505
begin
 
6506
    if (    (    ( extractFloatx80Exp( a ) = $7FFF )
 
6507
              and (bits64) ( extractFloatx80Frac( a ) shl 1 ) )
 
6508
         or (    ( extractFloatx80Exp( b ) = $7FFF )
 
6509
              and (bits64) ( extractFloatx80Frac( b ) shl 1 ) )
 
6510
       ) begin
 
6511
        if (    floatx80_is_signaling_nan( a )
 
6512
             or floatx80_is_signaling_nan( b ) ) begin
 
6513
            float_raise( float_flag_invalid );
 
6514
        end;
 
6515
        result := 0;
 
6516
    end;
 
6517
    aSign := extractFloatx80Sign( a );
 
6518
    bSign := extractFloatx80Sign( b );
 
6519
    if ( aSign <> bSign ) begin
 
6520
        result :=
 
6521
               aSign
 
6522
            and (    ( ( (bits16) ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
 
6523
                 <> 0 );
 
6524
    end;
 
6525
    result :=
 
6526
          aSign ? lt128( b.high, b.low, a.high, a.low )
 
6527
        : lt128( a.high, a.low, b.high, b.low );
 
6528
 
 
6529
end;
 
6530
 
 
6531
{$endif FPC_SOFTFLOAT_FLOATX80}
 
6532
 
 
6533
 
 
6534
{$ifdef FPC_SOFTFLOAT_FLOAT128}
 
6535
 
 
6536
{*----------------------------------------------------------------------------
 
6537
| Returns the least-significant 64 fraction bits of the quadruple-precision
 
6538
| floating-point value `a'.
 
6539
*----------------------------------------------------------------------------*}
 
6540
 
 
6541
function extractFloat128Frac1(a : float128): bits64;
 
6542
begin
 
6543
    result:=a.low;
 
6544
end;
 
6545
 
 
6546
{*----------------------------------------------------------------------------
 
6547
| Returns the most-significant 48 fraction bits of the quadruple-precision
 
6548
| floating-point value `a'.
 
6549
*----------------------------------------------------------------------------*}
 
6550
 
 
6551
function extractFloat128Frac0(a : float128): bits64;
 
6552
begin
 
6553
    result:=a.high and int64($0000FFFFFFFFFFFF);
 
6554
end;
 
6555
 
 
6556
{*----------------------------------------------------------------------------
 
6557
| Returns the exponent bits of the quadruple-precision floating-point value
 
6558
| `a'.
 
6559
*----------------------------------------------------------------------------*}
 
6560
 
 
6561
function extractFloat128Exp(a : float128): int32;
 
6562
begin
 
6563
    result:=( a.high shr 48 ) and $7FFF;
 
6564
end;
 
6565
 
 
6566
{*----------------------------------------------------------------------------
 
6567
| Returns the sign bit of the quadruple-precision floating-point value `a'.
 
6568
*----------------------------------------------------------------------------*}
 
6569
 
 
6570
function extractFloat128Sign(a : float128): flag;
 
6571
begin
 
6572
    result:=a.high shr 63;
 
6573
end;
 
6574
 
 
6575
{*----------------------------------------------------------------------------
 
6576
| Normalizes the subnormal quadruple-precision floating-point value
 
6577
| represented by the denormalized significand formed by the concatenation of
 
6578
| `aSig0' and `aSig1'.  The normalized exponent is stored at the location
 
6579
| pointed to by `zExpPtr'.  The most significant 49 bits of the normalized
 
6580
| significand are stored at the location pointed to by `zSig0Ptr', and the
 
6581
| least significant 64 bits of the normalized significand are stored at the
 
6582
| location pointed to by `zSig1Ptr'.
 
6583
*----------------------------------------------------------------------------*}
 
6584
 
 
6585
procedure normalizeFloat128Subnormal(
 
6586
     aSig0: bits64;
 
6587
     aSig1: bits64;
 
6588
     var zExpPtr: int32;
 
6589
     var zSig0Ptr: bits64;
 
6590
     var zSig1Ptr: bits64);
 
6591
var
 
6592
    shiftCount: int8;
 
6593
begin
 
6594
    if ( aSig0 = 0 ) then
 
6595
    begin
 
6596
        shiftCount := countLeadingZeros64( aSig1 ) - 15;
 
6597
        if ( shiftCount < 0 ) then
 
6598
        begin
 
6599
            zSig0Ptr := aSig1 shr ( - shiftCount );
 
6600
            zSig1Ptr := aSig1 shl ( shiftCount and 63 );
 
6601
        end
 
6602
        else begin
 
6603
            zSig0Ptr := aSig1 shl shiftCount;
 
6604
            zSig1Ptr := 0;
 
6605
        end;
 
6606
        zExpPtr := - shiftCount - 63;
 
6607
    end
 
6608
    else begin
 
6609
        shiftCount := countLeadingZeros64( aSig0 ) - 15;
 
6610
        shortShift128Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
 
6611
        zExpPtr := 1 - shiftCount;
 
6612
    end;
 
6613
 
 
6614
end;
 
6615
 
 
6616
{*----------------------------------------------------------------------------
 
6617
| Packs the sign `zSign', the exponent `zExp', and the significand formed
 
6618
| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision
 
6619
| floating-point value, returning the result.  After being shifted into the
 
6620
| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply
 
6621
| added together to form the most significant 32 bits of the result.  This
 
6622
| means that any integer portion of `zSig0' will be added into the exponent.
 
6623
| Since a properly normalized significand will have an integer portion equal
 
6624
| to 1, the `zExp' input should be 1 less than the desired result exponent
 
6625
| whenever `zSig0' and `zSig1' concatenated form a complete, normalized
 
6626
| significand.
 
6627
*----------------------------------------------------------------------------*}
 
6628
 
 
6629
function packFloat128( zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64) : float128;
 
6630
var
 
6631
    z: float128;
 
6632
begin
 
6633
    z.low := zSig1;
 
6634
    z.high := ( ( bits64(zSign) ) shl 63 ) + ( ( bits64(zExp) ) shl 48 ) + zSig0;
 
6635
    result:=z;
 
6636
end;
 
6637
 
 
6638
{*----------------------------------------------------------------------------
 
6639
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
 
6640
| and extended significand formed by the concatenation of `zSig0', `zSig1',
 
6641
| and `zSig2', and returns the proper quadruple-precision floating-point value
 
6642
| corresponding to the abstract input.  Ordinarily, the abstract value is
 
6643
| simply rounded and packed into the quadruple-precision format, with the
 
6644
| inexact exception raised if the abstract input cannot be represented
 
6645
| exactly.  However, if the abstract value is too large, the overflow and
 
6646
| inexact exceptions are raised and an infinity or maximal finite value is
 
6647
| returned.  If the abstract value is too small, the input value is rounded to
 
6648
| a subnormal number, and the underflow and inexact exceptions are raised if
 
6649
| the abstract input cannot be represented exactly as a subnormal quadruple-
 
6650
| precision floating-point number.
 
6651
|     The input significand must be normalized or smaller.  If the input
 
6652
| significand is not normalized, `zExp' must be 0; in that case, the result
 
6653
| returned is a subnormal number, and it must not require rounding.  In the
 
6654
| usual case that the input significand is normalized, `zExp' must be 1 less
 
6655
| than the ``true'' floating-point exponent.  The handling of underflow and
 
6656
| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
6657
*----------------------------------------------------------------------------*}
 
6658
 
 
6659
function roundAndPackFloat128(zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64; zSig2: bits64): float128;
 
6660
var
 
6661
    roundingMode: int8;
 
6662
    roundNearestEven, increment, isTiny: flag;
 
6663
begin
 
6664
    roundingMode := float_rounding_mode;
 
6665
    roundNearestEven := ord( roundingMode = float_round_nearest_even );
 
6666
    increment := ord( sbits64(zSig2) < 0 );
 
6667
    if ( roundNearestEven=0 ) then
 
6668
    begin
 
6669
        if ( roundingMode = float_round_to_zero ) then
 
6670
        begin
 
6671
            increment := 0;
 
6672
        end
 
6673
        else begin
 
6674
            if ( zSign<>0 ) then
 
6675
            begin
 
6676
                increment := ord( roundingMode = float_round_down ) and zSig2;
 
6677
            end
 
6678
            else begin
 
6679
                increment := ord( roundingMode = float_round_up ) and zSig2;
 
6680
            end;
 
6681
        end;
 
6682
    end;
 
6683
    if ( $7FFD <= bits32(zExp) ) then
 
6684
    begin
 
6685
        if (    ord( $7FFD < zExp )
 
6686
             or (    ord( zExp = $7FFD )
 
6687
                  and eq128(
 
6688
                         int64( $0001FFFFFFFFFFFF ),
 
6689
                         int64( $FFFFFFFFFFFFFFFF ),
 
6690
                         zSig0,
 
6691
                         zSig1
 
6692
                     )
 
6693
                  and increment
 
6694
                )
 
6695
           )<>0 then
 
6696
           begin
 
6697
            float_raise( float_flag_overflow or float_flag_inexact );
 
6698
            if (    ord( roundingMode = float_round_to_zero )
 
6699
                 or ( zSign and ord( roundingMode = float_round_up ) )
 
6700
                 or ( not(zSign) and ord( roundingMode = float_round_down ) )
 
6701
               )<>0 then
 
6702
               begin
 
6703
                result :=
 
6704
                    packFloat128(
 
6705
                        zSign,
 
6706
                        $7FFE,
 
6707
                        int64( $0000FFFFFFFFFFFF ),
 
6708
                        int64( $FFFFFFFFFFFFFFFF )
 
6709
                    );
 
6710
            end;
 
6711
            result:=packFloat128( zSign, $7FFF, 0, 0 );
 
6712
        end;
 
6713
        if ( zExp < 0 ) then
 
6714
        begin
 
6715
            isTiny :=
 
6716
                   ord(( float_detect_tininess = float_tininess_before_rounding )
 
6717
                or ( zExp < -1 )
 
6718
                or not( increment<>0 )
 
6719
                or boolean(lt128(
 
6720
                       zSig0,
 
6721
                       zSig1,
 
6722
                       int64( $0001FFFFFFFFFFFF ),
 
6723
                       int64( $FFFFFFFFFFFFFFFF )
 
6724
                   )));
 
6725
            shift128ExtraRightJamming(
 
6726
                zSig0, zSig1, zSig2, - zExp, zSig0, zSig1, zSig2 );
 
6727
            zExp := 0;
 
6728
            if ( isTiny and zSig2 )<>0 then
 
6729
              float_raise( float_flag_underflow );
 
6730
            if ( roundNearestEven<>0 ) then
 
6731
            begin
 
6732
                increment := ord( sbits64(zSig2) < 0 );
 
6733
            end
 
6734
            else begin
 
6735
                if ( zSign<>0 ) then
 
6736
                begin
 
6737
                    increment := ord( roundingMode = float_round_down ) and zSig2;
 
6738
                end
 
6739
                else begin
 
6740
                    increment := ord( roundingMode = float_round_up ) and zSig2;
 
6741
                end;
 
6742
            end;
 
6743
        end;
 
6744
    end;
 
6745
    if ( zSig2<>0 ) then
 
6746
      softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
6747
    if ( increment<>0 ) then
 
6748
    begin
 
6749
        add128( zSig0, zSig1, 0, 1, zSig0, zSig1 );
 
6750
        zSig1 := zSig1 and  not( ord( zSig2 + zSig2 = 0 ) and roundNearestEven );
 
6751
    end
 
6752
    else begin
 
6753
        if ( ( zSig0 or zSig1 ) = 0 ) then
 
6754
          zExp := 0;
 
6755
    end;
 
6756
    result:=packFloat128( zSign, zExp, zSig0, zSig1 );
 
6757
end;
 
6758
 
 
6759
{*----------------------------------------------------------------------------
 
6760
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
 
6761
| and significand formed by the concatenation of `zSig0' and `zSig1', and
 
6762
| returns the proper quadruple-precision floating-point value corresponding
 
6763
| to the abstract input.  This routine is just like `roundAndPackFloat128'
 
6764
| except that the input significand has fewer bits and does not have to be
 
6765
| normalized.  In all cases, `zExp' must be 1 less than the ``true'' floating-
 
6766
| point exponent.
 
6767
*----------------------------------------------------------------------------*}
 
6768
 
 
6769
function normalizeRoundAndPackFloat128(zSign: flag; zExp: int32; zSig0: bits64; zSig1: bits64): float128;
 
6770
var
 
6771
    shiftCount: int8;
 
6772
    zSig2: bits64;
 
6773
begin
 
6774
    if ( zSig0 = 0 ) then
 
6775
    begin
 
6776
        zSig0 := zSig1;
 
6777
        zSig1 := 0;
 
6778
        dec(zExp, 64);
 
6779
    end;
 
6780
    shiftCount := countLeadingZeros64( zSig0 ) - 15;
 
6781
    if ( 0 <= shiftCount ) then
 
6782
    begin
 
6783
        zSig2 := 0;
 
6784
        shortShift128Left( zSig0, zSig1, shiftCount, zSig0, zSig1 );
 
6785
    end
 
6786
    else begin
 
6787
        shift128ExtraRightJamming(
 
6788
            zSig0, zSig1, 0, - shiftCount, zSig0, zSig1, zSig2 );
 
6789
    end;
 
6790
    dec(zExp, shiftCount);
 
6791
    result:=roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
 
6792
 
 
6793
end;
 
6794
 
 
6795
{*----------------------------------------------------------------------------
 
6796
| Returns the result of converting the quadruple-precision floating-point
 
6797
| value `a' to the 32-bit two's complement integer format.  The conversion
 
6798
| is performed according to the IEC/IEEE Standard for Binary Floating-Point
 
6799
| Arithmetic---which means in particular that the conversion is rounded
 
6800
| according to the current rounding mode.  If `a' is a NaN, the largest
 
6801
| positive integer is returned.  Otherwise, if the conversion overflows, the
 
6802
| largest integer with the same sign as `a' is returned.
 
6803
*----------------------------------------------------------------------------*}
 
6804
 
 
6805
function float128_to_int32(a: float128): int32;
 
6806
var
 
6807
    aSign: flag;
 
6808
    aExp, shiftCount: int32;
 
6809
    aSig0, aSig1: bits64;
 
6810
begin
 
6811
    aSig1 := extractFloat128Frac1( a );
 
6812
    aSig0 := extractFloat128Frac0( a );
 
6813
    aExp := extractFloat128Exp( a );
 
6814
    aSign := extractFloat128Sign( a );
 
6815
    if ( ord( aExp = $7FFF ) and ( aSig0 or aSig1 ) )<>0 then
 
6816
      aSign := 0;
 
6817
    if ( aExp<>0 ) then
 
6818
      aSig0 := aSig0 or int64( $0001000000000000 );
 
6819
    aSig0 := aSig0 or ord( aSig1 <> 0 );
 
6820
    shiftCount := $4028 - aExp;
 
6821
    if ( 0 < shiftCount ) then
 
6822
      shift64RightJamming( aSig0, shiftCount, aSig0 );
 
6823
    result := roundAndPackInt32( aSign, aSig0 );
 
6824
 
 
6825
end;
 
6826
 
 
6827
{*----------------------------------------------------------------------------
 
6828
| Returns the result of converting the quadruple-precision floating-point
 
6829
| value `a' to the 32-bit two's complement integer format.  The conversion
 
6830
| is performed according to the IEC/IEEE Standard for Binary Floating-Point
 
6831
| Arithmetic, except that the conversion is always rounded toward zero.  If
 
6832
| `a' is a NaN, the largest positive integer is returned.  Otherwise, if the
 
6833
| conversion overflows, the largest integer with the same sign as `a' is
 
6834
| returned.
 
6835
*----------------------------------------------------------------------------*}
 
6836
 
 
6837
function float128_to_int32_round_to_zero(a: float128): int32;
 
6838
var
 
6839
    aSign: flag;
 
6840
    aExp, shiftCount: int32;
 
6841
    aSig0, aSig1, savedASig: bits64;
 
6842
    z: int32;
 
6843
label
 
6844
    invalid;
 
6845
begin
 
6846
    aSig1 := extractFloat128Frac1( a );
 
6847
    aSig0 := extractFloat128Frac0( a );
 
6848
    aExp := extractFloat128Exp( a );
 
6849
    aSign := extractFloat128Sign( a );
 
6850
    aSig0 := aSig0 or ord( aSig1 <> 0 );
 
6851
    if ( $401E < aExp ) then
 
6852
    begin
 
6853
        if ( ord( aExp = $7FFF ) and aSig0 )<>0 then
 
6854
          aSign := 0;
 
6855
        goto invalid;
 
6856
    end
 
6857
    else if ( aExp < $3FFF ) then
 
6858
    begin
 
6859
        if ( aExp or aSig0 )<>0 then
 
6860
          softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
6861
        result := 0;
 
6862
        exit;
 
6863
    end;
 
6864
    aSig0 := aSig0 or int64( $0001000000000000 );
 
6865
    shiftCount := $402F - aExp;
 
6866
    savedASig := aSig0;
 
6867
    aSig0 := aSig0 shr shiftCount;
 
6868
    z := aSig0;
 
6869
    if ( aSign )<>0 then
 
6870
      z := - z;
 
6871
    if ( ord( z < 0 ) xor aSign )<>0 then
 
6872
    begin
 
6873
 invalid:
 
6874
        float_raise( float_flag_invalid );
 
6875
        if aSign<>0 then
 
6876
          result:=$80000000
 
6877
        else
 
6878
          result:=$7FFFFFFF;
 
6879
        exit;
 
6880
    end;
 
6881
    if ( ( aSig0 shl shiftCount ) <> savedASig ) then
 
6882
    begin
 
6883
        softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
6884
    end;
 
6885
    result := z;
 
6886
end;
 
6887
 
 
6888
{*----------------------------------------------------------------------------
 
6889
| Returns the result of converting the quadruple-precision floating-point
 
6890
| value `a' to the 64-bit two's complement integer format.  The conversion
 
6891
| is performed according to the IEC/IEEE Standard for Binary Floating-Point
 
6892
| Arithmetic---which means in particular that the conversion is rounded
 
6893
| according to the current rounding mode.  If `a' is a NaN, the largest
 
6894
| positive integer is returned.  Otherwise, if the conversion overflows, the
 
6895
| largest integer with the same sign as `a' is returned.
 
6896
*----------------------------------------------------------------------------*}
 
6897
 
 
6898
function float128_to_int64(a: float128): int64;
 
6899
var
 
6900
    aSign: flag;
 
6901
    aExp, shiftCount: int32;
 
6902
    aSig0, aSig1: bits64;
 
6903
begin
 
6904
    aSig1 := extractFloat128Frac1( a );
 
6905
    aSig0 := extractFloat128Frac0( a );
 
6906
    aExp := extractFloat128Exp( a );
 
6907
    aSign := extractFloat128Sign( a );
 
6908
    if ( aExp<>0 ) then
 
6909
      aSig0 := aSig0 or int64( $0001000000000000 );
 
6910
    shiftCount := $402F - aExp;
 
6911
    if ( shiftCount <= 0 ) then
 
6912
    begin
 
6913
        if ( $403E < aExp ) then
 
6914
        begin
 
6915
            float_raise( float_flag_invalid );
 
6916
            if (    (aSign=0)
 
6917
                 or (    ( aExp = $7FFF )
 
6918
                      and ( (aSig1<>0) or ( aSig0 <> int64( $0001000000000000 ) ) )
 
6919
                    )
 
6920
               ) then
 
6921
               begin
 
6922
                result := int64( $7FFFFFFFFFFFFFFF );
 
6923
            end;
 
6924
            result := int64( $8000000000000000 );
 
6925
        end;
 
6926
        shortShift128Left( aSig0, aSig1, - shiftCount, aSig0, aSig1 );
 
6927
    end
 
6928
    else begin
 
6929
        shift64ExtraRightJamming( aSig0, aSig1, shiftCount, aSig0, aSig1 );
 
6930
    end;
 
6931
    result := roundAndPackInt64( aSign, aSig0, aSig1 );
 
6932
 
 
6933
end;
 
6934
 
 
6935
{*----------------------------------------------------------------------------
 
6936
| Returns the result of converting the quadruple-precision floating-point
 
6937
| value `a' to the 64-bit two's complement integer format.  The conversion
 
6938
| is performed according to the IEC/IEEE Standard for Binary Floating-Point
 
6939
| Arithmetic, except that the conversion is always rounded toward zero.
 
6940
| If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
 
6941
| the conversion overflows, the largest integer with the same sign as `a' is
 
6942
| returned.
 
6943
*----------------------------------------------------------------------------*}
 
6944
 
 
6945
function float128_to_int64_round_to_zero(a: float128): int64;
 
6946
var
 
6947
    aSign: flag;
 
6948
    aExp, shiftCount: int32;
 
6949
    aSig0, aSig1: bits64;
 
6950
    z: int64;
 
6951
begin
 
6952
    aSig1 := extractFloat128Frac1( a );
 
6953
    aSig0 := extractFloat128Frac0( a );
 
6954
    aExp := extractFloat128Exp( a );
 
6955
    aSign := extractFloat128Sign( a );
 
6956
    if ( aExp<>0 ) then
 
6957
      aSig0 := aSig0 or int64( $0001000000000000 );
 
6958
    shiftCount := aExp - $402F;
 
6959
    if ( 0 < shiftCount ) then
 
6960
    begin
 
6961
        if ( $403E <= aExp ) then
 
6962
        begin
 
6963
            aSig0 := aSig0 and int64( $0000FFFFFFFFFFFF );
 
6964
            if (    ( a.high = int64( $C03E000000000000 ) )
 
6965
                 and ( aSig1 < int64( $0002000000000000 ) ) ) then
 
6966
            begin
 
6967
                if ( aSig1<>0 ) then
 
6968
                  softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
6969
            end
 
6970
            else begin
 
6971
                float_raise( float_flag_invalid );
 
6972
                if ( (aSign=0) or ( ( aExp = $7FFF ) and (( aSig0 or aSig1 )<>0) ) ) then
 
6973
                begin
 
6974
                    result := int64( $7FFFFFFFFFFFFFFF );
 
6975
                    exit;
 
6976
                end;
 
6977
            end;
 
6978
            result := int64( $8000000000000000 );
 
6979
            exit;
 
6980
        end;
 
6981
        z := ( aSig0 shl shiftCount ) or ( aSig1>>( ( - shiftCount ) and 63 ) );
 
6982
        if ( int64( aSig1 shl shiftCount )<>0 ) then
 
6983
        begin
 
6984
            softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
6985
        end;
 
6986
    end
 
6987
    else begin
 
6988
        if ( aExp < $3FFF ) then
 
6989
        begin
 
6990
            if ( aExp or aSig0 or aSig1 )<>0 then
 
6991
            begin
 
6992
                softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
6993
            end;
 
6994
            result := 0;
 
6995
            exit;
 
6996
        end;
 
6997
        z := aSig0 shr ( - shiftCount );
 
6998
        if (    (aSig1<>0)
 
6999
             or ( (shiftCount<>0) and (int64( aSig0 shl ( shiftCount and 63 ) )<>0) ) ) then
 
7000
        begin
 
7001
            softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
7002
        end;
 
7003
    end;
 
7004
    if ( aSign<>0 ) then
 
7005
      z := - z;
 
7006
    result := z;
 
7007
 
 
7008
end;
 
7009
 
 
7010
{*----------------------------------------------------------------------------
 
7011
| Returns the result of converting the quadruple-precision floating-point
 
7012
| value `a' to the single-precision floating-point format.  The conversion
 
7013
| is performed according to the IEC/IEEE Standard for Binary Floating-Point
 
7014
| Arithmetic.
 
7015
*----------------------------------------------------------------------------*}
 
7016
 
 
7017
function float128_to_float32(a: float128): float32;
 
7018
var
 
7019
    aSign: flag;
 
7020
    aExp: int32;
 
7021
    aSig0, aSig1: bits64;
 
7022
    zSig: bits32;
 
7023
begin
 
7024
    aSig1 := extractFloat128Frac1( a );
 
7025
    aSig0 := extractFloat128Frac0( a );
 
7026
    aExp := extractFloat128Exp( a );
 
7027
    aSign := extractFloat128Sign( a );
 
7028
    if ( aExp = $7FFF ) then
 
7029
    begin
 
7030
        if ( aSig0 or aSig1 )<>0 then
 
7031
        begin
 
7032
            result := commonNaNToFloat32( float128ToCommonNaN( a ) );
 
7033
            exit;
 
7034
        end;
 
7035
        result := packFloat32( aSign, $FF, 0 );
 
7036
        exit;
 
7037
    end;
 
7038
    aSig0 := aSig0 or ord( aSig1 <> 0 );
 
7039
    shift64RightJamming( aSig0, 18, aSig0 );
 
7040
    zSig := aSig0;
 
7041
    if ( aExp or zSig )<>0 then
 
7042
    begin
 
7043
        zSig := zSig or $40000000;
 
7044
        dec(aExp,$3F81);
 
7045
    end;
 
7046
    result := roundAndPackFloat32( aSign, aExp, zSig );
 
7047
 
 
7048
end;
 
7049
 
 
7050
{*----------------------------------------------------------------------------
 
7051
| Returns the result of converting the quadruple-precision floating-point
 
7052
| value `a' to the double-precision floating-point format.  The conversion
 
7053
| is performed according to the IEC/IEEE Standard for Binary Floating-Point
 
7054
| Arithmetic.
 
7055
*----------------------------------------------------------------------------*}
 
7056
 
 
7057
function float128_to_float64(a: float128): float64;
 
7058
var
 
7059
    aSign: flag;
 
7060
    aExp: int32;
 
7061
    aSig0, aSig1: bits64;
 
7062
begin
 
7063
    aSig1 := extractFloat128Frac1( a );
 
7064
    aSig0 := extractFloat128Frac0( a );
 
7065
    aExp := extractFloat128Exp( a );
 
7066
    aSign := extractFloat128Sign( a );
 
7067
    if ( aExp = $7FFF ) then
 
7068
    begin
 
7069
        if ( aSig0 or aSig1 )<>0 then
 
7070
        begin
 
7071
            commonNaNToFloat64( float128ToCommonNaN( a ),result);
 
7072
            exit;
 
7073
        end;
 
7074
        result:=packFloat64( aSign, $7FF, 0);
 
7075
        exit;
 
7076
    end;
 
7077
    shortShift128Left( aSig0, aSig1, 14, aSig0, aSig1 );
 
7078
    aSig0 := aSig0 or ord( aSig1 <> 0 );
 
7079
    if ( aExp or aSig0 )<>0 then
 
7080
    begin
 
7081
        aSig0 := aSig0 or int64( $4000000000000000 );
 
7082
        dec(aExp,$3C01);
 
7083
    end;
 
7084
    result := roundAndPackFloat64( aSign, aExp, aSig0 );
 
7085
end;
 
7086
 
 
7087
{$ifdef FPC_SOFTFLOAT_FLOATX80}
 
7088
 
 
7089
{*----------------------------------------------------------------------------
 
7090
| Returns the result of converting the quadruple-precision floating-point
 
7091
| value `a' to the extended double-precision floating-point format.  The
 
7092
| conversion is performed according to the IEC/IEEE Standard for Binary
 
7093
| Floating-Point Arithmetic.
 
7094
*----------------------------------------------------------------------------*}
 
7095
 
 
7096
function float128_to_floatx80(a: float128): floatx80;
 
7097
var
 
7098
    aSign: flag;
 
7099
    aExp: int32;
 
7100
    aSig0, aSig1: bits64;
 
7101
begin
 
7102
    aSig1 := extractFloat128Frac1( a );
 
7103
    aSig0 := extractFloat128Frac0( a );
 
7104
    aExp := extractFloat128Exp( a );
 
7105
    aSign := extractFloat128Sign( a );
 
7106
    if ( aExp = $7FFF ) begin
 
7107
        if ( aSig0 or aSig1 ) begin
 
7108
            result := commonNaNToFloatx80( float128ToCommonNaN( a ) );
 
7109
        end;
 
7110
        result := packFloatx80( aSign, $7FFF, int64( $8000000000000000 ) );
 
7111
    end;
 
7112
    if ( aExp = 0 ) begin
 
7113
        if ( ( aSig0 or aSig1 ) = 0 ) result := packFloatx80( aSign, 0, 0 );
 
7114
        normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
 
7115
    end;
 
7116
    else begin
 
7117
        aSig0 or= int64( $0001000000000000 );
 
7118
    end;
 
7119
    shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 );
 
7120
    result := roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 );
 
7121
 
 
7122
end;
 
7123
 
 
7124
{$endif FPC_SOFTFLOAT_FLOATX80}
 
7125
 
 
7126
{*----------------------------------------------------------------------------
 
7127
| Rounds the quadruple-precision floating-point value `a' to an integer, and
 
7128
| Returns the result as a quadruple-precision floating-point value.  The
 
7129
| operation is performed according to the IEC/IEEE Standard for Binary
 
7130
| Floating-Point Arithmetic.
 
7131
*----------------------------------------------------------------------------*}
 
7132
 
 
7133
function float128_round_to_int(a: float128): float128;
 
7134
var
 
7135
    aSign: flag;
 
7136
    aExp: int32;
 
7137
    lastBitMask, roundBitsMask: bits64;
 
7138
    roundingMode: int8;
 
7139
    z: float128;
 
7140
begin
 
7141
    aExp := extractFloat128Exp( a );
 
7142
    if ( $402F <= aExp ) then
 
7143
    begin
 
7144
        if ( $406F <= aExp ) then
 
7145
        begin
 
7146
            if (    ( aExp = $7FFF )
 
7147
                 and (( extractFloat128Frac0( a ) or extractFloat128Frac1( a ) )<>0)
 
7148
               ) then
 
7149
               begin
 
7150
                result := propagateFloat128NaN( a, a );
 
7151
                exit;
 
7152
            end;
 
7153
            result := a;
 
7154
            exit;
 
7155
        end;
 
7156
        lastBitMask := 1;
 
7157
        lastBitMask := ( lastBitMask shl ( $406E - aExp ) ) shl 1;
 
7158
        roundBitsMask := lastBitMask - 1;
 
7159
        z := a;
 
7160
        roundingMode := float_rounding_mode;
 
7161
        if ( roundingMode = float_round_nearest_even ) then
 
7162
        begin
 
7163
            if ( lastBitMask )<>0 then
 
7164
            begin
 
7165
                add128( z.high, z.low, 0, lastBitMask shr 1, z.high, z.low );
 
7166
                if ( ( z.low and roundBitsMask ) = 0 ) then
 
7167
                  z.low := z.low and not(lastBitMask);
 
7168
            end
 
7169
            else begin
 
7170
                if ( sbits64(z.low) < 0 ) then
 
7171
                begin
 
7172
                    inc(z.high);
 
7173
                    if ( bits64( z.low shl 1 ) = 0 ) then
 
7174
                      z.high := z.high and not(1);
 
7175
                end;
 
7176
            end;
 
7177
        end
 
7178
        else if ( roundingMode <> float_round_to_zero ) then
 
7179
        begin
 
7180
            if (   extractFloat128Sign( z )
 
7181
                 xor ord( roundingMode = float_round_up ) )<>0 then
 
7182
            begin
 
7183
                add128( z.high, z.low, 0, roundBitsMask, z.high, z.low );
 
7184
            end;
 
7185
        end;
 
7186
        z.low := z.low and not(roundBitsMask);
 
7187
    end
 
7188
    else begin
 
7189
        if ( aExp < $3FFF ) then
 
7190
        begin
 
7191
            if ( ( ( bits64( a.high shl 1 ) ) or a.low ) = 0 ) then
 
7192
              begin
 
7193
                result := a;
 
7194
                exit;
 
7195
              end;
 
7196
            softfloat_exception_flags := softfloat_exception_flags or float_flag_inexact;
 
7197
            aSign := extractFloat128Sign( a );
 
7198
            case float_rounding_mode of
 
7199
            float_round_nearest_even:
 
7200
                if (    ( aExp = $3FFE )
 
7201
                     and (   extractFloat128Frac0( a )
 
7202
                          or extractFloat128Frac1( a ) )
 
7203
                   ) begin
 
7204
                   begin
 
7205
                     result := packFloat128( aSign, $3FFF, 0, 0 );
 
7206
                     exit;
 
7207
                   end;
 
7208
                end;
 
7209
             float_round_down:
 
7210
               begin
 
7211
                result :=
 
7212
                      aSign ? packFloat128( 1, $3FFF, 0, 0 )
 
7213
                    : packFloat128( 0, 0, 0, 0 );
 
7214
               end;
 
7215
             float_round_up:
 
7216
               begin
 
7217
                result :=
 
7218
                      aSign ? packFloat128( 1, 0, 0, 0 )
 
7219
                    : packFloat128( 0, $3FFF, 0, 0 );
 
7220
                exit;
 
7221
               end;
 
7222
            end;
 
7223
            result := packFloat128( aSign, 0, 0, 0 );
 
7224
            exit;
 
7225
        end;
 
7226
        lastBitMask := 1;
 
7227
        lastBitMask  shl = $402F - aExp;
 
7228
        roundBitsMask := lastBitMask - 1;
 
7229
        z.low := 0;
 
7230
        z.high := a.high;
 
7231
        roundingMode := float_rounding_mode;
 
7232
        if ( roundingMode = float_round_nearest_even ) begin
 
7233
            z.high += lastBitMask>>1;
 
7234
            if ( ( ( z.high and roundBitsMask ) or a.low ) = 0 ) begin
 
7235
                z.high &= ~ lastBitMask;
 
7236
            end;
 
7237
        end;
 
7238
        else if ( roundingMode <> float_round_to_zero ) begin
 
7239
            if (   extractFloat128Sign( z )
 
7240
                 xor ( roundingMode = float_round_up ) ) begin
 
7241
                z.high or= ( a.low <> 0 );
 
7242
                z.high += roundBitsMask;
 
7243
            end;
 
7244
        end;
 
7245
        z.high &= ~ roundBitsMask;
 
7246
    end;
 
7247
    if ( ( z.low <> a.low ) or ( z.high <> a.high ) ) begin
 
7248
        softfloat_exception_flags or= float_flag_inexact;
 
7249
    end;
 
7250
    result := z;
 
7251
 
 
7252
end;
 
7253
 
 
7254
{*----------------------------------------------------------------------------
 
7255
| Returns the result of adding the absolute values of the quadruple-precision
 
7256
| floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
 
7257
| before being returned.  `zSign' is ignored if the result is a NaN.
 
7258
| The addition is performed according to the IEC/IEEE Standard for Binary
 
7259
| Floating-Point Arithmetic.
 
7260
*----------------------------------------------------------------------------*}
 
7261
 
 
7262
function addFloat128Sigs( float128 a, float128 b, flag zSign ): float128;
 
7263
var
 
7264
    aExp, bExp, zExp: int32;
 
7265
    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits64;
 
7266
    expDiff: int32;
 
7267
begin
 
7268
    aSig1 := extractFloat128Frac1( a );
 
7269
    aSig0 := extractFloat128Frac0( a );
 
7270
    aExp := extractFloat128Exp( a );
 
7271
    bSig1 := extractFloat128Frac1( b );
 
7272
    bSig0 := extractFloat128Frac0( b );
 
7273
    bExp := extractFloat128Exp( b );
 
7274
    expDiff := aExp - bExp;
 
7275
    if ( 0 < expDiff ) begin
 
7276
        if ( aExp = $7FFF ) begin
 
7277
            if ( aSig0 or aSig1 ) result := propagateFloat128NaN( a, b );
 
7278
            result := a;
 
7279
        end;
 
7280
        if ( bExp = 0 ) begin
 
7281
            --expDiff;
 
7282
        end;
 
7283
        else begin
 
7284
            bSig0 or= int64( $0001000000000000 );
 
7285
        end;
 
7286
        shift128ExtraRightJamming(
 
7287
            bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 );
 
7288
        zExp := aExp;
 
7289
    end;
 
7290
    else if ( expDiff < 0 ) begin
 
7291
        if ( bExp = $7FFF ) begin
 
7292
            if ( bSig0 or bSig1 ) result := propagateFloat128NaN( a, b );
 
7293
            result := packFloat128( zSign, $7FFF, 0, 0 );
 
7294
        end;
 
7295
        if ( aExp = 0 ) begin
 
7296
            ++expDiff;
 
7297
        end;
 
7298
        else begin
 
7299
            aSig0 or= int64( $0001000000000000 );
 
7300
        end;
 
7301
        shift128ExtraRightJamming(
 
7302
            aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 );
 
7303
        zExp := bExp;
 
7304
    end;
 
7305
    else begin
 
7306
        if ( aExp = $7FFF ) begin
 
7307
            if ( aSig0 or aSig1 or bSig0 or bSig1 ) begin
 
7308
                result := propagateFloat128NaN( a, b );
 
7309
            end;
 
7310
            result := a;
 
7311
        end;
 
7312
        add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
 
7313
        if ( aExp = 0 ) result := packFloat128( zSign, 0, zSig0, zSig1 );
 
7314
        zSig2 := 0;
 
7315
        zSig0 or= int64( $0002000000000000 );
 
7316
        zExp := aExp;
 
7317
        goto shiftRight1;
 
7318
    end;
 
7319
    aSig0 or= int64( $0001000000000000 );
 
7320
    add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
 
7321
    --zExp;
 
7322
    if ( zSig0 < int64( $0002000000000000 ) ) goto roundAndPack;
 
7323
    ++zExp;
 
7324
 shiftRight1:
 
7325
    shift128ExtraRightJamming(
 
7326
        zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
 
7327
 roundAndPack:
 
7328
    result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
 
7329
 
 
7330
end;
 
7331
 
 
7332
{*----------------------------------------------------------------------------
 
7333
| Returns the result of subtracting the absolute values of the quadruple-
 
7334
| precision floating-point values `a' and `b'.  If `zSign' is 1, the
 
7335
| difference is negated before being returned.  `zSign' is ignored if the
 
7336
| result is a NaN.  The subtraction is performed according to the IEC/IEEE
 
7337
| Standard for Binary Floating-Point Arithmetic.
 
7338
*----------------------------------------------------------------------------*}
 
7339
 
 
7340
function subFloat128Sigs( float128 a, float128 b, flag zSign ): float128;
 
7341
var
 
7342
    aExp, bExp, zExp: int32;
 
7343
    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1: bits64;
 
7344
    expDiff: int32;
 
7345
    z: float128;
 
7346
begin
 
7347
    aSig1 := extractFloat128Frac1( a );
 
7348
    aSig0 := extractFloat128Frac0( a );
 
7349
    aExp := extractFloat128Exp( a );
 
7350
    bSig1 := extractFloat128Frac1( b );
 
7351
    bSig0 := extractFloat128Frac0( b );
 
7352
    bExp := extractFloat128Exp( b );
 
7353
    expDiff := aExp - bExp;
 
7354
    shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 );
 
7355
    shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 );
 
7356
    if ( 0 < expDiff ) goto aExpBigger;
 
7357
    if ( expDiff < 0 ) goto bExpBigger;
 
7358
    if ( aExp = $7FFF ) begin
 
7359
        if ( aSig0 or aSig1 or bSig0 or bSig1 ) begin
 
7360
            result := propagateFloat128NaN( a, b );
 
7361
        end;
 
7362
        float_raise( float_flag_invalid );
 
7363
        z.low := float128_default_nan_low;
 
7364
        z.high := float128_default_nan_high;
 
7365
        result := z;
 
7366
    end;
 
7367
    if ( aExp = 0 ) begin
 
7368
        aExp := 1;
 
7369
        bExp := 1;
 
7370
    end;
 
7371
    if ( bSig0 < aSig0 ) goto aBigger;
 
7372
    if ( aSig0 < bSig0 ) goto bBigger;
 
7373
    if ( bSig1 < aSig1 ) goto aBigger;
 
7374
    if ( aSig1 < bSig1 ) goto bBigger;
 
7375
    result := packFloat128( float_rounding_mode = float_round_down, 0, 0, 0 );
 
7376
 bExpBigger:
 
7377
    if ( bExp = $7FFF ) begin
 
7378
        if ( bSig0 or bSig1 ) result := propagateFloat128NaN( a, b );
 
7379
        result := packFloat128( zSign xor 1, $7FFF, 0, 0 );
 
7380
    end;
 
7381
    if ( aExp = 0 ) begin
 
7382
        ++expDiff;
 
7383
    end;
 
7384
    else begin
 
7385
        aSig0 or= int64( $4000000000000000 );
 
7386
    end;
 
7387
    shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
 
7388
    bSig0 or= int64( $4000000000000000 );
 
7389
 bBigger:
 
7390
    sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 );
 
7391
    zExp := bExp;
 
7392
    zSign  xor = 1;
 
7393
    goto normalizeRoundAndPack;
 
7394
 aExpBigger:
 
7395
    if ( aExp = $7FFF ) begin
 
7396
        if ( aSig0 or aSig1 ) result := propagateFloat128NaN( a, b );
 
7397
        result := a;
 
7398
    end;
 
7399
    if ( bExp = 0 ) begin
 
7400
        --expDiff;
 
7401
    end;
 
7402
    else begin
 
7403
        bSig0 or= int64( $4000000000000000 );
 
7404
    end;
 
7405
    shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 );
 
7406
    aSig0 or= int64( $4000000000000000 );
 
7407
 aBigger:
 
7408
    sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
 
7409
    zExp := aExp;
 
7410
 normalizeRoundAndPack:
 
7411
    --zExp;
 
7412
    result := normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 );
 
7413
 
 
7414
end;
 
7415
 
 
7416
{*----------------------------------------------------------------------------
 
7417
| Returns the result of adding the quadruple-precision floating-point values
 
7418
| `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
 
7419
| for Binary Floating-Point Arithmetic.
 
7420
*----------------------------------------------------------------------------*}
 
7421
 
 
7422
function float128_add(a: float128; b: float128): float128;
 
7423
var
 
7424
    aSign, bSign: flag;
 
7425
begin
 
7426
    aSign := extractFloat128Sign( a );
 
7427
    bSign := extractFloat128Sign( b );
 
7428
    if ( aSign = bSign ) begin
 
7429
        result := addFloat128Sigs( a, b, aSign );
 
7430
    end;
 
7431
    else begin
 
7432
        result := subFloat128Sigs( a, b, aSign );
 
7433
    end;
 
7434
 
 
7435
end;
 
7436
 
 
7437
{*----------------------------------------------------------------------------
 
7438
| Returns the result of subtracting the quadruple-precision floating-point
 
7439
| values `a' and `b'.  The operation is performed according to the IEC/IEEE
 
7440
| Standard for Binary Floating-Point Arithmetic.
 
7441
*----------------------------------------------------------------------------*}
 
7442
 
 
7443
function float128_sub(a: float128; b: float128): float128;
 
7444
var
 
7445
    aSign, bSign: flag;
 
7446
begin
 
7447
    aSign := extractFloat128Sign( a );
 
7448
    bSign := extractFloat128Sign( b );
 
7449
    if ( aSign = bSign ) begin
 
7450
        result := subFloat128Sigs( a, b, aSign );
 
7451
    end;
 
7452
    else begin
 
7453
        result := addFloat128Sigs( a, b, aSign );
 
7454
    end;
 
7455
 
 
7456
end;
 
7457
 
 
7458
{*----------------------------------------------------------------------------
 
7459
| Returns the result of multiplying the quadruple-precision floating-point
 
7460
| values `a' and `b'.  The operation is performed according to the IEC/IEEE
 
7461
| Standard for Binary Floating-Point Arithmetic.
 
7462
*----------------------------------------------------------------------------*}
 
7463
 
 
7464
function float128_mul(a: float128; b: float128): float128;
 
7465
var
 
7466
    aSign, bSign, zSign: flag;
 
7467
    aExp, bExp, zExp: int32;
 
7468
    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3: bits64;
 
7469
    z: float128;
 
7470
begin
 
7471
    aSig1 := extractFloat128Frac1( a );
 
7472
    aSig0 := extractFloat128Frac0( a );
 
7473
    aExp := extractFloat128Exp( a );
 
7474
    aSign := extractFloat128Sign( a );
 
7475
    bSig1 := extractFloat128Frac1( b );
 
7476
    bSig0 := extractFloat128Frac0( b );
 
7477
    bExp := extractFloat128Exp( b );
 
7478
    bSign := extractFloat128Sign( b );
 
7479
    zSign := aSign xor bSign;
 
7480
    if ( aExp = $7FFF ) begin
 
7481
        if (    ( aSig0 or aSig1 )
 
7482
             or ( ( bExp = $7FFF ) and ( bSig0 or bSig1 ) ) ) begin
 
7483
            result := propagateFloat128NaN( a, b );
 
7484
        end;
 
7485
        if ( ( bExp or bSig0 or bSig1 ) = 0 ) goto invalid;
 
7486
        result := packFloat128( zSign, $7FFF, 0, 0 );
 
7487
    end;
 
7488
    if ( bExp = $7FFF ) begin
 
7489
        if ( bSig0 or bSig1 ) result := propagateFloat128NaN( a, b );
 
7490
        if ( ( aExp or aSig0 or aSig1 ) = 0 ) begin
 
7491
 invalid:
 
7492
            float_raise( float_flag_invalid );
 
7493
            z.low := float128_default_nan_low;
 
7494
            z.high := float128_default_nan_high;
 
7495
            result := z;
 
7496
        end;
 
7497
        result := packFloat128( zSign, $7FFF, 0, 0 );
 
7498
    end;
 
7499
    if ( aExp = 0 ) begin
 
7500
        if ( ( aSig0 or aSig1 ) = 0 ) result := packFloat128( zSign, 0, 0, 0 );
 
7501
        normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
 
7502
    end;
 
7503
    if ( bExp = 0 ) begin
 
7504
        if ( ( bSig0 or bSig1 ) = 0 ) result := packFloat128( zSign, 0, 0, 0 );
 
7505
        normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
 
7506
    end;
 
7507
    zExp := aExp + bExp - $4000;
 
7508
    aSig0 or= int64( $0001000000000000 );
 
7509
    shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 );
 
7510
    mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 );
 
7511
    add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 );
 
7512
    zSig2 or= ( zSig3 <> 0 );
 
7513
    if ( int64( $0002000000000000 ) <= zSig0 ) begin
 
7514
        shift128ExtraRightJamming(
 
7515
            zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
 
7516
        ++zExp;
 
7517
    end;
 
7518
    result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
 
7519
 
 
7520
end;
 
7521
 
 
7522
{*----------------------------------------------------------------------------
 
7523
| Returns the result of dividing the quadruple-precision floating-point value
 
7524
| `a' by the corresponding value `b'.  The operation is performed according to
 
7525
| the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
7526
*----------------------------------------------------------------------------*}
 
7527
 
 
7528
function float128_div(a: float128; b: float128): float128;
 
7529
var
 
7530
    aSign, bSign, zSign: flag;
 
7531
    aExp, bExp, zExp: int32;
 
7532
    aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2: bits64;
 
7533
    rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;
 
7534
    z: float128;
 
7535
begin
 
7536
    aSig1 := extractFloat128Frac1( a );
 
7537
    aSig0 := extractFloat128Frac0( a );
 
7538
    aExp := extractFloat128Exp( a );
 
7539
    aSign := extractFloat128Sign( a );
 
7540
    bSig1 := extractFloat128Frac1( b );
 
7541
    bSig0 := extractFloat128Frac0( b );
 
7542
    bExp := extractFloat128Exp( b );
 
7543
    bSign := extractFloat128Sign( b );
 
7544
    zSign := aSign xor bSign;
 
7545
    if ( aExp = $7FFF ) begin
 
7546
        if ( aSig0 or aSig1 ) result := propagateFloat128NaN( a, b );
 
7547
        if ( bExp = $7FFF ) begin
 
7548
            if ( bSig0 or bSig1 ) result := propagateFloat128NaN( a, b );
 
7549
            goto invalid;
 
7550
        end;
 
7551
        result := packFloat128( zSign, $7FFF, 0, 0 );
 
7552
    end;
 
7553
    if ( bExp = $7FFF ) begin
 
7554
        if ( bSig0 or bSig1 ) result := propagateFloat128NaN( a, b );
 
7555
        result := packFloat128( zSign, 0, 0, 0 );
 
7556
    end;
 
7557
    if ( bExp = 0 ) begin
 
7558
        if ( ( bSig0 or bSig1 ) = 0 ) begin
 
7559
            if ( ( aExp or aSig0 or aSig1 ) = 0 ) begin
 
7560
 invalid:
 
7561
                float_raise( float_flag_invalid );
 
7562
                z.low := float128_default_nan_low;
 
7563
                z.high := float128_default_nan_high;
 
7564
                result := z;
 
7565
            end;
 
7566
            float_raise( float_flag_divbyzero );
 
7567
            result := packFloat128( zSign, $7FFF, 0, 0 );
 
7568
        end;
 
7569
        normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
 
7570
    end;
 
7571
    if ( aExp = 0 ) begin
 
7572
        if ( ( aSig0 or aSig1 ) = 0 ) result := packFloat128( zSign, 0, 0, 0 );
 
7573
        normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
 
7574
    end;
 
7575
    zExp := aExp - bExp + $3FFD;
 
7576
    shortShift128Left(
 
7577
        aSig0 or int64( $0001000000000000 ), aSig1, 15, &aSig0, &aSig1 );
 
7578
    shortShift128Left(
 
7579
        bSig0 or int64( $0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
 
7580
    if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) begin
 
7581
        shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 );
 
7582
        ++zExp;
 
7583
    end;
 
7584
    zSig0 := estimateDiv128To64( aSig0, aSig1, bSig0 );
 
7585
    mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 );
 
7586
    sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 );
 
7587
    while ( (sbits64) rem0 < 0 ) begin
 
7588
        --zSig0;
 
7589
        add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 );
 
7590
    end;
 
7591
    zSig1 := estimateDiv128To64( rem1, rem2, bSig0 );
 
7592
    if ( ( zSig1 and $3FFF ) <= 4 ) begin
 
7593
        mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 );
 
7594
        sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 );
 
7595
        while ( (sbits64) rem1 < 0 ) begin
 
7596
            --zSig1;
 
7597
            add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 );
 
7598
        end;
 
7599
        zSig1 or= ( ( rem1 or rem2 or rem3 ) <> 0 );
 
7600
    end;
 
7601
    shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 );
 
7602
    result := roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
 
7603
 
 
7604
end;
 
7605
 
 
7606
{*----------------------------------------------------------------------------
 
7607
| Returns the remainder of the quadruple-precision floating-point value `a'
 
7608
| with respect to the corresponding value `b'.  The operation is performed
 
7609
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
7610
*----------------------------------------------------------------------------*}
 
7611
 
 
7612
function float128_rem(a: float128; b: float128): float128;
 
7613
var
 
7614
    aSign, bSign, zSign: flag;
 
7615
    aExp, bExp, expDiff: int32;
 
7616
    aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2: bits64;
 
7617
    allZero, alternateASig0, alternateASig1, sigMean1: bits64;
 
7618
    sigMean0: sbits64;
 
7619
    z: float128;
 
7620
begin
 
7621
    aSig1 := extractFloat128Frac1( a );
 
7622
    aSig0 := extractFloat128Frac0( a );
 
7623
    aExp := extractFloat128Exp( a );
 
7624
    aSign := extractFloat128Sign( a );
 
7625
    bSig1 := extractFloat128Frac1( b );
 
7626
    bSig0 := extractFloat128Frac0( b );
 
7627
    bExp := extractFloat128Exp( b );
 
7628
    bSign := extractFloat128Sign( b );
 
7629
    if ( aExp = $7FFF ) begin
 
7630
        if (    ( aSig0 or aSig1 )
 
7631
             or ( ( bExp = $7FFF ) and ( bSig0 or bSig1 ) ) ) begin
 
7632
            result := propagateFloat128NaN( a, b );
 
7633
        end;
 
7634
        goto invalid;
 
7635
    end;
 
7636
    if ( bExp = $7FFF ) begin
 
7637
        if ( bSig0 or bSig1 ) result := propagateFloat128NaN( a, b );
 
7638
        result := a;
 
7639
    end;
 
7640
    if ( bExp = 0 ) begin
 
7641
        if ( ( bSig0 or bSig1 ) = 0 ) begin
 
7642
 invalid:
 
7643
            float_raise( float_flag_invalid );
 
7644
            z.low := float128_default_nan_low;
 
7645
            z.high := float128_default_nan_high;
 
7646
            result := z;
 
7647
        end;
 
7648
        normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
 
7649
    end;
 
7650
    if ( aExp = 0 ) begin
 
7651
        if ( ( aSig0 or aSig1 ) = 0 ) result := a;
 
7652
        normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
 
7653
    end;
 
7654
    expDiff := aExp - bExp;
 
7655
    if ( expDiff < -1 ) result := a;
 
7656
    shortShift128Left(
 
7657
        aSig0 or int64( $0001000000000000 ),
 
7658
        aSig1,
 
7659
        15 - ( expDiff < 0 ),
 
7660
        &aSig0,
 
7661
        &aSig1
 
7662
    );
 
7663
    shortShift128Left(
 
7664
        bSig0 or int64( $0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
 
7665
    q := le128( bSig0, bSig1, aSig0, aSig1 );
 
7666
    if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
 
7667
    expDiff -= 64;
 
7668
    while ( 0 < expDiff ) begin
 
7669
        q := estimateDiv128To64( aSig0, aSig1, bSig0 );
 
7670
        q := ( 4 < q ) ? q - 4 : 0;
 
7671
        mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 );
 
7672
        shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero );
 
7673
        shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero );
 
7674
        sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 );
 
7675
        expDiff -= 61;
 
7676
    end;
 
7677
    if ( -64 < expDiff ) begin
 
7678
        q := estimateDiv128To64( aSig0, aSig1, bSig0 );
 
7679
        q := ( 4 < q ) ? q - 4 : 0;
 
7680
        q >>= - expDiff;
 
7681
        shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 );
 
7682
        expDiff += 52;
 
7683
        if ( expDiff < 0 ) begin
 
7684
            shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
 
7685
        end;
 
7686
        else begin
 
7687
            shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 );
 
7688
        end;
 
7689
        mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 );
 
7690
        sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 );
 
7691
    end;
 
7692
    else begin
 
7693
        shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 );
 
7694
        shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 );
 
7695
    end;
 
7696
    do begin
 
7697
        alternateASig0 := aSig0;
 
7698
        alternateASig1 := aSig1;
 
7699
        ++q;
 
7700
        sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
 
7701
    end; while ( 0 <= (sbits64) aSig0 );
 
7702
    add128(
 
7703
        aSig0, aSig1, alternateASig0, alternateASig1, &sigMean0, &sigMean1 );
 
7704
    if (    ( sigMean0 < 0 )
 
7705
         or ( ( ( sigMean0 or sigMean1 ) = 0 ) and ( q and 1 ) ) ) begin
 
7706
        aSig0 := alternateASig0;
 
7707
        aSig1 := alternateASig1;
 
7708
    end;
 
7709
    zSign := ( (sbits64) aSig0 < 0 );
 
7710
    if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 );
 
7711
    result :=
 
7712
        normalizeRoundAndPackFloat128( aSign xor zSign, bExp - 4, aSig0, aSig1 );
 
7713
 
 
7714
end;
 
7715
 
 
7716
{*----------------------------------------------------------------------------
 
7717
| Returns the square root of the quadruple-precision floating-point value `a'.
 
7718
| The operation is performed according to the IEC/IEEE Standard for Binary
 
7719
| Floating-Point Arithmetic.
 
7720
*----------------------------------------------------------------------------*}
 
7721
 
 
7722
function float128_sqrt(a: float128): float128;
 
7723
var
 
7724
    aSign: flag;
 
7725
    aExp, zExp: int32;
 
7726
    aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0: bits64;
 
7727
    rem0, rem1, rem2, rem3, term0, term1, term2, term3: bits64;
 
7728
    z: float128;
 
7729
label
 
7730
    invalid;
 
7731
begin
 
7732
    aSig1 := extractFloat128Frac1( a );
 
7733
    aSig0 := extractFloat128Frac0( a );
 
7734
    aExp := extractFloat128Exp( a );
 
7735
    aSign := extractFloat128Sign( a );
 
7736
    if ( aExp = $7FFF ) begin
 
7737
        if ( aSig0 or aSig1 ) result := propagateFloat128NaN( a, a );
 
7738
        if ( ! aSign ) result := a;
 
7739
        goto invalid;
 
7740
    end;
 
7741
    if ( aSign ) begin
 
7742
        if ( ( aExp or aSig0 or aSig1 ) = 0 ) result := a;
 
7743
 invalid:
 
7744
        float_raise( float_flag_invalid );
 
7745
        z.low := float128_default_nan_low;
 
7746
        z.high := float128_default_nan_high;
 
7747
        result := z;
 
7748
    end;
 
7749
    if ( aExp = 0 ) begin
 
7750
        if ( ( aSig0 or aSig1 ) = 0 ) result := packFloat128( 0, 0, 0, 0 );
 
7751
        normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
 
7752
    end;
 
7753
    zExp := ( ( aExp - $3FFF )>>1 ) + $3FFE;
 
7754
    aSig0 := aSig0 or int64( $0001000000000000 );
 
7755
    zSig0 := estimateSqrt32( aExp, aSig0>>17 );
 
7756
    shortShift128Left( aSig0, aSig1, 13 - ( aExp and 1 ), &aSig0, &aSig1 );
 
7757
    zSig0 := estimateDiv128To64( aSig0, aSig1, zSig0 shl 32 ) + ( zSig0 shl 30 );
 
7758
    doubleZSig0 := zSig0 shl 1;
 
7759
    mul64To128( zSig0, zSig0, &term0, &term1 );
 
7760
    sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
 
7761
    while ( (sbits64) rem0 < 0 ) begin
 
7762
        --zSig0;
 
7763
        doubleZSig0 -= 2;
 
7764
        add128( rem0, rem1, zSig0>>63, doubleZSig0 or 1, &rem0, &rem1 );
 
7765
    end;
 
7766
    zSig1 := estimateDiv128To64( rem1, 0, doubleZSig0 );
 
7767
    if ( ( zSig1 and $1FFF ) <= 5 ) begin
 
7768
        if ( zSig1 = 0 ) zSig1 := 1;
 
7769
        mul64To128( doubleZSig0, zSig1, &term1, &term2 );
 
7770
        sub128( rem1, 0, term1, term2, &rem1, &rem2 );
 
7771
        mul64To128( zSig1, zSig1, &term2, &term3 );
 
7772
        sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
 
7773
        while ( (sbits64) rem1 < 0 ) begin
 
7774
            --zSig1;
 
7775
            shortShift128Left( 0, zSig1, 1, &term2, &term3 );
 
7776
            term3 or= 1;
 
7777
            term2 or= doubleZSig0;
 
7778
            add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
 
7779
        end;
 
7780
        zSig1 or= ( ( rem1 or rem2 or rem3 ) <> 0 );
 
7781
    end;
 
7782
    shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 );
 
7783
    result := roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 );
 
7784
 
 
7785
end;
 
7786
 
 
7787
{*----------------------------------------------------------------------------
 
7788
| Returns 1 if the quadruple-precision floating-point value `a' is equal to
 
7789
| the corresponding value `b', and 0 otherwise.  The comparison is performed
 
7790
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
7791
*----------------------------------------------------------------------------*}
 
7792
 
 
7793
function float128_eq(a: float128; b: float128): flag;
 
7794
begin
 
7795
    if (    (    ( extractFloat128Exp( a ) = $7FFF )
 
7796
              and ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ) ) )
 
7797
         or (    ( extractFloat128Exp( b ) = $7FFF )
 
7798
              and ( extractFloat128Frac0( b ) or extractFloat128Frac1( b ) ) )
 
7799
       ) begin
 
7800
        if (    float128_is_signaling_nan( a )
 
7801
             or float128_is_signaling_nan( b ) ) begin
 
7802
            float_raise( float_flag_invalid );
 
7803
        end;
 
7804
        result := 0;
 
7805
    end;
 
7806
    result :=
 
7807
           ( a.low = b.low )
 
7808
        and (    ( a.high = b.high )
 
7809
             or (    ( a.low = 0 )
 
7810
                  and ( (bits64) ( ( a.high or b.high ) shl 1 ) = 0 ) )
 
7811
           );
 
7812
 
 
7813
end;
 
7814
 
 
7815
{*----------------------------------------------------------------------------
 
7816
| Returns 1 if the quadruple-precision floating-point value `a' is less than
 
7817
| or equal to the corresponding value `b', and 0 otherwise.  The comparison
 
7818
| is performed according to the IEC/IEEE Standard for Binary Floating-Point
 
7819
| Arithmetic.
 
7820
*----------------------------------------------------------------------------*}
 
7821
 
 
7822
function float128_le(a: float128; b: float128): flag;
 
7823
var
 
7824
    aSign, bSign: flag;
 
7825
begin
 
7826
    if (    (    ( extractFloat128Exp( a ) = $7FFF )
 
7827
              and ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ) ) )
 
7828
         or (    ( extractFloat128Exp( b ) = $7FFF )
 
7829
              and ( extractFloat128Frac0( b ) or extractFloat128Frac1( b ) ) )
 
7830
       ) begin
 
7831
        float_raise( float_flag_invalid );
 
7832
        result := 0;
 
7833
    end;
 
7834
    aSign := extractFloat128Sign( a );
 
7835
    bSign := extractFloat128Sign( b );
 
7836
    if ( aSign <> bSign ) begin
 
7837
        result :=
 
7838
               aSign
 
7839
            or (    ( ( (bits64) ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
 
7840
                 = 0 );
 
7841
    end;
 
7842
    result :=
 
7843
          aSign ? le128( b.high, b.low, a.high, a.low )
 
7844
        : le128( a.high, a.low, b.high, b.low );
 
7845
 
 
7846
end;
 
7847
 
 
7848
{*----------------------------------------------------------------------------
 
7849
| Returns 1 if the quadruple-precision floating-point value `a' is less than
 
7850
| the corresponding value `b', and 0 otherwise.  The comparison is performed
 
7851
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
7852
*----------------------------------------------------------------------------*}
 
7853
 
 
7854
function float128_lt(a: float128; b: float128): flag;
 
7855
var
 
7856
    aSign, bSign: flag;
 
7857
begin
 
7858
    if (    (    ( extractFloat128Exp( a ) = $7FFF )
 
7859
              and ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ) ) )
 
7860
         or (    ( extractFloat128Exp( b ) = $7FFF )
 
7861
              and ( extractFloat128Frac0( b ) or extractFloat128Frac1( b ) ) )
 
7862
       ) begin
 
7863
        float_raise( float_flag_invalid );
 
7864
        result := 0;
 
7865
    end;
 
7866
    aSign := extractFloat128Sign( a );
 
7867
    bSign := extractFloat128Sign( b );
 
7868
    if ( aSign <> bSign ) begin
 
7869
        result :=
 
7870
               aSign
 
7871
            and (    ( ( (bits64) ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
 
7872
                 <> 0 );
 
7873
    end;
 
7874
    result :=
 
7875
          aSign ? lt128( b.high, b.low, a.high, a.low )
 
7876
        : lt128( a.high, a.low, b.high, b.low );
 
7877
 
 
7878
end;
 
7879
 
 
7880
{*----------------------------------------------------------------------------
 
7881
| Returns 1 if the quadruple-precision floating-point value `a' is equal to
 
7882
| the corresponding value `b', and 0 otherwise.  The invalid exception is
 
7883
| raised if either operand is a NaN.  Otherwise, the comparison is performed
 
7884
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
7885
*----------------------------------------------------------------------------*}
 
7886
 
 
7887
function float128_eq_signaling(a: float128; b: float128): flag;
 
7888
begin
 
7889
    if (    (    ( extractFloat128Exp( a ) = $7FFF )
 
7890
              and ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ) ) )
 
7891
         or (    ( extractFloat128Exp( b ) = $7FFF )
 
7892
              and ( extractFloat128Frac0( b ) or extractFloat128Frac1( b ) ) )
 
7893
       ) begin
 
7894
        float_raise( float_flag_invalid );
 
7895
        result := 0;
 
7896
    end;
 
7897
    result :=
 
7898
           ( a.low = b.low )
 
7899
        and (    ( a.high = b.high )
 
7900
             or (    ( a.low = 0 )
 
7901
                  and ( (bits64) ( ( a.high or b.high ) shl 1 ) = 0 ) )
 
7902
           );
 
7903
 
 
7904
end;
 
7905
 
 
7906
{*----------------------------------------------------------------------------
 
7907
| Returns 1 if the quadruple-precision floating-point value `a' is less than
 
7908
| or equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not
 
7909
| cause an exception.  Otherwise, the comparison is performed according to the
 
7910
| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 
7911
*----------------------------------------------------------------------------*}
 
7912
 
 
7913
function float128_le_quiet(a: float128; b: float128): flag;
 
7914
var
 
7915
    aSign, bSign: flag;
 
7916
begin
 
7917
    if (    (    ( extractFloat128Exp( a ) = $7FFF )
 
7918
              and ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ) ) )
 
7919
         or (    ( extractFloat128Exp( b ) = $7FFF )
 
7920
              and ( extractFloat128Frac0( b ) or extractFloat128Frac1( b ) ) )
 
7921
       ) begin
 
7922
        if (    float128_is_signaling_nan( a )
 
7923
             or float128_is_signaling_nan( b ) ) begin
 
7924
            float_raise( float_flag_invalid );
 
7925
        end;
 
7926
        result := 0;
 
7927
    end;
 
7928
    aSign := extractFloat128Sign( a );
 
7929
    bSign := extractFloat128Sign( b );
 
7930
    if ( aSign <> bSign ) begin
 
7931
        result :=
 
7932
               aSign
 
7933
            or (    ( ( (bits64) ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
 
7934
                 = 0 );
 
7935
    end;
 
7936
    result :=
 
7937
          aSign ? le128( b.high, b.low, a.high, a.low )
 
7938
        : le128( a.high, a.low, b.high, b.low );
 
7939
 
 
7940
end;
 
7941
 
 
7942
{*----------------------------------------------------------------------------
 
7943
| Returns 1 if the quadruple-precision floating-point value `a' is less than
 
7944
| the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
 
7945
| exception.  Otherwise, the comparison is performed according to the IEC/IEEE
 
7946
| Standard for Binary Floating-Point Arithmetic.
 
7947
*----------------------------------------------------------------------------*}
 
7948
 
 
7949
function float128_lt_quiet(a: float128; b: float128): flag;
 
7950
var
 
7951
    aSign, bSign: flag;
 
7952
begin
 
7953
    if (    (    ( extractFloat128Exp( a ) = $7FFF )
 
7954
              and ( extractFloat128Frac0( a ) or extractFloat128Frac1( a ) ) )
 
7955
         or (    ( extractFloat128Exp( b ) = $7FFF )
 
7956
              and ( extractFloat128Frac0( b ) or extractFloat128Frac1( b ) ) )
 
7957
       ) begin
 
7958
        if (    float128_is_signaling_nan( a )
 
7959
             or float128_is_signaling_nan( b ) ) begin
 
7960
            float_raise( float_flag_invalid );
 
7961
        end;
 
7962
        result := 0;
 
7963
    end;
 
7964
    aSign := extractFloat128Sign( a );
 
7965
    bSign := extractFloat128Sign( b );
 
7966
    if ( aSign <> bSign ) begin
 
7967
        result :=
 
7968
               aSign
 
7969
            and (    ( ( (bits64) ( ( a.high or b.high ) shl 1 ) ) or a.low or b.low )
 
7970
                 <> 0 );
 
7971
    end;
 
7972
    result :=
 
7973
          aSign ? lt128( b.high, b.low, a.high, a.low )
 
7974
        : lt128( a.high, a.low, b.high, b.low );
 
7975
 
 
7976
end;
 
7977
 
 
7978
{$endif FPC_SOFTFLOAT_FLOAT128}
 
7979
 
 
7980
{$endif not(defined(fpc_softfpu_interface))}
 
7981
 
 
7982
{$if not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}
 
7983
 
 
7984
end.
 
7985
 
 
7986
{$endif not(defined(fpc_softfpu_interface)) and not(defined(fpc_softfpu_implementation))}