2
This file is part of the Free Pascal run time library.
3
Copyright (c) 2004 by Florian Klaempfl
4
member of the Free Pascal development team
6
See the file COPYING.FPC, included in this distribution,
7
for details about the copyright.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
**********************************************************************}
19
_DN_FLUSH = $01000000;
21
_EM_INVALID = $00000010;
22
_EM_DENORMAL = $00080000;
23
_EM_ZERODIVIDE = $00000008;
24
_EM_OVERFLOW = $00000004;
25
_EM_UNDERFLOW = $00000002;
26
_EM_INEXACT = $00000001;
28
_IC_AFFINE = $00040000;
29
_IC_PROJECTIVE = $00000000;
46
function _controlfp(new: DWORD; mask: DWORD): DWORD; cdecl; external 'coredll';
48
function GetRoundMode: TFPURoundingMode;
53
Result:=TFPURoundingMode((c shr 16) and 3);
56
function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
60
c:=Ord(RoundMode) shl 16;
61
c:=_controlfp(c, _MCW_RC);
62
Result:=TFPURoundingMode((c shr 16) and 3);
65
function GetPrecisionMode: TFPUPrecisionMode;
70
if c and _MCW_PC = _PC_64 then
76
function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
80
Result:=GetPrecisionMode;
81
if Precision = pmSingle then
85
_controlfp(c, _MCW_PC);
88
function ConvertExceptionMask(em: dword): TFPUExceptionMask;
91
if em and _EM_INVALID <> 0 then
92
Result:=Result + [exInvalidOp];
93
if em and _EM_DENORMAL <> 0 then
94
Result:=Result + [exDenormalized];
95
if em and _EM_ZERODIVIDE <> 0 then
96
Result:=Result + [exZeroDivide];
97
if em and _EM_OVERFLOW <> 0 then
98
Result:=Result + [exOverflow];
99
if em and _EM_UNDERFLOW <> 0 then
100
Result:=Result + [exUnderflow];
101
if em and _EM_INEXACT <> 0 then
102
Result:=Result + [exPrecision];
105
function GetExceptionMask: TFPUExceptionMask;
107
Result:=ConvertExceptionMask(_controlfp(0, 0));
110
function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
115
if exInvalidOp in Mask then
117
if exDenormalized in Mask then
118
c:=c or _EM_DENORMAL;
119
if exZeroDivide in Mask then
120
c:=c or _EM_ZERODIVIDE;
121
if exOverflow in Mask then
122
c:=c or _EM_OVERFLOW;
123
if exUnderflow in Mask then
124
c:=c or _EM_UNDERFLOW;
125
if exPrecision in Mask then
127
c:=_controlfp(c, _MCW_EM);
128
Result:=ConvertExceptionMask(c);
129
softfloat_exception_mask:=dword(Mask);
132
procedure ClearExceptions(RaisePending: Boolean =true);
138
{*****************************************************************************
140
*****************************************************************************}
144
* We have a slight terminology confusion here. On the ARM, the register
145
* we're interested in is actually the FPU status word - the FPU control
146
* word is something different (which is implementation-defined and only
147
* accessible from supervisor mode.)
149
* The FPSR looks like this:
151
* 31-24 23-16 15-8 7-0
152
* | system ID | trap enable | system control | exception flags |
154
* We ignore the system ID bits; for interest's sake they are:
161
* The trap enable and exception flags are both structured like this:
164
* | reserved | INX | UFL | OFL | DVZ | IVO |
166
* where a `1' bit in the enable byte means that the trap can occur, and
167
* a `1' bit in the flags byte means the exception has occurred.
169
* The exceptions are:
171
* IVO - invalid operation
172
* DVZ - divide by zero
175
* INX - inexact (do not use; implementations differ)
177
* The system control byte looks like this:
180
* | reserved | AC | EP | SO | NE | ND |
182
* where the bits mean
184
* ND - no denormalised numbers (force them all to zero)
185
* NE - enable NaN exceptions
186
* SO - synchronous operation
187
* EP - use expanded packed-decimal format
188
* AC - use alternate definition for C flag on compare operations
191
/* masking of interrupts */
192
#define _FPU_MASK_IM 0x00010000 /* invalid operation */
193
#define _FPU_MASK_ZM 0x00020000 /* divide by zero */
194
#define _FPU_MASK_OM 0x00040000 /* overflow */
195
#define _FPU_MASK_UM 0x00080000 /* underflow */
196
#define _FPU_MASK_PM 0x00100000 /* inexact */
197
#define _FPU_MASK_DM 0x00000000 /* denormalized operation */
199
/* The system id bytes cannot be changed.
200
Only the bottom 5 bits in the trap enable byte can be changed.
201
Only the bottom 5 bits in the system control byte can be changed.
202
Only the bottom 5 bits in the exception flags are used.
203
The exception flags are set by the fpu, but can be zeroed by the user. */
204
#define _FPU_RESERVED 0xffe0e0e0 /* These bits are reserved. */
206
/* The fdlibm code requires strict IEEE double precision arithmetic,
207
no interrupts for exceptions, rounding to nearest. Changing the
208
rounding mode will break long double I/O. Turn on the AC bit,
209
the compiler generates code that assumes it is on. */
210
#define _FPU_DEFAULT 0x00001000 /* Default value. */
211
#define _FPU_IEEE 0x001f1000 /* Default + exceptions enabled. */
215
{$if not(defined(gba)) and not(defined(nds)) and not(defined(FPUSOFT)) and not(defined(FPULIBGCC))}
217
_FPU_MASK_IM = $00010000; { invalid operation }
218
_FPU_MASK_ZM = $00020000; { divide by zero }
219
_FPU_MASK_OM = $00040000; { overflow }
220
_FPU_MASK_UM = $00080000; { underflow }
221
_FPU_MASK_PM = $00100000; { inexact }
222
_FPU_MASK_DM = $00000000; { denormalized operation }
223
_FPU_MASK_ALL = $001f0000; { mask for all flags }
225
function FPU_GetCW : dword; nostackframe; assembler;
231
procedure FPU_SetCW(cw : dword); nostackframe; assembler;
238
function GetRoundMode: TFPURoundingMode;
244
function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
250
function GetPrecisionMode: TFPUPrecisionMode;
256
function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
262
function GetExceptionMask: TFPUExceptionMask;
266
{$if not(defined(gba)) and not(defined(nds)) and not(defined(FPUSOFT)) and not(defined(FPULIBGCC))}
270
if (cw and _FPU_MASK_IM)=0 then
271
include(Result,exInvalidOp);
273
if (cw and _FPU_MASK_DM)=0 then
274
include(Result,exDenormalized);
276
if (cw and _FPU_MASK_ZM)=0 then
277
include(Result,exZeroDivide);
279
if (cw and _FPU_MASK_OM)=0 then
280
include(Result,exOverflow);
282
if (cw and _FPU_MASK_UM)=0 then
283
include(Result,exUnderflow);
285
if (cw and _FPU_MASK_PM)=0 then
286
include(Result,exPrecision);
288
dword(Result):=softfloat_exception_mask;
293
function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
297
{$if not(defined(gba)) and not(defined(nds)) and not(defined(FPUSOFT)) and not(defined(FPULIBGCC))}
298
cw:=FPU_GetCW or _FPU_MASK_ALL;
300
if exInvalidOp in Mask then
301
cw:=cw and not(_FPU_MASK_IM);
303
if exDenormalized in Mask then
304
cw:=cw and not(_FPU_MASK_DM);
306
if exZeroDivide in Mask then
307
cw:=cw and not(_FPU_MASK_ZM);
309
if exOverflow in Mask then
310
cw:=cw and not(_FPU_MASK_OM);
312
if exUnderflow in Mask then
313
cw:=cw and not(_FPU_MASK_UM);
315
if exPrecision in Mask then
316
cw:=cw and not(_FPU_MASK_PM);
320
softfloat_exception_mask:=dword(Mask);
324
procedure ClearExceptions(RaisePending: Boolean =true);