mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 10:19:30 +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;
|
||||
begin
|
||||
Result := softfloat_exception_mask;
|
||||
@ -48,4 +161,4 @@ procedure ClearExceptions(RaisePending: Boolean);
|
||||
begin
|
||||
softfloat_exception_flags:=[];
|
||||
end;
|
||||
|
||||
{$endif}
|
||||
|
Loading…
Reference in New Issue
Block a user