mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-13 13:29:27 +02:00
* 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:
parent
0601b437a4
commit
518cdf9674
@ -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
|
||||
*****************************************************************************}
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
*****************************************************************************}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user