mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-11 10:29:21 +02:00
* removed the checkoverflow: boolean parameter of the software mul helpers;
replaced it with a separate "_checkoverflow" version of each helper git-svn-id: trunk@36344 -
This commit is contained in:
parent
2b2200fcc6
commit
34113b930b
@ -3362,10 +3362,11 @@ implementation
|
|||||||
else
|
else
|
||||||
internalerror(2011022301);
|
internalerror(2011022301);
|
||||||
end;
|
end;
|
||||||
|
if cs_check_overflow in current_settings.localswitches then
|
||||||
|
procname:=procname+'_checkoverflow';
|
||||||
result := ccallnode.createintern(procname,
|
result := ccallnode.createintern(procname,
|
||||||
ccallparanode.create(cordconstnode.create(ord(cs_check_overflow in current_settings.localswitches),pasbool8type,false),
|
|
||||||
ccallparanode.create(right,
|
ccallparanode.create(right,
|
||||||
ccallparanode.create(left,nil))));
|
ccallparanode.create(left,nil)));
|
||||||
left := nil;
|
left := nil;
|
||||||
right := nil;
|
right := nil;
|
||||||
firstpass(result);
|
firstpass(result);
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
**********************************************************************}
|
**********************************************************************}
|
||||||
|
|
||||||
{$define FPC_SYSTEM_HAS_MUL_DWORD}
|
{$define FPC_SYSTEM_HAS_MUL_DWORD}
|
||||||
function fpc_mul_dword( f1, f2: dword; checkoverflow: boolean ): dword; [public,alias: 'FPC_MUL_DWORD']; compilerproc;
|
function fpc_mul_dword( f1, f2: dword ): dword; [public,alias: 'FPC_MUL_DWORD']; compilerproc;
|
||||||
begin
|
begin
|
||||||
{ routine contributed by Max Nazhalov
|
{ routine contributed by Max Nazhalov
|
||||||
|
|
||||||
@ -33,8 +33,6 @@ begin
|
|||||||
mov ax,word[f1+2]
|
mov ax,word[f1+2]
|
||||||
mov di,word[f2]
|
mov di,word[f2]
|
||||||
mov si,word[f2+2]
|
mov si,word[f2+2]
|
||||||
cmp checkoverflow,0
|
|
||||||
jne @@checked
|
|
||||||
mul di
|
mul di
|
||||||
xchg ax,si
|
xchg ax,si
|
||||||
mul cx
|
mul cx
|
||||||
@ -42,34 +40,57 @@ begin
|
|||||||
mov ax,di
|
mov ax,di
|
||||||
mul cx
|
mul cx
|
||||||
add dx,si
|
add dx,si
|
||||||
jmp @@done
|
mov word[result],ax
|
||||||
@@checked:
|
mov word[result+2],dx
|
||||||
|
end [ 'ax','cx','dx','si','di' ];
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function fpc_mul_dword_checkoverflow( f1, f2: dword ): dword; [public,alias: 'FPC_MUL_DWORD_CHECKOVERFLOW']; compilerproc;
|
||||||
|
begin
|
||||||
|
{ routine contributed by Max Nazhalov
|
||||||
|
|
||||||
|
32-bit multiplications summary:
|
||||||
|
f1 = A1*$10000+A0
|
||||||
|
f2 = B1*$10000+B0
|
||||||
|
(A1:A0*B1:B0) = (A1*B1)<<32 + (A1*B0)<<16 + (A0*B1)<<16 + (A0*B0)
|
||||||
|
|
||||||
|
A1*B1 [only needed for overflow checking; overflow if <>0]
|
||||||
|
A1*B0
|
||||||
|
A0*B1
|
||||||
|
A0:B0
|
||||||
|
}
|
||||||
|
asm
|
||||||
|
mov cx,word[f1]
|
||||||
|
mov ax,word[f1+2]
|
||||||
|
mov di,word[f2]
|
||||||
|
mov si,word[f2+2]
|
||||||
test ax,ax
|
test ax,ax
|
||||||
jz @@skip
|
jz @@skip
|
||||||
test si,si
|
test si,si
|
||||||
jnz @@done
|
jnz @@overflow
|
||||||
mul di
|
mul di
|
||||||
test dx,dx
|
test dx,dx
|
||||||
jnz @@done
|
jnz @@overflow
|
||||||
@@skip:
|
@@skip:
|
||||||
xchg ax,si
|
xchg ax,si
|
||||||
mul cx
|
mul cx
|
||||||
test dx,dx
|
test dx,dx
|
||||||
jnz @@done
|
jnz @@overflow
|
||||||
add si,ax
|
add si,ax
|
||||||
jc @@done
|
jc @@overflow
|
||||||
mov ax,di
|
mov ax,di
|
||||||
mul cx
|
mul cx
|
||||||
add dx,si
|
add dx,si
|
||||||
jc @@done
|
jc @@overflow
|
||||||
// checked and succeed
|
// checked and succeed
|
||||||
mov checkoverflow,0
|
|
||||||
@@done:
|
|
||||||
mov word[result],ax
|
mov word[result],ax
|
||||||
mov word[result+2],dx
|
mov word[result+2],dx
|
||||||
|
jmp @@done
|
||||||
|
@@overflow:
|
||||||
|
call FPC_OVERFLOW
|
||||||
|
@@done:
|
||||||
end [ 'ax','cx','dx','si','di' ];
|
end [ 'ax','cx','dx','si','di' ];
|
||||||
if checkoverflow then
|
|
||||||
HandleErrorAddrFrameInd(215,get_pc_addr,get_frame);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -592,10 +592,21 @@ function fpc_mod_shortint(n,z : shortint) : shortint; compilerproc;
|
|||||||
{$endif FPC_INCLUDE_SOFTWARE_MOD_DIV}
|
{$endif FPC_INCLUDE_SOFTWARE_MOD_DIV}
|
||||||
|
|
||||||
{$ifdef FPC_INCLUDE_SOFTWARE_MUL}
|
{$ifdef FPC_INCLUDE_SOFTWARE_MUL}
|
||||||
|
{$ifdef VER3_0}
|
||||||
function fpc_mul_integer(f1,f2 : integer;checkoverflow : boolean) : integer; compilerproc;
|
function fpc_mul_integer(f1,f2 : integer;checkoverflow : boolean) : integer; compilerproc;
|
||||||
function fpc_mul_word(f1,f2 : word;checkoverflow : boolean) : word; compilerproc;
|
function fpc_mul_word(f1,f2 : word;checkoverflow : boolean) : word; compilerproc;
|
||||||
function fpc_mul_longint(f1,f2 : longint;checkoverflow : boolean) : longint; compilerproc;
|
function fpc_mul_longint(f1,f2 : longint;checkoverflow : boolean) : longint; compilerproc;
|
||||||
function fpc_mul_dword(f1,f2 : dword;checkoverflow : boolean) : dword; compilerproc;
|
function fpc_mul_dword(f1,f2 : dword;checkoverflow : boolean) : dword; compilerproc;
|
||||||
|
{$else VER3_0}
|
||||||
|
function fpc_mul_integer(f1,f2 : integer) : integer; compilerproc;
|
||||||
|
function fpc_mul_integer_checkoverflow(f1,f2 : integer) : integer; compilerproc;
|
||||||
|
function fpc_mul_word(f1,f2 : word) : word; compilerproc;
|
||||||
|
function fpc_mul_word_checkoverflow(f1,f2 : word) : word; compilerproc;
|
||||||
|
function fpc_mul_longint(f1,f2 : longint) : longint; compilerproc;
|
||||||
|
function fpc_mul_longint_checkoverflow(f1,f2 : longint) : longint; compilerproc;
|
||||||
|
function fpc_mul_dword(f1,f2 : dword) : dword; compilerproc;
|
||||||
|
function fpc_mul_dword_checkoverflow(f1,f2 : dword) : dword; compilerproc;
|
||||||
|
{$endif VER3_0}
|
||||||
{$endif FPC_INCLUDE_SOFTWARE_MUL}
|
{$endif FPC_INCLUDE_SOFTWARE_MUL}
|
||||||
|
|
||||||
{ from int64.inc }
|
{ from int64.inc }
|
||||||
|
@ -1327,6 +1327,8 @@ end;
|
|||||||
****************************************************************************}
|
****************************************************************************}
|
||||||
{$ifdef FPC_INCLUDE_SOFTWARE_MUL}
|
{$ifdef FPC_INCLUDE_SOFTWARE_MUL}
|
||||||
|
|
||||||
|
{$ifdef VER3_0}
|
||||||
|
|
||||||
{$ifndef FPC_SYSTEM_HAS_MUL_INTEGER}
|
{$ifndef FPC_SYSTEM_HAS_MUL_INTEGER}
|
||||||
function fpc_mul_integer(f1,f2 : integer;checkoverflow : boolean) : integer;[public,alias: 'FPC_MUL_INTEGER']; compilerproc;
|
function fpc_mul_integer(f1,f2 : integer;checkoverflow : boolean) : integer;[public,alias: 'FPC_MUL_INTEGER']; compilerproc;
|
||||||
var
|
var
|
||||||
@ -1495,6 +1497,215 @@ end;
|
|||||||
end;
|
end;
|
||||||
{$endif FPC_SYSTEM_HAS_MUL_DWORD}
|
{$endif FPC_SYSTEM_HAS_MUL_DWORD}
|
||||||
|
|
||||||
|
{$else VER3_0}
|
||||||
|
|
||||||
|
{$ifndef FPC_SYSTEM_HAS_MUL_INTEGER}
|
||||||
|
function fpc_mul_integer(f1,f2 : integer) : integer;[public,alias: 'FPC_MUL_INTEGER']; compilerproc;
|
||||||
|
begin
|
||||||
|
{ there's no difference between signed and unsigned multiplication,
|
||||||
|
when the destination size is equal to the source size and overflow
|
||||||
|
checking is off }
|
||||||
|
{ word(f1)*word(f2) is coded as a call to mulword }
|
||||||
|
fpc_mul_integer:=integer(word(f1)*word(f2));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function fpc_mul_integer_checkoverflow(f1,f2 : integer) : integer;[public,alias: 'FPC_MUL_INTEGER_CHECKOVERFLOW']; compilerproc;
|
||||||
|
var
|
||||||
|
sign : boolean;
|
||||||
|
q1,q2,q3 : word;
|
||||||
|
begin
|
||||||
|
sign:=false;
|
||||||
|
if f1<0 then
|
||||||
|
begin
|
||||||
|
sign:=not(sign);
|
||||||
|
q1:=word(-f1);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
q1:=f1;
|
||||||
|
if f2<0 then
|
||||||
|
begin
|
||||||
|
sign:=not(sign);
|
||||||
|
q2:=word(-f2);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
q2:=f2;
|
||||||
|
{ the q1*q2 is coded as call to mulword }
|
||||||
|
q3:=q1*q2;
|
||||||
|
|
||||||
|
if (q1 <> 0) and (q2 <>0) and
|
||||||
|
((q1>q3) or (q2>q3) or
|
||||||
|
{ the bit 63 can be only set if we have $8000 }
|
||||||
|
{ and sign is true }
|
||||||
|
(q3 shr 15<>0) and
|
||||||
|
((q3<>word(word(1) shl 15)) or not(sign))
|
||||||
|
) then
|
||||||
|
HandleErrorAddrFrameInd(215,get_pc_addr,get_frame);
|
||||||
|
|
||||||
|
if sign then
|
||||||
|
fpc_mul_integer_checkoverflow:=-q3
|
||||||
|
else
|
||||||
|
fpc_mul_integer_checkoverflow:=q3;
|
||||||
|
end;
|
||||||
|
{$endif FPC_SYSTEM_HAS_MUL_INTEGER}
|
||||||
|
|
||||||
|
|
||||||
|
{$ifndef FPC_SYSTEM_HAS_MUL_WORD}
|
||||||
|
function fpc_mul_word(f1,f2 : word) : word;[public,alias: 'FPC_MUL_WORD']; compilerproc;
|
||||||
|
var
|
||||||
|
_f1,bitpos : word;
|
||||||
|
b : byte;
|
||||||
|
begin
|
||||||
|
fpc_mul_word:=0;
|
||||||
|
bitpos:=1;
|
||||||
|
|
||||||
|
for b:=0 to 15 do
|
||||||
|
begin
|
||||||
|
if (f2 and bitpos)<>0 then
|
||||||
|
begin
|
||||||
|
_f1:=fpc_mul_word;
|
||||||
|
fpc_mul_word:=fpc_mul_word+f1;
|
||||||
|
end;
|
||||||
|
f1:=f1 shl 1;
|
||||||
|
bitpos:=bitpos shl 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function fpc_mul_word_checkoverflow(f1,f2 : word) : word;[public,alias: 'FPC_MUL_WORD_CHECKOVERFLOW']; compilerproc;
|
||||||
|
var
|
||||||
|
_f1,bitpos : word;
|
||||||
|
b : byte;
|
||||||
|
f1overflowed : boolean;
|
||||||
|
begin
|
||||||
|
fpc_mul_word_checkoverflow:=0;
|
||||||
|
bitpos:=1;
|
||||||
|
f1overflowed:=false;
|
||||||
|
|
||||||
|
for b:=0 to 15 do
|
||||||
|
begin
|
||||||
|
if (f2 and bitpos)<>0 then
|
||||||
|
begin
|
||||||
|
_f1:=fpc_mul_word_checkoverflow;
|
||||||
|
fpc_mul_word_checkoverflow:=fpc_mul_word_checkoverflow+f1;
|
||||||
|
|
||||||
|
{ if one of the operands is greater than the result an
|
||||||
|
overflow occurs }
|
||||||
|
if f1overflowed or ((_f1<>0) and (f1<>0) and
|
||||||
|
((_f1>fpc_mul_word_checkoverflow) or (f1>fpc_mul_word_checkoverflow))) then
|
||||||
|
HandleErrorAddrFrameInd(215,get_pc_addr,get_frame);
|
||||||
|
end;
|
||||||
|
{ when bootstrapping, we forget about overflow checking for qword :) }
|
||||||
|
f1overflowed:=f1overflowed or ((f1 and (1 shl 15))<>0);
|
||||||
|
f1:=f1 shl 1;
|
||||||
|
bitpos:=bitpos shl 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{$endif FPC_SYSTEM_HAS_MUL_WORD}
|
||||||
|
|
||||||
|
|
||||||
|
{$ifndef FPC_SYSTEM_HAS_MUL_LONGINT}
|
||||||
|
function fpc_mul_longint(f1,f2 : longint) : longint;[public,alias: 'FPC_MUL_LONGINT']; compilerproc;
|
||||||
|
begin
|
||||||
|
{ there's no difference between signed and unsigned multiplication,
|
||||||
|
when the destination size is equal to the source size and overflow
|
||||||
|
checking is off }
|
||||||
|
{ dword(f1)*dword(f2) is coded as a call to muldword }
|
||||||
|
fpc_mul_longint:=longint(dword(f1)*dword(f2));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function fpc_mul_longint_checkoverflow(f1,f2 : longint) : longint;[public,alias: 'FPC_MUL_LONGINT_CHECKOVERFLOW']; compilerproc;
|
||||||
|
var
|
||||||
|
sign : boolean;
|
||||||
|
q1,q2,q3 : dword;
|
||||||
|
begin
|
||||||
|
sign:=false;
|
||||||
|
if f1<0 then
|
||||||
|
begin
|
||||||
|
sign:=not(sign);
|
||||||
|
q1:=dword(-f1);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
q1:=f1;
|
||||||
|
if f2<0 then
|
||||||
|
begin
|
||||||
|
sign:=not(sign);
|
||||||
|
q2:=dword(-f2);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
q2:=f2;
|
||||||
|
{ the q1*q2 is coded as call to muldword }
|
||||||
|
q3:=q1*q2;
|
||||||
|
|
||||||
|
if (q1 <> 0) and (q2 <>0) and
|
||||||
|
((q1>q3) or (q2>q3) or
|
||||||
|
{ the bit 31 can be only set if we have $8000 0000 }
|
||||||
|
{ and sign is true }
|
||||||
|
(q3 shr 15<>0) and
|
||||||
|
((q3<>dword(dword(1) shl 31)) or not(sign))
|
||||||
|
) then
|
||||||
|
HandleErrorAddrFrameInd(215,get_pc_addr,get_frame);
|
||||||
|
|
||||||
|
if sign then
|
||||||
|
fpc_mul_longint_checkoverflow:=-q3
|
||||||
|
else
|
||||||
|
fpc_mul_longint_checkoverflow:=q3;
|
||||||
|
end;
|
||||||
|
{$endif FPC_SYSTEM_HAS_MUL_INTEGER}
|
||||||
|
|
||||||
|
|
||||||
|
{$ifndef FPC_SYSTEM_HAS_MUL_DWORD}
|
||||||
|
function fpc_mul_dword(f1,f2 : dword) : dword;[public,alias: 'FPC_MUL_DWORD']; compilerproc;
|
||||||
|
var
|
||||||
|
_f1,bitpos : dword;
|
||||||
|
b : byte;
|
||||||
|
begin
|
||||||
|
fpc_mul_dword:=0;
|
||||||
|
bitpos:=1;
|
||||||
|
|
||||||
|
for b:=0 to 31 do
|
||||||
|
begin
|
||||||
|
if (f2 and bitpos)<>0 then
|
||||||
|
begin
|
||||||
|
_f1:=fpc_mul_dword;
|
||||||
|
fpc_mul_dword:=fpc_mul_dword+f1;
|
||||||
|
end;
|
||||||
|
f1:=f1 shl 1;
|
||||||
|
bitpos:=bitpos shl 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function fpc_mul_dword_checkoverflow(f1,f2 : dword) : dword;[public,alias: 'FPC_MUL_DWORD_CHECKOVERFLOW']; compilerproc;
|
||||||
|
var
|
||||||
|
_f1,bitpos : dword;
|
||||||
|
b : byte;
|
||||||
|
f1overflowed : boolean;
|
||||||
|
begin
|
||||||
|
fpc_mul_dword_checkoverflow:=0;
|
||||||
|
bitpos:=1;
|
||||||
|
f1overflowed:=false;
|
||||||
|
|
||||||
|
for b:=0 to 31 do
|
||||||
|
begin
|
||||||
|
if (f2 and bitpos)<>0 then
|
||||||
|
begin
|
||||||
|
_f1:=fpc_mul_dword_checkoverflow;
|
||||||
|
fpc_mul_dword_checkoverflow:=fpc_mul_dword_checkoverflow+f1;
|
||||||
|
|
||||||
|
{ if one of the operands is greater than the result an
|
||||||
|
overflow occurs }
|
||||||
|
if f1overflowed or ((_f1<>0) and (f1<>0) and
|
||||||
|
((_f1>fpc_mul_dword_checkoverflow) or (f1>fpc_mul_dword_checkoverflow))) then
|
||||||
|
HandleErrorAddrFrameInd(215,get_pc_addr,get_frame);
|
||||||
|
end;
|
||||||
|
{ when bootstrapping, we forget about overflow checking for qword :) }
|
||||||
|
f1overflowed:=f1overflowed or ((f1 and (dword(1) shl 31))<>0);
|
||||||
|
f1:=f1 shl 1;
|
||||||
|
bitpos:=bitpos shl 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{$endif FPC_SYSTEM_HAS_MUL_DWORD}
|
||||||
|
|
||||||
|
{$endif VER3_0}
|
||||||
|
|
||||||
{$endif FPC_INCLUDE_SOFTWARE_MUL}
|
{$endif FPC_INCLUDE_SOFTWARE_MUL}
|
||||||
|
|
||||||
{****************************************************************************
|
{****************************************************************************
|
||||||
|
Loading…
Reference in New Issue
Block a user