mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-28 08:27:24 +01:00
resolves #15453:
* fixes i386 DivMod with negative numbers with a patch from Jonas * fixes generic DivMod with negative numbers * test updated git-svn-id: trunk@14532 -
This commit is contained in:
parent
a8a332e029
commit
31e2f16484
@ -61,29 +61,27 @@ function cotan(x : float) : float;assembler;
|
|||||||
{$define FPC_MATH_HAS_DIVMOD}
|
{$define FPC_MATH_HAS_DIVMOD}
|
||||||
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);assembler;
|
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);assembler;
|
||||||
asm
|
asm
|
||||||
pushw %di
|
pushl %edi
|
||||||
movw %dx,%di
|
movzwl %dx,%edi
|
||||||
movl %eax,%edx
|
cltd
|
||||||
shrl $16,%edx
|
idiv %edi
|
||||||
div %di
|
|
||||||
movw %ax,(%ecx)
|
movw %ax,(%ecx)
|
||||||
movl Remainder,%ecx
|
movl Remainder,%ecx
|
||||||
movw %dx,(%ecx)
|
movw %dx,(%ecx)
|
||||||
popw %di
|
popl %edi
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: SmallInt);assembler;
|
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: SmallInt);assembler;
|
||||||
asm
|
asm
|
||||||
pushw %di
|
pushl %edi
|
||||||
movw %dx,%di
|
movzwl %dx,%edi
|
||||||
movl %eax,%edx
|
cltd
|
||||||
shrl $16,%edx
|
idiv %edi
|
||||||
div %di
|
|
||||||
movw %ax,(%ecx)
|
movw %ax,(%ecx)
|
||||||
movl Remainder,%ecx
|
movl Remainder,%ecx
|
||||||
movw %dx,(%ecx)
|
movw %dx,(%ecx)
|
||||||
popw %di
|
popl %edi
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -104,7 +102,7 @@ procedure DivMod(Dividend: Integer; Divisor: Integer; var Result, Remainder: Int
|
|||||||
asm
|
asm
|
||||||
pushl %edi
|
pushl %edi
|
||||||
movl %edx,%edi
|
movl %edx,%edi
|
||||||
xorl %edx,%edx
|
cltd
|
||||||
idiv %edi
|
idiv %edi
|
||||||
movl %eax,(%ecx)
|
movl %eax,(%ecx)
|
||||||
movl Remainder,%ecx
|
movl Remainder,%ecx
|
||||||
@ -112,6 +110,7 @@ asm
|
|||||||
popl %edi
|
popl %edi
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function GetRoundMode: TFPURoundingMode;
|
function GetRoundMode: TFPURoundingMode;
|
||||||
begin
|
begin
|
||||||
Result := TFPURoundingMode((Get8087CW shr 10) and 3);
|
Result := TFPURoundingMode((Get8087CW shr 10) and 3);
|
||||||
|
|||||||
@ -2221,33 +2221,71 @@ end;
|
|||||||
{$ifndef FPC_MATH_HAS_DIVMOD}
|
{$ifndef FPC_MATH_HAS_DIVMOD}
|
||||||
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);
|
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);
|
||||||
begin
|
begin
|
||||||
|
if Dividend < 0 then
|
||||||
|
begin
|
||||||
|
{ Use DivMod with >=0 dividend }
|
||||||
|
Dividend:=-Dividend;
|
||||||
|
{ The documented behavior of Pascal's div/mod operators and DivMod
|
||||||
|
on negative dividends is to return Result closer to zero and
|
||||||
|
a negative Remainder. Which means that we can just negate both
|
||||||
|
Result and Remainder, and all it's Ok. }
|
||||||
|
Result:=-(Dividend Div Divisor);
|
||||||
|
Remainder:=-(Dividend+(Result*Divisor));
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
Result:=Dividend Div Divisor;
|
Result:=Dividend Div Divisor;
|
||||||
Remainder:=Dividend -(Result*Divisor);
|
Remainder:=Dividend-(Result*Divisor);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: SmallInt);
|
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: SmallInt);
|
||||||
var
|
|
||||||
UnsignedResult: Word absolute Result;
|
|
||||||
UnsignedRemainder: Word absolute Remainder;
|
|
||||||
begin
|
begin
|
||||||
DivMod(Dividend, Divisor, UnsignedResult, UnsignedRemainder);
|
if Dividend < 0 then
|
||||||
|
begin
|
||||||
|
{ Use DivMod with >=0 dividend }
|
||||||
|
Dividend:=-Dividend;
|
||||||
|
{ The documented behavior of Pascal's div/mod operators and DivMod
|
||||||
|
on negative dividends is to return Result closer to zero and
|
||||||
|
a negative Remainder. Which means that we can just negate both
|
||||||
|
Result and Remainder, and all it's Ok. }
|
||||||
|
Result:=-(Dividend Div Divisor);
|
||||||
|
Remainder:=-(Dividend+(Result*Divisor));
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Result:=Dividend Div Divisor;
|
||||||
|
Remainder:=Dividend-(Result*Divisor);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure DivMod(Dividend: DWord; Divisor: DWord; var Result, Remainder: DWord);
|
procedure DivMod(Dividend: DWord; Divisor: DWord; var Result, Remainder: DWord);
|
||||||
begin
|
begin
|
||||||
Result:=Dividend Div Divisor;
|
Result:=Dividend Div Divisor;
|
||||||
Remainder:=Dividend -(Result*Divisor);
|
Remainder:=Dividend-(Result*Divisor);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure DivMod(Dividend: Integer; Divisor: Integer; var Result, Remainder: Integer);
|
procedure DivMod(Dividend: Integer; Divisor: Integer; var Result, Remainder: Integer);
|
||||||
var
|
|
||||||
UnsignedResult: DWord absolute Result;
|
|
||||||
UnsignedRemainder: DWord absolute Remainder;
|
|
||||||
begin
|
begin
|
||||||
DivMod(Dividend, Divisor, UnsignedResult, UnsignedRemainder);
|
if Dividend < 0 then
|
||||||
|
begin
|
||||||
|
{ Use DivMod with >=0 dividend }
|
||||||
|
Dividend:=-Dividend;
|
||||||
|
{ The documented behavior of Pascal's div/mod operators and DivMod
|
||||||
|
on negative dividends is to return Result closer to zero and
|
||||||
|
a negative Remainder. Which means that we can just negate both
|
||||||
|
Result and Remainder, and all it's Ok. }
|
||||||
|
Result:=-(Dividend Div Divisor);
|
||||||
|
Remainder:=-(Dividend+(Result*Divisor));
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Result:=Dividend Div Divisor;
|
||||||
|
Remainder:=Dividend-(Result*Divisor);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
{$endif FPC_MATH_HAS_DIVMOD}
|
{$endif FPC_MATH_HAS_DIVMOD}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
{$mode objfpc}
|
||||||
uses
|
uses
|
||||||
math;
|
math;
|
||||||
{ tests:
|
{ tests:
|
||||||
@ -55,5 +56,18 @@ begin
|
|||||||
doerror(3003);
|
doerror(3003);
|
||||||
if RemainderInteger<>15 then
|
if RemainderInteger<>15 then
|
||||||
doerror(3004);
|
doerror(3004);
|
||||||
|
|
||||||
|
DivMod(-9, 5, QuotientInteger,RemainderInteger);
|
||||||
|
if QuotientInteger<>-1 then
|
||||||
|
doerror(3005);
|
||||||
|
if RemainderInteger<>-4 then
|
||||||
|
doerror(3006);
|
||||||
|
|
||||||
|
DivMod(-9, -5, QuotientInteger,RemainderInteger);
|
||||||
|
if QuotientInteger<>1 then
|
||||||
|
doerror(3007);
|
||||||
|
if RemainderInteger<>-4 then
|
||||||
|
doerror(3008);
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user