瀏覽代碼

* replaced the saved_XXX_registers arrays with virtual methods inside
tcpuparamanager, very similar to the existing get_volatile_registers_XXX. The
new methods are called get_saved_registers_XXX, where XXX is the register
type ("int", "address", "fpu" or "mm")

git-svn-id: trunk@38794 -

nickysn 7 年之前
父節點
當前提交
518cdf9674

+ 0 - 19
compiler/aarch64/cpubase.pas

@@ -305,25 +305,6 @@ unit cpubase;
       NR_DEFAULTFLAGS = NR_NZCV;
       NR_DEFAULTFLAGS = NR_NZCV;
       RS_DEFAULTFLAGS = RS_NZCV;
       RS_DEFAULTFLAGS = RS_NZCV;
 
 
-{*****************************************************************************
-                       GCC /ABI linking information
-*****************************************************************************}
-
-    const
-      { Registers which must be saved when calling a routine declared as
-        cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
-        saved should be the ones as defined in the target ABI and / or GCC.
-
-        This value can be deduced from the CALLED_USED_REGISTERS array in the
-        GCC source.
-      }
-      saved_standard_registers : array[0..9] of tsuperregister =
-        (RS_X19,RS_X20,RS_X21,RS_X22,RS_X23,RS_X24,RS_X25,RS_X26,RS_X27,RS_X28);
-      saved_mm_registers : array[0..7] of tsuperregister = (RS_D8,RS_D9,RS_D10,RS_D11,RS_D12,RS_D13,RS_D14,RS_D15);
-
-      { this is only for the generic code which is not used for this architecture }
-      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
-
 {*****************************************************************************
 {*****************************************************************************
                                   Helpers
                                   Helpers
 *****************************************************************************}
 *****************************************************************************}

+ 19 - 0
compiler/aarch64/cpupara.pas

@@ -37,6 +37,8 @@ unit cpupara;
           function get_volatile_registers_int(calloption: tproccalloption): tcpuregisterset; override;
           function get_volatile_registers_int(calloption: tproccalloption): tcpuregisterset; override;
           function get_volatile_registers_fpu(calloption: tproccalloption): tcpuregisterset; override;
           function get_volatile_registers_fpu(calloption: tproccalloption): tcpuregisterset; override;
           function get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset; override;
           function get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset; override;
+          function get_saved_registers_int(calloption: tproccalloption): tcpuregisterarray; override;
+          function get_saved_registers_mm(calloption: tproccalloption): tcpuregisterarray; override;
           function push_addr_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean; override;
           function push_addr_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean; override;
           function ret_in_param(def: tdef; pd: tabstractprocdef):boolean;override;
           function ret_in_param(def: tdef; pd: tabstractprocdef):boolean;override;
           function create_paraloc_info(p: tabstractprocdef; side: tcallercallee):longint;override;
           function create_paraloc_info(p: tabstractprocdef; side: tcallercallee):longint;override;
@@ -87,6 +89,23 @@ unit cpupara;
       end;
       end;
 
 
 
 
+    function tcpuparamanager.get_saved_registers_int(calloption: tproccalloption): tcpuregisterarray;
+      const
+        saved_regs : array[0..9] of tsuperregister =
+          (RS_X19,RS_X20,RS_X21,RS_X22,RS_X23,RS_X24,RS_X25,RS_X26,RS_X27,RS_X28);
+      begin
+        result:=saved_regs;
+      end;
+
+
+    function tcpuparamanager.get_saved_registers_mm(calloption: tproccalloption): tcpuregisterarray;
+      const
+        saved_mm_regs : array[0..7] of tsuperregister = (RS_D8,RS_D9,RS_D10,RS_D11,RS_D12,RS_D13,RS_D14,RS_D15);
+      begin
+        result:=saved_mm_regs;
+      end;
+
+
     function is_hfa_internal(p: tdef; var basedef: tdef; var elecount: longint): boolean;
     function is_hfa_internal(p: tdef; var basedef: tdef; var elecount: longint): boolean;
       var
       var
         i: longint;
         i: longint;

+ 0 - 14
compiler/arm/cpubase.pas

@@ -341,20 +341,6 @@ unit cpubase;
 *****************************************************************************}
 *****************************************************************************}
 
 
     const
     const
-      { Registers which must be saved when calling a routine declared as
-        cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
-        saved should be the ones as defined in the target ABI and / or GCC.
-
-        This value can be deduced from the CALLED_USED_REGISTERS array in the
-        GCC source.
-      }
-      saved_standard_registers : array[0..6] of tsuperregister =
-        (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
-
-      { this is only for the generic code which is not used for this architecture }
-      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
-      saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
-
       { Required parameter alignment when calling a routine declared as
       { Required parameter alignment when calling a routine declared as
         stdcall and cdecl. The alignment value should be the one defined
         stdcall and cdecl. The alignment value should be the one defined
         by GCC or the target ABI.
         by GCC or the target ABI.

+ 10 - 0
compiler/arm/cpupara.pas

@@ -37,6 +37,7 @@ unit cpupara;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
+          function get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;override;
           function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
           function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
           function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
           function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
           procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
           procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
@@ -81,6 +82,15 @@ unit cpupara;
       end;
       end;
 
 
 
 
+    function tcpuparamanager.get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;
+      const
+        saved_regs : array[0..6] of tsuperregister =
+          (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
+      begin
+        result:=saved_regs;
+      end;
+
+
     procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
     procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;

+ 0 - 14
compiler/avr/cpubase.pas

@@ -278,17 +278,6 @@ unit cpubase;
 *****************************************************************************}
 *****************************************************************************}
 
 
     const
     const
-      { Registers which must be saved when calling a routine declared as
-        cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
-        saved should be the ones as defined in the target ABI and / or GCC.
-
-        This value can be deduced from the CALLED_USED_REGISTERS array in the
-        GCC source.
-      }
-      { on avr, gen_entry/gen_exit code saves/restores registers, so
-        we don't need this array }
-      saved_standard_registers : array[0..0] of tsuperregister =
-        (RS_INVALID);
       { Required parameter alignment when calling a routine declared as
       { Required parameter alignment when calling a routine declared as
         stdcall and cdecl. The alignment value should be the one defined
         stdcall and cdecl. The alignment value should be the one defined
         by GCC or the target ABI.
         by GCC or the target ABI.
@@ -298,9 +287,6 @@ unit cpubase;
       }
       }
       std_param_align = 4;
       std_param_align = 4;
 
 
-      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
-      saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
-
 {*****************************************************************************
 {*****************************************************************************
                                   Helpers
                                   Helpers
 *****************************************************************************}
 *****************************************************************************}

+ 40 - 28
compiler/cgobj.pas

@@ -2523,15 +2523,21 @@ implementation
         href : treference;
         href : treference;
         size : longint;
         size : longint;
         r : integer;
         r : integer;
+        regs_to_save_int,
+        regs_to_save_address,
+        regs_to_save_mm : tcpuregisterarray;
       begin
       begin
+        regs_to_save_int:=paramanager.get_saved_registers_int(current_procinfo.procdef.proccalloption);
+        regs_to_save_address:=paramanager.get_saved_registers_address(current_procinfo.procdef.proccalloption);
+        regs_to_save_mm:=paramanager.get_saved_registers_mm(current_procinfo.procdef.proccalloption);
         { calculate temp. size }
         { calculate temp. size }
         size:=0;
         size:=0;
-        for r:=low(saved_standard_registers) to high(saved_standard_registers) do
-          if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+        for r:=low(regs_to_save_int) to high(regs_to_save_int) do
+          if regs_to_save_int[r] in rg[R_INTREGISTER].used_in_proc then
             inc(size,sizeof(aint));
             inc(size,sizeof(aint));
         if uses_registers(R_ADDRESSREGISTER) then
         if uses_registers(R_ADDRESSREGISTER) then
-          for r:=low(saved_address_registers) to high(saved_address_registers) do
-            if saved_address_registers[r] in rg[R_ADDRESSREGISTER].used_in_proc then
+          for r:=low(regs_to_save_int) to high(regs_to_save_int) do
+            if regs_to_save_int[r] in rg[R_ADDRESSREGISTER].used_in_proc then
               inc(size,sizeof(aint));
               inc(size,sizeof(aint));
 
 
         { mm registers }
         { mm registers }
@@ -2542,8 +2548,8 @@ implementation
               of the temp is smaller than needed for an OS_VECTOR }
               of the temp is smaller than needed for an OS_VECTOR }
             inc(size,tcgsize2size[OS_VECTOR]);
             inc(size,tcgsize2size[OS_VECTOR]);
 
 
-            for r:=low(saved_mm_registers) to high(saved_mm_registers) do
-              if saved_mm_registers[r] in rg[R_MMREGISTER].used_in_proc then
+            for r:=low(regs_to_save_mm) to high(regs_to_save_mm) do
+              if regs_to_save_mm[r] in rg[R_MMREGISTER].used_in_proc then
                 inc(size,tcgsize2size[OS_VECTOR]);
                 inc(size,tcgsize2size[OS_VECTOR]);
           end;
           end;
 
 
@@ -2554,25 +2560,25 @@ implementation
 
 
             { Copy registers to temp }
             { Copy registers to temp }
             href:=current_procinfo.save_regs_ref;
             href:=current_procinfo.save_regs_ref;
-            for r:=low(saved_standard_registers) to high(saved_standard_registers) do
+            for r:=low(regs_to_save_int) to high(regs_to_save_int) do
               begin
               begin
-                if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+                if regs_to_save_int[r] in rg[R_INTREGISTER].used_in_proc then
                   begin
                   begin
-                    a_load_reg_ref(list,OS_ADDR,OS_ADDR,newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE),href);
+                    a_load_reg_ref(list,OS_ADDR,OS_ADDR,newreg(R_INTREGISTER,regs_to_save_int[r],R_SUBWHOLE),href);
                     inc(href.offset,sizeof(aint));
                     inc(href.offset,sizeof(aint));
                   end;
                   end;
-                include(rg[R_INTREGISTER].preserved_by_proc,saved_standard_registers[r]);
+                include(rg[R_INTREGISTER].preserved_by_proc,regs_to_save_int[r]);
               end;
               end;
 
 
             if uses_registers(R_ADDRESSREGISTER) then
             if uses_registers(R_ADDRESSREGISTER) then
-              for r:=low(saved_address_registers) to high(saved_address_registers) do
+              for r:=low(regs_to_save_address) to high(regs_to_save_address) do
                 begin
                 begin
-                  if saved_address_registers[r] in rg[R_ADDRESSREGISTER].used_in_proc then
+                  if regs_to_save_address[r] in rg[R_ADDRESSREGISTER].used_in_proc then
                     begin
                     begin
-                      a_load_reg_ref(list,OS_ADDR,OS_ADDR,newreg(R_ADDRESSREGISTER,saved_address_registers[r],R_SUBWHOLE),href);
+                      a_load_reg_ref(list,OS_ADDR,OS_ADDR,newreg(R_ADDRESSREGISTER,regs_to_save_address[r],R_SUBWHOLE),href);
                       inc(href.offset,sizeof(aint));
                       inc(href.offset,sizeof(aint));
                     end;
                     end;
-                  include(rg[R_ADDRESSREGISTER].preserved_by_proc,saved_address_registers[r]);
+                  include(rg[R_ADDRESSREGISTER].preserved_by_proc,regs_to_save_address[r]);
                 end;
                 end;
 
 
             if uses_registers(R_MMREGISTER) then
             if uses_registers(R_MMREGISTER) then
@@ -2580,20 +2586,20 @@ implementation
                 if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
                 if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
                   inc(href.offset,tcgsize2size[OS_VECTOR]-(href.offset mod tcgsize2size[OS_VECTOR]));
                   inc(href.offset,tcgsize2size[OS_VECTOR]-(href.offset mod tcgsize2size[OS_VECTOR]));
 
 
-                for r:=low(saved_mm_registers) to high(saved_mm_registers) do
+                for r:=low(regs_to_save_mm) to high(regs_to_save_mm) do
                   begin
                   begin
                     { the array has to be declared even if no MM registers are saved
                     { the array has to be declared even if no MM registers are saved
                       (such as with SSE on i386), and since 0-element arrays don't
                       (such as with SSE on i386), and since 0-element arrays don't
                       exist, they contain a single RS_INVALID element in that case
                       exist, they contain a single RS_INVALID element in that case
                     }
                     }
-                    if saved_mm_registers[r]<>RS_INVALID then
+                    if regs_to_save_mm[r]<>RS_INVALID then
                       begin
                       begin
-                        if saved_mm_registers[r] in rg[R_MMREGISTER].used_in_proc then
+                        if regs_to_save_mm[r] in rg[R_MMREGISTER].used_in_proc then
                           begin
                           begin
-                            a_loadmm_reg_ref(list,OS_VECTOR,OS_VECTOR,newreg(R_MMREGISTER,saved_mm_registers[r],R_SUBMMWHOLE),href,nil);
+                            a_loadmm_reg_ref(list,OS_VECTOR,OS_VECTOR,newreg(R_MMREGISTER,regs_to_save_mm[r],R_SUBMMWHOLE),href,nil);
                             inc(href.offset,tcgsize2size[OS_VECTOR]);
                             inc(href.offset,tcgsize2size[OS_VECTOR]);
                           end;
                           end;
-                        include(rg[R_MMREGISTER].preserved_by_proc,saved_mm_registers[r]);
+                        include(rg[R_MMREGISTER].preserved_by_proc,regs_to_save_mm[r]);
                       end;
                       end;
                   end;
                   end;
               end;
               end;
@@ -2606,15 +2612,21 @@ implementation
         href     : treference;
         href     : treference;
         r        : integer;
         r        : integer;
         hreg     : tregister;
         hreg     : tregister;
+        regs_to_save_int,
+        regs_to_save_address,
+        regs_to_save_mm : tcpuregisterarray;
       begin
       begin
         if not(pi_has_saved_regs in current_procinfo.flags) then
         if not(pi_has_saved_regs in current_procinfo.flags) then
           exit;
           exit;
+        regs_to_save_int:=paramanager.get_saved_registers_int(current_procinfo.procdef.proccalloption);
+        regs_to_save_address:=paramanager.get_saved_registers_address(current_procinfo.procdef.proccalloption);
+        regs_to_save_mm:=paramanager.get_saved_registers_mm(current_procinfo.procdef.proccalloption);
         { Copy registers from temp }
         { Copy registers from temp }
         href:=current_procinfo.save_regs_ref;
         href:=current_procinfo.save_regs_ref;
-        for r:=low(saved_standard_registers) to high(saved_standard_registers) do
-          if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+        for r:=low(regs_to_save_int) to high(regs_to_save_int) do
+          if regs_to_save_int[r] in rg[R_INTREGISTER].used_in_proc then
             begin
             begin
-              hreg:=newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE);
+              hreg:=newreg(R_INTREGISTER,regs_to_save_int[r],R_SUBWHOLE);
               { Allocate register so the optimizer does not remove the load }
               { Allocate register so the optimizer does not remove the load }
               a_reg_alloc(list,hreg);
               a_reg_alloc(list,hreg);
               a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,hreg);
               a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,hreg);
@@ -2622,10 +2634,10 @@ implementation
             end;
             end;
 
 
         if uses_registers(R_ADDRESSREGISTER) then
         if uses_registers(R_ADDRESSREGISTER) then
-          for r:=low(saved_address_registers) to high(saved_address_registers) do
-            if saved_address_registers[r] in rg[R_ADDRESSREGISTER].used_in_proc then
+          for r:=low(regs_to_save_address) to high(regs_to_save_address) do
+            if regs_to_save_address[r] in rg[R_ADDRESSREGISTER].used_in_proc then
               begin
               begin
-                hreg:=newreg(R_ADDRESSREGISTER,saved_address_registers[r],R_SUBWHOLE);
+                hreg:=newreg(R_ADDRESSREGISTER,regs_to_save_address[r],R_SUBWHOLE);
                 { Allocate register so the optimizer does not remove the load }
                 { Allocate register so the optimizer does not remove the load }
                 a_reg_alloc(list,hreg);
                 a_reg_alloc(list,hreg);
                 a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,hreg);
                 a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,hreg);
@@ -2637,11 +2649,11 @@ implementation
             if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
             if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
               inc(href.offset,tcgsize2size[OS_VECTOR]-(href.offset mod tcgsize2size[OS_VECTOR]));
               inc(href.offset,tcgsize2size[OS_VECTOR]-(href.offset mod tcgsize2size[OS_VECTOR]));
 
 
-            for r:=low(saved_mm_registers) to high(saved_mm_registers) do
+            for r:=low(regs_to_save_mm) to high(regs_to_save_mm) do
               begin
               begin
-                if saved_mm_registers[r] in rg[R_MMREGISTER].used_in_proc then
+                if regs_to_save_mm[r] in rg[R_MMREGISTER].used_in_proc then
                   begin
                   begin
-                    hreg:=newreg(R_MMREGISTER,saved_mm_registers[r],R_SUBMMWHOLE);
+                    hreg:=newreg(R_MMREGISTER,regs_to_save_mm[r],R_SUBMMWHOLE);
                     { Allocate register so the optimizer does not remove the load }
                     { Allocate register so the optimizer does not remove the load }
                     a_reg_alloc(list,hreg);
                     a_reg_alloc(list,hreg);
                     a_loadmm_ref_reg(list,OS_VECTOR,OS_VECTOR,href,hreg,nil);
                     a_loadmm_ref_reg(list,OS_VECTOR,OS_VECTOR,href,hreg,nil);

+ 1 - 0
compiler/cgutils.pas

@@ -42,6 +42,7 @@ unit cgutils;
     type
     type
       { Set type definition for cpuregisters }
       { Set type definition for cpuregisters }
       tcpuregisterset = set of 0..maxcpuregister;
       tcpuregisterset = set of 0..maxcpuregister;
+      tcpuregisterarray = array of tsuperregister;
 
 
 {$packset 1}
 {$packset 1}
       { a reference may be volatile for reading, writing, or both. E.g., local variables
       { a reference may be volatile for reading, writing, or both. E.g., local variables

+ 0 - 11
compiler/i386/cpubase.inc

@@ -131,17 +131,6 @@
 *****************************************************************************}
 *****************************************************************************}
 
 
     const
     const
-      {# Registers which must be saved when calling a routine declared as
-         cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
-         saved should be the ones as defined in the target ABI and / or GCC.
-
-         This value can be deduced from the CALLED_USED_REGISTERS array in the
-         GCC source.
-      }
-      saved_standard_registers : array[0..3] of tsuperregister = (RS_EBX,RS_ESI,RS_EDI,RS_EBP);
-
-      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
-      saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
       {# Required parameter alignment when calling a routine declared as
       {# Required parameter alignment when calling a routine declared as
          stdcall and cdecl. The alignment value should be the one defined
          stdcall and cdecl. The alignment value should be the one defined
          by GCC or the target ABI.
          by GCC or the target ABI.

+ 9 - 0
compiler/i386/cpupara.pas

@@ -40,6 +40,7 @@ unit cpupara;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
+          function get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;override;
           function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
           function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
           function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
           function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
           procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
           procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
@@ -286,6 +287,14 @@ unit cpupara;
       end;
       end;
 
 
 
 
+    function tcpuparamanager.get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;
+      const
+        saveregs : array[0..3] of tsuperregister = (RS_EBX,RS_ESI,RS_EDI,RS_EBP);
+      begin
+        result:=saveregs;
+      end;
+
+
     function  tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;
     function  tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;
       var
       var
         retcgsize  : tcgsize;
         retcgsize  : tcgsize;

+ 0 - 11
compiler/i8086/cpubase.inc

@@ -150,17 +150,6 @@
 *****************************************************************************}
 *****************************************************************************}
 
 
     const
     const
-      {# Registers which must be saved when calling a routine declared as
-         cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
-         saved should be the ones as defined in the target ABI and / or GCC.
-
-         This value can be deduced from the CALLED_USED_REGISTERS array in the
-         GCC source.
-      }
-      saved_standard_registers : array[0..0] of tsuperregister = (RS_BP);
-
-      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
-      saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
       {# Required parameter alignment when calling a routine declared as
       {# Required parameter alignment when calling a routine declared as
          stdcall and cdecl. The alignment value should be the one defined
          stdcall and cdecl. The alignment value should be the one defined
          by GCC or the target ABI.
          by GCC or the target ABI.

+ 9 - 0
compiler/i8086/cpupara.pas

@@ -41,6 +41,7 @@ unit cpupara;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
+          function get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;override;
           { Returns the location for the nr-st 16 Bit int parameter
           { Returns the location for the nr-st 16 Bit int parameter
             if every parameter before is an 16 Bit int parameter as well
             if every parameter before is an 16 Bit int parameter as well
             and if the calling conventions for the helper routines of the
             and if the calling conventions for the helper routines of the
@@ -236,6 +237,14 @@ unit cpupara;
       end;
       end;
 
 
 
 
+    function tcpuparamanager.get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;
+      const
+        saveregs_pascal: array [0..0] of tsuperregister = (RS_BP);
+      begin
+        result:=saveregs_pascal;
+      end;
+
+
     procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
     procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;

+ 0 - 11
compiler/jvm/cpubase.pas

@@ -255,17 +255,6 @@ uses
 
 
       { dummies, not used for JVM }
       { dummies, not used for JVM }
 
 
-      {# Registers which must be saved when calling a routine
-
-      }
-      saved_standard_registers : array[0..0] of tsuperregister = (
-        RS_NO
-      );
-
-      { this is only for the generic code which is not used for this architecture }
-      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
-      saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
-
       {# Required parameter alignment when calling a routine
       {# Required parameter alignment when calling a routine
       }
       }
       std_param_align = 1;
       std_param_align = 1;

+ 9 - 0
compiler/jvm/cpupara.pas

@@ -35,6 +35,7 @@ interface
       { tcpuparamanager }
       { tcpuparamanager }
 
 
       tcpuparamanager=class(TParaManager)
       tcpuparamanager=class(TParaManager)
+        function  get_saved_registers_int(calloption: tproccalloption): tcpuregisterarray;override;
         function  push_high_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
         function  push_high_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
         function  keep_para_array_range(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean; override;
         function  keep_para_array_range(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean; override;
         function  push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
         function  push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
@@ -70,6 +71,14 @@ implementation
         internalerror(2010121001);
         internalerror(2010121001);
       end;
       end;
 
 
+    function tcpuparamanager.get_saved_registers_int(calloption: tproccalloption): tcpuregisterarray;
+      const
+        { dummy, not used for JVM }
+        saved_regs: array [0..0] of tsuperregister = (RS_NO);
+      begin
+        result:=saved_regs;
+      end;
+
     function tcpuparamanager.push_high_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean;
     function tcpuparamanager.push_high_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean;
       begin
       begin
         { we don't need a separate high parameter, since all arrays in Java
         { we don't need a separate high parameter, since all arrays in Java

+ 36 - 24
compiler/m68k/cgcpu.pas

@@ -1963,6 +1963,9 @@ unit cgcpu;
         size : longint;
         size : longint;
         fsize : longint;
         fsize : longint;
         r : integer;
         r : integer;
+        regs_to_save_int,
+        regs_to_save_address,
+        regs_to_save_fpu: tcpuregisterarray;
       begin
       begin
         { The code generated by the section below, particularly the movem.l
         { The code generated by the section below, particularly the movem.l
           instruction is known to cause an issue when compiled by some GNU 
           instruction is known to cause an issue when compiled by some GNU 
@@ -1974,33 +1977,36 @@ unit cgcpu;
         addrregs:=[];
         addrregs:=[];
         fpuregs:=[];
         fpuregs:=[];
 
 
+        regs_to_save_int:=paramanager.get_saved_registers_int(current_procinfo.procdef.proccalloption);
+        regs_to_save_address:=paramanager.get_saved_registers_address(current_procinfo.procdef.proccalloption);
+        regs_to_save_fpu:=paramanager.get_saved_registers_fpu(current_procinfo.procdef.proccalloption);
         { calculate temp. size }
         { calculate temp. size }
         size:=0;
         size:=0;
         fsize:=0;
         fsize:=0;
         hreg:=NR_NO;
         hreg:=NR_NO;
         hfreg:=NR_NO;
         hfreg:=NR_NO;
-        for r:=low(saved_standard_registers) to high(saved_standard_registers) do
-          if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+        for r:=low(regs_to_save_int) to high(regs_to_save_int) do
+          if regs_to_save_int[r] in rg[R_INTREGISTER].used_in_proc then
             begin
             begin
-              hreg:=newreg(R_INTREGISTER,saved_address_registers[r],R_SUBWHOLE);
+              hreg:=newreg(R_INTREGISTER,regs_to_save_int[r],R_SUBWHOLE);
               inc(size,sizeof(aint));
               inc(size,sizeof(aint));
-              dataregs:=dataregs + [saved_standard_registers[r]];
+              dataregs:=dataregs + [regs_to_save_int[r]];
             end;
             end;
         if uses_registers(R_ADDRESSREGISTER) then
         if uses_registers(R_ADDRESSREGISTER) then
-          for r:=low(saved_address_registers) to high(saved_address_registers) do
-            if saved_address_registers[r] in rg[R_ADDRESSREGISTER].used_in_proc then
+          for r:=low(regs_to_save_address) to high(regs_to_save_address) do
+            if regs_to_save_address[r] in rg[R_ADDRESSREGISTER].used_in_proc then
               begin
               begin
-                hreg:=newreg(R_ADDRESSREGISTER,saved_address_registers[r],R_SUBWHOLE);
+                hreg:=newreg(R_ADDRESSREGISTER,regs_to_save_address[r],R_SUBWHOLE);
                 inc(size,sizeof(aint));
                 inc(size,sizeof(aint));
-                addrregs:=addrregs + [saved_address_registers[r]];
+                addrregs:=addrregs + [regs_to_save_address[r]];
               end;
               end;
         if uses_registers(R_FPUREGISTER) then
         if uses_registers(R_FPUREGISTER) then
-          for r:=low(saved_fpu_registers) to high(saved_fpu_registers) do
-            if saved_fpu_registers[r] in rg[R_FPUREGISTER].used_in_proc then
+          for r:=low(regs_to_save_fpu) to high(regs_to_save_fpu) do
+            if regs_to_save_fpu[r] in rg[R_FPUREGISTER].used_in_proc then
               begin
               begin
-                hfreg:=newreg(R_FPUREGISTER,saved_fpu_registers[r],R_SUBNONE);
+                hfreg:=newreg(R_FPUREGISTER,regs_to_save_fpu[r],R_SUBNONE);
                 inc(fsize,fpuregsize);
                 inc(fsize,fpuregsize);
-                fpuregs:=fpuregs + [saved_fpu_registers[r]];
+                fpuregs:=fpuregs + [regs_to_save_fpu[r]];
               end;
               end;
 
 
         { 68k has no MM registers }
         { 68k has no MM registers }
@@ -2052,6 +2058,9 @@ unit cgcpu;
         hfreg   : tregister;
         hfreg   : tregister;
         size    : longint;
         size    : longint;
         fsize   : longint;
         fsize   : longint;
+        regs_to_save_int,
+        regs_to_save_address,
+        regs_to_save_fpu: tcpuregisterarray;
       begin
       begin
         { see the remark about buggy GNU AS versions in g_save_registers() (KB) }
         { see the remark about buggy GNU AS versions in g_save_registers() (KB) }
         dataregs:=[];
         dataregs:=[];
@@ -2060,41 +2069,44 @@ unit cgcpu;
 
 
         if not(pi_has_saved_regs in current_procinfo.flags) then
         if not(pi_has_saved_regs in current_procinfo.flags) then
           exit;
           exit;
+        regs_to_save_int:=paramanager.get_saved_registers_int(current_procinfo.procdef.proccalloption);
+        regs_to_save_address:=paramanager.get_saved_registers_address(current_procinfo.procdef.proccalloption);
+        regs_to_save_fpu:=paramanager.get_saved_registers_fpu(current_procinfo.procdef.proccalloption);
         { Copy registers from temp }
         { Copy registers from temp }
         size:=0;
         size:=0;
         fsize:=0;
         fsize:=0;
         hreg:=NR_NO;
         hreg:=NR_NO;
         hfreg:=NR_NO;
         hfreg:=NR_NO;
-        for r:=low(saved_standard_registers) to high(saved_standard_registers) do
-          if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+        for r:=low(regs_to_save_int) to high(regs_to_save_int) do
+          if regs_to_save_int[r] in rg[R_INTREGISTER].used_in_proc then
             begin
             begin
               inc(size,sizeof(aint));
               inc(size,sizeof(aint));
-              hreg:=newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE);
+              hreg:=newreg(R_INTREGISTER,regs_to_save_int[r],R_SUBWHOLE);
               { Allocate register so the optimizer does not remove the load }
               { Allocate register so the optimizer does not remove the load }
               a_reg_alloc(list,hreg);
               a_reg_alloc(list,hreg);
-              dataregs:=dataregs + [saved_standard_registers[r]];
+              dataregs:=dataregs + [regs_to_save_int[r]];
             end;
             end;
 
 
         if uses_registers(R_ADDRESSREGISTER) then
         if uses_registers(R_ADDRESSREGISTER) then
-          for r:=low(saved_address_registers) to high(saved_address_registers) do
-            if saved_address_registers[r] in rg[R_ADDRESSREGISTER].used_in_proc then
+          for r:=low(regs_to_save_address) to high(regs_to_save_address) do
+            if regs_to_save_address[r] in rg[R_ADDRESSREGISTER].used_in_proc then
               begin
               begin
                 inc(size,sizeof(aint));
                 inc(size,sizeof(aint));
-                hreg:=newreg(R_ADDRESSREGISTER,saved_address_registers[r],R_SUBWHOLE);
+                hreg:=newreg(R_ADDRESSREGISTER,regs_to_save_address[r],R_SUBWHOLE);
                 { Allocate register so the optimizer does not remove the load }
                 { Allocate register so the optimizer does not remove the load }
                 a_reg_alloc(list,hreg);
                 a_reg_alloc(list,hreg);
-                addrregs:=addrregs + [saved_address_registers[r]];
+                addrregs:=addrregs + [regs_to_save_address[r]];
               end;
               end;
 
 
         if uses_registers(R_FPUREGISTER) then
         if uses_registers(R_FPUREGISTER) then
-          for r:=low(saved_fpu_registers) to high(saved_fpu_registers) do
-            if saved_fpu_registers[r] in rg[R_FPUREGISTER].used_in_proc then
+          for r:=low(regs_to_save_fpu) to high(regs_to_save_fpu) do
+            if regs_to_save_fpu[r] in rg[R_FPUREGISTER].used_in_proc then
               begin
               begin
                 inc(fsize,fpuregsize);
                 inc(fsize,fpuregsize);
-                hfreg:=newreg(R_FPUREGISTER,saved_fpu_registers[r],R_SUBNONE);
+                hfreg:=newreg(R_FPUREGISTER,regs_to_save_fpu[r],R_SUBNONE);
                 { Allocate register so the optimizer does not remove the load }
                 { Allocate register so the optimizer does not remove the load }
                 a_reg_alloc(list,hfreg);
                 a_reg_alloc(list,hfreg);
-                fpuregs:=fpuregs + [saved_fpu_registers[r]];
+                fpuregs:=fpuregs + [regs_to_save_fpu[r]];
               end;
               end;
 
 
         { 68k has no MM registers }
         { 68k has no MM registers }

+ 0 - 14
compiler/m68k/cpubase.pas

@@ -320,20 +320,6 @@ unit cpubase;
                        GCC /ABI linking information
                        GCC /ABI linking information
 *****************************************************************************}
 *****************************************************************************}
 
 
-      {# Registers which must be saved when calling a routine declared as
-         cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
-         saved should be the ones as defined in the target ABI and / or GCC.
-
-         This value can be deduced from CALLED_USED_REGISTERS array in the
-         GCC source.
-      }
-      saved_standard_registers : array[0..5] of tsuperregister = (RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7);
-      saved_address_registers : array[0..4] of tsuperregister = (RS_A2,RS_A3,RS_A4,RS_A5,RS_A6);
-      saved_fpu_registers : array[0..5] of tsuperregister = (RS_FP2,RS_FP3,RS_FP4,RS_FP5,RS_FP6,RS_FP7);
-
-      { this is only for the generic code which is not used for this architecture }
-      saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
-
       {# Required parameter alignment when calling a routine declared as
       {# Required parameter alignment when calling a routine declared as
          stdcall and cdecl. The alignment value should be the one defined
          stdcall and cdecl. The alignment value should be the one defined
          by GCC or the target ABI.
          by GCC or the target ABI.

+ 24 - 0
compiler/m68k/cpupara.pas

@@ -50,6 +50,9 @@ unit cpupara;
           function get_volatile_registers_int(calloption:tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_int(calloption:tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_address(calloption:tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_address(calloption:tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption:tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption:tproccalloption):tcpuregisterset;override;
+          function get_saved_registers_int(calloption:tproccalloption):tcpuregisterarray;override;
+          function get_saved_registers_address(calloption:tproccalloption):tcpuregisterarray;override;
+          function get_saved_registers_fpu(calloption:tproccalloption):tcpuregisterarray;override;
           function get_para_align(calloption : tproccalloption):byte;override;
           function get_para_align(calloption : tproccalloption):byte;override;
          private
          private
           function parse_loc_string_to_register(var locreg: tregister; const s : string): boolean;
           function parse_loc_string_to_register(var locreg: tregister; const s : string): boolean;
@@ -99,6 +102,27 @@ unit cpupara;
         Result:=VOLATILE_FPUREGISTERS;
         Result:=VOLATILE_FPUREGISTERS;
       end;
       end;
 
 
+    function tcpuparamanager.get_saved_registers_int(calloption:tproccalloption):tcpuregisterarray;
+      const
+        saved_regs: array[0..5] of tsuperregister = (RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7);
+      begin
+        result:=saved_regs;
+      end;
+
+    function tcpuparamanager.get_saved_registers_address(calloption:tproccalloption):tcpuregisterarray;
+      const
+        saved_addr_regs: array[0..4] of tsuperregister = (RS_A2,RS_A3,RS_A4,RS_A5,RS_A6);
+      begin
+        result:=saved_addr_regs;
+      end;
+
+    function tcpuparamanager.get_saved_registers_fpu(calloption:tproccalloption):tcpuregisterarray;
+      const
+        saved_fpu_regs: array[0..5] of tsuperregister = (RS_FP2,RS_FP3,RS_FP4,RS_FP5,RS_FP6,RS_FP7);
+      begin
+        result:=saved_fpu_regs;
+      end;
+
     function tcpuparamanager.get_para_align(calloption : tproccalloption):byte;
     function tcpuparamanager.get_para_align(calloption : tproccalloption):byte;
       begin
       begin
         result:=target_info.stackalign;
         result:=target_info.stackalign;

+ 0 - 14
compiler/mips/cpubase.pas

@@ -238,20 +238,6 @@ unit cpubase;
 *****************************************************************************}
 *****************************************************************************}
 
 
     const
     const
-      { Registers which must be saved when calling a routine declared as
-        cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
-        saved should be the ones as defined in the target ABI and / or GCC.
-
-        This value can be deduced from the CALLED_USED_REGISTERS array in the
-        GCC source.
-      }
-      saved_standard_registers : array[0..0] of tsuperregister =
-        (RS_NO);
-
-      { this is only for the generic code which is not used for this architecture }
-      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
-      saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
-
       { Required parameter alignment when calling a routine declared as
       { Required parameter alignment when calling a routine declared as
         stdcall and cdecl. The alignment value should be the one defined
         stdcall and cdecl. The alignment value should be the one defined
         by GCC or the target ABI.
         by GCC or the target ABI.

+ 10 - 0
compiler/mips/cpupara.pas

@@ -71,6 +71,7 @@ interface
         function  push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
         function  push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
         function  get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
         function  get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
         function  get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
         function  get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
+        function  get_saved_registers_int(calloption : tproccalloption):TCpuRegisterArray;override;
         function  create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
         function  create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
         function  create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override;
         function  create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override;
         function  get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
         function  get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
@@ -106,6 +107,15 @@ implementation
       end;
       end;
 
 
 
 
+    function tcpuparamanager.get_saved_registers_int(calloption : tproccalloption):TCpuRegisterArray;
+      const
+        saved_regs : array[0..0] of tsuperregister =
+          (RS_NO);
+      begin
+        result:=saved_regs;
+      end;
+
+
     { whether "def" must be treated as record when used as function result,
     { whether "def" must be treated as record when used as function result,
       i.e. its address passed in a0 }
       i.e. its address passed in a0 }
     function tcpuparamanager.is_abi_record(def: tdef): boolean;
     function tcpuparamanager.is_abi_record(def: tdef): boolean;

+ 43 - 0
compiler/paramgr.pas

@@ -82,6 +82,17 @@ unit paramgr;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;virtual;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;virtual;
           function get_volatile_registers_flags(calloption : tproccalloption):tcpuregisterset;virtual;
           function get_volatile_registers_flags(calloption : tproccalloption):tcpuregisterset;virtual;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;virtual;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;virtual;
+          {# Registers which must be saved when calling a routine declared as
+            cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+            saved should be the ones as defined in the target ABI and / or GCC.
+
+            This value can be deduced from the CALLED_USED_REGISTERS array in the
+            GCC source.
+          }
+          function get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;virtual;
+          function get_saved_registers_address(calloption : tproccalloption):tcpuregisterarray;virtual;
+          function get_saved_registers_fpu(calloption : tproccalloption):tcpuregisterarray;virtual;
+          function get_saved_registers_mm(calloption : tproccalloption):tcpuregisterarray;virtual;
 
 
           procedure getintparaloc(list: TAsmList; pd: tabstractprocdef; nr : longint; var cgpara: tcgpara);virtual;
           procedure getintparaloc(list: TAsmList; pd: tabstractprocdef; nr : longint; var cgpara: tcgpara);virtual;
 
 
@@ -299,6 +310,38 @@ implementation
         result:=[];
         result:=[];
       end;
       end;
 
 
+
+    function tparamanager.get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;
+      const
+        inv: array [0..0] of tsuperregister = (RS_INVALID);
+      begin
+        result:=inv;
+      end;
+
+
+    function tparamanager.get_saved_registers_address(calloption : tproccalloption):tcpuregisterarray;
+      const
+        inv: array [0..0] of tsuperregister = (RS_INVALID);
+      begin
+        result:=inv;
+      end;
+
+
+    function tparamanager.get_saved_registers_fpu(calloption : tproccalloption):tcpuregisterarray;
+      const
+        inv: array [0..0] of tsuperregister = (RS_INVALID);
+      begin
+        result:=inv;
+      end;
+
+
+    function tparamanager.get_saved_registers_mm(calloption : tproccalloption):tcpuregisterarray;
+      const
+        inv: array [0..0] of tsuperregister = (RS_INVALID);
+      begin
+        result:=inv;
+      end;
+
 {$if first_mm_imreg = 0}
 {$if first_mm_imreg = 0}
   {$WARN 4044 OFF} { Comparison might be always false ... }
   {$WARN 4044 OFF} { Comparison might be always false ... }
 {$endif}
 {$endif}

+ 0 - 17
compiler/powerpc/cpubase.pas

@@ -338,23 +338,6 @@ uses
                        GCC /ABI linking information
                        GCC /ABI linking information
 *****************************************************************************}
 *****************************************************************************}
 
 
-      {# Registers which must be saved when calling a routine declared as
-         cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
-         saved should be the ones as defined in the target ABI and / or GCC.
-
-         This value can be deduced from CALLED_USED_REGISTERS array in the
-         GCC source.
-      }
-      saved_standard_registers : array[0..18] of tsuperregister = (
-        RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
-        RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25,RS_R26,RS_R27,RS_R28,RS_R29,
-        RS_R30,RS_R31
-      );
-
-      { this is only for the generic code which is not used for this architecture }
-      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
-      saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
-
       {# Required parameter alignment when calling a routine declared as
       {# Required parameter alignment when calling a routine declared as
          stdcall and cdecl. The alignment value should be the one defined
          stdcall and cdecl. The alignment value should be the one defined
          by GCC or the target ABI.
          by GCC or the target ABI.

+ 13 - 0
compiler/powerpc/cpupara.pas

@@ -35,6 +35,7 @@ unit cpupara;
        tcpuparamanager = class(tparamanager)
        tcpuparamanager = class(tparamanager)
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+          function get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;override;
           function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
           function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
 
 
           procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
           procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
@@ -78,6 +79,18 @@ unit cpupara;
       end;
       end;
 
 
 
 
+    function tcpuparamanager.get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;
+      const
+        saved_regs : array[0..18] of tsuperregister = (
+          RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
+          RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25,RS_R26,RS_R27,RS_R28,RS_R29,
+          RS_R30,RS_R31
+        );
+      begin
+        result:=saved_regs;
+      end;
+
+
     procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
     procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;

+ 0 - 17
compiler/powerpc64/cpubase.pas

@@ -332,23 +332,6 @@ const
                          GCC /ABI linking information
                          GCC /ABI linking information
   *****************************************************************************}
   *****************************************************************************}
 
 
-  {# Registers which must be saved when calling a routine declared as
-     cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
-     saved should be the ones as defined in the target ABI and / or GCC.
-
-     This value can be deduced from CALLED_USED_REGISTERS array in the
-     GCC source.
-  }
-  saved_standard_registers: array[0..17] of tsuperregister = (
-    RS_R14, RS_R15, RS_R16, RS_R17, RS_R18, RS_R19,
-    RS_R20, RS_R21, RS_R22, RS_R23, RS_R24, RS_R25,
-    RS_R26, RS_R27, RS_R28, RS_R29, RS_R30, RS_R31
-    );
-
-  { this is only for the generic code which is not used for this architecture }
-  saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
-  saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
-  
   {# Required parameter alignment when calling a routine declared as
   {# Required parameter alignment when calling a routine declared as
      stdcall and cdecl. The alignment value should be the one defined
      stdcall and cdecl. The alignment value should be the one defined
      by GCC or the target ABI.
      by GCC or the target ABI.

+ 14 - 0
compiler/powerpc64/cpupara.pas

@@ -37,6 +37,8 @@ type
       tcpuregisterset; override;
       tcpuregisterset; override;
     function get_volatile_registers_fpu(calloption: tproccalloption):
     function get_volatile_registers_fpu(calloption: tproccalloption):
       tcpuregisterset; override;
       tcpuregisterset; override;
+    function get_saved_registers_int(calloption: tproccalloption):
+      tcpuregisterarray; override;
     function push_addr_param(varspez: tvarspez; def: tdef; calloption:
     function push_addr_param(varspez: tvarspez; def: tdef; calloption:
       tproccalloption): boolean; override;
       tproccalloption): boolean; override;
     function ret_in_param(def: tdef; pd: tabstractprocdef): boolean; override;
     function ret_in_param(def: tdef; pd: tabstractprocdef): boolean; override;
@@ -79,6 +81,18 @@ begin
   result := [RS_F0..RS_F13];
   result := [RS_F0..RS_F13];
 end;
 end;
 
 
+function tcpuparamanager.get_saved_registers_int(calloption: tproccalloption):
+  tcpuregisterarray;
+const
+  saved_regs: array[0..17] of tsuperregister = (
+    RS_R14, RS_R15, RS_R16, RS_R17, RS_R18, RS_R19,
+    RS_R20, RS_R21, RS_R22, RS_R23, RS_R24, RS_R25,
+    RS_R26, RS_R27, RS_R28, RS_R29, RS_R30, RS_R31
+    );
+begin
+  result:=saved_regs;
+end;
+
 procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr: longint; var cgpara: tcgpara);
 procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr: longint; var cgpara: tcgpara);
 var
 var
   paraloc: pcgparalocation;
   paraloc: pcgparalocation;

+ 0 - 13
compiler/sparcgen/cpubase.pas

@@ -305,19 +305,6 @@ uses
                        GCC /ABI linking information
                        GCC /ABI linking information
 *****************************************************************************}
 *****************************************************************************}
 
 
-      {# Registers which must be saved when calling a routine declared as
-         cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
-         saved should be the ones as defined in the target ABI and / or GCC.
-
-         This value can be deduced from CALLED_USED_REGISTERS array in the
-         GCC source.
-      }
-      saved_standard_registers : array[0..0] of tsuperregister = (RS_INVALID);
-
-      { this is only for the generic code which is not used for this architecture }
-      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
-      saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
-
       {# Required parameter alignment when calling a routine declared as
       {# Required parameter alignment when calling a routine declared as
          stdcall and cdecl. The alignment value should be the one defined
          stdcall and cdecl. The alignment value should be the one defined
          by GCC or the target ABI.
          by GCC or the target ABI.

+ 10 - 6
compiler/x86/cgx86.pas

@@ -3294,14 +3294,16 @@ unit cgx86;
         var
         var
           r: longint;
           r: longint;
           usedregs: tcpuregisterset;
           usedregs: tcpuregisterset;
+          regs_to_save_int: tcpuregisterarray;
         begin
         begin
           regsize:=0;
           regsize:=0;
           usedregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
           usedregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
-          for r := low(saved_standard_registers) to high(saved_standard_registers) do
-            if saved_standard_registers[r] in usedregs then
+          regs_to_save_int:=paramanager.get_saved_registers_int(current_procinfo.procdef.proccalloption);
+          for r := low(regs_to_save_int) to high(regs_to_save_int) do
+            if regs_to_save_int[r] in usedregs then
               begin
               begin
                 inc(regsize,sizeof(aint));
                 inc(regsize,sizeof(aint));
-                list.concat(Taicpu.Op_reg(A_PUSH,tcgsize2opsize[OS_ADDR],newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE)));
+                list.concat(Taicpu.Op_reg(A_PUSH,tcgsize2opsize[OS_ADDR],newreg(R_INTREGISTER,regs_to_save_int[r],R_SUBWHOLE)));
               end;
               end;
         end;
         end;
 
 
@@ -3572,13 +3574,15 @@ unit cgx86;
         hreg: tregister;
         hreg: tregister;
         href: treference;
         href: treference;
         usedregs: tcpuregisterset;
         usedregs: tcpuregisterset;
+        regs_to_save_int: tcpuregisterarray;
       begin
       begin
         href:=current_procinfo.save_regs_ref;
         href:=current_procinfo.save_regs_ref;
         usedregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
         usedregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
-        for r:=high(saved_standard_registers) downto low(saved_standard_registers) do
-          if saved_standard_registers[r] in usedregs then
+        regs_to_save_int:=paramanager.get_saved_registers_int(current_procinfo.procdef.proccalloption);
+        for r:=high(regs_to_save_int) downto low(regs_to_save_int) do
+          if regs_to_save_int[r] in usedregs then
             begin
             begin
-              hreg:=newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE);
+              hreg:=newreg(R_INTREGISTER,regs_to_save_int[r],R_SUBWHOLE);
               { Allocate register so the optimizer does not remove the load }
               { Allocate register so the optimizer does not remove the load }
               a_reg_alloc(list,hreg);
               a_reg_alloc(list,hreg);
               if use_pop then
               if use_pop then

+ 25 - 47
compiler/x86_64/cgcpu.pas

@@ -65,42 +65,12 @@ unit cgcpu;
 
 
 
 
     procedure Tcgx86_64.init_register_allocators;
     procedure Tcgx86_64.init_register_allocators;
-      const
-        win64_saved_std_regs : array[0..7] of tsuperregister = (RS_RBX,RS_RDI,RS_RSI,RS_R12,RS_R13,RS_R14,RS_R15,RS_RBP);
-        others_saved_std_regs : array[0..4] of tsuperregister = (RS_RBX,RS_R12,RS_R13,RS_R14,RS_R15);
-        saved_regs_length : array[boolean] of longint = (5,7);
-
-        win64_saved_xmm_regs : array[0..9] of tsuperregister = (RS_XMM6,RS_XMM7,
-          RS_XMM8,RS_XMM9,RS_XMM10,RS_XMM11,RS_XMM12,RS_XMM13,RS_XMM14,RS_XMM15);
       var
       var
-        i : longint;
         ms_abi: boolean;
         ms_abi: boolean;
       begin
       begin
         inherited init_register_allocators;
         inherited init_register_allocators;
 
 
         ms_abi:=use_ms_abi;
         ms_abi:=use_ms_abi;
-        if (length(saved_standard_registers)<>saved_regs_length[ms_abi]) then
-          begin
-            if ms_abi then
-              begin
-                SetLength(saved_standard_registers,Length(win64_saved_std_regs));
-                SetLength(saved_mm_registers,Length(win64_saved_xmm_regs));
-
-                for i:=low(win64_saved_std_regs) to high(win64_saved_std_regs) do
-                  saved_standard_registers[i]:=win64_saved_std_regs[i];
-
-                for i:=low(win64_saved_xmm_regs) to high(win64_saved_xmm_regs) do
-                  saved_mm_registers[i]:=win64_saved_xmm_regs[i];
-              end
-            else
-              begin
-                SetLength(saved_standard_registers,Length(others_saved_std_regs));
-                SetLength(saved_mm_registers,0);
-
-                for i:=low(others_saved_std_regs) to high(others_saved_std_regs) do
-                  saved_standard_registers[i]:=others_saved_std_regs[i];
-              end;
-          end;
         if ms_abi then
         if ms_abi then
           begin
           begin
             if (cs_userbp in current_settings.optimizerswitches) and assigned(current_procinfo) and (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
             if (cs_userbp in current_settings.optimizerswitches) and assigned(current_procinfo) and (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
@@ -156,14 +126,16 @@ unit cgcpu;
     function tcgx86_64.saved_xmm_reg_size: longint;
     function tcgx86_64.saved_xmm_reg_size: longint;
       var
       var
         i: longint;
         i: longint;
+        regs_to_save_mm: tcpuregisterarray;
       begin
       begin
         result:=0;
         result:=0;
         if (target_info.system<>system_x86_64_win64) or
         if (target_info.system<>system_x86_64_win64) or
            (not uses_registers(R_MMREGISTER)) then
            (not uses_registers(R_MMREGISTER)) then
           exit;
           exit;
-        for i:=low(saved_mm_registers) to high(saved_mm_registers) do
+        regs_to_save_mm:=paramanager.get_saved_registers_mm(current_procinfo.procdef.proccalloption);
+        for i:=low(regs_to_save_mm) to high(regs_to_save_mm) do
           begin
           begin
-            if (saved_mm_registers[i] in rg[R_MMREGISTER].used_in_proc) then
+            if (regs_to_save_mm[i] in rg[R_MMREGISTER].used_in_proc) then
               inc(result,tcgsize2size[OS_VECTOR]);
               inc(result,tcgsize2size[OS_VECTOR]);
           end;
           end;
       end;
       end;
@@ -180,6 +152,8 @@ unit cgcpu;
         suppress_endprologue: boolean;
         suppress_endprologue: boolean;
         stackmisalignment: longint;
         stackmisalignment: longint;
         xmmsize: longint;
         xmmsize: longint;
+        regs_to_save_int,
+        regs_to_save_mm: tcpuregisterarray;
 
 
       procedure push_one_reg(reg: tregister);
       procedure push_one_reg(reg: tregister);
         begin
         begin
@@ -197,15 +171,17 @@ unit cgcpu;
           usedregs: tcpuregisterset;
           usedregs: tcpuregisterset;
         begin
         begin
           usedregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
           usedregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
-          for r := low(saved_standard_registers) to high(saved_standard_registers) do
-            if saved_standard_registers[r] in usedregs then
+          for r := low(regs_to_save_int) to high(regs_to_save_int) do
+            if regs_to_save_int[r] in usedregs then
               begin
               begin
                 inc(stackmisalignment,sizeof(pint));
                 inc(stackmisalignment,sizeof(pint));
-                push_one_reg(newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE));
+                push_one_reg(newreg(R_INTREGISTER,regs_to_save_int[r],R_SUBWHOLE));
               end;
               end;
         end;
         end;
 
 
       begin
       begin
+        regs_to_save_int:=paramanager.get_saved_registers_int(current_procinfo.procdef.proccalloption);
+        regs_to_save_mm:=paramanager.get_saved_registers_mm(current_procinfo.procdef.proccalloption);
         hitem:=list.last;
         hitem:=list.last;
         { pi_has_unwind_info may already be set at this point if there are
         { pi_has_unwind_info may already be set at this point if there are
           SEH directives in assembler body. In this case, .seh_endprologue
           SEH directives in assembler body. In this case, .seh_endprologue
@@ -282,10 +258,10 @@ unit cgcpu;
                     if use_push and (xmmsize<>0) then
                     if use_push and (xmmsize<>0) then
                       begin
                       begin
                         href:=current_procinfo.save_regs_ref;
                         href:=current_procinfo.save_regs_ref;
-                        for r:=low(saved_mm_registers) to high(saved_mm_registers) do
-                          if saved_mm_registers[r] in rg[R_MMREGISTER].used_in_proc then
+                        for r:=low(regs_to_save_mm) to high(regs_to_save_mm) do
+                          if regs_to_save_mm[r] in rg[R_MMREGISTER].used_in_proc then
                             begin
                             begin
-                              a_loadmm_reg_ref(list,OS_VECTOR,OS_VECTOR,newreg(R_MMREGISTER,saved_mm_registers[r],R_SUBMMWHOLE),href,nil);
+                              a_loadmm_reg_ref(list,OS_VECTOR,OS_VECTOR,newreg(R_MMREGISTER,regs_to_save_mm[r],R_SUBMMWHOLE),href,nil);
                               inc(href.offset,tcgsize2size[OS_VECTOR]);
                               inc(href.offset,tcgsize2size[OS_VECTOR]);
                             end;
                             end;
                       end;
                       end;
@@ -316,11 +292,11 @@ unit cgcpu;
         href:=current_procinfo.save_regs_ref;
         href:=current_procinfo.save_regs_ref;
         if (not use_push) then
         if (not use_push) then
           begin
           begin
-            for r:=low(saved_standard_registers) to high(saved_standard_registers) do
-              if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+            for r:=low(regs_to_save_int) to high(regs_to_save_int) do
+              if regs_to_save_int[r] in rg[R_INTREGISTER].used_in_proc then
                 begin
                 begin
                   templist.concat(cai_seh_directive.create_reg_offset(ash_savereg,
                   templist.concat(cai_seh_directive.create_reg_offset(ash_savereg,
-                    newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE),
+                    newreg(R_INTREGISTER,regs_to_save_int[r],R_SUBWHOLE),
                     href.offset+frame_offset));
                     href.offset+frame_offset));
                  inc(href.offset,sizeof(aint));
                  inc(href.offset,sizeof(aint));
                 end;
                 end;
@@ -330,12 +306,12 @@ unit cgcpu;
             if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
             if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
               inc(href.offset,tcgsize2size[OS_VECTOR]-(href.offset mod tcgsize2size[OS_VECTOR]));
               inc(href.offset,tcgsize2size[OS_VECTOR]-(href.offset mod tcgsize2size[OS_VECTOR]));
 
 
-            for r:=low(saved_mm_registers) to high(saved_mm_registers) do
+            for r:=low(regs_to_save_mm) to high(regs_to_save_mm) do
               begin
               begin
-                if saved_mm_registers[r] in rg[R_MMREGISTER].used_in_proc then
+                if regs_to_save_mm[r] in rg[R_MMREGISTER].used_in_proc then
                   begin
                   begin
                     templist.concat(cai_seh_directive.create_reg_offset(ash_savexmm,
                     templist.concat(cai_seh_directive.create_reg_offset(ash_savexmm,
-                      newreg(R_MMREGISTER,saved_mm_registers[r],R_SUBMMWHOLE),
+                      newreg(R_MMREGISTER,regs_to_save_mm[r],R_SUBMMWHOLE),
                       href.offset+frame_offset));
                       href.offset+frame_offset));
                     inc(href.offset,tcgsize2size[OS_VECTOR]);
                     inc(href.offset,tcgsize2size[OS_VECTOR]);
                   end;
                   end;
@@ -366,7 +342,9 @@ unit cgcpu;
         href : treference;
         href : treference;
         hreg : tregister;
         hreg : tregister;
         r : longint;
         r : longint;
+        regs_to_save_mm: tcpuregisterarray;
       begin
       begin
+        regs_to_save_mm:=paramanager.get_saved_registers_mm(current_procinfo.procdef.proccalloption);;
         { Prevent return address from a possible call from ending up in the epilogue }
         { Prevent return address from a possible call from ending up in the epilogue }
         { (restoring registers happens before epilogue, providing necessary padding) }
         { (restoring registers happens before epilogue, providing necessary padding) }
         if (current_procinfo.flags*[pi_has_unwind_info,pi_do_call,pi_has_saved_regs])=[pi_has_unwind_info,pi_do_call] then
         if (current_procinfo.flags*[pi_has_unwind_info,pi_do_call,pi_has_saved_regs])=[pi_has_unwind_info,pi_do_call] then
@@ -379,11 +357,11 @@ unit cgcpu;
                 if (saved_xmm_reg_size<>0) then
                 if (saved_xmm_reg_size<>0) then
                   begin
                   begin
                     href:=current_procinfo.save_regs_ref;
                     href:=current_procinfo.save_regs_ref;
-                    for r:=low(saved_mm_registers) to high(saved_mm_registers) do
-                      if saved_mm_registers[r] in rg[R_MMREGISTER].used_in_proc then
+                    for r:=low(regs_to_save_mm) to high(regs_to_save_mm) do
+                      if regs_to_save_mm[r] in rg[R_MMREGISTER].used_in_proc then
                         begin
                         begin
                           { Allocate register so the optimizer does not remove the load }
                           { Allocate register so the optimizer does not remove the load }
-                          hreg:=newreg(R_MMREGISTER,saved_mm_registers[r],R_SUBMMWHOLE);
+                          hreg:=newreg(R_MMREGISTER,regs_to_save_mm[r],R_SUBMMWHOLE);
                           a_reg_alloc(list,hreg);
                           a_reg_alloc(list,hreg);
                           a_loadmm_ref_reg(list,OS_VECTOR,OS_VECTOR,href,hreg,nil);
                           a_loadmm_ref_reg(list,OS_VECTOR,OS_VECTOR,href,hreg,nil);
                           inc(href.offset,tcgsize2size[OS_VECTOR]);
                           inc(href.offset,tcgsize2size[OS_VECTOR]);

+ 0 - 5
compiler/x86_64/cpubase.inc

@@ -126,11 +126,6 @@ const
 *****************************************************************************}
 *****************************************************************************}
 
 
     const
     const
-      { these arrays differ between unix and win64 }
-      saved_standard_registers : array of tsuperregister = nil;
-      saved_mm_registers : array of tsuperregister = nil;
-
-      saved_address_registers : array[0..0] of tsuperregister = (RS_INVALID);
       { Required parameter alignment when calling a routine declared as
       { Required parameter alignment when calling a routine declared as
         stdcall and cdecl. The alignment value should be the one defined
         stdcall and cdecl. The alignment value should be the one defined
         by GCC or the target ABI.
         by GCC or the target ABI.

+ 27 - 1
compiler/x86_64/cpupara.pas

@@ -43,6 +43,8 @@ unit cpupara;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+          function get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;override;
+          function get_saved_registers_mm(calloption: tproccalloption):tcpuregisterarray;override;
           function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
           function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
           function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
           function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
           function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
           function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
@@ -56,7 +58,7 @@ unit cpupara;
        defutil,
        defutil,
        symtable,
        symtable,
        cpupi,
        cpupi,
-       cgx86;
+       cgx86,cgobj,cgcpu;
 
 
     const
     const
       paraintsupregs : array[0..5] of tsuperregister = (RS_RDI,RS_RSI,RS_RDX,RS_RCX,RS_R8,RS_R9);
       paraintsupregs : array[0..5] of tsuperregister = (RS_RDI,RS_RSI,RS_RDX,RS_RCX,RS_R8,RS_R9);
@@ -1364,6 +1366,30 @@ unit cpupara;
       end;
       end;
 
 
 
 
+    function tcpuparamanager.get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;
+      const
+        win64_saved_std_regs : array[0..7] of tsuperregister = (RS_RBX,RS_RDI,RS_RSI,RS_R12,RS_R13,RS_R14,RS_R15,RS_RBP);
+        others_saved_std_regs : array[0..4] of tsuperregister = (RS_RBX,RS_R12,RS_R13,RS_R14,RS_R15);
+      begin
+        if tcgx86_64(cg).use_ms_abi then
+          result:=win64_saved_std_regs
+        else
+          result:=others_saved_std_regs;
+      end;
+
+
+    function tcpuparamanager.get_saved_registers_mm(calloption: tproccalloption):tcpuregisterarray;
+      const
+        win64_saved_xmm_regs : array[0..9] of tsuperregister = (RS_XMM6,RS_XMM7,
+          RS_XMM8,RS_XMM9,RS_XMM10,RS_XMM11,RS_XMM12,RS_XMM13,RS_XMM14,RS_XMM15);
+      begin
+        if tcgx86_64(cg).use_ms_abi then
+          result:=win64_saved_xmm_regs
+        else
+          SetLength(result,0);
+      end;
+
+
     function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
     function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
       const
       const
         intretregs: array[0..1] of tregister = (NR_FUNCTION_RETURN_REG,NR_FUNCTION_RETURN_REG_HIGH);
         intretregs: array[0..1] of tregister = (NR_FUNCTION_RETURN_REG,NR_FUNCTION_RETURN_REG_HIGH);