diff --git a/compiler/aarch64/cpubase.pas b/compiler/aarch64/cpubase.pas
index 7b3afd309f..05f8c89c68 100644
--- a/compiler/aarch64/cpubase.pas
+++ b/compiler/aarch64/cpubase.pas
@@ -305,25 +305,6 @@ unit cpubase;
       NR_DEFAULTFLAGS = NR_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
 *****************************************************************************}
diff --git a/compiler/aarch64/cpupara.pas b/compiler/aarch64/cpupara.pas
index 21423daa4d..c0f811aaab 100644
--- a/compiler/aarch64/cpupara.pas
+++ b/compiler/aarch64/cpupara.pas
@@ -37,6 +37,8 @@ unit cpupara;
           function get_volatile_registers_int(calloption: tproccalloption): tcpuregisterset; override;
           function get_volatile_registers_fpu(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 ret_in_param(def: tdef; pd: tabstractprocdef):boolean;override;
           function create_paraloc_info(p: tabstractprocdef; side: tcallercallee):longint;override;
@@ -87,6 +89,23 @@ unit cpupara;
       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;
       var
         i: longint;
diff --git a/compiler/arm/cpubase.pas b/compiler/arm/cpubase.pas
index fca256f431..0dde9d2835 100644
--- a/compiler/arm/cpubase.pas
+++ b/compiler/arm/cpubase.pas
@@ -341,20 +341,6 @@ unit cpubase;
 *****************************************************************************}
 
     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
         stdcall and cdecl. The alignment value should be the one defined
         by GCC or the target ABI.
diff --git a/compiler/arm/cpupara.pas b/compiler/arm/cpupara.pas
index d679bbc5cb..088a8215ae 100644
--- a/compiler/arm/cpupara.pas
+++ b/compiler/arm/cpupara.pas
@@ -37,6 +37,7 @@ unit cpupara;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(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 ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
           procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
@@ -81,6 +82,15 @@ unit cpupara;
       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);
       var
         paraloc : pcgparalocation;
diff --git a/compiler/avr/cpubase.pas b/compiler/avr/cpubase.pas
index 91ecf6ef79..955e18484a 100644
--- a/compiler/avr/cpubase.pas
+++ b/compiler/avr/cpubase.pas
@@ -278,17 +278,6 @@ unit cpubase;
 *****************************************************************************}
 
     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
         stdcall and cdecl. The alignment value should be the one defined
         by GCC or the target ABI.
@@ -298,9 +287,6 @@ unit cpubase;
       }
       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
 *****************************************************************************}
diff --git a/compiler/cgobj.pas b/compiler/cgobj.pas
index cd82da0e88..6b30cfb0a1 100644
--- a/compiler/cgobj.pas
+++ b/compiler/cgobj.pas
@@ -2523,15 +2523,21 @@ implementation
         href : treference;
         size : longint;
         r : integer;
+        regs_to_save_int,
+        regs_to_save_address,
+        regs_to_save_mm : tcpuregisterarray;
       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 }
         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));
         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));
 
         { mm registers }
@@ -2542,8 +2548,8 @@ implementation
               of the temp is smaller than needed for an 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]);
           end;
 
@@ -2554,25 +2560,25 @@ implementation
 
             { Copy registers to temp }
             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
-                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
-                    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));
                   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;
 
             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
-                  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
-                      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));
                     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;
 
             if uses_registers(R_MMREGISTER) then
@@ -2580,20 +2586,20 @@ implementation
                 if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
                   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
                     { 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
                       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
-                        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
-                            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]);
                           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;
@@ -2606,15 +2612,21 @@ implementation
         href     : treference;
         r        : integer;
         hreg     : tregister;
+        regs_to_save_int,
+        regs_to_save_address,
+        regs_to_save_mm : tcpuregisterarray;
       begin
         if not(pi_has_saved_regs in current_procinfo.flags) then
           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 }
         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
-              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 }
               a_reg_alloc(list,hreg);
               a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,hreg);
@@ -2622,10 +2634,10 @@ implementation
             end;
 
         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
-                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 }
                 a_reg_alloc(list,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
               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
-                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
-                    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 }
                     a_reg_alloc(list,hreg);
                     a_loadmm_ref_reg(list,OS_VECTOR,OS_VECTOR,href,hreg,nil);
diff --git a/compiler/cgutils.pas b/compiler/cgutils.pas
index 124ca4016f..50485fe688 100644
--- a/compiler/cgutils.pas
+++ b/compiler/cgutils.pas
@@ -42,6 +42,7 @@ unit cgutils;
     type
       { Set type definition for cpuregisters }
       tcpuregisterset = set of 0..maxcpuregister;
+      tcpuregisterarray = array of tsuperregister;
 
 {$packset 1}
       { a reference may be volatile for reading, writing, or both. E.g., local variables
diff --git a/compiler/i386/cpubase.inc b/compiler/i386/cpubase.inc
index b604845055..de3cb7ec61 100644
--- a/compiler/i386/cpubase.inc
+++ b/compiler/i386/cpubase.inc
@@ -131,17 +131,6 @@
 *****************************************************************************}
 
     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
          stdcall and cdecl. The alignment value should be the one defined
          by GCC or the target ABI.
diff --git a/compiler/i386/cpupara.pas b/compiler/i386/cpupara.pas
index 62a493dc13..05b9abd1a0 100644
--- a/compiler/i386/cpupara.pas
+++ b/compiler/i386/cpupara.pas
@@ -40,6 +40,7 @@ unit cpupara;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(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_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;
@@ -286,6 +287,14 @@ unit cpupara;
       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;
       var
         retcgsize  : tcgsize;
diff --git a/compiler/i8086/cpubase.inc b/compiler/i8086/cpubase.inc
index 733c0a6346..950d0029f5 100644
--- a/compiler/i8086/cpubase.inc
+++ b/compiler/i8086/cpubase.inc
@@ -150,17 +150,6 @@
 *****************************************************************************}
 
     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
          stdcall and cdecl. The alignment value should be the one defined
          by GCC or the target ABI.
diff --git a/compiler/i8086/cpupara.pas b/compiler/i8086/cpupara.pas
index 3171c3af65..1b4a1aeb73 100644
--- a/compiler/i8086/cpupara.pas
+++ b/compiler/i8086/cpupara.pas
@@ -41,6 +41,7 @@ unit cpupara;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(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
             if every parameter before is an 16 Bit int parameter as well
             and if the calling conventions for the helper routines of the
@@ -236,6 +237,14 @@ unit cpupara;
       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);
       var
         paraloc : pcgparalocation;
diff --git a/compiler/jvm/cpubase.pas b/compiler/jvm/cpubase.pas
index a4cb80b49c..e880bf76a7 100644
--- a/compiler/jvm/cpubase.pas
+++ b/compiler/jvm/cpubase.pas
@@ -255,17 +255,6 @@ uses
 
       { 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
       }
       std_param_align = 1;
diff --git a/compiler/jvm/cpupara.pas b/compiler/jvm/cpupara.pas
index 4c7eb718f3..929abfe184 100644
--- a/compiler/jvm/cpupara.pas
+++ b/compiler/jvm/cpupara.pas
@@ -35,6 +35,7 @@ interface
       { tcpuparamanager }
 
       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  keep_para_array_range(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);
       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;
       begin
         { we don't need a separate high parameter, since all arrays in Java
diff --git a/compiler/m68k/cgcpu.pas b/compiler/m68k/cgcpu.pas
index bd0f511c0c..4b49e99c19 100644
--- a/compiler/m68k/cgcpu.pas
+++ b/compiler/m68k/cgcpu.pas
@@ -1963,6 +1963,9 @@ unit cgcpu;
         size : longint;
         fsize : longint;
         r : integer;
+        regs_to_save_int,
+        regs_to_save_address,
+        regs_to_save_fpu: tcpuregisterarray;
       begin
         { The code generated by the section below, particularly the movem.l
           instruction is known to cause an issue when compiled by some GNU 
@@ -1974,33 +1977,36 @@ unit cgcpu;
         addrregs:=[];
         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 }
         size:=0;
         fsize:=0;
         hreg:=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
-              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));
-              dataregs:=dataregs + [saved_standard_registers[r]];
+              dataregs:=dataregs + [regs_to_save_int[r]];
             end;
         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
-                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));
-                addrregs:=addrregs + [saved_address_registers[r]];
+                addrregs:=addrregs + [regs_to_save_address[r]];
               end;
         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
-                hfreg:=newreg(R_FPUREGISTER,saved_fpu_registers[r],R_SUBNONE);
+                hfreg:=newreg(R_FPUREGISTER,regs_to_save_fpu[r],R_SUBNONE);
                 inc(fsize,fpuregsize);
-                fpuregs:=fpuregs + [saved_fpu_registers[r]];
+                fpuregs:=fpuregs + [regs_to_save_fpu[r]];
               end;
 
         { 68k has no MM registers }
@@ -2052,6 +2058,9 @@ unit cgcpu;
         hfreg   : tregister;
         size    : longint;
         fsize   : longint;
+        regs_to_save_int,
+        regs_to_save_address,
+        regs_to_save_fpu: tcpuregisterarray;
       begin
         { see the remark about buggy GNU AS versions in g_save_registers() (KB) }
         dataregs:=[];
@@ -2060,41 +2069,44 @@ unit cgcpu;
 
         if not(pi_has_saved_regs in current_procinfo.flags) then
           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 }
         size:=0;
         fsize:=0;
         hreg:=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
               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 }
               a_reg_alloc(list,hreg);
-              dataregs:=dataregs + [saved_standard_registers[r]];
+              dataregs:=dataregs + [regs_to_save_int[r]];
             end;
 
         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
                 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 }
                 a_reg_alloc(list,hreg);
-                addrregs:=addrregs + [saved_address_registers[r]];
+                addrregs:=addrregs + [regs_to_save_address[r]];
               end;
 
         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
                 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 }
                 a_reg_alloc(list,hfreg);
-                fpuregs:=fpuregs + [saved_fpu_registers[r]];
+                fpuregs:=fpuregs + [regs_to_save_fpu[r]];
               end;
 
         { 68k has no MM registers }
diff --git a/compiler/m68k/cpubase.pas b/compiler/m68k/cpubase.pas
index ebf4e1856e..b74ee580b7 100644
--- a/compiler/m68k/cpubase.pas
+++ b/compiler/m68k/cpubase.pas
@@ -320,20 +320,6 @@ unit cpubase;
                        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
          stdcall and cdecl. The alignment value should be the one defined
          by GCC or the target ABI.
diff --git a/compiler/m68k/cpupara.pas b/compiler/m68k/cpupara.pas
index 5e74472c71..a6915f842c 100644
--- a/compiler/m68k/cpupara.pas
+++ b/compiler/m68k/cpupara.pas
@@ -50,6 +50,9 @@ unit cpupara;
           function get_volatile_registers_int(calloption:tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_address(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;
          private
           function parse_loc_string_to_register(var locreg: tregister; const s : string): boolean;
@@ -99,6 +102,27 @@ unit cpupara;
         Result:=VOLATILE_FPUREGISTERS;
       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;
       begin
         result:=target_info.stackalign;
diff --git a/compiler/mips/cpubase.pas b/compiler/mips/cpubase.pas
index d57b2d8195..70f368463c 100644
--- a/compiler/mips/cpubase.pas
+++ b/compiler/mips/cpubase.pas
@@ -238,20 +238,6 @@ unit cpubase;
 *****************************************************************************}
 
     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
         stdcall and cdecl. The alignment value should be the one defined
         by GCC or the target ABI.
diff --git a/compiler/mips/cpupara.pas b/compiler/mips/cpupara.pas
index cf666ea979..d3c1ef12c6 100644
--- a/compiler/mips/cpupara.pas
+++ b/compiler/mips/cpupara.pas
@@ -71,6 +71,7 @@ interface
         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_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_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override;
         function  get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
@@ -106,6 +107,15 @@ implementation
       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,
       i.e. its address passed in a0 }
     function tcpuparamanager.is_abi_record(def: tdef): boolean;
diff --git a/compiler/paramgr.pas b/compiler/paramgr.pas
index e28fb15e5a..898b7d5a98 100644
--- a/compiler/paramgr.pas
+++ b/compiler/paramgr.pas
@@ -82,6 +82,17 @@ unit paramgr;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;virtual;
           function get_volatile_registers_flags(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;
 
@@ -299,6 +310,38 @@ implementation
         result:=[];
       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}
   {$WARN 4044 OFF} { Comparison might be always false ... }
 {$endif}
diff --git a/compiler/powerpc/cpubase.pas b/compiler/powerpc/cpubase.pas
index c97318f663..e569e13423 100644
--- a/compiler/powerpc/cpubase.pas
+++ b/compiler/powerpc/cpubase.pas
@@ -338,23 +338,6 @@ uses
                        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
          stdcall and cdecl. The alignment value should be the one defined
          by GCC or the target ABI.
diff --git a/compiler/powerpc/cpupara.pas b/compiler/powerpc/cpupara.pas
index b20f59cdb6..1edfaafa94 100644
--- a/compiler/powerpc/cpupara.pas
+++ b/compiler/powerpc/cpupara.pas
@@ -35,6 +35,7 @@ unit cpupara;
        tcpuparamanager = class(tparamanager)
           function get_volatile_registers_int(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;
 
           procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
@@ -78,6 +79,18 @@ unit cpupara;
       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);
       var
         paraloc : pcgparalocation;
diff --git a/compiler/powerpc64/cpubase.pas b/compiler/powerpc64/cpubase.pas
index 7c847c1260..1a4d672399 100644
--- a/compiler/powerpc64/cpubase.pas
+++ b/compiler/powerpc64/cpubase.pas
@@ -332,23 +332,6 @@ const
                          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
      stdcall and cdecl. The alignment value should be the one defined
      by GCC or the target ABI.
diff --git a/compiler/powerpc64/cpupara.pas b/compiler/powerpc64/cpupara.pas
index adfce8efdc..5ac2d9dd68 100644
--- a/compiler/powerpc64/cpupara.pas
+++ b/compiler/powerpc64/cpupara.pas
@@ -37,6 +37,8 @@ type
       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 ret_in_param(def: tdef; pd: tabstractprocdef): boolean; override;
@@ -79,6 +81,18 @@ begin
   result := [RS_F0..RS_F13];
 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);
 var
   paraloc: pcgparalocation;
diff --git a/compiler/sparcgen/cpubase.pas b/compiler/sparcgen/cpubase.pas
index be5944eacc..43b1a91d31 100644
--- a/compiler/sparcgen/cpubase.pas
+++ b/compiler/sparcgen/cpubase.pas
@@ -305,19 +305,6 @@ uses
                        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
          stdcall and cdecl. The alignment value should be the one defined
          by GCC or the target ABI.
diff --git a/compiler/x86/cgx86.pas b/compiler/x86/cgx86.pas
index 5e9b4182f9..7707936fdd 100644
--- a/compiler/x86/cgx86.pas
+++ b/compiler/x86/cgx86.pas
@@ -3294,14 +3294,16 @@ unit cgx86;
         var
           r: longint;
           usedregs: tcpuregisterset;
+          regs_to_save_int: tcpuregisterarray;
         begin
           regsize:=0;
           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
                 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;
 
@@ -3572,13 +3574,15 @@ unit cgx86;
         hreg: tregister;
         href: treference;
         usedregs: tcpuregisterset;
+        regs_to_save_int: tcpuregisterarray;
       begin
         href:=current_procinfo.save_regs_ref;
         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
-              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 }
               a_reg_alloc(list,hreg);
               if use_pop then
diff --git a/compiler/x86_64/cgcpu.pas b/compiler/x86_64/cgcpu.pas
index 7dda93406a..d36b8ce2b5 100644
--- a/compiler/x86_64/cgcpu.pas
+++ b/compiler/x86_64/cgcpu.pas
@@ -65,42 +65,12 @@ unit cgcpu;
 
 
     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
-        i : longint;
         ms_abi: boolean;
       begin
         inherited init_register_allocators;
 
         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
           begin
             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;
       var
         i: longint;
+        regs_to_save_mm: tcpuregisterarray;
       begin
         result:=0;
         if (target_info.system<>system_x86_64_win64) or
            (not uses_registers(R_MMREGISTER)) then
           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
-            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]);
           end;
       end;
@@ -180,6 +152,8 @@ unit cgcpu;
         suppress_endprologue: boolean;
         stackmisalignment: longint;
         xmmsize: longint;
+        regs_to_save_int,
+        regs_to_save_mm: tcpuregisterarray;
 
       procedure push_one_reg(reg: tregister);
         begin
@@ -197,15 +171,17 @@ unit cgcpu;
           usedregs: tcpuregisterset;
         begin
           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
                 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;
 
       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;
         { pi_has_unwind_info may already be set at this point if there are
           SEH directives in assembler body. In this case, .seh_endprologue
@@ -282,10 +258,10 @@ unit cgcpu;
                     if use_push and (xmmsize<>0) then
                       begin
                         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
-                              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]);
                             end;
                       end;
@@ -316,11 +292,11 @@ unit cgcpu;
         href:=current_procinfo.save_regs_ref;
         if (not use_push) then
           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
                   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));
                  inc(href.offset,sizeof(aint));
                 end;
@@ -330,12 +306,12 @@ unit cgcpu;
             if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
               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
-                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
                     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));
                     inc(href.offset,tcgsize2size[OS_VECTOR]);
                   end;
@@ -366,7 +342,9 @@ unit cgcpu;
         href : treference;
         hreg : tregister;
         r : longint;
+        regs_to_save_mm: tcpuregisterarray;
       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 }
         { (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
@@ -379,11 +357,11 @@ unit cgcpu;
                 if (saved_xmm_reg_size<>0) then
                   begin
                     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
                           { 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_loadmm_ref_reg(list,OS_VECTOR,OS_VECTOR,href,hreg,nil);
                           inc(href.offset,tcgsize2size[OS_VECTOR]);
diff --git a/compiler/x86_64/cpubase.inc b/compiler/x86_64/cpubase.inc
index 44c92397f3..816fba50be 100644
--- a/compiler/x86_64/cpubase.inc
+++ b/compiler/x86_64/cpubase.inc
@@ -126,11 +126,6 @@ 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
         stdcall and cdecl. The alignment value should be the one defined
         by GCC or the target ABI.
diff --git a/compiler/x86_64/cpupara.pas b/compiler/x86_64/cpupara.pas
index fca7b8382a..c268072c61 100644
--- a/compiler/x86_64/cpupara.pas
+++ b/compiler/x86_64/cpupara.pas
@@ -43,6 +43,8 @@ unit cpupara;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(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_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
           function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
@@ -56,7 +58,7 @@ unit cpupara;
        defutil,
        symtable,
        cpupi,
-       cgx86;
+       cgx86,cgobj,cgcpu;
 
     const
       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;
 
 
+    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;
       const
         intretregs: array[0..1] of tregister = (NR_FUNCTION_RETURN_REG,NR_FUNCTION_RETURN_REG_HIGH);