+ provide also 8 and 16 bit div/mod helper

* tmoddivnode.first_moddivint does not force a 32 bit helper, the used helper depends now on the resultdef type set by tmoddivnode.pass_typecheck

git-svn-id: trunk@31195 -
This commit is contained in:
florian 2015-07-05 20:16:50 +00:00
parent cf64e05c6f
commit ba1297b1ab
4 changed files with 287 additions and 11 deletions

View File

@ -56,7 +56,7 @@
{$define SUPPORT_SAFECALL}
{$define cpuneedsmulhelper}
{ TODO: add another define in order to disable the div helper for 16-bit divs? }
{$define cpuneedsdiv32helper}
{$define cpuneedsdivhelper}
{$define VOLATILE_ES}
{$define SUPPORT_GET_FRAME}
{$endif i8086}
@ -145,7 +145,7 @@
{$define cpu32bitalu}
{$define cpuflags}
{$define cpufpemu}
{$define cpuneedsdiv32helper}
{$define cpuneedsdivhelper}
{$define cpurox}
{$define cputargethasfixedstack}
{$define cpurefshaveindexreg}
@ -178,7 +178,7 @@
{$define cpufpemu}
{$define cpurefshaveindexreg}
{$define cpucapabilities}
{$define cpuneedsdiv32helper}
{$define cpuneedsdivhelper}
{$endif m68k}
{$ifdef avr}
@ -188,7 +188,7 @@
{$define cpuflags}
{$define cpunofpu}
{$define cpunodefaultint}
{$define cpuneedsdiv32helper}
{$define cpuneedsdivhelper}
{$define cpuneedsmulhelper}
{$define cpurefshaveindexreg}
{$define cpucapabilities}

View File

@ -393,7 +393,7 @@ implementation
function tmoddivnode.first_moddivint: tnode;
{$ifdef cpuneedsdiv32helper}
{$ifdef cpuneedsdivhelper}
var
procname: string[31];
begin
@ -404,12 +404,25 @@ implementation
procname := 'fpc_div_'
else
procname := 'fpc_mod_';
{ only qword needs the unsigned code, the
signed code is also used for currency }
if is_signed(resultdef) then
procname := procname + 'longint'
else
procname := procname + 'dword';
case torddef(resultdef).ordtype of
u8bit:
procname := procname + 'byte';
s8bit:
procname := procname + 'shortint';
u16bit:
procname := procname + 'word';
s16bit:
procname := procname + 'smallint';
u32bit:
procname := procname + 'dword';
s32bit:
procname := procname + 'longint'
else
internalerror(2015070501);
end;
result := ccallnode.createintern(procname,ccallparanode.create(left,
ccallparanode.create(right,nil)));
@ -424,7 +437,7 @@ implementation
if torddef(result.resultdef).ordtype <> torddef(resultdef).ordtype then
inserttypeconv(result,resultdef);
end;
{$else cpuneedsdiv32helper}
{$else cpuneedsdivhelper}
begin
result:=nil;
end;

View File

@ -568,6 +568,14 @@ function fpc_div_dword(n,z : dword) : dword; compilerproc;
function fpc_mod_dword(n,z : dword) : dword; compilerproc;
function fpc_div_longint(n,z : longint) : longint; compilerproc;
function fpc_mod_longint(n,z : longint) : longint; compilerproc;
function fpc_div_word(n,z : word) : word; compilerproc;
function fpc_mod_word(n,z : word) : word; compilerproc;
function fpc_div_smallint(n,z : smallint) : smallint; compilerproc;
function fpc_mod_smallint(n,z : smallint) : smallint; compilerproc;
function fpc_div_byte(n,z : byte) : byte; compilerproc;
function fpc_mod_byte(n,z : byte) : byte; compilerproc;
function fpc_div_shortint(n,z : shortint) : shortint; compilerproc;
function fpc_mod_shortint(n,z : shortint) : shortint; compilerproc;
{$endif FPC_INCLUDE_SOFTWARE_MOD_DIV}
{$ifdef FPC_INCLUDE_SOFTWARE_MUL}

View File

@ -1556,6 +1556,136 @@ function fpc_mod_dword(n,z : dword) : dword; [public,alias: 'FPC_MOD_DWORD']; co
{$endif FPC_SYSTEM_HAS_MOD_DWORD}
{$ifndef FPC_SYSTEM_HAS_DIV_WORD}
function fpc_div_word(n,z : word) : word; [public,alias: 'FPC_DIV_WORD']; compilerproc;
var
shift,lzz,lzn : Byte;
begin
result:=0;
if n=0 then
HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
if z=0 then
exit;
lzz:=BsrWord(z);
lzn:=BsrWord(n);
{ if the denominator contains less zeros
then the numerator
then d is greater than the n }
if lzn>lzz then
exit;
shift:=lzz-lzn;
n:=n shl shift;
for shift:=shift downto 0 do
begin
if z>=n then
begin
z:=z-n;
result:=result+word(word(1) shl shift);
end;
n:=n shr 1;
end;
end;
{$endif FPC_SYSTEM_HAS_DIV_WORD}
{$ifndef FPC_SYSTEM_HAS_MOD_WORD}
function fpc_mod_word(n,z : word) : word; [public,alias: 'FPC_MOD_WORD']; compilerproc;
var
shift,lzz,lzn : Byte;
begin
result:=0;
if n=0 then
HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
if z=0 then
exit;
lzz:=BsrWord(z);
lzn:=BsrWord(n);
{ if the denominator contains less zeros
then the numerator
then d is greater than the n }
if lzn>lzz then
begin
result:=z;
exit;
end;
shift:=lzz-lzn;
n:=n shl shift;
for shift:=shift downto 0 do
begin
if z>=n then
z:=z-n;
n:=n shr 1;
end;
result:=z;
end;
{$endif FPC_SYSTEM_HAS_MOD_WORD}
{$ifndef FPC_SYSTEM_HAS_DIV_BYTE}
function fpc_div_byte(n,z : byte) : byte; [public,alias: 'FPC_DIV_BYTE']; compilerproc;
var
shift,lzz,lzn : Byte;
begin
result:=0;
if n=0 then
HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
if z=0 then
exit;
lzz:=BsrByte(z);
lzn:=BsrByte(n);
{ if the denominator contains less zeros
then the numerator
then d is greater than the n }
if lzn>lzz then
exit;
shift:=lzz-lzn;
n:=n shl shift;
for shift:=shift downto 0 do
begin
if z>=n then
begin
z:=z-n;
result:=result+byte(byte(1) shl shift);
end;
n:=n shr 1;
end;
end;
{$endif FPC_SYSTEM_HAS_DIV_BYTE}
{$ifndef FPC_SYSTEM_HAS_MOD_BYTE}
function fpc_mod_byte(n,z : byte) : byte; [public,alias: 'FPC_MOD_BYTE']; compilerproc;
var
shift,lzz,lzn : Byte;
begin
result:=0;
if n=0 then
HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
if z=0 then
exit;
lzz:=BsrByte(z);
lzn:=BsrByte(n);
{ if the denominator contains less zeros
then the numerator
then d is greater than the n }
if lzn>lzz then
begin
result:=z;
exit;
end;
shift:=lzz-lzn;
n:=n shl shift;
for shift:=shift downto 0 do
begin
if z>=n then
z:=z-n;
n:=n shr 1;
end;
result:=z;
end;
{$endif FPC_SYSTEM_HAS_MOD_BYTE}
{$ifndef FPC_SYSTEM_HAS_DIV_LONGINT}
function fpc_div_longint(n,z : longint) : longint; [public,alias: 'FPC_DIV_LONGINT']; compilerproc;
var
@ -1618,8 +1748,133 @@ function fpc_mod_longint(n,z : longint) : longint; [public,alias: 'FPC_MOD_LONGI
end;
{$endif FPC_SYSTEM_HAS_MOD_LONGINT}
{$endif FPC_INCLUDE_SOFTWARE_MOD_DIV}
{$ifndef FPC_SYSTEM_HAS_DIV_SMALLINT}
function fpc_div_smallint(n,z : smallint) : smallint; [public,alias: 'FPC_DIV_SMALLINT']; compilerproc;
var
sign : boolean;
w1,w2 : word;
begin
if n=0 then
HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
sign:=false;
if z<0 then
begin
sign:=not(sign);
w1:=word(-z);
end
else
w1:=z;
if n<0 then
begin
sign:=not(sign);
w2:=word(-n);
end
else
w2:=n;
{ the div is coded by the compiler as call to divdword }
if sign then
result:=-(w1 div w2)
else
result:=w1 div w2;
end;
{$endif FPC_SYSTEM_HAS_DIV_SMALLINT}
{$ifndef FPC_SYSTEM_HAS_MOD_SMALLINT}
function fpc_mod_smallint(n,z : smallint) : smallint; [public,alias: 'FPC_MOD_SMALLINT']; compilerproc;
var
signed : boolean;
r,nq,zq : word;
begin
if n=0 then
HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
nq:=abs(n);
if z<0 then
begin
zq:=word(-z);
signed:=true;
end
else
begin
zq:=z;
signed:=false;
end;
r:=zq mod nq;
if signed then
result:=-smallint(r)
else
result:=r;
end;
{$endif FPC_SYSTEM_HAS_MOD_SMALLINT}
{$ifndef FPC_SYSTEM_HAS_DIV_SHORTINT}
function fpc_div_shortint(n,z : shortint) : shortint; [public,alias: 'FPC_DIV_SHORTINT']; compilerproc;
var
sign : boolean;
b1,b2 : byte;
begin
if n=0 then
HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
sign:=false;
if z<0 then
begin
sign:=not(sign);
b1:=byte(-z);
end
else
b1:=z;
if n<0 then
begin
sign:=not(sign);
b2:=byte(-n);
end
else
b2:=n;
{ the div is coded by the compiler as call to divdword }
if sign then
result:=-(b1 div b2)
else
result:=b1 div b2;
end;
{$endif FPC_SYSTEM_HAS_DIV_SHORTINT}
{$ifndef FPC_SYSTEM_HAS_MOD_SHORTINT}
function fpc_mod_shortint(n,z : shortint) : shortint; [public,alias: 'FPC_MOD_SHORTINT']; compilerproc;
var
signed : boolean;
r,nq,zq : byte;
begin
if n=0 then
HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
nq:=abs(n);
if z<0 then
begin
zq:=byte(-z);
signed:=true;
end
else
begin
zq:=z;
signed:=false;
end;
r:=zq mod nq;
if signed then
result:=-shortint(r)
else
result:=r;
end;
{$endif FPC_SYSTEM_HAS_MOD_SHORTINT}
{$endif FPC_INCLUDE_SOFTWARE_MOD_DIV}
{****************************************************************************}