* 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 -
This commit is contained in:
nickysn 2018-04-19 21:22:16 +00:00
parent 0601b437a4
commit 518cdf9674
28 changed files with 299 additions and 266 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 for r:=low(regs_to_save_int) to high(regs_to_save_int) do
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
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 for r:=low(regs_to_save_int) to high(regs_to_save_int) do
if saved_address_registers[r] in rg[R_ADDRESSREGISTER].used_in_proc then 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 for r:=low(regs_to_save_mm) to high(regs_to_save_mm) do
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
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 for r:=low(regs_to_save_int) to high(regs_to_save_int) do
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
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 for r:=low(regs_to_save_address) to high(regs_to_save_address) do
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
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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 for r:=low(regs_to_save_int) to high(regs_to_save_int) do
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
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 for r:=low(regs_to_save_address) to high(regs_to_save_address) do
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
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 for r:=low(regs_to_save_fpu) to high(regs_to_save_fpu) do
if saved_fpu_registers[r] in rg[R_FPUREGISTER].used_in_proc then 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 for r:=low(regs_to_save_int) to high(regs_to_save_int) do
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
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 for r:=low(regs_to_save_address) to high(regs_to_save_address) do
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
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 for r:=low(regs_to_save_fpu) to high(regs_to_save_fpu) do
if saved_fpu_registers[r] in rg[R_FPUREGISTER].used_in_proc then 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 }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 regs_to_save_int:=paramanager.get_saved_registers_int(current_procinfo.procdef.proccalloption);
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(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 regs_to_save_int:=paramanager.get_saved_registers_int(current_procinfo.procdef.proccalloption);
if saved_standard_registers[r] in usedregs then 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

View File

@ -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 for r := low(regs_to_save_int) to high(regs_to_save_int) do
if saved_standard_registers[r] in usedregs then 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 for r:=low(regs_to_save_mm) to high(regs_to_save_mm) do
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;
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 for r:=low(regs_to_save_int) to high(regs_to_save_int) do
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
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 for r:=low(regs_to_save_mm) to high(regs_to_save_mm) do
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
{ 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]);

View File

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

View File

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