+ procedure DivMod(Dividend: Integer; Divisor: integer; var Result, Remainder: integer); and procedure DivMod(Dividend: cardinal; Divisor: cardinal; var Result, Remainder: cardinal);, resolves #14286

+ assembler implementations of DivMod for i386

git-svn-id: trunk@13508 -
This commit is contained in:
florian 2009-08-09 20:47:06 +00:00
parent c97a407633
commit a14db25c64
4 changed files with 140 additions and 9 deletions

1
.gitattributes vendored
View File

@ -8445,6 +8445,7 @@ tests/test/units/fpcunit/testclasses.lpr svneol=native#text/plain
tests/test/units/fpcunit/testcomps.pp svneol=native#text/plain
tests/test/units/fpcunit/tstrutils.lpi svneol=native#text/plain
tests/test/units/fpcunit/tstrutils.lpr svneol=native#text/plain
tests/test/units/math/tdivmod.pp svneol=native#text/plain
tests/test/units/math/tmask.inc svneol=native#text/plain
tests/test/units/math/tmask.pp svneol=native#text/plain
tests/test/units/math/tmask2.pp svneol=native#text/plain

View File

@ -58,11 +58,66 @@ function cotan(x : float) : float;assembler;
end;
{$define FPC_MATH_HAS_DIVMOD}
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);assembler;
asm
pushw %di
movw %dx,%di
movl %eax,%edx
shrl $16,%edx
div %di
movw %ax,(%ecx)
movl Remainder,%ecx
movw %dx,(%ecx)
popw %di
end;
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: SmallInt);assembler;
asm
pushw %di
movw %dx,%di
movl %eax,%edx
shrl $16,%edx
div %di
movw %ax,(%ecx)
movl Remainder,%ecx
movw %dx,(%ecx)
popw %di
end;
procedure DivMod(Dividend: DWord; Divisor: DWord; var Result, Remainder: DWord);assembler;
asm
pushl %edi
movl %edx,%edi
xorl %edx,%edx
div %edi
movl %eax,(%ecx)
movl Remainder,%ecx
movl %edx,(%ecx)
popl %edi
end;
procedure DivMod(Dividend: Integer; Divisor: Integer; var Result, Remainder: Integer);assembler;
asm
pushl %edi
movl %edx,%edi
xorl %edx,%edx
idiv %edi
movl %eax,(%ecx)
movl Remainder,%ecx
movl %edx,(%ecx)
popl %edi
end;
function GetRoundMode: TFPURoundingMode;
begin
Result := TFPURoundingMode((Get8087CW shr 10) and 3);
end;
function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
var
CtlWord: Word;

View File

@ -171,7 +171,8 @@ function EnsureRange(const AValue, AMin, AMax: Double): Double;inline; overload
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: SmallInt);
procedure DivMod(Dividend: DWord; Divisor: DWord; var Result, Remainder: DWord);
procedure DivMod(Dividend: Integer; Divisor: Integer; var Result, Remainder: Integer);
// Sign functions
Type
@ -1380,7 +1381,7 @@ begin
m2 := reciprocalN * m2;
m3 := reciprocalN * m3;
m4 := reciprocalN * m4;
skew := m3 / (sqrt(m2)*m2);
kurtosis := m4 / (m2 * m2);
end;
@ -1548,7 +1549,7 @@ begin
m2 := reciprocalN * m2;
m3 := reciprocalN * m3;
m4 := reciprocalN * m4;
skew := m3 / (sqrt(m2)*m2);
kurtosis := m4 / (m2 * m2);
end;
@ -1717,7 +1718,7 @@ begin
m2 := reciprocalN * m2;
m3 := reciprocalN * m3;
m4 := reciprocalN * m4;
skew := m3 / (sqrt(m2)*m2);
kurtosis := m4 / (m2 * m2);
end;
@ -2216,15 +2217,13 @@ begin
end;
// Some CPUs probably allow a faster way of doing this in a single operation...
// There weshould define CPUDIVMOD in the header mathuh.inc and implement it using asm.
{$ifndef CPUDIVMOD}
// There weshould define FPC_MATH_HAS_CPUDIVMOD in the header mathuh.inc and implement it using asm.
{$ifndef FPC_MATH_HAS_DIVMOD}
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);
begin
Result:=Dividend Div Divisor;
Remainder:=Dividend Mod Divisor;
Remainder:=Dividend -(Result*Divisor);
end;
{$endif}
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: SmallInt);
@ -2236,6 +2235,23 @@ begin
end;
procedure DivMod(Dividend: DWord; Divisor: DWord; var Result, Remainder: DWord);
begin
Result:=Dividend Div Divisor;
Remainder:=Dividend -(Result*Divisor);
end;
procedure DivMod(Dividend: Integer; Divisor: Integer; var Result, Remainder: Integer);
var
UnsignedResult: DWord absolute Result;
UnsignedRemainder: DWord absolute Remainder;
begin
DivMod(Dividend, Divisor, UnsignedResult, UnsignedRemainder);
end;
{$endif FPC_MATH_HAS_DIVMOD}
function ifthen(val:boolean;const iftrue:integer; const iffalse:integer= 0) :integer;
begin
if val then result:=iftrue else result:=iffalse;

View File

@ -0,0 +1,59 @@
uses
math;
{ tests:
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: SmallInt);
procedure DivMod(Dividend: DWord; Divisor: DWord; var Result, Remainder: DWord);
procedure DivMod(Dividend: Integer; Divisor: Integer; var Result, Remainder: Integer);
}
procedure doerror(i : integer);
begin
writeln('Error: ',i);
halt(1);
end;
var
QuotientWord,RemainderWord : Word;
QuotientSmallInt,RemainderSmallInt : SmallInt;
QuotientDWord,RemainderDWord : DWord;
QuotientInteger,RemainderInteger : Integer;
begin
DivMod($ffff,65,QuotientWord,RemainderWord);
if QuotientWord<>1008 then
doerror(1);
if RemainderWord<>15 then
doerror(2);
DivMod($ffff,65,QuotientSmallInt,RemainderSmallInt);
if QuotientSmallInt<>1008 then
doerror(1001);
if RemainderSmallInt<>15 then
doerror(2);
DivMod($ffff,65,QuotientDWord,RemainderDWord);
if QuotientDWord<>1008 then
doerror(2001);
if RemainderDWord<>15 then
doerror(2002);
DivMod(123456,23,QuotientDWord,RemainderDWord);
if QuotientDWord<>5367 then
doerror(2003);
if RemainderDWord<>15 then
doerror(2004);
DivMod($ffff,65,QuotientInteger,RemainderInteger);
if QuotientInteger<>1008 then
doerror(3001);
if RemainderInteger<>15 then
doerror(3002);
DivMod(123456,23,QuotientInteger,RemainderInteger);
if QuotientInteger<>5367 then
doerror(3003);
if RemainderInteger<>15 then
doerror(3004);
end.