mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-06 21:07:58 +02: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}
|
||||
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
|
||||
pushl %edi
|
||||
movzwl %dx,%edi
|
||||
cltd
|
||||
idiv %edi
|
||||
movw %ax,(%ecx)
|
||||
movl Remainder,%ecx
|
||||
movw %dx,(%ecx)
|
||||
popl %edi
|
||||
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
|
||||
pushl %edi
|
||||
movzwl %dx,%edi
|
||||
cltd
|
||||
idiv %edi
|
||||
movw %ax,(%ecx)
|
||||
movl Remainder,%ecx
|
||||
movw %dx,(%ecx)
|
||||
popl %edi
|
||||
end;
|
||||
|
||||
|
||||
@ -92,7 +90,7 @@ asm
|
||||
pushl %edi
|
||||
movl %edx,%edi
|
||||
xorl %edx,%edx
|
||||
div %edi
|
||||
div %edi
|
||||
movl %eax,(%ecx)
|
||||
movl Remainder,%ecx
|
||||
movl %edx,(%ecx)
|
||||
@ -104,7 +102,7 @@ procedure DivMod(Dividend: Integer; Divisor: Integer; var Result, Remainder: Int
|
||||
asm
|
||||
pushl %edi
|
||||
movl %edx,%edi
|
||||
xorl %edx,%edx
|
||||
cltd
|
||||
idiv %edi
|
||||
movl %eax,(%ecx)
|
||||
movl Remainder,%ecx
|
||||
@ -112,6 +110,7 @@ asm
|
||||
popl %edi
|
||||
end;
|
||||
|
||||
|
||||
function GetRoundMode: TFPURoundingMode;
|
||||
begin
|
||||
Result := TFPURoundingMode((Get8087CW shr 10) and 3);
|
||||
|
@ -2221,33 +2221,71 @@ end;
|
||||
{$ifndef FPC_MATH_HAS_DIVMOD}
|
||||
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);
|
||||
begin
|
||||
Result:=Dividend Div Divisor;
|
||||
Remainder:=Dividend -(Result*Divisor);
|
||||
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;
|
||||
|
||||
|
||||
procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: SmallInt);
|
||||
var
|
||||
UnsignedResult: Word absolute Result;
|
||||
UnsignedRemainder: Word absolute Remainder;
|
||||
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;
|
||||
|
||||
|
||||
procedure DivMod(Dividend: DWord; Divisor: DWord; var Result, Remainder: DWord);
|
||||
begin
|
||||
Result:=Dividend Div Divisor;
|
||||
Remainder:=Dividend -(Result*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);
|
||||
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;
|
||||
{$endif FPC_MATH_HAS_DIVMOD}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
{$mode objfpc}
|
||||
uses
|
||||
math;
|
||||
{ tests:
|
||||
@ -55,5 +56,18 @@ begin
|
||||
doerror(3003);
|
||||
if RemainderInteger<>15 then
|
||||
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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user