mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-24 14:09:17 +02:00
m68k: added support for setting the rounding mode on hardware FPUs
git-svn-id: trunk@36523 -
This commit is contained in:
parent
8a6c995b75
commit
f1ee65610d
@ -12,6 +12,119 @@
|
|||||||
|
|
||||||
**********************************************************************}
|
**********************************************************************}
|
||||||
|
|
||||||
|
{$if defined(FPU68881) or defined(FPUCOLDFIRE)}
|
||||||
|
|
||||||
|
{ 68881/2 FPCR Encodings
|
||||||
|
Rounding Mode Rounding Precision
|
||||||
|
(RND Field) Encoding (PREC Field)
|
||||||
|
To Nearest (RN) 0 0 Extend (X)
|
||||||
|
To Zero (RZ) 0 1 Single (S)
|
||||||
|
To Minus Infinity (RM) 1 0 Double (D)
|
||||||
|
To Plus Infinity (RP) 1 1 Undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
{ 68881/2 FPCR layout }
|
||||||
|
{ Exception Enable Byte: }
|
||||||
|
{ 15 - BSUN - Branch/Set on Unordered }
|
||||||
|
{ 14 - SNAN - Signal Not A Number }
|
||||||
|
{ 13 - OPERR - Operand Error }
|
||||||
|
{ 12 - OVFL - Overflow }
|
||||||
|
{ 11 - UNFL - Underflow }
|
||||||
|
{ 10 - DZ - Divide by Zero }
|
||||||
|
{ 09 - INEX2 - Inexact Operation }
|
||||||
|
{ 08 - INEX1 - Inexact Decimal Input }
|
||||||
|
{ Mode Control Byte: }
|
||||||
|
{ 07 - PREC - Rounding Precision }
|
||||||
|
{ 06 - PREC - Rounding Precision }
|
||||||
|
{ 05 - RND - Rounding Mode }
|
||||||
|
{ 04 - RND - Rounding Mode }
|
||||||
|
{ 03 - 0 - Reserved, Set to zero }
|
||||||
|
{ 02 - 0 - Reserved, Set to zero }
|
||||||
|
{ 01 - 0 - Reserved, Set to zero }
|
||||||
|
{ 00 - 0 - Reserved, Set to zero }
|
||||||
|
|
||||||
|
{
|
||||||
|
Please note that the rounding mode setting via FPCR in most emulators is broken.
|
||||||
|
The list includes most versions and incarnations of UAE, MorphOS' Trance emulator,
|
||||||
|
and others. The following code was verified to work on real hardware. (KB)
|
||||||
|
}
|
||||||
|
|
||||||
|
const
|
||||||
|
FPU68K_ROUND_MASK_SHIFT = 4;
|
||||||
|
FPU68K_ROUND_MASK = 3 shl FPU68K_ROUND_MASK_SHIFT;
|
||||||
|
|
||||||
|
FPU68K_ROUND_NEAREST = 0 shl FPU68K_ROUND_MASK_SHIFT;
|
||||||
|
FPU68K_ROUND_ZERO = 1 shl FPU68K_ROUND_MASK_SHIFT;
|
||||||
|
FPU68K_ROUND_MINUSINF = 2 shl FPU68K_ROUND_MASK_SHIFT;
|
||||||
|
FPU68K_ROUND_PLUSINF = 3 shl FPU68K_ROUND_MASK_SHIFT;
|
||||||
|
|
||||||
|
const
|
||||||
|
FPU68K_PREC_MASK_SHIFT = 6;
|
||||||
|
FPU68K_PREC_MASK = 3 shl FPU68K_PREC_MASK_SHIFT;
|
||||||
|
|
||||||
|
FPU68K_PREC_EXTENDED = 0 shl FPU68K_PREC_MASK_SHIFT;
|
||||||
|
FPU68K_PREC_SINGLE = 1 shl FPU68K_PREC_MASK_SHIFT;
|
||||||
|
FPU68K_PREC_DOUBLE = 2 shl FPU68K_PREC_MASK_SHIFT;
|
||||||
|
|
||||||
|
|
||||||
|
function GetFPCR: DWord; assembler; nostackframe;
|
||||||
|
asm
|
||||||
|
fmove.l fpcr,d0
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SetFPCR(x: DWord): DWord; assembler; nostackframe;
|
||||||
|
asm
|
||||||
|
fmove.l x, fpcr
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetExceptionMask: TFPUExceptionMask;
|
||||||
|
begin
|
||||||
|
Result := softfloat_exception_mask;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
|
||||||
|
begin
|
||||||
|
result:=softfloat_exception_mask;
|
||||||
|
softfloat_exception_mask:=mask;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetRoundMode: TFPURoundingMode;
|
||||||
|
const
|
||||||
|
FPUToFPCRoundingMode: array[0..3] of TFPURoundingMode = ( rmNearest, rmTruncate, rmUp, rmDown );
|
||||||
|
begin
|
||||||
|
Result:=FPUToFPCRoundingMode[(GetFPCR and FPU68K_ROUND_MASK) shr FPU68K_ROUND_MASK_SHIFT];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
|
||||||
|
const
|
||||||
|
FPCToFPURoundingMode: array[TFPURoundingMode] of DWord =
|
||||||
|
( FPU68K_ROUND_NEAREST, FPU68K_ROUND_MINUSINF, FPU68K_ROUND_PLUSINF, FPU68K_ROUND_ZERO );
|
||||||
|
var
|
||||||
|
FPCR: DWord;
|
||||||
|
begin
|
||||||
|
FPCR:=GetFPCR and not FPU68K_ROUND_MASK;
|
||||||
|
SetFPCR(FPCR or FPCToFPURoundingMode[RoundMode]);
|
||||||
|
softfloat_rounding_mode:=RoundMode;
|
||||||
|
Result:=RoundMode;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetPrecisionMode: TFPUPrecisionMode;
|
||||||
|
begin
|
||||||
|
result:=pmDouble;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
|
||||||
|
begin
|
||||||
|
result:=pmDouble;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ClearExceptions(RaisePending: Boolean);
|
||||||
|
begin
|
||||||
|
softfloat_exception_flags:=[];
|
||||||
|
end;
|
||||||
|
|
||||||
|
{$else}
|
||||||
|
|
||||||
function GetExceptionMask: TFPUExceptionMask;
|
function GetExceptionMask: TFPUExceptionMask;
|
||||||
begin
|
begin
|
||||||
Result := softfloat_exception_mask;
|
Result := softfloat_exception_mask;
|
||||||
@ -48,4 +161,4 @@ procedure ClearExceptions(RaisePending: Boolean);
|
|||||||
begin
|
begin
|
||||||
softfloat_exception_flags:=[];
|
softfloat_exception_flags:=[];
|
||||||
end;
|
end;
|
||||||
|
{$endif}
|
||||||
|
Loading…
Reference in New Issue
Block a user