* fixed overflow checking on AArch64 for signed multiplications with zero

(mantis #29912)

git-svn-id: trunk@33380 -
This commit is contained in:
Jonas Maebe 2016-03-29 09:50:42 +00:00
parent 73a303c899
commit 322493c195
3 changed files with 35 additions and 8 deletions

1
.gitattributes vendored
View File

@ -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

View File

@ -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
View 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.