mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-29 14:40:25 +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;
|
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
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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 }
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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}
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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]);
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user