mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-09 14:08:05 +02:00
* fixed overflow checking on AArch64 for signed multiplications with zero
(mantis #29912) git-svn-id: trunk@33380 -
This commit is contained in:
parent
73a303c899
commit
322493c195
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -14993,6 +14993,7 @@ tests/webtbs/tw29792.pp svneol=native#text/pascal
|
||||
tests/webtbs/tw2983.pp svneol=native#text/plain
|
||||
tests/webtbs/tw2984.pp svneol=native#text/plain
|
||||
tests/webtbs/tw29893.pp svneol=native#text/pascal
|
||||
tests/webtbs/tw29912.pp svneol=native#text/plain
|
||||
tests/webtbs/tw2998.pp svneol=native#text/plain
|
||||
tests/webtbs/tw2999.pp svneol=native#text/plain
|
||||
tests/webtbs/tw3004.pp svneol=native#text/plain
|
||||
|
@ -1340,7 +1340,7 @@ implementation
|
||||
|
||||
procedure tcgaarch64.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: topcg; size: tcgsize; src1, src2, dst: tregister; setflags : boolean; var ovloc : tlocation);
|
||||
var
|
||||
tmpreg1: tregister;
|
||||
tmpreg1, tmpreg2: tregister;
|
||||
begin
|
||||
ovloc.loc:=LOC_VOID;
|
||||
{ overflow can only occur with 64 bit calculations on 64 bit cpus }
|
||||
@ -1375,17 +1375,22 @@ implementation
|
||||
end;
|
||||
OP_IMUL:
|
||||
begin
|
||||
{ check whether the sign bit of the (128 bit) result is the
|
||||
same as "sign bit of src1" xor "signbit of src2" (if so, no
|
||||
overflow and the xor-product of all sign bits is 0) }
|
||||
{ check whether the upper 64 bits of the 128 bit multiplication
|
||||
result have the same value as the replicated sign bit of the
|
||||
lower 64 bits }
|
||||
tmpreg1:=getintregister(list,OS_64);
|
||||
list.concat(taicpu.op_reg_reg_reg(A_SMULH,tmpreg1,src2,src1));
|
||||
list.concat(taicpu.op_reg_reg_reg(A_EOR,tmpreg1,tmpreg1,src1));
|
||||
list.concat(taicpu.op_reg_reg_reg(A_EOR,tmpreg1,tmpreg1,src2));
|
||||
list.concat(taicpu.op_reg_const(A_TST,tmpreg1,$80000000));
|
||||
{ calculate lower 64 bits (afterwards, because dst may be
|
||||
equal to src1 or src2) }
|
||||
a_op_reg_reg_reg(list,op,size,src1,src2,dst);
|
||||
{ replicate sign bit }
|
||||
tmpreg2:=getintregister(list,OS_64);
|
||||
a_op_const_reg_reg(list,OP_SAR,OS_S64,63,dst,tmpreg2);
|
||||
list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
|
||||
ovloc.loc:=LOC_FLAGS;
|
||||
ovloc.resflags:=F_NE;
|
||||
{ still have to perform the actual multiplication }
|
||||
{ finished }
|
||||
exit;
|
||||
end;
|
||||
OP_IDIV,
|
||||
OP_DIV:
|
||||
|
21
tests/webtbs/tw29912.pp
Normal file
21
tests/webtbs/tw29912.pp
Normal file
@ -0,0 +1,21 @@
|
||||
program Project1;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$R+,Q+,S+,T+}
|
||||
|
||||
var
|
||||
x,y,z:integer;
|
||||
begin
|
||||
x:=0;
|
||||
z:=0;
|
||||
// all ok
|
||||
y:=Int64(x-1);
|
||||
writeln(y);
|
||||
// all ok
|
||||
y:=Int64(z);
|
||||
writeln(y);
|
||||
// arithmetic overflow
|
||||
y:=Int64(x-1)*Int64(z);
|
||||
writeln(y);
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user