* replaced the saved_XXX_registers arrays with virtual methods inside

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

git-svn-id: trunk@38794 -
This commit is contained in:
nickysn 2018-04-19 21:22:16 +00:00
parent 0601b437a4
commit 518cdf9674
28 changed files with 299 additions and 266 deletions

View File

@ -305,25 +305,6 @@ unit cpubase;
NR_DEFAULTFLAGS = NR_NZCV;
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
*****************************************************************************}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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