Przeglądaj źródła

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

florian 10 lat temu
rodzic
commit
ba1297b1ab
4 zmienionych plików z 287 dodań i 11 usunięć
  1. 4 4
      compiler/fpcdefs.inc
  2. 19 6
      compiler/nmat.pas
  3. 8 0
      rtl/inc/compproc.inc
  4. 256 1
      rtl/inc/generic.inc

+ 4 - 4
compiler/fpcdefs.inc

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

+ 19 - 6
compiler/nmat.pas

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

+ 8 - 0
rtl/inc/compproc.inc

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

+ 256 - 1
rtl/inc/generic.inc

@@ -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}
 
 {****************************************************************************}